]> xenbits.xen.org Git - xenclient/grub2.git/commitdiff
Import svn://svn.sv.gnu.org/grub/trunk/grub2 r1998. origin/HEAD origin/master
authorJean Guyader <jean.guyader@eu.citrix.com>
Wed, 20 May 2009 17:54:55 +0000 (17:54 +0000)
committerJean Guyader <jean.guyader@eu.citrix.com>
Wed, 20 May 2009 17:54:55 +0000 (17:54 +0000)
485 files changed:
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
DISTLIST [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.in [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
THANKS [new file with mode: 0644]
TODO [new file with mode: 0644]
aclocal.m4 [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
boot/i386/pc/boot.S [new file with mode: 0644]
boot/i386/pc/cdboot.S [new file with mode: 0644]
boot/i386/pc/diskboot.S [new file with mode: 0644]
boot/i386/pc/lnxboot.S [new file with mode: 0644]
boot/i386/pc/pxeboot.S [new file with mode: 0644]
bus/pci.c [new file with mode: 0644]
bus/usb/ohci.c [new file with mode: 0644]
bus/usb/uhci.c [new file with mode: 0644]
bus/usb/usb.c [new file with mode: 0644]
bus/usb/usbhub.c [new file with mode: 0644]
bus/usb/usbtrans.c [new file with mode: 0644]
commands/blocklist.c [new file with mode: 0644]
commands/boot.c [new file with mode: 0644]
commands/cat.c [new file with mode: 0644]
commands/cmp.c [new file with mode: 0644]
commands/configfile.c [new file with mode: 0644]
commands/crc.c [new file with mode: 0644]
commands/date.c [new file with mode: 0644]
commands/echo.c [new file with mode: 0644]
commands/halt.c [new file with mode: 0644]
commands/hdparm.c [new file with mode: 0644]
commands/help.c [new file with mode: 0644]
commands/hexdump.c [new file with mode: 0644]
commands/i386/cpuid.c [new file with mode: 0644]
commands/i386/pc/halt.c [new file with mode: 0644]
commands/i386/pc/play.c [new file with mode: 0644]
commands/i386/pc/pxecmd.c [new file with mode: 0644]
commands/i386/pc/vbeinfo.c [new file with mode: 0644]
commands/i386/pc/vbetest.c [new file with mode: 0644]
commands/ieee1275/suspend.c [new file with mode: 0644]
commands/loadenv.c [new file with mode: 0644]
commands/ls.c [new file with mode: 0644]
commands/lsmmap.c [new file with mode: 0644]
commands/lspci.c [new file with mode: 0644]
commands/read.c [new file with mode: 0644]
commands/reboot.c [new file with mode: 0644]
commands/search.c [new file with mode: 0644]
commands/sleep.c [new file with mode: 0644]
commands/terminal.c [new file with mode: 0644]
commands/test.c [new file with mode: 0644]
commands/usbtest.c [new file with mode: 0644]
commands/videotest.c [new file with mode: 0644]
conf/common.mk [new file with mode: 0644]
conf/common.rmk [new file with mode: 0644]
conf/i386-coreboot.mk [new file with mode: 0644]
conf/i386-coreboot.rmk [new file with mode: 0644]
conf/i386-efi.mk [new file with mode: 0644]
conf/i386-efi.rmk [new file with mode: 0644]
conf/i386-ieee1275.mk [new file with mode: 0644]
conf/i386-ieee1275.rmk [new file with mode: 0644]
conf/i386-pc-cygwin-img-ld.sc [new file with mode: 0644]
conf/i386-pc.mk [new file with mode: 0644]
conf/i386-pc.rmk [new file with mode: 0644]
conf/i386.mk [new file with mode: 0644]
conf/i386.rmk [new file with mode: 0644]
conf/powerpc-ieee1275.mk [new file with mode: 0644]
conf/powerpc-ieee1275.rmk [new file with mode: 0644]
conf/sparc64-ieee1275.mk [new file with mode: 0644]
conf/sparc64-ieee1275.rmk [new file with mode: 0644]
conf/x86_64-efi.mk [new file with mode: 0644]
conf/x86_64-efi.rmk [new file with mode: 0644]
config.guess [new file with mode: 0644]
config.h.in [new file with mode: 0644]
config.sub [new file with mode: 0644]
configure [new file with mode: 0755]
configure.ac [new file with mode: 0644]
disk/ata.c [new file with mode: 0644]
disk/ata_pthru.c [new file with mode: 0644]
disk/dmraid_nvidia.c [new file with mode: 0644]
disk/efi/efidisk.c [new file with mode: 0644]
disk/fs_uuid.c [new file with mode: 0644]
disk/host.c [new file with mode: 0644]
disk/i386/pc/biosdisk.c [new file with mode: 0644]
disk/ieee1275/nand.c [new file with mode: 0644]
disk/ieee1275/ofdisk.c [new file with mode: 0644]
disk/loopback.c [new file with mode: 0644]
disk/lvm.c [new file with mode: 0644]
disk/mdraid_linux.c [new file with mode: 0644]
disk/memdisk.c [new file with mode: 0644]
disk/raid.c [new file with mode: 0644]
disk/raid5_recover.c [new file with mode: 0644]
disk/raid6_recover.c [new file with mode: 0644]
disk/scsi.c [new file with mode: 0644]
disk/usbms.c [new file with mode: 0644]
docs/fdl.texi [new file with mode: 0644]
docs/grub.cfg [new file with mode: 0644]
docs/grub.texi [new file with mode: 0644]
docs/mdate-sh [new file with mode: 0755]
docs/texinfo.tex [new file with mode: 0644]
font/font.c [new file with mode: 0644]
font/font_cmd.c [new file with mode: 0644]
fs/affs.c [new file with mode: 0644]
fs/afs.c [new file with mode: 0644]
fs/cpio.c [new file with mode: 0644]
fs/ext2.c [new file with mode: 0644]
fs/fat.c [new file with mode: 0644]
fs/fshelp.c [new file with mode: 0644]
fs/hfs.c [new file with mode: 0644]
fs/hfsplus.c [new file with mode: 0644]
fs/i386/pc/pxe.c [new file with mode: 0644]
fs/iso9660.c [new file with mode: 0644]
fs/jfs.c [new file with mode: 0644]
fs/minix.c [new file with mode: 0644]
fs/ntfs.c [new file with mode: 0644]
fs/ntfscomp.c [new file with mode: 0644]
fs/reiserfs.c [new file with mode: 0644]
fs/sfs.c [new file with mode: 0644]
fs/tar.c [new file with mode: 0644]
fs/udf.c [new file with mode: 0644]
fs/ufs.c [new file with mode: 0644]
fs/xfs.c [new file with mode: 0644]
gencmdlist.sh [new file with mode: 0644]
gendistlist.sh [new file with mode: 0755]
genfslist.sh [new file with mode: 0644]
geninit.sh [new file with mode: 0644]
geninitheader.sh [new file with mode: 0644]
genkernsyms.sh.in [new file with mode: 0644]
genmk.rb [new file with mode: 0644]
genmoddep.awk [new file with mode: 0644]
genmodsrc.sh [new file with mode: 0644]
genpartmaplist.sh [new file with mode: 0644]
gensymlist.sh.in [new file with mode: 0644]
hello/hello.c [new file with mode: 0644]
hook/datehook.c [new file with mode: 0644]
include/grub/acorn_filecore.h [new file with mode: 0644]
include/grub/aout.h [new file with mode: 0644]
include/grub/arg.h [new file with mode: 0644]
include/grub/ata.h [new file with mode: 0644]
include/grub/bitmap.h [new file with mode: 0644]
include/grub/boot.h [new file with mode: 0644]
include/grub/bufio.h [new file with mode: 0644]
include/grub/cache.h [new file with mode: 0644]
include/grub/device.h [new file with mode: 0644]
include/grub/disk.h [new file with mode: 0644]
include/grub/dl.h [new file with mode: 0644]
include/grub/efi/api.h [new file with mode: 0644]
include/grub/efi/chainloader.h [new file with mode: 0644]
include/grub/efi/console.h [new file with mode: 0644]
include/grub/efi/console_control.h [new file with mode: 0644]
include/grub/efi/disk.h [new file with mode: 0644]
include/grub/efi/efi.h [new file with mode: 0644]
include/grub/efi/pe32.h [new file with mode: 0644]
include/grub/efi/time.h [new file with mode: 0644]
include/grub/efi/uga_draw.h [new file with mode: 0644]
include/grub/elf.h [new file with mode: 0644]
include/grub/elfload.h [new file with mode: 0644]
include/grub/env.h [new file with mode: 0644]
include/grub/err.h [new file with mode: 0644]
include/grub/file.h [new file with mode: 0644]
include/grub/font.h [new file with mode: 0644]
include/grub/fs.h [new file with mode: 0644]
include/grub/fshelp.h [new file with mode: 0644]
include/grub/gpt_partition.h [new file with mode: 0644]
include/grub/gzio.h [new file with mode: 0644]
include/grub/hfs.h [new file with mode: 0644]
include/grub/i386/at_keyboard.h [new file with mode: 0644]
include/grub/i386/bsd.h [new file with mode: 0644]
include/grub/i386/cmos.h [new file with mode: 0644]
include/grub/i386/coreboot/boot.h [new file with mode: 0644]
include/grub/i386/coreboot/console.h [new file with mode: 0644]
include/grub/i386/coreboot/init.h [new file with mode: 0644]
include/grub/i386/coreboot/kernel.h [new file with mode: 0644]
include/grub/i386/coreboot/loader.h [new file with mode: 0644]
include/grub/i386/coreboot/machine.h [new file with mode: 0644]
include/grub/i386/coreboot/memory.h [new file with mode: 0644]
include/grub/i386/coreboot/serial.h [new file with mode: 0644]
include/grub/i386/coreboot/time.h [new file with mode: 0644]
include/grub/i386/efi/kernel.h [new file with mode: 0644]
include/grub/i386/efi/loader.h [new file with mode: 0644]
include/grub/i386/efi/machine.h [new file with mode: 0644]
include/grub/i386/efi/time.h [new file with mode: 0644]
include/grub/i386/halt.h [new file with mode: 0644]
include/grub/i386/ieee1275/console.h [new file with mode: 0644]
include/grub/i386/ieee1275/ieee1275.h [new file with mode: 0644]
include/grub/i386/ieee1275/kernel.h [new file with mode: 0644]
include/grub/i386/ieee1275/loader.h [new file with mode: 0644]
include/grub/i386/ieee1275/machine.h [new file with mode: 0644]
include/grub/i386/ieee1275/memory.h [new file with mode: 0644]
include/grub/i386/ieee1275/serial.h [new file with mode: 0644]
include/grub/i386/ieee1275/time.h [new file with mode: 0644]
include/grub/i386/io.h [new file with mode: 0644]
include/grub/i386/kernel.h [new file with mode: 0644]
include/grub/i386/linux.h [new file with mode: 0644]
include/grub/i386/loader.h [new file with mode: 0644]
include/grub/i386/pc/biosdisk.h [new file with mode: 0644]
include/grub/i386/pc/boot.h [new file with mode: 0644]
include/grub/i386/pc/chainloader.h [new file with mode: 0644]
include/grub/i386/pc/console.h [new file with mode: 0644]
include/grub/i386/pc/init.h [new file with mode: 0644]
include/grub/i386/pc/kernel.h [new file with mode: 0644]
include/grub/i386/pc/loader.h [new file with mode: 0644]
include/grub/i386/pc/machine.h [new file with mode: 0644]
include/grub/i386/pc/memory.h [new file with mode: 0644]
include/grub/i386/pc/pxe.h [new file with mode: 0644]
include/grub/i386/pc/serial.h [new file with mode: 0644]
include/grub/i386/pc/time.h [new file with mode: 0644]
include/grub/i386/pc/vbe.h [new file with mode: 0644]
include/grub/i386/pc/vbeblit.h [new file with mode: 0644]
include/grub/i386/pc/vbefill.h [new file with mode: 0644]
include/grub/i386/pc/vbeutil.h [new file with mode: 0644]
include/grub/i386/pc/vga.h [new file with mode: 0644]
include/grub/i386/pci.h [new file with mode: 0644]
include/grub/i386/pit.h [new file with mode: 0644]
include/grub/i386/reboot.h [new file with mode: 0644]
include/grub/i386/setjmp.h [new file with mode: 0644]
include/grub/i386/time.h [new file with mode: 0644]
include/grub/i386/tsc.h [new file with mode: 0644]
include/grub/i386/types.h [new file with mode: 0644]
include/grub/i386/vga_common.h [new file with mode: 0644]
include/grub/ieee1275/ieee1275.h [new file with mode: 0644]
include/grub/ieee1275/ofdisk.h [new file with mode: 0644]
include/grub/kernel.h [new file with mode: 0644]
include/grub/lib/LzFind.h [new file with mode: 0644]
include/grub/lib/LzHash.h [new file with mode: 0644]
include/grub/lib/LzmaDec.h [new file with mode: 0644]
include/grub/lib/LzmaEnc.h [new file with mode: 0644]
include/grub/lib/LzmaTypes.h [new file with mode: 0644]
include/grub/lib/crc.h [new file with mode: 0644]
include/grub/lib/datetime.h [new file with mode: 0644]
include/grub/lib/envblk.h [new file with mode: 0644]
include/grub/lib/hexdump.h [new file with mode: 0644]
include/grub/loader.h [new file with mode: 0644]
include/grub/lvm.h [new file with mode: 0644]
include/grub/menu.h [new file with mode: 0644]
include/grub/menu_viewer.h [new file with mode: 0644]
include/grub/misc.h [new file with mode: 0644]
include/grub/mm.h [new file with mode: 0644]
include/grub/multiboot.h [new file with mode: 0644]
include/grub/multiboot2.h [new file with mode: 0644]
include/grub/multiboot_loader.h [new file with mode: 0644]
include/grub/net.h [new file with mode: 0644]
include/grub/normal.h [new file with mode: 0644]
include/grub/ntfs.h [new file with mode: 0644]
include/grub/parser.h [new file with mode: 0644]
include/grub/partition.h [new file with mode: 0644]
include/grub/pc_partition.h [new file with mode: 0644]
include/grub/pci.h [new file with mode: 0644]
include/grub/powerpc/ieee1275/biosdisk.h [new file with mode: 0644]
include/grub/powerpc/ieee1275/console.h [new file with mode: 0644]
include/grub/powerpc/ieee1275/ieee1275.h [new file with mode: 0644]
include/grub/powerpc/ieee1275/kernel.h [new file with mode: 0644]
include/grub/powerpc/ieee1275/loader.h [new file with mode: 0644]
include/grub/powerpc/ieee1275/machine.h [new file with mode: 0644]
include/grub/powerpc/ieee1275/memory.h [new file with mode: 0644]
include/grub/powerpc/ieee1275/time.h [new file with mode: 0644]
include/grub/powerpc/ieee1275/util/biosdisk.h [new file with mode: 0644]
include/grub/powerpc/kernel.h [new file with mode: 0644]
include/grub/powerpc/libgcc.h [new file with mode: 0644]
include/grub/powerpc/setjmp.h [new file with mode: 0644]
include/grub/powerpc/time.h [new file with mode: 0644]
include/grub/powerpc/types.h [new file with mode: 0644]
include/grub/raid.h [new file with mode: 0644]
include/grub/rescue.h [new file with mode: 0644]
include/grub/script.h [new file with mode: 0644]
include/grub/scsi.h [new file with mode: 0644]
include/grub/scsicmd.h [new file with mode: 0644]
include/grub/setjmp.h [new file with mode: 0644]
include/grub/sparc64/ieee1275/console.h [new file with mode: 0644]
include/grub/sparc64/ieee1275/ieee1275.h [new file with mode: 0644]
include/grub/sparc64/ieee1275/kernel.h [new file with mode: 0644]
include/grub/sparc64/ieee1275/machine.h [new file with mode: 0644]
include/grub/sparc64/ieee1275/time.h [new file with mode: 0644]
include/grub/sparc64/libgcc.h [new file with mode: 0644]
include/grub/sparc64/setjmp.h [new file with mode: 0644]
include/grub/sparc64/time.h [new file with mode: 0644]
include/grub/sparc64/types.h [new file with mode: 0644]
include/grub/symbol.h [new file with mode: 0644]
include/grub/term.h [new file with mode: 0644]
include/grub/terminfo.h [new file with mode: 0644]
include/grub/time.h [new file with mode: 0644]
include/grub/tparm.h [new file with mode: 0644]
include/grub/types.h [new file with mode: 0644]
include/grub/usb.h [new file with mode: 0644]
include/grub/usbdesc.h [new file with mode: 0644]
include/grub/usbtrans.h [new file with mode: 0644]
include/grub/util/getroot.h [new file with mode: 0644]
include/grub/util/hostdisk.h [new file with mode: 0644]
include/grub/util/lvm.h [new file with mode: 0644]
include/grub/util/misc.h [new file with mode: 0644]
include/grub/util/raid.h [new file with mode: 0644]
include/grub/util/resolve.h [new file with mode: 0644]
include/grub/video.h [new file with mode: 0644]
include/grub/x86_64/efi/kernel.h [new file with mode: 0644]
include/grub/x86_64/efi/loader.h [new file with mode: 0644]
include/grub/x86_64/efi/machine.h [new file with mode: 0644]
include/grub/x86_64/efi/time.h [new file with mode: 0644]
include/grub/x86_64/kernel.h [new file with mode: 0644]
include/grub/x86_64/linux.h [new file with mode: 0644]
include/grub/x86_64/pci.h [new file with mode: 0644]
include/grub/x86_64/setjmp.h [new file with mode: 0644]
include/grub/x86_64/time.h [new file with mode: 0644]
include/grub/x86_64/types.h [new file with mode: 0644]
include/multiboot.h [new file with mode: 0644]
include/multiboot2.h [new file with mode: 0644]
install-sh [new file with mode: 0755]
io/bufio.c [new file with mode: 0644]
io/gzio.c [new file with mode: 0644]
kern/device.c [new file with mode: 0644]
kern/disk.c [new file with mode: 0644]
kern/dl.c [new file with mode: 0644]
kern/efi/efi.c [new file with mode: 0644]
kern/efi/init.c [new file with mode: 0644]
kern/efi/mm.c [new file with mode: 0644]
kern/elf.c [new file with mode: 0644]
kern/env.c [new file with mode: 0644]
kern/err.c [new file with mode: 0644]
kern/file.c [new file with mode: 0644]
kern/fs.c [new file with mode: 0644]
kern/generic/millisleep.c [new file with mode: 0644]
kern/generic/rtc_get_time_ms.c [new file with mode: 0644]
kern/i386/coreboot/init.c [new file with mode: 0644]
kern/i386/coreboot/mmap.c [new file with mode: 0644]
kern/i386/coreboot/startup.S [new file with mode: 0644]
kern/i386/dl.c [new file with mode: 0644]
kern/i386/efi/init.c [new file with mode: 0644]
kern/i386/efi/startup.S [new file with mode: 0644]
kern/i386/halt.c [new file with mode: 0644]
kern/i386/ieee1275/init.c [new file with mode: 0644]
kern/i386/ieee1275/startup.S [new file with mode: 0644]
kern/i386/loader.S [new file with mode: 0644]
kern/i386/multiboot_mmap.c [new file with mode: 0644]
kern/i386/pc/init.c [new file with mode: 0644]
kern/i386/pc/lzma_decode.S [new file with mode: 0644]
kern/i386/pc/lzo1x.S [new file with mode: 0644]
kern/i386/pc/mmap.c [new file with mode: 0644]
kern/i386/pc/startup.S [new file with mode: 0644]
kern/i386/pit.c [new file with mode: 0644]
kern/i386/realmode.S [new file with mode: 0644]
kern/i386/reboot.c [new file with mode: 0644]
kern/i386/tsc.c [new file with mode: 0644]
kern/ieee1275/cmain.c [new file with mode: 0644]
kern/ieee1275/ieee1275.c [new file with mode: 0644]
kern/ieee1275/init.c [new file with mode: 0644]
kern/ieee1275/mmap.c [new file with mode: 0644]
kern/ieee1275/openfw.c [new file with mode: 0644]
kern/loader.c [new file with mode: 0644]
kern/main.c [new file with mode: 0644]
kern/misc.c [new file with mode: 0644]
kern/mm.c [new file with mode: 0644]
kern/parser.c [new file with mode: 0644]
kern/partition.c [new file with mode: 0644]
kern/powerpc/cache.S [new file with mode: 0644]
kern/powerpc/dl.c [new file with mode: 0644]
kern/powerpc/ieee1275/startup.S [new file with mode: 0644]
kern/rescue.c [new file with mode: 0644]
kern/sparc64/cache.S [new file with mode: 0644]
kern/sparc64/dl.c [new file with mode: 0644]
kern/sparc64/ieee1275/init.c [new file with mode: 0644]
kern/sparc64/ieee1275/openfw.c [new file with mode: 0644]
kern/term.c [new file with mode: 0644]
kern/time.c [new file with mode: 0644]
kern/x86_64/dl.c [new file with mode: 0644]
kern/x86_64/efi/callwrap.S [new file with mode: 0644]
kern/x86_64/efi/startup.S [new file with mode: 0644]
lib/LzFind.c [new file with mode: 0644]
lib/LzmaDec.c [new file with mode: 0644]
lib/LzmaEnc.c [new file with mode: 0644]
lib/crc.c [new file with mode: 0644]
lib/datetime.c [new file with mode: 0644]
lib/efi/datetime.c [new file with mode: 0644]
lib/envblk.c [new file with mode: 0644]
lib/hexdump.c [new file with mode: 0644]
lib/i386/datetime.c [new file with mode: 0644]
loader/aout.c [new file with mode: 0644]
loader/efi/appleloader.c [new file with mode: 0644]
loader/efi/chainloader.c [new file with mode: 0644]
loader/efi/chainloader_normal.c [new file with mode: 0644]
loader/i386/bsd.c [new file with mode: 0644]
loader/i386/bsd_normal.c [new file with mode: 0644]
loader/i386/efi/linux.c [new file with mode: 0644]
loader/i386/ieee1275/linux.c [new file with mode: 0644]
loader/i386/linux.c [new file with mode: 0644]
loader/i386/pc/chainloader.c [new file with mode: 0644]
loader/i386/pc/chainloader_normal.c [new file with mode: 0644]
loader/i386/pc/linux.c [new file with mode: 0644]
loader/i386/pc/multiboot.c [new file with mode: 0644]
loader/i386/pc/multiboot2.c [new file with mode: 0644]
loader/i386/pc/multiboot_normal.c [new file with mode: 0644]
loader/ieee1275/multiboot2.c [new file with mode: 0644]
loader/linux_normal.c [new file with mode: 0644]
loader/multiboot2.c [new file with mode: 0644]
loader/multiboot_loader.c [new file with mode: 0644]
loader/multiboot_loader_normal.c [new file with mode: 0644]
loader/powerpc/ieee1275/linux.c [new file with mode: 0644]
loader/powerpc/ieee1275/linux_normal.c [new file with mode: 0644]
mkinstalldirs [new file with mode: 0755]
normal/arg.c [new file with mode: 0644]
normal/cmdline.c [new file with mode: 0644]
normal/color.c [new file with mode: 0644]
normal/command.c [new file with mode: 0644]
normal/completion.c [new file with mode: 0644]
normal/execute.c [new file with mode: 0644]
normal/function.c [new file with mode: 0644]
normal/i386/setjmp.S [new file with mode: 0644]
normal/lexer.c [new file with mode: 0644]
normal/main.c [new file with mode: 0644]
normal/menu.c [new file with mode: 0644]
normal/menu_entry.c [new file with mode: 0644]
normal/menu_text.c [new file with mode: 0644]
normal/menu_viewer.c [new file with mode: 0644]
normal/misc.c [new file with mode: 0644]
normal/parser.y [new file with mode: 0644]
normal/powerpc/setjmp.S [new file with mode: 0644]
normal/script.c [new file with mode: 0644]
normal/sparc64/setjmp.S [new file with mode: 0644]
normal/x86_64/setjmp.S [new file with mode: 0644]
partmap/acorn.c [new file with mode: 0644]
partmap/amiga.c [new file with mode: 0644]
partmap/apple.c [new file with mode: 0644]
partmap/gpt.c [new file with mode: 0644]
partmap/pc.c [new file with mode: 0644]
partmap/sun.c [new file with mode: 0644]
stamp-h.in [new file with mode: 0644]
term/efi/console.c [new file with mode: 0644]
term/gfxterm.c [new file with mode: 0644]
term/i386/pc/at_keyboard.c [new file with mode: 0644]
term/i386/pc/console.c [new file with mode: 0644]
term/i386/pc/serial.c [new file with mode: 0644]
term/i386/pc/vesafb.c [new file with mode: 0644]
term/i386/pc/vga.c [new file with mode: 0644]
term/i386/pc/vga_text.c [new file with mode: 0644]
term/i386/vga_common.c [new file with mode: 0644]
term/ieee1275/ofconsole.c [new file with mode: 0644]
term/terminfo.c [new file with mode: 0644]
term/tparm.c [new file with mode: 0644]
term/usb_keyboard.c [new file with mode: 0644]
util/console.c [new file with mode: 0644]
util/elf/grub-mkimage.c [new file with mode: 0644]
util/getroot.c [new file with mode: 0644]
util/grub-editenv.c [new file with mode: 0644]
util/grub-emu.c [new file with mode: 0644]
util/grub-fstest.c [new file with mode: 0644]
util/grub-mkconfig.in [new file with mode: 0644]
util/grub-mkconfig_lib.in [new file with mode: 0644]
util/grub-mkdevicemap.c [new file with mode: 0644]
util/grub-mkfont.c [new file with mode: 0644]
util/grub-pe2elf.c [new file with mode: 0644]
util/grub-probe.c [new file with mode: 0644]
util/grub.d/00_header.in [new file with mode: 0644]
util/grub.d/10_freebsd.in [new file with mode: 0644]
util/grub.d/10_hurd.in [new file with mode: 0644]
util/grub.d/10_linux.in [new file with mode: 0644]
util/grub.d/10_windows.in [new file with mode: 0644]
util/grub.d/30_os-prober.in [new file with mode: 0644]
util/grub.d/40_custom.in [new file with mode: 0644]
util/grub.d/README [new file with mode: 0644]
util/hostdisk.c [new file with mode: 0644]
util/hostfs.c [new file with mode: 0644]
util/i386/efi/grub-install.in [new file with mode: 0644]
util/i386/efi/grub-mkimage.c [new file with mode: 0644]
util/i386/pc/grub-install.in [new file with mode: 0644]
util/i386/pc/grub-mkimage.c [new file with mode: 0644]
util/i386/pc/grub-mkrescue.in [new file with mode: 0644]
util/i386/pc/grub-setup.c [new file with mode: 0644]
util/i386/pc/misc.c [new file with mode: 0644]
util/ieee1275/grub-install.in [new file with mode: 0644]
util/lvm.c [new file with mode: 0644]
util/misc.c [new file with mode: 0644]
util/powerpc/ieee1275/grub-mkrescue.in [new file with mode: 0644]
util/powerpc/ieee1275/misc.c [new file with mode: 0644]
util/raid.c [new file with mode: 0644]
util/resolve.c [new file with mode: 0644]
util/update-grub_lib.in [new file with mode: 0644]
util/usb.c [new file with mode: 0644]
video/bitmap.c [new file with mode: 0644]
video/i386/pc/vbe.c [new file with mode: 0644]
video/i386/pc/vbeblit.c [new file with mode: 0644]
video/i386/pc/vbefill.c [new file with mode: 0644]
video/i386/pc/vbeutil.c [new file with mode: 0644]
video/readers/jpeg.c [new file with mode: 0644]
video/readers/png.c [new file with mode: 0644]
video/readers/tga.c [new file with mode: 0644]
video/video.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..8de5c4d
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,23 @@
+The following authors assigned copyright on their work to the Free
+Software Foundation:
+
+Yoshinori K. Okuji designed and implemented the initial version.
+
+Jeroen Dekkers added initrd support, Multiboot support, and fixed bugs
+in ext2fs.
+
+Marco Gerards added ext2fs support, grub-emu, a new command-line
+engine, and fixed many bugs.
+
+Omniflux added terminfo and serial support.
+
+Vincent Pelletier added Sparc64 support.
+
+Hollis Blanchard implemented many parts of PowerPC support.
+
+Tomas Ebenlendr added the command chainloader into the normal mode,
+fixed some bugs.
+
+Guillem Jover merged architecture-independent ELF support code.
+
+Vesa Jaaskelainen added VBE support.
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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.
+
+    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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..0ec24e9
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,14419 @@
+2009-02-21  Robert Millan  <rmh@aybabtu.com>
+
+       Implement USB keyboard support (based on patch by Marco Gerards)
+
+       * conf/i386-pc.rmk (pkglib_MODULES): Add `usb_keyboard.mod'.
+       (usb_keyboard_mod_SOURCES, usb_keyboard_mod_CFLAGS)
+       (usb_keyboard_mod_LDFLAGS): New variables.
+
+       * term/usb_keyboard.c: New file.
+
+2009-02-14  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       Corrected wrong declaration
+
+       * kern/disk.c: corrected declaration of grub_disk_ata_pass_through.
+
+2009-02-14  Christian Franke  <franke@computer.org>
+
+       * commands/lspci.c (grub_pci_classes): Add `SATA Controller'.
+       (grub_lspci_iter): Print class code and programming interface byte.
+
+2009-02-14  Christian Franke  <franke@computer.org>
+
+       * gendistlist.sh: Ignore `.svn' directories.
+
+2009-02-14  Felix Zielcke  <fzielcke@z-51.de>
+
+       * fs/fat.c: Add 2009 to Copyright line.
+
+2009-02-14  Christian Franke  <franke@computer.org>
+
+       * commands/hdparm.c: New file.  Provides `hdparm' command
+       which sends ATA commands via grub_disk_ata_pass_through ().
+
+       * conf/i386-pc.rmk: Add ata_pthru.mod and hdparm.mod.
+
+       * disk/ata.c: Include <grub/ata.h>.  Move <grub/misc.h>
+       and <grub/cpu/io.h> to include/grub/ata.h.
+       (enum grub_ata_addressing_t): Move to include/grub/ata.h.
+       (GRUB_CDROM_SECTOR_SIZE): Remove.
+       (GRUB_ATA_*): Move to include/grub/ata.h.
+       (GRUB_ATAPI_*): Likewise.
+       (enum grub_ata_commands): Likewise.
+       (enum grub_ata_timeout_milliseconds): Likewise.
+       (struct grub_ata_device): Likewise.
+       (grub_ata_regset): Likewise.
+       (grub_ata_regget): Likewise.
+       (grub_ata_regset2): Likewise.
+       (grub_ata_regget2): Likewise.
+       (grub_ata_check_ready): Likewise.
+       (grub_ata_wait_not_busy): Remove static, exported in
+       include/grub/ata.h.
+       (grub_ata_wait_drq): Likewise.
+       (grub_ata_pio_read): Likewise.
+
+       * disk/ata_pthru.c: New file.  Provides grub_ata_pass_through ()
+       function for hdparm.mod.
+
+       * include/grub/ata.h: New file, contains declarations from
+       disk/ata.c.
+       (enum grub_ata_commands): Add new commands for commands/hdparm.c.
+
+       * include/grub/disk.h (grub_disk_ata_pass_through_parms): New struct.
+       (grub_disk_ata_pass_through): New exported variable.
+
+       * kern/disk.c (grub_disk_ata_pass_through): New variable.
+
+2009-02-13  Colin D Bennett  <colin@gibibit.com>
+
+       Support multiple fallback entries, and provide an API to support
+       executing default+fallback menu entries.  Renamed the `terminal' menu
+       viewer to `text'.
+
+       * include/grub/normal.h (grub_normal_text_menu_viewer): New global
+       variable declaration.
+       (grub_menu_execute_callback): New structure declaration.
+       (grub_menu_execute_callback_t): New typedef.
+       (grub_menu_execute_with_fallback): New function declaration.
+       (grub_menu_get_entry): Likewise.
+       (grub_menu_get_timeout): Likewise.
+       (grub_menu_set_timeout): Likewise.
+
+       * normal/main.c (GRUB_MOD_INIT(normal)): Refer to new variable name.
+
+       * normal/menu.c (grub_wait_after_message): Moved to
+       `normal/menu_text.c'.
+       (draw_border): Likewise.
+       (print_message): Likewise.
+       (print_entry): Likewise.
+       (print_entries): Likewise.
+       (grub_menu_init_page): Likewise.
+       (get_entry_number): Likewise.
+       (print_timeout): Likewise.
+       (run_menu): Likewise.
+       (grub_menu_execute_entry): Likewise.
+       (show_text_menu): Likewise.
+       (get_and_remove_first_entry_number): New function.
+       (grub_menu_execute_with_fallback): Likewise.
+       (get_entry): Renamed to ...
+       (grub_menu_get_entry): .. this and made it global.
+       (get_timeout): Renamed to ...
+       (grub_menu_get_timeout): ... this and made it global.
+       (set_timeout): Renamed to ...
+       (grub_menu_set_timeout): ... this and made it global.
+       (grub_normal_terminal_menu_viewer): Renamed to ...
+       (grub_normal_text_menu_viewer): ... this.
+
+       * normal/menu_text.c: New file.  Extracted text-menu-specific code
+       from normal/menu.c.
+
+       * conf/i386-coreboot.rmk (grub_emu_SOURCES): Add `normal/menu_text.c'.
+       (normal_mod_SOURCES): Likewise.
+
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise.
+       (normal_mod_SOURCES): Likewise.
+
+       * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       (normal_mod_SOURCES): Likewise.
+
+       * conf/i386-pc.rmk, (grub_emu_SOURCES): Likewise.
+       (normal_mod_SOURCES): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       (normal_mod_SOURCES): Likewise.
+
+       * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       (normal_mod_SOURCES): Likewise.
+
+       * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise.
+       (normal_mod_SOURCES): Likewise.
+
+2009-02-11  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/00_header.in: Update old reference to `font' command.
+
+2009-02-10  Felix Zielcke  <fzielcke@z-51.de>
+
+       * fs/fat.c (grub_fat_mount): Fix wrong comparison.
+
+       Based on patch from Javier Martín.
+
+2009-02-09  Felix Zielcke  <fzielcke@z-51.de>
+
+       * conf/common.rmk (grub_probe_SOURCES): Move fs/ext2.c before fs/fat.c
+       to avoid false posivites with FAT.
+       (grub_fstest_SOURCES): Likewise.
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise.
+       * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       * conf/i386-coreboot.rmk (grub_emu_SOURCES): Likewise.
+       * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+
+2009-02-09  Felix Zielcke  <fzielcke@z-51.de>
+
+       * fs/fat.c (grub_fat_mount): Try to avoid false positives by checking
+       bpb.version_specific.fat12_or_fat16.fstype and
+       bpb.version_specific.fat32.fstype.
+
+2009-02-08  Robert Millan  <rmh@aybabtu.com>
+
+       * fs/tar.c: Replace "fs/cpio.c" with "cpio.c".
+
+2009-02-08  Robert Millan  <rmh@aybabtu.com>
+
+       * Makefile.in (host_os, host_cpu): New variables.
+       (target_os): Remove.  Update all users.
+
+2009-02-08  Marco Gerards  <marco@gnu.org>
+
+       * Makefile.in (enable_grub_emu_usb): New variable.
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Add `disk/scsi.c'.
+       (grub_emu_SOURCES) [grub_emu_SOURCES]: Add `disk/usbms.c',
+       `util/usb.c', `bus/usb/usb.c' and `commands/usbtest.c'.
+       (grub_emu_LDFLAGS): Add `$(LIBUSB)'.
+       (pkglib_MODULES): Add `usb.mod', `uhci.mod', `ohci.mod',
+       `usbtest.mod' and `usbms.mod'.
+       (usb_mod_SOURCES, usb_mod_CFLAGS, usb_mod_LDFLAGS)
+       (usbtest_mod_SOURCES, usbtest_mod_CFLAGS, usbtest_mod_LDFLAGS)
+       (uhci_mod_SOURCES, uhci_mod_CFLAGS, uhci_mod_LDFLAGS,
+       (ohci_mod_SOURCES, ohci_mod_CFLAGS, ohci_mod_LDFLAGS)
+       (usbms_mod_SOURCES, usbms_mod_CFLAGS, usbms_mod_LDFLAGS): New
+       variables.
+
+       * disk/usbms.c: New file.
+
+       * include/grub/usb.h: Likewise.
+
+       * include/grub/usbtrans.h: Likewise.
+
+       * include/grub/usbdesc.h: Likewise.
+
+       * bus/usb/usbtrans.c: Likewise.
+
+       * bus/usb/ohci.c: Likewise.
+
+       * bus/usb/uhci.c: Likewise.
+
+       * bus/usb/usbhub.c: Likewise.
+
+       * bus/usb/usb.c: Likewise.
+
+       * commands/usbtest.c: Likewise.
+
+       * util/usb.c: Likewise.
+       
+       * include/grub/err.h (grub_err_t): Add `GRUB_ERR_IO'.
+
+       * configure.ac: Test for libusb presence.
+       
+       * util/grub-emu.c (main) [HAVE_LIBUSB_H]: Call `grub_libusb_init'.
+
+2009-02-08  Vesa Jääskeläinen  <chaac@nic.fi>
+
+       * kern/mm.c: Add more comments.
+
+2009-02-08  Robert Millan  <rmh@aybabtu.com>
+
+       Patch from Javier Martín.
+       * fs/ext2.c (EXT2_DRIVER_SUPPORTED_INCOMPAT): Add
+       `EXT4_FEATURE_INCOMPAT_FLEX_BG'.
+
+2009-02-08  Robert Millan  <rmh@aybabtu.com>
+
+       * fs/cpio.c: Split tar functionality to ...
+       * fs/tar.c: ... here (new file).  Update all users.
+
+2009-02-07  Robert Millan  <rmh@aybabtu.com>
+
+       * fs/ext2.c (grub_ext2_mount): Avoid mounting filesystems with
+       backward-incompatible features.
+
+       Based on patch from Javier Martín, with some adjustments.
+
+2009-02-07  Michael Scherer <misc@mandriva.org>
+
+       * fs/hfs.c (grub_hfsplus_iterate_dir): Treat hfs+ as case insensitive.
+
+2009-02-07  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/common.rmk (grub_probe_SOURCES, grub_fstest_SOURCES): Move
+       position of `disk/lvm.c' to ensure grub_init_all() always picks it
+       after the RAID stuff.
+
+2009-02-05  Vesa Jääskeläinen  <chaac@nic.fi>
+
+       Fixes problem when running vbetest command as reported by 
+       Vladimir Serbinenko <phcoder@gmail.com>.
+
+       * (grub_vbe_set_video_mode): Fixed problem with text modes.
+
+2009-02-04  Felix Zielcke  <fzielcke@z-51.de>
+
+       util/getroot.c (grub_util_get_grub_dev): Add support for /dev/mdNpN and
+       /dev/md/NpN style mdraid devices.
+
+2009-02-03  Felix Zielcke  <fzielcke@z-51.de>
+
+       * util/unifont2pff.rb: Remove.
+
+2009-02-03  Felix Zielcke  <fzielcke@z-51.de>
+
+       * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Add a missing trailing
+       `#'.
+
+2009-02-03  Felix Zielcke  <fzielcke@z-51.de>
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Add `normal/menu_viewer.c'.
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise.
+       * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise.
+       * conf/i386-coreboot.rmk (grub_emu_SOURCES): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+
+2009-02-02  Christian Franke  <franke@computer.org>
+
+       * lib/hexdump.c (hexdump): Print at most 3 lines if data is identical.
+
+2009-02-01  Felix Zielcke  <fzielcke@z-51.de>
+
+       * INSTALL: Note that we now require at least autoconf 2.59 and
+       that LZO is optional.
+
+2009-02-01  Vesa Jääskeläinen  <chaac@nic.fi>
+
+       Base on patch on bug #24154 created by Tomas Tintera
+       <trosos@seznam.cz>.
+
+       * video/i386/pc/vbe.c (grub_video_vbe_scroll): Fix downward scrolling.
+
+2009-02-01  Vesa Jääskeläinen  <chaac@nic.fi>
+
+       Based on patch on bug #25318 created by Bernhard Rosenkraenzer
+       <bero@arklinux.org>.
+
+       * normal/parser.y (script_init): Add missing semicolon.
+
+2009-01-31  Colin D Bennett  <colin@gibibit.com>
+
+       * normal/main.c: Add include to grub/menu_viewer.h.
+       (free_menu_entry_classes): Added.
+       (grub_normal_menu_addentry): Added class property handling.
+       (grub_normal_execute): Changed to use new menu viewer for menu viewing.
+       (GRUB_MOD_INIT(normal)): Added register for text based menu viewer.
+
+       * normal/menu_viewer.c: New file.
+
+       * normal/menu.c (run_menu_entry): Renamed to ...
+       (grub_menu_execute_entry): ... this and made it as global.
+       (grub_menu_run): Renamed to ...
+       (show_text_menu): ... this and made it local.
+       (show_text_menu): Adapt to new function names.
+       (grub_normal_terminal_menu_viewer): New global variable.
+
+       * include/grub/menu.h: New file.
+
+       * include/grub/menu_viewer.h: New file.
+
+       * include/grub/normal.h: Added include to grub/menu.h.
+       (grub_menu_entry): Moved to include/grub/menu.h.
+       (grub_menu_entry_t): Likewise.
+       (grub_menu): Likewise.
+       (grub_menu_t): Likewise.
+       (grub_normal_terminal_menu_viewer): Added.
+       (grub_menu_execute_entry): Likewise.
+       (grub_menu_run): Removed.
+
+       * DISTLIST: Added include/grub/menu.h.
+       Added include/grub/menu_viewer.h.
+       Added normal/menu_viewer.c.
+
+2009-01-31  Vesa Jääskeläinen  <chaac@nic.fi>
+
+       * normal/execute.c (grub_script_execute_menuentry): Changed to use
+       arglist for menutitle arguments.
+
+       * normal/main.c (grub_normal_menu_addentry): Likewise.
+
+       * normal/parser.y (menuentry): Likewise.
+
+       * normal/script.c (grub_script_create_cmdmenu): Likewise.
+
+       * include/grub/script.h (grub_script_cmd_menuentry): Likewise.
+       (grub_script_create_cmdmenu): Likewise.
+
+       * include/grub/normal.h (grub_normal_menu_addentry): Likewise.
+
+       * conf/i386-pc.rmk (normal_mod_SOURCES): Adapt Colin D Bennett's
+       changes.
+
+       * conf/x86_64-efi.rmk (normal_mod_SOURCES): Likewise.
+
+       * conf/i386-coreboot.rmk (normal_mod_SOURCES): Likewise.
+
+       * conf/i386-efi.rmk (normal_mod_SOURCES): Likewise.
+
+       * conf/i386-ieee1275.rmk (normal_mod_SOURCES): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (normal_mod_SOURCES): Likewise.
+
+       * conf/sparc64-ieee1275.rmk (normal_mod_SOURCES): Likewise.
+
+2009-01-30  Christian Franke  <franke@computer.org>
+
+       * normal/arg.c (grub_arg_show_help): Add indentation if '\n' appears
+       in option help text.
+
+2009-01-27  Pavel Roskin  <proski@gnu.org>
+
+       * disk/fs_uuid.c (search_fs_uuid): Ignore case of the UUID.
+
+2009-01-27  Vesa Jääskeläinen  <chaac@nic.fi>
+
+       * commands/lsmmap.c: Add include to grub/machine/memory.h.
+
+       * fs/i386/pc/pxe.c (grub_pxefs_open): Fix sign problem.
+
+       * term/i386/pc/at_keyboard.c (GRUB_MOD_FINI(at_keyboard)): Use proper
+       unregister function.
+
+2009-01-27  Vesa Jääskeläinen  <chaac@nic.fi>
+
+       * disk/scsi.c (grub_scsi_read): Fix sign problem.
+
+       * term/i386/pc/vga_text.c (grub_vga_text_init_fini). Fix declaration.
+
+       * util/grub-mkfont.c (usage): Fix typo.
+
+       * util/elf/grub-mkimage.c (load_modules): Fix warning.
+
+2009-01-26  Daniel Mierswa  <impulze@impulze.org>
+
+       * fs/fat.c (grub_fat_uuid): Fix shift of the first two bytes.
+
+       * commands/search.c (search_fs_uuid): Ignore case of the UUID.
+
+       * kern/misc.c (grub_strcasecmp): New function.
+       (grub_strcasecmp): Use grub_size_t instead of int for length.
+       Fix return value.
+       * include/grub/misc.h: Update function prototypes.
+
+2009-01-26  Robert Millan  <rmh@aybabtu.com>
+
+       * configure.ac: Fix cross-compilation check.
+
+2009-01-22  Christian Franke  <franke@computer.org>
+
+       * kern/misc.c (grub_vsprintf): Fix size and termination of `format2'
+       (precision) digit string.  Allow `.format2' without `format1' (width).
+       Limit input chars for `%s' output to `format2' if specified.  This is
+       compatible with standard printf ().
+
+2009-01-22  Christian Franke  <franke@computer.org>
+
+       * disk/ata.c (grub_ata_wait_status): Replace by ...
+       (grub_ata_wait_not_busy): ... this function.  Checks only BSY bit,
+       other status bits may be invalid while BSY is asserted.
+       (grub_ata_check_ready): New function.
+       (grub_ata_cmd): Removed.
+       (grub_ata_wait_drq): New function.
+       (grub_ata_strncpy): Remove inline.
+       (grub_ata_pio_read): Reduce to actual block transfer.  BSY wait
+       and error check now done by grub_ata_wait_drq ().
+       (grub_ata_pio_write): Likewise.
+       (grub_atapi_identify): Set DEV before check for !BSY.  Use
+       grub_ata_wait_drq () to wait for data.
+       (grub_ata_device_initialize): Add status register check to
+       detect missing SATA slave devices.  Add debug messages.
+       (grub_atapi_wait_drq): Use grub_ata_wait_not_busy ().
+       (grub_atapi_packet): Set DEV before check for !BSY.  Replace
+       transfer loop by grub_ata_pio_write ().
+       (grub_ata_identify): Set DEV before check for !BSY. Use
+       grub_ata_wait_drq () to wait for data.
+       (grub_ata_setaddress): Set DEV before check for !BSY.
+       (grub_ata_readwrite): Remove duplicate code, handle batch/rest and
+       read/write in one loop.  Fix invalid command on write.  Fix incomplete
+       command on (size % batch) == 0.  Add missing error check after write of
+       last block.  Add debug messages.
+       (grub_atapi_read):  Replace transfer loop by grub_ata_pio_read ().
+
+2009-01-19  Christian Franke  <franke@computer.org>
+
+       * disk/ata.c (GRUB_ATAPI_REG_*): New defines.
+       (GRUB_ATAPI_IREASON_*): Likewise.
+       (grub_ata_pio_write): Fix timeout error return.
+       (grub_atapi_identify): Add grub_ata_wait () after cmd.
+       (grub_atapi_wait_drq): New function.
+       (grub_atapi_packet): New parameter `size'.
+       Use grub_atapi_wait_drq () and direct write instead of
+       grub_ata_pio_write ().
+       (grub_atapi_read): Replace grub_ata_pio_read () by a loop which
+       reads the number of bytes requested by the device for each DRQ
+       assertion.
+       (grub_atapi_write): Remove old implementation, return not
+       implemented instead.
+
+2009-01-19  Christian Franke  <franke@computer.org>
+
+       * disk/scsi.c (grub_scsi_read10): Use scsi->blocksize instead
+       of 512 to calculate data size.
+       (grub_scsi_read12): Likewise.
+       (grub_scsi_write10): Likewise.
+       (grub_scsi_write12): Likewise.
+       (grub_scsi_read): Adjust size according to blocksize.
+       Add checks for invalid blocksize and unaligned transfer.
+
+2009-01-19  Vesa Jääskeläinen  <chaac@nic.fi>
+
+       * font/font.c (grub_font_loader_init): Re-position unknown glyph.
+
+       * term/gfxterm.c (write_char): Fix background rendering for wide
+       width glyphs.
+
+2009-01-19  Robert Millan  <rmh@aybabtu.com>
+
+       * config.guess: Update to latest version from config git.
+       * config.sub: Likewise.
+
+2009-01-17  Felix Zielcke  <fzielcke@z-51.de>
+
+       * Makefile.in: Change font compilation to use new grub-mkfont instead
+       of java version.
+
+       * util/fonttool/src/org/gnu/grub/fonttool/BDFLoader.java: Remove.
+       * util/fonttool/src/org/gnu/grub/fonttool/CharDefs.java: Likewise.
+       * util/fonttool/src/org/gnu/grub/fonttool/CharacterRange.java: Likewise.
+       * util/fonttool/src/org/gnu/grub/fonttool/CharacterRange.java: Likewise.
+       * util/fonttool/src/org/gnu/grub/fonttool/Converter.java: Likewise.
+       * util/fonttool/src/org/gnu/grub/fonttool/Font.java: Likewise.
+       * util/fonttool/src/org/gnu/grub/fonttool/Glyph.java: Likewise.
+       * util/fonttool/src/org/gnu/grub/fonttool/PFF2Sections.java: Likewise.
+       * util/fonttool/src/org/gnu/grub/fonttool/PFF2Writer.java: Likewise.
+
+2009-01-16  Christian Franke  <franke@computer.org>
+
+       * disk/ata.c (enum grub_ata_commands): Remove EXEC_DEV_DIAGNOSTICS.
+       (enum grub_ata_timeout_milliseconds): New enum.
+       (grub_ata_wait_status): Add parameter milliseconds.
+       (grub_ata_cmd): Remove variable `err'.  Remove wait for !DRQ to allow
+       recovery from timed-out commands.
+       (grub_ata_pio_read): Add parameter milliseconds.  Fix error return,
+       return grub_errno instead of REG_ERROR.
+       (grub_ata_pio_write): Add parameter milliseconds.
+       (grub_atapi_identify): Fix size of ATAPI IDENTIFY sector.
+       Pass milliseconds to grub_ata_wait_status () and
+       grub_ata_pio_read ().
+       (grub_atapi_packet): Pass milliseconds to grub_ata_pio_write ().
+       (grub_ata_identify): Remove variable `ataerr'.  Pass milliseconds to
+       grub_ata_wait_status ().  Fix IDENTIFY timeout check.
+       (grub_ata_device_initialize): Remove EXECUTE DEVICE DIAGNOSTICS.
+       It is not suitable for device detection, because DEV bit is ignored,
+       the command may run too long, and not all devices set the signature
+       properly.
+       (grub_ata_pciinit): Clear grub_errno before grub_ata_device_initialize ().
+       (grub_ata_setaddress): Pass milliseconds to grub_ata_wait_status ().
+       Fix device selection, DEV bit must be set first to address the registers
+       of the correct device.
+       (grub_ata_readwrite): Pass milliseconds to grub_ata_wait_status () and
+       grub_ata_pio_read/write ().
+       (grub_atapi_read): Pass milliseconds to grub_ata_pio_read ().
+       (grub_atapi_write): Pass milliseconds to grub_ata_pio_write ().
+
+2009-01-13  Carles Pina i Estany  <carles@pina.cat>
+
+       * util/grub-editenv.c (main): Use fseeko(), not fseek().
+
+2009-01-13  Bean  <bean123ch@gmail.com>
+
+       * util/grub-mkfont.c (write_font): forget to remove some debug code.
+
+2009-01-13  Bean  <bean123ch@gmail.com>
+
+       * Makefile.in: (enable_grub_mkfont): New variable.
+       (freetype_cflags): Likewise.
+       (freetype_libs): Likewise.
+
+       * common.rmk (bin_UTILITIES): Add `grub-mkfont' if requested.
+       (grub_mkfont_SOURCES): New variable.
+       (grub_mkfont_CFLAGS): Likewise.
+       (grub_mkfont_LDFLAGS): Likewise.
+
+       * configure.ac (--enable-grub-mkfont): New option. Check for freetype2
+       library if `--enable-grub-mkfont' is requested.
+       (enable_grub_mkfont): New variable.
+       (freetype_cflags): Likewise.
+       (freetype_libs): Likewise.
+
+       * util/grub-mkfont.c: New file.
+
+2009-01-12  Christian Franke  <franke@computer.org>
+
+       * disk/ata.c (grub_ata_pciinit): Fix bit numbers of compatibility
+       mode check.  Fix setting of compat_use[].
+
+2009-01-10  Robert Millan  <rmh@aybabtu.com>
+
+       Update a few copyright years which we forgot to do in 2008 (only for
+       files whose changes made in 2008 were copyright-significant)
+
+       * Makefile.in: Add 2008 to Copyright line.
+       * disk/ieee1275/ofdisk.c: Likewise.
+       * disk/efi/efidisk.c: Likewise.
+       * kern/dl.c: Likewise.
+       * kern/sparc64/ieee1275/init.c: Likewise.
+       * kern/mm.c: Likewise.
+       * kern/efi/mm.c: Likewise.
+       * boot/i386/pc/boot.S: Likewise.
+       * genfslist.sh: Likewise.
+       * fs/iso9660.c: Likewise.
+       * fs/hfs.c: Likewise.
+       * fs/jfs.c: Likewise.
+       * fs/minix.c: Likewise.
+       * fs/ufs.c: Likewise.
+       * gensymlist.sh.in: Likewise.
+       * genkernsyms.sh.in: Likewise.
+       * include/grub/misc.h: Likewise.
+       * include/grub/types.h: Likewise.
+       * include/grub/symbol.h: Likewise.
+       * include/grub/elf.h: Likewise.
+       * include/grub/kernel.h: Likewise.
+       * include/grub/disk.h: Likewise.
+       * include/grub/dl.h: Likewise.
+       * include/grub/i386/linux.h: Likewise.
+       * include/grub/i386/pc/biosdisk.h: Likewise.
+       * include/grub/efi/api.h: Likewise.
+       * include/grub/efi/pe32.h: Likewise.
+       * include/grub/util/misc.h: Likewise.
+       * normal/execute.c: Likewise.
+       * normal/arg.c: Likewise.
+       * normal/completion.c: Likewise.
+       * normal/lexer.c: Likewise.
+       * normal/parser.y: Likewise.
+       * normal/misc.c: Likewise.
+       * commands/i386/pc/vbeinfo.c: Likewise.
+       * commands/hexdump.c: Likewise.
+       * commands/terminal.c: Likewise.
+       * commands/ls.c: Likewise.
+       * commands/help.c: Likewise.
+       * partmap/pc.c: Likewise.
+       * loader/efi/chainloader.c: Likewise.
+       * loader/multiboot_loader.c: Likewise.
+       * loader/i386/pc/multiboot2.c: Likewise.
+       * term/efi/console.c: Likewise.
+       * term/i386/pc/serial.c: Likewise.
+       * util/lvm.c: Likewise.
+       * util/console.c: Likewise.
+       * util/i386/efi/grub-mkimage.c: Likewise.
+       * util/raid.c: Likewise.
+
+2009-01-06  Vesa Jääskeläinen  <chaac@nic.fi>
+
+       * commands/videotest.c: Removed include to grub/machine/memory.h.
+
+       * conf/i386-pc.rmk (pkglib_MODULES): Removed video.mod, gfxterm.mod,
+       videotest.mod, bitmap.mod, tga.mod, jpeg.mod, png.mod.
+       (video_mod_SOURCES): Removed.
+       (video_mod_CFLAGS): Likewise.
+       (video_mod_LDFLAGS): Likewise.
+       (gfxterm_mod_SOURCES): Likewise.
+       (gfxterm_mod_CFLAGS): Likewise.
+       (gfxterm_mod_LDFLAGS): Likewise.
+       (videotest_mod_SOURCES): Likewise.
+       (videotest_mod_CFLAGS): Likewise.
+       (videotest_mod_LDFLAGS): Likewise.
+       (bitmap_mod_SOURCES): Likewise.
+       (bitmap_mod_CFLAGS): Likewise.
+       (bitmap_mod_LDFLAGS): Likewise.
+       (tga_mod_SOURCES): Likewise.
+       (tga_mod_CFLAGS): Likewise.
+       (tga_mod_LDFLAGS): Likewise.
+       (jpeg_mod_SOURCES): Likewise.
+       (jpeg_mod_CFLAGS): Likewise.
+       (jpeg_mod_LDFLAGS): Likewise.
+       (png_mod_SOURCES): Likewise.
+       (png_mod_CFLAGS): Likewise.
+       (png_mod_LDFLAGS): Likewise.
+
+       * conf/common.rmk (pkglib_MODULES): Added video.mod, videotest.mod,
+       bitmap.mod, tga.mod, jpeg.mod, png.mod, font.mod, gfxterm.mod
+       (video_mod_SOURCES): Added.
+       (video_mod_CFLAGS): Likewise.
+       (video_mod_LDFLAGS): Likewise.
+       (videotest_mod_SOURCES): Likewise.
+       (videotest_mod_CFLAGS): Likewise.
+       (videotest_mod_LDFLAGS): Likewise.
+       (bitmap_mod_SOURCES): Likewise.
+       (bitmap_mod_CFLAGS): Likewise.
+       (bitmap_mod_LDFLAGS): Likewise.
+       (tga_mod_SOURCES): Likewise.
+       (tga_mod_CFLAGS): Likewise.
+       (tga_mod_LDFLAGS): Likewise.
+       (jpeg_mod_SOURCES): Likewise.
+       (jpeg_mod_CFLAGS): Likewise.
+       (jpeg_mod_LDFLAGS): Likewise.
+       (png_mod_SOURCES): Likewise.
+       (png_mod_CFLAGS): Likewise.
+       (png_mod_LDFLAGS): Likewise.
+       (gfxterm_mod_SOURCES): Likewise.
+       (gfxterm_mod_CFLAGS): Likewise.
+       (gfxterm_mod_LDFLAGS): Likewise.
+
+       * term/gfxterm.c: Removed include to grub/machine/memory.h,
+       grub/machine/console.h.
+
+2009-01-04  Jerone Young  <jerone@gmail.com>
+
+       Make on screen instructions clearer
+
+       Based on patch created by Jidanni <jidanni@jidanni.org>
+
+       * normal/menu.c: print clearer instructions on the screen
+
+2009-01-02  Colin D Bennett  <colin@gibibit.com>
+
+       New font engine.
+
+       Additional changes by Vesa Jääskeläinen <chaac@nic.fi> to adapt to
+       build system and fixed gfxterm.c to work with different sized fonts.
+
+       * configure.ac: Changed UNIFONT_HEX to UNIFONT_BDF.
+
+       * configure: Re-generated.
+
+       * DISTLIST: Removed font/manager.c.
+       Added font/font.c.
+       Added font/font_cmd.c.
+
+       * Makefile.in: Changed UNIFONT_HEX to UNIFONT_BDF.  Added Font tool
+       compilation.
+
+       * include/grub/misc.h (grub_utf8_to_ucs4): Changed prototype.  Changed users.
+
+       * kern/misc.c (grub_utf8_to_ucs4): Changed prototype.
+
+       * kern/term.c: Changed users of grub_utf8_to_ucs4.
+
+       * normal/menu.c: Likewise.
+
+       * conf/common.rmk (font_mod_SOURCES): Removed font/manager.c.
+       (font_mod_SOURCES): Added font/font_cmd.c, font/font.c.
+
+       * include/grub/font.h: Replaced with new file.
+
+       * include/grub/video.h (GRUB_VIDEO_MODE_TYPE_ALPHA): Changed value.
+       (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED): Likewise.
+       (GRUB_VIDEO_MODE_TYPE_COLOR_MASK): Likewise.
+       (GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP): Added.
+       (grub_video_blit_format): Added GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED.
+       (grub_video_mode_info): Added bg_red, bg_green, bg_blue, bg_alpha,
+       fg_red, fg_green, fg_blue, fg_alpha.
+       (grub_video_adapter): Removed blit_glyph.
+       (grub_video_blit_glyph): Removed.
+
+       * font/manager.c: Removed file.
+
+       * font/font.c: New file.
+
+       * font/font_cmd.c: Likewise.
+
+       * video/video.c (grub_video_blit_glyph): Removed.
+
+       * video/i386/pc/vbe.c (grub_video_vbe_map_rgb): Added 1-bit support.
+       (grub_video_vbe_map_rgba): Likewise.
+       (grub_video_vbe_unmap_color_int): Likewise.
+       (grub_video_vbe_blit_glyph): Removed.
+       (grub_video_vbe_adapter): Removed blit_glyph.
+
+       * video/i386/pc/vbeutil.c (get_data_ptr): Added 1-bit support.
+       (get_pixel): Likewise.
+       (set_pixel): Likewise.
+
+       * commands/videotest.c (grub_cmd_videotest): Added more tests for fonts.
+
+       * term/gfxterm.c: Adapted to new font engine.
+
+       * term/i386/pc/vesafb.c: Marked as deprecated.  Made it compile.
+
+       * term/i386/pc/vga.c: Likewise.
+
+       * util/fonttool/src/org/gnu/grub/fonttool/BDFLoader.java: New file.
+
+       * util/fonttool/src/org/gnu/grub/fonttool/CharDefs.java: Likewise.
+
+       * util/fonttool/src/org/gnu/grub/fonttool/CharacterRange.java: Likewise.
+
+       * util/fonttool/src/org/gnu/grub/fonttool/CharacterRange.java: Likewise.
+
+       * util/fonttool/src/org/gnu/grub/fonttool/Converter.java: Likewise.
+
+       * util/fonttool/src/org/gnu/grub/fonttool/Font.java: Likewise.
+
+       * util/fonttool/src/org/gnu/grub/fonttool/Glyph.java: Likewise.
+
+       * util/fonttool/src/org/gnu/grub/fonttool/PFF2Sections.java: Likewise.
+
+       * util/fonttool/src/org/gnu/grub/fonttool/PFF2Writer.java: Likewise.
+
+       * util/grub.d/00_header.in: Changed to use new loadfont command.
+
+       * util/grub-mkconfig_lib.in: Changed font extension.
+
+2008-12-28  Felix Zielcke  <fzielcke@z-51.de>
+
+       * util/getroot.c (grub_util_get_grub_dev): Add support for
+       /dev/md/dNNpNN style partitionable mdraid devices.
+
+2008-12-12  Alex Smith  <alex@alex-smith.me.uk>
+
+       * fs/i386/pc/pxe.c (grub_pxefs_open): Handle the one open connection
+       at a time limit of the PXE TFTP API correctly.
+       (grub_pxefs_close): Likewise.
+
+2008-11-29  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/ata.c (grub_ata_pciinit): Handle errors raised by
+       grub_ata_device_initialize() calls.
+
+2008-11-28  Krzysztof Smiechowicz  <deadwood@wp.pl>
+
+       * fs/affs.c (grub_affs_iterate_dir): Return failure when directory
+       iteration failed.
+       * fs/sfs.c (grub_sfs_iterate_dir): Likewise.
+
+2008-11-28  Robert Millan  <rmh@aybabtu.com>
+
+       Fix build on powerpc-ieee1275.  Based on patch created by
+       Manoel Abranches <mrabran@linux.vnet.ibm.com>.
+       * conf/powerpc-ieee1275.rmk (kernel_elf_SOURCES): Add
+       `kern/ieee1275/mmap.c'.
+       * include/grub/powerpc/ieee1275/memory.h: New file.
+
+       Provide grub-install on coreboot.
+       * conf/i386-coreboot.rmk (sbin_SCRIPTS): Add `grub-install'.
+       (grub_install_SOURCES): New variable.
+       * util/i386/pc/grub-install.in: Add a few condition checks to make it
+       usable on coreboot.
+
+2008-11-25  Felix Zielcke  <fzielcke@z-51.de>
+
+       * util/grub-fstest.c (grub_term_get_current_input): Change return type
+       to `grub_term_input_t'.
+       (grub_term_get_current_output): Change return type to
+       `grub_term_output_t'.
+
+2008-11-22  Robert Millan  <rmh@aybabtu.com>
+
+       Fix breakage on coreboot due to declaration mismatch.
+       * term/i386/pc/vga_text.c (grub_vga_text_init_fini): New function.
+       (grub_vga_text_term): Use grub_vga_text_init_fini() instead of
+       grub_vga_text_cls().
+
+       * kern/i386/loader.S (grub_multiboot_backward_relocator): Improve
+       comments.  Avoid copying one more byte than necessary (just in case).
+
+       * conf/powerpc-ieee1275.rmk (kernel_elf_LDFLAGS): Change link address
+       to 0x200000 (avoids trouble with some OFW implementations, and matches
+       with the one in Yaboot).
+       Reported by Manoel Abranches
+
+2008-11-20  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/i386/coreboot/init.c (grub_time_tics): Remove variable.
+       (grub_get_rtc, grub_exit): Abort with grub_fatal() if called.
+
+       * util/grub-mkconfig_lib.in (grub_warn): New function.
+       (convert_system_path_to_grub_path): Use grub_warn() when issuing
+       warnings, to obtain consistent formatting.
+       * util/grub.d/00_header.in: Likewise.
+       * util/update-grub_lib.in: Likewise.
+
+       * loader/i386/linux.c (allocate_pages): Fix a warning.
+       Move comment text to `#error' stanza.
+
+       Harmonize ieee1275's grub_available_iterate() with the generic
+       grub_machine_mmap_iterate() interface (fixes a recently-introduced
+       build problem on i386-ieee1275):
+       * kern/ieee1275/openfw.c (grub_available_iterate): Moved from here ...
+       * kern/ieee1275/mmap.c (grub_machine_mmap_iterate): ... here.  Add third
+       parameter `type'.  Update all users of this function.
+       * conf/i386-ieee1275.rmk (kernel_elf_SOURCES): Add
+       `kern/ieee1275/mmap.c'.
+       * kern/ieee1275/init.c
+       * include/grub/ieee1275/ieee1275.h (grub_available_iterate): Replace
+       with ...
+       (grub_machine_mmap_iterate): ... this.
+       * include/grub/i386/pc/memory.h (grub_machine_mmap_iterate): Change
+       return type to `grub_err_t'.  Update all implementations of this
+       function prototype.
+       * include/grub/i386/coreboot/memory.h (grub_machine_mmap_iterate):
+       Likewise.
+
+       Add `lsmmap' command (lists firmware-provided memory map):
+       * commands/lsmmap.c: New file.
+       * conf/i386-pc.rmk (pkglib_MODULES): Add `lsmmap.mod'.
+       (lsmmap_mod_SOURCES, lsmmap_mod_CFLAGS, lsmmap_mod_LDFLAGS): New
+       variables.
+       * conf/powerpc-ieee1275.rmk: Likewise.
+       * conf/i386-coreboot.rmk: Likewise.
+       * conf/i386-ieee1275.rmk: Likewise.
+
+2008-11-19  Robert Millan  <rmh@aybabtu.com>
+
+       * loader/i386/pc/linux.c (grub_rescue_cmd_initrd): Fix a typo.
+       * loader/i386/linux.c (grub_rescue_cmd_initrd): Implement a few needed
+       constraints to initrd allocation (based on code from
+       loader/i386/pc/linux.c).  Without them, initrd was allocated too high
+       for Linux to find it.
+
+2008-11-14  Robert Millan  <rmh@aybabtu.com>
+
+       * fs/cpio.c (grub_cpio_open): Compare `name' and `fn' by hand in
+       order to cope with duplicate slashes.
+
+2008-11-14  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/i386/coreboot/memory.h (GRUB_MEMORY_MACHINE_LOWER_SIZE):
+       Redefine to match with GRUB_MEMORY_MACHINE_UPPER_START (0x100000).  We
+       don't want to mess with lower memory, because it is used in the Linux
+       loader.
+
+       * loader/i386/linux.c (allocate_pages): Allocate `real_mode_mem' in
+       an appropriate place in lower memory, between 0x10000 and 0x90000,
+       like loader/i386/efi/linux.c does.  Linux often panics if real_mode_mem
+       is in our heap (probably as a result of it being corrupted during
+       decompression).  Add #error instance with comment to explain why this
+       loader isn't currently usable on PC/BIOS.
+
+2008-11-14  Robert Millan  <rmh@aybabtu.com>
+
+       * term/i386/pc/serial.c [! GRUB_MACHINE_PCBIOS]
+       (GRUB_SERIAL_PORT_NUM): Fix miscalculation.
+
+2008-11-12  Robert Millan  <rmh@aybabtu.com>
+
+       Make loader/i386/linux.c buildable on i386-pc (although disabled).
+
+       * include/grub/i386/pc/init.h: Include `<grub/machine/memory.h>'.
+       (struct grub_machine_mmap_entry, grub_machine_mmap_iterate): Move
+       from here ...
+       * include/grub/i386/pc/memory.h: ... to here.
+
+2008-11-12  Robert Millan  <rmh@aybabtu.com>
+
+       Fix build problems on i386-ieee1275 and *-efi (introduced by vga_text
+       split).
+
+       * include/grub/i386/pc/console.h: Include `<grub/i386/vga_common.h>'.
+       (grub_console_cur_color, grub_console_real_putchar)
+       (grub_console_putchar, grub_console_getcharwidth, grub_console_getwh)
+       (grub_console_setcolorstate, grub_console_setcolor)
+       (grub_console_getcolor): Move from here ...
+       * include/grub/i386/vga_common.h: ... to here (new file).
+
+       * term/i386/pc/vga_text.c: Replace `<grub/machine/console.h>' with
+       `<grub/i386/vga_common.h>' and `<grub/cpu/io.h>' with
+       `<grub/i386/io.h>'.
+       * term/i386/vga_common.c: Replace `<grub/machine/console.h>' with
+       `<grub/i386/vga_common.h>'.
+
+2008-11-12  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-pc.rmk (kernel_img_SOURCES): Add `term/i386/vga_common.c'.
+       * conf/i386.rmk (pkglib_MODULES): Add `vga_text.mod'.
+       (vga_text_mod_SOURCES, vga_text_mod_CFLAGS, vga_text_mod_LDFLAGS): New
+       variables.
+       * conf/i386-coreboot.rmk (kernel_elf_SOURCES): Replace
+       `term/i386/pc/console.c' with `term/i386/vga_common.c'.
+
+       * kern/i386/coreboot/init.c (grub_machine_init): Replace call to
+       grub_console_init() with call to grub_vga_text_init().
+       (grub_machine_fini): Replace call to
+       grub_console_fini() with call to grub_vga_text_fini() and
+       grub_at_keyboard_fini().
+
+       * include/grub/i386/pc/console.h: Include `<grub/term.h>'.
+       (grub_console_putchar, grub_console_getcharwidth, grub_console_getwh)
+       (grub_console_setcolorstate, grub_console_setcolor)
+       (grub_console_getcolor): New function prototypes.
+
+       * term/i386/pc/vga_text.c: Include `<grub/dl.h>'.
+       (grub_vga_text_getxy, grub_vga_text_gotoxy, grub_vga_text_cls)
+       (grub_vga_text_setcursor): Static-ize.
+       (grub_vga_text_term): New structure.
+       (GRUB_MOD_INIT(vga_text), GRUB_MOD_FINI(vga_text)): New functions.
+
+       * term/i386/pc/console.c: Remove `<grub/machine/machine.h>'.
+       (grub_console_cur_color, grub_console_standard_color)
+       (grub_console_normal_color, grub_console_highlight_color)
+       (map_char, grub_console_putchar, grub_console_getcharwidth)
+       (grub_console_getwh, grub_console_setcolorstate, grub_console_setcolor)
+       (grub_console_getcolor): Move from here ...
+       * term/i386/vga_common.c: ... to here (same function names).
+
+2008-11-12  Robert Millan  <rmh@aybabtu.com>
+
+       Use newly-added Multiboot support in coreboot.
+
+       * conf/i386-coreboot.rmk (kernel_elf_SOURCES): Replace
+       `kern/i386/coreboot/mmap.c' with `kern/i386/multiboot_mmap.c'.
+
+       * kern/i386/coreboot/startup.S: Enable Multiboot header, fix its
+       alignment, set `MULTIBOOT_MEMORY_INFO' flag.
+       (codestart): Store the MBI in `startup_multiboot_info' when we're
+       being loaded using Multiboot.
+
+       * kern/i386/coreboot/init.c (grub_machine_init): Move
+       grub_at_keyboard_init() call to beginning of function (useful for
+       debugging).  Call grub_machine_mmap_init() before attempting to use
+       grub_machine_mmap_iterate().
+       (grub_lower_mem, grub_upper_mem): Move from here ...
+       * kern/i386/multiboot_mmap.c (grub_lower_mem, grub_upper_mem): ... to
+       here (new file).
+
+       * include/grub/i386/coreboot/memory.h (grub_machine_mmap_init): New
+       function prototype.
+
+2008-11-12  Robert Millan  <rmh@aybabtu.com>
+
+       Fix a regression introduced by the at_keyboard.mod split.  Because
+       some terminals are default on some platforms and non-default on
+       others, the first terminal being registered determines which is
+       going to be default.
+
+       * kern/term.c (grub_term_register_input): If this is the first
+       terminal being registered, set it as the current one.
+       (grub_term_register_output): Likewise.
+
+       * term/efi/console.c (grub_console_init): Do not call
+       grub_term_set_current_output() or grub_term_set_current_input().
+       * term/ieee1275/ofconsole.c (grub_console_init): Likewise.
+       * term/i386/pc/console.c (grub_console_init): Likewise.
+       (grub_console_fini): Do not call grub_term_set_current_input()
+       (but leave grub_term_set_current_output() to restore text mode).
+
+2008-11-10  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/00_header.in: Add backward compatibility check for
+       versions of terminal.mod that don't understand `terminal_input' or
+       `terminal_output'.
+
+2008-11-09  Robert Millan  <rmh@aybabtu.com>
+
+       * commands/terminal.c (GRUB_MOD_FINI(terminal)): Unregister
+       `terminal_input' / `terminal_output', not `terminal'.
+
+2008-11-08  Robert Millan  <rmh@aybabtu.com>
+
+       * Makefile.in (include_DATA): Fix srcdir=. assumption.
+       (DISTCLEANFILES): Add `build_env.mk'.
+
+2008-11-08  Robert Millan  <rmh@aybabtu.com>
+
+       * term/i386/pc/vesafb.c (grub_vesafb_term): Change type to
+       `struct grub_term_output'.  Remove `.checkkey' and `.getkey'
+       members.  Update all users.
+       * util/console.c (grub_ncurses_term): Split in ...
+       (grub_ncurses_term_input): ... this, and ...
+       (grub_ncurses_term_output): ... this.  Update all users.
+       * term/ieee1275/ofconsole.c: Remove stale `#endif'.
+
+2008-11-08  Robert Millan  <rmh@aybabtu.com>
+
+       * Makefile.in (PKGLIB): Add $(pkglib_BUILDDIR).
+       (PKGDATA): Add $(pkgdata_SRCDIR).
+       (pkglib_BUILDDIR): New variable.
+       (pkgdata_SRCDIR): New variable.
+       (build_env.mk): New target.
+       (include_DATA): New variable.
+       (install-local): Install $(include_DATA) files in $(includedir).
+
+2008-11-07  Pavel Roskin  <proski@gnu.org>
+
+       * gendistlist.sh: Use C locale for sorting to ensure consistent
+       output on all systems.
+
+       * util/grub.d/00_header.in: Remove incorrect space before
+       "serial".
+
+2008-11-07  Robert Millan  <rmh@aybabtu.com>
+
+       * include/multiboot2.h (struct multiboot_header): Add `flags' member as
+       per specification.
+       * loader/multiboot2.c (grub_multiboot2): Fix Multiboot2 header check.
+       * loader/multiboot_loader.c (find_multi_boot2_header): New function
+       (based on find_multi_boot1_header).
+       (grub_rescue_cmd_multiboot_loader): Check for Multiboot2 header,
+       using find_multi_boot2_header(), and abort if neither Multiboot or
+       Multiboot headers were found.
+
+2008-11-07  Robert Millan  <rmh@aybabtu.com>
+
+       Modularize at_keyboard.mod:
+
+       * conf/i386.rmk (pkglib_MODULES): Add `at_keyboard.mod'.
+       (at_keyboard_mod_SOURCES, at_keyboard_mod_CFLAGS)
+       (at_keyboard_mod_LDFLAGS): New variables.
+
+       Actual terminal split:
+
+       * include/grub/term.h (struct grub_term): Split in ...
+       (struct grub_term_input): ... this, and ...
+       (struct grub_term_output): ... this.  Update all users.
+       (grub_term_set_current): Split in ...
+       (grub_term_set_current_input): ... this, and ...
+       (grub_term_set_current_output): ... this.
+       (grub_term_get_current): Split in ...
+       (grub_term_get_current_input): ... this, and ...
+       (grub_term_get_current_output): ... this.
+       (grub_term_register): Split in ...
+       (grub_term_register_input): ... this, and ...
+       (grub_term_register_output): ... this.
+       (grub_term_unregister): Split in ...
+       (grub_term_unregister_input): ... this, and ...
+       (grub_term_unregister_output): ... this.
+       (grub_term_iterate): Split in ...
+       (grub_term_iterate_input): ... this, and ...
+       (grub_term_iterate_output): ... this.
+
+       * kern/term.c (grub_term_list): Split in ...
+       (grub_term_list_input): ... this, and ...
+       (grub_term_list_output): ... this.  Update all users.
+       (grub_cur_term): Split in ...
+       (grub_cur_term_input): ... this, and ...
+       (grub_cur_term_output): ... this.  Update all users.
+       (grub_term_set_current): Split in ...
+       (grub_term_set_current_input): ... this, and ...
+       (grub_term_set_current_output): ... this.
+       (grub_term_get_current): Split in ...
+       (grub_term_get_current_input): ... this, and ...
+       (grub_term_get_current_output): ... this.
+       (grub_term_register): Split in ...
+       (grub_term_register_input): ... this, and ...
+       (grub_term_register_output): ... this.
+       (grub_term_unregister): Split in ...
+       (grub_term_unregister_input): ... this, and ...
+       (grub_term_unregister_output): ... this.
+       (grub_term_iterate): Split in ...
+       (grub_term_iterate_input): ... this, and ...
+       (grub_term_iterate_output): ... this.
+
+       * kern/misc.c (grub_abort): Split use of grub_term_get_current() into
+       a check for input and one for output (and only attempt to get keys
+       from user when input works).
+
+       * util/grub-probe.c (grub_term_get_current): Split in ...
+       (grub_term_get_current_input): ... this, and ...
+       (grub_term_get_current_output): ... this.
+       * util/grub-fstest.c: Likewise.
+       * util/i386/pc/grub-setup.c: Likewise.
+       * util/grub-editenv.c: Likewise.
+
+       Portability adjustments:
+
+       * conf/i386-ieee1275.rmk (kernel_elf_SOURCES): Remove
+       `term/i386/pc/at_keyboard.c'.
+       * kern/ieee1275/init.c [__i386__] (grub_machine_init): Remove call to
+       grub_keyboard_controller_init() (now handled by terminal .init).
+       * kern/i386/coreboot/init.c (grub_machine_init): Add call to
+       grub_at_keyboard_init().
+       * include/grub/i386/ieee1275/console.h (grub_keyboard_controller_init)
+       (grub_console_checkkey, grub_console_getkey): Remove (now provided by
+       at_keyboard.mod via input terminal interface).
+       * include/grub/i386/coreboot/console.h: Convert into a stub for
+       `<grub/i386/pc/console.h>'.
+
+       Migrate full terminals to new API:
+
+       * term/efi/console.c (grub_console_term): Split into ...
+       (grub_console_term_input): ... this, and ...
+       (grub_console_term_output): ... this.  Update all users.
+       * term/ieee1275/ofconsole.c: Remove __i386__ hack.
+       (grub_ofconsole_init): Split into ...
+       (grub_ofconsole_init_input): ... this, and ...
+       (grub_ofconsole_init_output): ... this.
+       (grub_ofconsole_term): Split into ...
+       (grub_ofconsole_term_input): ... this, and ...
+       (grub_ofconsole_term_output): ... this.  Update all users.
+       * term/i386/pc/serial.c (grub_serial_term): Split into ...
+       (grub_serial_term_input): ... this, and ...
+       (grub_serial_term_output): ... this.  Update all users.
+       * term/i386/pc/console.c (grub_console_term): Split into ...
+       (grub_console_term_input): ... this, and ...
+       (grub_console_term_output): ... this.  Update all users.
+       (grub_console_term_input): Only enable it on PC/BIOS platform.
+       (grub_console_init): Remove grub_keyboard_controller_init() call.
+
+       Migrate input terminals to new API:
+
+       * term/i386/pc/at_keyboard.c: Replace `cpu' and `machine' with
+       `i386' and `i386/pc' to enable build on x86_64 (this driver is
+       i386-specific anyway).
+       (grub_console_checkkey): Rename to ...
+       (grub_at_keyboard_checkkey): ... this.  Static-ize.  Update all
+       users.
+       (grub_keyboard_controller_orig): New variable.
+       (grub_console_getkey): Rename to ...
+       (grub_at_keyboard_getkey): ... this.  Static-ize.  Update all
+       users.
+       (grub_keyboard_controller_init): Static-ize.  Save original
+       controller value so that it can be restored ...
+       (grub_keyboard_controller_fini): ... here (new function).
+       (grub_at_keyboard_term): New structure.
+       (GRUB_MOD_INIT(at_keyboard), GRUB_MOD_FINI(at_keyboard)): New
+       functions.
+
+       Migrate output terminals to new API:
+
+       * term/i386/pc/vga.c (grub_vga_term): Change type to
+       `struct  grub_term_output'.  Remove `.checkkey' and `.getkey'
+       members.  Update all users.
+       * term/gfxterm.c (grub_video_term): Change type to
+       `struct  grub_term_output'.  Remove `.checkkey' and `.getkey'
+       members.  Update all users.
+       * include/grub/i386/pc/console.h (grub_console_checkkey)
+       (grub_console_getkey): Do not export (no longer needed by gfxterm,
+       etc).
+
+       Migrate `terminal' command and userland tools to new API:
+
+       * commands/terminal.c (grub_cmd_terminal): Split into ...
+       (grub_cmd_terminal_input): ... this, and ...
+       (grub_cmd_terminal_output): ... this.
+       (GRUB_MOD_INIT(terminal)): Split `terminal' command in two commands:
+       `terminal_input' and `terminal_output'.
+       * util/grub.d/00_header.in: Adjust `terminal' calls to new
+       `terminal_input' / `terminal_output' API.
+       * util/grub-mkconfig.in: Export ${GRUB_TERMINAL_INPUT} and
+       ${GRUB_TERMINAL_OUTPUT} instead of ${GRUB_TERMINAL} (and if user
+       provided ${GRUB_TERMINAL}, convert it).
+
+2008-11-04  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/10_freebsd.in: New file.  Generate grub configuration
+       for FreeBSD.
+       * conf/common.rmk (grub-mkconfig_SCRIPTS): Add 10_freebsd.
+
+2008-11-03  Bean  <bean123ch@gmail.com>
+
+       * kern/elf.c (grub_elf32_load): Revert to previous code.
+       (grub_elf64_load): Likewise.
+
+       * loader/i386/bsd.c (grub_bsd_elf32_hook): Change return address.
+
+2008-11-01  Robert Millan  <rmh@aybabtu.com>
+
+       * Makefile.in (CPPFLAGS): Fix builddir=. assumption.
+       (TARGET_CPPFLAGS): Likewise.
+       * genmk.rb (mod_src): Fix builddir=. and srcdir=. assumptions.
+
+2008-11-01  Carles Pina i Estany  <carles@pina.cat>
+
+       * normal/menu.c (run_menu): Add Previous and Next Page keys in menu.
+
+2008-10-29  Guillem Jover  <guillem.jover@nokia.com>
+
+       * disk/lvm.c (grub_lvm_scan_device): Fix error recovery by delaying the
+       addition of objects until the code is not going to be able to fail.
+
+2008-10-29  Guillem Jover  <guillem.jover@nokia.com>
+
+       * disk/lvm.c (grub_lvm_scan_device): Fix possible NULL value handling
+       (add a missing NULL check, and correct them by moving the pointer
+       operations after the actual check).
+
+2008-10-29  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-install.in: Handle empty string as output from
+       make_system_path_relative_to_its_root().
+
+2008-10-05  Hans Lambermont  <hans@lambermont.dyndns.org>
+
+       * disk/lvm.c (grub_lvm_scan_device): Allocate buffer space for the
+       circular metadata worst case scenario. If the metadata is circular
+       then copy the wrap in place.
+       * include/grub/lvm.h: Add GRUB_LVM_MDA_HEADER_SIZE, from the LVM2
+       project lib/format_text/layout.h
+       Circular metadata bug found and patch debugged by Jan Derk Gerlings.
+
+2008-10-03  Felix Zielcke  <fzielcke@z-51.de>
+
+       * util/i386/pc/grub-install.in: Source grub-mkconfig_lib instead of update-grub_lib.
+
+2008-10-03  Felix Zielcke  <fzielcke@z-51.de>
+
+       * util/update-grub_lib.in: Mention filename in warning message.
+
+2008-09-29  Felix Zielcke  <fzielcke@z-51.de>
+
+       * NEWS: Update for rename of update-grub to grub-mkconfig.
+
+2008-09-29  Felix Zielcke  <fzielcke@z-51.de>
+
+       * util/update-grub_lib.in: Copy to ...
+       * util/grub-mkconfig_lib.in: ... this.  Update all users.
+       * util/update-grub_lib.in: Make it a stub to `grub-mkconfig_lib.in'.
+       * util/update-grub.in: Rename to ...
+       * util/grub-mkconfig.in: ... this.  Update all users.  Remove `-y'
+       option. Add `--output' option to allow users to specify the generated
+       configuration file.  Default to stdout.
+       (update_grub_dir): Rename to ...
+       (grub_mkconfig_dir): ... this.
+       (grub_cfg): Default to an empty string.
+       * conf/common.rmk (update-grub): Rename to ...
+       (grub-mkconfig): ... this.
+       (update-grub_lib): Copy to ...
+       (grub-mkconfig_lib): ... this.
+       (update-grub_SCRIPTS): Copy to ...
+       (grub-mkconfig_SCRIPTS): ... this. Update all users.
+       (update-grub_DATA): Rename to ...
+       (grub-mkconfig_DATA): ... this.
+
+2008-09-28  Robert Millan  <rmh@aybabtu.com>
+
+       * fs/iso9660.c (struct grub_iso9660_primary_voldesc): Rename `created'
+       to `modified'.  Add the real `created' field.
+       (grub_iso9660_uuid): Use `modified' rather than `created' for
+       constructing the UUID.
+
+2008-09-28  Felix Zielcke  <fzielcke@z-51.de>
+
+       fs/jfs.c (grub_jfs_find_file): Treat multiple slashes like one.
+       Based on code from Tomas Ebenlendr <ebik@ucw.cz>.
+
+2008-09-28  Bean  <bean123ch@gmail.com>
+
+       * fs/ntfs.c (grub_ntfs_iterate_dir): Fix a bug in the previous patch.
+       Thanks to Christian Franke for finding this bug.
+
+2008-09-25  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub-mkdevicemap.c (make_device_map): Actually replace all
+       instances of grub_util_get_disk_name() (see previous commit).
+
+2008-09-25  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-pc.rmk (grub_mkdevicemap_SOURCES): Remove
+       `util/i386/get_disk_name.c'.
+       * conf/i386-efi.rmk: Likewise.
+       * conf/x86_64-efi.rmk: Likewise.
+       * conf/i386-coreboot.rmk: Likewise.
+       * conf/i386-ieee1275.rmk: Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_mkdevicemap_SOURCES): Remove
+       `util/ieee1275/get_disk_name.c'.
+       * include/grub/util/misc.h (grub_util_get_disk_name): Remove.
+       * util/ieee1275/get_disk_name.c: Remove file.
+       * util/i386/get_disk_name.c: Remove file.
+       * util/grub-mkdevicemap.c (make_device_map): Back to hardcoding
+       "hd%d" for device.map entries, rather than using
+       grub_util_get_disk_name().
+
+2008-09-24  Carles Pina i Estany  <carles@pina.cat>
+
+       * disk/dmraid_nvidia.c (grub_dmraid_nv_detect): Fix `unused parameter'
+       warning.
+       * commands/i386/pc/pxecmd.c (dmraid_nvidia): Likewise.
+
+2008-09-24  Carles Pina i Estany  <carles@pina.cat>
+
+       * include/grub/i386/pc/console.h (GRUB_TERM_NPAGE):
+       Changed to 0x5100.
+       (GRUB_TERM_PPAGE): Changed to 0x4900.
+
+2008-09-24  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/powerpc/ieee1275/console.h (GRUB_CONSOLE_KEY_*): Remove
+       macros (they were i386-pc specific).
+       * include/grub/sparc64/ieee1275/console.h: Likewise.
+       * include/grub/efi/console.h: Likewise.
+
+2008-09-22  Bean  <bean123ch@gmail.com>
+
+       * fs/ntfs.c (grub_ntfs_iterate_dir): Fix a rare case where $BITMAP is
+       resident and in attribute list.
+
+       * include/grub/ntfs.h (BMP_LEN): Removed.
+
+2008-09-22  Bean  <bean123ch@gmail.com>
+
+       * disk/ata.c (grub_atapi_open): Initialize devfnd, no need to set
+       scsi->name and scsi->luns, as they will be set in grub_scsi_open.
+
+       * disk/scsi.c (grub_scsi_open): Don't call p->close (scsi) here when
+       error occurs, as grub_disk_open will call grub_disk_close, which will
+       call p->close (scsi).
+
+2008-09-21  Felix Zielcke  <fzielcke@z-51.de>
+
+       * configure.ac (AC_INIT): Quote `GRUB' string and version number.
+       (AC_PREREQ): Bumped to 2.59.
+       (AC_TRY_COMPILE): Replace obsolete macro with ...
+       (AC_COMPILE_IFELSE): ... this.
+       * aclocal.m4 (AC_TRY_LINK): Replace obsolete macro with ...
+       (AC_LINK_IFELSE): ... this.
+
+2008-09-21  Felix Zielcke  <fzielcke@z-51.de>
+
+       * autogen.sh: Add a call to `gendistlist.sh'.
+
+2008-09-19  Christian Franke  <franke@computer.org>
+
+       * aclocal.m4 (grub_CHECK_ENABLE_EXECUTE_STACK): New function.
+       * configure.ac: Call grub_CHECK_ENABLE_EXECUTE_STACK.
+       * include/grub/misc.h [NEED_ENABLE_EXECUTE_STACK]:
+       Export __enable_execute_stack() to modules.
+       * kern/misc.c [NEED_ENABLE_EXECUTE_STACK] (__enable_execute_stack):
+       New function.
+
+2008-09-09  Felix Zielcke  <fzielcke@z-51.de>
+
+       * Makefile.in (RMKFILES): Add `i386.rmk' and `x86_64-efi.rmk'.
+       Sort the list.
+
+2008-09-09  Felix Zielcke  <fzielcke@z-51.de>
+
+       * util/hostdisk.c: Replace #include <grub/util/biosdisk.h> with
+       #include <grub/util/hostdisk.h>.
+
+2008-09-08  Robert Millan  <rmh@aybabtu.com>
+
+       * loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): Skip
+       segments when their filesz is zero (grub_file_read() interprets
+       zero-size as "read until EOF", which results in memory corruption).
+       Use `lowest_segment' rather than 0 for calculating the current
+       segment load address.
+
+2008-09-08  Robert Millan  <rmh@aybabtu.com>
+
+       * util/hostdisk.c (open_device): Replace a grub_util_info() call
+       with grub_dprintf("hostdisk", ...), as it was so verbose that it
+       clobbered useful information.
+
+2008-09-08  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/util/biosdisk.h: Move to ...
+       * include/grub/util/hostdisk.h: ... here.  Update all users.
+       * util/biosdisk.c: Move to ...
+       * util/hostdisk.c: ... here.  Update all users.
+
+2008-09-07  Robert Millan  <rmh@aybabtu.com>
+
+       * loader/i386/pc/multiboot.c (mmap_addr, mmap_length): Remove
+       variables.
+       (grub_multiboot): Move `mbi' allocation upwards, so that mmap address
+       and length can be stored directly in the `mbi->mmap_addr' and
+       `mbi->mmap_length' struct fields.
+
+2008-09-07  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386.rmk: New file.  Provides declaration for building
+       `cpuid.mod'.
+       * conf/i386-pc.rmk (pkglib_MODULES): Remove `cpuid.mod'.
+       (cpuid_mod_SOURCES, cpuid_mod_CFLAGS, cpuid_mod_LDFLAGS): Remove
+       variables.
+       Include `conf/i386.mk'.
+       * conf/i386-efi.rmk: Likewise.
+       * conf/x86_64-efi.rmk: Likewise.
+       * conf/i386-coreboot.rmk: Likewise.
+       * conf/i386-ieee1275.rmk: Likewise.
+
+2008-09-07  Vesa Jääskeläinen  <chaac@nic.fi>
+
+       Based on patch created by Colin D Bennett <colin@gibibit.com>.
+       Adds optimization support for BGR based modes.
+
+       * include/grub/i386/pc/vbeblit.h (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8) Removed.
+       (grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8): Likewise.
+       (grub_video_i386_vbeblit_R8G8B8_R8G8B8A8): Likewise.
+       (grub_video_i386_vbeblit_R8G8B8_R8G8B8X8): Likewise.
+       (grub_video_i386_vbeblit_index_R8G8B8A8): Likewise.
+       (grub_video_i386_vbeblit_index_R8G8B8X8): Likewise.
+       (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8): Likewise.
+       (grub_video_i386_vbeblit_R8G8B8_R8G8B8): Likewise.
+       (grub_video_i386_vbeblit_index_R8G8B8): Likewise.
+       (grub_video_i386_vbeblit_index_index): Likewise.
+       (grub_video_i386_vbeblit_replace_directN): Added.
+       (grub_video_i386_vbeblit_replace_BGRX8888_RGBX8888): Likewise.
+       (grub_video_i386_vbeblit_replace_BGRX8888_RGB888): Likewise.
+       (grub_video_i386_vbeblit_replace_BGR888_RGBX8888): Likewise.
+       (grub_video_i386_vbeblit_replace_BGR888_RGB888): Likewise.
+       (grub_video_i386_vbeblit_replace_RGBX8888_RGB888): Likewise.
+       (grub_video_i386_vbeblit_replace_RGB888_RGBX8888): Likewise.
+       (grub_video_i386_vbeblit_replace_index_RGBX8888): Likewise.
+       (grub_video_i386_vbeblit_replace_index_RGB888): Likewise.
+       (grub_video_i386_vbeblit_blend_BGRA8888_RGBA8888): Likewise.
+       (grub_video_i386_vbeblit_blend_BGR888_RGBA8888): Likewise.
+       (grub_video_i386_vbeblit_blend_RGBA8888_RGBA8888): Likewise.
+       (grub_video_i386_vbeblit_blend_RGB888_RGBA8888): Likewise.
+       (grub_video_i386_vbeblit_blend_index_RGBA8888): Likewise.
+
+       * include/grub/i386/pc/vbefill.h (grub_video_i386_vbefill_R8G8B8A8) Removed.
+       (grub_video_i386_vbefill_R8G8B8): Likewise.
+       (grub_video_i386_vbefill_index): Likewise.
+       (grub_video_i386_vbefill_direct32): Added.
+       (grub_video_i386_vbefill_direct24): Likewise.
+       (grub_video_i386_vbefill_direct16): Likewise.
+       (grub_video_i386_vbefill_direct8): Likewise.
+
+       * include/grub/video.h (grub_video_blit_format): Removed
+       GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8, GRUB_VIDEO_BLIT_FORMAT_R8G8B8.
+       (grub_video_blit_format): Added GRUB_VIDEO_BLIT_FORMAT_RGBA_8888,
+       GRUB_VIDEO_BLIT_FORMAT_BGRA_8888, GRUB_VIDEO_BLIT_FORMAT_RGB_888,
+       GRUB_VIDEO_BLIT_FORMAT_BGR_888, GRUB_VIDEO_BLIT_FORMAT_RGB_565,
+       GRUB_VIDEO_BLIT_FORMAT_BGR_565.
+
+       * video/video.c (grub_video_get_blit_format): Updated to use new
+       blit formats.  Added handling for 16 bit color modes.
+
+       * video/i386/pc/vbe.c (grub_video_vbe_fill_rect): Updated to use new
+       fillers.
+       (common_blitter): Updated to use new blitters.
+
+       * video/i386/pc/vbeblit.c (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8):
+       Removed.
+       (grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8): Likewise.
+       (grub_video_i386_vbeblit_R8G8B8_R8G8B8A8): Likewise.
+       (grub_video_i386_vbeblit_R8G8B8_R8G8B8X8): Likewise.
+       (grub_video_i386_vbeblit_index_R8G8B8A8): Likewise.
+       (grub_video_i386_vbeblit_index_R8G8B8X8): Likewise.
+       (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8): Likewise.
+       (grub_video_i386_vbeblit_R8G8B8_R8G8B8): Likewise.
+       (grub_video_i386_vbeblit_index_R8G8B8): Likewise.
+       (grub_video_i386_vbeblit_index_index): Likewise.
+       (grub_video_i386_vbeblit_replace_directN): Added.
+       (grub_video_i386_vbeblit_replace_BGRX8888_RGBX8888): Likewise.
+       (grub_video_i386_vbeblit_replace_BGRX8888_RGB888): Likewise.
+       (grub_video_i386_vbeblit_replace_BGR888_RGBX8888): Likewise.
+       (grub_video_i386_vbeblit_replace_BGR888_RGB888): Likewise.
+       (grub_video_i386_vbeblit_replace_RGBX8888_RGB888): Likewise.
+       (grub_video_i386_vbeblit_replace_RGB888_RGBX8888): Likewise.
+       (grub_video_i386_vbeblit_replace_index_RGBX8888): Likewise.
+       (grub_video_i386_vbeblit_replace_index_RGB888): Likewise.
+       (grub_video_i386_vbeblit_blend_BGRA8888_RGBA8888): Likewise.
+       (grub_video_i386_vbeblit_blend_BGR888_RGBA8888): Likewise.
+       (grub_video_i386_vbeblit_blend_RGBA8888_RGBA8888): Likewise.
+       (grub_video_i386_vbeblit_blend_RGB888_RGBA8888): Likewise.
+       (grub_video_i386_vbeblit_blend_index_RGBA8888): Likewise.
+
+       * video/i386/pc/vbefill.c (grub_video_i386_vbefill_R8G8B8A8): Removed.
+       (grub_video_i386_vbefill_R8G8B8): Likewise.
+       (grub_video_i386_vbefill_index): Likewise.
+       (grub_video_i386_vbefill_direct32): Added.
+       (grub_video_i386_vbefill_direct24): Likewise.
+       (grub_video_i386_vbefill_direct16): Likewise.
+       (grub_video_i386_vbefill_direct8): Likewise.
+
+       * video/readers/jpeg.c (grub_jpeg_decode_sos): Adapt to new blitter
+       types.
+
+       * video/readers/tga.c (grub_video_reader_tga): Adapt to new blitter
+       types.
+
+       * video/readers/png.c (grub_png_decode_image_header): Adapt to new
+       blitter types.
+
+       * video/bitmap.c (grub_video_bitmap_create): Adapt to new blitter
+       types.
+
+2008-09-06  Felix Zielcke  <fzielcke@z-51.de>
+
+       * disk/raid.c (insert_array): Set `array->chunk_size' to 64 for
+       RAID level 1.
+
+2008-09-06  Felix Zielcke  <fzielcke@z-51.de>
+
+       * fs/iso9660.c (grub_iso9660_date): New structure.
+       (grub_iso9660_primary_voldesc): Add `grub_iso9660_date' member.
+       (grub_iso9660_uuid): New function.
+
+2008-09-05  Bean  <bean123ch@gmail.com>
+
+       * fs/fshelp.c (grub_fshelp_find_file): Handle case insensitive names.
+
+       * fs/ntfs.c (list_file): Ignore names in DOS namespace, set the case
+       insensitive bit for names in Win32 and Win32 & DOS namespace.
+
+       * include/grub/fshelp.h (GRUB_FSHELP_CASE_INSENSITIVE): New macro.
+
+       * include/grub/types.h (LONG_MAX): Likewise.
+
+2008-09-04  Felix Zielcke  <fzielcke@z-51.de>
+
+       * util/getroot.c: Include <config.h>.
+       (grub_util_get_grub_dev): Rewrite to use asprintf for mdraid devices,
+       add support for /dev/md/N devices and handle LVM double dash escaping.
+
+2008-09-04  Felix Zielcke  <fzielcke@z-51.de>
+
+       * config.guess: Update to latest version from config git.
+       * config.sub: Likewise.
+
+2008-09-03  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/scsi.c (grub_scsi_open): Remove size limit when printing
+       `disk->total_sectors'.
+
+2008-09-01  Colin D Bennett  <colin@gibibit.com>
+
+       * include/grub/normal.h: Fixed incorrect comment for
+       GRUB_COMMAND_FLAG_NO_ARG_PARSE.
+
+2008-09-01  Colin D Bennett  <colin@gibibit.com>
+
+       * commands/i386/pc/vbeinfo.c (grub_cmd_vbeinfo): Replaced constant
+       values with defines.
+
+       * include/grub/i386/pc/vbe.h (GRUB_VBE_MODEATTR_SUPPORTED): Added.
+       (GRUB_VBE_MODEATTR_RESERVED_1): Likewise.
+       (GRUB_VBE_MODEATTR_BIOS_TTY_OUTPUT_SUPPORT): Likewise.
+       (GRUB_VBE_MODEATTR_COLOR): Likewise.
+       (GRUB_VBE_MODEATTR_GRAPHICS): Likewise.
+       (GRUB_VBE_MODEATTR_VGA_COMPATIBLE): Likewise.
+       (GRUB_VBE_MODEATTR_VGA_WINDOWED_AVAIL): Likewise.
+       (GRUB_VBE_MODEATTR_LFB_AVAIL): Likewise.
+       (GRUB_VBE_MODEATTR_DOUBLE_SCAN_AVAIL): Likewise.
+       (GRUB_VBE_MODEATTR_INTERLACED_AVAIL): Likewise.
+       (GRUB_VBE_MODEATTR_TRIPLE_BUF_AVAIL): Likewise.
+       (GRUB_VBE_MODEATTR_STEREO_AVAIL): Likewise.
+       (GRUB_VBE_MODEATTR_DUAL_DISPLAY_START): Likewise.
+       (GRUB_VBE_MEMORY_MODEL_TEXT): Likewise.
+       (GRUB_VBE_MEMORY_MODEL_CGA): Likewise.
+       (GRUB_VBE_MEMORY_MODEL_HERCULES): Likewise.
+       (GRUB_VBE_MEMORY_MODEL_PLANAR): Likewise.
+       (GRUB_VBE_MEMORY_MODEL_NONCHAIN4_256): Likewise.
+       (GRUB_VBE_MEMORY_MODEL_YUV): Likewise.
+
+2008-08-31  Robert Millan  <rmh@aybabtu.com>
+
+       * loader/i386/pc/multiboot.c (grub_get_multiboot_mmap_len): Fix
+       declaration.
+       (grub_multiboot): Fix a few warnings.
+
+2008-08-31  Robert Millan  <rmh@aybabtu.com>
+
+       * loader/i386/pc/multiboot.c: Update comment not to say that
+       boot_device support is unimplemented.
+
+2008-08-31  Robert Millan  <rmh@aybabtu.com>
+
+       * loader/i386/pc/multiboot.c: Update comment not to say that a.out
+       or memory map support are unimplemented.
+
+2008-08-31  Colin D Bennett  <colin@gibibit.com>
+
+       * util/i386/pc/grub-mkrescue.in: Support multiple overlay directories.
+
+2008-08-31  Colin D Bennett  <colin@gibibit.com>
+
+       * commands/i386/pc/vbeinfo.c (grub_cmd_vbeinfo): Show VBE version and
+       total video memory in 'vbeinfo' output; show color format details for
+       each video mode.
+
+2008-08-30  Pavel Roskin  <proski@gnu.org>
+
+       * util/genmoddep.c: Remove for real this time.
+       * DISTLIST: Remove util/genmoddep.c.
+
+2008-08-30  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/i386/pc/startup.S (multiboot_header): Force 4-byte alignment
+       as required by Multiboot spec (it was already 4-byte aligned, but
+       only by chance).
+
+2008-08-29  Pavel Roskin  <proski@gnu.org>
+
+       * kern/powerpc/ieee1275/crt0.S: Rename to ...
+       * kern/powerpc/ieee1275/startup.S: ... this.
+       * conf/powerpc-ieee1275.rmk: Adjust for the above.
+       * DISTLIST: Likewise.
+
+       * kern/powerpc/ieee1275/crt0.S: Include grub/symbol.h and
+       grub/cpu/kernel.h.  Add start label for consistency with other
+       platforms.  Add grub_prefix immediately after start.  Add jump
+       to the code after grub_prefix.
+       * include/grub/powerpc/kernel.h: Provide valid values for
+       GRUB_KERNEL_CPU_PREFIX and GRUB_KERNEL_CPU_DATA_END.
+
+2008-08-29  Bean  <bean123ch@gmail.com>
+
+       * configure.ac: Change host_os to cygwin for mingw.
+       (asprintf): New check for function.
+
+       * include/grub/symbol.h: Replace #ifndef __CYGWIN__ with
+       #if ! defined (__CYGWIN__) && ! defined (__MINGW32__).
+
+       * include/grub/util/misc.h: #include <config.h> and <grub/types.h>,
+       declare asprintf if HAVE_ASPRINTF is not set, declare fseeko, ftello,
+       sync, sleep and grub_util_get_disk_size for mingw.
+
+       * util/biosdisk.c (grub_util_biosdisk_open): Use grub_util_get_disk_size
+       to get size in mingw.
+       (open_device): Use flag O_BINARY if it's defined.
+       (find_root_device): Add dummy code for mingw.
+
+       * util/grub-mkdevicemap.c (get_floppy_disk_name): Return 0 for mingw.
+       (get_ide_disk_name): Return //./PHYSICALDRIVE%d for mingw.
+       (get_scsi_disk_name): Return 0 for mingw.
+
+       * util/hostfs.c: #include <grub/util/misc.h>.
+       (grub_hostfs_open): Use "rb" flag to open file, use
+       grub_util_get_disk_size to get disk size for mingw.
+
+       * util/misc.c: #include <windows.h> and <winioctl.h> in mingw.
+       (asprintf): New function if HAVE_ASPRINTF is not set.
+       (sync): New function for mingw.
+       (sleep): Likewise.
+       (grub_util_get_disk_size): Likewise.
+
+2008-08-28  Pavel Roskin  <proski@gnu.org>
+
+       * conf/powerpc-ieee1275.rmk (kernel_elf_SOURCES): Add
+       kern/time.c.
+
+2008-08-28  Robert Millan  <rmh@aybabtu.com>
+
+       * util/biosdisk.c (find_grub_drive): Declare missing `i' variable.
+
+2008-08-28  Robert Millan  <rmh@aybabtu.com>
+
+       Change find_grub_drive() syntax so it doesn't prevent it from
+       detecting NULL names as errors.
+
+       * util/biosdisk.c (find_grub_drive): Move free slot search code
+       from here ...
+       (find_free_slot): ... to here.
+       (read_device_map): Use find_free_slot() to search for free slots.
+
+2008-08-27  Marco Gerards  <marco@gnu.org>
+
+       * conf/common.rmk (pkglib_MODULES): Add scsi.mod.
+       (scsi_mod_SOURCES): New variable.
+       (scsi_mod_CFLAGS): Likewise
+       (scsi_mod_LDFLAGS): Likewise.
+
+       * disk/scsi.c: New file.
+
+       * include/grub/scsi.h: Likewise.
+
+       * include/grub/scsicmd.h: Likewise.
+
+       * disk/ata.c: Include <grub/scsi.h>.
+       (grub_atapi_packet): Do not use grub_ata_cmd, use registers
+       instead.
+       (grub_ata_iterate): Skip ATAPI devices.
+       (grub_ata_open): Only handle ATAPI devices.
+       (struct grub_atapi_read): Removed.
+       (grub_atapi_readsector): Likewise.
+       (grub_ata_read): No longer handle ATAPI devices.
+       (grub_ata_write): Likewise.
+       (grub_atapi_iterate): New function.
+       (grub_atapi_read): Likewise.
+       (grub_atapi_write): Likewise.
+       (grub_atapi_open): Likewise.
+       (grub_atapi_close): Likewise.
+       (grub_atapi_dev): New variable.
+       (GRUB_MOD_INIT(ata)): Register ATAPI as SCSI device.
+       (GRUB_MOD_FINI(ata)): Unregister ATAPI.
+
+       * include/grub/disk.h (enum grub_disk_dev_id): Add
+       `GRUB_DISK_DEVICE_SCSI_ID'.
+
+2008-08-26  Robert Millan  <rmh@aybabtu.com>
+
+       * util/biosdisk.c (grub_util_biosdisk_open, open_device)
+       (grub_util_biosdisk_get_grub_dev): Make error messages a bit more
+       descriptive.
+
+2008-08-23  Bean  <bean123ch@gmail.com>
+
+       * conf/common.rmk (grub_probe_SOURCES): Add disk/mdraid_linux.c.
+       (grub_fstest_SOURCES): Add disk/raid5_recover.c, disk/raid6_recover.c,
+       disk/mdraid_linux.c and disk/dmraid_nvidia.c and lib/crc.c.
+       (pkglib_MODULES): Add raid5rec.mod, raid6rec.mod, mdraid.mod and
+       dm_nv.mod.
+       (raid5rec_mod_SOURCES): New macro.
+       (raid5rec_mod_CFLAGS): Likewise.
+       (raid5rec_mod_LDFLAGS): Likewise.
+       (raid6rec_mod_SOURCES): Likewise.
+       (raid6rec_mod_CFLAGS): Likewise.
+       (raid6rec_mod_LDFLAGS): Likewise.
+       (mdraid_mod_SOURCES): Likewise.
+       (mdraid_mod_CFLAGS): Likewise.
+       (mdraid_mod_LDFLAGS): Likewise.
+       (dm_nv_mod_SOURCES): Likewise.
+       (dm_nv_mod_CFLAGS): Likewise.
+       (dm_nv_mod_LDFLAGS): Likewise.
+
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Add disk/mdraid_linux.c.
+       (grub_emu_SOURCES):  Add disk/raid5_recover.c, disk/raid6_recover.c,
+       disk/mdraid_linux.c and disk/dmraid_nvidia.c.
+
+       * conf/i386-coreboot.rmk (grub_emu_SOURCES): Add disk/raid5_recover.c,
+       disk/raid6_recover.c, disk/mdraid_linux.c and disk/dmraid_nvidia.c.
+
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+
+       * disk/raid5_recover.c: New file.
+
+       * disk/raid6_recover.c: Likewise.
+
+       * disk/mdraid_linux.c: Likewise.
+
+       * disk/dmraid_nvidia.c: Likewise.
+
+       * disk/i386/pc/biosdisk.c: Set total_sectors of cdrom device to
+       ULONG_MAX.
+
+       * disk/raid.c (grub_raid_open): Use the size of the smallest disk to
+       calculate the size of raid device.
+       (grub_raid_read): Simplify raid0 code. Support raid4, raid6 and four
+       different layout of raid5.
+       (grub_raid_scan_device): Remove code specific to mdraid.
+       (grub_raid_list): New variable.
+       (free_array): New function.
+       (grub_raid_register): Likewise.
+       (grub_raid_unregister): Likewise.
+       (grub_raid_rescan): Likewise.
+       (GRUB_MOD_INIT): Don't iterate device here.
+       (GRUB_MOD_FINI): Use free_array to release resource.
+
+       * include/grub/raid.h: Remove macro and structure specific to mdraid.
+       (grub_raid5_recover_func_t): New function variable type.
+       (grub_raid6_recover_func_t): Likewise.
+       (grub_raid5_recover_func): New variable.
+       (grub_raid6_recover_func): Likewise.
+       (grub_raid_register): New function.
+       (grub_raid_unregister): Likewise.
+       (grub_raid_rescan): Likewise.
+       (grub_raid_block_xor): Likewise.
+
+       * util/grub-fstest.c: Add #include <grub/raid.h> and <grub/lib/crc.h>.
+       (CMD_CRC): New macro.
+       (part): Removed.
+       (read_file): Handle device as well as file.
+       (cmd_crc): New function.
+       (fstest): Handle multiple disks.
+       (options): Remove part, raw and long, add root and diskcount.
+       (usage): Add crc, remove -p, -r, -l, add -r and -c.
+       (main): Find the first non option entry and ignore subsequent options,
+       add handling for the new options, support multiple disks.
+
+       * util/grub-probe.c (probe): Add mdraid to abstraction_name.
+
+2008-08-23  Bean  <bean123ch@gmail.com>
+
+       * normal/x86_64/setjmp.S (grub_longjmp): Return 1 when val = 0.
+
+       * genfslist.sh: Ignore kernel.mod.
+
+       * genpartmaplist.sh: Likewise.
+
+2008-08-23  Robert Millan  <rmh@aybabtu.com>
+
+       * util/getroot.c (find_root_device): Skip anything that starts with
+       a dot, not just directories.  This avoids things like /dev/.tmp.md0.
+
+2008-08-22  Felix Zielcke  <fzielcke@z-51.de>
+
+       * util/update-grub.in (GRUB_GFXMODE): Export variable.
+       * util/grub.d/00_header.in: Allow the administrator to change default
+       gfxmode via ${GRUB_GFXMODE}.
+
+2008-08-21  Felix Zielcke  <fzielcke@z-51.de>
+
+       * fs/ntfs.c (grub_ntfs_mount): Fix a memory leak.
+
+2008-08-21  Robert Millan  <rmh@aybabtu.com>
+
+       * loader/i386/linux.c: New file.  Implements generic 32-bit Linux
+       loader.
+       * conf/i386-coreboot.rmk (_linux_mod_SOURCES): Replace
+       `loader/i386/pc/linux.c' with `loader/i386/linux.c'.
+
+2008-08-20  Carles Pina i Estany  <carles@pina.cat>
+
+       * menu/normal.c (run_menu): Replace hardcoded numbers with macros
+       (16 for GRUB_TERM_UP and 14 for GRUB_TERM_DOWN)
+
+2008-08-19  Robert Millan  <rmh@aybabtu.com>
+
+       * term/gfxterm.c (DEFAULT_CURSOR_COLOR): Remove.
+       (struct grub_virtual_screen): Remove `cursor_color'.
+       (grub_virtual_screen_setup): Remove `virtual_screen.cursor_color'
+       initialization.
+       (write_cursor): Use `virtual_screen.fg_color' to draw cursor.
+
+2008-08-18  Robert Millan  <rmh@aybabtu.com>
+
+       Unify (identical) linux_normal.c files.
+       * loader/i386/efi/linux_normal.c: Move from here ...
+       * loader/linux_normal.c: ... to here.  Update all users.
+       * loader/i386/pc/linux_normal.c: Delete.  Update all users.
+       * loader/i386/ieee1275/linux_normal.c: Likewise.
+
+2008-08-18  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/i386/linux.h (LINUX_LOADER_ID_LILO)
+       (LINUX_LOADER_ID_LOADLIN, LINUX_LOADER_ID_BOOTSECT)
+       (LINUX_LOADER_ID_SYSLINUX, LINUX_LOADER_ID_ETHERBOOT)
+       (LINUX_LOADER_ID_ELILO, LINUX_LOADER_ID_GRUB, LINUX_LOADER_ID_UBOOT)
+       (LINUX_LOADER_ID_XEN, LINUX_LOADER_ID_GUJIN, LINUX_LOADER_ID_QEMU):
+       New macros.
+       (GRUB_LINUX_CL_OFFSET, GRUB_LINUX_CL_END_OFFSET): Move from here ...
+       * loader/i386/pc/linux.c (GRUB_LINUX_CL_OFFSET)
+       (GRUB_LINUX_CL_END_OFFSET): ... to here.
+       * loader/i386/efi/linux.c (GRUB_EFI_CL_OFFSET): Rename to ...
+       (GRUB_LINUX_CL_OFFSET): ... this.  Update all users.
+       (GRUB_EFI_CL_END_OFFSET): Rename to ...
+       (GRUB_LINUX_CL_END_OFFSET): ... this.  Update all users.
+       (grub_rescue_cmd_linux): Macroify `type_of_loader' initialization.
+       Initialize `params->video_cursor_x' and `params->video_cursor_y'
+       portably using grub_getxy().
+       Replace `-EFI' with `-bzImage' in boot message.
+
+2008-08-17  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/x86_64/kernel.h: New file (<grub/i386/kernel.h> stub).
+
+2008-08-17  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/i386/pc/mmap.c'.
+
+       * include/grub/i386/pc/init.h (GRUB_MACHINE_MEMORY_AVAILABLE)
+       (GRUB_MACHINE_MEMORY_RESERVED): New macros.
+       (grub_machine_mmap_iterate): New function declaration.
+       * include/grub/multiboot.h (struct grub_multiboot_mmap_entry): New
+       structure.
+       (GRUB_MMAP_MEMORY_AVAILABLE, GRUB_MMAP_MEMORY_RESERVED): New
+       macros.
+
+       * kern/i386/pc/init.c (grub_machine_init): Replace hardcoded region
+       type check value with `GRUB_MACHINE_MEMORY_AVAILABLE'.
+       Move e820 parsing from here ...
+       * kern/i386/pc/mmap.c: New file.
+       (grub_machine_mmap_iterate): ... to here.
+
+       * include/grub/i386/coreboot/memory.h: Remove `<grub/err.h>'.
+       (GRUB_LINUXBIOS_MEMORY_AVAILABLE): Rename (for consistency) to ...
+       (GRUB_MACHINE_MEMORY_AVAILABLE): ... this.  Update all users.
+       (grub_available_iterate): Redeclare to return `void', and redeclare
+       its hook to use grub_uint64_t as addr and size parameters, and rename
+       to ...
+       (grub_machine_mmap_iterate): ... this.  Update all users.
+
+       * kern/i386/coreboot/mmap.c (grub_mmap_iterate): Simplify parser loop
+       to make it more readable.  Rename to ...
+       (grub_machine_mmap_iterate): ... this.
+
+       * loader/i386/pc/multiboot.c (mmap_addr, mmap_length): New variables.
+       (grub_get_multiboot_mmap_len, grub_fill_multiboot_mmap): New functions.
+       (grub_multiboot): Allocate an extra region after the payload, and fill
+       it with a Multiboot memory map.  Adjust a.out loader to calculate size
+       with the extra space.
+       (grub_multiboot_load_elf32): Adjust elf32 loader to calculate size
+       with the extra space.
+
+2008-08-17  Carles Pina i Estany  <carles@pina.cat>
+
+       * menu/normal.c (run_menu): Add Home and End keys in grub-menu.
+
+2008-08-17  Felix Zielcke  <fzielcke@z-51.de>
+
+       * gendistlist.sh: Add *.y, *.tex, *.texi, grub.cfg, README, *.sc,
+       mdate-sh to the list `find' searches for.
+       * DISTLIST: Regenerated.
+
+2008-08-16  Felix Zielcke  <fzielcke@z-51.de>
+
+       * gendistlist.sh (EXTRA_DISTFILES): Remove gensymlist.sh,
+       genkernsyms.sh.  Add geninit.sh, geninitheader.sh, genkernsyms.sh.in,
+       genmoddep.awk, gensymlist.sh.in.
+       (DISTDIRS): Add bus, docs, hook, lib.
+       * DISTLIST: Regenerated.
+       * NEWS: Add cygwin support and change the `os-prober' entry a bit.
+
+2008-08-16  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/raid.c (grub_raid_init): Handle/report errors set by
+       grub_device_iterate().
+       * disk/lvm.c (grub_lvm_init): Likewise.
+
+2008-08-15  Bean  <bean123ch@gmail.com>
+
+       * conf/i386-pc.rmk (pkglib_MODULES): Add datetime.mod, date.mod
+       and datehook.mod.
+       (datetime_mod_SOURCES): New macro.
+       (datetime_mod_CFLAGS): Likewise.
+       (datetime_mod_LDFLAGS): Likewise.
+       (date_mod_SOURCES): Likewise.
+       (date_mod_CFLAGS): Likewise.
+       (date_mod_LDFLAGS): Likewise.
+       (datehook_mod_SOURCES): Likewise.
+       (datehook_mod_CFLAGS): Likewise.
+       (datehook_mod_LDFLAGS): Likewise.
+
+       * conf/i386-coreboot.rmk (pkglib_MODULES): Add datetime.mod, date.mod
+       and datehook.mod.
+       (datetime_mod_SOURCES): New macro.
+       (datetime_mod_CFLAGS): Likewise.
+       (datetime_mod_LDFLAGS): Likewise.
+       (date_mod_SOURCES): Likewise.
+       (date_mod_CFLAGS): Likewise.
+       (date_mod_LDFLAGS): Likewise.
+       (datehook_mod_SOURCES): Likewise.
+       (datehook_mod_CFLAGS): Likewise.
+       (datehook_mod_LDFLAGS): Likewise.
+
+       * conf/i386-ieee1275.rmk (pkglib_MODULES): Add datetime.mod, date.mod
+       and datehook.mod.
+       (datetime_mod_SOURCES): New macro.
+       (datetime_mod_CFLAGS): Likewise.
+       (datetime_mod_LDFLAGS): Likewise.
+       (date_mod_SOURCES): Likewise.
+       (date_mod_CFLAGS): Likewise.
+       (date_mod_LDFLAGS): Likewise.
+       (datehook_mod_SOURCES): Likewise.
+       (datehook_mod_CFLAGS): Likewise.
+       (datehook_mod_LDFLAGS): Likewise.
+
+       * conf/i386-efi.rmk (pkglib_MODULES): Add datetime.mod, date.mod
+       and datehook.mod.
+       (datetime_mod_SOURCES): New macro.
+       (datetime_mod_CFLAGS): Likewise.
+       (datetime_mod_LDFLAGS): Likewise.
+       (date_mod_SOURCES): Likewise.
+       (date_mod_CFLAGS): Likewise.
+       (date_mod_LDFLAGS): Likewise.
+       (datehook_mod_SOURCES): Likewise.
+       (datehook_mod_CFLAGS): Likewise.
+       (datehook_mod_LDFLAGS): Likewise.
+
+       * conf/x86_64-efi.rmk (pkglib_MODULES): Add datetime.mod, date.mod
+       and datehook.mod.
+       (datetime_mod_SOURCES): New macro.
+       (datetime_mod_CFLAGS): Likewise.
+       (datetime_mod_LDFLAGS): Likewise.
+       (date_mod_SOURCES): Likewise.
+       (date_mod_CFLAGS): Likewise.
+       (date_mod_LDFLAGS): Likewise.
+       (datehook_mod_SOURCES): Likewise.
+       (datehook_mod_CFLAGS): Likewise.
+       (datehook_mod_LDFLAGS): Likewise.
+
+       * kern/env.c (grub_env_insert): Fix a bug in prevp pointer.
+
+       * commands/date.c: New file.
+
+       * hook/datehook.c: Likewise.
+
+       * include/grub/lib/datetime.h: Likewise.
+
+       * include/grub/i386/cmos.h: Likewise.
+
+       * lib/datetime.c: Likewise.
+
+       * lib/i386/datetime.c: Likewise.
+
+       * lib/efi/datetime.c: Likewise.
+
+2008-08-14  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/common.rmk (bin_UTILITIES): Add `grub-mkelfimage'.
+       (grub_mkelfimage_SOURCES): New variable.
+       (util/elf/grub-mkimage.c_DEPENDENCIES): Likewise.
+
+       * conf/i386-coreboot.rmk (bin_UTILITIES, grub_mkimage_SOURCES)
+       (grub_mkimage_LDFLAGS, util/elf/grub-mkimage.c_DEPENDENCIES): Remove.
+       * conf/powerpc-ieee1275.rmk: Likewise.
+       * conf/i386-ieee1275.rmk: Likewise.
+
+       * kern/ieee1275/init.c: Include `<grub/cpu/kernel.h>'.
+       * kern/i386/coreboot/init.c: Likewise.
+
+       * kern/i386/ieee1275/startup.S: Replace `<grub/machine/kernel.h>'
+       with `<grub/cpu/kernel.h>'.
+       (GRUB_KERNEL_MACHINE_PREFIX, GRUB_KERNEL_MACHINE_DATA_END): Renamed
+       to ...
+       (GRUB_KERNEL_CPU_PREFIX, GRUB_KERNEL_CPU_DATA_END): ... this.
+       * kern/i386/coreboot/startup.S: Likewise.
+
+       * include/grub/powerpc/ieee1275/kernel.h (GRUB_MOD_ALIGN)
+       (GRUB_MOD_GAP): Remove.
+       * include/grub/powerpc/kernel.h: New file.
+       * include/grub/i386/ieee1275/kernel.h (GRUB_KERNEL_MACHINE_PREFIX)
+       (GRUB_KERNEL_MACHINE_DATA_END): Remove.
+       * include/grub/i386/kernel.h: New file.
+       * include/grub/i386/coreboot/kernel.h (GRUB_MOD_ALIGN)
+       (GRUB_MOD_GAP, GRUB_KERNEL_MACHINE_PREFIX)
+       (GRUB_KERNEL_MACHINE_DATA_END): Remove.
+
+       * util/ieee1275/grub-install.in (grub_mkimage): Initialize to use
+       `grub-mkelfimage'.
+       Use --directory when invoking grub_mkimage.
+
+       * util/elf/grub-mkimage.c: Include `<grub/cpu/kernel.h>'.
+       (add_segments): Replace GRUB_KERNEL_MACHINE_DATA_END and
+       GRUB_KERNEL_MACHINE_PREFIX with GRUB_KERNEL_CPU_DATA_END
+       and GRUB_KERNEL_CPU_PREFIX.
+
+2008-08-14  Felix Zielcke  <fzielcke@z-51.de>
+
+       * include/grub/err.h (grub_err_printf): New function prototype.
+       * util/misc.c (grub_err_printf): New function.
+       * kern/misc.c [! GRUB_UTIL] (grub_err_printf): New alias for
+       grub_printf.
+       * kern/err.c (grub_print_error): Use grub_err_printf.
+
+2008-08-13  Robert Millan  <rmh@aybabtu.com>
+
+       * docs/grub.cfg: Remove `/dev/' prefix in GNU/Hurd boot entry.
+
+2008-08-13  Robert Millan  <rmh@aybabtu.com>
+
+       * docs/grub.cfg: Use the native device name for the example GNU/Hurd
+       boot entry.
+
+2008-08-12  Robert Millan  <rmh@aybabtu.com>
+
+       * loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): Move part
+       of the relocation code from here ...
+       (grub_multiboot): ... to here.
+       (forward_relocator, backward_relocator): Move from here ...
+       * kern/i386/loader.S (grub_multiboot_forward_relocator)
+       (grub_multiboot_backward_relocator): ... to here.
+       (grub_multiboot_real_boot): Use %edx for entry offset.  Put Multiboot
+       magic in %eax.  Use %ebp for jumping (so %edx is not trashed).
+       * include/grub/i386/loader.h (grub_multiboot_forward_relocator)
+       (grub_multiboot_forward_relocator_end)
+       (grub_multiboot_backward_relocator)
+       (grub_multiboot_backward_relocator_end): New variables.
+
+2008-08-12  Bean  <bean123ch@gmail.com>
+
+       * disk/raid.c (grub_raid_read): Fix a bug in raid0 code.
+
+2008-08-11  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/i386/linuxbios/startup.S: Move from here ...
+       * kern/i386/coreboot/startup.S: ... to here.
+
+       * kern/i386/linuxbios/init.c: Move from here ...
+       * kern/i386/coreboot/init.c: ... to here.
+
+       * kern/i386/linuxbios/table.c: Move from here ...
+       * kern/i386/coreboot/mmap.c: ... to here.
+
+       * conf/i386-coreboot.rmk (kernel_elf_SOURCES): Update moved files.
+
+2008-08-11  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/device.c (grub_device_open): Do not handle grub_disk_open()
+       errors.  Leave it to the upper layer to handle them.
+
+2008-08-09  Christian Franke  <franke@computer.org>
+
+       * Makefile.in: Add `target_os' and `enable_grub_pe2elf'.
+       * conf/common.rmk: Install `grub-pe2elf' only if requested.
+       Install `grub.d/10_windows' only on Cygwin.
+       * configure.ac: Add subst of `target_os'.
+       Check `target_os' also before setting TARGET_OBJ2ELF.
+       Add `--enable-grub-pe2elf'.
+
+2008-08-08  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/disk.c: Replace `<grub/machine/time.h>' with `<grub/time.h>'.
+       (grub_last_time): Change type to grub_uint64_t.
+       (grub_disk_open): Migrate code from to using grub_get_time_ms().
+       (grub_disk_close): Likewise.
+
+       * normal/menu.c: Replace `<grub/machine/time.h>' with `<grub/time.h>'.
+       (run_menu): Migrate code from to using grub_get_time_ms().
+
+       * util/misc.c (grub_get_time_ms): New function.
+
+2008-08-08  Marco Gerards  <marco@gnu.org>
+
+       * disk/ata.c (grub_ata_regget): Change return type to
+       `grub_uint8_t'.
+       (grub_ata_regget2): Likewise.
+       (grub_ata_wait_status): New function.
+       (grub_ata_wait_busy): Removed function, updated all users to use
+       `grub_ata_wait_status'.
+       (grub_ata_wait_drq): Likewise.
+       (grub_ata_cmd): New function.
+       (grub_ata_pio_read): Change return type to `grub_uint8_t'.  Add
+       error handling.
+       (grub_ata_pio_write): Add error handling.
+       (grub_atapi_identify): Likewise.
+       (grub_atapi_packet): Use `grub_ata_cmd' and improve error
+       handling.
+       (grub_ata_identify): Use `grub_ata_cmd' and improve error
+       handling.  Actually use the detected registers.  Reorder the
+       detection logic such that it is easier to read.
+       (grub_ata_pciinit): Do not assign the same ID to each controller.
+       (grub_ata_setaddress): Use `grub_ata_cmd' and improve error
+       handling.
+       (grub_atapi_readsector): Check the result of `grub_ata_pio_read'.
+
+       * include/grub/err.h (grub_err_t): Add `GRUB_ERR_TIMEOUT'.
+
+2008-08-08  Marco Gerards  <marco@gnu.org>
+
+       * NEWS: Update.
+
+2008-08-07  Bean  <bean123ch@gmail.com>
+
+       * include/grub/x86_64/pci.h: New file.
+
+2008-08-07  Christian Franke  <franke@computer.org>
+
+       * kern/i386/pit.c (TIMER2_SPEAKER): New define.
+       (TIMER2_GATE): Likewise.
+       (grub_pit_wait): Add enable/disable of the timer2 gate
+       bit of port 0x61.  This fixes a possible infinite loop.
+
+2008-08-07  Bean  <bean123ch@gmail.com>
+
+       * conf/x86_64-efi.rmk (kernel_mod_SOURCES): Add kern/time.c,
+       kern/i386/tsc.c and kern/i386/pit.c.
+
+       * include/grub/i386/tsc.h (grub_cpu_is_cpuid_supported): Handle
+       x86_64 platform.
+
+       * kern/i386/efi/init.c: Replace <grub/cpu/tsc.h> with
+       <grub/i386/tsc.h>.
+
+       * kern/i386/pit.c: Replace <grub/cpu/io.h> with <grub/i386/io.h>.
+
+2008-08-07  Bean  <bean123ch@gmail.com>
+
+       * conf/i386-efi.rmk (kernel_mod_SOURCES): Add kern/time.c.
+
+       * conf/i386-ieee1275.rmk (kernel_elf_SOURCES): Add kern/time.c,
+
+       * include/grub/i386/pit.h: Use macro KERNEL_CPU_PIT_HEADER to avoid
+       multiple inclusion. Add #include <grub/types.h>.
+
+2008-08-06  Christian Franke  <franke@computer.org>
+
+       * conf/common.rmk: Build and install `10_windows'.
+       * util/grub.d/10_windows.in: New script.
+
+2008-08-06  Pavel Roskin  <proski@gnu.org>
+
+       * kern/i386/pit.c: Include `<grub/i386/pit.h>'.
+
+2008-08-06  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-coreboot.rmk (kernel_elf_ASFLAGS): New variable.
+       * kern/i386/tsc.c: Include `<grub/i386/pit.h>'.
+
+2008-08-06  Bean  <bean123ch@gmail.com>
+
+       * fs/i386/pc/pxe.c (grub_pxe_data): New member block_size.
+       (grub_pxefs_fs_int): Remove dummy definition.
+       (grub_pxefs_open): Use data->block_size to store the current block
+       size setting.
+       (grub_pxefs_read): Use block size stored in data->block_size. As the
+       value of grub_pxe_blksize can be changed after the file is opened.
+
+2008-08-06  Bean  <bean123ch@gmail.com>
+
+       * fs/i386/pc/pxe.c (curr_file): new variable.
+       (grub_pxefs_open): Simply the handling of pxe file system. Don't
+       require the dummy internal file system anymore.
+       (grub_pxefs_read): Removed.
+       (grub_pxefs_close): Likewise.
+       (grub_pxefs_fs_int): Likewise.
+       (grub_pxefs_read_int): Renamed to grub_pxefs_read. Reinitialize tftp
+       connection when we switch file.
+       (grub_pxefs_close_int): Renamed to grub_pxefs_close.
+
+2008-08-06  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-coreboot.rmk (pkglib_MODULES): Add `reboot.mod' and
+       `halt.mod'.
+       (reboot_mod_SOURCES, reboot_mod_CFLAGS, reboot_mod_LDFLAGS)
+       (halt_mod_SOURCES, halt_mod_CFLAGS, halt_mod_LDFLAGS): New variables.
+
+       * kern/i386/halt.c: New file.
+       * kern/i386/reboot.c: Likewise.
+       * include/grub/i386/reboot.h: Likewise.
+       * include/grub/i386/halt.h: Likewise.
+
+       * commands/halt.c [! GRUB_MACHINE_IEEE1275 ! GRUB_MACHINE_EFI]:
+       Include `<grub/cpu/halt.h>'.
+       * commands/reboot.c [! GRUB_MACHINE_IEEE1275 ! GRUB_MACHINE_EFI]
+       [! GRUB_MACHINE_PCBIOS]: Include `<grub/cpu/reboot.h>'.
+
+       * term/i386/pc/at_keyboard.c: Include `<grub/cpu/at_keyboard.h>'.
+       (SHIFT_L, SHIFT_R, CTRL, ALT, CAPS_LOCK, KEYBOARD_REG_DATA)
+       (KEYBOARD_REG_STATUS, KEYBOARD_COMMAND_ISREADY, KEYBOARD_COMMAND_READ)
+       (KEYBOARD_COMMAND_WRITE, KEYBOARD_COMMAND_REBOOT)
+       (KEYBOARD_SCANCODE_SET1, KEYBOARD_ISMAKE, KEYBOARD_ISREADY)
+       (KEYBOARD_SCANCODE, OLPC_UP, OLPC_DOWN, OLPC_LEFT, OLPC_RIGHT): Move
+       from here ...
+       * include/grub/i386/at_keyboard.h: ... to here.
+
+2008-08-05  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/i386/pit.c'.
+       * conf/i386-efi.rmk (kernel_mod_SOURCES): Likewise.
+       * conf/i386-coreboot.rmk (kernel_elf_SOURCES): Likewise. Also add
+       `kern/i386/tsc.c', `kern/generic/rtc_get_time_ms.c' and
+       `kern/generic/millisleep.c'.
+
+       * kern/i386/tsc.c (calibrate_tsc): Rewrite using grub_pit_wait()
+       instead of grub_get_rtc().
+       (grub_tsc_init): Initialize `tsc_boot_time'.
+
+       * kern/i386/linuxbios/init.c (grub_millisleep): Remove stub.
+       (grub_machine_init): Use grub_tsc_init() rather than
+       installing an RTC-based handler via grub_install_get_time_ms().
+
+       * kern/i386/pit.c: New file.
+       * include/grub/i386/pit.h: Likewise.
+
+2008-08-05  Bean  <bean123ch@gmail.com>
+
+       * boot/i386/pc/pxeboot.S (_start): Use drive number 0x7F for pxe.
+
+       * conf/i386-pc.rmk (kernel_img_HEADERS): Add machine/pxe.h.
+       (pkglib_MODULES): Add pxe.mod and pxecmd.mod.
+       (pxe_mod_SOURCES): New macro.
+       (pxe_mod_CFLAGS): Likewise.
+       (pxe_mod_LDFLAGS): Likewise.
+       (pxecmd_mod_SOURCES): Likewise.
+       (pxecmd_mod_CFLAGS): Likewise.
+       (pxecmd_mod_LDFLAGS): Likewise.
+
+       * kern/i386/pc/startup.S (grub_pxe_scan): New function.
+       (grub_pxe_call): Likewise.
+
+       * include/grub/disk.h (grub_disk_dev_id): Add GRUB_DISK_DEVICE_PXE_ID.
+
+       * commands/i386/pc/pxecmd.c: New file.
+
+       * fs/i386/pc/pxe.c: Likewise.
+
+       * include/grub/i386/pc/pxe.h: Likewise.
+
+2008-08-05  Bean  <bean123ch@gmail.com>
+
+       * util/console.c (grub_console_cur_color): New variable.
+       (grub_console_standard_color): Likewise.
+       (grub_console_normal_color): Likewise.
+       (grub_console_highlight_color): Likewise.
+       (color_map): Likewise.
+       (use_color): Likewise.
+       (NUM_COLORS): New macro.
+       (grub_ncurses_setcolorstate): Handle color properly.
+       (grub_ncurses_setcolor): Don't change color here, just remember the
+       settings, color will be set in grub_ncurses_setcolorstate.
+       (grub_ncurses_getcolor): New function.
+       (grub_ncurses_init): Initialize color pairs.
+       (grub_ncurses_term): New member grub_ncurses_getcolor.
+
+2008-08-05  Colin D Bennett  <colin@gibibit.com>
+
+       High resolution timer support.  Implemented for x86 CPUs using TSC.
+       Extracted generic grub_millisleep() so it's linked in only as needed.
+       This requires a Pentium compatible CPU; if the RDTSC instruction is
+       not supported, then it falls back on the generic grub_get_time_ms()
+       implementation that uses the machine's RTC.
+
+       * conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/time.c',
+       `kern/i386/tsc.c', `kern/generic/rtc_get_time_ms.c' and
+       `kern/generic/millisleep.c'.
+
+       * conf/i386-efi.rmk (kernel_mod_SOURCES): Add `kern/i386/tsc.c',
+       `kern/generic/rtc_get_time_ms.c' and `kern/generic/millisleep.c'.
+
+       * conf/x86_64-efi.rml (kernel_mod_SOURCES): Add
+       `kern/generic/millisleep.c' and `kern/generic/rtc_get_time_ms.c'.
+
+       * conf/sparc64-ieee1275.rmk (kernel_elf_SOURCES): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (kernel_elf_SOURCES): Add
+       `kern/generic/millisleep.c'.
+
+       * conf/i386-ieee1275.rmk (kernel_elf_SOURCES): Likewise.
+
+       * conf/i386-coreboot.rmk (kernel_elf_SOURCES): Add `kern/time.c'.
+
+       * kern/generic/rtc_get_time_ms.c: New file.
+
+       * kern/generic/millisleep.c: New file.
+
+       * kern/misc.c: Don't include
+       <kern/time.h> anymore.
+       (grub_millisleep_generic): Removed.
+
+       * commands/sleep.c (grub_interruptible_millisleep): Uses
+       grub_get_time_ms() instead of grub_get_rtc().
+
+       * include/grub/i386/tsc.h (grub_get_tsc): New file.  New inline
+       function.
+       (grub_cpu_is_cpuid_supported): New inline function.
+       (grub_cpu_is_tsc_supported): New inline function.
+       (grub_tsc_init): New function prototype.
+       (grub_tsc_get_time_ms): New function prototype.
+
+       * kern/i386/tsc.c (grub_get_time_ms): New file.
+
+       * include/grub/time.h: Include <grub/types.h.
+       (grub_millisleep_generic): Removed.
+       (grub_get_time_ms): New prototype.
+       (grub_install_get_time_ms): New prototype.
+       (grub_rtc_get_time_ms): New prototype.
+
+       * kern/time.c (grub_get_time_ms): New function.
+       (grub_install_get_time_ms): New function.
+
+       * kern/i386/efi/init.c: Include <grub/cpu/tsc.h>.  Don't include
+       <grub/time.h> anymore.
+       (grub_millisleep): Removed.
+       (grub_machine_init): Call grub_tsc_init.
+
+       * kern/i386/linuxbios/init.c (grub_machine_init): Install the RTC
+       get_time_ms() implementation.
+
+       * kern/sparc64/ieee1275/init.c (grub_millisleep): Removed.
+       (ieee1275_get_time_ms): New function.
+       (grub_machine_init): Install get_time_ms() implementation.
+
+       * kern/i386/pc/init.c: Include <grub/cpu/tsc.h>.
+       (grub_machine_init): Call grub_tsc_init().
+       (grub_millisleep): Removed.
+
+       * kern/ieee1275/init.c (grub_millisleep): Removed.
+       (grub_machine_init): Install ieee1275_get_time_ms()
+       implementation.
+       (ieee1275_get_time_ms): New function.
+       (grub_get_rtc): Now calls ieee1275_get_time_ms(), which does the
+       real work.
+
+2008-08-05  Marco Gerards  <marco@gnu.org>
+
+       * disk/ata.c: Include <grub/pci.h>.
+       (enum grub_ata_commands): Add `GRUB_ATA_CMD_EXEC_DEV_DIAGNOSTICS'.
+       (grub_ata_initialize): Rewritten.
+       (grub_ata_device_initialize): New function.
+
+2008-08-04  Pavel Roskin  <proski@gnu.org>
+
+       * kern/main.c: Include grub/mm.h.
+
+2008-08-04  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-coreboot.rmk (COMMON_ASFLAGS, COMMON_CFLAGS)
+       (COMMON_LDFLAGS): Harmonize with i386-pc version (fixes a code
+       corruption problem).
+
+2008-08-04  Robert Millan  <rmh@aybabtu.com>
+
+       * loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): Fix misc
+       warnings introduced in my last commit.
+
+2008-08-03  Robert Millan  <rmh@aybabtu.com>
+
+       Make PCI available on all i386 architectures.
+
+       * include/grub/i386/pc/pci.h: Move from here ...
+       * include/grub/i386/pci.h: ... to here.
+
+       * include/grub/i386/pc/pci.h: Remove.
+       * include/grub/i386/efi/pci.h: Remove.
+       * include/grub/x86_64/efi/pci.h: Remove.
+
+       * include/grub/pci.h: Replace `<grub/machine/pci.h>' with
+       `<grub/cpu/pci.h>'.
+
+       * conf/i386-coreboot.rmk (pkglib_MODULES): Add `pci' and `lspci'.
+       (pci_mod_SOURCES, pci_mod_CFLAGS, pci_mod_LDFLAGS, lspci_mod_SOURCES)
+       (lspci_mod_CFLAGS, lspci_mod_LDFLAGS): New variables.
+
+       * conf/i386-ieee1275.rmk: Likewise.
+
+2008-08-03  Robert Millan  <rmh@aybabtu.com>
+
+       * term/i386/pc/vga_text.c (CRTC_CURSOR_DISABLE): New macro.
+       (grub_console_setcursor): Make it possible to set cursor off.
+
+2008-08-03  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/00_header.in: Be platform-agnostic.  Probe for existence
+       of modules instead of assuming which platform provides what.
+       * util/update-grub.in: Likewise.
+
+2008-08-03  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/i386/pc/init.c (make_install_device): Check for `grub_prefix'
+       instead of `grub_install_dos_part' to determine whether a drive needs
+       to be prepended to prefix (`grub_install_dos_part' is not reliable,
+       because it can be overridden when loading GRUB via Multiboot).
+
+2008-08-02  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-install.in: Remove trailing slash from prefix.
+
+2008-08-02  Robert Millan  <rmh@aybabtu.com>
+
+       * loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): Add a pair
+       of informational grub_dprintf() calls.
+
+2008-08-02  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/memdisk.c (memdisk_size): Don't initialize.
+       (GRUB_MOD_INIT(memdisk)): Find memdisk using grub_module_iterate().
+
+       * include/grub/i386/pc/kernel.h
+       (GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE): Remove macro.
+       (GRUB_KERNEL_MACHINE_PREFIX, GRUB_KERNEL_MACHINE_DATA_END): Shift.
+       (grub_memdisk_image_size, grub_arch_memdisk_addr)
+       (grub_arch_memdisk_size): Remove.
+
+       * include/grub/kernel.h (struct grub_module_header): Remove `offset'
+       field (was only used to transfer a constant).  Add `type' field to
+       support multiple module types.
+       (grub_module_iterate): New function.
+
+       * kern/device.c (grub_device_open): Do not hide error messages
+       when grub_disk_open() fails.  Use grub_print_error() instead.
+
+       * kern/i386/pc/init.c (grub_arch_modules_addr)
+       (grub_arch_memdisk_size): Remove functions.
+       (grub_arch_modules_addr): Return the module address in high memory
+       (now that it isn't copied anymore).
+
+       * kern/i386/pc/startup.S (grub_memdisk_image_size): Remove variable.
+       (codestart): Don't add grub_memdisk_image_size to %ecx in LZMA
+       decompression routine (grub_total_module_size already includes that
+       now).  Don't copy modules back to low memory.
+
+       * kern/main.c: Include `<grub/mm.h>'.
+       (grub_load_modules): Split out (and use) ...
+       (grub_module_iterate): ... this function, which iterates through
+       module objects and runs a hook.
+       Comment out grub_mm_init_region() call, as it would cause non-ELF
+       modules to be overwritten.
+
+       * util/i386/pc/grub-mkimage.c (generate_image): Instead of appending
+       the memdisk image in its own region, make it part of the module list.
+       * util/elf/grub-mkimage.c (options): Add "memdisk"|'m' option.
+       (main): Parse --memdisk|-m option, and pass user-provided path as
+       parameter to generate_image().
+       (add_segments): Pass `memdisk_path' down to load_modules().
+       (load_modules): Embed memdisk image in module section when requested.
+       * util/i386/efi/grub-mkimage.c (make_mods_section): Initialize
+       `header.type' instead of `header.offset'.
+
+       * conf/powerpc-ieee1275.rmk (pkglib_MODULES): Add `memdisk.mod'.
+       (memdisk_mod_SOURCES, memdisk_mod_CFLAGS)
+       (memdisk_mod_LDFLAGS): New variables.
+       * conf/i386-coreboot.rmk: Likewise.
+       * conf/i386-ieee1275.rmk: Likewise.
+
+2008-08-02  Robert Millan  <rmh@aybabtu.com>
+
+       * loader/i386/pc/multiboot.c (playground, forward_relocator)
+       (backward_relocator): New variables.  Used to allocate and relocate
+       the payload, respectively.
+       (grub_multiboot_load_elf32): Load into heap instead of requested
+       address, install the appropriate relocator code in each bound of
+       the payload, and set the entry point such that
+       grub_multiboot_real_boot() will jump to one of them.
+
+       * kern/i386/loader.S (grub_multiboot_payload_size)
+       (grub_multiboot_payload_orig, grub_multiboot_payload_dest)
+       (grub_multiboot_payload_entry_offset): New variables.
+       (grub_multiboot_real_boot): Set cpu context to what the relocator
+       expects, and jump to the relocator instead of the payload.
+
+       * include/grub/i386/loader.h (grub_multiboot_payload_size)
+       (grub_multiboot_payload_orig, grub_multiboot_payload_dest)
+       (grub_multiboot_payload_entry_offset): Export.
+
+2008-08-01  Bean  <bean123ch@gmail.com>
+
+       * normal/menu_entry.c (editor_getline): Don't return the original
+       string as result, as it will be released by lexer once it has done
+       using it.
+
+2008-08-01  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/10_linux.in: Use prepare_grub_to_access_device() from
+       within menuentries, not before them.
+       util/grub.d/10_hurd.in: Likewise.
+
+2008-08-01  Bean  <bean123ch@gmail.com>
+
+       * conf/common.rmk (pkglib_MODULES): Add bufio.mod.
+       (bufio_mod_SOURCES): New macro.
+       (bufio_mod_CFLAGS): Likewise.
+       (bufio_mod_LDFLAGS): Likewise.
+
+       * include/grub/bufio.h: New file.
+
+       * io/bufio.c: Likewise.
+
+       * video/png.c: Replace <grub/file.h> with <grub/bufio.h>.
+       (grub_video_reader_png): Use grub_buffile_open to open file.
+
+       * video/jpeg.c: Replace <grub/file.h> with <grub/bufio.h>.
+       (grub_video_reader_jpeg): Use grub_buffile_open to open file.
+
+       * video/tga.c: Replace <grub/file.h> with <grub/bufio.h>.
+       (grub_video_reader_tga): Use grub_buffile_open to open file.
+
+       * font/manager.c: Include <grub/bufio.h>.
+       (add_font): Use grub_buffile_open to open file.
+
+2008-07-31  Robert Millan  <rmh@aybabtu.com>
+
+       * loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): When loading
+       ELF segments, use a macro for arbitrarily accessing any of them instead
+       of preparing a pointer that allows access to one at a time.
+       (grub_multiboot_load_elf64): Likewise.
+
+2008-07-31  Bean  <bean123ch@gmail.com>
+
+       * boot/i386/pc/lnxboot.S (real_code_2): Replace 0x50 with
+       GRUB_KERNEL_MACHINE_DATA_END.
+
+2008-07-30  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/i386/pc/kernel.h (GRUB_KERNEL_MACHINE_DATA_END):
+       Increase from 0x50 to 0x60.
+       * util/i386/pc/grub-install.in: Detect cross-disk installs, and
+       use UUIDs to identify the root drive for them.  If that's not
+       possible, abort.
+       * util/i386/pc/grub-setup.c (setup): Do not special-case, or even
+       check, for cross-disk installs.
+
+2008-07-30  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/ieee1275/init.c (grub_machine_set_prefix): If `grub_prefix'
+       is non-empty, use it to set the `prefix' environment variable instead
+       of the usual approach.
+       * kern/i386/linuxbios/init.c (make_install_device): Remove function.
+       (grub_machine_set_prefix): Use `grub_prefix' to set the `prefix'
+       environment variable instead of dummy make_install_device().
+
+       * kern/i386/ieee1275/startup.S: Include `<grub/machine/kernel.h>'.
+       (start): Insert a data section, with `grub_prefix' variable.
+       * kern/i386/linuxbios/startup.S: Likewise.
+
+       * include/grub/powerpc/ieee1275/kernel.h [!ASM_FILE] (grub_prefix):
+       New variable reference.
+       * include/grub/i386/ieee1275/kernel.h (GRUB_KERNEL_MACHINE_PREFIX):
+       New macro.  Defines offset of `grub_prefix' within startup.S (relative
+       to `start').
+       (GRUB_KERNEL_MACHINE_DATA_END): New macro.  Defines the end of data
+       section within startup.S (relative to `start').
+       * include/grub/i386/coreboot/kernel.h: Likewise.
+
+       * util/elf/grub-mkimage.c (add_segments): Receive `prefix' parameter.
+       Overwrite grub_prefix with its contents, at the beginning of the
+       first segment.
+       (main): Understand -p|--prefix.
+
+2008-07-30  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/10_hurd.in: Source ${libdir}/grub/update-grub_lib.
+
+2008-07-30  Robert Millan  <rmh@aybabtu.com>
+
+       * term/i386/pc/vga_text.c (grub_console_cls): Use
+       grub_console_gotoxy() to go back to beginning of the screen.
+       Found by Patrick Georgi <patrick.georgi@coresystems.de>
+
+2008-07-29  Christian Franke  <franke@computer.org>
+
+       * util/update-grub_lib.in (make_system_path_relative_to_its_root):
+       Add conversion of emulated mount points on Cygwin.
+
+2008-07-29  Christian Franke  <franke@computer.org>
+
+       * util/update-grub.in: Add a check for admin
+       group on Cygwin.
+       Remove old `grub.cfg.new' before creation.
+       Add `-f' to `mv' to handle the different filesystem
+       semantics of Windows.
+
+2008-07-29  Bean  <bean123ch@gmail.com>
+
+       * normal/main.c (get_line): Fix buffer overflow bug.
+
+2008-07-28  Robert Millan  <rmh@aybabtu.com>
+
+       * partmap/apple.c (GRUB_APPLE_HEADER_MAGIC): New macro.
+       (struct grub_apple_header): New struct.  Describes the layout of
+       the partmap header.
+       (apple_partition_map_iterate): Check the header magic as well as the
+       partition magic (which was already being checked).
+
+2008-07-28  Pavel Roskin  <proski@gnu.org>
+
+       * genmk.rb: Add a warning to the beginning of the output that
+       it's a generated file and should not be edited.
+
+2008-07-28  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/raid.c (grub_raid_scan_device): Do not abort when two disks
+       with the same number are found, just use issue a warning with
+       grub_dprintf(), as this error has been reported to be non-fatal.
+
+2008-07-27  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/ata.c (grub_ata_dumpinfo): Use grub_dprintf() for debugging
+       information.
+
+2008-07-27  Bean  <bean123ch@gmail.com>
+
+       * fs/fat.c (GRUB_FAT_MAXFILE): New constant.
+       (grub_fat_find_dir): Ignore case when comparing filename.
+
+2008-07-27  Bean  <bean123ch@gmail.com>
+
+       * fs/xfs.c (grub_xfs_dir_header): Change field i8count back to
+       smallino, as it's more descriptive, and i8count can be confused with
+       the other field count.
+       (grub_xfs_iterate_dir): Adjust grub_xfs_dir_entry pointer for small
+       inode type.
+
+2008-07-27  Bean  <bean123ch@gmail.com>
+
+       * commands/crc.c: New file.
+
+       * lib/crc.c: Likewise.
+
+       * include/grub/lib/crc.h: Likewise.
+
+       * util/grub-fstest.c: grub/hexdump.h => grub/lib/hexdump.h.
+
+       * commands/hexdump.c: grub/hexdump.h => grub/lib/hexdump.h.
+       (hexdump): Move this function to ...
+
+       * lib/hexdump.c: ... here.
+
+       * include/grub/hexdump.h: Renamed to ...
+
+       * include/grub/lib/hexdump.h: ... this.
+
+       * commands/loadenv.c: grub/envblk.h => grub/lib/envblk.h
+
+       * util/grub-editenv.c: Likewise.
+
+       * include/envblk.h: Renamed to ...
+
+       * include/lib/envblk.h: ... this.
+
+       * util/envblk.c: Renamed to ...
+
+       * lib/envblk.c: ... this.
+
+       * conf/common.rmk (grub_fstest_SOURCES): commands/hexdump.c =>
+       lib/hexdump.c.
+       (grub_editenv_SOURCES): util/envblk.c => lib/envblk.c
+       (pkglib_MODULES): Add crc.mod.
+       (hexdump_mod_SOURCES): Add lib/hexdump.c.
+       (loadenv_mod_SOURCES): util/envblk.c => lib/envblk.c.
+       (crc_mod_SOURCES): New macro.
+       (crc_mod_CFLAGS): Likewise.
+       (crc_mod_LDFLAGS): Likewise.
+
+       * conf/i386-coreboot.rmk (grub_emu_SOURCES): Add lib/hexdump.c.
+
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise.
+
+2008-07-27  Felix Zielcke  <fzielcke@z-51.de>
+
+       * commands/help.c: Include <grub/term.h>.
+       (TERM_WIDTH): Removed.  Updated all users.
+
+2008-07-27  Pavel Roskin  <proski@gnu.org>
+
+       * util/getroot.c (find_root_device): Rephrase a comment to avoid
+       spurious warnings about a comment within a comment.
+
+2008-07-25  Robert Millan  <rmh@aybabtu.com>
+
+       * util/getroot.c (find_root_device): Skip devices that match
+       /dev/dm-[0-9].  This lets the real device be found for any type of
+       abstraction (LVM, EVMS, RAID..).
+       (grub_guess_root_device): Do not traverse /dev/mapper (for LVM)
+       and /dev/evms (for EVMS) before traversing /dev.  If a /dev/dm-[0-9]
+       device is found first, find_root_device() will now skip it.
+
+2008-07-24  Pavel Roskin  <proski@gnu.org>
+
+       * include/grub/types.h: Use __builtin_bswap32() and
+       __builtin_bswap64() with gcc 4.3 and newer.
+
+2008-07-24  Christian Franke  <franke@computer.org>
+
+       * util/i386/pc/grub-install.in: If `--debug' is specified,
+       pass `--verbose' to grub-setup.
+       Abort script if make_system_path_relative_to_its_root() fails.
+
+2008-07-24  Bean  <bean123ch@gmail.com>
+
+       * configure.ac: Fixed a bug caused by the previous cygwin patch,
+       variable `target_platform' should be `platform'.
+
+2008-07-24  Bean  <bean123ch@gmail.com>
+
+       * video/reader/png.c (DEFLATE_HLIT_MAX): Change value.
+       (grub_png_init_fixed_block): New function.
+       (grub_png_decode_image_data): Handle fixed huffman code compression.
+
+2008-07-24  Bean  <bean123ch@gmail.com>
+
+       * common.rmk (bin_UTILITIES): Add grub-pe2elf.
+       (grub_pe2elf_SOURCES): New macro.
+       (CLEANFILES): Add grub-pe2elf.
+
+       * include/grub/efi/pe32.h (GRUB_PE32_SCN_ALIGN_1BYTES): New constant.
+       (GRUB_PE32_SCN_ALIGN_2BYTES): Likewise.
+       (GRUB_PE32_SCN_ALIGN_4BYTES): Likewise.
+       (GRUB_PE32_SCN_ALIGN_8BYTES): Likewise.
+       (GRUB_PE32_SCN_ALIGN_16BYTES): Likewise.
+       (GRUB_PE32_SCN_ALIGN_32BYTES): Likewise.
+       (GRUB_PE32_SCN_ALIGN_64BYTES): Likewise.
+       (GRUB_PE32_SCN_ALIGN_SHIFT): Likewise.
+       (GRUB_PE32_SCN_ALIGN_MASK): Likewise.
+       (GRUB_PE32_SYM_CLASS_EXTERNAL): Likewise.
+       (GRUB_PE32_SYM_CLASS_STATIC): Likewise.
+       (GRUB_PE32_SYM_CLASS_FILE): Likewise.
+       (GRUB_PE32_DT_FUNCTION): Likewise.
+       (GRUB_PE32_REL_I386_DIR32): Likewise.
+       (GRUB_PE32_REL_I386_REL32): Likewise.
+       (grub_pe32_symbol): New structure.
+       (grub_pe32_reloc): Likewise.
+
+       * util/grub-pe2elf.c: New file.
+
+       * configure.ac: Set TARGET_OBJ2ELF if host os is cygwin. Don't test for
+       start symbol in non pc platform.
+
+       * genmk.rb: Use TARGET_OBJ2ELF to convert native object format to elf.
+
+       The following patches are from Christian Franke.
+
+       * include/grub/dl.h: Remove .previous, gas supports this only
+       for ELF format.
+
+       * include/grub/symbol.h [__CYGWIN__] (#define FUNCTION/VARIABLE):
+       Remove .type, gas supports this only for ELF format.
+
+       * kern/dl.c (grub_dl_resolve_dependencies): Add check for trailing
+       nullbytes in symbol table. This fixes an infinite loop if table is
+       zero filled.
+
+       * Makefile.in: Add autoconf replacements TARGET_IMG_LDSCRIPT,
+       TARGET_IMG_LDFLAGS and EXEEXT.
+
+       * aclocal.m4 (grub_PROG_OBJCOPY_ABSOLUTE): Replace -Wl,-N by
+       TARGET_IMG_LDFLAGS_AC.
+       (grub_CHECK_STACK_ARG_PROBE): New function.
+
+       * conf/i386-pc.rmk: Replace -Wl,-N by TARGET_IMG_LDFLAGS.
+
+       * conf/i386-pc-cygwin-ld-img.sc: New linker script.
+
+       * configure.ac: Add check for linker script "conf/${target}-img-ld.c"
+       to set TARGET_IMG_LD* accordingly.
+       Add check for Cygwin to set TARGET_MOD_OBJCOPY accordingly.
+       Add call to grub_CHECK_STACK_ARG_PROBE.
+       Use TARGET_IMG_LDFLAGS to check start, bss_start, end symbols.
+
+       * genkernsyms.sh.in: Handle HAVE_ASM_USCORE case.
+
+       * genmk.rb: Add EXEEXT to CLEANFILES.
+
+2008-07-23  Robert Millan  <rmh@aybabtu.com>
+
+       * Makefile.in (UNICODE_ARROWS, UNICODE_LINES): New variables (they
+       define the codes for arrows and lines used for the menu).
+       (ascii.pff): Generate fonts for $(UNICODE_ARROWS) and $(UNICODE_LINES)
+       as well.
+
+       * util/update-grub_lib.in (font_path): Prefer ascii.pff over complete
+       fonts, because the latter are too slow.
+
+2008-07-21  Bean  <bean123ch@gmail.com>
+
+       * kern/i386/pc/startup.S (gate_a20_try_bios): Change test order for
+       a20. Run keyboard test last, as it will cause macbook to halt.
+
+2008-07-18  Pavel Roskin  <proski@gnu.org>
+
+       * kern/dl.c: Go back to using GRUB_CPU_SIZEOF_VOID_P.  We cannot
+       load foreign architecture modules correctly anyway.  Keep
+       support for loading host architecture modules, whether we
+       compile them or not.
+
+2008-07-17  Pavel Roskin  <proski@gnu.org>
+
+       * configure.ac: Use -m32 or -m64 regardless of whether we had to
+       change target_cpu.  The compiler default can mismatch target_cpu
+       in any case.
+
+       * disk/efi/efidisk.c: Fix format warnings on x86_64.
+       * kern/efi/efi.c: Likewise.
+
+       * aclocal.m4 (grub_PROG_TARGET_CC): New macro.  Check if the
+       target compiler is functional.
+       * configure.ac: Call grub_PROG_TARGET_CC once all target flags
+       are set up.
+
+       * configure.ac: Default to efi platform for x86_64-apple.  Allow
+       powerpc64 CPU, default to ieee1275 platform for it.  Split CPU
+       adjustments from the rest, only do them if target is not
+       explicitly given.  Merge other adjustments with the final sanity
+       check.  Remove an extraneous check for supported CPU.  Be
+       specific which CPU and which platform is not supported.
+
+       * configure.ac: Default to pc platform for x86_64.
+
+2008-07-17  Robert Millan  <rmh@aybabtu.com>
+
+       Partial LinuxBIOS -> Coreboot rename.
+
+       * conf/i386-linuxbios.rmk: Renamed to ...
+       * conf/i386-coreboot.rmk: ... this.
+       * Makefile.in (RMKFILES): s/i386-linuxbios.rmk/i386-coreboot.rmk/g.
+       * configure.ac: Accept "coreboot" as input platform (but maintain
+       compatibility with "linuxbios").
+       * include/grub/i386/linuxbios: Renamed to ...
+       * include/grub/i386/coreboot: ... this.
+
+2008-07-17  Bean  <bean123ch@gmail.com>
+
+       * conf/i386/efi.rmk (pkglib_MODULES): add pci.mod and lspci.mod.
+       (appleldr_mod_SOURCE): New variable.
+       (appleldr_mod_CFLAGS): Likewise.
+       (appleldr_mod_LDFLAGS): Likewise.
+       (pci_mod_SOURCES): Likewise.
+       (pci_mod_CFLAGS): Likewise.
+       (pci_mod_LDFLAGS): Likewise.
+       (lspci_mod_SOURCES): Likewise.
+       (lspci_mod_CFLAGS): Likewise.
+       (lspci_mod_LDFLAGS): Likewise.
+
+       * conf/x86_64-efi.rmk: New file.
+
+       * disk/efi/efidisk.c (grub_efidisk_read): Wrap efi calls with efi_call_N
+       macro.
+       (grub_efidisk_write): Likewise.
+
+       * include/efi/api.h (efi_call_0): New macro.
+       (efi_call_1): Likewise.
+       (efi_call_2): Likewise.
+       (efi_call_3): Likewise.
+       (efi_call_4): Likewise.
+       (efi_call_5): Likewise.
+       (efi_call_6): Likewise.
+
+       * include/grub/efi/chainloader.h (grub_chainloader_cmd): Rename to
+       grub_rescue_cmd_chainloader.
+
+       * include/grub/efi/pe32.h (GRUB_PE32_MACHINE_X86_64): New macro.
+       (grub_pe32_optional_header): Change some fields based on i386 or
+       x86_64 platform.
+       (GRUB_PE32_PE32_MAGIC): Likewise.
+
+       * include/grub/efi/uga_draw.h: New file.
+
+       * include/grub/elf.h (STN_ABS): New constant.
+       (R_X86_64_NONE): Relocation constant for x86_64.
+       (R_X86_64_64): Likewise.
+       (R_X86_64_PC32): Likewise.
+       (R_X86_64_GOT32): Likewise.
+       (R_X86_64_PLT32): Likewise.
+       (R_X86_64_COPY): Likewise.
+       (R_X86_64_GLOB_DAT): Likewise.
+       (R_X86_64_JUMP_SLOT): Likewise.
+       (R_X86_64_RELATIVE): Likewise.
+       (R_X86_64_GOTPCREL): Likewise.
+       (R_X86_64_32): Likewise.
+       (R_X86_64_32S): Likewise.
+       (R_X86_64_16): Likewise.
+       (R_X86_64_PC16): Likewise.
+       (R_X86_64_8): Likewise.
+       (R_X86_64_PC8): Likewise.
+
+       * include/grub/i386/efi/pci.h: New file.
+
+       * include/grub/i386/linux.h (GRUB_LINUX_EFI_SIGNATURE):
+       Change it value based on platform.
+       (GRUB_LINUX_EFI_SIGNATURE_0204): New constant.
+       (GRUB_E820_RAM): Likewise.
+       (GRUB_E820_RESERVED): Likewise.
+       (GRUB_E820_ACPI): Likewise.
+       (GRUB_E820_NVS): Likewise.
+       (GRUB_E820_EXEC_CODE): Likewise.
+       (GRUB_E820_MAX_ENTRY): Likewise.
+       (grub_e820_mmap): New structure.
+       (linux_kernel_header): Change the efi field according to different
+       kernel version, also field from linux_kernel_header.
+
+       * include/grub/kernel.h (grub_module_info): Add padding for x86_64.
+
+       * include/grub/pci.h (GRUB_PCI_ADDR_SPACE_MASK): New constant.
+       (GRUB_PCI_ADDR_SPACE_MEMORY): Likewise.
+       (GRUB_PCI_ADDR_SPACE_IO): Likewise.
+       (GRUB_PCI_ADDR_MEM_TYPE_MASK): Likewise.
+       (GRUB_PCI_ADDR_MEM_TYPE_32): Likewise.
+       (GRUB_PCI_ADDR_MEM_TYPE_1M): Likewise.
+       (GRUB_PCI_ADDR_MEM_TYPE_64): Likewise.
+       (GRUB_PCI_ADDR_MEM_PREFETCH): Likewise.
+       (GRUB_PCI_ADDR_MEM_MASK): Likewise.
+       (GRUB_PCI_ADDR_IO_MASK): Likewise.
+
+       * include/grub/x86_64/efi/kernel.h: New file.
+
+       * include/grub/x86_64/efi/loader.h: Likewise.
+
+       * include/grub/x86_64/efi/machine.h: Likewise.
+
+       * include/grub/x86_64/efi/pci.h: Likewise.
+
+       * include/grub/x86_64/efi/time.h: Likewise.
+
+       * include/grub/x86_64/linux.h: Likewise.
+
+       * include/grub/x86_64/setjmp.h: Likewise.
+
+       * include/grub/x86_64/time.h: Likewise.
+
+       * include/grub/x86_64/types.h: Likewise.
+
+       * kern/dl.c (GRUB_CPU_SIZEOF_VOID_P): Changed to
+        GRUB_TARGET_SIZEOF_VOID_P.
+
+       * kern/efi/efi.c (grub_efi_locate_protocol): Wrap efi calls.
+       (grub_efi_locate_handle): Likewise.
+       (grub_efi_open_protocol): Likewise.
+       (grub_efi_set_text_mode): Likewise.
+       (grub_efi_stall): Likewise.
+       (grub_exit): Likewise.
+       (grub_reboot): Likewise.
+       (grub_halt): Likewise.
+       (grub_efi_exit_boot_services): Likewise.
+       (grub_get_rtc): Likewise.
+
+       * kern/efi/mm.c (MEMORY_MAP_SIZE): Change to 0x3000 for new models.
+       (GRUB_CPU_SIZEOF_VOID_P): Changed to GRUB_TARGET_SIZEOF_VOID_P.
+       (grub_efi_allocate_pages): Wrap efi calls.
+       (grub_efi_free_pages): Wrap efi calls.
+       (grub_efi_get_memory_map): Wrap efi calls.
+
+       * kern/x86_64/dl.c: New file.
+
+       * kern/x86_64/efi/callwrap.S: Likewise.
+
+       * kern/x86_64/efi/startup.S: Likewise.
+
+       * loader/efi/appleloader.c: Likewise.
+
+       * loader/efi/chainloader.c (cmdline): New variable.
+       (grub_chainloader_unload): Wrap efi calls.
+       (grub_chainloader_boot): Likewise.
+       (grub_rescue_cmd_chainloader): Wrap efi calls, handle
+       command line.
+
+       * loader/efi/chainloader_normal.c (chainloader_command):
+       Change grub_chainloader_cmd to grub_rescue_cmd_chainloader, pass
+       command line.
+
+       * loader/i386/efi/linux.c (allocate_pages): Change allocation
+       method.
+       (grub_e820_add_region): New function.
+       (grub_linux_boot): Construct e820 map from efi map, handle x86_64
+       booting.
+       (grub_find_video_card): New function.
+       (grub_linux_setup_video): New function.
+       (grub_rescue_cmd_linux): Probe for video information.
+
+       * normal/x86_64/setjmp.S: New file.
+
+       * term/efi/console.c (map_char): New function.
+       (grub_console_putchar): Map unicode char.
+       (grub_console_checkkey): Wrap efi calls.
+       (grub_console_getkey): Likewise.
+       (grub_console_getwh): Likewise.
+       (grub_console_gotoxy): Likewise.
+       (grub_console_cls): Likewise.
+       (grub_console_setcolorstate): Likewise.
+       (grub_console_setcursor): Likewise.
+
+       * util/i386/efi/grub-mkimage.c: Add support for x86_64.
+
+2008-07-16  Pavel Roskin  <proski@gnu.org>
+
+       * loader/i386/efi/linux.c (allocate_pages): Fix warnings in
+       format strings.
+
+       * util/i386/efi/grub-mkimage.c (get_target_address): Return a
+       pointer, not an integer.  This fixes a warning and prevents
+       precision loss on 64-bit systems.
+       (relocate_addresses): Remove unneeded cast.
+
+2008-07-15  Pavel Roskin  <proski@gnu.org>
+
+       * kern/i386/ieee1275/init.c: Include grub/cache.h.
+
+       * term/ieee1275/ofconsole.c: Disable code unused on i386.
+
+       * kern/ieee1275/ieee1275.c (grub_ieee1275_get_integer_property):
+       Fix comparison between signed and unsigned.
+
+       * include/grub/i386/ieee1275/console.h: Declare
+       grub_console_init() and grub_console_fini().
+
+       * loader/i386/ieee1275/linux.c (grub_set_bootpath): Remove.
+       It's empty and unused.
+
+       * fs/ext2.c (grub_ext2_read_block): Initialize blknr in the
+       beginning to avoid warnings with some compilers.
+
+       * loader/ieee1275/multiboot2.c: Include grub/machine/loader.h.
+       [__i386__] (grub_mb2_arch_boot): Avoid unnecessary cast.
+
+2008-07-14  Pavel Roskin  <proski@gnu.org>
+
+       * kern/env.c (grub_register_variable_hook): Don't copy empty
+       string, it leaks memory.  Pass "" to grub_env_set(), it should
+       handle constant strings.
+
+       * commands/blocklist.c (grub_cmd_blocklist): Fix format warning.
+       * commands/cmp.c (grub_cmd_cmp): Likewise.
+       * kern/dl.c (grub_dl_flush_cache): Likewise.
+       (grub_dl_load_core): Likewise.
+       * kern/elf.c (grub_elf32_load_phdrs): Likewise.
+       (grub_elf64_load_phdrs): Likewise.
+
+2008-07-13  Pavel Roskin  <proski@gnu.org>
+
+       * lib/LzmaEnc.c (LzmaEnc_SetProps): Fix warning about comparison
+       between signed and unsigned.
+       (LzmaEnc_Finish): Fix warning about an unused parameter.
+
+2008-07-13  Bean  <bean123ch@gmail.com>
+
+       * Makefile.in (enable_lzo): New rule.
+
+       * conf/i386-pc.rmk (grub_mkimage_SOURCES): New test with enable_lzo.
+
+       * configure.ac (ENABLE_LZO): New option --enable-lzo.
+
+       * boot/i386/pc/lnxboot.S: #include <config.h>.
+
+       * include/grub/i386/pc/kernel.h (GRUB_KERNEL_MACHINE_RAW_SIZE): Change
+       its value according to the compression algorithm used, lzo or lzma.
+
+       * util/i386/pc/grub-mkimage.c (compress_kernel): Use different
+       compression algorithm according to configure macro.
+
+       * kern/i386/pc/startup.S (codestart): Likewise.
+
+       * kern/i386/pc/lzma_decode.S: New file.
+
+       * include/grub/lib/LzFind.h: Likewise.
+
+       * include/grub/lib/LzHash.h: Likewise.
+
+       * include/grub/lib/LzmaDec.h: Likewise.
+
+       * include/grub/lib/LzmaEnc.h: Likewise.
+
+       * include/grub/lib/LzmaTypes.h: Likewise.
+
+       * lib/LzFind.c: Likewise.
+
+       * lib/LzmaDec.c: Likewise.
+
+       * lib/LzmaEnc.c: Likewise.
+
+2008-07-13  Bean  <bean123ch@gmail.com>
+
+       * fs/ext2.c (EXT4_EXTENTS_FLAG): New macro.
+       (grub_ext4_extent_header): New structure.
+       (grub_ext4_extent): Likewise.
+       (grub_ext4_extent_idx): Likewise.
+       (grub_ext4_find_leaf): New function.
+       (grub_ext2_read_block): Handle extents.
+
+2008-07-12  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-mkrescue.in: s/grub-install/grub-mkrescue/g.
+
+2008-07-11  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/40_custom.in: New file. Example on how to add custom
+       entries to /etc/grub.d.
+       * conf/common.rmk (%, update-grub_SCRIPTS, CLEANFILES): Install
+       40_custom (implicitly, by merging all the grub.d rules).
+
+2008-07-11  Pavel Roskin  <proski@gnu.org>
+
+       * commands/read.c (grub_getline): Fix invalid memory access.
+       Don't add newline to the variable value.
+
+       * term/i386/pc/serial.c (GRUB_SERIAL_PORT_NUM): New constant.
+       [!GRUB_MACHINE_PCBIOS] (serial_hw_io_addr): Add COM2 and COM3.
+       (serial_hw_get_port): Check validity of the port number.
+       (grub_cmd_serial): Check return value of serial_hw_get_port().
+
+2008-07-07  Pavel Roskin  <proski@gnu.org>
+
+       * boot/i386/pc/diskboot.S (notification_string): Replace
+       "Loading kernel" with just "loading".  This is shorter, less
+       confusing and saves a few bytes for possible future changes.
+
+2008-07-05  Pavel Roskin  <proski@gnu.org>
+
+       * disk/ata.c (grub_ata_dumpinfo): Don't output addressing and
+       size for ATAPI devices, they are undefined.  Output sector
+       number in decimal form.
+
+       * disk/ata.c: Use named constants for status bits.
+
+2008-07-04  Pavel Roskin  <proski@gnu.org>
+
+       * kern/i386/linuxbios/init.c (grub_machine_init): Cast addr to
+       grub_addr_t before casting it to the void pointer to fix a
+       warning.  Non-addressable regions are discarded earlier.
+       (grub_arch_modules_addr): Cast _end to grub_addr_t.
+       * kern/i386/linuxbios/table.c: Include grub/misc.h.
+       (check_signature): Don't shadow table_header.
+       (grub_linuxbios_table_iterate): Cast numeric constants to
+       grub_linuxbios_table_header_t.
+       * include/grub/i386/linuxbios/init.h: Add noreturn attribute to
+       grub_stop().
+
+       * kern/ieee1275/init.c: Cast _start and _end to grub_addr_t to
+       prevent warnings.
+
+       * include/grub/misc.h (ALIGN_UP): Avoid unnecessary cast to a
+       pointer, which can cause warnings.  Support 64-bit addresses.
+
+       * util/elf/grub-mkimage.c: Use GRUB_TARGET_SIZEOF_LONG instead
+       of sizeof(long).  This fixes PowerPC image generation on x86_64.
+
+2008-07-04  Robert Millan  <rmh@aybabtu.com>
+
+       This fixes a performance issue when pc & gpt partmap iterators
+       didn't abort iteration even after our hook found what it was
+       looking for (often causing expensive probes of non-existent drives).
+
+       Some callers relied on previous buggy behaviour, since they would
+       raise an error when their own hooks caused early abortion of its
+       iteration.
+
+       * kern/device.c (grub_device_open): Improve error message.
+       * disk/lvm.c (grub_lvm_open): Likewise.
+       * disk/raid.c (grub_raid_open): Likewise.
+
+       * partmap/pc.c (pc_partition_map_iterate): Abort parent iteration
+       when hook requests it, independently of grub_errno.
+       (pc_partition_map_probe): Do not fail when find_func() caused
+       early abortion of pc_partition_map_iterate().
+
+       * partmap/gpt.c (gpt_partition_map_iterate): Abort parent iteration
+       when hook requests it, independently of grub_errno.
+       (gpt_partition_map_probe): Do not fail when find_func() caused
+       early abortion of gpt_partition_map_iterate().
+
+       * kern/partition.c (grub_partition_iterate): Abort parent iteration
+       when hook requests it, independently of grub_errno.  Do not fail when
+       part_map_iterate_hook() caused early abortion of p->iterate().
+
+       * util/biosdisk.c (grub_util_biosdisk_get_grub_dev): Do not fail
+       when grub_partition_iterate() returned with non-zero.
+
+2008-07-03  Pavel Roskin  <proski@gnu.org>
+
+       * disk/ata.c (grub_ata_pio_write): Check status before writing,
+       like we do in grub_ata_pio_read().
+       (grub_ata_readwrite): Always write individual sectors.  Fix the
+       sector count for the remainder.
+       (grub_ata_write): Enable writing to ATA devices.  Correctly
+       report error for ATAPI devices.
+
+2008-07-02  Pavel Roskin  <proski@gnu.org>
+
+       * boot/i386/pc/cdboot.S: Add _start entry to fix a linker
+       warning.
+
+       * disk/ata.c (grub_ata_readwrite): Don't increment sector number
+       for every read sector, we already increment it for the whole
+       batch.  This fixes reading more than 256 sectors at once.
+
+       * util/grub-editenv.c (cmd_info): Cast argument to long
+       explicitly.  ptrdiff_t reduces to int on i386.
+
+       * util/grub-editenv.c (main): Be specific which parameter is
+       missing.
+
+       * disk/memdisk.c (memdisk_addr): Make a pointer to fix warnings.
+       (memdisk): Make memdisk_orig_addr a pointer.
+
+       * fs/reiserfs.c (grub_reiserfs_read): Fix misuse of grub_size_t
+       for file offsets, use grub_off_t instead.  Fix printf format
+       warnings.
+
+       * fs/reiserfs.c: Remove #warning, TODO list items don't belong
+       there.  Real unexpected warnings should not drown in the noise
+       about known problems.
+
+       * commands/hexdump.c (grub_cmd_hexdump): Fix misuse of
+       grub_disk_addr_t for memory addresses.
+
+       * loader/aout.c (grub_aout_load): Cast load_addr to pointer
+       explicitly to fix a warning.
+
+       * util/grub-editenv.c (cmd_info): Fix warning in printf format.
+
+       * Makefile.in (MODULE_LDFLAGS): New variable.
+       * aclocal.m4 (grub_PROG_LD_BUILD_ID_NONE): New macro.  Check if
+       the linker accepts --build-id=none.
+       * configure.ac: Call grub_PROG_LD_BUILD_ID_NONE.  Substitute
+       MODULE_LDFLAGS.
+       * genmk.rb: Use MODULE_LDFLAGS when linking modules.
+
+       * fs/xfs.c (struct grub_xfs_dir_header): Use names similar to
+       those in Linux XFS code.  Provide a way to access 64-bit parent
+       inode.
+       (grub_xfs_iterate_dir): Use the new names.  Avoid reading past
+       the end of struct grub_xfs_dir_header.
+
+2008-07-02  Bean  <bean123ch@gmail.com>
+
+       * include/grub/ieee1275.h (grub_ieee1275_flag): New constant
+       GRUB_IEEE1275_FLAG_CANNOT_INTERPRET, GRUB_IEEE1275_FLAG_FORCE_CLAIM
+       and GRUB_IEEE1275_FLAG_NO_ANSI.
+
+       * kern/ieee1275/cmain.c (grub_ieee1275_find_options): Set flag
+       GRUB_IEEE1275_FLAG_CANNOT_INTERPRET, GRUB_IEEE1275_FLAG_FORCE_CLAIM
+       and GRUB_IEEE1275_FLAG_NO_ANSI for Open Hackware.
+
+       * kern/ieee1275/ieee1275.c (grub_ieee1275_interpret): Return
+       immediately if GRUB_IEEE1275_FLAG_CANNOT_INTERPRET is set.
+
+       * kern/ieee1275/init.c (grub_claim_heap): Claim memory directly if
+       GRUB_IEEE1275_FLAG_FORCE_CLAIM is set.
+
+       * term/ieee1275/ofconsole.c (grub_ofconsole_writeesc): Don't output
+       esc sequence on non ANSI terminal.
+       (grub_ofconsole_gotoxy): Emulate backspace key on non ANSI terminal.
+
+       * util/elf/grub-mkimage.c (add_segments): Move ELF header to the
+       beginning of file.
+
+2008-07-02  Bean  <bean123ch@gmail.com>
+
+       * conf/common.rmk (bin_UTILITIES): Add grub-editenv.
+       (grub_editenv_SOURCES): New variable.
+       (pkglib_MODULES): Add loadenv.mod.
+       (loadenv_mod_SOURCES): New variable.
+       (loadenv_mod_CFLAGS): Likewise.
+       (loadenv_mod_LDFLAGS): Likewise.
+
+       * include/grub/envblk.h: New file.
+
+       * util/envblk.c: New file.
+
+       * util/grub-editenv.c: New file.
+
+       * commands/loadenv.c: New file.
+
+2008-07-01  Pavel Roskin  <proski@gnu.org>
+
+       * include/multiboot2.h (struct multiboot_tag_module): Use char,
+       not unsigned char.  This fixes warnings and is consistent with
+       other tags.
+
+       * disk/fs_uuid.c (search_fs_uuid): Correctly increment count.
+
+       * normal/parser.y: Define YYENABLE_NLS as 0 to fix warnings.
+
+       * term/tparm.c (analyze): Always set *popcount.
+
+       * loader/i386/pc/linux.c (grub_rescue_cmd_linux): Remove useless
+       cast to fix a warning.
+
+       * loader/i386/pc/multiboot2.c (grub_mb2_arch_module_alloc): Use
+       cast to suppress a warning.
+
+       * fs/afs.c (grub_afs_read_block): Return grub_disk_addr_t, as
+       grub_fshelp_read_file() expects.
+
+       * fs/fat.c: Fix UUID calculation on big-endian systems.  We
+       write uuid as a 32-bit value in CPU byte order, so declare and
+       use it as such.
+
+       * disk/raid.c: Cast grub_dprintf() arguments to unsigned long
+       long if the format specifier expects it.
+       * partmap/gpt.c (gpt_partition_map_iterate): Likewise.
+       * partmap/pc.c (pc_partition_map_iterate): Likewise.
+       * fs/ntfs.c (grub_ntfs_uuid): Cast data->uuid to unsigned long
+       long to fix a warning.
+       * fs/reiserfs.c (grub_reiserfs_read): Change casts in
+       grub_dprintf() arguments to fix warnings.
+
+2008-06-30  Pavel Roskin  <proski@gnu.org>
+
+       * util/i386/pc/grub-setup.c (setup): Write install_dos_part and
+       install_bsd_part immediately before core.img is embedded or
+       modified on disk.  This fixes core.img verification if core.img
+       cannot be embedded.
+
+       * util/i386/pc/grub-setup.c (setup): Use core_path_dev, not
+       core_path to calculate the blocklist.
+       Patch from Javier Martín <lordhabbit@gmail.com>
+
+2008-06-29  Robert Millan  <rmh@aybabtu.com>
+
+       * fs/xfs.c (GRUB_XFS_FSB_TO_BLOCK): New macro.  Maps filesystem
+       block to disk block.
+       (grub_xfs_read_block): Use GRUB_XFS_FSB_TO_BLOCK() on result.
+       Patch from Niels Böhm <bitbucket@arcor.de>
+
+2008-06-29  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub_lib.in (font_path): Search for fonts in
+       /boot/grub first, which is more likely to be readable (we aren't
+       deciding where fonts live, just looking for them).
+
+2008-06-26  Pavel Roskin  <proski@gnu.org>
+
+       * util/biosdisk.c (read_device_map): Don't leave dead map
+       entries for devices failing stat() check.
+
+       * util/i386/pc/grub-setup.c (setup): Don't reuse core_path, use
+       core_path_dev for the core.img path on the target device.
+
+2008-06-26  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/fs_uuid.c: New file.
+       * conf/common.rmk (pkglib_MODULES): Add `fs_uuid.mod'.
+       (fs_uuid_mod_SOURCES, fs_uuid_mod_CFLAGS)
+       (fs_uuid_mod_LDFLAGS): New variables.
+       * include/grub/disk.h (grub_disk_dev_id): Add
+       `GRUB_DISK_DEVICE_UUID_ID'.
+       * kern/disk.c (grub_disk_dev_iterate): Allow disk devices not to
+       implement iterate().
+
+2008-06-26  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/10_linux.in: Avoid passing UUIDs to Linux when either
+       "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" does not exist, or when a
+       Linux image includes no initrd.
+
+2008-06-21  Javier Martín  <lordhabbit@gmail.com>
+
+       * util/i386/pc/grub-setup.c (setup): Remove literal "core.img" in a
+       call to resolve the core image location that effectively appended the
+       name twice.
+
+2008-06-21  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/00_header.in: Move last prepare_grub_to_access_device()
+       call from here ...
+
+       * util/grub.d/10_hurd.in: ... to here ...
+       * util/grub.d/10_linux.in: ... and here.
+
+2008-06-19  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/main.c (grub_main): Export `prefix' variable immediately
+       after it has been set by grub_machine_set_prefix().
+
+2008-06-19  Robert Millan  <rmh@aybabtu.com>
+
+       * commands/search.c (search_label, search_fs_uuid, search_file): Print
+       search result when not saving to variable, not the other way around.
+       When saving to variable, abort iteration as soon as a match is found.
+
+2008-06-19  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub_lib.in (prepare_grub_to_access_device): Remove
+       check for partition that provides /boot/grub.  Its logic is flawed,
+       as it prevents prepare_grub_to_access_device() from being called
+       multiple times.
+
+2008-06-19  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub_lib.in (prepare_grub_to_access_device): Issue
+       "insmod" command directly when abstraction modules are needed,
+       instead of relying on GRUB_PRELOAD_MODULES (which had no effect
+       since it had already been processed).
+
+2008-06-19  Pavel Roskin  <proski@gnu.org>
+
+       * conf/i386-efi.rmk: Recompile grub-mkimage.c if Makefile has
+       changed.  This is needed in case GRUB_LIBDIR changes.
+       * conf/i386-ieee1275.rmk: Likewise.
+       * conf/i386-linuxbios.rmk: Likewise.
+       * conf/i386-pc.rmk: Likewise.
+       * conf/powerpc-ieee1275.rmk: Likewise.
+
+2008-06-18  Pavel Roskin  <proski@gnu.org>
+
+       * conf/powerpc-ieee1275.rmk (kernel_elf_SOURCES): Rename
+       kernel_elf_symlist.c to symlist.c for consistency with other
+       architectures.  Update all users.
+       * conf/sparc64-ieee1275.rmk (kernel_elf_SOURCES): Likewise.
+
+2008-06-18  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-install.in: If the drive is LVM or RAID, prepend
+       it in prefix.
+
+       * util/i386/pc/grub-setup.c (main): Don't handle prefix at all.  Set
+       `must_embed' to 1 when root_dev is a RAID device.  When dest_dev is
+       a RAID device, run setup() for all members independently on whether
+       LVM abstraction is being used.
+       (setup): Don't handle prefix at all; let grub-mkimage take care of it.
+       If grub-mkimage has set `*install_dos_part == -2', don't override this
+       value.
+       Perform *install_dos_part adjustments independently on whether
+       we're embedding or not.
+       Clarify error message when image is too big for embedding.
+       Remove duplicate *install_dos_part stanza.
+
+2008-06-17  Robert Millan  <rmh@aybabtu.com>
+
+       * term/ieee1275/ofconsole.c (fgcolor, bgcolor): Remove variables.
+       (grub_ofconsole_normal_color, grub_ofconsole_highlight_color): New
+       variables.
+       (grub_ofconsole_setcolor, grub_ofconsole_getcolor): Load/store
+       values in grub_ofconsole_normal_color and
+       grub_ofconsole_highlight_color (they're not directly related to
+       background and foreground).
+       (grub_ofconsole_setcolorstate): Extract background and foreground
+       from grub_ofconsole_normal_color and grub_ofconsole_highlight_color.
+
+2008-06-17  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub_lib.in (prepare_grub_to_access_device): Use
+       /boot/grub for the check in last commit, not /boot (they could be
+       different partitions).
+
+2008-06-16  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub_lib.in (prepare_grub_to_access_device): If we were
+       asked to setup access for the same partition that provides /boot,
+       don't bother using UUIDs since our root already has the value we
+       want.
+
+2008-06-16  Robert Millan  <rmh@aybabtu.com>
+
+       * util/biosdisk.c (convert_system_partition_to_system_disk): Detect
+       I2O devices.
+       Patch from Sven Mueller <sven@debian.org>.
+
+2008-06-16  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub.in: Check for $EUID instead of $UID.
+       Reported by Vincent Zweije.
+
+2008-06-16  Bean  <bean123ch@gmail.com>
+
+       * fs/ext2.c (grub_ext2_blockgroup): Revert to pre-journal state.
+       (grub_ext2_read_block): Likewise.
+       (grub_ext2_read_inode): Likewise.
+       (grub_ext2_mount): Likewise.
+       (grub_ext2_close): Likewise.
+       (grub_ext3_get_journal): Removed.
+
+       * fs/reiserfs.c (grub_reiserfs_get_item): Revert to pre-journal state.
+       (grub_reiserfs_read_symlink): Likewise.
+       (grub_reiserfs_mount): Likewise.
+       (grub_reiserfs_open): Likewise.
+       (grub_reiserfs_read): Likewise.
+       (grub_reiserfs_close): Likewise.
+       (grub_reiserfs_get_journal): Removed.
+
+       * fs/fshelp.c (grub_fshelp_read): Removed.
+       (grub_fshelp_map_block): Likewise.
+
+       * include/grub/fshelp.h (grub_fshelp_journal_type): Removed.
+       (grub_fshelp_journal): Likewise.
+       (grub_fshelp_read): Likewise.
+       (grub_fshelp_map_block): Likewise.
+
+2008-06-16  Pavel Roskin  <proski@gnu.org>
+
+       * conf/powerpc-ieee1275.rmk: Remove -msoft-float, we don't use
+       floating point anymore.
+       * include/grub/powerpc/libgcc.h: Leave only necessary exports.
+
+2008-06-15  Pavel Roskin  <proski@gnu.org>
+
+       * commands/ls.c (grub_ls_list_files): Use integer calculations
+       for human readable format, avoid floating point use.
+       * kern/misc.c (grub_ftoa): Remove.
+       (grub_vsprintf): Remove floating point support.
+
+2008-06-15  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/10_linux.in: Use the underlying device for loop-AES
+       devices.
+       Reported by Max Vozeler.
+
+2008-06-15  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-mkimage.c (generate_image): If we included a drive
+       in our prefix, set install_{dos,bsd}_part = -2 to indicate this can be
+       skipped later.
+       (main): If a memdisk was requested, add "(memdisk)" drive explicitly to
+       the beginning of the prefix.
+
+       * kern/i386/pc/init.c (make_install_device): Remove memdisk check.
+       It is assumed that if we have a memdisk, grub-mkimage has set
+       grub_prefix to include the "(memdisk)" drive in it.
+
+2008-06-15  Robert Millan  <rmh@aybabtu.com>
+
+       * term/i386/pc/console.c [GRUB_MACHINE_LINUXBIOS] (grub_console_init):
+       Initialize keyboard controller after registering the terminal, so that
+       grub_printf() can be called from grub_keyboard_controller_init().
+
+2008-06-15  Robert Millan  <rmh@aybabtu.com>
+
+       * fs/sfs.c (grub_sfs_read_extent): Fix the count of nodes in
+       extent-btree which is written as big endian on disk.
+       Reported by Alain Greppin  <al@chilibi.org>.
+
+2008-06-14  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/efi/grub-install.in (modules): Remove `_chain'.
+       * util/i386/pc/grub-install.in (modules): Likewise.
+
+2008-06-13  Pavel Roskin  <proski@gnu.org>
+
+       * commands/ls.c (grub_ls_list_files): Fix format warnings.
+
+2008-06-13  Bean  <bean123ch@gmail.com>
+
+       * commands/hexdump.c (grub_cmd_hexdump): Adjust offset for partition.
+
+       * fs/ext2.c (grub_ext3_get_journal): Fix revoke block handling.
+
+       * fs/fshelp.c (grub_fshelp_map_block): Don't map block 0 as it's used
+       to indicate sparse block.
+
+2008-06-12  Pavel Roskin  <proski@gnu.org>
+
+       * fs/ext2.c (grub_ext2_read_inode): Don't normalize block
+       number, grub_fshelp_read() does it for us.
+
+       * fs/fshelp.c (grub_fshelp_read): New function.  Implement
+       linear disk read with journal translation.
+       * fs/ext2.c: Use grub_fshelp_read() instead of grub_disk_read().
+       * include/grub/fshelp.h: Declare grub_fshelp_read().
+
+2008-06-09  Pavel Roskin  <proski@gnu.org>
+
+       * fs/minix.c (grub_minix_mount): Handle error reading
+       superblock.
+
+2008-06-08  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-setup.c (main): If install drive is an LVM,
+       don't append the RAID prefix afterwards.
+       Reported by Clint Adams.
+
+2008-06-08  Robert Millan  <rmh@aybabtu.com>
+
+       Based on description from Pavel:
+       * kern/disk.c (grub_disk_check_range): Rename to ...
+       (grub_disk_adjust_range): ... this.  Add a comment explaining the
+       tasks performed by this function.
+
+2008-06-08  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/ntfs.h (struct grub_ntfs_bpb): Rename `serial_number' to
+       `num_serial' (for consistency with other variables).
+       (struct grub_ntfs_data): Add `uuid' member.
+       * fs/ntfs.c (grub_ntfs_mount): Initialize `data->uuid'.
+       (grub_ntfs_uuid): New function.
+       (grub_ntfs_fs): Reference grub_ntfs_uuid() in `uuid' struct member.
+
+2008-06-07  Pavel Roskin  <proski@gnu.org>
+
+       * util/biosdisk.c (open_device): Revert last change to the
+       function, it broke installation.  The sector needs to be
+       different dependent on which device is opened.
+
+2008-06-06  Robert Millan  <rmh@aybabtu.com>
+
+       Ensure GRUB_KERNEL_MACHINE_DATA_END is always consistent with the
+       rest of GRUB, and breakage doesn't happen if its value were modified.
+
+       * include/grub/i386/pc/kernel.h (GRUB_KERNEL_MACHINE_RAW_SIZE):
+       Redefine as an offset from `GRUB_KERNEL_MACHINE_DATA_END' instead of
+       a constant (same value).
+       * kern/i386/pc/startup.S: Replace hardcoded `0x50' with
+       `GRUB_KERNEL_MACHINE_DATA_END' (same value).
+
+2008-06-06  Robert Millan  <rmh@aybabtu.com>
+
+       * util/biosdisk.c (open_device): Do not modify sector offset when
+       accessing a partition.  kern/disk.c already handles this for us.
+
+2008-06-06  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub-emu.c (grub_machine_init): Move code in this function from
+       here ...
+       (main): ... to here (before grub_util_biosdisk_init() call, to prevent
+       segfault in case grub_printf() is called).
+
+       * util/i386/pc/grub-install.in: Append `--device-map=${device_map}' to
+       grub_probe.  Update all users not to explicitly add it again.
+       (grub_device): New variable; contains corresponding device for grubdir.
+       (fs_module, partmap_module, devabstraction_module): Pass
+       `--device ${grub_device}' to grub_probe to avoid traversing /dev
+       every time.
+
+2008-06-05  Robert Millan  <rmh@aybabtu.com>
+
+       * normal/misc.c (grub_normal_print_device_info): When a filesystem UUID
+       is found, print it (same layout as with labels).
+
+2008-06-04  Robert Millan  <rmh@aybabtu.com>
+
+       * util/biosdisk.c (get_drive): Rename to ...
+       (find_grub_drive): ... this.  Update all users.
+
+       (get_os_disk): Rename to ...
+       (convert_system_partition_to_system_disk): ... this.  Update all users.
+
+       (find_drive): Rename to ...
+       (find_system_device): ... this.  Update all users.
+
+2008-06-04  Robert Millan  <rmh@aybabtu.com>
+
+       * util/biosdisk.c (get_os_disk): Handle IDA devices.
+       * util/grub-mkdevicemap.c (get_mmc_disk_name)
+       (make_device_map): Likewise.
+
+2008-06-01  Robert Millan  <rmh@aybabtu.com>
+
+       *  util/biosdisk.c (get_drive): Verify that `map[i].drive' is non-NULL
+       before dereferencing it.
+
+       * fs/fat.c (struct grub_fat_bpb): Move fat32-specific fields into a
+       union with fat12/fat16-specific ones.  Add some new fields, including
+       `num_serial' for both versions.
+       (struct grub_fat_data): Add `uuid' member.
+       (grub_fat_mount): Refer to fat32-specific fields in `bpb' by their new
+       names.  Initialize `data->uuid' using `num_serial'.
+       (grub_fat_uuid): New function.
+       (grub_fat_fs): Reference grub_fat_uuid() in `uuid' struct member.
+
+       * fs/reiserfs.c (grub_reiserfs_superblock): Add `uuid' field.
+       (grub_reiserfs_uuid): New function.
+       (grub_reiserfs_fs): Reference grub_reiserfs_uuid() in `uuid' struct
+       member.
+
+       * fs/xfs.c (grub_xfs_sblock): Add `uuid' field.
+       (grub_xfs_uuid): New function.
+       (grub_xfs_fs): Reference grub_reiserfs_uuid() in `uuid' struct member.
+
+2008-06-01  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub_lib.in (prepare_grub_to_access_device): Generate
+       code that is backward compatible with pre-uuid search command.
+
+2008-05-31  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/i386/pc/biosdisk.c (grub_biosdisk_iterate): Iterate through
+       floppies after everything else, to ensure floppy drive isn't accessed
+       unnecessarily (patch from Bean).
+
+2008-05-31  Robert Millan  <rmh@aybabtu.com>
+
+       * commands/search.c (search_label, search_fs_uuid, search_file): Do
+       not print device names when we were asked to set a variable.
+
+2008-05-31  Robert Millan  <rmh@aybabtu.com>
+
+       * term/ieee1275/ofconsole.c (grub_ofconsole_setcursor): Implement
+       using "cursor-on" and "cursor-off" commands (understood at least by
+       the Open Firmware flavour on OLPC).
+
+2008-05-31  Michael Gorven  <michael@gorven.za.net>
+
+       * term/terminfo.c (grub_terminfo_set_current): Correct vt100 cursor
+       on and off sequences.
+
+2008-05-31  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub_lib.in: Replace `grub-probe' with `${grub_probe}'.
+       * util/update-grub.in: Likewise.
+
+2008-05-30  Pavel Roskin  <proski@gnu.org>
+
+       * util/biosdisk.c (linux_find_partition): Simplify logic and
+       make the code more universal.  Keep special processing for
+       devfs, but use a simple rule for all other devices.  If the
+       device ends with a number, append 'p' and the partition number.
+       Otherwise, append only the partition number.
+
+2008-05-30  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub.in (GRUB_DISABLE_LINUX_UUID): Export variable.
+       * util/grub.d/10_linux.in: If GRUB_DEVICE_UUID is set, and
+       GRUB_DISABLE_LINUX_UUID isn't true, use the filesystem UUIDs as
+       the `root' parameter to Linux.
+
+2008-05-30  Robert Millan  <rmh@aybabtu.com>
+
+       * commands/search.c (options): Rename --fs_uuid to --fs-uuid.
+       * util/update-grub_lib.in (prepare_grub_to_access_device): Replace
+       --fs_uuid with --fs-uuid.
+       * util/update-grub.in: Allow filesystem UUID probes to fail (since not
+       all filesystems support them).
+
+2008-05-30  Robert Millan  <rmh@aybabtu.com>
+
+       * fs/ext2.c (grub_ext2_uuid): Use `04x' instead of '02x' as
+       grub_printf() flags, since we're printing in units of 2 bytes.
+
+2008-05-30  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/00_header.in: Remove obsolete comment referencing
+       convert_system_path_to_grub_path().
+       * util/update-grub.in: Likewise.
+       * util/update-grub_lib.in (is_path_readable_by_grub): New function.
+       (convert_system_path_to_grub_path): Add a warning message explaining
+       that this function is deprecated.  Rely on is_path_readable_by_grub()
+       for the readability checks.
+       (font_path): Use is_path_readable_by_grub() for the readability
+       check rather than convert_system_path_to_grub_path().
+
+2008-05-30  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub_lib.in (prepare_grub_to_access_device): New function.
+       * util/update-grub.in: Set `GRUB_FONT_PATH' to the system path, without
+       converting it first.
+       * util/grub.d/00_header.in: Use prepare_grub_to_access_device() to setup
+       grub.cfg for access to font file, and afterwards call it again to set
+       the root device.
+
+2008-05-30  Robert Millan  <rmh@aybabtu.com>
+
+       * commands/search.c (options): Add --fs_uuid option.
+       (search_fs_uuid): New function.
+       (grub_cmd_search): Fix --set argument passing.
+       Use search_fs_uuid() when requested via --fs_uuid.
+       (grub_search_init): Update help message.
+       * fs/ext2.c (struct grub_ext2_sblock): Rename `unique_id' to `uuid'
+       and redeclare it as an array of 16-bit words.
+       (grub_ext2_uuid): New function.
+       (grub_ext2_fs): Reference grub_ext2_uuid() in `uuid' struct member.
+       * include/grub/fs.h (struct grub_fs): Add `uuid' struct member.
+       * util/update-grub.in (GRUB_DEVICE_UUID, GRUB_DEVICE_BOOT)
+       (GRUB_DEVICE_BOOT_UUID): New variables.
+       (GRUB_DRIVE. GRUB_DRIVE_BOOT. GRUB_DRIVE_BOOT_GRUB): Remove.
+       * util/grub.d/00_header.in: Set root using `search --fs_uuid' command
+       whenever possible.
+       * util/grub.d/10_hurd.in: Avoid explicit use of root drive.  Instead,
+       just assume `root' variable has the right value.
+       * util/grub.d/10_linux.in: Likewise.
+       * util/grub-probe.c (probe): Probe for filesystem UUID when requested
+       via PRINT_FS_UUID.
+       (main): Recognise `-t fs_uuid' argument.
+
+2008-05-30  Robert Millan  <rmh@aybabtu.com>
+
+       * util/biosdisk.c (map): Redefine structure to hold information
+       about GRUB drive name.
+       (get_drive): Reimplement without assuming (and verifying) BIOS-like
+       drive names.
+       (call_hook): Remove.
+       (grub_util_biosdisk_iterate): Access drive names via `.drive' struct
+       member.  Assume drive has partitions.
+       (grub_util_biosdisk_open): Access device names via `.device' struct
+       member.
+       (open_device): Likewise.
+       (find_drive): Likewise.
+       (read_device_map): Adjust map[] usage to match the new struct
+       definition.  Don't check for duplicates (still possible, but not cheap
+       anymore).
+       (grub_util_biosdisk_fini): Free malloced buffers referenced by map[].
+       (make_device_name): Remove assumption of BIOS-like drive names.
+
+2008-05-30  Pavel Roskin  <proski@gnu.org>
+
+       * conf/i386-efi.rmk (normal/execute.c_DEPENDENCIES): Remove, as
+       compiling execute.c doesn't need grub_script.tab.h anymore.
+       (normal/command.c_DEPENDENCIES): Likewise.
+       (normal/function.c_DEPENDENCIES): Likewise.
+       * conf/i386-ieee1275.rmk: Likewise.
+       * conf/i386-linuxbios.rmk: Likewise.
+       * conf/i386-pc.rmk: Likewise.
+       * conf/powerpc-ieee1275.rmk: Likewise.
+       * conf/sparc64-ieee1275.rmk: Likewise.
+
+2008-05-29  Pavel Roskin  <proski@gnu.org>
+
+       * disk/lvm.c (grub_lvm_scan_device): Check for the buffer end
+       when scanning metadata for volume group name.
+
+       * include/grub/script.h: Don't include grub_script.tab.h.  It's
+       a generated file, which may only be included from the files with
+       DEPENDENCIES rules in the makefile.  Don't use typedef YYSTYPE,
+       use union YYSTYPE, as the later allows forward declaration.
+       * normal/lexer.c: Don't use typedef YYSTYPE, use union YYSTYPE.
+
+2008-05-29  Robert Millan  <rmh@aybabtu.com>
+
+       * term/i386/pc/at_keyboard.c: Include `grub/machine/machine.h'.
+       (OLPC_UP, OLPC_DOWN, OLPC_LEFT, OLPC_RIGHT): New macros.
+       [GRUB_MACHINE_IEEE1275] (keyboard_map): Add OLPC scan codes
+       (grub_console_checkkey): Add grub_dprintf() call to report unknown
+       scan codes.
+
+2008-05-29  Robert Millan  <rmh@aybabtu.com>
+
+       * term/i386/pc/at_keyboard.c (grub_console_checkkey): Add support for
+       control key combinations.
+
+2008-05-29  Robert Millan  <rmh@aybabtu.com>
+
+       * util/powerpc/ieee1275/grub-install.in: Move from here ...
+       * util/ieee1275/grub-install.in: ... to here.
+       * powerpc-ieee1275.rmk (grub_install_SOURCES): Update location.
+       * i386-ieee1275.rmk (sbin_SCRIPTS): New variable.
+       (grub_install_SOURCES): Likewise.
+
+2008-05-29  Robert Millan  <rmh@aybabtu.com>
+
+       * fs/affs.c: Update copyright year.
+       * fs/ext2.c: Likewise.
+       * fs/fshelp.c: Likewise.
+       * fs/hfsplus.c: Likewise.
+       * fs/ntfs.c: Likewise.
+       * fs/xfs.c: Likewise.
+       * include/grub/fshelp.h: Likewise.
+       * util/grub-mkdevicemap.c: Likewise.
+
+2008-05-28  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub.in: Allow chmod call to fail, since /boot/grub/
+       might need to be fatfs to support some firmware implementations
+       (e.g. OFW or EFI).
+
+2008-05-28  Robert Millan  <rmh@aybabtu.com>
+
+       * util/biosdisk.c (linux_find_partition, get_os_disk): Handle MMC
+       devices.
+       * util/grub-mkdevicemap.c (get_mmc_disk_name)
+       (make_device_map): Likewise.
+
+2008-05-20  Bean  <bean123ch@gmail.com>
+
+       * fs/fshelp.c (grub_fshelp_map_block): New function.
+       (grub_fshelp_find_file): Use 64-bit type for pos and block address.
+       Use `>>' and `&' operator to avoid 64-bit divide and modulo.
+
+       * include/grub/fshelp.h (grub_fshelp_journal_type): New enum.
+       (GRUB_FSHELP_JOURNAL_UNUSED_MAPPING): New macro.
+       (grub_fshelp_journal): New structure.
+       (grub_fshelp_map_block): New function prototype.
+       (grub_fshelp_read_file): Use grub_disk_addr_t as block type.
+       (grub_fshelp_map_block): Likewise.
+
+       * fs/ext2.c (EXT3_FEATURE_COMPAT_HAS_JOURNAL): New macro.
+       (EXT3_JOURNAL_MAGIC_NUMBER): Likewise.
+       (EXT3_JOURNAL_DESCRIPTOR_BLOCK): Likewise.
+       (EXT3_JOURNAL_COMMIT_BLOCK): Likewise.
+       (EXT3_JOURNAL_SUPERBLOCK_V1): Likewise.
+       (EXT3_JOURNAL_SUPERBLOCK_V2): Likewise.
+       (EXT3_JOURNAL_REVOKE_BLOCK): Likewise.
+       (EXT3_JOURNAL_FLAG_ESCAPE): Likewise.
+       (EXT3_JOURNAL_FLAG_SAME_UUID): Likewise.
+       (EXT3_JOURNAL_FLAG_DELETED): Likewise.
+       (EXT3_JOURNAL_FLAG_LAST_TAG): Likewise.
+       (grub_ext2_sblock): New members for journal support.
+       (grub_ext3_journal_header): New structure.
+       (grub_ext3_journal_revoke_header): Likewise.
+       (grub_ext3_journal_block_tag): Likewise.
+       (grub_ext3_journal_sblock): Likewise.
+       (grub_fshelp_node): New members logfile and journal.
+       (grub_ext2_read_block): Change block type to grub_disk_addr_t. Use
+       grub_fshelp_map_block to get real block number.
+       (grub_ext2_blockgroup): Use grub_fshelp_map_block to get real block
+       number.
+       (grub_ext2_read_inode): Likewise.
+       (grub_ext3_get_journal): New function.
+       (grub_read_inode): Initialize journal using grub_ext3_get_journal.
+       (grub_ext2_close): Release memory used by journal.
+
+       * fs/reiserfs.c (REISERFS_MAGIC_STRING): Changed to "ReIsEr".
+       (REISERFS_MAGIC_DESC_BLOCK): New macro.
+       (grub_reiserfs_transaction_header): Renamed to
+       grub_reiserfs_description_block, replace field data with real_blocks.
+       (grub_reiserfs_commit_block): New structure.
+       (grub_reiserfs_data): New member journal.
+       (grub_reiserfs_get_item): Use grub_fshelp_map_block to get real block
+       number.
+       (grub_reiserfs_read_symlink): Likewise.
+       (grub_reiserfs_iterate_dir): Likewise.
+       (grub_reiserfs_open): Likewise.
+       (grub_reiserfs_read): Likewise.
+       (grub_reiserfs_get_journal): New function.
+       (grub_reiserfs_mount): Use "ReIsEr" as super block magic, as there are
+       three varieties ReIsErFs, ReIsEr2Fs and ReIsEr3Fs. Initialize journal
+       using grub_reiserfs_get_journal.
+       (grub_reiserfs_close): Release memory used by journal.
+
+       * fs/affs.c (grub_affs_read_block): Change block type to
+       grub_disk_addr_t. Use grub_divmod64 to do 64-bit division.
+
+       * fs/afs.c (grub_afs_read_block): Change block type to grub_disk_addr_t.
+
+       * fs/hfsplus.c (grub_hfsplus_read_block): Likewise.
+
+       * fs/ntfs.c (grub_ntfs_read_block): Likewise.
+
+       * fs/udf.c (grub_udf_read_block): Change block type to
+       grub_disk_addr_t. Use type cast to avoid warning.
+
+       * fs/xfs.c (grub_xfs_read_block): Likewise.
+
+2008-05-16  Christian Franke  <franke@computer.org>
+
+       * commands/cat.c (grub_cmd_cat): Remove non-ESC keys from keyboard queue
+       to ensure that break with ESC will always work.
+       * commands/sleep.c (grub_interruptible_millisleep): Likewise.
+       Remove ESC from keyboard queue.
+
+2008-05-16  Christian Franke  <franke@computer.org>
+
+       * util/biosdisk.c: [__CYGWIN__] Add includes.
+       (grub_util_biosdisk_open): Use Linux code also for Cygwin.
+       (get_os_disk): Move variable declarations to OS specific
+       parts to avoid warning.
+       [__GNU__] (get_os_disk): Fix /dev/sdXsN case.
+       [__CYGWIN__] (get_os_disk): Add Cygwin /dev/sdXN device names.
+       (grub_util_biosdisk_get_grub_dev): Use Linux code also for
+       Cygwin.
+       * util/getroot.c: [__CYGWIN__] Add includes.
+       (strip_extra_slashes): Fix "/" case.
+       [__CYGWIN__] (get_win32_path): New function.
+       [__CYGWIN__] (grub_get_prefix): Add conversion to win32 path.
+       [__CYGWIN__] (find_root_device): Disable.
+       [__CYGWIN__] (get_bootsec_serial): New function.
+       [__CYGWIN__] (find_cygwin_root_device): Likewise.
+       [__linux__] (grub_guess_root_device): Add early returns to simplify
+       structure.
+       [__CYGWIN__] (grub_guess_root_device): Call find_cygwin_root_device.
+       [__linux__] (grub_util_get_dev_abstraction): Enable LVM and RAID
+       check for Linux only.
+
+2008-05-15  Bean  <bean123ch@gmail.com>
+
+       * kern/i386/pc/startup.S (grub_console_getkey): Workaround for the
+       keyboard hang problem in apple's intel mac.
+
+2008-05-09  Robert Millan  <rmh@aybabtu.com>
+
+       * util/biosdisk.c (linux_find_partition, get_os_disk): Handle Virtio
+       devices.
+       * util/grub-mkdevicemap.c (get_virtio_disk_name)
+       (make_device_map): Likewise.
+       Reported by Aurelien Jarno <aurel32@debian.org>
+
+2008-05-07  Ian Campbell  <ijc@hellion.org.uk>
+
+       * util/biosdisk.c (get_os_disk): Recognise xvd type disks.
+       * util/grub-mkdevicemap.c (get_xvd_disk_name): New function.
+       (make_device_map): Output entries for xvd type disks.
+
+2008-05-07  Robert Millan  <rmh@aybabtu.com>
+
+       * util/biosdisk.c (linux_find_partition, get_os_disk): Handle CCISS
+       devices.
+       * util/grub-mkdevicemap.c (get_cciss_disk_name)
+       (make_device_map): Likewise.
+       Reported by Roland Dreier <rdreier@cisco.com>
+
+2008-05-07  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/lvm.c (grub_lvm_scan_device): Detect errors in an additional
+       grub_strstr() call.  Correct a few mistakes in failure path handling.
+
+2008-05-06  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub_lib.in (make_system_path_relative_to_its_root):
+       Do not print a trailing slash (therefore, the root directory is an
+       empty string).
+       (convert_system_path_to_grub_path): Do not remove trailing slash
+       from make_system_path_relative_to_its_root() output.
+
+       * util/i386/pc/grub-install.in: Add trailing slash to output from
+       make_system_path_relative_to_its_root().
+
+2008-05-06  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub-fstest.c (grub_refresh): Call `fflush (stdout)'.  This
+       ensures that output lines aren't intermangled with those sent to
+       stderr (via grub_util_info()).
+       * util/grub-probe.c (grub_refresh): Likewise.
+       * util/i386/pc/grub-setup.c (grub_refresh): Likewise.
+
+2008-05-05  Christian Franke  <franke@computer.org>
+
+       * util/grub-mkdevicemap.c (get_floppy_disk_name) [__CYGWIN__]:
+       Add Cygwin device names.
+       (get_ide_disk_name) [__CYGWIN__]: Likewise.
+       (get_scsi_disk_name) [__CYGWIN__]: Likewise.
+       (check_device): Return error instead of success on empty name.
+       (make_device_map): Move label inside linux specific code to
+       prevent compiler warning.
+
+2008-04-30  Robert Millan  <rmh@aybabtu.com>
+
+       Based on patch from Fabian Greffrath <greffrath@leat.rub.de>
+       * util/grub.d/10_linux.in: Add ${GRUB_CMDLINE_LINUX_DEFAULT} to the
+       first boot option.
+       * util/update-grub.in: Export GRUB_CMDLINE_LINUX_DEFAULT.
+
+2008-04-29  Robert Millan  <rmh@aybabtu.com>
+
+       * docs/grub.cfg: New file (example GRUB configuration).
+
+2008-04-26  Robert Millan  <rmh@aybabtu.com>
+
+       * DISTLIST: Sort (sort -u < DISTLIST | sponge DISTLIST).  Add
+       `loader/i386/ieee1275/linux.c', `loader/i386/ieee1275/linux_normal.c'
+       and `disk/ieee1275/nand.c'.
+
+2008-04-25  Bean  <bean123ch@gmail.com>
+
+       * Makefile.in (RMKFILES): Add missing arch i386-ieee1275 and
+       i386-linuxbios.
+
+       * commands/hexdump.c (grub_cmd_hexdump): Support dumping of device,
+       change the buffer size to 4096 for cdrom device.
+
+       * conf/i386-ieee1275.rmk (pkglib_MODULES): Add _linux.mod, linux.mod
+       and nand.mod.
+       (_linux_mod_SOURCES): New variable.
+       (_linux_mod_CFLAGS): Likewise.
+       (_linux_mod_LDFLAGS): Likewise.
+       (linux_mod_SOURCES): Likewise.
+       (linux_mod_CFLAGS): Likewise.
+       (linux_mod_LDFLAGS): Likewise.
+       (nand_mod_SOURCES): Likewise.
+       (nand_mod_CFLAGS): Likewise.
+       (nand_mod_LDFLAGS): Likewise.
+
+       * disk/ieee1275/ofdisk.c (grub_ofdisk_open): Return
+       GRUB_ERR_UNKNOWN_DEVICE instead of GRUB_ERR_BAD_DEVICE if no device
+       type property. (nand device in olpc don't have this property)
+
+       * include/grub/disk.h (grub_disk_dev_id): New macro
+       GRUB_DISK_DEVICE_NAND_ID.
+
+       * include/grub/i386/ieee1275/loader.h (grub_rescue_cmd_linux): New
+       function prototype.
+       (grub_rescue_cmd_initrd): Likewise.
+
+       * include/grub/i386/linux.h (GRUB_LINUX_OFW_SIGNATURE): New macro.
+       (linux_kernel_params): Add new member ofw_signature, ofw_num_items,
+       ofw_cif_handler and ofw_idt, adjust padding number.
+
+       * include/grub/i386/pc/memory.h (grub_upper_mem): Export it if
+       GRUB_MACHINE_IEEE1275 is defined.
+
+       * include/grub/ieee1275/ieee1275.h (grub_available_iterate):
+       Use NESTED_FUNC_ATTR attribute on the hook parameter.
+
+       * kern/powerpc/ieee1275/init.c (grub_claim_heap): Use NESTED_FUNC_ATTR
+       on nested function heap_init.
+       (grub_upper_mem): New variable for i386-ieee1275.
+       (grub_get_extended_memory): New function for i386-ieee1275.
+       (grub_machine_init): Call grub_get_extended_memory for i386-ieee1275.
+
+       * kern/powerpc/ieee1275/openfw.c (grub_available_iterate): Use
+       NESTED_FUNC_ATTR on the hook parameter. Don't quit if no device type
+       property.
+
+       * loader/i386/ieee1275/linux.c: New file.
+
+       * loader/i386/ieee1275/linux_normal.c: New file.
+
+       * disk/ieee1275/nand.c: New file.
+
+2008-04-18  Thomas Schwinge  <tschwinge@gnu.org>
+
+       * util/i386/pc/grub-mkrescue.in (grub_mkimage): Don't overwrite correct
+       value.
+       * util/powerpc/ieee1275/grub-mkrescue.in (grub_mkimage): Likewise.
+
+2008-04-18  Robert Millan  <rmh@aybabtu.com>
+
+       Restructures early code path on ieee1275 to unify grub_main() as
+       the first C function that is executed in every platform.
+
+       * include/grub/ieee1275/ieee1275.h (grub_ieee1275_init): New prototype.
+       * kern/i386/ieee1275/startup.S (_start): Jump to grub_main() instead of
+       cmain().
+       * kern/powerpc/ieee1275/crt0.S (_start): Likewise.
+       * kern/ieee1275/cmain.c (cmain): Rename to ...
+       * kern/ieee1275/cmain.c (grub_ieee1275_init): ... this.
+       * kern/ieee1275/init.c (grub_machine_init): Call grub_ieee1275_init()
+       at the beginning.
+
+2008-04-18  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub.in: Fix syntax error when setting
+       `GRUB_PRELOAD_MODULES'.
+       Reported by Stephane Chazelas <stephane@artesyncp.com>
+
+2008-04-17  Lubomir Kundrak  <lkundrak@redhat.com>
+
+       * aclocal.m4 (grub_PROG_OBJCOPY_ABSOLUTE): take only .text
+       section into account, newer toolchains generate unique build ids
+       * configure.ac: remove the test for --build-id=none acceptance,
+       we want build ids to be preserved
+       * genmk.rb: add -R .note.gnu.build-id to objcopy, so build id
+       far from other sections don't cause the raw binary images grow
+       size
+
+2008-04-15  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/lvm.c: Update copyright year.
+       * kern/misc.c: Likewise.
+
+2008-04-14  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * disk/lvm.c (grub_lvm_scan_device): Add forgotten failure path when
+       there is no memory left for physical volume name.
+
+2008-04-14  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * disk/lvm.c (grub_lvm_scan_device): Fix logical volume's physical
+       volume name mapping to support bigger than 9 character names properly.
+
+2008-04-13  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/i386/pc/biosdisk.c (grub_biosdisk_rw): Fix CHS limit check,
+       as per http://www.allensmith.net/Storage/HDDlimit/Int13h.htm
+
+2008-04-13  Christian Franke  <franke@computer.org>
+
+       * util/i386/pc/grub-mkrescue.in: Add --emulation=floppy
+       to create a floppy emulation boot CD when non emulation mode
+       does not work.
+       Enable Joliet CD filesystem extension.
+
+2008-04-13  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/misc.c (grub_strncat): Fix off-by-one error.
+       Reported by Zhang Huan <zhanghuan@nrchpc.ac.cn>
+
+       * kern/env.c (grub_env_context_close): Clear current context, not
+       previous one.
+       Patch from Zhang Huan <zhanghuan@nrchpc.ac.cn>
+
+       * kern/misc.c (grub_strcat): Minor speed optimization (same code size).
+
+2008-04-13  Robert Millan  <rmh@aybabtu.com>
+
+       Improve robustness when handling LVM.
+
+       * disk/lvm.c (grub_lvm_getvalue): Return 0 when `*p' is NULL
+       (and leave `*p' unmodified).
+       (grub_lvm_iterate): Don't assume `vg->lvs != NULL' when iterating
+       through it.
+       (grub_lvm_memberlist): Don't assume `lv->vg->pvs != NULL' when
+       iterating through it.
+       (grub_lvm_open): Don't assume `vg->lvs != NULL' when iterating
+       through it.
+       (grub_lvm_scan_device): Check the return value (and fail gracefully
+       when due) on each grub_lvm_getvalue() or grub_strstr() call.
+       Don't assume `vg->pvs != NULL' when iterating through it.
+
+2008-04-13  Robert Millan  <rmh@aybabtu.com>
+
+       * gendistlist.sh (EXTRA_DISTFILES): Add `genpartmaplist.sh'.
+       * genmk.rb (partmap): New variable.
+       (CLEANFILES, PARTMAPFILES): Add #{partmap}.
+       (#{partmap}): New target rule.
+       * genpartmaplist.sh: New file.
+       * Makefile.in (pkglib_DATA): Add partmap.lst.
+       (partmap.lst): New target rule.
+       * util/i386/pc/grub-mkrescue.in: Generate grub.cfg that loads needed
+       modules (including all partition maps), instead of preloading them.
+
+2007-04-13  Fabian Greffrath  <fabian.greffrath@web.de>
+
+       * util/grub.d/30_os-prober.in: New script. Use `os-prober' and
+       `linux-boot-prober' (if installed) to detect other operating
+       systems which are installed on the computer and add them to
+       the boot menu.
+       * conf/common.rmk: Build and install 30_os-prober.
+
+2008-04-12  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/powerpc/ieee1275/init.c: Move from here ...
+       * kern/ieee1275/init.c: ... to here.  Update all users.
+
+       * kern/powerpc/ieee1275/cmain.c: Move from here ...
+       * kern/ieee1275/cmain.c: ... to here.  Update all users.
+
+       * kern/powerpc/ieee1275/openfw.c: Move from here ...
+       * kern/ieee1275/openfw.c: ... to here.  Update all users.
+
+       * loader/powerpc/ieee1275/multiboot2.c: Move from here ...
+       * loader/ieee1275/multiboot2.c: ... to here.  Update all users.
+
+2008-04-10  Pavel Roskin  <proski@gnu.org>
+
+       * configure.ac: Always use "_cv_" in cache variables for
+       compatibility with Autoconf 2.62.
+
+2008-04-07  Robert Millan  <rmh@aybabtu.com>
+
+       Revert grub/machine/init.h addition by Pavel (since it breaks on
+       i386-ieee1275 and others):
+       * util/i386/pc/misc.c: Remove grub/machine/init.h.
+       * util/powerpc/ieee1275/misc.c: Likewise.
+
+2008-04-07  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub-probe.c (probe): Improve error message.
+
+2008-04-07  Robert Millan  <rmh@aybabtu.com>
+
+       * util/biosdisk.c (read_device_map): Skip devices that don't exist
+       (this prevents the presence of a bogus entry from ruining the whole
+       thing).
+
+2008-04-06  Pavel Roskin  <proski@gnu.org>
+
+       * util/biosdisk.c: Include grub/util/biosdisk.h.
+       * util/grub-fstest.c (execute_command): Make static.
+       * util/grub-mkdevicemap.c (check_device): Likewise.
+       * util/i386/pc/misc.c: Include grub/machine/init.h.
+       * util/powerpc/ieee1275/misc.c: Likewise.
+       * util/lvm.c: Include grub/util/lvm.h.
+       * util/misc.c: Include grub/kernel.h, grub/misc.h and
+       grub/cache.h.
+       * util/raid.c: Include grub/util/raid.h.
+       (grub_util_getdiskname): Make static.
+
+       * util/grub-emu.c (main): Remove calls to grub_hostfs_init() and
+       grub_hostfs_fini(), as they are called from grub_init_all() and
+       grub_fini_all() respectively.  This fixes an infinite loop in
+       grub-fstest due to double registration of hostfs.
+       Reported by Christian Franke <Christian.Franke@t-online.de>
+
+2008-04-05  Pavel Roskin  <proski@gnu.org>
+
+       * bus/pci.c (grub_pci_iterate): For multifunction devices, probe
+       all 8 functions.  Otherwise, probe function 0 only.
+
+2008-04-04  Pavel Roskin  <proski@gnu.org>
+
+       * commands/lspci.c (grub_lspci_iter): Print the bus number
+       correctly.
+
+       * commands/lspci.c (grub_pci_classes): Fix typos.
+       (grub_lspci_iter): Don't print func twice.  Print vendor ID
+       before device ID, as it's normally done.
+
+       * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_find_options):
+       Fix signedness warnings.
+       * kern/powerpc/ieee1275/openfw.c (grub_available_iterate):
+       Likewise.
+       * util/ieee1275/get_disk_name.c: Include config.h so that
+       _GNU_SOURCE is defined and getline() is declared.  Mark an
+       unused argument as such.  Fix a signedness warning.
+
+2008-04-02  Pavel Roskin  <proski@gnu.org>
+
+       * genkernsyms.sh.in: Use more robust assignments for CC and
+       srcdir.  Quote srcdir.
+       * gensymlist.sh.in: Likewise.  Assert at the compile time that
+       the symbol table is not empty.
+
+       * disk/raid.c (grub_raid_memberlist): Fix a signedness warning.
+       * fs/cpio.c (grub_cpio_read): Likewise.
+
+2008-04-01  Pavel Roskin  <proski@gnu.org>
+
+       * disk/ata.c (grub_ata_open): Don't lose precision in disk->id.
+       * disk/host.c (grub_host_open): Likewise.
+       * disk/loopback.c (grub_loopback_open): Likewise.
+       * disk/memdisk.c (grub_memdisk_open): Use a string pointer for
+       disk->id as in disk/host.c, not a multi-character constant.
+
+       * util/grub-fstest.c (cmd_cmp): Use fseeko(), not fseek().  The
+       later is obsolete, potentially dangerous and sets a bad example.
+       * util/i386/efi/grub-mkimage.c (make_header): Likewise.
+       * util/misc.c (grub_util_get_image_size): Likewise.
+
+       * disk/loopback.c (options): Improve help for "--partitions".
+
+       * normal/arg.c (grub_arg_show_help): Fix spacing of the long
+       options to align them with the short options, e.g. "echo -e".
+
+2008-03-31  Bean  <bean123ch@gmail.com>
+
+       * video/reader/png.c (grub_png_data): New member is_16bit and
+       image_data.
+       (grub_png_decode_image_header): Detect 16 bit png image.
+       (grub_png_convert_image): New function to convert 16 bit image to 8 bit.
+       (grub_png_decode_png): Call grub_png_convert_image for 16 bit image.
+       (grub_video_reader_png): Release memory occupied by image_data.
+
+       * fs/ntfs.c (find_attr): Handle non-resident attribute list larger than
+       4096 bytes.
+       (grub_nfs_mount): Skip the test for sector per cluster.
+
+       * include/grub/ntfs.h (MAX_SPC): Removed.
+
+2008-03-31  Bean  <bean123ch@gmail.com>
+
+       * conf/common.rmk (pkgdata_MODULES): Add afs.mod.
+       (grub_probe_SOURCES): Add fs/afs.c.
+       (grub_fstest_SOURCES): Likewise.
+       (afs_mod_SOURCES): New variable.
+       (afs_mod_CFLAGS): Likewise.
+       (afs_mod_LDFLAGS): Likewise.
+
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/afs.c.
+       (grub_emu_SOURCES): Likewise.
+
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+
+       * fs/afs.c: New file.
+
+2008-03-30  Pavel Roskin  <proski@gnu.org>
+
+       * disk/host.c: Include grub/misc.h to fix a warning.
+       * util/hostfs.c: Use GRUB_MOD_INIT and GRUB_MOD_FINI to fix
+       warnings about implicit declarations.
+
+       * fs/udf.c (grub_udf_mount): Fix warning about a shadowing a
+       variable.
+       * include/grub/i386/loader.h: Change declaration of
+       grub_linux_boot() to match what grub_loader_set() expects.
+       * util/getroot.c (grub_guess_root_device): Return const char* to
+       fix a warning.
+       * util/grub-probe.c (probe): Fix a warning about uninitialized
+       abstraction_name variable.
+       * util/i386/get_disk_name.c (grub_util_get_disk_name): Mark
+       second argument as unused to fix a warning.
+
+       * loader/i386/pc/multiboot2.c (grub_mb2_arch_elf64_hook): Add
+       missing grub_error() call.
+
+       * util/update-grub_lib.in: Define datarootdir, since Autoconf
+       2.60 and newer uses it to define datadir.
+
+       * commands/sleep.c: Fix warning about implicit declaration.
+       * disk/memdisk.c: Likewise.
+       * loader/aout.c: Likewise.
+       * loader/i386/bsd_normal.c: Likewise.
+       * util/grub-probe.c: Likewise.
+
+       * commands/i386/cpuid.c (has_longmode): Make static.
+       * disk/i386/pc/biosdisk.c (cd_drive): Likewise.
+       * include/grub/i386/bsd.h (bios_memmap_t): Remove, it's unused.
+
+       * kern/i386/pc/startup.S (real_to_prot): Use %cs prefix to load
+       GDT.  This is more robust, as %ds can change.
+       (grub_biosdisk_rw_int13_extensions): Don't clear %ds before
+       calling real_to_prot().
+       (grub_biosdisk_get_diskinfo_int13_extensions): Likewise.
+
+2008-03-28  Pavel Roskin  <proski@gnu.org>
+
+       * kern/i386/pc/startup.S: Assert that uncompressed functions
+       don't spill beyond GRUB_KERNEL_MACHINE_RAW_SIZE.
+       * kern/i386/pc/lzo1x.S: Remove all .align directives in the
+       code, as they push parts of the code (error handlers) beyond
+       GRUB_KERNEL_MACHINE_RAW_SIZE.  Speed is not as important in this
+       code as correctness and size.
+
+2008-03-28  Pavel Roskin  <proski@gnu.org>
+
+       * kern/i386/pc/startup.S
+       (grub_biosdisk_get_diskinfo_int13_extensions): When converting
+       data block address to the real mode, keep offset minimal.  This
+       works around a bug in AWARD BIOS on old Athlon systems, which
+       makes CD detection hang.
+
+2008-03-26  Pavel Roskin  <proski@gnu.org>
+
+       * normal/color.c (grub_parse_color_name_pair): Make `name' a
+       const.
+       * include/grub/normal.h: Add grub_parse_color_name_pair()
+       declaration.
+
+2008-03-24  Bean  <bean123ch@gmail.com>
+
+       * disk/i386/pc/biosdisk.c (cd_start): Removed.
+       (cd_count): Removed.
+       (cd_drive): New variable.
+       (grub_biosdisk_get_drive): Don't check for (cdN) device.
+       (grub_biosdisk_call_hook): Likewise.
+       (grub_biosdisk_iterate): Change cdrom detection method.
+       (grub_biosdisk_open): Replace cd_start with cd_drive.
+       (GRUB_MOD_INIT): Use grub_biosdisk_get_cdinfo_int13_extension to
+       detect cdrom device.
+
+       * include/grub/i386/pc/biosdisk.h (GRUB_BIOSDISK_MACHINE_CDROM_START):
+       Removed.
+       (GRUB_BIOSDISK_MACHINE_CDROM_END): Removed.
+       (GRUB_BIOSDISK_CDTYPE_NO_EMUL): New macro.
+       (GRUB_BIOSDISK_CDTYPE_1_2_M): Likewise.
+       (GRUB_BIOSDISK_CDTYPE_1_44_M): Likewise.
+       (GRUB_BIOSDISK_CDTYPE_2_88_M): Likewise.
+       (GRUB_BIOSDISK_CDTYPE_HARDDISK): Likewise.
+       (GRUB_BIOSDISK_CDTYPE_MASK): Likewise.
+       (grub_biosdisk_cdrp): New structure.
+       (grub_biosdisk_get_cdinfo_int13_extensions): New function.
+
+       * include/grub/i386/pc/kernel.h (grub_boot_drive): Export this variable.
+
+       * kern/i386/pc/init.c (make_install_device): Don't use (cdN) as root
+       device.
+
+       * kern/i386/pc/startup.S (grub_biosdisk_get_cdinfo_int13_extensions):
+       New function.
+
+2008-03-20  Robert Millan  <rmh@aybabtu.com>
+
+       Remove 2 TiB limit in ata.mod.
+       * disk/ata.c (grub_ata_device): Promote `size' to grub_uint64_t.
+       (grub_ata_dumpinfo): Print sector count with 0x%llx.
+       (grub_ata_identify): Interpret `&info16[100]' as a pointer to
+       grub_uint64_t instead of grub_uint32_t.
+
+2008-03-05  Bean  <bean123ch@gmail.com>
+
+       * loader/i386/pc/multiboot.c (grub_multiboot_get_bootdev): New function.
+       (grub_multiboot): Set boot device.
+
+       * boot/i386/pc/lnxboot.S (real_code_2): Set %dh to 0xFF.
+
+2008-03-02  Bean  <bean123ch@gmail.com>
+
+       * fs/reiserfs.c (grub_reiserfs_read_symlink): Add 0 at the end of
+       symlink_buffer.
+
+2008-03-01  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * DISTLIST: Added docs/fdl.texi, docs/grub.texi, docs/mdate-sh and
+       texinfo.tex.
+
+       * docs/grub.texi: New file. Copied from GRUB Legacy, and slightly
+       modified.
+
+       * docs/fdl.texi: New file.
+
+       * docs/mdate-sh: New file. Copied from gnulib.
+       * docs/texinfo.tex: Likewise.
+
+       * config.guess: Updated from gnulib.
+       * install-sh: Likewise.
+
+2008-02-28  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-linuxbios.rmk (pkglib_MODULES): Add aout.mod.
+       (aout_mod_SOURCES): New variable.
+       (aout_mod_CFLAGS): Likewise.
+       (aout_mod_LDFLAGS): Likewise.
+
+       * conf/i386-ieee1275.rmk: Likewise.
+
+2008-02-28  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub.in: Reorganise terminal validity check.  Accept
+       `ieee1275:console' (OLPC) and `*:gfxterm' as valid too.
+       Based on suggestion by Franklin PIAT.
+
+2008-02-28  Fabian Greffrath  <greffrath@leat.rub.de>
+
+       * include/grub/util/getroot.h (grub_util_check_block_device): Export new
+       function.
+       * util/getroot.c (grub_util_check_block_device): New function that
+       returns the given argument if it is a block device and returns NULL else.
+       * util/grub-probe.c (argument_is_device): New variable.
+       (probe): Promote device_name from a variable to an argument. Receive
+       device_name from grub_util_check_block_device() if path is NULL and from
+       grub_guess_root_device() else. Do not free() device_name anymore.
+       (options): Introduce new parameter '-d, --device'.
+       (main): Add description of the new parameter to the help screen.
+       Rename path variable to argument. Set argument_is_device if the '-d'
+       option is given. Pass argument to probe() depending on
+       argument_is_device.
+
+2008-02-24  Bean  <bean123ch@gmail.com>
+
+       * fs/iso9660.c (GRUB_ISO9660_VOLDESC_BOOT): New macro.
+       (GRUB_ISO9660_VOLDESC_PRIMARY): Likewise.
+       (GRUB_ISO9660_VOLDESC_SUPP): Likewise.
+       (GRUB_ISO9660_VOLDESC_PART): Likewise.
+       (GRUB_ISO9660_VOLDESC_END): Likewise.
+       (grub_iso9660_primary_voldesc): New member escape.
+       (grub_iso9660_data): New member joliet.
+       (grub_iso9660_convert_string): New function.
+       (grub_iso9660_mount): Detect joliet extension.
+       (grub_iso9660_iterate_dir): Convert filename when joliet is detected.
+       (grub_iso9660_iso9660_label): Likewise.
+
+       * conf/common.rmk (pkgdata_MODULES): Add udf.mod.
+       (grub_setup_SOURCES): Add fs/udf.c.
+       (grub_fstest_SOURCES): Likewise.
+       (udf_mod_SOURCES): New variable.
+       (udf_mod_CFLAGS): Likewise.
+       (udf_mod_LDFLAGS): Likewise.
+
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/udf.c.
+       (grub_emu_SOURCES): Likewise.
+
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+
+       * fs/udf.c: New file.
+
+2008-02-24  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-efi.rmk (normal/function.c_DEPENDENCIES)
+       (normal/lexer.c_DEPENDENCIES): New variables.
+       * conf/i386-ieee1275.rmk (normal/function.c_DEPENDENCIES)
+       (normal/lexer.c_DEPENDENCIES): Likewise.
+       * conf/i386-linuxbios.rmk (normal/function.c_DEPENDENCIES)
+       (normal/lexer.c_DEPENDENCIES): Likewise.
+       * conf/i386-pc.rmk (normal/function.c_DEPENDENCIES)
+       (normal/lexer.c_DEPENDENCIES): Likewise.
+       * conf/powerpc-ieee1275.rmk (normal/function.c_DEPENDENCIES)
+       (normal/lexer.c_DEPENDENCIES): Likewise.
+       * conf/sparc64-ieee1275.rmk (normal/function.c_DEPENDENCIES)
+       (normal/lexer.c_DEPENDENCIES): Likewise.
+
+2008-02-23  Robert Millan  <rmh@aybabtu.com>
+
+       * partmap/gpt.c (grub_gpt_magic): Add `0x' qualifier to each member,
+       since they were intended to be in hex.  This didn't break previously
+       because of a bug in gpt_partition_map_iterate() (see below).
+
+       (gpt_partition_map_iterate): Replace `grub_memcmp' with `! grub_memcmp'
+       when checking the validity of GPT header.
+       Remove `partno', since it always provides the same information as `i'.
+
+2008-02-21  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * include/grub/efi/time.h: Fix a wrong comment.
+
+2008-02-19  Pavel Roskin  <proski@gnu.org>
+
+       * kern/rescue.c (grub_enter_rescue_mode): Improve initial
+       message.
+
+2008-02-19  Bean  <bean123ch@gmail.com>
+
+       * conf/i386-pc.rmk (pkglib_MODULES): Add aout.mod _bsd.mod and bsd.mod.
+       (aout_mod_SOURCES): New variable.
+       (aout_mod_CFLAGS): Likewise.
+       (aout_mod_LDFLAGS): Likewise.
+       (_bsd_mod_SOURCES): New variable.
+       (_bsd_mod_CFLAGS): Likewise.
+       (_bsd_mod_LDFLAGS): Likewise.
+       (bsd_mod_SOURCES): New variable.
+       (bsd_mod_CFLAGS): Likewise.
+       (bsd_mod_LDFLAGS): Likewise.
+
+       * include/grub/aout.h: New file.
+
+       * include/grub/i386/loader.h (grub_unix_real_boot): New function.
+
+       * include/grub/i386/bsd.h: New file.
+
+       * include/grub/i386/pc/init.h (grub_get_mmap_entry): Use EXPORT_FUNC
+       to make it public.
+
+       * kern/elf.c (grub_elf32_load): Get the physical address after the hook
+       function is called, so that it's possible to change it inside the hook.
+       (grub_elf64_load): Likewise.
+       (grub_elf_file): Don't close the file if elf header is not found.
+       (grub_elf_close): Close the file if grub_elf_file fails (The new
+       grub_elf_file won't close it).
+       (grub_elf32_size): Use NESTED_FUNC_ATTR for nested function calcsize.
+       (grub_elf64_size): Likewise.
+
+       * kern/i386/loader.S (grub_unix_real_boot): New function.
+
+       * loader/aout.c: New file.
+
+       * loader/i386/bsd.c: New file.
+
+       * loader/i386/bsd_normal.c: New file.
+
+       * loader/i386/pc/multiboot.c (grub_multiboot): Handle a.out format.
+
+       * loader/multiboot2.c (grub_multiboot2): Reset grub_errno so that it
+       can test other formats.
+
+2008-02-19  Robert Millan  <rmh@aybabtu.com>
+
+       * partmap/gpt.c: Include `<grub/gpt_partition.h>'.
+       (grub_gpt_partition_type_empty): Redefine with macro from
+       `<grub/gpt_partition.h>'.
+       (gpt_partition_map_iterate): Adjust partition type comparison.
+
+       Export `entry' as partmap-specific `part.data' struct.
+       (grub_gpt_header, grub_gpt_partentry): Move from here ...
+
+       * include/grub/gpt_partition.h (grub_gpt_header)
+       (grub_gpt_partentry): ... to here (new file).
+
+       * util/i386/pc/grub-setup.c: Include `<grub/gpt_partition.h>'.
+
+       (grub_gpt_partition_type_bios_boot): New const variable, defined
+       with macro from `<grub/gpt_partition.h>'.
+
+       (setup): Replace `first_start' with `embed_region', which keeps
+       track of the embed region (and is partmap-agnostic).
+
+       Replace find_first_partition_start() with find_usable_region(),
+       which finds a usable region for embedding using partmap-specific
+       knowledge (supports PC/MSDOS and GPT).
+
+       Fix all assumptions that the embed region start at sector 1, using
+       `embed_region.start' from now on.  Similarly, use `embed_region.end'
+       rather than `first_start' to calculate available size.
+
+       In grub_util_info() message, replace "into after the MBR" with an
+       indication of the specific sector our embed region starts at.
+
+2008-02-19  Robert Millan  <rmh@aybabtu.com>
+
+       * DISTLIST: Replace `commands/ieee1275/halt.c' and
+       `commands/ieee1275/reboot.c' with `commands/halt.c' and
+       `commands/reboot.c'.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES, reboot_mod_SOURCES)
+       (halt_mod_SOURCES): Likewise.
+       * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES, reboot_mod_SOURCES)
+       (halt_mod_SOURCES): Likewise.
+
+2008-02-17  Christian Franke  <franke@computer.org>
+
+       * commands/cat.c (grub_cmd_cat): Add break on GRUB_TERM_ESC key.
+
+2008-02-17  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-setup.c (setup): In find_first_partition_start(),
+       set `first_start' to 0 for non-PC/MSDOS partition maps.
+
+2008-02-16  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-setup.c (setup): In find_first_partition_start(),
+       do not assume partition map is PC/MSDOS before performing checks that
+       are specific to that layout.
+
+2008-02-13  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Remove
+       `commands/i386/pc/halt.c' and `commands/i386/pc/reboot.c'.
+       * kern/i386/linuxbios/init.c (grub_halt, grub_reboot): Remove stubs.
+
+2008-02-13  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * configure.ac: Only a cosmetic change on the handling of
+       -fno-stack-protector.
+
+2008-02-12  Alexandre Boeglin  <alex@boeglin.org>
+
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Replace
+       commands/i386/pc/halt.c and reboot.c by commands/halt.c and
+       reboot.c.
+       (grub_install_SOURCES): Add halt.mod and reboot.mod.
+       (halt_mod_SOURCES): New variable.
+       (halt_mod_CFLAGS): Likewise.
+       (halt_mod_LDFLAGS): Likewise.
+       (reboot_mod_SOURCES): Likewise.
+       (reboot_mod_CFLAGS): Likewise.
+       (reboot_mod_LDFLAGS): Likewise.
+
+       * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Replace
+       commands/ieee1275/halt.c and reboot.c by commands/halt.c and
+       reboot.c.
+       (halt_mod_SOURCES): Likewise.
+       (reboot_mod_SOURCES): Likewise.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Replace
+       commands/i386/pc/reboot.c by commands/reboot.c.
+       (reboot_mod_SOURCES): Likewise.
+
+       * commands/i386/pc/reboot.c: merge this file ...
+
+       * commands/ieee1275/reboot.c: ... and this file ...
+
+       * commands/reboot.c: ... to this file.
+       Add some precompiler directive to include the correct header for
+       each machine.
+
+       * commands/ieee1275/halt.c: move this file ...
+
+       * commands/halt.c: ... to here.
+       Add some precompiler directive to include the correct header for
+       each machine.
+
+       * include/grub/efi/efi.h (grub_reboot): New function declaration.
+       (grub_halt): Likewise.
+
+       * kern/efi/efi.c (grub_reboot): New function.
+       (grub_halt): Likewise.
+
+2008-02-12  Robert Millan  <rmh@aybabtu.com>
+
+       * util/getroot.c (grub_guess_root_device): Inspect /dev/evms before
+       /dev (like it is done for /dev/mapper).  This doesn't provide support
+       for EVMS, but at least it is now easy to identify the problem when it
+       arises.
+
+2008-02-11  Robert Millan  <rmh@aybabtu.com>
+
+       * util/biosdisk.c (grub_util_biosdisk_open, linux_find_partition)
+       (grub_util_biosdisk_get_grub_dev): Check open() exit status by
+       comparing it with -1, not 0.
+
+2008-02-10  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Add `disk/raid.c' and
+       `disk/lvm.c'.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Likewise.
+
+       * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Move `disk/raid.c' and
+       `disk/lvm.c' to the end of the list.
+       * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise.
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise.
+
+2008-02-10  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/main.c (grub_load_normal_mode): Do not reset `grub_errno'.  Call
+       grub_print_error() instead.  This will let user know why we're entering
+       rescue mode.
+       Based on suggestions from Sam Morris.
+
+2008-02-10  Alexandre Boeglin  <alex@boeglin.org>
+
+       * normal/arg.c (grub_arg_parse): If one of the args is "--", call add_arg()
+       on remaining N args, instead of "--" arg N times.
+
+2008-02-09  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * font/manager.c (unknown_glyph): Added variable for unknown glyph.
+       (fill_with_default_glyph): Changed to use unknown_glyph for fill
+       pattern for unknown glyphs.
+
+2008-02-09  Robert Millan  <rmh@aybabtu.com>
+
+       * configure.ac: Probe for `help2man'.
+       * Makefile.in (builddir): New variable.
+       (HELP2MAN): Likewise.  Set to `true' when @HELP2MAN@ doesn't provide it,
+       or otherwise add a few flags/options to it.
+       (install-local): For every executable utility or script that is
+       installed, invoke $(HELP2MAN) to install a manpage based on --help
+       output.
+
+       * util/i386/pc/grub-install.in: Move down `update-grub_lib' sourcing, so
+       that it doesn't prevent --help from working in build tree.
+
+       * util/i386/pc/grub-mkrescue.in (usage): Replace `grub-devel@gnu.org'
+       with `bug-grub@gnu.org'.
+       * util/powerpc/ieee1275/grub-mkrescue.in (usage): Likewise.
+       * util/update-grub.in (usage): New function.
+       Implement proper argument check, with support for --help and --version
+       (as well as existing -y).
+
+2008-02-09  Christian Franke  <franke@computer.org>
+
+       * commands/cat.c (grub_cmd_cat): Print '\r' as hex to
+       avoid overwriting previous output.
+       * kern/rescue.c (grub_rescue_cmd_cat): Likewise.
+
+2008-02-09  Robert Millan  <rmh@aybabtu.com>
+
+       * normal/menu.c (run_menu): If timeout is set to zero, don't bother
+       drawing the menu.
+
+2008-02-09  Robert Millan  <rmh@aybabtu.com>
+
+       * commands/sleep.c: New file.
+       * conf/common.rmk (pkglib_MODULES): Add `commands/sleep.c'.
+       (sleep_mod_SOURCES): New variable.
+       (sleep_mod_CFLAGS): Likewise.
+       (sleep_mod_LDFLAGS): Likewise.
+
+2008-02-09  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/raid.c (grub_raid_scan_device): Add a pair of sanity checks for
+       situations in which we can deduce the RAID size and the superblock
+       doesn't match it.
+
+2008-02-09  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/lvm.c [GRUB_UTIL] (grub_lvm_memberlist): New function.  Construct
+       and return a grub_diskmemberlist_t composed of LVM physical volumes.
+       [GRUB_UTIL] (grub_lvm_dev): Add `memberlist' member.
+
+       * disk/raid.c [GRUB_UTIL] (grub_raid_memberlist): New function.  Construct
+       and return a grub_diskmemberlist_t composed of physical array members.
+       [GRUB_UTIL] (grub_raid_dev): Add `memberlist' member.
+
+       * include/grub/disk.h [GRUB_UTIL] (grub_disk_memberlist): New struct
+       prototype.
+       [GRUB_UTIL] (struct grub_disk_dev): Add `memberlist' function pointer.
+       [GRUB_UTIL] (struct grub_disk_memberlist): New struct declaration.
+       [GRUB_UTIL] (grub_disk_memberlist_t): New typedef.
+
+       * util/grub-probe.c (probe): Move partmap probing code from here ...
+       (probe_partmap): ... to here.
+       (probe): Use probe_partmap() once for the disk we're probing, and
+       additionally, when such disk contains a memberlist() struct member,
+       once for each disk that is contained in the structure returned by
+       memberlist().
+
+2008-02-09  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub-probe.c (main): When `verbosity > 1', set `debug'
+       environment variable to 'all' in order to obtain debug output from
+       non-util/ code.
+       * util/i386/pc/grub-setup.c (main): Likewise.
+
+2008-02-08  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/raid.c (grub_raid_scan_device): Check for
+       `array->device[sb.this_disk.number]' rather than for
+       `array->device[sb.this_disk.number]->name', since the latter is not
+       guaranteed to be accessible.
+
+2008-02-08  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/raid.c: Update copyright.
+       * fs/cpio.c: Likewise.
+       * include/grub/raid.h: Likewise.
+       * loader/i386/pc/multiboot.c: Likewise.
+       * util/hostfs.c: Likewise.
+
+2008-02-08  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/raid.h (struct grub_raid_array): Change type of `device'
+       to a grub_disk_t array.
+       * disk/raid.c (grub_raid_read): Replace `device[x].disk' accesses with
+       `device[x]'.
+       (grub_raid_scan_device): Replace `device[x].name' accesses with
+       `device[x]->name'.  Simplify initialization of `array->device[x]'.
+
+2008-02-08  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/raid.c (grub_raid_open, grub_raid_scan_device): Add a few
+       grub_dprintf() calls.
+       * kern/disk.c (grub_disk_read): Include grub_errmsg in out of range
+       error message.
+
+2008-02-07  Christian Franke  <franke@computer.org>
+
+       * util/hostfs.c (grub_hostfs_open): Use fseeko and ftello
+       instead of fseek and ftell to support large files.
+       (grub_hostfs_read): Likewise.
+
+2008-02-07  Robert Millan  <rmh@aybabtu.com>
+
+       Patch from Jeroen Dekkers.
+       * disk/raid.c (grub_raid_scan_device): Reset `grub_errno' on disk
+       failure, since successfully reading all array members might not be
+       required.
+
+2008-02-06  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub-probe.c (probe): Simplify partmap probing (with the
+       assumption that the first word up to the underscore equals to
+       the module name).
+
+2008-02-06  Christian Franke  <franke@computer.org>
+
+       * fs/cpio.c (grub_cpio_find_file): Return GRUB_ERR_NONE
+       (and set *ofs = 0) instead of GRUB_ERR_FILE_NOT_FOUND on
+       last block of a cpio or tar stream.
+       Check for "TRAILER!!!" instead of any empty data
+       block to detect last block of a cpio stream.
+       (grub_cpio_dir): Fix constness of variable np.
+       (grub_cpio_open): Return GRUB_ERR_FILE_NOT_FOUND if
+       cpio or tar trailer is detected.  This fixes a crash
+       on open of a non existing file.
+
+2008-02-05  Bean  <bean123ch@gmail.com>
+
+       * loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): Get physical
+       address of entry.
+       (grub_multiboot_load_elf64): Likewise.
+       (grub_multiboot): Initialize mbi structure.
+
+       * util/grub-fstest.c: Don't include unused header file script.h.
+
+       * conf/common.rmk (grub-fstest.c_DEPENDENCIES): Move to the beginning
+       of file.
+       (grub_fstest_SOURCES): Likewise.
+
+2008-02-05  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/term.h (GRUB_TERM_LEFT, GRUB_TERM_RIGHT)
+       (GRUB_TERM_UP, GRUB_TERM_DOWN, GRUB_TERM_HOME, GRUB_TERM_END)
+       (GRUB_TERM_DC, GRUB_TERM_PPAGE, GRUB_TERM_NPAGE, GRUB_TERM_ESC)
+       (GRUB_TERM_TAB, GRUB_TERM_BACKSPACE): New macros.
+
+       * kern/i386/pc/startup.S: Include `<grub/term.h>'.
+       (translation_table): Replace hardcoded values with macros
+       provided by `<grub/term.h>'.
+
+       * term/i386/pc/at_keyboard.c: Include `<grub/term.h>'.
+       (keyboard_map): Correct/add a few values, with macros provided
+       by `<grub/term.h>'.
+       (keyboard_map_shift): Zero values that don't differ from their
+       `keyboard_map' equivalents.
+       (grub_console_checkkey): Optimize KEYBOARD_STATUS_CAPS_LOCK toggling.
+       Discard the second scan code that is always sent by Caps lock.
+       Only use `keyboard_map_shift' when it provides a non-zero value,
+       otherwise fallback to `keyboard_map'.
+
+2008-02-04  Bean  <bean123ch@gmail.com>
+
+       * Makefile.in (enable_grub_fstest): New variable.
+
+       * conf/common.rmk (grub_fstest_init.lst): New rule.
+       (grub_fstest_init.h): Likewise.
+       (grub_fstest_init.c): Likewise.
+       (util/grub-fstest.c_DEPENDENCIES): New variable.
+       (grub_fstest_SOURCES): Likewise.
+
+       * configure.ac (enable_grub_fstest): Check for --enable-grub-fstest.
+
+       * util/grub-fstest.c: New file.
+
+2008-02-03  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Make grub-setup handle a separate root device.
+
+       * util/i386/pc/grub-setup.c (setup): Always open the root device,
+       so that the root device can be compared with the destination
+       device.
+       When embedding the core image, if the root and destination devices
+       are different, set ROOT_DRIVE to ROOT_DEV->DISK->ID. Otherwise, to
+       0xFF.
+       When not embedding, set ROOT_DRIVE to 0xFF.
+
+2008-02-03  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Add support for having a grub directory in a different drive. This
+       is still only the data handling part.
+
+       * kern/i386/pc/startup.S (multiboot_trampoline): Set %dh to 0xFF.
+       (codestart): Save %dh in GRUB_ROOT_DRIVE.
+       (grub_root_drive): New variable.
+
+       * kern/i386/pc/init.c (make_install_device): Use GRUB_ROOT_DRIVE
+       instead of GRUB_BOOT_DRIVE to construct a device name. Set
+       GRUB_ROOT_DRIVE to GRUB_BOOT_DRIVE if it is 0xFF, otherwise use it
+       as it was.
+
+       * include/grub/i386/pc/kernel.h (grub_root_drive): New prototype.
+
+       * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_ROOT_DRIVE): New
+       macro.
+       (GRUB_BOOT_MACHINE_DRIVE_CHECK): Set to 0x4f.
+
+       * boot/i386/pc/pxeboot.S (_start): Set %dh to 0xFF. For now, this
+       is bogus, because PXE booting does not specify any drive
+       correctly.
+
+       * boot/i386/pc/lnxboot.S (reg_edx): Set the second byte to 0xFF. I
+       am not sure if this is really correct.
+
+       * boot/i386/pc/cdboot.S: Set %dh to 0xFF, because the root drive
+       is always identical to the boot drive when booting from a CD.
+
+       * boot/i386/pc/boot.S (MOV_MEM_TO_AL): Removed. Not needed any
+       longer.
+       (root_drive): New variable.
+       (real_start): Unconditionally set %dh to ROOT_DRIVE.
+       (setup_sectors): Push %dx right after popping it, because %dh will
+       be modified later.
+       (copy_buffer): Restore %dx.
+
+2008-02-03  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-mkrescue.in: Rewrite most of image generation to
+       use `cdboot.img' for cdrom images.
+
+2008-02-03  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/00_header.in: Issue scripting commands for GRUB to
+       only setup gfxterm when `font' command has succeeded.
+
+2008-02-03  Robert Millan  <rmh@aybabtu.com>
+
+       * loader/multiboot_loader.c [GRUB_MACHINE_LINUXBIOS]
+       (grub_rescue_cmd_multiboot_loader)
+       (grub_rescue_cmd_module_loader): Enable multiboot1 calls.
+
+2008-02-03  Pavel Roskin  <proski@gnu.org>
+
+       * kern/i386/pc/startup.S (grub_chainloader_real_boot): Pop
+       %edx and %esi from stack only after grub_gate_a20() is called.
+       grub_gate_a20() clobbers %edx.
+
+2008-02-03  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * configure.ac (AC_INIT): Bumped to 1.96.
+
+       * DISTLIST: Added boot/i386/pc/cdboot.S, bus/pci.c,
+       commands/lspci.c,disk/memdisk.c, include/grub/pci.h,
+       include/grub/i386/pc/pci.h, video/readers/jpeg.c, and
+       video/readers/png.c.
+
+2008-02-03  Bean  <bean123ch@gmail.com>
+
+       * conf/i386-pc.rmk (pkglib_IMAGES): Add cdboot.img.
+       (cdboot_img_SOURCES): New variable.
+       (cdboot_img_ASFLAGS): New variable.
+       (cdboot_img_LDFLAGS): New variable.
+
+       * boot/i386/pc/cdboot.S: New file.
+
+       * disk/i386/pc/biosdisk.c (cd_start): New variable.
+       (cd_count): Likewise.
+       (grub_biosdisk_get_drive): Add support for cd device.
+       (grub_biosdisk_call_hook): Likewise.
+       (grub_biosdisk_iterate): Likewise.
+       (grub_biosdisk_open): Likewise.
+       (GRUB_BIOSDISK_CDROM_RETRY_COUNT): New macro.
+       (grub_biosdisk_rw): Support reading from cd device.
+       (GRUB_MOD_INIT): Iterate cd devices.
+
+       * include/grub/i386/pc/biosdisk.h (GRUB_BIOSDISK_FLAG_CDROM): New macro.
+       (GRUB_BIOSDISK_MACHINE_CDROM_START): Likewise.
+       (GRUB_BIOSDISK_MACHINE_CDROM_END): Likewise.
+
+       * kern/i386/pc/init.c (make_install_device): Check for cd device.
+
+2008-02-02  Robert Millan  <rmh@aybabtu.com>
+
+       * commands/read.c: New file.
+       * conf/common.rmk (pkglib_MODULES): Add `commands/read.c'.
+       (read_mod_SOURCES): New variable.
+       (read_mod_CFLAGS): Likewise.
+       (read_mod_LDFLAGS): Likewise.
+
+2008-02-02  Robert Millan  <rmh@aybabtu.com>
+
+       * normal/main.c (grub_normal_execute): Check for `menu->size' when
+       determining whether menu has to be displayed.
+
+2008-02-02  Marco Gerards  <marco@gnu.org>
+
+       * bus/pci.c: New file.
+
+       * include/grub/pci.h: Likewise.
+
+       * include/grub/i386/pc/pci.h: Likewise.
+
+       * commands/lspci.c: Likewise.
+
+       * conf/i386-pc.rmk (pkglib_MODULES): Add `pci.mod' and
+       `lspci.mod'.
+       (pci_mod_SOURCES): New variable.
+       (pci_mod_CFLAGS): Likewise.
+       (pci_mod_LDFLAGS): Likewise.
+       (lspci_mod_SOURCES): Likewise.
+       (lspci_mod_CFLAGS): Likewise.
+       (lspci_mod_LDFLAGS): Likewise.
+
+2008-02-02  Bean  <bean123ch@gmail.com>
+
+       * fs/ufs.c (INODE_BLKSZ): Fix incorrect value.
+       (grub_ufs_get_file_block): Fix indirect block calculation problem.
+
+       * fs/xfs.c (grub_xfs_sblock): New member log2_dirblk.
+       (grub_xfs_btree_node): New structure.
+       (grub_xfs_btree_root): New structure.
+       (grub_xfs_inode): New members nblocks, extsize, nextents and btree.
+       (GRUB_XFS_EXTENT_OFFSET): Use exts instead of inode->data.extents.
+       (GRUB_XFS_EXTENT_BLOCK): Likewise.
+       (GRUB_XFS_EXTENT_SIZE): Likewise.
+       (grub_xfs_read_block): Support btree format type.
+       (grub_xfs_iterate_dir): Use NESTED_FUNC_ATTR in call_hook.
+       Use directory block as basic unit.
+
+       * fs/fshelp.c (grub_fshelp_read_file): Bug fix for sparse block.
+
+       * aclocal.m4 (grub_i386_CHECK_REGPARM_BUG): Define NESTED_FUNC_ATTR as
+       __attribute__ ((__regparm__ (1))).
+
+2008-02-01  Robert Millan  <rmh@aybabtu.com>
+
+       Correct a mistake in previous commit.
+
+       * conf/i386-pc.rmk (normal/execute.c_DEPENDENCIES): Move to the
+       top.
+       (normal/command.c_DEPENDENCIES): New variable.
+
+2008-02-01  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-efi.rmk (normal/execute.c_DEPENDENCIES): Move to the
+       top.
+       (normal/command.c_DEPENDENCIES): New variable.
+       (grub-emu_DEPENDENCIES, normal_mod_DEPENDENCIES): Remove variables.
+       * conf/i386-ieee1275.rmk: Likewise.
+       * conf/i386-linuxbios.rmk: Likewise.
+       * conf/i386-pc.rmk: Likewise.
+       * conf/sparc64-ieee1275.rmk: Likewise.
+       * conf/powerpc-ieee1275.rmk: Likewise.
+       (grub_emu_SOURCES): Add `fs/fshelp.c'.
+
+       * genmk.rb: Add `$(#{src}_DEPENDENCIES)' in targets that require it.
+
+2008-02-01  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/disk.c (grub_disk_read, grub_disk_write): Add grub_dprintf()
+       call at beginning of function.
+
+2008-01-31  Pavel Roskin  <proski@gnu.org>
+
+       * util/powerpc/ieee1275/grub-mkrescue.in: New file.
+       * conf/powerpc-ieee1275.rmk (bin_SCRIPTS): New variable.
+       (grub_mkrescue_SOURCES): Likewise.
+       * DISTLIST: Add util/powerpc/ieee1275/grub-mkrescue.in.
+
+2008-01-30  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-pc.rmk (sbin_UTILITIES): Remove `grub-probe'.
+       (util/grub-probe.c_DEPENDENCIES, grub_probe_SOURCES): Moved from here ...
+       * conf/common.rmk (util/grub-probe.c_DEPENDENCIES)
+       (grub_probe_SOURCES): ... to here.
+
+       * conf/i386-efi.rmk (sbin_UTILITIES): Remove `grub-probe'.
+       (util/grub-probe.c_DEPENDENCIES, grub_probe_SOURCES): Remove.
+       * conf/i386-ieee1275.rmk: Likewise.
+       * conf/i386-linuxbios.rmk: Likewise.
+       * conf/powerpc-ieee1275.rmk: Likewise.
+
+2008-01-30  Tristan Gingold  <gingold@free.fr>
+
+       * kern/rescue.c: Silently accept empty lines.
+
+2008-01-29  Bean  <bean123ch@gmail.com>
+
+       * boot/i386/pc/lnxboot.S (data_start): Code cleanup.
+       (real_code_2): Code cleanup and change comment style.
+       (move_memory): Avoid using 32-bit address mode.
+
+2008-01-29  Bean  <bean123ch@gmail.com>
+
+       * conf/i386-pc.rmk (pkglib_MODULES): Add `png.mod'.
+       (png_mod_SOURCES): New variable.
+       (png_mod_CFLAGS): Likewise.
+       (png_mod_LDFLAGS): Likewise.
+
+       * video/readers/png.c: New file.
+
+2008-01-28  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/i386/linuxbios/kernel.h (GRUB_MOD_GAP): New macro.
+       * kern/powerpc/ieee1275/init.c (grub_arch_modules_addr): Remove
+       `ifndef GRUB_MOD_GAP' hack.
+       * util/elf/grub-mkimage.c (add_segments): Likewise.
+
+2008-01-27  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/powerpc/ieee1275/init.c (grub_arch_modules_addr): Skip
+       `GRUB_MOD_GAP' for platforms in which it's not defined.
+       * util/elf/grub-mkimage.c (add_segments): Likewise.
+
+2008-01-27  Robert Millan  <rmh@aybabtu.com>
+
+       Get grub-emu to build again (including parallel builds).
+
+       * conf/i386-pc.rmk (util/grub-emu.c_DEPENDENCIES): Remove variable.
+       Split into ...
+       (util/grub-emu.c_DEPENDENCIES): ... this, ...
+       (normal/execute.c_DEPENDENCIES): ... this, ...
+       (grub-emu_DEPENDENCIES): ... and this.
+
+       * conf/i386-efi.rmk: Likewise.
+       * conf/i386-linuxbios.rmk: Likewise.
+       * conf/i386-ieee1275.rmk: Likewise.
+       * conf/powerpc-ieee1275.rmk: Likewise.
+       (grub_emu_SOURCES): Remove duplicated `kern/file.c'.
+
+2008-01-27  Robert Millan  <rmh@aybabtu.com>
+
+       * NEWS: Add a few items.
+
+2008-01-27  Robert Millan  <rmh@aybabtu.com>
+
+       Fix parallel builds with grub-emu.  Based on earlier commit for
+       grub-probe and grub-setup.
+
+       * conf/i386-pc.rmk (grub-emu_DEPENDENCIES): Renamed to ...
+       (util/grub-emu.c_DEPENDENCIES): ... this.
+       * conf/i386-efi.rmk (grub-emu_DEPENDENCIES): Renamed to ...
+       (util/grub-emu.c_DEPENDENCIES): ... this.
+       * conf/i386-linuxbios.rmk (grub-emu_DEPENDENCIES): Renamed to ...
+       (util/grub-emu.c_DEPENDENCIES): ... this.
+       * conf/i386-ieee1275.rmk (grub-emu_DEPENDENCIES): Renamed to ...
+       (util/grub-emu.c_DEPENDENCIES): ... this.
+       * conf/powerpc-ieee1275.rmk (grub-emu_DEPENDENCIES): Renamed to ...
+       (util/grub-emu.c_DEPENDENCIES): ... this.
+
+2008-01-27  Pavel Roskin  <proski@gnu.org>
+
+       * include/grub/powerpc/ieee1275/kernel.h: Introduce GRUB_MOD_GAP
+       to create a gap between _end and the modules added to the image
+       with grub-mkrescue.  That fixes "CLAIM failed" on PowerMAC.
+       * kern/powerpc/ieee1275/init.c: Use GRUB_MOD_GAP.
+       * util/elf/grub-mkimage.c (add_segments): Likewise.
+
+2008-01-26  Pavel Roskin  <proski@gnu.org>
+
+       * kern/dl.c (grub_dl_load): Don't abort if prefix is not set,
+       just return an error.
+
+2008-01-26  Bean  <bean123ch@gmail.com>
+
+       * fs/reiserfs.c (grub_fshelp_node): New member next_offset.
+       (grub_reiserfs_get_item): Save offset of the next item.
+       (grub_reiserfs_iterate_dir): Use next_offset to find next item.
+
+2008-01-25  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-pc.rmk (grub_setup_SOURCES, grub_emu_SOURCES): Regroup to
+       make all filesystem sources appear together (possibly fixing omissions
+       while at it).
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise.
+       * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/i386-pc.rmk (grub_probe_SOURCES): Likewise.  Additionally,
+       add `kern/file.c'.
+       * conf/i386-efi.rmk (grub_probe_SOURCES): Likewise.
+       * conf/i386-ieee1275.rmk (grub_probe_SOURCES): Likewise.
+       * conf/i386-linuxbios.rmk (grub_probe_SOURCES): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_probe_SOURCES): Likewise.
+
+       * util/grub-probe.c: Include `<grub/file.h>' and `<sys/stat.h>'.
+       (probe): Add a sanity check to make sure of our ability to read
+       requested files when probing for filesystem type.
+
+       * genmk.rb: Update copyright year (2007).
+
+       * include/grub/fs.h (grub_fat_init, grub_fat_fini, grub_ext2_init)
+       (grub_ext2_fini, grub_ufs_init, grub_ufs_fini, grub_minix_init)
+       (grub_minix_fini, grub_hfs_init, grub_hfs_fini, grub_jfs_init)
+       (grub_jfs_fini, grub_xfs_init, grub_xfs_fini, grub_affs_init)
+       (grub_affs_fini, grub_sfs_init, grub_sfs_fini, grub_iso9660_init)
+       : Remove function prototypes.
+
+2008-01-25  Robert Millan  <rmh@aybabtu.com>
+
+       Revert my previous commits (based on wrong assumption of how grub_errno
+       works).
+
+       * kern/disk.c (grub_disk_open): Stop resetting grub_errno.
+       * kern/file.c (grub_file_open): Likewise.
+
+2008-01-24  Pavel Roskin  <proski@gnu.org>
+
+       * include/grub/ieee1275/ieee1275.h: Introduce flag for firmwares
+       that hang if GRUB tries to setup colors.
+       * term/ieee1275/ofconsole.c (grub_ofconsole_init): Don't set
+       colors for firmwares that don't support it.
+       * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_set_flag):
+       Recognize Open Hack'Ware, set flags to work around its
+       limitations.
+
+2008-01-24  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/file.c (grub_file_open): Do not account previous failures of
+       unrelated functions when grub_errno is checked for.
+       Reported by Oleg Strikov.
+
+2008-01-24  Bean  <bean123ch@gmail.com>
+
+       * fs/ufs.c (GRUB_UFS_VOLNAME_LEN): New macro.
+       (grub_ufs_sblock): New member volume name.
+       (grub_ufs_find_file): Fix string copy bug.
+       (grub_ufs_label): Implement this function properly.
+
+       * fs/hfs.c (grub_hfs_cnid_type): New enum.
+       (grub_hfs_iterate_records): Use the correct file number for extents
+       and catalog file. Fix problem in next index calculation.
+       (grub_hfs_find_node): Replace recursive function call with loop.
+       (grub_hfs_iterate_dir): Replace recursive function call with loop.
+
+2008-01-23  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/i386/ieee1275/loader.h: Include `<grub/types.h>',
+       `<grub/symbol.h>' and `<grub/multiboot.h>'.
+       (grub_multiboot2_real_boot): New function prototype.
+
+       * include/grub/i386/pc/memory.h: Include `<grub/machine/machine.h>'.
+       [!GRUB_MACHINE_IEEE1275] (grub_lower_mem, grub_upper_mem): Disable.
+
+       * kern/i386/ieee1275/init.c (grub_os_area_addr)
+       (grub_os_area_size, grub_lower_mem, grub_upper_mem): Remove variables.
+
+2008-01-23  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/mm.c (grub_mm_init_region): Replace grub_dprintf() call with
+       #ifdef'ed out grub_printf().
+
+2008-01-23  Robert Millan  <rmh@aybabtu.com>
+
+       * term/i386/pc/at_keyboard.c (grub_keyboard_isr): #ifdef out
+       grub_dprintf calls, since they make "debug=all" mode unusable.
+       (grub_console_checkkey): Likewise.
+
+2008-01-23  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-ieee1275.rmk (kernel_elf_SOURCES): Add
+       `term/i386/pc/at_keyboard.c'.
+       (pkglib_MODULES): Add `serial.mod'.
+       (serial_mod_SOURCES): New variable.
+       (serial_mod_CFLAGS): Likewise.
+       (serial_mod_LDFLAGS): Likewise.
+
+       * include/grub/i386/ieee1275/console.h: Add `<grub/symbol.h>'.  Remove
+       `<grub/powerpc/ieee1275/console.h>'.
+       (grub_keyboard_controller_init): New function prototype.
+       (grub_console_checkkey): Likewise.
+       (grub_console_getkey): Likewise.
+
+       * kern/powerpc/ieee1275/init.c (grub_machine_init): Initialize AT
+       keyboard on i386.
+
+       * term/ieee1275/ofconsole.c (grub_ofconsole_term): On i386, use
+       grub_ofconsole_checkkey() and grub_ofconsole_getkey() for input.
+
+2008-01-23  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/i386/pc/init.c (make_install_device): When memdisk image is
+       present, "(memdisk)/boot/grub" becomes the default prefix.
+
+       * util/i386/pc/grub-mkrescue.in: Switch to a minimal core.img plus
+       a memdisk tarball with all the modules.  Add --overlay=DIR option that
+       allows users to overlay additional files into the image.
+
+2008-01-23  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-ieee1275.rmk (kernel_elf_SOURCES): Add `machine/loader.h'
+       and `machine/memory.h'.
+       (pkglib_MODULES): Add `multiboot.mod' and `_multiboot.mod'.
+       (_multiboot_mod_SOURCES): New variable.
+       (_multiboot_mod_CFLAGS): Likewise.
+       (_multiboot_mod_LDFLAGS): Likewise.
+       (multiboot_mod_SOURCES): Likewise.
+       (multiboot_mod_CFLAGS): Likewise.
+       (multiboot_mod_LDFLAGS): Likewise.
+
+       * include/grub/i386/ieee1275/loader.h: New file.
+
+       * include/grub/i386/ieee1275/machine.h: Likewise.
+
+       * include/grub/i386/ieee1275/memory.h: Likewise.
+
+       * include/grub/i386/pc/init.h (grub_os_area_addr): Remove (redundant)
+       variable declaration.
+       (grub_os_area_size): Likewise.
+
+       * kern/i386/ieee1275/init.c (grub_os_area_addr, grub_os_area_size)
+       (grub_lower_mem, grub_upper_mem): New variables.
+       (grub_stop_floppy): New function (just to make
+       grub_multiboot2_real_boot() happy).
+
+       * kern/i386/ieee1275/startup.S: Include `<grub/machine/memory.h>',
+       `<grub/cpu/linux.h>', `<multiboot.h>' and `<multiboot2.h>'.
+       (grub_stop): New function.
+       Include `"../realmode.S"' and `"../loader.S"'.
+
+       * loader/multiboot_loader.c: Include `<grub/machine/machine.h>'.
+       Replace `__i386__' #ifdefs with `GRUB_MACHINE_PCBIOS'.
+
+       * loader/powerpc/ieee1275/multiboot2.c (grub_mb2_arch_boot): On i386,
+       rely on grub_multiboot2_real_boot() for final boot.
+
+2008-01-22  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/ieee1275/ofdisk.c (grub_ofdisk_iterate): When
+       `GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY' flag is set, skip any
+       device that doesn't look like an SD card.
+       * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): Add
+       `GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY' flag.
+       * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_set_flag): Detect
+       OLPC laptop, and set `GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY' when
+       found.
+
+2008-01-22  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/powerpc/ieee1275/init.c (grub_claim_heap): Add sanity check to
+       avoid claiming over our own code.
+
+2008-01-22  Bean  <bean123ch@gmail.com>
+
+       * conf/i386-pc.rmk (pkglib_MODULES): Add `jpeg.mod'.
+       (jpeg_mod_SOURCES): New variable.
+       (jpeg_mod_CFLAGS): Likewise.
+       (jpeg_mod_LDFLAGS): Likewise.
+
+       * video/readers/jpeg.c : New file.
+
+2008-01-22  Bean  <bean123ch@gmail.com>
+
+       * fs/cpio.c (grub_cpio_find_file): Return GRUB_ERR_FILE_NOT_FOUND when
+       there are no more items.
+
+2008-01-21  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/mm.c (grub_mm_init_region): Improve debug message.
+
+2008-01-21  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-pc.rmk (GRUB_MEMORY_MACHINE_LINK_ADDR): New variable.
+       (kernel_img_LDFLAGS): Use `GRUB_MEMORY_MACHINE_LINK_ADDR' as link
+       address.
+       (grub_mkimage_CFLAGS): Propagate `GRUB_MEMORY_MACHINE_LINK_ADDR' as
+       a C macro.
+       * include/grub/i386/pc/memory.h (GRUB_MEMORY_MACHINE_UPPER): New macro.
+       Indicates start of upper memory.
+       * util/i386/pc/grub-mkimage.c: Include `<grub/machine/memory.h>'.
+       (generate_image): Abort when image size is big enough to corrupt
+       upper memory.
+
+       * include/grub/i386/pc/vga.h: Include `<grub/machine/memory.h>'.
+       (GRUB_MEMORY_MACHINE_VGA_ADDR): Alias for `GRUB_MEMORY_MACHINE_UPPER'.
+       * term/i386/pc/vga.c (VGA_MEM): Use `GRUB_MEMORY_MACHINE_VGA_ADDR'
+       instead of hardcoding 0xA0000.
+       * video/i386/pc/vbe.c: Include `<grub/machine/vga.h>'.
+       (grub_vbe_set_video_mode): Use `GRUB_MEMORY_MACHINE_VGA_ADDR'
+       instead of hardcoding 0xA0000.
+
+2008-01-21  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/memdisk.c (memdisk_size): New variable.
+       (grub_memdisk_open): Replace grub_arch_memdisk_size() call with
+       `memdisk_size'.
+       (grub_memdisk_init): Initialize `memdisk_size'.  Reallocate memdisk
+       image to dynamic memory.
+       (grub_memdisk_fini): Replace grub_arch_memdisk_size() call with
+       `memdisk_size'.  Free memdisk block.
+
+2008-01-21  Robert Millan  <rmh@aybabtu.com>
+
+       Fix detection of very small filesystems (like tar).
+
+       * fs/reiserfs.c (grub_reiserfs_mount): When disk is too small to
+       contain a ReiserFS, abort with GRUB_ERR_BAD_FS rather than
+       GRUB_ERR_OUT_OF_RANGE (which made the upper layer think there's
+       a problem with this disk).
+
+2008-01-21  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/i386/pc/biosdisk.c (grub_biosdisk_iterate): Add debug message
+       on grub_biosdisk_rw_standard() error.
+
+2008-01-21  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/ieee1275/ieee1275.h: Add 2008 to Copyright line for
+       recent changes.
+       * kern/elf.c: Likewise.
+       * kern/ieee1275/ieee1275.c: Likewise.
+       * kern/powerpc/ieee1275/openfw.c: Likewise.
+       * term/ieee1275/ofconsole.c: Likewise.
+
+2008-01-21  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/i386/pc/kernel.h: Include `<grub/symbol.h>'.
+
+       * include/grub/kernel.h (grub_arch_memdisk_addr)
+       (grub_arch_memdisk_size): Moved from here ...
+
+       * include/grub/i386/pc/kernel.h (grub_arch_memdisk_addr)
+       (grub_arch_memdisk_size): ... to here.
+
+2008-01-21  Robert Millan  <rmh@aybabtu.com>
+
+       Mostly based on bugfix from Bean.
+
+       * kern/elf.c (grub_elf32_phdr_iterate): Use `NESTED_FUNC_ATTR'
+       attribute with hook() parameter.
+       (grub_elf32_load): Use `NESTED_FUNC_ATTR' with grub_elf32_load_segment()
+       declaration.
+       (grub_elf64_phdr_iterate): Use `NESTED_FUNC_ATTR'
+       attribute with hook() parameter.
+       (grub_elf64_load): Use `NESTED_FUNC_ATTR' with grub_elf64_load_segment()
+       declaration.
+
+2008-01-21  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-pc.rmk (kernel_img_HEADERS): Add `machine/kernel.h'.
+       (pkglib_MODULES): Add `memdisk.mod'.
+       (memdisk_mod_SOURCES): New variable.
+       (memdisk_mod_CFLAGS): Likewise.
+       (memdisk_mod_LDFLAGS): Likewise.
+
+       * disk/memdisk.c: New file.
+
+       * include/grub/disk.h (grub_disk_dev_id): Add
+       `GRUB_DISK_DEVICE_MEMDISK_ID'.
+
+       * include/grub/i386/pc/kernel.h
+       (GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE): New macro.
+       (GRUB_KERNEL_MACHINE_PREFIX): Increment by 4.
+       (grub_kernel_image_size): New variable declaration.
+       (grub_total_module_size): Likewise.
+       (grub_memdisk_image_size): Likewise.
+
+       * include/grub/i386/pc/memory.h
+       (GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR): New macro.
+
+       * include/grub/kernel.h: Include `<grub/symbol.h>'.
+       (grub_arch_memdisk_addr): New variable declaration.
+       (grub_arch_memdisk_size): Likewise.
+
+       * kern/i386/pc/init.c (grub_arch_memdisk_addr): New function.
+       (grub_arch_memdisk_size): Likewise.
+
+       * kern/i386/pc/startup.S (grub_memdisk_image_size): New variable.
+       (codestart): Replace hardcoded `0x100000' with
+       `GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR' macro.
+
+       * util/i386/pc/grub-mkimage.c: Include `<grub/misc.h>'.
+       (generate_image): Add `memdisk_path' parameter.  When `memdisk_path' is
+       not NULL, append the contents of the file it refers to, at the end of
+       the compressed kernel image.  Initialize `grub_memdisk_image_size'
+       variable (at `GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE' offset).
+       (options): Add "memdisk"|'m' option.
+       (main): Parse --memdisk|-m option, and pass user-provided path as
+       parameter to generate_image().
+
+2008-01-20  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/sparc64/ieee1275/openfw.c (grub_devalias_iterate): Copy debug
+       grub_dprintf() calls from here ...
+       * kern/powerpc/ieee1275/openfw.c (grub_devalias_iterate): ... to here.
+
+2008-01-20  Robert Millan  <rmh@aybabtu.com>
+
+       Fix detection of "real mode" when /options/real-mode? doesn't exist.
+
+       * include/grub/ieee1275/ieee1275.h (grub_ieee1275_mmu): New variable
+       declaration.
+       * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_mmu): New variable.
+       (grub_ieee1275_find_options): If `grub_ieee1275_mmu' is 0, set
+       `GRUB_IEEE1275_FLAG_REAL_MODE'.
+       (cmain): Initialize `grub_ieee1275_mmu' (using /chosen/mmu integer
+       property).
+       * kern/powerpc/ieee1275/openfw.c (grub_map): Rely on pre-initialized
+       `grub_ieee1275_mmu' rather than obtaining a handler on every call.
+
+2008-01-19  Robert Millan  <rmh@aybabtu.com>
+
+       Get rid of confusing function (superseded by
+       `grub_ieee1275_get_integer_property')
+       * include/grub/ieee1275/ieee1275.h (grub_ieee1275_decode_int_4): Remove
+       prototype.
+       * kern/ieee1275/ieee1275.c (grub_ieee1275_decode_int_4): Remove
+       function.
+       * term/ieee1275/ofconsole.c (grub_ofconsole_init): Avoid use of
+       grub_ieee1275_decode_int_4(), by obtaining integer properties directly
+       in native endianness from grub_ieee1275_get_integer_property().
+
+2008-01-19  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/powerpc/ieee1275/openfw.c (grub_halt): Issue "power-off"
+       command after "shut-down", since implementations differ on which
+       the command for halt is.
+
+2008-01-19  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/i386/linuxbios/console.h: Add header protection.
+       (grub_keyboard_controller_init): New function prototype.
+       * term/i386/pc/at_keyboard.c (KEYBOARD_COMMAND_ISREADY): New macro.
+       (KEYBOARD_COMMAND_READ): Likewise.
+       (KEYBOARD_COMMAND_WRITE): Likewise.
+       (KEYBOARD_SCANCODE_SET1): Likewise.
+       (grub_keyboard_controller_write): New function.
+       (grub_keyboard_controller_read): Likewise.
+       (grub_keyboard_controller_init): Likewise.
+
+       * term/i386/pc/console.c: Include `<grub/machine/machine.h>'.
+       (grub_console_init): On coreboot/LinuxBIOS, call
+       grub_keyboard_controller_init().
+
+2008-01-19  Robert Millan  <rmh@aybabtu.com>
+
+       PowerPC changes provided by Pavel Roskin.
+
+       * kern/powerpc/ieee1275/cmain.c (cmain): Don't take any arguments.
+       * kern/powerpc/ieee1275/crt0.S: Store r5 in grub_ieee1275_entry_fn,
+       don't rely on cmain() doing it.
+       * kern/i386/ieee1275/startup.S (_start): Store %eax in
+       grub_ieee1275_entry_fn, don't rely on cmain() doing it.
+
+2008-01-16  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/i386/linuxbios/memory.h
+       (GRUB_MEMORY_MACHINE_LINUXBIOS_TABLE_ADDR): Remove macro.
+       * kern/i386/linuxbios/table.c (grub_linuxbios_table_iterate): Do not
+       receive `table_header' as argument.  Instead, probe for it in the
+       known memory ranges where it can be present.
+       (grub_available_iterate): Do not pass a fixed `table_header' address
+       to grub_linuxbios_table_iterate().
+
+2008-01-15  Robert Millan  <rmh@aybabtu.com>
+
+       * configure.ac: Add `i386-ieee1275' to the list of supported targets.
+       * conf/i386-ieee1275.rmk: New file.
+       * include/grub/i386/ieee1275/console.h: Likewise.
+       * include/grub/i386/ieee1275/ieee1275.h: Likewise.
+       * include/grub/i386/ieee1275/kernel.h: Likewise.
+       * include/grub/i386/ieee1275/time.h: Likewise.
+       * kern/i386/ieee1275/init.c: Likewise.
+       * kern/i386/ieee1275/startup.S: Likewise.
+
+2008-01-15  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/misc.c (grub_vsprintf): Do not reset `longlongfmt' to zero
+       when pointers are 32-bit (but still do set it to one when they are
+       64-bit).
+
+2008-01-15  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/ieee1275/ieee1275.h
+       (grub_ieee1275_get_integer_property): New function prototype.
+
+       * kern/ieee1275/ieee1275.c: Include `<grub/types.h>'.
+       (grub_ieee1275_get_integer_property): New function.  Wraps around
+       grub_ieee1275_get_property() to handle endianness.
+
+       * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_find_options): Replace
+       grub_ieee1275_get_property() with grub_ieee1275_get_integer_property()
+       where appropriate.
+       * kern/powerpc/ieee1275/openfw.c (grub_available_iterate): Likewise.
+       (grub_map): Likewise.
+       * kern/sparc64/ieee1275/openfw.c (grub_map): Likewise.
+
+2008-01-15  Bean  <bean123ch@gmail.com>
+
+       * normal/execute.c (grub_script_exec_argument_to_string): Check for undefined variable.
+       (grub_script_execute_cmdline): Reset grub_errno.
+
+       * normal/main.c (read_config_file): Reset grub_errno.
+
+       * normal/parse.y (script_init): New.
+       (script): Move function and menuentry here.
+       (delimiter): New.
+       (command): Add delimiter at the end of command.
+       (commands): Adjust to match the new command.
+       (commandblock): Remove grub_script_lexer_record_start.
+       (menuentry): Add grub_script_lexer_record_start, use the new commands.
+       (if): Use the new commands.
+
+       * conf/common.rmk (pkgdata_MODULES): Add echo.mod.
+
+2008-01-15  Robert Millan  <rmh@aybabtu.com>
+
+       * normal/menu.c (run_menu): Move timeout message from here ...
+       (print_timeout): ... to here.
+       (run_menu): Use print_timeout() once during initial draw to print
+       the whole message, and again in every clock tick to update only
+       the number of seconds.
+
+2008-01-15  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/powerpc/ieee1275/openfw.c (grub_available_iterate): Obtain
+       actual size of `available' from grub_ieee1275_get_property(), and
+       restrict parsing to that bound.
+
+2008-01-15  Christian Franke  <franke@computer.org>
+
+       * util/grub-emu.c: Replace <argp.h> by <getopt.h>.
+       (argp_program_version): Remove variable.
+       (argp_program_bug_address): Likewise.
+       (options): Convert from struct argp_option to struct option.
+       (struct arguments): Remove.
+       (parse_opt): Remove.
+       (usage): New function.
+       (main): Replace struct args members by simple variables.
+       Replace argp_parse() by getopt_long().
+       Add switch to evaluate options.
+       Add missing "(...)" around root_dev in prefix string.
+
+2008-01-14  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/powerpc/ieee1275/init.c (grub_exit): Reimplement as a wrapper
+       for grub_ieee1275_exit(), in order to improve portability.
+
+2008-01-14  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/10_linux.in (prefix): Define.
+       (exec_prefix): Likewise.  Both definitions are later used by `libdir'.
+
+2008-01-13  Pavel Roskin  <proski@gnu.org>
+
+       * disk/ieee1275/ofdisk.c (grub_ofdisk_open): Don't use
+       grub_errno if no errors have been detected.
+
+2008-01-12  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/util/getroot.h (grub_dev_abstraction_types): New enum.
+       (grub_util_get_dev_abstraction): New function prototype.
+
+       * util/getroot.c: Include `<grub/util/getroot.h>'
+       (grub_util_get_grub_dev): Move detection of abstraction type to ...
+       (grub_util_get_dev_abstraction): ... here (new function).
+
+       * util/grub-probe.c: Convert PRINT_* to an enum.  Add
+       `PRINT_ABSTRACTION'.
+       (probe): Probe for abstraction type when requested.
+       (main): Understand `--target=abstraction'.
+
+       * util/i386/efi/grub-install.in: Add abstraction module to core
+       image when it is found to be necessary.
+       * util/i386/pc/grub-install.in: Likewise.
+       * util/powerpc/ieee1275/grub-install.in: Likewise.
+
+       * util/update-grub_lib.in (font_path): Return system path without
+       converting to GRUB path.
+       * util/update-grub.in: Convert system path returned by font_path()
+       to a GRUB path.  Use `grub-probe -t abstraction' to determine what
+       abstraction module is needed for loading fonts (if any).  Export
+       that as `GRUB_PRELOAD_MODULES'.
+       * util/grub.d/00_header.in: Process `GRUB_PRELOAD_MODULES' (print
+       insmod commands).
+
+2008-01-12  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Remove some unused code from reiserfs.
+
+       * fs/reiserfs.c (struct grub_reiserfs_key)
+       [GRUB_REISERFS_KEYV2_BITFIELD]: Removed offset and type.
+       (struct grub_reiserfs_node_body): Removed.
+       (grub_reiserfs_get_key_v2_type) [GRUB_REISERFS_KEYV2_BITFIELD]:
+       Likewise.
+       (grub_reiserfs_get_key_offset) [GRUB_REISERFS_KEYV2_BITFIELD]:
+       Likewise.
+       (grub_reiserfs_set_key_offset) [GRUB_REISERFS_KEYV2_BITFIELD]:
+       Likewise.
+       (grub_reiserfs_set_key_offset) [GRUB_REISERFS_KEYV2_BITFIELD]:
+       Likewise.
+       (grub_reiserfs_set_key_type) [GRUB_REISERFS_KEYV2_BITFIELD]:
+       Likewise.
+       (grub_reiserfs_iterate_dir) [GRUB_REISERFS_KEYV2_BITFIELD]:
+       Likewise.
+       (grub_reiserfs_open) [GRUB_REISERFS_KEYV2_BITFIELD]: Likewise.
+       (grub_reiserfs_read) [GRUB_REISERFS_KEYV2_BITFIELD]: Likewise.
+       (grub_reiserfs_dir) [GRUB_REISERFS_KEYV2_BITFIELD]: Likewise.
+
+2008-01-10  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub_lib.in (grub_file_is_not_garbage): New function.
+       Determines if a file is garbage left by packaging systems, etc.
+       * util/update-grub.in: Use grub_file_is_not_garbage() as a condition
+       for processing /etc/grub.d scripts.
+       * util/grub.d/10_hurd.in: Fix `GRUB_DISTRIBUTOR' comparison.
+       * util/grub.d/10_linux.in: Likewise.  Use grub_file_is_not_garbage()
+       as a condition for processing Linux images.
+
+2008-01-10  Pavel Roskin  <proski@gnu.org>
+
+       * include/grub/powerpc/libgcc.h (__ucmpdi2): New export.  Needed
+       to compile reiserfs.c on PowerPC.
+
+2008-01-10  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/device.c (grub_device_iterate): Do not abort device iteration
+       when one of the devices cannot be opened.
+       * kern/disk.c (grub_disk_open): Do not account previous failures of
+       unrelated functions when grub_errno is checked for.
+
+2008-01-08  Robert Millan  <rmh@aybabtu.com>
+
+       * loader/i386/pc/linux.c (grub_rescue_cmd_linux): For
+       `! grub_linux_is_bzimage', change order of address comparison to make
+       it more intuitive, and improve "too big zImage" error message.
+
+2008-01-08  Robert Millan  <rmh@aybabtu.com>
+
+       * Makefile.in (uninstall): Handle `$(update-grub_SCRIPTS)' and
+       `$(update-grub_DATA)'.
+       (distcheck): Fix race condition when invoking `$(MAKE)' on multiple
+       targets.
+
+2008-01-07  Robert Millan  <rmh@aybabtu.com>
+
+       * boot/i386/pc/boot.S (boot_drive_check): Add a comment indicating
+       which instruction is modified by grub-setup during installation
+       (since it wasn't obvious by only looking at this file).
+
+2008-01-07  Robert Millan  <rmh@aybabtu.com>
+
+       * TODO: Rewrite.  Just refer to the wiki and the BTS instead of
+       listing actual TODO items.
+
+2008-01-06  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * fs/reiserfs.c (grub_reiserfs_get_key_v2_type): Handle endianness
+       correctly.
+       (grub_reiserfs_get_key_offset): Likewise.
+       (grub_reiserfs_set_key_offset): Likewise.
+       (grub_reiserfs_set_key_type): Likewise.
+       (grub_reiserfs_iterate_dir): Return 1 if found, otherwise 0.
+
+       (GRUB_REISERFS_KEYV2_BITFIELD): Undefined. Probably it would be
+       better to remove the bitfield version completely.
+
+2008-01-06  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * fs/reiserfs.c (grub_reiserfs_iterate_dir): ENTRY_ITEM must be
+       allocated from the heap, due to the fshelp implementation.
+       (grub_reiserfs_dir): Free NODE, due to the same reason.
+
+2008-01-06  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Mostly from Vincent Pelletier:
+
+       * fs/reiserfs.c: New file.
+
+       * conf/common.rmk (pkglib_MODULES): Added reiserfs.mod.
+       (reiserfs_mod_SOURCES): New variable.
+       (reiserfs_mod_CFLAGS): Likewise.
+       (reiserfs_mod_LDFLAGS): Likewise.
+
+       * DISTLIST: Added boot/i386/pc/lnxboot.S, commands/hexdump.c,
+       disk/ata.c, fs/cpio.c, fs/ntfscomp.c, fs/reiserfs.c,
+       include/grub/ntfs.h, include/grub/i386/pc/machine.h, and
+       normal/color.c.
+
+2008-01-06  Robert Millan  <rmh@aybabtu.com>
+
+       * normal/color.c: Remove `<grub/env.h>'.
+
+2008-01-05  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * include/grub/normal.h: Include <grub/env.h>.
+
+2008-01-05  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-setup.c (usage): Replace obsolete `(hd0,0)' in
+       usage example with `(hd0,1)'.
+       Reported by Samuel Thibault.
+
+2008-01-05  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/i386/loader.S (grub_linux_is_bzimage): New variable.
+       (grub_linux_boot_zimage): Rename to ...
+       (grub_linux_boot): ... this.
+       (grub_linux_boot_bzimage): Merge with `grub_linux_boot_zimage'.
+       (grub_linux_boot_zimage): Conditionalize zImage copy.
+
+       * include/grub/i386/loader.h (grub_linux_is_bzimage): Add prototype.
+       (grub_linux_boot_bzimage): Remove prototype.
+       (grub_linux_boot_zimage): Rename to ...
+       (grub_linux_boot): ... this.
+
+       * loader/i386/pc/linux.c (big_linux): Replace with `grub_linux_is_bzimage'.
+       (grub_linux_boot): Remove function.
+
+2008-01-05  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/normal.h (grub_env_write_color_normal): New prototype.
+       (grub_env_write_color_highlight): Likewise.
+       (grub_wait_after_message): Likewise.
+
+       * normal/color.c: New file.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Add `normal/color.c'.
+       (normal_mod_DEPENDENCIES): Likewise.
+
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Add `normal/color.c'.
+       (normal_mod_DEPENDENCIES): Likewise.
+
+       * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Add `normal/color.c'.
+       (normal_mod_DEPENDENCIES): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add `normal/color.c'.
+       (normal_mod_DEPENDENCIES): Likewise.
+
+       * normal/menu_entry.c (run): Rely on grub_wait_after_message()
+       for waiting after a message is printed.
+       * normal/main.c (read_config_file): Likewise.
+       (grub_normal_init): Register grub_env_write_color_normal() and
+       grub_env_write_color_highlight() hooks.  Mark `color_normal' and
+       `color_highlight' variables as global.
+
+       * normal/menu.c (grub_wait_after_message): New function.
+       (grub_color_menu_normal): New variable.  Replaces ...
+       (GRUB_COLOR_MENU_NORMAL): ... this macro.
+       (grub_color_menu_highlight): New variable.  Replaces ...
+       (GRUB_COLOR_MENU_HIGHLIGHT): ... this macro.
+       (draw_border): Set color state to `GRUB_TERM_COLOR_NORMAL' instead of
+       `GRUB_TERM_COLOR_STANDARD'.
+       (print_message): Use `grub_setcolorstate' to reload colors.  Rename
+       `normal_code' and `highlight_code' to `old_color_normal' and
+       `old_color_highlight', respectively.
+       (grub_menu_init_page): Update colors when drawing the menu, based on
+       `menu_color_normal' and `menu_color_highlight' variables.
+       (grub_menu_run): Rely on grub_wait_after_message() for waiting after
+       a message is printed.
+
+2008-01-05  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/env.c (grub_env_context_open): Propagate hooks for global
+       variables to new context.
+
+       * kern/main.c (grub_set_root_dev): Export `root' variable.
+
+2008-01-05  Robert Millan  <rmh@aybabtu.com>
+
+       * util/biosdisk.c (get_os_disk): Check for devfs-style IDE and SCSI
+       discs unconditionally, since udev and others have options to provide
+       them.
+
+2008-01-05  Robert Millan  <rmh@aybabtu.com>
+
+       * normal/completion.c (iterate_dir): Skip `.' and `..' directories.
+
+2008-01-04  Christian Franke  <franke@computer.org>
+
+       * kern/i386/pc/init.c (grub_machine_init): Fix evaluation
+       of eisa_mmap.
+
+2008-01-03  Pavel Roskin  <proski@gnu.org>
+
+       * kern/i386/linuxbios/init.c: Put "void" to all function
+       declarations with no arguments.
+       * kern/powerpc/ieee1275/init.c: Likewise.
+       * term/i386/pc/at_keyboard.c: Likewise.
+       * term/i386/pc/vga_text.c: Likewise.
+       * util/grub-mkdevicemap.c: Likewise.
+
+2008-01-02  Robert Millan  <rmh@aybabtu.com>
+
+       * loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): Improve error
+       message when loaded image is out of bounds.
+       (grub_multiboot_load_elf64): Likewise.
+
+2008-01-02  Pavel Roskin  <proski@gnu.org>
+
+       * util/grub.d/10_linux.in: Try version without ".old" when
+       looking for initrd.  It's better to use initrd from the newer
+       kernel of the same version than no initrd at all.
+
+2008-01-01  Robert Millan  <rmh@aybabtu.com>
+
+       * util/biosdisk.c (get_os_disk): Fix check for IDE or SCSI discs.
+
+2008-01-01  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * include/grub/video.h: Added grub_video_unmap_color and
+       grub_video_get_active_render_target.
+       (grub_video_adapter): Added unmap_color and get_active_render_target.
+
+       * video/video.c: Added grub_video_unmap_color and
+       grub_video_get_active_render_target.
+       (grub_video_get_info): Changed method to accept NULL pointer as an
+       argument to allow detection of active video adapter.
+
+       * video/i386/pc/vbe.c: Renamed grub_video_vbe_unmap_color as
+       grub_video_vbe_unmap_color_int.
+       Added grub_video_vbe_unmap_color and
+       grub_video_vbe_get_active_render_target.
+       (grub_video_vbe_adapter): Added unmap_color and
+       get_active_render_target.
+
+       * video/i386/pc/vbeblit.c: Replaced grub_video_vbe_unmap_color usage
+       with grub_video_vbe_unmap_color_int.
+
+       * term/gfxterm.c (DEFAULT_STANDARD_COLOR): Added.
+       (DEFAULT_NORMAL_COLOR): Likewise.
+       (DEFAULT_HIGHLIGHT_COLOR) Likewise.
+       (DEFAULT_FG_COLOR): Removed.
+       (DEFAULT_BG_COLOR): Likewise.
+       (DEFAULT_CURSOR_COLOR): Changed value.
+       (grub_virtual_screen): Added standard_color_setting,
+       normal_color_setting, highlight_color_setting and term_color.
+       (grub_virtual_screen): Removed fg_color_setting and bg_color_setting.
+       (bitmap_width): Added.
+       (bitmap_height): Likewise.
+       (bitmap): Likewise.
+       (set_term_color): Likewise.
+       (grub_virtual_screen_setup): Changed to use new terminal coloring
+       settings.
+       (grub_gfxterm_init): Added init for bitmap.
+       (grub_gfxterm_fini): Added destroy for bitmap.
+       (redraw_screen_rect): Updated to use background bitmap and new
+       terminal coloring.
+       (scroll_up): Added optimization for case when there is no bitmap.
+       (grub_gfxterm_cls): Fixed to use correct background color.
+       (grub_virtual_screen_setcolorstate): Changed to use new terminal
+       coloring.
+       (grub_virtual_screen_setcolor): Likewise.
+       (grub_virtual_screen_getcolor): Added.
+       (grub_gfxterm_background_image_cmd): Likewise.
+       (grub_video_term): Added setcolor and getcolor.
+       (MOD_INIT): Added registration of background_image command.
+       (MOD_TERM): Added unregistration for background_image command.
+
+2007-12-30  Pavel Roskin  <proski@gnu.org>
+
+       * loader/multiboot_loader.c: Fix multiboot command
+       unregistration.  Fix all typos in the word "multiboot".
+
+2007-12-29  Pavel Roskin  <proski@gnu.org>
+
+       * util/grub.d/10_linux.in: Refactor search for initrd.  Add
+       support for initrd names used in Fedora.
+
+2007-12-26  Bean  <bean123ch@gmail.com>
+
+       * conf/common.rmk (pkgdata_MODULES): Add cpio.mod.
+       (cpio_mod_SOURCES): New variable.
+       (cpio_mod_CFLAGS): Likewise.
+       (cpio_mod_LDFLAGS): Likewise.
+
+       * fs/cpio.c: New file.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Add cpio.c.
+
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+
+2007-12-25  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/term.h (struct grub_term): Add `getcolor' function.
+       (grub_getcolor): New function.
+
+       * kern/term.c (grub_getcolor): New function.
+       * normal/menu.c (GRUB_COLOR_MENU_NORMAL): New macro.
+       (GRUB_COLOR_MENU_HIGHLIGHT): New macro.
+       (print_entry): Set normal and highlight colors to
+       `GRUB_COLOR_MENU_NORMAL' and `GRUB_COLOR_MENU_HIGHLIGHT',
+       respectively, before printing and restore them to old
+       values afterwards.
+       (grub_menu_init_page): Likewise.  Fill an additional colored space
+       that would otherwise be left blank.
+
+       * term/efi/console.c (grub_console_getcolor): New function.
+       (struct grub_console_term.getcolor): New variable.
+       * term/i386/pc/console.c (grub_console_getcolor): New function.
+       (struct grub_console_term.getcolor): New variable.
+       * term/ieee1275/ofconsole.c (grub_ofconsole_getcolor): New function.
+       (struct grub_console_term.getcolor): New variable.
+
+       * term/i386/pc/serial.c (grub_serial_setcolor): Remove function.
+       (struct grub_console_term.setcolor): Remove variable.
+       * term/i386/pc/vesafb.c (grub_virtual_screen_setcolor): Remove function.
+       (struct grub_console_term.setcolor): Remove variable.
+       * term/i386/pc/vga.c (grub_vga_setcolor): Remove function.
+       (struct grub_console_term.setcolor): Remove variable.
+       * term/gfxterm.c (grub_virtual_screen_setcolor): Remove function.
+       (struct grub_console_term.setcolor): Remove variable.
+
+2007-12-25  Robert Millan  <rmh@aybabtu.com>
+
+       * configure.ac: Search for possible unifont.hex locations, and
+       define UNIFONT_HEX if found.
+
+       * Makefile.in (UNIFONT_HEX): Define variable.
+       (DATA): Rename to ...
+       (PKGLIB): ... this.  Update all users.
+       (PKGDATA): New variable.
+       (pkgdata_IMAGES): Rename to ...
+       (pkglib_IMAGES): ... this. Update all users.
+       (pkgdata_MODULES): Rename to ...
+       (pkglib_MODULES): ... this. Update all users.
+       (pkgdata_PROGRAMS): Rename to ...
+       (pkglib_PROGRAMS): ... this. Update all users.
+       (pkgdata_DATA): Rename to ...
+       (pkglib_DATA): ... this. Update all users.
+       (CLEANFILES): Redefine to `$(pkglib_DATA) $(pkgdata_DATA)'.
+       (unicode.pff, ascii.pff): New rules.
+       (all-local): Add `$(PKGDATA)' dependency.
+       (install-local): Process `$(PKGDATA)'.
+
+       * util/update-grub_lib.in (font_path): Search for *.pff files in
+       a few more locations, including `${pkgdata}'.
+
+2007-12-23  Robert Millan  <rmh@aybabtu.com>
+
+       Patch from Bean  <bean123ch@gmail.com>:
+       * disk/loopback.c (grub_loopback_read): Add missing bit shift to
+       `size'.
+
+2007-12-21  Bean  <bean123ch@gmail.com>
+
+       * conf/common.rmk (pkgdata_MODULES): Add ntfscomp.mod.
+       (ntfscomp_mod_SOURCES): New variable.
+       (ntfscomp_mod_CFLAGS): Likewise.
+       (ntfscomp_mod_LDFLAGS): Likewise.
+
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/ntfscomp.c.
+       (grub_probe_SOURCES): Likewise.
+       (grub_emu_SOURCES): Likewise.
+
+       * conf/i386-efi.rmk (grub_probe_SOURCES): Add fs/ntfscomp.c.
+       (grub_emu_SOURCES): Likewise.
+
+       * conf/i386-linuxbios.rmk (grub_probe_SOURCES): Add fs/ntfscomp.c.
+       (grub_emu_SOURCES): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (grub_probe_SOURCES): Add fs/ntfscomp.c.
+       (grub_emu_SOURCES): Likewise.
+
+       * fs/ntfs.c (grub_ntfscomp_func): New variable.
+       (read_run_list): Renamed to grub_ntfs_read_run_list.
+       (decomp_nextvcn): Moved to ntfscomp.c.
+       (decomp_getch): Likewise.
+       (decomp_get16): Likewise.
+       (decomp_block): Likewise.
+       (read_block): Likewise.
+       (read_data): Partially moved to ntfscomp.c.
+       (fixup): Change unsigned to grub_uint16_t.
+       (read_mft): Change unsigned long to grub_uint32_t.
+       (read_attr): Likewise.
+       (read_data): Likewise.
+       (read_run_data): Likewise.
+       (read_run_list): Likewise.
+       (read_mft): Likewise.
+
+       * fs/ntfscomp.c: New file.
+
+       * include/grub/ntfs.h: New file.
+
+2007-12-16  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub-mkdevicemap.c (make_device_map): Iterate up to 20 for
+       IDE disk check, since Linux is known to support 20 IDE disks.
+       Reported by Colin Watson.
+
+2007-12-15  Bean  <bean123ch@gmail.com>
+
+       * conf/i386-pc.rmk (pkgdata_IMAGES): Add lnxboot.img.
+       (lnxboot_img_SOURCES): New variable.
+       (lnxboot_img_ASFLAGS): Likewise.
+       (lnxboot_img_LDFLAGS): Likewise.
+
+       * boot/i386/pc/lnxboot.S: New file.
+
+2007-11-24  Pavel Roskin  <proski@gnu.org>
+
+       * configure.ac: Test if '--build-id=none' is supported by the
+       linker.  If yes, add it to TARGET_LDFLAGS.  Build ID causes
+       objcopy to generate incorrect binary files (binutils
+       2.17.50.0.18-1 as shipped by Fedora 8).
+       * aclocal.m4 (grub_PROG_OBJCOPY_ABSOLUTE): Use LDFLAGS when
+       linking, so that build ID doesn't break the test.
+
+2007-11-24  Pavel Roskin  <proski@gnu.org>
+
+       * include/grub/i386/time.h: use "void" in the argument list
+       of grub_cpu_idle().
+       * include/grub/powerpc/time.h: Likewise.
+       * include/grub/sparc64/time.h: Likewise.
+
+2007-11-18  Christian Franke  <franke@computer.org>
+
+       * util/console.c (grub_ncurses_getkey): Change curses KEY_* mapping,
+       now return control chars instead of GRUB_CONSOLE_KEY_* constants.
+       This fixes the problem that function keys did not work in grub-emu.
+
+2007-11-18  Christian Franke  <franke@computer.org>
+
+       * disk/host.c (grub_host_open): Remove attribute unused from
+       name parameter. Add check for "host". This fixes the problem
+       that grub-emu does not find partitions.
+
+2007-11-18  Christian Franke  <franke@computer.org>
+
+       * util/hostfs.c (is_dir): New function.
+       (grub_hostfs_dir):  Handle missing dirent.d_type case.
+       (grub_hostfs_read): Add missing fseek().
+       (grub_hostfs_label): Clear label pointer.  This fixes a crash
+       of grub-emu on "ls (host)".
+
+2007-11-18  Christian Franke  <franke@computer.org>
+
+       * include/grub/i386/pc/init.h (struct grub_machine_mmap_entry):
+       Add attribute packed, gcc 3.4.4 on Cygwin aligns this
+       to 64 bit boundary by default.
+
+2007-11-18  Bean  <bean123ch@gmail.com>
+
+       * conf/common.rmk (pkgdata_MODULES): Add hexdump.mod.
+       (hexdump_mod_SOURCES): New variable.
+       (hexdump_mod_CFLAGS): Likewise.
+       (hexdump_mod_LDFLAGS): Likewise.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Add command/hexdump.c.
+
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Add command/hexdump.c.
+
+       * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Add command/hexdump.c.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add command/hexdump.c.
+
+       * include/grub/hexdump.h: New file.
+
+       * commands/hexdump.c: New file.
+
+2007-11-10  Robert Millan  <rmh@aybabtu.com>
+
+       * commands/i386/pc/play.c (beep_off): Switch order of arguments
+       in grub_outb() calls.
+       (beep_on): Likewise.
+
+2007-11-10  Christian Franke  <franke@computer.org>
+
+       * normal/menu.c (run_menu): Check for empty menu to avoid crash.
+       (grub_menu_run): Likewise.
+
+2007-11-10  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/i386/efi/machine.h: New file.
+       * include/grub/i386/linuxbios/machine.h: Likewise.
+       * include/grub/i386/pc/machine.h: Likewise.
+       * include/grub/powerpc/ieee1275/machine.h: Likewise.
+       * include/grub/sparc64/ieee1275/machine.h: Likewise.
+
+       * term/i386/pc/serial.c: Include <grub/machine/machine.h>.
+       (serial_hw_io_addr): New variable.
+       (serial_hw_get_port): Obtain port address from `serial_hw_io_addr'
+       instead of `(unsigned short *) 0x400'.
+
+2007-11-10  Bean  <bean123ch@gmail.com>
+
+       * fs/ntfs.c (read_block): Fix a bug caused by adjacent blocks.
+
+2007-11-10  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * conf/i386-pc.rmk (pkgdata_MODULES): Added vga.mod.
+       (vga_mod_SOURCES): Added.
+       (vga_mod_CFLAGS): Likewise.
+       (vga_mod_LDFLAGS): Likewise.
+
+       * term/i386/pc/vga.c (get_map_mask): Switch order of arguments in
+       grub_outb() calls.
+       (set_map_mask): Likewise.
+       (set_read_map): Likewise.
+       (set_read_address): Likewise.
+       (vga_font): Removed variable.
+       (get_vga_glyph): Removed function.
+       (invalidate_char): Likewise.
+       (write_char): Changed to use grub_font_get_glyph() for font
+       information.
+       (grub_vga_putchar): Likewise.
+       (grub_vga_getcharwidth): Likewise.
+
+2007-11-10  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * conf/i386-pc.rmk (boot_img_LDFLAGS): Use COMMON_LDFLAGS for target
+       flags.
+       (pxeboot_img_LDFLAGS): Likewise.
+       (diskboot_img_LDFLAGS): Likewise.
+       (kernel_img_LDFLAGS): Likewise.
+
+2007-11-06  Robert Millan  <rmh@aybabtu.com>
+
+       * term/i386/pc/serial.c (serial_hw_put): Switch order of arguments
+       in grub_outb() calls.
+       (serial_hw_init): Likewise.
+
+2007-11-05  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub.in: Allow files in ${update_grub_dir} to contain
+       spaces.  Skip non-regular files.
+
+2007-11-05  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/disk.c (grub_disk_firmware_fini)
+       (grub_disk_firmware_is_tainted): New variables.
+
+       * include/grub/disk.h (grub_disk_firmware_fini)
+       (grub_disk_firmware_is_tainted): Likewise.
+
+       * disk/i386/pc/biosdisk.c (GRUB_MOD_FINI(biosdisk)): Moved from here ...
+       (grub_disk_biosdisk_fini): ... to here.
+       (GRUB_MOD_FINI(biosdisk)): Implement using grub_disk_biosdisk_fini().
+       (GRUB_MOD_INIT(biosdisk)): Abort when `grub_disk_firmware_is_tainted'
+       is set.  Register grub_disk_biosdisk_fini() in
+       `grub_disk_firmware_fini'.
+
+       * disk/ata.c: Remove `<grub/machine/biosdisk.h>'.
+       (GRUB_MOD_INIT(ata)): Remove grub_biosdisk_fini() call.
+       Use `grub_disk_firmware_is_tainted' and `grub_disk_firmware_fini'
+       to finish existing firmware disk interface.
+
+       * conf/i386-linuxbios.rmk (pkgdata_MODULES): Add `ata.mod'.
+       (ata_mod_SOURCES): New variable.
+       (ata_mod_CFLAGS): Likewise.
+       (ata_mod_LDFLAGS): Likewise.
+
+2007-11-05  Robert Millan  <rmh@aybabtu.com>
+
+       * disk/ata.c: Remove `<grub/machine/time.h>'.  Include `<grub/time.h>'.
+       (grub_ata_wait): Reimplement using grub_millisleep().
+
+       * include/grub/misc.h (grub_div_roundup): Fix parenthesization.
+       * include/grub/i386/time.h (grub_cpu_idle): Disable `hlt' instruction.
+
+2007-11-03  Marco Gerards  <marco@gnu.org>
+
+       * term/i386/pc/vga_text.c: Include <grub/cpu/io.h>.
+       (CRTC_ADDR_PORT): New macro.
+       (CRTC_DATA_PORT): Likewise.
+       (CRTC_CURSOR): Likewise.
+       (CRTC_CURSOR_ADDR_HIGH): Likewise.
+       (CRTC_CURSOR_ADDR_LOW): Likewise.
+       (update_cursor): New function.
+       (grub_console_real_putchar): Call `update_cursor'.
+       (grub_console_gotoxy): Likewise.
+       (grub_console_cls): Set the default color when clearing the
+       screen.
+       (grub_console_setcursor): Implemented.
+
+2007-11-03  Marco Gerards  <marco@gnu.org>
+
+       * disk/ata.c (grub_ata_pio_read): Don't wait for the command to
+       become activate.
+       (grub_ata_pio_write): Likewise.
+
+       (grub_atapi_identify): Wait after issuing an ATA command.
+       (grub_atapi_packet): Likewise.
+       (grub_ata_identify): Likewise.
+       (grub_ata_readwrite): Likewise.
+
+2007-11-03  Marco Gerards  <marco@gnu.org>
+
+       * disk/ata.c (grub_ata_pio_read): Detect and return the error code.
+       (grub_ata_pio_write): Likewise.
+       (grub_ata_readwrite): Use `grub_error', instead of
+       returning `grub_errno'.
+
+2007-11-03  Marco Gerards  <marco@gnu.org>
+
+       * disk/ata.c (grub_ata_readwrite): Call grub_ata_pio_read and
+       grub_ata_pio_write once for every single sector, instead of for
+       multiple sectors.
+
+2007-10-31  Robert Millan  <rmh@aybabtu.com>
+
+       * configure.ac: Add `i386-linuxbios' to the list of supported targets.
+
+       * conf/i386-linuxbios.rmk: New file.
+
+       * kern/i386/pc/hardware.c: Likewise.
+       * term/i386/pc/at_keyboard.c: Likewise.
+       * term/i386/pc/vga_text.c: Likewise.
+
+       * include/grub/i386/linuxbios/boot.h: Likewise.
+       * include/grub/i386/linuxbios/console.h: Likewise.
+       * include/grub/i386/linuxbios/init.h: Likewise.
+       * include/grub/i386/linuxbios/kernel.h: Likewise.
+       * include/grub/i386/linuxbios/loader.h: Likewise.
+       * include/grub/i386/linuxbios/memory.h: Likewise.
+       * include/grub/i386/linuxbios/serial.h: Likewise.
+       * include/grub/i386/linuxbios/time.h: Likewise.
+
+       * kern/i386/linuxbios/init.c: Likewise.
+       * kern/i386/linuxbios/startup.S: Likewise.
+       * kern/i386/linuxbios/table.c: Likewise.
+
+2007-10-31  Marco Gerards  <marco@gnu.org>
+
+       * conf/i386-pc.rmk (pkgdata_MODULES): Add `ata.mod'.
+       (ata_mod_SOURCES): New variable.
+       (ata_mod_CFLAGS): Likewise.
+       (ata_mod_LDFLAGS): Likewise.
+
+       * disk/ata.c: New file.
+
+       * include/grub/disk.h (grub_disk_dev_id): Add
+       `GRUB_DISK_DEV_ATA_ID'.
+
+2007-10-31  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/i386/pc/init.h (grub_lower_mem): Moved from here ...
+       * include/grub/i386/pc/memory.h (grub_lower_mem): ... to here.
+
+       * include/grub/i386/pc/init.h (grub_upper_mem): Moved from here ...
+       * include/grub/i386/pc/memory.h (grub_upper_mem): ... to here.
+
+       * include/grub/i386/pc/memory.h: Include `<grub/symbol.h>' and
+       `<grub/types.h>'.
+
+       * loader/i386/pc/multiboot.c: Include `<grub/machine/memory.h>'.
+
+2007-10-27  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/types.h (ULONG_MAX): Define macro.
+
+2007-10-22  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/i386/pc/startup.S: Remove `"kern/i386/realmode.S"'.  Include
+       `"../realmode.S"'.
+       Remove `"kern/i386/loader.S"'.  Include `"../loader.S"'.
+
+2007-10-22  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-pc.rmk (kernel_img_SOURCES): Remove `disk/i386/pc/biosdisk.c'.
+       (pkgdata_MODULES): Add `biosdisk.mod'.
+       (biosdisk_mod_SOURCES, biosdisk_mod_CFLAGS, biosdisk_mod_LDFLAGS): New
+       variables.
+
+       * disk/i386/pc/biosdisk.c: Include `<grub/dl.h>'.
+       (grub_biosdisk_init): Replace with ...
+       (GRUB_MOD_INIT(biosdisk)): ... this.
+       (grub_biosdisk_fini): Replace with ...
+       (GRUB_MOD_FINI(biosdisk)): ... this.
+
+       * kern/i386/pc/init.c: Remove `<grub/machine/biosdisk.h>'.
+       (grub_machine_init): Remove call to grub_biosdisk_init().
+       (grub_machine_fini): Remove call to grub_machine_fini().
+
+       * util/i386/pc/grub-install.in (modules): Add `biosdisk'.
+
+2007-10-22  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/time.h: New file.
+       * include/grub/i386/time.h: Likewise.
+       * include/grub/powerpc/time.h: Likewise.
+       * include/grub/sparc64/time.h: Likewise.
+
+       * include/grub/i386/pc/time.h (KERNEL_TIME_HEADER): Rename all
+       instances to ...
+       (KERNEL_MACHINE_TIME_HEADER): ... this.
+       * include/grub/powerpc/ieee1275/time.h (KERNEL_TIME_HEADER): Rename all
+       instances to ...
+       (KERNEL_MACHINE_TIME_HEADER): ... this.
+       * include/grub/sparc64/ieee1275/time.h (KERNEL_TIME_HEADER): Rename all
+       instances to ...
+       (KERNEL_MACHINE_TIME_HEADER): ... this.
+
+       * kern/i386/efi/init.c: Include `<grub/time.h>'.
+       (grub_millisleep): New function.
+       * kern/i386/pc/init.c: Include `<grub/time.h>'.
+       (grub_millisleep): New function.
+       * kern/powerpc/ieee1275/init.c: Include `<grub/time.h>'.
+       Remove `grub/machine/time.h' include.
+       (grub_millisleep): New function.
+       * kern/sparc64/ieee1275/init.c: Include `<grub/time.h>'.
+       Remove `grub/machine/time.h' include.
+       (grub_millisleep): New function.
+
+       * include/grub/misc.h (grub_div_roundup): New function.
+
+       * kern/misc.c: Include `<grub/time.h>'.
+       (grub_millisleep_generic): New function.
+
+       * conf/i386-efi.rmk (kernel_mod_HEADERS): Remove `i386/efi/time.h'.
+       Add `time.h'.
+       * conf/i386-pc.rmk (kernel_img_HEADERS): Remove `machine/time.h'.
+       Add `time.h'.
+       * conf/powerpc-ieee1275.rmk (kernel_elf_HEADERS): Remove
+       `machine/time.h'.  Add `time.h'.
+       * conf/sparc64-ieee1275.rmk (kernel_elf_HEADERS): Likewise.
+
+2007-10-21  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/misc.h (grub_max): New function.
+
+2007-10-21  Robert Millan  <rmh@aybabtu.com>
+
+       * util/misc.c (grub_util_info): Call fflush() before returning.
+
+2007-10-20  Robert Millan  <rmh@aybabtu.com>
+
+       * genmk.rb (Image): Copy `extra_flags' from here ...
+       (PModule): ... to here.  Use it in `#{obj}: #{src}' rule.
+
+       * commands/i386/cpuid.c (grub_cmd_cpuid): Add __attribute__ ((unused))
+       to `argc' and `args' arguments.
+
+2007-10-17  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/i386/loader.S: New file.
+
+       * kern/i386/pc/startup.S (grub_linux_prot_size): Moved from here ...
+       * kern/i386/loader.S (grub_linux_prot_size)... to here.
+       * kern/i386/pc/startup.S (grub_linux_tmp_addr): Moved from here ...
+       * kern/i386/loader.S (grub_linux_tmp_addr)... to here.
+       * kern/i386/pc/startup.S (grub_linux_real_addr): Moved from here ...
+       * kern/i386/loader.S (grub_linux_real_addr)... to here.
+       * kern/i386/pc/startup.S (grub_linux_boot_zimage): Moved from here ...
+       * kern/i386/loader.S (grub_linux_boot_zimage)... to here.
+       * kern/i386/pc/startup.S (grub_linux_boot_bzimage): Moved from here ...
+       * kern/i386/loader.S (grub_linux_boot_bzimage)... to here.
+       * kern/i386/pc/startup.S (grub_multiboot_real_boot): Moved from here ...
+       * kern/i386/loader.S (grub_multiboot_real_boot)... to here.
+       * kern/i386/pc/startup.S (grub_multiboot2_real_boot): Moved from here ...
+       * kern/i386/loader.S (grub_multiboot2_real_boot)... to here.
+
+       * kern/i386/realmode.S: New file.
+
+       * kern/i386/pc/startup.S (protstack): Moved from here ...
+       * kern/i386/realmode.S (protstack)... to here.
+       * kern/i386/pc/startup.S (gdt): Moved from here ...
+       * kern/i386/realmode.S (gdt)... to here.
+       * kern/i386/pc/startup.S (prot_to_real): Moved from here ...
+       * kern/i386/realmode.S (prot_to_real)... to here.
+
+       * kern/i386/pc/startup.S: Include `kern/i386/loader.S' and
+       `kern/i386/realmode.S'.
+
+2007-10-17  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/i386/loader.h: New file.
+
+       * include/grub/i386/pc/loader.h (grub_linux_prot_size)
+       (grub_linux_tmp_addr, grub_linux_real_addr, grub_os_area_addr)
+       (grub_os_area_size, grub_linux_boot_zimage, grub_linux_boot_bzimage)
+       (grub_multiboot_real_boot, grub_multiboot2_real_boot)
+       (grub_rescue_cmd_linux, grub_rescue_cmd_initrd): Moved from here ...
+       * include/grub/i386/loader.h (grub_linux_prot_size)
+       (grub_linux_tmp_addr, grub_linux_real_addr, grub_os_area_addr)
+       (grub_os_area_size, grub_linux_boot_zimage, grub_linux_boot_bzimage)
+       (grub_multiboot_real_boot, grub_multiboot2_real_boot)
+       (grub_rescue_cmd_linux, grub_rescue_cmd_initrd): ... to here.
+
+       * include/grub/i386/pc/loader.h: Include `grub/cpu/loader.h'.
+
+2007-10-15  Robert Millan  <rmh@aybabtu.com>
+
+       * normal/misc.c (grub_normal_print_device_info): Do not probe for
+       filesystem when dev->disk is unset.
+       Do probe for filesystem even when dev->disk->has_partitions is set.
+       In case a filesystem is found, always report it.
+       In case it isn't, if dev->disk->has_partitions is set, report that
+       a partition table was found instead of reporting that no filesystem
+       could be identified.
+
+2007-10-12  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/powerpc-ieee1275.rmk (grub_mkimage_SOURCES): Replace reference
+       to util/powerpc/ieee1275/grub-mkimage.c with util/elf/grub-mkimage.c.
+
+       * include/grub/types.h (grub_host_to_target16): New macro.
+       (grub_host_to_target32): Likewise.
+       (grub_host_to_target64): Likewise.
+       (grub_target_to_host16): Likewise.
+       (grub_target_to_host32): Likewise.
+       (grub_target_to_host64): Likewise.
+
+       * include/grub/powerpc/ieee1275/kernel.h (GRUB_IEEE1275_MOD_ALIGN):
+       Renamed from to ...
+       (GRUB_MOD_ALIGN): ...this.  Update all users.
+
+       * util/elf/grub-mkimage.c (load_note): Replace grub_cpu_to_be32 with
+       grub_host_to_target32.
+       Replace grub_be_to_cpu32 with grub_target_to_host32.
+       (load_modules): Likewise.
+       (add_segments): Replace grub_be_to_cpu16 with grub_target_to_host16.
+       Replace grub_be_to_cpu32 with grub_target_to_host32.
+       Replace grub_cpu_to_be16 with grub_host_to_target16.
+       Replace grub_cpu_to_be32 grub_host_to_target32.
+
+2007-10-12  Robert Millan  <rmh@aybabtu.com>
+
+       * util/powerpc/ieee1275/grub-mkimage.c: Moved to ...
+       * util/elf/grub-mkimage.c: ... here.
+
+       * DISTLIST: Add `util/elf/grub-mkimage.c'.  Remove
+       `util/powerpc/ieee1275/grub-mkimage.c'.
+
+2007-10-07  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/powerpc/ieee1275/init.c: Rename HEAP_LIMIT to HEAP_MAX_ADDR,
+       and make it easier to figure out.
+       Add HEAP_MIN_SIZE and HEAP_MAX_ADDR definitions.
+       (grub_claim_heap): Use HEAP_MAX_ADDR rather than taking a parameter.
+       Do not avoid claiming a region above HEAP_MAX_ADDR if that would
+       leave us with less than HEAP_MIN_SIZE total heap.
+       Avoid our total amount of heap to surpass HEAP_MAX_SIZE.
+
+2007-10-03  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/i386/io.h: New file.
+       * commands/i386/pc/play.c (inb): Removed.
+       (outb): Removed.
+       Include grub/cpu/io.h.  Replace inb() with grub_inb() and outb()
+       with grub_outb().
+       * term/i386/pc/serial.c  (inb): Removed.
+       (outb): Removed.
+       Include grub/cpu/io.h.  Replace inb() with grub_inb() and outb()
+       with grub_outb().
+       * term/i386/pc/vga.c  (inb): Removed.
+       (outb): Removed.
+       Include grub/cpu/io.h.  Replace inb() with grub_inb() and outb()
+       with grub_outb().
+
+2007-10-02  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Add util/hostfs.c.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       Reported by Marcin Kurek.
+
+2007-09-07  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_test_flag): Detect
+       SmartFirmware version updates (as released by Sven Luther), and avoid
+       setting GRUB_IEEE1275_FLAG_NO_PARTITION_0 or
+       GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS unless the running version is
+       known broken.
+
+2007-09-03  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       From Hitoshi Ozeki:
+       * kern/i386/pc/init.c (compact_mem_regions): Decrease NUM_REGIONS
+       when merging two regions.
+
+2007-09-03  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/rescue.c (grub_enter_rescue_mode): Free ARGS.
+       * normal/completion.c (grub_normal_do_completion): Likewise.
+       Reported by Hitoshi Ozeki.
+
+2007-09-03  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Do not use devices at boot in chainloading.
+
+       * loader/i386/pc/chainloader.c (boot_drive): New variable.
+       (boot_part_addr): Likewise.
+       (grub_chainloader_boot): Simply call grub_chainloader_real_boot
+       with BOOT_DRIVE and BOOT_PART_ADDR.
+       (grub_chainloader_cmd): Set BOOT_DRIVE and BOOT_PART_ADDR.
+       Reported by Hitoshi Ozeki <h-ozeki@ck2.so-net.ne.jp>.
+
+2007-08-29  Robert Millan  <rmh@aybabtu.com>
+
+       Patch from Simon Peter <dn.tlp@gmx.net>:
+       * genmk.rb (Utility): Append $(#{src}_DEPENDENCIES) to #{obj} targets.
+       * conf/i386-pc.rmk: Replace grub-probe_DEPENDENCIES with
+       util/grub-probe.c_DEPENDENCIES.  Replace grub-setup_DEPENDENCIES with
+       util/i386/pc/grub-setup.c_DEPENDENCIES.
+       * conf/i386-efi.rmk: Replace grub-probe_DEPENDENCIES with
+       util/grub-probe.c_DEPENDENCIES.
+       * conf/powerpc-ieee1275.rmk: Likewise.
+
+2007-08-28  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/get_disk_name.c: New.  Implement grub_util_get_disk_name()
+       to tell grub-mkdevicemap how to name devices.
+       * util/ieee1275/get_disk_name.c: Likewise (using "ofpathname -a"
+       feature).
+
+       * conf/i386-efi.rmk (grub_mkdevicemap_SOURCES): Add
+       util/i386/get_disk_name.c.
+       * conf/i386-pc.rmk (grub_mkdevicemap_SOURCES): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_mkdevicemap_SOURCES): Add
+       util/ieee1275/get_disk_name.c.
+
+       * include/grub/util/misc.h: grub_util_get_disk_name() declaration.
+
+       * DISTLIST: Add util/i386/get_disk_name.c and
+       util/ieee1275/get_disk_name.c.
+
+       * util/grub-mkdevicemap.c: Replace device naming logic with
+       grub_util_get_disk_name() calls.
+
+2007-08-20  Robert Millan  <rmh@aybabtu.com>
+
+       * normal/menu.c (run_menu): Refer to seconds as "s" not "seconds"
+       (so that it works for both plural and singular quantities).
+
+2007-08-05  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/10_linux.in (test_gt): Strip out vmlinu[xz]- prefix
+       so that [xz] isn't taken into account when determining order.
+
+2007-08-02  Marco Gerards  <marco@gnu.org>
+
+       * DISTLIST: Add `disk/host.c', `fs/ntfs.c', `include/multiboot.h',
+       `include/multiboot2.h', `include/grub/elfload.h',
+       `include/multiboot.h', `include/grub/multiboot.h',
+       `include/grub/multiboot_loader.h', `include/grub/multiboot2.h',
+       `include/grub/i386/pc/biosdisk.h', `include/grub/util/biosdisk.h',
+       `kern/elf.c', `loader/multiboot_loader.c',
+       `loader/multiboot_loader_normal.c', `loader/multiboot2.c',
+       `loader/i386/pc/multiboot2.c',
+       `loader/powerpc/ieee1275/multiboot2.c', `util/hostfs.c' and
+       `util/i386/pc/grub-mkrescue.in'.  Remove
+       `include/grub/biosdisk.h', `include/grub/i386/pc/multiboot.h',
+       `include/grub/i386/pc/util/biosdisk.h' and
+       `include/grub/powerpc/ieee1275/multiboot.h'.
+
+2007-08-02  Bean  <bean123ch@gmail.com>
+
+       * conf/common.rmk (pkgdata_MODULES): Add ntfs.mod.
+       (ntfs_mod_SOURCES): New variable.
+       (ntfs_mod_CFLAGS): Likewise.
+       (ntfs_mod_LDFLAGS): Likewise.
+
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/ntfs.c.
+       (grub_probe_SOURCES): Likewise.
+       (grub_emu_SOURCES): Likewise.
+
+       * conf/i386-efi.rmk (grub_probe_SOURCES): Add fs/ntfs.c.
+       (grub_emu_SOURCES): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (grub_probe_SOURCES): Add fs/ntfs.c.
+       (grub_emu_SOURCES): Likewise.
+
+       * conf/misc.c (grub_utf16_to_utf8): Fix unicode conversion bug.
+
+       * fs/ntfs.c: New file.
+
+2007-08-02  Bean  <bean123ch@gmail.com>
+
+       * disk.h (grub_disk): Use NESTED_FUNC_ATTR.
+
+       * file.h (grub_file): Likewise.
+
+       * fshelp.h (grub_fshelp_read_file): Likewise.
+
+       * util/i386/pc/grub-setup.c (setup): Likewise.
+       (save_first_sector): Likewise.
+       (save_blocklists): Likewise.
+
+       * fs/affs.c (grub_affs_read_file): Likewise.
+
+       * fs/ext2.c (grub_ext2_read_file): Likewise.
+
+       * fs/fat.c (grub_fat_read_data): Likewise.
+
+       * fs/fshelp.c (grub_fshelp_read_file): Likewise.
+
+       * fs/hfs.c (grub_hfs_read_file): Likewise.
+
+       * fs/hfsplus.c (grub_hfsplus_read_file): Likewise.
+
+       * fs/jfs.c (grub_jfs_read_file): Likewise.
+
+       * fs/minix.c (grub_minix_read_file): Likewise.
+
+       * fs/sfs.c (grub_sfs_read_file): Likewise.
+
+       * fs/ufs.c (grub_ufs_read_file): Likewise.
+
+       * fs/xfs.c (grub_xfs_read_file): Likewise.
+
+       * command/blocklist.c (read_blocklist): Likewise.
+       (print_blocklist): Likewise.
+
+2007-08-02  Marco Gerards  <marco@gnu.org>
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Add `disk/host.c' and
+       `util/hostfs.c'.
+
+       * disk/host.c: New file.
+
+       * util/hostfs.c: Likewise.
+
+       * fs/hfsplus.c (grub_hfsplus_mount): When reading out of disk,
+       return `GRUB_ERR_BAD_FS'.
+       * fs/sfs.c (grub_sfs_mount): Likewise.
+       * fs/xfs.c (grub_xfs_mount): Likewise.
+
+       * include/grub/disk.h (enum grub_disk_dev_id): Add
+       `GRUB_DISK_DEVICE_HOST_ID'.
+
+       * util/grub-emu.c (main): Initialize and de-initialize hostfs.
+
+2007-07-24  Jerone Young  <jerone@gmail.com>
+
+       * conf/i386-pc.rmk: Add Multiboot loader and multiboot 2 to multiboot
+       modules for compilation.
+       * conf/powerpc-ieee1275.rmk: Likewise.
+
+       * include/multiboot.h: Move multiboot definitions to one file. Rename
+       many definitions to not get grub specific.
+       * include/multiboot2.h: Create header with multiboot 2 definitions.
+       * include/grub/multiboot.h: Header for grub specific function
+       prototypes and definitions.
+       * include/grub/multiboot2.h: Likewise.
+       * include/grub/multiboot_loader.h: Likewise.
+       * include/grub/i386/pc/multiboot.h: Removed.
+       * include/grub/powerpc/ieee1275/multiboot.h: Removed.
+
+       * loader/multiboot_loader.c: Created to act as a proxy for multiboot 1
+       and 2 to allow for one multiboot and module commands.
+       * loader/multiboot2.c: Add multiboot2 functionality.
+       * loader/i386/pc/multiboot.c: Modify for new multiboot header location
+       and definition names.
+       * loader/i386/pc/multiboot2.c: Created to add i386 specific multiboot
+       2 functions.
+       * loader/powerpc/ieee1275/multiboot2.c: Created to add powerpc
+       ieee1275 specific multiboot2 code.
+
+       * kern/i386/pc/startup.S: Change headers and definition names for
+       multiboot. Add function grub_multiboot2_real_boot for multiboot 2.
+
+2007-07-22  Robert Millan  <rmh@aybabtu.com>
+
+       * geninitheader.sh: Process file specified in first parameter rather
+       than hardcoding grub_modules_init.lst.
+       * geninit.sh: Likewise.  Also, construct header name dynamically rather
+       than hardcoding grub_modules_init.h.
+
+       * conf/common.rmk: Rename grub_modules_init.[ch] files associated with
+       grub-emu to grub_emu_init.[ch].  Add rules to build analogous
+       grub_probe_init.[ch] and grub_setup_init.[ch].
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_DEPENDENCIES): Replace
+       grub_modules_init.h with grub_emu_init.h.
+       (grub_probe_DEPENDENCIES, grub_probe_SOURCES): Add new
+       grub_probe_init.[ch] files.
+       * conf/i386-efi.rmk: Likewise.
+       * conf/i386-pc.rmk: Likewise.
+       (grub_setup_DEPENDENCIES, grub_setup_SOURCES): Add new
+       grub_setup_init.[ch] files.
+
+       * util/grub-emu.c: Replace grub_modules_init.h with grub_emu_init.h.
+       * util/grub-probe.c: Include grub_probe_init.h.  Use grub_init_all()
+       to initialize modules rather than a list of hardcoded functions.
+       * util/i386/pc/grub-setup.c: Include grub_setup_init.h.  Use
+       grub_init_all() to initialize modules rather than a list of hardcoded
+       functions.
+
+2007-07-22  Robert Millan  <rmh@aybabtu.com>
+
+       * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_find_options): Set
+       GRUB_IEEE1275_FLAG_NO_PARTITION_0 flag when running on SmartFirmware.
+
+2007-07-22  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): Add
+       GRUB_IEEE1275_FLAG_BROKEN_OUTPUT flag.
+       * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_find_options): Set this
+       flag when running on SmartFirmware.
+       * term/ieee1275/ofconsole.c (grub_ofconsole_init): Avoid running
+       "output-device output" command when GRUB_IEEE1275_FLAG_BROKEN_OUTPUT
+       was set.
+
+       * kern/powerpc/ieee1275/openfw.c (grub_ieee1275_encode_devname):
+       Increase partno when GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS flag is set,
+       rather than decreasing it.
+
+       * util/i386/pc/grub-setup.c (setup): When embedding is required, but
+       there's not enough space to do it, fail in the same way as when it
+       can't be done because there are no partitions.
+
+       * util/powerpc/ieee1275/grub-install.in: Improve error message shown
+       when nvsetenv failed.
+
+2007-07-22  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * conf/i386-pc.rmk (CLEANFILES): Removed for grub-mkrescue,
+       because this rule is automatically generated.
+       (grub-mkrescue): Removed for the same reason as above.
+
+2007-07-22  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Migrate to GNU General Public License Version 3.
+
+       * COPYING: Replaced with the plain text version of GPLv3.
+
+       * config.guess: Updated from gnulib.
+       * config.sub: Likewise.
+
+       * geninit.sh: Output a GPLv3 copyright notice.
+       * geninitheader.sh: Likewise.
+       * genmodsrc.sh: Likewise.
+       * gensymlist.sh.in: Likewise.
+
+       * boot/i386/pc/boot.S: Upgraded to GPLv3.
+       * boot/i386/pc/diskboot.S: Likewise.
+       * boot/i386/pc/pxeboot.S: Likewise.
+       * commands/blocklist.c: Likewise.
+       * commands/boot.c: Likewise.
+       * commands/cat.c: Likewise.
+       * commands/cmp.c: Likewise.
+       * commands/configfile.c: Likewise.
+       * commands/echo.c: Likewise.
+       * commands/help.c: Likewise.
+       * commands/ls.c: Likewise.
+       * commands/search.c: Likewise.
+       * commands/terminal.c: Likewise.
+       * commands/test.c: Likewise.
+       * commands/videotest.c: Likewise.
+       * commands/i386/cpuid.c: Likewise.
+       * commands/i386/pc/halt.c: Likewise.
+       * commands/i386/pc/play.c: Likewise.
+       * commands/i386/pc/reboot.c: Likewise.
+       * commands/i386/pc/vbeinfo.c: Likewise.
+       * commands/i386/pc/vbetest.c: Likewise.
+       * commands/ieee1275/halt.c: Likewise.
+       * commands/ieee1275/reboot.c: Likewise.
+       * commands/ieee1275/suspend.c: Likewise.
+       * disk/loopback.c: Likewise.
+       * disk/lvm.c: Likewise.
+       * disk/raid.c: Likewise.
+       * disk/efi/efidisk.c: Likewise.
+       * disk/i386/pc/biosdisk.c: Likewise.
+       * disk/ieee1275/ofdisk.c: Likewise.
+       * font/manager.c: Likewise.
+       * fs/affs.c: Likewise.
+       * fs/ext2.c: Likewise.
+       * fs/fat.c: Likewise.
+       * fs/fshelp.c: Likewise.
+       * fs/hfs.c: Likewise.
+       * fs/hfsplus.c: Likewise.
+       * fs/iso9660.c: Likewise.
+       * fs/jfs.c: Likewise.
+       * fs/minix.c: Likewise.
+       * fs/sfs.c: Likewise.
+       * fs/ufs.c: Likewise.
+       * fs/xfs.c: Likewise.
+       * hello/hello.c: Likewise.
+       * include/grub/acorn_filecore.h: Likewise.
+       * include/grub/arg.h: Likewise.
+       * include/grub/bitmap.h: Likewise.
+       * include/grub/boot.h: Likewise.
+       * include/grub/cache.h: Likewise.
+       * include/grub/device.h: Likewise.
+       * include/grub/disk.h: Likewise.
+       * include/grub/dl.h: Likewise.
+       * include/grub/elfload.h: Likewise.
+       * include/grub/env.h: Likewise.
+       * include/grub/err.h: Likewise.
+       * include/grub/file.h: Likewise.
+       * include/grub/font.h: Likewise.
+       * include/grub/fs.h: Likewise.
+       * include/grub/fshelp.h: Likewise.
+       * include/grub/gzio.h: Likewise.
+       * include/grub/hfs.h: Likewise.
+       * include/grub/kernel.h: Likewise.
+       * include/grub/loader.h: Likewise.
+       * include/grub/lvm.h: Likewise.
+       * include/grub/misc.h: Likewise.
+       * include/grub/mm.h: Likewise.
+       * include/grub/net.h: Likewise.
+       * include/grub/normal.h: Likewise.
+       * include/grub/parser.h: Likewise.
+       * include/grub/partition.h: Likewise.
+       * include/grub/pc_partition.h: Likewise.
+       * include/grub/raid.h: Likewise.
+       * include/grub/rescue.h: Likewise.
+       * include/grub/script.h: Likewise.
+       * include/grub/setjmp.h: Likewise.
+       * include/grub/symbol.h: Likewise.
+       * include/grub/term.h: Likewise.
+       * include/grub/terminfo.h: Likewise.
+       * include/grub/tparm.h: Likewise.
+       * include/grub/types.h: Likewise.
+       * include/grub/video.h: Likewise.
+       * include/grub/efi/api.h: Likewise.
+       * include/grub/efi/chainloader.h: Likewise.
+       * include/grub/efi/console.h: Likewise.
+       * include/grub/efi/console_control.h: Likewise.
+       * include/grub/efi/disk.h: Likewise.
+       * include/grub/efi/efi.h: Likewise.
+       * include/grub/efi/pe32.h: Likewise.
+       * include/grub/efi/time.h: Likewise.
+       * include/grub/i386/linux.h: Likewise.
+       * include/grub/i386/setjmp.h: Likewise.
+       * include/grub/i386/types.h: Likewise.
+       * include/grub/i386/efi/kernel.h: Likewise.
+       * include/grub/i386/efi/loader.h: Likewise.
+       * include/grub/i386/efi/time.h: Likewise.
+       * include/grub/i386/pc/biosdisk.h: Likewise.
+       * include/grub/i386/pc/boot.h: Likewise.
+       * include/grub/i386/pc/chainloader.h: Likewise.
+       * include/grub/i386/pc/console.h: Likewise.
+       * include/grub/i386/pc/init.h: Likewise.
+       * include/grub/i386/pc/kernel.h: Likewise.
+       * include/grub/i386/pc/loader.h: Likewise.
+       * include/grub/i386/pc/memory.h: Likewise.
+       * include/grub/i386/pc/multiboot.h: Likewise.
+       * include/grub/i386/pc/serial.h: Likewise.
+       * include/grub/i386/pc/time.h: Likewise.
+       * include/grub/i386/pc/vbe.h: Likewise.
+       * include/grub/i386/pc/vbeblit.h: Likewise.
+       * include/grub/i386/pc/vbefill.h: Likewise.
+       * include/grub/i386/pc/vbeutil.h: Likewise.
+       * include/grub/i386/pc/vga.h: Likewise.
+       * include/grub/ieee1275/ieee1275.h: Likewise.
+       * include/grub/ieee1275/ofdisk.h: Likewise.
+       * include/grub/powerpc/libgcc.h: Likewise.
+       * include/grub/powerpc/setjmp.h: Likewise.
+       * include/grub/powerpc/types.h: Likewise.
+       * include/grub/powerpc/ieee1275/biosdisk.h: Likewise.
+       * include/grub/powerpc/ieee1275/console.h: Likewise.
+       * include/grub/powerpc/ieee1275/ieee1275.h: Likewise.
+       * include/grub/powerpc/ieee1275/kernel.h: Likewise.
+       * include/grub/powerpc/ieee1275/loader.h: Likewise.
+       * include/grub/powerpc/ieee1275/multiboot.h: Likewise.
+       * include/grub/powerpc/ieee1275/time.h: Likewise.
+       * include/grub/powerpc/ieee1275/util/biosdisk.h: Likewise.
+       * include/grub/sparc64/libgcc.h: Likewise.
+       * include/grub/sparc64/setjmp.h: Likewise.
+       * include/grub/sparc64/types.h: Likewise.
+       * include/grub/sparc64/ieee1275/console.h: Likewise.
+       * include/grub/sparc64/ieee1275/ieee1275.h: Likewise.
+       * include/grub/sparc64/ieee1275/kernel.h: Likewise.
+       * include/grub/sparc64/ieee1275/time.h: Likewise.
+       * include/grub/util/biosdisk.h: Likewise.
+       * include/grub/util/getroot.h: Likewise.
+       * include/grub/util/lvm.h: Likewise.
+       * include/grub/util/misc.h: Likewise.
+       * include/grub/util/raid.h: Likewise.
+       * include/grub/util/resolve.h: Likewise.
+       * io/gzio.c: Likewise.
+       * kern/device.c: Likewise.
+       * kern/disk.c: Likewise.
+       * kern/dl.c: Likewise.
+       * kern/elf.c: Likewise.
+       * kern/env.c: Likewise.
+       * kern/err.c: Likewise.
+       * kern/file.c: Likewise.
+       * kern/fs.c: Likewise.
+       * kern/loader.c: Likewise.
+       * kern/main.c: Likewise.
+       * kern/misc.c: Likewise.
+       * kern/mm.c: Likewise.
+       * kern/parser.c: Likewise.
+       * kern/partition.c: Likewise.
+       * kern/rescue.c: Likewise.
+       * kern/term.c: Likewise.
+       * kern/efi/efi.c: Likewise.
+       * kern/efi/init.c: Likewise.
+       * kern/efi/mm.c: Likewise.
+       * kern/i386/dl.c: Likewise.
+       * kern/i386/efi/init.c: Likewise.
+       * kern/i386/efi/startup.S: Likewise.
+       * kern/i386/pc/init.c: Likewise.
+       * kern/i386/pc/lzo1x.S: Likewise.
+       * kern/i386/pc/startup.S: Likewise.
+       * kern/ieee1275/ieee1275.c: Likewise.
+       * kern/powerpc/cache.S: Likewise.
+       * kern/powerpc/dl.c: Likewise.
+       * kern/powerpc/ieee1275/cmain.c: Likewise.
+       * kern/powerpc/ieee1275/crt0.S: Likewise.
+       * kern/powerpc/ieee1275/init.c: Likewise.
+       * kern/powerpc/ieee1275/openfw.c: Likewise.
+       * kern/sparc64/cache.S: Likewise.
+       * kern/sparc64/dl.c: Likewise.
+       * kern/sparc64/ieee1275/init.c: Likewise.
+       * kern/sparc64/ieee1275/openfw.c: Likewise.
+       * loader/efi/chainloader.c: Likewise.
+       * loader/efi/chainloader_normal.c: Likewise.
+       * loader/i386/efi/linux.c: Likewise.
+       * loader/i386/efi/linux_normal.c: Likewise.
+       * loader/i386/pc/chainloader.c: Likewise.
+       * loader/i386/pc/chainloader_normal.c: Likewise.
+       * loader/i386/pc/linux.c: Likewise.
+       * loader/i386/pc/linux_normal.c: Likewise.
+       * loader/i386/pc/multiboot.c: Likewise.
+       * loader/i386/pc/multiboot_normal.c: Likewise.
+       * loader/powerpc/ieee1275/linux.c: Likewise.
+       * loader/powerpc/ieee1275/linux_normal.c: Likewise.
+       * normal/arg.c: Likewise.
+       * normal/cmdline.c: Likewise.
+       * normal/command.c: Likewise.
+       * normal/completion.c: Likewise.
+       * normal/execute.c: Likewise.
+       * normal/function.c: Likewise.
+       * normal/lexer.c: Likewise.
+       * normal/main.c: Likewise.
+       * normal/menu.c: Likewise.
+       * normal/menu_entry.c: Likewise.
+       * normal/misc.c: Likewise.
+       * normal/parser.y: Likewise.
+       * normal/script.c: Likewise.
+       * normal/i386/setjmp.S: Likewise.
+       * normal/powerpc/setjmp.S: Likewise.
+       * normal/sparc64/setjmp.S: Likewise.
+       * partmap/acorn.c: Likewise.
+       * partmap/amiga.c: Likewise.
+       * partmap/apple.c: Likewise.
+       * partmap/gpt.c: Likewise.
+       * partmap/pc.c: Likewise.
+       * partmap/sun.c: Likewise.
+       * term/gfxterm.c: Likewise.
+       * term/terminfo.c: Likewise.
+       * term/efi/console.c: Likewise.
+       * term/i386/pc/console.c: Likewise.
+       * term/i386/pc/serial.c: Likewise.
+       * term/i386/pc/vesafb.c: Likewise.
+       * term/i386/pc/vga.c: Likewise.
+       * term/ieee1275/ofconsole.c: Likewise.
+       * util/biosdisk.c: Likewise.
+       * util/console.c: Likewise.
+       * util/genmoddep.c: Likewise.
+       * util/getroot.c: Likewise.
+       * util/grub-emu.c: Likewise.
+       * util/grub-mkdevicemap.c: Likewise.
+       * util/grub-probe.c: Likewise.
+       * util/lvm.c: Likewise.
+       * util/misc.c: Likewise.
+       * util/raid.c: Likewise.
+       * util/resolve.c: Likewise.
+       * util/update-grub.in: Likewise.
+       * util/update-grub_lib.in: Likewise.
+       * util/grub.d/00_header.in: Likewise.
+       * util/grub.d/10_hurd.in: Likewise.
+       * util/grub.d/10_linux.in: Likewise.
+       * util/i386/efi/grub-install.in: Likewise.
+       * util/i386/efi/grub-mkimage.c: Likewise.
+       * util/i386/pc/grub-install.in: Likewise.
+       * util/i386/pc/grub-mkimage.c: Likewise.
+       * util/i386/pc/grub-mkrescue.in: Likewise.
+       * util/i386/pc/grub-setup.c: Likewise.
+       * util/i386/pc/misc.c: Likewise.
+       * util/powerpc/ieee1275/grub-install.in: Likewise.
+       * util/powerpc/ieee1275/grub-mkimage.c: Likewise.
+       * util/powerpc/ieee1275/misc.c: Likewise.
+       * video/bitmap.c: Likewise.
+       * video/video.c: Likewise.
+       * video/i386/pc/vbe.c: Likewise.
+       * video/i386/pc/vbeblit.c: Likewise.
+       * video/i386/pc/vbefill.c: Likewise.
+       * video/i386/pc/vbeutil.c: Likewise.
+       * video/readers/tga.c: Likewise.
+
+2007-07-02  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-efi.rmk: Replace obsolete reference to
+       util/i386/pc/biosdisk.c with util/biosdisk.c, and util/i386/pc/getroot.c
+       with util/getroot.c.
+       * conf/powerpc-ieee1275.rmk: Likewise.
+       * conf/sparc64-ieee1275.rmk: Likewise.
+
+       * util/grub-emu.c (main): Fix unchecked pointer handling.
+
+2007-07-02  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/efi/grub-install.in: Allow `grub_probe --target=partmap'
+       invocation to fail, in order to support partition-less media.
+
+       * util/i386/pc/grub-install.in: Likewise.
+
+       * util/powerpc/ieee1275/grub-install.in: Use grub-probe to determine
+       which fs or partmap modules are needed (akin to its sister scripts).
+
+       Also use grub-probe to get rid of unportable /proc/mounts check.
+
+       Print the same informational message that the other scripts do, before
+       exiting.
+
+2007-06-23  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub_lib.in (font_path): New function.  Determine whether
+       a font file can be found and, if so, echo the GRUB path to it.
+
+       * util/update-grub.in: Handle multiple terminals depending on user
+       input, platform availability and font file presence.  Propagate
+       variables of our findings to /etc/grub.d/ children.
+
+       * util/grub.d/00_header.in: Handle multiple terminals, based on
+       environment setup by update-grub.
+
+2007-06-23  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-pc.rmk (pkgdata_MODULES): Add serial.mod.
+
+2007-06-21  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/i386/pc/kernel.h: Define GRUB_KERNEL_MACHINE_DATA_END to
+       indicate end of data section in kernel image.
+       * include/grub/i386/efi/kernel.h: Define GRUB_KERNEL_MACHINE_PREFIX and
+       GRUB_KERNEL_MACHINE_DATA_END.
+
+       * kern/i386/pc/startup.S: Do not initialize grub_prefix, only reserve
+       space for it.
+       * kern/i386/efi/startup.S: Likewise.
+
+       * util/i386/pc/grub-mkimage.c: Initialize grub_prefix to /boot/grub
+       during image generation.  Implement --prefix option to override this
+       patch.
+       * util/i386/efi/grub-mkimage.c: Likewise.
+
+       * util/update-grub_lib.in (convert_system_path_to_grub_path): Split
+       code to make path relative to its root into a separate function.
+
+       * util/i386/pc/grub-install.in: Use newly provided
+       make_system_path_relative_to_its_root() to convert ${grubdir}, then
+       pass the result to grub-install --prefix.
+
+2007-06-13  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/util/misc.h: Define DEFAULT_DIRECTORY and
+       DEFAULT_DEVICE_MAP.
+       * util/grub-emu.c: Use above definitions from misc.h instead of
+       defining them.
+       * util/grub-mkdevicemap.c: Likewise.
+       * util/i386/pc/grub-setup.c: Likewise.
+       * util/grub-probe.c: Likewise.
+       (probe): Abort with grub_util_error() when either
+       grub_guess_root_device or grub_util_get_grub_dev fails.
+
+2007-06-12  Robert Millan  <rmh@aybabtu.com>
+
+       * normal/command.c (grub_command_execute): Use NULL rather than 0 for
+       "pager" assignment.
+       * util/biosdisk.c (grub_util_biosdisk_get_grub_dev): Likewise for
+       "pcdata".
+       * util/grub-probe.c (probe): Likewise for "drive_name".
+
+2007-06-11  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-mkrescue.in: Pad both floppy images with zeroes,
+       not just the cdrom one.
+
+2007-06-11  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-mkrescue.in: Add "set -e".
+       Add --pkglibdir=DIR option to override pkglibdir.
+       Mention --image-type=TYPE in help output.
+       Fix --grub-mkimage (it was a no-op).
+       Abort gracefully when no parameter is given.
+
+2007-06-11  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-mkrescue.in: New file.
+       * conf/i386-pc.rmk: Add its build declarations.  Put it in bin_SCRIPTS.
+       * Makefile.in: Handle bin_SCRIPTS.
+
+2007-06-10  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * term/gfxterm.c (grub_gfxterm_init): Added support for specifying
+       list of video modes.
+
+2007-06-06  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub_lib.in (convert_system_path_to_grub_path): Abort if
+       file doesn't exist, or if it is in a filesystem grub can't read.
+
+       * util/update-grub.in: Set fallback for GRUB_FS check to "unknown".  Do
+       not abort if GRUB_DRIVE could not be defined.  Rearrange generated
+       header comment to fit in 80 columns when the variables are resolved.
+
+       * util/grub.d/00_header.in: Only set root variable when GRUB_DRIVE
+       could be identified by update-grub.  Remove redundant check for
+       unifont.pff existence (since convert_system_path_to_grub_path now
+       handles that).
+
+2007-06-04  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-efi.rmk (grub_probe_SOURCES): Add partmap/apple.c.
+
+       * conf/i386-pc.rmk (grub_probe_SOURCES): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (grub_probe_SOURCES): Add partmap/pc.c.
+
+2007-06-04  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/powerpc-ieee1275.rmk: Enable grub-mkdevicemap and grub-probe.
+
+       * include/grub/partition.h: Declare grub_apple_partition_map_init and
+       grub_apple_partition_map_fini.
+
+       * util/biosdisk.c
+       (grub_util_biosdisk_open): Replace BLKGETSIZE with BLKGETSIZE64 (needed
+       to access >2 TiB disks).
+
+       Print disk->total_sectors with %llu instead of %lu, since this
+       variable is always 64-bit (prevents wrong disk size from being displayed
+       on either >2 TiB disk or big-endian CPU).
+
+       (grub_util_biosdisk_get_grub_dev): Convert gpt_partition_map handling
+       into a generic case that supports all (sane) partition maps.
+
+       Stop using grub_cpu_to_le32() on dos_part / bsd_part since it actually
+       breaks big-endian.
+
+       * util/grub-probe.c: Call grub_apple_partition_map_init() before probe()
+       and grub_apple_partition_map_fini() after that.
+
+2007-06-01  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub.in: Export GRUB_CMDLINE_LINUX.
+
+       * util/grub.d/00_header.in: Only enable gfxterm when
+       convert_system_path_to_grub_path() succeeds.
+
+2007-05-20  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub_lib.in: New file.
+       * DISTLIST: Add update-grub_lib.in.
+       * conf/common.rmk: Generate update-grub_lib and install it in
+       $(lib_DATA).
+       * Makefile.in: Add install routine for $(lib_DATA).
+
+       * util/grub.d/00_header.in: Use convert_system_path_to_grub_path()
+       function provided by update-grub_lib to support arbitrary paths of
+       unifont.pff.
+       * util/update-grub.in: Use convert_system_path_to_grub_path() to
+       initialize GRUB_DRIVE_BOOT and GRUB_DRIVE_BOOT_GRUB variables.
+
+2007-05-19  Robert Millan  <rmh@aybabtu.com>
+
+       * commands/i386/cpuid.c: New module.
+       * DISTLIST: Add it.
+       * conf/i386-efi.rmk: Enable cpuid.mod.
+       * conf/i386-pc.rmk: Likewise.
+
+2007-05-18  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * kern/disk.c (grub_disk_read): Check return value of
+       grub_realloc().
+
+2007-05-18  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * util/getroot.c (grub_util_get_grub_dev): Support partitionable
+       arrays.
+       * disk/raid.c (grub_raid_open): Likewise.
+
+2007-05-17  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * util/biosdisk.c (linux_find_partition): Allocate real_dev on the
+       stack instead of on the heap.
+
+       * kern/disk.c (grub_disk_read): Make sure tmp_buf is big enough
+       before doing a read on it.
+
+       * configure.ac: Only use -fno-stack-protector for the target
+       environment.
+
+2007-05-17  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * video/i386/pc/vbe.c (grub_video_vbe_create_render_target): Add
+       __attribute_ ((unused)) to mode_type argument.
+
+       * util/getroot.c (grub_guess_root_device): Fix #endif.
+
+       * kern/misc.c (memcmp): Fix prototype.
+
+       * include/grub/partition.h [GRUB_UTIL]
+       (grub_gpt_partition_map_init): Add prototype.
+       (grub_gpt_partition_map_fini): Likewise.
+
+       * fs/jfs.c (struct grub_jfs_inode): Put __attribute__ ((packed)
+       at the right place.
+
+       * fs/fat.c (grub_fat_mount): Replace ~0UL with ~0U.
+       (grub_fat_read_data): Likewise.
+       (grub_fat_find_dir): Likewise.
+
+       * font/manager.c (find_glyph): Make table a const.
+       (grub_font_get_glyph): Remove bitmap from if statement.
+
+2007-05-16  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * util/getroot.c (grub_guess_root_device): Remove RAID and LVM
+       code, first search for device in /dev/mapper, then in /dev.
+       (grub_util_get_grub_dev): New function.
+       * include/grub/util/getroot.h (grub_util_get_grub_dev): Add
+       prototype.
+       * util/grub-probe.c (probe): Remove check for RAID, call
+       grub_util_get_grub_dev() instead of
+       grub_util_biosdisk_get_grub_dev().
+       * util/grub-emu.c (main): Call grub_util_get_grub_dev() instead of
+       grub_util_biosdisk_get_grub_dev().
+       * util/i386/pc/grub-setup.c (main): Likewise.
+
+2007-05-16  Robert Millan  <rmh@aybabtu.com>
+
+       * DISTLIST: Update for the latest changes.
+       * conf/i386-pc.rmk: Use the new paths for util/getroot.c,
+       util/grub-mkdevicemap.c, util/grub-probe.c and util/biosdisk.c.
+       * util/grub-emu.c: Replace grub/i386/pc/util/biosdisk.h with
+       grub/util/biosdisk.h.
+       * util/i386/pc/grub-setup.c: Replace grub/machine/util/biosdisk.h with
+       grub/util/biosdisk.h.
+
+2007-05-16  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/00_header.in: Set default gfxmode to `640x480'.
+
+2007-05-16  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/efi/grub-install.in: New.
+       * conf/i386-efi.rmk: Enable grub-mkdevicemap, grub-probe and the
+       newly added grub-install.
+       * util/biosdisk.c: Remove unnecessary grub/machine/biosdisk.h
+       include.
+       * util/getroot.c: Replace grub/i386/pc/util/biosdisk.h with
+       grub/util/biosdisk.h.
+       * util/grub-probe.c: Replace grub/machine/util/biosdisk.h with
+       grub/util/biosdisk.h.
+
+2007-05-16  Robert Millan  <rmh@aybabtu.com>
+
+       * include/grub/i386/pc/util/biosdisk.h: Moved to ...
+       * include/grub/util/biosdisk.h: ... here.
+       * util/i386/pc/biosdisk.c: Moved to ...
+       * util/biosdisk.c: ... here.
+       * util/i386/pc/getroot.c: Moved to ...
+       * util/getroot.c: ... here.
+       * util/i386/pc/grub-mkdevicemap.c: Moved to ...
+       * util/grub-mkdevicemap.c: ... here.
+       * util/i386/pc/grub-probe.c: Moved to ...
+       * util/grub-probe.c: ... here.
+
+2007-05-15  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub.in: Remove duplicated line in grub.cfg header
+       message.
+
+2007-05-13  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub.in: Fix a few assumptions about the devices holding
+       /, /boot and /boot/grub being the same.
+       * util/grub.d/00_header.in: Likewise.
+       * util/grub.d/10_hurd.in: Likewise.
+       * util/grub.d/10_linux.in: Likewise.
+
+       * util/grub.d/10_linux.in: Implement Linux image sorting with arbitrary
+       patterns.  Use that to define the `.old' suffix as older than `'.
+
+       * util/grub.d/00_header.in: Set default gfxmode to `800x600x16'.
+
+       * util/update-grub.in: Add a reference to ${sysconfdir}/default/grub in
+       the grub.cfg header message.
+
+2007-05-11  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub.in: Create device.map if it doesn't already exist,
+       before attempting to run grub-probe.
+       Check for grub-probe and grub-mkdevicemap with the same code
+       grub-install is using.
+       Remove test mode.
+
+2007-05-09  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * Makefile.in: Add the datarootdir autoconf variable.
+
+2007-05-09  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-probe.c (probe): When detecting partition map,
+       fail gracefully if dev->disk->partition == NULL.
+
+2007-05-07  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-probe.c: Add `grub-probe -t partmap' parameter to
+       determine partition map module.
+       * util/i386/pc/grub-install.in: Use this feature to decide which
+       partition module to load, instead of hardcoding pc and gpt.
+
+2007-05-07  Robert Millan  <rmh@aybabtu.com>
+
+       * Makefile.in: Fix assumption that $(srcdir) has a trailing slash when
+       source directory differs from build directory.
+
+2007-05-05  Robert Millan  <rmh@aybabtu.com>
+
+       * util/powerpc/ieee1275/grub-install.in: Fix syntax error in pkglibdir
+       initialisation.
+
+2007-05-05  Robert Millan  <rmh@aybabtu.com>
+
+       * util/update-grub.in: Create ${grub_prefix} if it doesn't exist.
+
+2007-05-05  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub.d/10_linux.in: Allow the administrator to insert Linux
+       command-line arguments via ${GRUB_CMDLINE_LINUX}.
+
+2007-05-05  Robert Millan  <rmh@aybabtu.com>
+
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Add partmap/gpt.c.
+       (grub_probe_SOURCES): Likewise.
+       * util/i386/pc/biosdisk.c (grub_util_biosdisk_get_grub_dev): Detect
+       GPT and initialize dos_part and bsd_part accordingly.
+       * util/i386/pc/grub-setup.c (setup): Ditto for install_dos_part and
+       install_bsd_part.
+       (main): Activate gpt module for use during partition identification,
+       and deactivate it afterwards.
+       * util/i386/pc/grub-install.in: Add gpt module to core.img.
+       * util/i386/pc/grub-probe.c (main): Activate gpt module for use during
+       partition identification, and deactivate it afterwards.
+
+2007-05-05  Robert Millan  <rmh@aybabtu.com>
+
+       * term/i386/pc/console.c (grub_console_fini): Call
+       grub_term_set_current() before grub_term_unregister().
+
+2007-05-04  Robert Millan  <rmh@aybabtu.com>
+
+       * DISTLIST: Add util/update-grub.in, util/grub.d/00_header.in,
+       util/grub.d/10_hurd.in, util/grub.d/10_linux.in and util/grub.d/README.
+       * Makefile.in: Build update-grub_SCRIPTS.  Install update-grub_SCRIPTS
+       and update-grub_DATA.
+       * conf/common.rmk: Build and install update-grub components.
+       * conf/common.mk: Regenerate.
+       * util/update-grub.in: New.  Core of update-grub.
+       * util/grub.d/00_header.in: New.  Generates grub.cfg header.
+       * util/grub.d/10_hurd.in: New.  Generates boot entries for the Hurd.
+       * util/grub.d/10_linux.in: New.  Generates boot entries for Linux.
+       * util/grub.d/README: New.  Document grub.d directory layout.
+
+2007-05-01  Robert Millan  <rmh@aybabtu.com>
+
+       * util/grub-emu.c: Move initialization functions
+       grub_util_biosdisk_init() and grub_init_all() before
+       grub_util_biosdisk_get_grub_dev(), which relies on them.
+
+2007-04-19  Robert Millan  <rmh@aybabtu.com>
+
+       * util/powerpc/ieee1275/grub-install.in: Initialize ${bindir}, since
+       it is used later.
+
+2007-04-18  Jerone Young  <jerone@gmail.com>
+
+       * kernel/elf.c: Add missing parenthesis for conditional statement
+       stanza.
+
+2007-04-10  Jerone Young  <jerone@gmail.com>
+
+       * util/i386/pc/getroot.c: Update so that if root device is /dev/root ,
+       continue on and look for device node with real device name.
+
+2007-04-10  Jerone Young  <jerone@gmail.com>
+
+       * configure.ac: Add argument for autoconf to use transformation
+       ability.
+       * Makefile.in: Add autoconf package transformation code.
+       * util/i386/pc/grub-install.in: Likewise.
+       * util/powerpc/ieee1275/grub-install.in: Likewise.
+
+2007-03-19  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * fs/ext2.c (EXT2_GOOD_OLD_REVISION): New macro.
+       (EXT2_GOOD_OLD_INODE_SIZE): Likewise.
+       (EXT2_REVISION): Likewise.
+       (EXT2_INODE_SIZE): Likewise.
+       (struct grub_ext2_block_group): Added a missing member
+       "used_dirs".
+       (grub_ext2_read_inode): Divide by the inode size in a superblock
+       instead of 128 to obtain INODES_PER_BLOCK.
+       Use the macro EXT2_INODE_SIZE instead of directly using
+       SBLOCK->INODE_SIZE.
+
+2007-03-18  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * fs/ext2.c (grub_ext2_read_inode): Use the inode size in a
+       superblock instead of the structure size to compute an
+       offset. This fixes the problem that GRUB could not read a
+       filesystem when inode size is different from 128-byte.
+
+2007-03-05  Marco Gerards  <marco@gnu.org>
+
+       * normal/main.c (read_config_file): When "menu" is not set, create
+       an initial context.
+
+2007-02-21  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/powerpc/ieee1275/init.c (HEAP_SIZE): Removed.
+       (HEAP_LIMIT): New macro.
+       (grub_claim_heap): Claim memory up to `heaplimit'.
+
+2007-02-21  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * conf/powerpc-ieee1275.rmk (kernel_elf_LDFLAGS): Link at 64KB.
+       * kern/powerpc/ieee1275/init.c (_end): Add declaration.
+       (_start): Likewise.
+       (grub_arch_modules_addr): Return address after `_end'.
+       * util/powerpc/ieee1275/grub-mkimage.c: Include grub/misc.h.
+       (load_modules): Use new parameter as `p_paddr' and `p_vaddr'.
+       (add_segments): Calculate `_end' from phdr size and location.
+       (ALIGN_UP): Moved to ...
+       * include/grub/misc.h: here.
+       * include/grub/powerpc/ieee1275/kernel.h (GRUB_IEEE1275_MOD_ALIGN):
+       New macro.
+       (GRUB_IEEE1275_MODULE_BASE): Removed.
+
+2007-02-20  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/powerpc/ieee1275/openfw.c (grub_available_iterate): Correct
+       loop boundary.
+
+2007-02-20  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * include/grub/elfload.h (grub_elf32_load_hook_t): Return grub_err_t.
+       All users updated.
+       (grub_elf64_load_hook_t): Likewise.
+       * kern/elf.c: Call `grub_error_push' before `grub_error'. Improve
+       debug output.
+
+2007-02-20  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/mm.c: Update copyright.
+       (grub_mm_debug): Correct syntax error.
+       (grub_mm_dump_free): New function.
+       (grub_debug_free): Call `grub_free'.
+       * include/grub/mm.h: Update copyright.
+       (grub_mm_dump_free): Add declaration.
+
+2007-02-12  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * include/grub/ieee1275/ieee1275.h: Update copyright.
+       * kern/powerpc/ieee1275/init.c: Likewise.
+       * kern/powerpc/ieee1275/openfw.c: Likewise.
+
+       * loader/powerpc/ieee1275/linux.c: Likewise.
+       * include/grub/elfload.h: Likewise.
+       * kern/elf.c: Likewise.
+       (grub_elf32_load): Pass `base' and `size' parameters.  Update all
+       callers.
+       (grub_elf64_load): Likewise.
+       (grub_elf32_load_segment): Move to a nested function.
+       (grub_elf64_load_segment): Likewise.
+
+2007-02-12  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * include/grub/ieee1275/ieee1275.h (grub_available_iterate): New
+       prototype.
+       * kern/powerpc/ieee1275/init.c (grub_heap_start): Removed.
+       (grub_heap_len): Likewise.
+       (HEAP_SIZE): New macro.
+       (grub_claim_heap): New function.
+       (grub_machine_init): Don't claim heap directly.  Call
+       `grub_claim_heap'.
+       * kern/powerpc/ieee1275/openfw.c: Include alloca.h.
+       (grub_available_iterate): New function.
+
+2007-02-03  Thomas Schwinge  <tschwinge@gnu.org>
+
+       * aclocal.m4 (grub_CHECK_STACK_PROTECTOR): New definition.
+       * configure.ac: Use it for testing the HOST and TARGET compilers.
+
+2006-12-13  Thomas Schwinge  <tschwinge@gnu.org>
+
+       * Makefile.in (enable_grub_emu): New variable.
+       * configure.ac (--enable-grub-emu): New option.
+       Do the checks for (n)curses only if `--enable-grub-emu' is requested.
+       * conf/i386-efi.rmk (sbin_UTILITIES): Add `grub-emu' only if requested.
+       * conf/i386-pc.rmk: Likewise.
+       * conf/powerpc-ieee1275.rmk: Likewise.
+       * conf/sparc64-ieee1275.rmk (bin_UTILITIES): Likewise.
+
+2006-12-12  Marco Gerards  <marco@gnu.org>
+
+       * include/grub/err.h (grub_err_t): Add `GRUB_ERR_MENU'.
+
+       * kern/env.c (grub_env_unset): Don't free the member `value' when
+       the type is GRUB_ENV_VAR_DATA, in this case it's a user defined
+       pointer.
+
+       * normal/main.c (current_menu): Removed.
+       (free_menu): Unset the `menu' environment variable.
+       (grub_normal_menu_addentry): Make use of the environment variable
+       `menu', instead of using the global `current_menu'.  Allocate
+       memory for the sourcecode of this entry.
+       (read_config_file): New argument `nested', changed all callers.
+       Only in the case of a new context, initialize a new menu.  Set the
+       `menu' environment variable.
+       (grub_normal_execute): Don't set and unset the environment
+       variable `menu' here anymore.  Only free the menu when leaving the
+       context.
+
+       * util/i386/pc/biosdisk.c (linux_find_partition): Fixed a memory
+       leak.
+
+2006-12-11  Marco Gerards  <marco@gnu.org>
+
+       * normal/menu_entry.c (run): Fix off by one bug so the last line
+       is executed.  Move the loader check to outside the loop.
+
+2006-12-08  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/powerpc/ieee1275/cmain.c (cmain): Mark r3 and r4 as `UNUSED'.
+
+2006-11-25  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * util/i386/pc/grub-mkimage.c (generate_image): Fix the offset of
+       the number of sectors.  Reported by Andrey Shuvikov
+       <mr_hyro@yahoo.com>.
+
+2006-11-11  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * kern/disk.c (grub_disk_read): When there is a read error, always
+       try to read only the necessary data.
+
+       * conf/i386-pc.rmk (grub_probe_SOURCES): Add disk/lvm.c and
+       disk/raid.c.
+       * include/grub/disk.h [GRUB_UTIL] (grub_raid_init): New
+       prototype.
+       [GRUB_UTIL] (grub_raid_fini): Likewise.
+       [GRUB_UTIL] (grub_lvm_init): Likewise.
+       [GRUB_UTIL] (grub_lvm_fini): Likewise.
+       * util/i386/pc/grub-probe.c (probe): Check whether DEVICE_NAME is
+       RAID device and copy DEVICE_NAME to DRIVE_NAME in that case.
+       (main): Call grub_raid_init(), grub_lvm_init(), grub_lvm_fini()
+       and grub_raid_fini().
+
+2006-11-09  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * include/grub/types.h (__unused): Rename to UNUSED.
+       * kern/elf.c (grub_elf32_size): Use UNUSED instead of __unused.
+       (grub_elf64_size): Likewise.
+
+2006-11-03  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/elf.c (grub_elf_file): Call grub_file_seek. Call
+       grub_error_push and grub_error_pop in the error-handling path.
+       (grub_elf32_load_segment): Only call grub_file_read with non-zero
+       length.
+
+2006-11-03  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Add kern/elf.c.
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       (kernel_elf_SOURCES): Likewise.
+       * conf/i386-efi.rmk (kernel_mod_HEADERS): Add elfload.h and cache.h.
+       * conf/i386-pc.rmk (kernel_mod_HEADERS): Likewise.
+       * conf/powerpc-ieee1275.rmk (kernel_elf_HEADERS): Likewise.
+       * conf/sparc64-ieee1275.rmk (kernel_elf_HEADERS): Likewise.
+       * conf/common.rmk (pkgdata_MODULES): Add elf.mod.
+       (elf_mod_SOURCES): New variable.
+       (elf_mod_CFLAGS): Likewise.
+       (elf_mod_LDFLAGS): Likewise.
+       * include/grub/types.h (__unused): New macro.
+       * include/grub/elfload.h: New file.
+       * kern/elf.c: Likewise.
+       * loader/powerpc/ieee1275/linux.c: Include elfload.h.
+       (ELF32_LOADMASK): New macro.
+       (ELF64_LOADMASK): Likewise.
+       (vmlinux): Removed.
+       (grub_linux_load32): New function.
+       (grub_linux_load64): Likewise.
+       (grub_rescue_cmd_linux): Call grub_linux_load32 or grub_linux_load64.
+       Use grub_elf_t instead of grub_file_t.
+
+2006-11-02  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/ieee1275/ieee1275.c (grub_ieee1275_set_color): Add
+       `catch_result' to struct set_color_args.
+
+2006-10-28  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * normal/menu.c: Include grub/script.h.
+       * normal/menu_entry.c: Likewise.
+       * include/grub/normal.h: Do not include grub/script.h.
+
+2006-10-27  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/disk.c (grub_disk_read): Correct debug printf formatting.
+
+2006-10-27  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/disk.c (grub_disk_open): Print debug messages when opening a
+       disk.
+       (grub_disk_close): Print debug messages when closing a disk.
+       (grub_disk_read): Print debug messages when disk read fails.
+       * kern/fs.c (grub_fs_probe): Print debug messages when detecting
+       filesystem type.
+       * kern/partition.c: Include misc.h.
+       (grub_partition_iterate): Print debug messages when detecting
+       partition type.
+
+2006-10-27  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * disk/ieee1275/ofdisk.c (grub_ofdisk_read): Return error if `status'
+       is negative.
+       * kern/ieee1275/ieee1275.c (IEEE1275_IHANDLE_INVALID): Change to 0.
+
+2006-10-26  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/powerpc/ieee1275/openfw.c (grub_ieee1275_encode_devname):
+       Reverse GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS test.
+
+2006-10-25  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * disk/lvm.c (grub_lvm_scan_device): Malloc sizeof(*lv) bytes
+       instead of sizeof(lv). Patch by Michael Guntsche.
+
+2006-10-18  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * disk/lvm.c: Rename VGS to VG_LIST.
+       (grub_lvm_iterate): Change VGS->LV to VG-LV.
+       (grub_lvm_open): Likewise.
+       Thanks to Michael Guntsche for finding this bug.
+
+2006-10-15  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * configure.ac (AC_INIT): Bumped to 1.95.
+
+2006-10-14  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/getroot.c (grub_guess_root_device): Don't compare os_dev
+       with "/dev/.static/dev/md".
+
+2006-10-14  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * util/i386/pc/grub-probe.c (probe): Print DEVICE_NAME instead of
+       DRIVE_NAME when grub_util_biosdisk_get_grub_dev fails. Open
+       DRIVE_NAME instead of DEVICE_NAME. Make sure that DEVICE_NAME and
+       DRIVE_NAME are always freed.
+
+       * util/i386/pc/biosdisk.c (make_device_name): Add one into
+       DOS_PART, as a DOS partition is counted from one instead of zero
+       now. Reported by Robert Millan.
+
+2006-10-14  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/getroot.c (grub_guess_root_device): Stop using
+       grub_util_biosdisk_get_grub_dev to convert system device to GRUB device.
+       * util/grub-emu.c (main): Use grub_util_biosdisk_get_grub_dev with the
+       string returned by grub_guess_root_device.
+       * util/i386/pc/grub-setup.c: Likewise.
+       * util/i386/pc/grub-probefs.c: Likewise.
+
+       * util/i386/pc/grub-probefs.c: Rename to ...
+       * util/i386/pc/grub-probe.c: ... this.
+       * DISTLIST: Remove grub-probefs, add grub-probe.
+       * conf/i386-efi.rmk: Likewise.
+       * conf/i386-pc.rmk: Likewise.
+       * util/i386/pc/grub-install.in: Likewise.
+
+       * util/i386/pc/grub-probe.c: Add --target=(fs|device|drive) option to
+       choose which information we want to print.
+
+2006-10-14  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * DISTLIST: Added commands/echo.c, disk/lvm.c, disk/raid.c,
+       include/grub/bitmap.h, include/grub/lvm.h, include/grub/raid.h,
+       include/grub/i386/pc/vbeutil.h, include/grub/util/lvm.h,
+       include/grub/util/raid.h, util/lvm.c, util/raid.c, video/bitmap.c,
+       video/readers/tga.c and video/i386/pc/vbeutil.c.
+
+2006-10-14  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       Added support for RAID and LVM.
+
+       * disk/lvm.c: New file.
+       * disk/raid.c: Likewise.
+       * include/grub/lvm.h: Likewise.
+       * include/grub/raid.h: Likewise.
+       * include/grub/util/lvm.h: Likewise.
+       * include/grub/util/raid.h: Likewise.
+       * util/lvm.c: Likewise.
+       * util/raid.c: Likewise.
+
+       * include/grub/disk.h (grub_disk_dev_id): Add
+       GRUB_DISK_DEVICE_RAID_ID and GRUB_DISK_DEVICE_LVM_ID.
+       (grub_disk_get_size): New prototype.
+       * kern/disk.c (grub_disk_open): Check whether grub_partition_probe()
+       returns a partition.
+       (grub_disk_get_size): New function.
+
+       * kern/i386/pc/init.c (make_install_device): Copy the prefix
+       verbatim if grub_install_dos_part is -2.
+
+       * util/i386/pc/getroot.c (grub_guess_root_device): Support RAID
+       and LVM devices.
+
+       * util/i386/pc/grub-setup.c (setup): New argument
+       MUST_EMBED. Force embedding of GRUB when the argument is
+       true. Close FILE before returning.
+       (main): Add support for RAID and LVM.
+
+       * conf/common.rmk: Add RAID and LVM modules.
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Add util/raid.c and
+       util/lvm.c.
+       (grub_emu_SOURCES): Add disk/raid.c and disk/lvm.c.
+
+       * kern/misc.c (grub_strstr): New function.
+       * include/grub/misc.h (grub_strstr): New prototype.
+
+2006-10-10  Tristan Gingold  <tristan.gingold@bull.net>
+
+       * include/grub/efi/api.h (GRUB_EFI_ERROR_CODE): Long constant.
+
+2006-10-05  Tristan Gingold  <tristan.gingold@bull.net>
+
+       * kern/misc.c (grub_strtoull): Guess the base only if not
+       specified.
+
+2006-10-01  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/powerpc/ieee1275/cmain.c (cmain): Remove incomplete Old World
+       PowerMac support.
+
+2006-10-01  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * disk/ieee1275/ofdisk.c (grub_ofdisk_iterate): Cast `size' to long.
+
+       * include/grub/ieee1275/ieee1275.h (grub_ieee1275_next_property):
+       Remove `flags' argument.  All callers changed.
+       * kern/ieee1275/ieee1275.c (IEEE1275_PHANDLE_ROOT): Removed.
+       (IEEE1275_IHANDLE_INVALID): New variable.
+       (IEEE1275_CELL_INVALID): New variable.
+       (grub_ieee1275_finddevice, grub_ieee1275_get_property,
+       grub_ieee1275_get_property_length, grub_ieee1275_instance_to_package,
+       grub_ieee1275_package_to_path, grub_ieee1275_instance_to_path,
+       grub_ieee1275_peer, grub_ieee1275_child, grub_ieee1275_open,
+       grub_ieee1275_claim, grub_ieee1275_set_property): Error-check return
+       codes from Open Firmware.  All callers updated.
+       (grub_ieee1275_next_property): Directly return Open Firmware return
+       code.
+       * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_find_options):
+       Standardize error checking from `grub_ieee1275_get_property'.
+       * kern/powerpc/ieee1275/openfw.c (grub_devalias_iterate): Rename
+       `devalias' to `aliases'.  Correct comments.  Consolidate error paths.
+
+2006-10-01  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/ieee1275/ieee1275.c (grub_ieee1275_instance_to_path): Rename
+       `instance_to_package_args' to `instance_to_path_args'.
+
+       * kern/powerpc/ieee1275/init.c (grub_machine_init): Use
+       `grub_ieee1275_chosen'.
+
+       * term/ieee1275/ofconsole.c (grub_ofconsole_init): Call
+       `grub_ieee1275_interpret'.
+
+2006-09-25  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * util/powerpc/ieee1275/grub-mkimage.c: Include config.h.
+
+2006-09-25  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * include/grub/powerpc/libgcc.h (__floatdisf): New prototype.
+       (__cmpdi): Likewise.
+
+       * kern/powerpc/ieee1275/openfw.c (grub_devalias_iterate): Pass 0 as
+       `flags' to `grub_ieee1275_next_property'.  Change `pathlen' to type
+       `grub_ssize_t'.
+
+       * kern/powerpc/ieee1275/cmain.c: Include grub/misc.h.
+
+       * loader/powerpc/ieee1275/linux.c (grub_linux_boot): Change `actual'
+       to type `grub_ssize_t'.
+       (grub_rescue_cmd_linux): Cast -1 to `grub_off_t'.
+
+2006-09-22  Marco Gerards  <marco@gnu.org>
+
+       * normal/script.c (grub_script_create_cmdmenu): Skip leading
+       newlines.
+
+2006-09-22  Marco Gerards  <marco@gnu.org>
+
+       * commands/echo.c: New file.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Add `commands/echo.c'.
+
+       * conf/common.rmk (echo_mod_SOURCES): New variable.
+       (echo_mod_CFLAGS): Likewise.
+       (echo_mod_LDFLAGS): Likewise.
+
+2006-09-22  Marco Gerards  <marco@gnu.org>
+
+       * normal/main.c (get_line): Malloc memory instead of using
+       preallocated memory.  Removed the arguments `cmdline' and
+       `max_len'.  Updated all callers.
+
+2006-09-22  Marco Gerards  <marco@gnu.org>
+
+       * conf/i386-efi.rmk (grub_emu_DEPENDENCIES): New variable.
+       (normal_mod_DEPENDENCIES): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_DEPENDENCIES): Likewise.
+       (normal_mod_DEPENDENCIES): Likewise.
+
+       * conf/sparc64-ieee1275.rmk (normal_mod_DEPENDENCIES): Likewise.
+
+2006-09-22  Johan Rydberg  <jrydberg@gnu.org>
+
+       * genmk.rb: Add DEPENDENCIES variables to modules, utilities, and
+       programs.
+       * conf/i386-pc.rmk (grub_emu_DEPENDENCIES): Declare.
+       (normal_mod_DEPENDENCIES): Likewise.
+       * conf/i386-pc.mk: Regenerate.
+       * conf/i386-efi.mk: Likewise
+       * conf/common.mk: Likewise.
+       * conf/powerpc-ieee1275.mk: Likewise.
+       * conf/sparc64-ieee1275.mk: Likewise.
+
+2006-09-22  Robert Millan  <rmh@aybabtu.com>
+
+       Sync with i386 version.
+       * conf/powerpc-ieee1275.rmk (bin_UTILITIES): Remove grub-emu, add grub-mkimage.
+       * conf/powerpc-ieee1275.rmk (sbin_UTILITIES): Remove grub-mkimage, add grub-emu.
+
+2006-09-21  Robert Millan  <rmh@aybabtu.com>
+
+       Import from GRUB Legacy (lib/device.c):
+       * util/i386/pc/grub-mkdevicemap.c (get_i2o_disk_name): New function.
+       (init_device_map) [__linux__]: Add support for I2O devices.
+
+2006-09-14  Marco Gerards  <marco@gnu.org>
+
+       * conf/i386-pc.rmk (COMMON_LDFLAGS): Use `-m32' instead of
+       `-melf_i386'.
+
+2006-09-14  Robert Millan  <rmh@aybabtu.com>
+
+       * util/i386/pc/grub-install.in: Skip menu.lst when removing
+       /boot/grub/*.lst.
+
+       * util/i386/pc/getroot.c: Don't recurse into dotdirs (e.g. ".static").
+
+       * util/i386/pc/grub-mkdevicemap.c: Make sure the floppy device exists
+       before adding it to device.map.
+
+2006-08-15  Johan Rydberg  <jrydberg@gnu.org>
+
+       * genmk.rb: Let GCC generate dependencies the first time it
+       compiles a file; using the -MD option.
+       * conf/common.mk: Regenerate.
+       * conf/i386-pc.mk: Likewise.
+       * conf/i386-efi.mk: Likewise.
+       * conf/powerpc-ieee1275.mk: Likewise.
+       * conf/sparc64-ieee1275.mk: Likewise.
+
+2006-08-04  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Move the prototypes of grub_setjmp and grub_longjmp to
+       cpu/setjmp.h, so that each architecture may specify different
+       attributes.
+
+       * include/grub/i386/setjmp.h (grub_setjmp): New prototype.
+       (grub_longjmp): Likewise.
+       * include/grub/powerpc/setjmp.h (grub_setjmp): Likewise..
+       (grub_longjmp): Likewise.
+       * include/grub/sparc64/setjmp.h (grub_setjmp): Likewise..
+       (grub_longjmp): Likewise.
+
+       * include/grub/setjmp.h [!GRUB_UTIL] (grub_setjmp): Removed.
+       [!GRUB_UTIL] (grub_longjmp): Removed.
+
+2006-08-01  Pelletier Vincent  <subdino2004@yahoo.fr>
+
+       * kern/ieee1275/ieee1275.c (grub_ieee1275_set_color): IEEE1275
+       "color!" method does not return any value.
+
+2006-07-29  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * include/grub/bitmap.h: New file.
+
+       * include/grub/i386/pc/vbeutil.h: Likewise.
+
+       * video/bitmap.c: Likewise.
+
+       * video/readers/tga.c: Likewise.
+
+       * video/i386/pc/vbeutil.c: Likewise.
+
+       * commands/videotest.c: Code cleanup and updated to reflect to new
+       video API.
+
+       * term/gfxterm.c: Likewise.
+
+       * video/video.c: Likewise.
+
+       * conf/i386-pc.rmk (pkgdata_MODULES): Added tga.mod and bitmap.mod.
+       (vbe_mod_SOURCES): Added video/i386/pc/vbeutil.c.
+       (bitmap_mod_SOURCES): New entry.
+       (bitmap_mod_CFLAGS): Likewise.
+       (bitmap_mod_LDFLAGS): Likewise.
+       (tga_mod_SOURCES): Likewise.
+       (tga_mod_CFLAGS): Likewise.
+       (tga_mod_LDFLAGS): Likewise.
+
+       * include/grub/video.h (grub_video_blit_operators): New enum type.
+       (grub_video_render_target): Changed as forward declaration and moved
+       actual definition to be video driver specific.
+       (grub_video_adapter.blit_bitmap): Added blitting operator.
+       (grub_video_adapter.blit_render_target): Likewise.
+       (grub_video_blit_bitmap): Likewise.
+       (grub_video_blit_render_target): Likewise.
+
+       * include/grub/i386/pc/vbe.h (grub_video_render_target): Added
+       driver specific render target definition.
+       (grub_video_vbe_map_rgba): Added driver internal helper.
+       (grub_video_vbe_unmap_color): Updated to use
+       grub_video_i386_vbeblit_info.
+       (grub_video_vbe_get_video_ptr): Likewise.
+
+       * include/grub/i386/pc/vbeblit.h
+       (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8): Updated to use
+       grub_video_i386_vbeblit_info.
+       (grub_video_i386_vbeblit_R8G8B8_R8G8B8A8): Likewise.
+       (grub_video_i386_vbeblit_index_R8G8B8A8): Likewise.
+       (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8): Likewise.
+       (grub_video_i386_vbeblit_R8G8B8_R8G8B8): Likewise.
+       (grub_video_i386_vbeblit_index_R8G8B8): Likewise.
+       (grub_video_i386_vbeblit_index_index): Likewise.
+       (grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8): New blitter function.
+       (grub_video_i386_vbeblit_R8G8B8_R8G8B8X8): Likewise.
+       (grub_video_i386_vbeblit_index_R8G8B8X8): Likewise.
+       (grub_video_i386_vbeblit_blend): Added generic blitter for blend
+       operator.
+       (grub_video_i386_vbeblit_replace): Added generic blitter for replace
+       operator.
+
+       * video/i386/pc/vbeblit.c: Updated to reflect changes on
+       include/grub/i386/pc/vbeblit.h.
+
+       * include/grub/i386/pc/vbefill.h (grub_video_i386_vbefill_R8G8B8A8):
+       Updated to use grub_video_i386_vbeblit_info.
+       (grub_video_i386_vbefill_R8G8B8): Likewise.
+       (grub_video_i386_vbefill_index): Likewise.
+       (grub_video_i386_vbefill): Added generic filler.
+
+       * video/i386/pc/vbefill.c: Updated to reflect changes on
+       include/grub/i386/pc/vbefill.h.
+
+       * video/i386/pc/vbe.c (grub_video_vbe_get_video_ptr): Updated to use
+       grub_video_i386_vbeblit_info.
+       (grub_video_vbe_unmap_color): Likewise.
+       (grub_video_vbe_blit_glyph): Likewise.
+       (grub_video_vbe_scroll): Likewise.
+       (grub_video_vbe_draw_pixel): Removed function.
+       (grub_video_vbe_get_pixel): Likewise.
+       (grub_video_vbe_fill_rect): Moved all blitters to vbefill.c and
+       updated code to use it.
+       (common_blitter): Added common blitter for render target and bitmap.
+       (grub_video_vbe_blit_bitmap): Updated to use common_blitter.
+       (grub_video_vbe_blit_render_target): Likewise.
+
+2006-07-30  Johan Rydberg  <jrydberg@gnu.org>
+
+       * kern/efi/efi.c (grub_efi_set_text_mode): Assume console already
+       is in text mode if there is no console control protocol instance
+       available.
+
+2006-07-29  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * include/grub/video.h: Code cleanup.
+
+       * include/grub/i386/pc/vbe.h: Likewise.
+
+       * video/i386/pc/vbe.c: Likewise.
+
+       * video/i386/pc/vbeblit.c: Likewise.
+
+       * video/i386/pc/vbefill.c: Likewise.
+
+       * video/video.c: Likewise.  Also added more comments.
+
+2006-07-29  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * disk/i386/pc/biosdisk.c (struct grub_biosdisk_drp): Moved to ...
+       (struct grub_biosdisk_dap): Likewise.
+
+       * include/grub/i386/pc/biosdisk.h: ... to here.  Also corrected
+       linkage settings for all functions.
+
+2006-07-12  Marco Gerards  <marco@gnu.org>
+
+       * configure.ac (--enable-mm-debug): Fix typo.
+
+       * genkernsyms.sh.in: Use proper quoting for `CC'.
+
+2006-07-02  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * conf/i386-pc.rmk (COMMON_ASFLAGS): Add "-m32".
+       (normal_mod_ASFLAGS): Remove "-m32".
+
+2006-06-14  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * util/misc.c: Include config.h.
+       [!HAVE_MEMALIGN]: Do not include malloc.h.
+       (grub_memalign): Use posix_memalign, if present. Then, use
+       memalign, if present. Otherwise, emit an error.
+
+       * util/grub-emu.c: Do not include malloc.h.
+
+       * include/grub/util/misc.h: Include unistd.h. This is required for
+       FreeBSD, because off_t is defined in unistd.h. Reported by Harley
+       D. Eades III <hde@foobar-qux.org>.
+
+       * configure.ac (AC_GNU_SOURCE): Added.
+       (AC_CHECK_FUNCS): Check posix_memalign and memalign for the host
+       type.
+
+2006-06-09  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * loader/i386/pc/linux.c (grub_rescue_cmd_initrd): Make sure that
+       ADDR_MAX does not exceed GRUB_LINUX_INITRD_MAX_ADDRESS.
+
+2006-06-07  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * include/grub/types.h (grub_host_addr_t): Rename to
+       grub_target_addr_t.
+       (grub_host_off_t): Rename to grub_target_off_t.
+       (grub_host_size_t): Rename to grub_target_size_t.
+       (grub_host_ssize_t): Rename to grub_target_ssize_t.
+       Refer to GRUB_TARGET_SIZEOF_VOID_P to define those variables.
+
+       * include/grub/kernel.h (struct grub_module_header): Change type
+       of OFFSET to grub_target_off_t and type of SIZE to grub_target_size_t.
+       (grub_module_info): Likewise.
+
+2006-06-05  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * loader/i386/pc/linux.c (grub_rescue_cmd_initrd): The conditional
+       of checking LINUX_MEM_SIZE was reverse. Reported by Jesus
+       Velazquez <jesus.velazquez@gmail.com>.
+
+2006-06-05  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Count partitions from 1 instead of 0 in the string representation
+       of partitions. Still use 0-based internally.
+
+       * partmap/sun.c (grub_sun_is_valid): A cosmetic change.
+       (sun_partition_map_iterate): Use grub_partition_t instead of
+       struct grub_partition *. Cast DESC->START_CYLINDER to
+       grub_uint64_t after converting the endian.
+       (sun_partition_map_probe): Subtract 1 for PARTNUM.
+       (sun_partition_map_get_name): Add 1 to P->INDEX.
+
+       * partmap/pc.c (grub_partition_parse): Subtract 1 for
+       PCDATA->DOS_PART.
+       (pc_partition_map_get_name): Add 1 into PCDATA->DOS_PART.
+
+       * partmap/gpt.c (gpt_partition_map_iterate): Initialize PARTNO to
+       zero instead of one.
+       (gpt_partition_map_probe): Subtract 1 for PARTNUM.
+       (gpt_partition_map_get_name): Add 1 into P->INDEX.
+
+       * partmap/apple.c (apple_partition_map_iterate): Change the type
+       of POS to unsigned.
+       (apple_partition_map_probe): Subtract 1 for PARTNUM.
+       (apple_partition_map_get_name): Add 1 into P->INDEX.
+
+       * partmap/amiga.c (amiga_partition_map_iterate): Change the type
+       of POS to unsigned.
+       (amiga_partition_map_iterate): Cast NEXT to grub_off_t to
+       calculate the offset of a partition.
+       (amiga_partition_map_probe): Subtract 1 for PARTNUM.
+       (amiga_partition_map_get_name): Add 1 into P->INDEX.
+
+       * partmap/acorn.c (acorn_partition_map_find): Change the type of
+       SECTOR to grub_disk_addr_t.
+       (acorn_partition_map_iterate): Likewise.
+       (acorn_partition_map_probe): Subtract 1 for PARTNUM.
+       Change the type of SECTOR to grub_disk_addr_t. Declare P on the
+       top.
+       (acorn_partition_map_get_name): Add 1 into P->INDEX.
+
+       * kern/i386/pc/init.c (make_install_device): Add 1 into
+       GRUB_INSTALL_DOS_PART.
+
+       * fs/iso9660.c (grub_iso9660_mount): Fixed a reversed
+       conditional.
+
+2006-06-04  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Clean up the code to support 64-bit addressing in disks and
+       files. This change is not enough for filesystems yet.
+
+       * util/i386/pc/grub-setup.c (struct boot_blocklist): Change the
+       type of "start" to grub_uint64_t.
+       (setup): Change the types of KERNEL_SECTOR and FIRST_SECTOR to
+       grub_disk_addr_t * and grub_disk_addr_t. Fix the format string in
+       save_first_sector and save_blocklists. Use grub_le_to_cpu64 to
+       convert addresses.
+
+       * util/i386/pc/biosdisk.c (open_device): Change the type of SECTOR
+       to grub_disk_addr_t.
+
+       * partmap/gpt.c (gpt_partition_map_iterate): Fix the format
+       string.
+
+       * partmap/pc.c (pc_partition_map_iterate): Likewise.
+
+       * partmap/amiga.c (amiga_partition_map_iterate): Cast RDSK.MAGIC
+       to char *.
+
+       * normal/script.c (grub_script_parse): Remove unused MEMFREE.
+
+       * normal/parser.y (YYLTYPE_IS_TRIVIAL): New macro.
+
+       * normal/lexer.c (grub_script_yyerror): Specify unused to LEX.
+
+       * loader/i386/pc/multiboot.c (grub_multiboot_load_elf64): Cast -1
+       to grub_off_t, to detect an error from grub_file_seek.
+       (grub_multiboot_load_elf32): Likewise.
+
+       * kern/misc.c (grub_strtoul): Use grub_strtoull. Return the
+       maximum unsigned long value when an overflow is detected.
+       (grub_strtoull): New function.
+       (grub_divmod64): Likewise.
+       (grub_lltoa): use grub_divmod64.
+
+       * kern/fs.c (struct grub_fs_block): Change the type of "offset" to
+       grub_disk_addr_t.
+       (grub_fs_blocklist_open): Increase P if P is not NULL to advance
+       the pointer to next character. Use grub_strtoull instead of
+       grub_strtoul.
+       (grub_fs_blocklist_read): Change the types of SECTOR, OFFSET and
+       SIZE to grub_disk_addr_t, grub_off_t and grub_size_t,
+       respectively.
+
+       * kern/file.c (grub_file_read): Prevent an overflow of LEN, as the
+       return value is signed.
+       (grub_file_seek): Change the type of OLD to grub_off_t. Do not
+       test if OFFSET is less than zero, as OFFSET is unsigned now.
+
+       * kern/disk.c (struct grub_disk_cache): Change the type of
+       "sector" to grub_disk_addr_t.
+       (grub_disk_cache_get_index): Change the type of SECTOR to
+       grub_disk_addr_t. Calculate the hash with SECTOR casted to
+       unsigned after shifting.
+       (grub_disk_cache_invalidate): Change the type of SECTOR to
+       grub_disk_addr_t.
+       (grub_disk_cache_unlock): Likewise.
+       (grub_disk_cache_store): Likewise.
+       (grub_disk_check_range): Change the types of SECTOR, OFFSET, SIZE,
+       START and LEN to grub_disk_addr_t *, grub_off_t *, grub_size_t,
+       grub_disk_addr_t and grub_uint64_t, respectively.
+       (grub_disk_read): Use an unsigned variable REAL_OFFSET for the
+       body, as the value of OFFSET is tweaked by
+       grub_disk_check_range. Change the types of START_SECTOR, LEN and
+       POS to grub_disk_addr_t, grub_size_t and grub_size_t,
+       respectively.
+       (grub_disk_write): Use an unsigned variable REAL_OFFSET for the
+       body, as the value of OFFSET is tweaked by
+       grub_disk_check_range. Change the types of LEN and N to
+       grub_size_t.
+
+       * io/gzio.c (struct grub_gzio): Change the types of "data_offset"
+       and "saved_offset" to grub_off_t.
+       (test_header): Cast BUF to char *.
+       (get_byte): Cast GZIO->DATA_OFFSET to grub_off_t. Cast GZIO->INBUF
+       to char *.
+       (grub_gzio_read): Change the types of OFFSET and SIZE to
+       grub_off_t and grub_size_t, respectively.
+
+       * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_FORCE_LBA):
+       Removed.
+       (GRUB_BOOT_MACHINE_BOOT_DRIVE): Changed to 0x4c.
+       (GRUB_BOOT_MACHINE_KERNEL_ADDRESS): Changed to 0x40.
+       (GRUB_BOOT_MACHINE_KERNEL_SEGMENT): Changed to 0x42.
+       (GRUB_BOOT_MACHINE_DRIVE_CHECK): Changed to 0x4e.
+       (GRUB_BOOT_MACHINE_LIST_SIZE): Increased to 12.
+
+       * include/grub/types.h (grub_off_t): Unconditionally set to
+       grub_uint64_t.
+       (grub_disk_addr_t): Changed to grub_uint64_t.
+
+       * include/grub/partition.h (struct grub_partition): Change the
+       types of "start", "len" and "offset" to grub_disk_addr_t,
+       grub_uint64_t and grub_disk_addr_t, respectively.
+       (grub_partition_get_start): Return grub_disk_addr_t.
+       (grub_partition_get_len): Return grub_uint64_t.
+
+       * include/grub/misc.h (grub_strtoull): New prototype.
+       (grub_divmod64): Likewise.
+
+       * include/grub/fshelp.h (grub_fshelp_read_file): Change the types
+       of SECTOR, LEN and FILESIZE to grub_disk_addr_t, grub_size_t and
+       grub_off_t, respectively.
+       All callers and references changed.
+
+       * include/grub/fs.h (struct grub_fs): Change the type of LEN to
+       grub_size_t in "read".
+       All callers and references changed.
+
+       * include/grub/file.h (struct grub_file): Change the types of
+       "offset" and "size" to grub_off_t and grub_off_t,
+       respectively. Change the type of SECTOR to grub_disk_addr_t in
+       "read_hook".
+       (grub_file_read): Change the type of LEN to grub_size_t.
+       (grub_file_seek): Return grub_off_t. Change the type of OFFSET to
+       grub_off_t.
+       (grub_file_size): Return grub_off_t.
+       (grub_file_tell): Likewise.
+       All callers and references changed.
+
+       * include/grub/disk.h (struct grub_disk_dev): Change the types of
+       SECTOR and SIZE to grub_disk_addr_t and grub_size_t in "read" and
+       "write".
+       (struct grub_disk): Change the type of "total_sectors" to
+       grub_uint64_t. Change the type of SECTOR to grub_disk_addr_t in
+       "read_hook".
+       (grub_disk_read): Change the types of SECTOR, OFFSET and SIZE to
+       grub_disk_addr_t, grub_off_t and grub_size_t, respectively.
+       (grub_disk_write): Likewise.
+       All callers and references changed.
+
+       * fs/iso9660.c (grub_iso9660_susp_iterate): Cast parameters to
+       char * for grub_strncmp to silence gcc.
+       (grub_iso9660_mount): Likewise.
+       (grub_iso9660_mount): Likewise.
+       (grub_iso9660_read_symlink): Likewise. Also, remove the nonsense
+       return statement.
+       (grub_iso9660_iterate_dir): Likewise.
+       (grub_iso9660_label): Cast DATA->VOLDESC.VOLNAME to char *.
+
+       * fs/hfs.c (grub_hfs_read_file): Change the types of SECTOR and
+       LEN to grub_disk_addr_t and grub_size_t, respectively.
+
+       * fs/hfsplus.c (grub_hfsplus_read_file): Likewise.
+
+       * fs/jfs.c (grub_jfs_read_file): Likewise.
+
+       * fs/minix.c (grub_jfs_read_file): Likewise.
+
+       * fs/sfs.c (grub_jfs_read_file): Likewise.
+
+       * fs/ufs.c (grub_jfs_read_file): Likewise.
+
+       * fs/xfs.c (grub_jfs_read_file): Likewise.
+
+       * fs/fat.c (grub_fat_read_data): Change the types of SECTOR, LEN
+       and SIZE to grub_disk_addr_t, grub_size_t and grub_size_t,
+       respectively.
+
+       * fs/ext2.c (grub_ext2_read_block): When an error happens, set
+       BLKNR to -1 instead of returning GRUB_ERRNO.
+       (grub_ext2_read_file): Change the types of SECTOR and
+       LEN to grub_disk_addr_t and grub_size_t, respectively.
+
+       * fs/affs.c (grub_affs_read_file): Change the types of SECTOR and
+       LEN to grub_disk_addr_t and grub_size_t, respectively.
+
+       * font/manager.c (grub_font_get_glyph): Cast BITMAP to char * for
+       grub_file_read.
+
+       * disk/ieee1275/ofdisk.c (grub_ofdisk_read): Fix the format
+       string. Do not cast SECTOR explicitly.
+
+       * disk/i386/pc/biosdisk.c (grub_biosdisk_open): Change the type of
+       TOTAL_SECTORS to grub_uint64_t. Do not mask DRP->TOTAL_SECTORS.
+       (grub_biosdisk_rw): Change the types of SECTOR and SIZE to
+       grub_disk_addr_t and grub_size_t, respectively. If the sector is
+       over 2TB and LBA mode is not supported, raise an error.
+       (get_safe_sectors): New function.
+       (grub_biosdisk_read): Use get_safe_sectors.
+       (grub_biosdisk_write): Likewise.
+
+       * disk/efi/efidisk.c (grub_efidisk_read): Fix the format string.
+       (grub_efidisk_write): Likewise.
+
+       * disk/loopback.c (delete_loopback): Cosmetic changes.
+       (grub_cmd_loopback): Likewise. Also, test NEWDEV->FILENAME
+       correctly.
+       (grub_loopback_open): Likewise.
+       (grub_loopback_read): Likewise. Also, change the type of POS to
+       grub_off_t, and fix the usage of grub_memset.
+
+       * commands/i386/pc/play.c: Include grub/machine/time.h.
+
+       * commands/ls.c (grub_ls_list_files): Use "llu" instead of "d" to
+       print FILE->SIZE.
+
+       * commands/configfile.c: Include grub/env.h.
+
+       * commands/cmp.c (grub_cmd_cmp): Do not use ERR, but use
+       GRUB_ERRNO directly instead. Change the type of POS to
+       grub_off_t. Follow the coding standard.
+
+       * commands/blocklist.c: Include grub/partition.h.
+       (grub_cmd_blocklist): Return an error if the underlying device is
+       not a disk. Take the starting sector of a partition into account,
+       if a partition is used.
+
+       * boot/i386/pc/diskboot.S (bootloop): Adapted to the new offset of
+       a length field.
+       (lba_mode): Support 64-bit addresses.
+       (chs_mode): Likewise.
+       (copy_buffer): Adapted to the new offsets of a length field and a
+       segment field.
+       (blocklist_default_start): Allocate 64-bit space.
+
+       * boot/i386/pc/boot.S (force_lba): Removed.
+       (boot_drive): Moved to under KERNEL_SECTOR.
+       (kernel_sector): Moved to under KERNEL_SEGMENT. Allocate 64-bit
+       space.
+       (real_start): Set %si earlier. Remove code for FORCE_LBA, since it
+       is useless.
+       (lba_mode): Refactored to support a 64-bit address. More size
+       optimization.
+       (setup_sectors): Likewise.
+
+2006-06-04  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * DISTLIST: Added include/grub/i386/linux.h. Removed
+       include/grub/i386/pc/linux.h
+
+       * configure.ac (AC_INIT): Bumped to 1.94.
+
+       * config.guess: Updated from gnulib.
+       * config.sub: Likewise.
+       * install-sh: Likewise.
+       * mkinstalldirs: Likewise.
+
+2006-06-02  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * conf/common.rmk (grub_modules_init.lst): Depended on
+       grub_emu_SOURCES, excluding grub_emu_init.c, instead of
+       MODSRCFILES.
+
+       * genmk.rb (PModule::rule): Reverted the previous change.
+
+2006-06-02  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * conf/common.rmk (grub_modules_init.lst): Depends on
+       $(MODSRCFILES). Grep only the files in $(MODSRCFILES). Make sure
+       that the target does not exist before producing.
+       (grub_modules_init.h): Remove the target before generating.
+       (grub_emu_init.c): Likewise.
+
+       * genmk.rb (PModule::rule): Add source files into MODSRCFILES.
+
+2006-05-31  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * configure.ac: Don't set host_m32 for x86_64. Also reset LIBS
+       for the target-specific tests. Make sure that we also have the
+       up-to-date target variables for those tests.
+
+2006-05-31  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * genmk.rb (Image::rule): Prefix CFLAGS or ASFLAGS with TARGET_.
+       (PModule::rule): Likewise.
+
+2006-05-31  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * genmk.rb (Image::rule): Set FLAG to CFLAGS or ASFLAGS instead of
+       TARGET_CFLAGS or TARGET_ASFLAGS. There is no reason why
+       target-specific flags should be prefixed.
+       (PModule::rule): Likewise.
+
+2006-05-30  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * configure.ac (CMP): Check if cmp is available explicitly.
+
+2006-05-29  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * util/powerpc/ieee1275/grub-install.in (host_cpu): Removed.
+       (target_cpu): New variable.
+       (pkglibdir): Use target_cpu instead of host_cpu.
+
+       * util/i386/pc/grub-install.in (host_cpu): Removed.
+       (target_cpu): New variable.
+       (pkglibdir): Use target_cpu instead of host_cpu.
+
+       * util/genmoddep.c: Removed.
+
+       * kern/efi/mm.c (filter_memory_map): Use GRUB_CPU_SIZEOF_VOID_P
+       instead of GRUB_HOST_SIZEOF_VOID_P.
+       * kern/dl.c: Likewise.
+
+       * include/grub/i386/types.h (GRUB_HOST_SIZEOF_VOID_P): Renamed to
+       ...
+       (GRUB_TARGET_SIZEOF_VOID_P): ... this.
+       (GRUB_HOST_SIZEOF_LONG): Renamed to ...
+       (GRUB_TARGET_SIZEOF_LONG): ... this.
+       (GRUB_HOST_WORDS_BIGENDIAN): Renamed to ...
+       (GRUB_TARGET_WORDS_BIGENDIAN): ... this.
+       * include/grub/powerpc/types.h (GRUB_HOST_SIZEOF_VOID_P): Renamed
+       to ...
+       (GRUB_TARGET_SIZEOF_VOID_P): ... this.
+       (GRUB_HOST_SIZEOF_LONG): Renamed to ...
+       (GRUB_TARGET_SIZEOF_LONG): ... this.
+       (GRUB_HOST_WORDS_BIGENDIAN): Renamed to ...
+       (GRUB_TARGET_WORDS_BIGENDIAN): ... this.
+       * include/grub/sparc64/types.h (GRUB_HOST_SIZEOF_VOID_P): Renamed
+       to ...
+       (GRUB_TARGET_SIZEOF_VOID_P): ... this.
+       (GRUB_HOST_SIZEOF_LONG): Renamed to ...
+       (GRUB_TARGET_SIZEOF_LONG): ... this.
+       (GRUB_HOST_WORDS_BIGENDIAN): Renamed to ...
+       (GRUB_TARGET_WORDS_BIGENDIAN): ... this.
+
+       * include/grub/types.h [!GRUB_UTIL] (GRUB_CPU_SIZEOF_VOID_P): Use
+       GRUB_TARGET_SIZEOF_VOID_P instead of GRUB_HOST_SIZEOF_VOID_P.
+       [!GRUB_UTIL] (GRUB_CPU_SIZEOF_LONG): Use GRUB_TARGET_SIZEOF_LONG
+       instead of GRUB_HOST_SIZEOF_LONG.
+       [!GRUB_UTIL]: Refer to GRUB_TARGET_WORDS_BIGENDIAN instead of
+       GRUB_HOST_WORDS_BIGENDIAN to define or undefine
+       GRUB_CPU_WORDS_BIGENDIAN.
+       Refer to SIZEOF_VOID_P instead of GRUB_HOST_SIZEOF_VOID_P to
+       define grub_host_addr_t, grub_host_off_t, grub_host_size_t and
+       grub_host_ssize_t.
+
+       * conf/i386-efi.rmk (noinst_UTILITIES): Removed.
+       (genmoddep_SOURCES): Likewise.
+       * conf/i386-pc.rmk (noinst_UTILITIES): Likewise.
+       (genmoddep_SOURCES): Likewise.
+       * conf/conf/powerpc-ieee1275.rmk (noinst_UTILITIES): Likewise.
+       (genmoddep_SOURCES): Likewise.
+       * conf/conf/conf/sparc64-ieee1275.rmk (noinst_UTILITIES):
+       Likewise.
+       (genmoddep_SOURCES): Likewise.
+
+       * genmoddep.awk: New file.
+
+       * genmk.rb (Image::rule): Use TARGET_CC, TARGET_CPPFLAGS,
+       TARGET_CFLAGS, TARGET_ASFLAGS and TARGET_LDFLAGS instead of CC,
+       CPPFLAGS, CFLAGS, ASFLAGS and LDFLAGS, respectively.
+       (PModule::rule): Likewise.
+       (Program::rule): Likewise.
+       (Utility::rule): Use CC, CPPFLAGS, CFLAGS and LDFLAGS instead of
+       BUILD_CC, BUILD_CPPFLAGS, BUILD_CFLAGS and BUILD_LDFLAGS,
+       respectively.
+
+       * configure.ac: Rewritten intensively to use host and target
+       instead of build and host, respectively.
+
+       * Makefile.in (pkglibdir): Use target_cpu instead of host_cpu.
+       (host_cpu): Removed.
+       (target_cpu): New variable.
+       (CPPFLAGS): Added @CPPFLAGS@ and -DGRUB_LIBDIR=\"$(pkglibdir)\".
+       (BUILD_CC): Removed.
+       (BUILD_CFLAGS): Likewise.
+       (BUILD_CPPFLAGS): Likewise.
+       (TARGET_CC): New variable.
+       (TARGET_CFLAGS): Likewise.
+       (TARGET_CPPFLAGS): Likewise.
+       (TARGET_LDFLAGS): Likewise.
+       (AWK): Likewise.
+       (include): Use target_cpu instead of host_cpu.
+       (moddep.lst:): Use genmoddep.awk instead of genmoddep.
+
+       * DISTLIST: Added genmoddep.awk. Removed util/genmoddep.c.
+
+2006-05-29  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * include/grub/script.h (grub_script_cmdif): Renamed field 'bool' to
+       'exec_to_evaluate'.  Renamed field 'true' to 'exec_on_true'.  Renamed
+       field 'false' to 'exec_on_false'.
+       (grub_script_create_cmdif): Renamed argument names to reflect above
+       changes.
+
+       * normal/execute.c (grub_script_execute_cmdif): Likewise.
+
+       * normal/script.c (grub_script_create_cmdif): Likewise.
+
+2006-05-28  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * fs/hfsplus.c (grub_hfsplus_btree_recoffset): Moved to near the
+       top.
+       (grub_hfsplus_btree_recptr): Likewise.
+       (grub_hfsplus_find_block): Do not take RETRY any longer. Use
+       FILEBLOCK both to pass a block number and store next block
+       number.
+       (grub_hfsplus_read_block): Rewritten heavily to support an extent
+       overflow file correctly. Specify errors appropriately, because
+       fshelp expects that GRUB_ERRNO is set when fails. Reuse
+       grub_hfsplus_btree_recptr to get the pointer to a found key.
+       (grub_hfsplus_btree_search): Return 1 instead of 0 when no match
+       is found.
+
+       * conf/i386-efi.rmk (pkgdata_MODULES): Added _linux.mod and
+       linux.mod.
+       (_linux_mod_SOURCES): New variable.
+       (_linux_mod_CFLAGS): Likewise.
+       (_linux_mod_LDFLAGS): Likewise.
+       (linux_mod_SOURCES): Likewise.
+       (linux_mod_CFLAGS): Likewise.
+       (linux_mod_LDFLAGS): Likewise.
+
+       * DISTLIST: Added loader/i386/efi/linux.c,
+       loader/i386/efi/linux_normal.c and
+       include/grub/i386/efi/loader.h.
+
+       * loader/i386/efi/linux.c: New file.
+       * loader/i386/efi/linux_normal.c: Likewise.
+       * include/grub/i386/efi/loader.h: Likewise.
+
+2006-05-27  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * commands/blocklist.c: New file.
+
+       * DISTLIST: Added commands/blocklist.c.
+
+       * term/efi/console.c (grub_console_highlight_color): Use a lighter
+       color for the background, and a darker color for the foreground.
+       (grub_console_checkkey): Return READ_KEY.
+       (grub_console_cls): Set the background to
+       GRUB_EFI_BACKGROUND_BLACK temporarily to clean out the screen.
+
+       * kern/efi/efi.c (grub_efi_exit_boot_services): New function.
+
+       * include/grub/i386/linux.h (struct linux_kernel_params): Fixed
+       the size of "padding5", "hd0_drive_info" and "hd1_drive_info".
+
+       * include/grub/efi/efi.h (grub_efi_exit_boot_services): New
+       prototype.
+
+       * include/grub/efi/api.h (GRUB_EFI_TEXT_ATTR): Do not shift
+       BG. The spec is wrong again.
+
+       * include/grub/normal.h [GRUB_UTIL] (grub_blocklist_init): New
+       prototype.
+       [GRUB_UTIL] (grub_blocklist_fini): Likewise.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Added
+       commands/blocklist.c.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+
+       * conf/common.rmk (pkgdata_MODULES): Added blocklist.mod.
+       (blocklist_mod_SOURCES): New variable.
+       (blocklist_mod_CFLAGS): Likewise.
+       (blocklist_mod_LDFLAGS): Likewise.
+
+2006-05-20  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * boot/i386/pc/boot.S (real_start): Set %si earlier to eliminate
+       duplication.
+       (lba_mode): Use %eax more intensively to reduce the code size.
+
+2006-05-20  Marco Gerards  <marco@gnu.org>
+
+       * normal/lexer.c (grub_script_yylex): Don't filter out newlines.
+
+       * normal/parser.y (commandblock): Defined as <cmd>.  A subroutine
+       for `menuentry'.
+       (script): Accept leading newlines.
+       (newlines): New rule to describe 0 or more newlines.
+       (commands): Accept `command' with trailing newline.  Fixed the
+       order in which arguments were passed to `grub_script_add_cmd'.
+       Accept commands separated by newlines.
+       (function): Changed to accept newlines.
+       (menuentry) Rewritten.
+
+       * normal/script.c (grub_script_create_cmdmenu): Add new entries in
+       front of the list, instead of to the end.
+
+2006-05-19  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * util/i386/pc/grub-install.in (bindir): New variable.
+       (grub_mkimage): Use BINDIR instead of SBINDIR. Reported by Lee
+       Shaver <lbgwjl@gmail.com>.
+
+2006-05-14  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/i386/pc/startup.S: Include grub/cpu/linux.h instead of
+       grub/machine/linux.h
+       * loader/i386/pc/linux.c: Likewise.
+
+       * include/grub/i386/pc/linux.h: Moved to ...
+       * include/grub/i386/linux.h: ... here.
+
+       * include/grub/i386/linux.h (struct linux_kernel_params): New
+       struct.
+
+2006-05-09  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * video/i386/pc/vbe.c (grub_video_vbe_fill_rect): Corrected bounds
+       checking.
+       (grub_video_vbe_blit_glyph): Likewise.
+       (grub_video_vbe_blit_bitmap): Likewise.
+       (grub_video_vbe_blit_render_target): Likewise.
+
+2006-05-09  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * configure.ac (--with-platform): Properly quote the square
+       brackets.
+
+2006-05-08  Marco Gerards  <marco@gnu.org>
+
+       * conf/powerpc-ieee1275.rmk (grubof_HEADERS): Renamed from
+       this...
+       (kernel_elf_HEADERS): ...to this.  Updated all users.
+       (grubof_symlist.c): Renamed from this...
+       (kernel_elf_symlist.c): ...to this.  Updated all users.
+       (pkgdata_PROGRAMS): Changed `grubof' to `kernel.elf'.
+       (grubof_SOURCES): Renamed from this...
+       (kernel_elf_SOURCES): ...to this.
+       (grubof_HEADERS): Renamed from this...
+       (kernel_elf_HEADERS): ...to this.
+       (grubof_CFLAGS): Renamed from this...
+       (kernel_elf_CFLAGS): ...to this.
+       (grubof_ASFLAGS): Renamed from this...
+       (kernel_elf_ASFLAGS): ...to this.
+       (grubof_LDFLAGS): Renamed from this...
+       (kernel_elf_LDFLAGS): ...to this.
+
+       * conf/sparc64-ieee1275.rmk (grubof_HEADERS): Renamed from
+       this...
+       (kernel_elf_HEADERS): ...to this.  Updated all users.
+       (grubof_symlist.c): Renamed from this...
+       (kernel_elf_symlist.c): ...to this.  Updated all users.
+       (pkgdata_PROGRAMS): Changed `grubof' to `kernel.elf'.
+       (grubof_SOURCES): Renamed from this...
+       (kernel_elf_SOURCES): ...to this.
+       (grubof_HEADERS): Renamed from this...
+       (kernel_elf_HEADERS): ...to this.
+       (grubof_CFLAGS): Renamed from this...
+       (kernel_elf_CFLAGS): ...to this.
+       (grubof_ASFLAGS): Renamed from this...
+       (kernel_elf_ASFLAGS): ...to this.
+       (grubof_LDFLAGS): Renamed from this...
+       (kernel_elf_LDFLAGS): ...to this.
+
+       * util/powerpc/ieee1275/grub-mkimage.c (add_segments): Use
+       `kernel.elf' instead of `grubof'.
+
+2006-05-08  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Add --with-platform to configure. Use pkglibdir instead of
+       pkgdatadir. This is reported by Roger Leigh.
+
+       * util/powerpc/ieee1275/grub-install.in (datadir): Removed.
+       (host_vendor): Likewise.
+       (host_os): Likewise.
+       (pkgdatadir): Likewise.
+       (platform): New variable.
+       (pkglibdir): Likewise.
+       Use PKGLIBDIR instead of PKGDATADIR.
+
+       * util/i386/pc/grub-install.in (datadir): Removed.
+       (host_vendor): Likewise.
+       (host_os): Likewise.
+       (pkgdatadir): Likewise.
+       (platform): New variable.
+       (pkglibdir): Likewise.
+       Use PKGLIBDIR instead of PKGDATADIR.
+
+       * util/powerpc/ieee1275/grub-mkimage.c (usage): Use GRUB_LIBDIR
+       instead of GRUB_DATADIR.
+       (main): Likewise.
+       * util/i386/pc/grub-mkimage.c (usage): Likewise.
+       (main): Likewise.
+       * util/i386/efi/grub-mkimage.c (usage): Likewise.
+       (main): Likewise.
+
+       * configure.ac (--with-platform): New option.
+       Use PLATFORM instead of HOST_VENDOR to specify a platform.
+
+       * Makefile.in: Include a makefile based on PLATFORM instead of
+       HOST_VENDOR.
+       (pkgdatadir): Not appended by the machine type.
+       (pkglibdir): Appended by the machine type.
+       (host_vendor): Removed.
+       (platform): New variable.
+       (BUILD_CPPFLAGS): Specify GRUB_LIBDIR instead of GRUB_DATADIR.
+       (install-local): Use PKGLIBDIR instead of PKGDATADIR.
+       (uninstall): Likewise.
+
+2006-05-07  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Use the environment context in the menu. Remove the commands
+       "default" and "timeout", and use variables instead.
+
+       * normal/menu.c: Include grub/env.h.
+       (print_entry): Cast TITLE to silence gcc.
+       (get_timeout): New function.
+       (set_timeout): Likewise.
+       (get_entry_number): Likewise.
+       (run_menu): Use a default entry, a fallback entry and a timeout
+       in the environment variables "default", "fallback" and
+       "timeout". Also, tweak the default entry if it is not within the
+       current menu entries.
+       (grub_menu_run): Use a fallback entry in the environment variable
+       "fallback".
+
+       * normal/main.c (read_config_file): Do not initialize
+       NEWMENU->DEFAULT_ENTRY, NEWMENU->FALLBACK_ENTRY or
+       NEWMENU->TIMEOUT.
+       (grub_normal_execute): Use a data slot to store the menu.
+
+       * include/grub/normal.h (struct grub_menu): Removed default_entry,
+       fallback_entry and timeout.
+       (struct grub_menu_list): Removed.
+       (grub_menu_list_t): Likewise.
+       (struct grub_context): Likewise.
+       (grub_context_t): Likewise.
+       (grub_context_get): Likewise.
+       (grub_context_get_current_menu): Likewise.
+       (grub_context_push_menu): Likewise.
+       (grub_context_pop_menu): Likewise.
+       (grub_default_init): Likewise.
+       (grub_default_fini): Likewise.
+       (grub_timeout_init): Likewise.
+       (grub_timeout_fini): Likewise.
+
+       * conf/sparc64-ieee1275.rmk (pkgdata_MODULES): Removed default.mod
+       and timeout.mod.
+       (normal_mod_SOURCES): Removed normal/context.c.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Removed
+       commands/default.c, commands/timeout.c and normal/context.c.
+       (normal_mod_SOURCES): Removed normal/context.c.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Removed commands/default.c,
+       commands/timeout.c and normal/context.c.
+       (normal_mod_SOURCES): Removed normal/context.c.
+
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Removed
+       commands/default.c, commands/timeout.c and normal/context.c.
+       (normal_mod_SOURCES): Removed normal/context.c.
+
+       * conf/common.rmk (pkgdata_MODULES): Removed default.mod and
+       timeout.mod.
+       (default_mod_SOURCES): Removed.
+       (default_mod_CFLAGS): Likewise.
+       (default_mod_LDFLAGS): Likewise.
+       (timeout_mod_SOURCES): Removed.
+       (timeout_mod_CFLAGS): Likewise.
+       (timeout_mod_LDFLAGS): Likewise.
+
+       * DISTLIST: Removed commands/default.c, commands/timeout.c and
+       normal/context.c.
+
+       * commands/default.c: Removed.
+       * commands/timeout.c: Likewise.
+       * normal/context.c: Likewise.
+
+2006-05-07  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * kern/i386/pc/startup.S (grub_exit): Added missing .code32 tag.
+
+2006-05-02  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/env.c (struct grub_env_context): Removed "sorted". Renamed
+       "next" to "prev" for readability.
+       (struct grub_env_sorted_var): New struct.
+       (grub_env_context): Renamed to ...
+       (initial_context): ... this.
+       (grub_env_var_context): Renamed to ...
+       (current_context): ... this.
+       (grub_env_find): Look only at CURRENT_CONTEXT.
+       (grub_env_context_open): Rewritten to copy exported variables from
+       previous context.
+       (grub_env_context_close): Rewritten according to the new
+       scheme. Also, add an assertion to prevent the initial context from
+       removed.
+       (grub_env_insert): Removed the code for the sorted list.
+       (grub_env_remove): Likewise.
+       (grub_env_export): Simply mark the variable with
+       GRUB_ENV_VAR_GLOBAL.
+       (grub_env_set): A cosmetic change for naming consistency.
+       (grub_env_get): Likewise.
+       (grub_env_unset): Likewise.
+       (grub_env_iterate): Rewritten to sort variables within this
+       function.
+       (grub_register_variable_hook): Fixed for naming consistency. Call
+       grub_env_find again, only if NAME is not found at the first time.
+       (mangle_data_slot_name): New function.
+       (grub_env_set_data_slot): Likewise.
+       (grub_env_get_data_slot): Likewise.
+       (grub_env_unset_data_slot): Likewise.
+
+       * include/grub/env.h (grub_env_var_type): New enum.
+       (GRUB_ENV_VAR_LOCAL): New constant.
+       (GRUB_ENV_VAR_GLOBAL): Likewise.
+       (GRUB_ENV_VAR_DATA): Likewise.
+       (struct grub_env_var): Removed "sort_next" and "sort_prevp". Added
+       "type".
+       (grub_env_set): Replace VAR with NAME for consistency.
+       (grub_register_variable_hook): Likewise.
+       (grub_env_export): Specify the name of the argument.
+       (grub_env_set_data_slot): New prototype.
+       (grub_env_get_data_slot): Likewise.
+       (grub_env_unset_data_slot): Likewise.
+
+2006-04-30  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Extend the loader so that GRUB can accept a loader which comes
+       back to GRUB when a loaded image exits. Also, this change adds
+       support for a chainloader on EFI.
+
+       * term/efi/console.c: Include grub/misc.h.
+       (grub_console_checkkey): Display a scan code on the top for
+       debugging. This will be removed once the EFI port gets stable.
+       Correct the scan code mapping.
+
+       * kern/efi/mm.c (sort_memory_map): Sort in a descending order to
+       allocate memory from larger regions, in order to reduce the number
+       of allocated regions. Otherwise, the MacOSX loader panics.
+       (filter_memory_map): Avoid less than 1MB for compatibility with
+       other loaders.
+       (add_memory_regions): Allocate from the tail of a region, if
+       possible, to avoid allocating a region near to 1MB, for the MacOSX
+       loader.
+
+       * kern/efi/init.c (grub_efi_set_prefix): Specify
+       GRUB_EFI_IMAGE_HANDLE to grub_efi_get_loaded_image.
+
+       * kern/efi/efi.c (grub_efi_get_loaded_image): Accept a new
+       argument IMAGE_HANDLE and specify it to get a loaded image.
+       (grub_arch_modules_addr): Specify GRUB_EFI_IMAGE_HANDLE to
+       grub_efi_get_loaded_image.
+       (grub_efi_get_filename): Divide the length by the size of
+       grub_efi_char16_t.
+       (grub_efi_get_device_path): New function.
+       (grub_efi_print_device_path): Print End Device Path nodes. Divide
+       the length by the size of grub_efi_char16_t for a file path device
+       path node.
+
+       * kern/loader.c (grub_loader_noreturn): New variable.
+       (grub_loader_set): Accept a new argument NORETURN. Set
+       GRUB_LOADER_NORETURN to NORETURN.
+       All callers changed.
+       (grub_loader_boot): If GRUB_LOADER_NORETURN is false, do not call
+       grub_machine_fini.
+
+       * include/grub/efi/efi.h (grub_efi_get_device_path): New
+       prototype.
+       (grub_efi_get_loaded_image): Take an argument to specify an image
+       handle.
+
+       * include/grub/loader.h (grub_loader_set): Added one more argument
+       NORETURN.
+
+       * disk/efi/efidisk.c (make_devices): Use grub_efi_get_device_path
+       instead of grub_efi_open_protocol.
+       (grub_efidisk_get_device_name): Likewise.
+       (grub_efidisk_close): Print a newline.
+       (grub_efidisk_get_device_handle): Fixed to use
+       GRUB_EFI_DEVICE_PATH_SUBTYPE instead of
+       GRUB_EFI_DEVICE_PATH_TYPE.
+
+       * disk/efi/efidisk.c (device_path_guid): Moved to ...
+       * kern/efi/efi.c (device_path_guid): ... here.
+
+       * conf/i386-efi.rmk (pkgdata_MODULES): Added _chain.mod and
+       chain.mod.
+       (kernel_mod_HEADERS): Added efi/disk.h.
+       (_chain_mod_SOURCES): New variable.
+       (_chain_mod_CFLAGS): Likewise.
+       (_chain_mod_LDFLAGS): Likewise.
+       (chain_mod_SOURCES): Likewise.
+       (chain_mod_CFLAGS): Likewise.
+       (chain_mod_LDFLAGS): Likewise.
+
+       * DISTLIST: Added include/grub/efi/chainloader.h,
+       loader/efi/chainloader.c and loader/efi/chainloader_normal.c.
+
+       * include/grub/efi/chainloader.h: New file.
+       * loader/efi/chainloader.c: Likewise.
+       * loader/efi/chainloader_normal.c: Likewise.
+
+2006-04-30  Marco Gerards  <marco@gnu.org>
+
+       * commands/configfile.c (grub_cmd_source): New function.
+       (GRUB_MOD_INIT): Register the commands `source' and `.'.
+       (GRUB_MOD_FINI): De-register the commands `source' and `.'.
+
+2006-04-30  Marco Gerards  <marco@gnu.org>
+
+       * normal/execute.c (grub_script_execute_cmd): Change the return
+       type to `grub_err_t'.  Correctly return the error.
+       (grub_script_execute_cmdline): In case a command line is not a
+       command or a function, try to interpret it as an assignment.
+
+2006-04-30  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * fs/hfsplus.c (grub_hfsplus_read_block): Fixed a memory leak.
+       (grub_hfsplus_iterate_dir): Reordered to skip unknown nodes. Also,
+       skip a node whose name is obviously invalid as UTF-16,
+       i.e. contains a NUL character. Stop the iteration when the last
+       directory entry is found. Instead of using the return value of
+       grub_hfsplus_btree_iterate_node, store the value in RET and use
+       it, because the iterator can be stopped by the last directory
+       entry.
+
+2006-04-30  Marco Gerards  <marco@gnu.org>
+
+       * include/grub/env.h (grub_env_export): New prototype.  Reported
+       by Jan C. Kleinsorge <jan.kleinsorge@udo.edu>.
+
+2006-04-30  Marco Gerards  <marco@gnu.org>
+
+       * fs/hfsplus.c (grub_hfsplus_iterate_dir): Correctly calculate the
+       size of the extents in a catalog file record.
+
+2006-04-29  Marco Gerards  <marco@gnu.org>
+
+       * commands/configfile.c (grub_cmd_configfile): Execute the
+       configfile within its own context.
+
+       * include/grub/env.h (grub_env_context_open): New prototype.
+       (grub_env_context_close): Likewise.
+
+       * kern/env.c (grub_env): Removed.
+       (grub_env_sorted): Likewise.
+       (grub_env_context): New variable.
+       (grub_env_var_context): Likewise.
+       (grub_env_find): Search both the active context and the global
+       context.
+       (grub_env_context_open): New function.
+       (grub_env_context_close): Likewise.
+       (grub_env_insert): Likewise.
+       (grub_env_remove): Likewise.
+       (grub_env_export): Likewise.
+       (grub_env_set): Changed to use helper functions to avoid code
+       duplication.
+       (grub_env_iterate): Rewritten so both the current context and the
+       global context are being used.
+
+       * normal/command.c (export_command): New function.
+       (grub_command_init): Register the `export' function.
+
+2006-04-26  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * util/i386/pc/grub-mkimage.c (compress_kernel): Cast arguments
+       explicitly to suppress gcc's warnings.
+       * fs/fat.c (grub_fat_find_dir): Likewise.
+       (grub_fat_label): Likewise.
+       * fs/xfs.c (grub_xfs_read_inode): Likewise.
+       (grub_xfs_mount): Likewise.
+       (grub_xfs_label): Likewise.
+       * fs/affs.c (grub_affs_mount): Likewise.
+       (grub_affs_label): Likewise.
+       (grub_affs_iterate_dir): Likewise.
+       * fs/sfs.c (grub_sfs_mount): Likewise.
+       (grub_sfs_iterate_dir): Likewise.
+       * fs/ufs.c (grub_ufs_lookup_symlink): Likewise.
+       * fs/hfs.c (grub_hfs_mount): Likewise.
+       (grub_hfs_cmp_catkeys): Likewise.
+       (grub_hfs_find_dir): Likewise.
+       (grub_hfs_dir): Likewise.
+       (grub_hfs_label): Likewise.
+       * fs/jfs.c (grub_jfs_mount): Likewise.
+       (grub_jfs_opendir): Likewise.
+       (grub_jfs_getent): Likewise.
+       (grub_jfs_lookup_symlink): Likewise.
+       (grub_jfs_label): Likewise.
+       * fs/hfsplus.c (grub_hfsplus_cmp_catkey): Likewise.
+       (grub_hfsplus_iterate_dir): Likewise.
+       (grub_hfsplus_btree_iterate_node): Made static.
+
+       * util/grub-emu.c (prefix): New variable.
+       (grub_machine_set_prefix): New function.
+       (main): Do not set the environment variable "prefix" here. Only
+       set PREFIX, which is used later by grub_machine_set_prefix.
+
+       * include/grub/video.h: Do not include grub/symbol.h.
+       (grub_video_register): Not exported. This symbol is not defined in
+       the kernel.
+       (grub_video_unregister): Likewise.
+       (grub_video_iterate): Likewise.
+       (grub_video_setup): Likewise.
+       (grub_video_restore): Likewise.
+       (grub_video_get_info): Likewise.
+       (grub_video_get_blit_format): Likewise.
+       (grub_video_set_palette): Likewise.
+       (grub_video_get_palette): Likewise.
+       (grub_video_set_viewport): Likewise.
+       (grub_video_get_viewport): Likewise.
+       (grub_video_map_color): Likewise.
+       (grub_video_map_rgb): Likewise.
+       (grub_video_map_rgba): Likewise.
+       (grub_video_fill_rect): Likewise.
+       (grub_video_blit_glyph): Likewise.
+       (grub_video_blit_bitmap): Likewise.
+       (grub_video_blit_render_target): Likewise.
+       (grub_video_scroll): Likewise.
+       (grub_video_swap_buffers): Likewise.
+       (grub_video_create_render_target): Likewise.
+       (grub_video_delete_render_target): Likewise.
+       (grub_video_set_active_render_target): Likewise.
+
+       * include/grub/symbol.h [GRUB_SYMBOL_GENERATOR] (EXPORT_FUNC):
+       Undefined.
+       [GRUB_SYMBOL_GENERATOR] (EXPORT_VAR): Likewise.
+
+       * conf/sparc64-ieee1275.rmk (grubof_symlist.c): Depended on
+       config.h. Use gensymlist.sh instead of $(srcdir)/gensymlist.sh.
+       (kernel_syms.lst): Depended on config.h. Use genkernsyms.sh
+       instead of $(srcdir)/genkernsyms.sh.
+
+       * conf/powerpc-ieee1275.rmk (grubof_symlist.c): Depended on
+       config.h. Use gensymlist.sh instead of $(srcdir)/gensymlist.sh.
+       (kernel_syms.lst): Depended on config.h. Use genkernsyms.sh
+       instead of $(srcdir)/genkernsyms.sh.
+
+       * conf/i386-pc.rmk (symlist.c): Depended on config.h. Use
+       gensymlist.sh instead of $(srcdir)/gensymlist.sh.
+       (kernel_syms.lst): Depended on config.h. Use genkernsyms.sh
+       instead of $(srcdir)/genkernsyms.sh.
+
+       * conf/i386-efi.rmk (symlist.c): Depended on config.h. Use
+       gensymlist.sh instead of $(srcdir)/gensymlist.sh.
+       (kernel_syms.lst): Depended on config.h. Use genkernsyms.sh
+       instead of $(srcdir)/genkernsyms.sh.
+
+       * configure.ac (AC_CONFIG_FILES): Added gensymlist.sh and
+       genkernsyms.sh.
+
+       * Makefile.in (DISTCLEANFILES): Added gensymlist.sh and
+       genkernsyms.sh.
+       (gensymlist.sh): New target.
+       (genkernsyms.sh): Likewise.
+
+       * DISTLIST: Removed genkernsyms.sh and gensymlist.sh. Added
+       genkernsyms.sh.in and gensymlist.sh.in.
+
+       * genkernsyms.sh: Removed.
+       * gensymlist.sh: Likewise.
+
+       * genkernsyms.sh.in: New file.
+       * gensymlist.sh.in: Likewise.
+
+2006-04-25  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/powerpc/ieee1275/init.c (grub_machine_set_prefix): Do not
+       clobber "prefix", since we may have already set it manually.
+
+2006-04-25  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/misc.c (abort): New alias for grub_abort.
+
+2006-04-25  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       A new machine-specific function "grub_machine_set_prefix" is
+       defined. This is called after loading modules, so that a prefix
+       initialization can use modules. Also, this change adds an
+       intensive debugging feature for the memory manager via the
+       configure option "--enable-mm-debug".
+
+       * partmap/gpt.c (gpt_partition_map_iterate): Add one more into
+       PART.LEN.
+
+       * kern/sparc64/ieee1275/init.c (abort): Removed.
+       (grub_stop): Likewise.
+       (grub_exit): New function.
+       (grub_set_prefix): Renamed to ...
+       (grub_machine_set_prefix): ... this.
+       (grub_machine_init): Do not call grub_set_prefix.
+
+       * kern/powerpc/ieee1275/init.c (grub_set_prefix): Renamed to ...
+       (grub_machine_set_prefix): ... this.
+       (grub_machine_init): Do not call grub_set_prefix.
+
+       * kern/i386/pc/init.c (grub_machine_set_prefix): New function.
+       (grub_machine_init): Do not set the prefix here.
+
+       * kern/i386/efi/init.c (grub_machine_set_prefix): New function.
+
+       * kern/efi/init.c: Include grub/mm.h.
+       (grub_efi_set_prefix): New function.
+
+       * kern/efi/efi.c (grub_exit): Call grub_efi_fini.
+       (grub_efi_get_filename): New function.
+       (grub_print_device_path): Renamed to ...
+       (grub_efi_print_device_path): ... this.
+
+       * kern/mm.c [MM_DEBUG] (grub_malloc): Undefined.
+       [MM_DEBUG] (grub_realloc): Likewise.
+       [MM_DEBUG] (grub_free): Likewise.
+       [MM_DEBUG] (grub_memalign): Likewise.
+       [MM_DEBUG] (grub_mm_debug): New variable.
+       [MM_DEBUG] (grub_debug_malloc): New function.
+       [MM_DEBUG] (grub_debug_free): New function.
+       [MM_DEBUG] (grub_debug_realloc): New function.
+       [MM_DEBUG] (grub_debug_memalign): New function.
+
+       * kern/misc.c (grub_abort): Print a newline to distinguish
+       the message.
+
+       * kern/main.c (grub_main): Call grub_machine_set_prefix and
+       grub_set_root_dev after loading modules. This is necessary when
+       setting a prefix depends on modules.
+
+       * include/grub/efi/efi.h (grub_print_device_path): Renamed to ...
+       (grub_efi_print_device_path): ... this.
+       (grub_efi_get_filename): New prototype.
+       (grub_efi_set_prefix): Likewise.
+
+       * include/grub/efi/disk.h: Include grub/efi/api.h, grub/symbol.h
+       and grub/disk.h.
+       (grub_efidisk_get_device_handle): New prototype.
+       (grub_efidisk_get_device_name): Likewise.
+
+       * include/grub/mm.h: Include config.h.
+       (MM_DEBUG): Removed.
+       [MM_DEBUG && !GRUB_UTIL] (grub_mm_debug): New prototype.
+       [MM_DEBUG && !GRUB_UTIL] (grub_malloc): New macro.
+       [MM_DEBUG && !GRUB_UTIL] (grub_realloc): Likewise.
+       [MM_DEBUG && !GRUB_UTIL] (grub_memalign): Likewise.
+       [MM_DEBUG && !GRUB_UTIL] (grub_free): Likewise.
+       [MM_DEBUG && !GRUB_UTIL] (grub_debug_malloc): New prototype.
+       [MM_DEBUG && !GRUB_UTIL] (grub_debug_realloc): New prototype.
+       [MM_DEBUG && !GRUB_UTIL] (grub_debug_memalign): New prototype.
+       [MM_DEBUG && !GRUB_UTIL] (grub_debug_free): New prototype.
+
+       * include/grub/kernel.h (grub_machine_set_prefix): New prototype.
+
+       * disk/efi/efidisk.c: Include grub/partition.h.
+       (iterate_child_devices): New function.
+       (add_device): First, compare only last device path nodes, so that
+       devices are sorted by the types.
+       (grub_efidisk_get_device_handle): New function.
+       (grub_efidisk_get_device_name): Likewise.
+
+       * configure.ac (--enable-mm-debug): New option to enable the
+       memory manager debugging feature. This makes the binary much
+       bigger, so is disabled by default.
+
+2006-04-23  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Use grub_abort instead of grub_stop, and grub_exit must be
+       define in each architecture now. Also, this change adds support
+       for EFI disks.
+
+       * util/i386/pc/grub-probefs.c: Include grub/term.h.
+       (grub_getkey): New function.
+       (grub_term_get_current): Likewise.
+
+       * util/i386/pc/grub-setup.c: Include grub/term.h.
+       (grub_getkey): New function.
+       (grub_term_get_current): Likewise.
+
+       * util/misc.c (grub_stop): Renamed to ...
+       (grub_exit): ... this.
+
+       * kern/powerpc/ieee1275/init.c (abort): Renamed to ...
+       (grub_exit): ... this.
+       (grub_machine_init): Use grub_abort instead of abort.
+       (grub_stop): Removed.
+
+       * kern/powerpc/ieee1275/cmain.c (cmain): Use grub_abort instead of
+       abort.
+
+       * kern/i386/pc/startup.S (grub_exit): New function.
+       (cold_reboot): New label.
+
+       * kern/efi/init.c: Include grub/efi/disk.h and grub/env.h.
+       (grub_efi_init): Call grub_efidisk_init.
+       (grub_efi_fini): Call grub_efidisk_fini.
+
+       * kern/efi/efi.c: Include grub/mm.h.
+       (grub_efi_console_control_guid): Renamed to ...
+       (console_control_guid): ... this.
+       (grub_efi_loaded_image_guid): Renamed to ...
+       (loaded_image_guid): ... this.
+       (grub_efi_locate_handle): New function.
+       (grub_efi_open_protocol): Likewise.
+       (grub_efi_set_text_mode): Use CONSOLE_CONTROL_GUID instead of
+       GRUB_EFI_CONSOLE_CONTROL_GUID.
+       (grub_efi_exit): Removed.
+       (grub_stop): Likewise.
+       (grub_efi_get_loaded_image): Use grub_efi_open_protocol.
+       (grub_exit): New function.
+       (grub_print_device_path): Likewise.
+
+       * kern/rescue.c (grub_rescue_cmd_exit): New function.
+       (grub_enter_rescue_mode): Register "exit".
+
+       * kern/misc.c (grub_real_dprintf): A cosmetic change.
+       (grub_abort): New function.
+
+       * kern/err.c (grub_fatal): Use grub_abort instead of grub_stop.
+
+       * include/grub/sparc64/ieee1275/kernel.h (abort): Removed.
+
+       * include/grub/powerpc/ieee1275/kernel.h (abort): Removed.
+
+       * include/grub/efi/efi.h (grub_efi_exit): Removed.
+       (grub_print_device_path): New prototype.
+       (grub_efi_locate_handle): Likewise.
+       (grub_efi_open_protocol): Likewise.
+
+       * include/grub/efi/disk.h (grub_efidisk_fini): New file.
+       * disk/efi/efidisk.c: Likewise.
+
+       * DISTLIST: Added disk/efi/efidisk.c and include/grub/efi/disk.h.
+
+       * include/grub/efi/console_control.h
+       (GRUB_EFI_CONSOLE_CONTROL_GUID): Use an array for the last 8 bytes.
+
+       * include/grub/efi/api.h (GRUB_EFI_LOADED_IMAGE_GUID): Specify the
+       last 8 bytes as an array.
+       (GRUB_EFI_DISK_IO_GUID): New macro.
+       (GRUB_EFI_BLOCK_IO_GUID): Likewise.
+       (GRUB_EFI_DEVICE_PATH_GUID): Likewise.
+       (grub_efi_ipv6_address_t): Change the type to grub_uint16_t from
+       grub_uint8_t.
+       (struct grub_efi_guid): Use an array to specify the last 8 bytes.
+       (struct grub_efi_device_path): Rename the member "sub_type" to
+       "subtype".
+       (GRUB_EFI_DEVICE_PATH_TYPE): New macro.
+       (GRUB_EFI_DEVICE_PATH_SUBTYPE): Likewise.
+       (GRUB_EFI_DEVICE_PATH_LENGTH): Likewise.
+       (GRUB_EFI_END_DEVICE_PATH_TYPE): Likewise.
+       (GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE): Likewise.
+       (GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE): Likewise.
+       (GRUB_EFI_END_ENTIRE_DEVICE_PATH): Likewise.
+       (GRUB_EFI_NEXT_DEVICE_PATH): Likewise.
+       (GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE): Likewise.
+       (GRUB_EFI_PCI_DEVICE_PATH_SUBTYPE): Likewise.
+       (struct grub_efi_pci_device_path): New structure.
+       (grub_efi_pci_device_path_t): New type.
+       (GRUB_EFI_PCCARD_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_pccard_device_path): New structure.
+       (grub_efi_pccard_device_path_t): New type.
+       (GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_memory_mapped_device_path): New structure.
+       (grub_efi_memory_mapped_device_path_t): New type.
+       (GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_vendor_device_path): New structure.
+       (grub_efi_vendor_device_path_t): New type.
+       (GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_controller_device_path): New structure.
+       (grub_efi_controller_device_path_t): New type.
+       (GRUB_EFI_ACPI_DEVICE_PATH_TYPE): New macro.
+       (GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE): Likewise.
+       (struct grub_efi_acpi_device_path): New structure.
+       (grub_efi_acpi_device_path_t): New type.
+       (GRUB_EFI_EXPANDED_ACPI_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_expanded_acpi_device_path): New structure.
+       (grub_efi_expanded_acpi_device_path_t): New type.
+       (GRUB_EFI_EXPANDED_ACPI_HIDSTR): New macro.
+       (GRUB_EFI_EXPANDED_ACPI_UIDSTR): Likewise.
+       (GRUB_EFI_EXPANDED_ACPI_CIDSTR): Likewise.
+       (GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE): Likewise.
+       (GRUB_EFI_ATAPI_DEVICE_PATH_SUBTYPE): Likewise.
+       (struct grub_efi_atapi_device_path): New structure.
+       (grub_efi_atapi_device_path_t): New type.
+       (GRUB_EFI_FIBRE_CHANNEL_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_fibre_channel_device_path): New structure.
+       (grub_efi_fibre_channel_device_path_t): New type.
+       (GRUB_EFI_1394_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_1394_device_path): New structure.
+       (grub_efi_1394_device_path_t): New type.
+       (GRUB_EFI_USB_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_usb_device_path): New structure.
+       (grub_efi_usb_device_path_t): New type.
+       (GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_usb_class_device_path): New structure.
+       (grub_efi_usb_class_device_path_t): New type.
+       (GRUB_EFI_I2O_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_i2o_device_path): New structure.
+       (grub_efi_i2o_device_path_t): New type.
+       (GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_mac_address_device_path): New structure.
+       (grub_efi_mac_address_device_path_t): New type.
+       (GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_ipv4_device_path): New structure.
+       (grub_efi_ipv4_device_path_t): New type.
+       (GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_ipv6_device_path): New structure.
+       (grub_efi_ipv6_device_path_t): New type.
+       (GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_infiniband_device_path): New structure.
+       (grub_efi_infiniband_device_path_t): New type.
+       (GRUB_EFI_UART_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_uart_device_path): New structure.
+       (grub_efi_uart_device_path_t): New type.
+       (GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_vendor_messaging_device_path): New structure.
+       (grub_efi_vendor_messaging_device_path_t): New type.
+       (GRUB_EFI_MEDIA_DEVICE_PATH_TYPE): New macro.
+       (GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE): Likewise.
+       (struct grub_efi_hard_drive_device_path): New structure.
+       (grub_efi_hard_drive_device_path_t): New type.
+       (GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_cdrom_device_path): New structure.
+       (grub_efi_cdrom_device_path_t): New type.
+       (GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_vendor_media_device_path): New structure.
+       (grub_efi_vendor_media_device_path_t): New type.
+       (GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_file_path_device_path): New structure.
+       (grub_efi_file_path_device_path_t): New type.
+       (GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE): New macro.
+       (struct grub_efi_protocol_device_path): New structure.
+       (grub_efi_protocol_device_path_t): New type.
+       (GRUB_EFI_BIOS_DEVICE_PATH_TYPE): New macro.
+       (GRUB_EFI_BIOS_DEVICE_PATH_SUBTYPE): Likewise.
+       (struct grub_efi_bios_device_path): New structure.
+       (grub_efi_bios_device_path_t): New type.
+       (struct grub_efi_disk_io): New structure.
+       (grub_efi_disk_io_t): New type.
+       (struct grub_efi_block_io_media): New structure.
+       (grub_efi_block_io_media_t): New type.
+       (struct grub_efi_block_io): New structure.
+       (grub_efi_block_io_t): New type.
+
+       * include/grub/misc.h (grub_stop): Removed.
+       (grub_exit): New prototype.
+       (grub_abort): Likewise.
+
+       * include/grub/disk.h (enum grub_disk_dev_id): Added
+       GRUB_DISK_DEVICE_EFIDISK_ID.
+
+       * conf/i386-efi.rmk (kernel_mod_SOURCES): Added
+       disk/efi/efidisk.c.
+       (kernel_syms.lst): Remove the target if an error occurs.
+
+2006-04-22  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/misc.c (grub_lltoa): Rewritten the decimal conversion part,
+       as it was simply too buggy.
+
+2006-04-21  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/misc.c (grub_lltoa): New function.
+       (grub_vsprintf): Added support for the long long suffix,
+       i.e. "ll".
+
+2006-04-20  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * Makefile.in (LDFLAGS): Add variable.
+       (LD): Remove variable.
+       * configure.ac: Add -m32 to LDFLAGS.
+       * genmk.rb (PModule#rule): Use $(CC) instead of $(LD).
+       * conf/powerpc-ieee1275.rmk (COMMON_LDFLAGS): Add variable.
+       (grubof_LDFLAGS): Use $(COMMON_LDFLAGS).
+       (_linux_mod_LDFLAGS, linux_mod_LDFLAGS, normal_mod_LDFLAGS,
+       suspend_mod_LDFLAGS, reboot_mod_LDFLAGS, halt_mod_LDFLAGS): New
+       variables.
+       * conf/sparc64-ieee1275.rmk (COMMON_LDFLAGS): Add -nostdlib.
+       * conf/i386-pc.rmk (COMMON_LDFLAGS): Add -nostdlib.
+       * conf/i386-efi.rmk (COMMON_LDFLAGS): Add -nostdlib.
+
+2006-04-20  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * term/gfxterm.c (grub_gfxterm_getcharwidth): Fixed character
+       length for unknown glyph.
+
+2006-04-20  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Add support for pre-loaded modules into the EFI port.
+
+       * util/i386/efi/grub-mkimage.c (make_mods_section): Rewritten
+       completely. Accept one more argument DIR. The caller has changed.
+
+       * kern/i386/efi/init.c (grub_arch_modules_addr): Removed.
+
+       * kern/efi/efi.c: Include grub/efi/pe32.h and grub/kernel.h.
+       (grub_efi_loaded_image_guid): New variable.
+       (grub_efi_get_loaded_image): New function.
+       (grub_arch_modules_addr): Likewise.
+
+       * include/grub/efi/efi.h (grub_efi_get_loaded_image): New
+       prototype.
+
+       * include/grub/efi/api.h (GRUB_EFI_LOADED_IMAGE_GUID): New macro.
+       (struct grub_efi_loaded_image): New structure.
+       (grub_efi_loaded_image_t): New type.
+
+2006-04-20  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * loader/i386/pc/linux.c (grub_rescue_cmd_linux): Compare the file
+       size with GRUB_OS_AREA_SIZE as grub_size_t instead of
+       grub_ssize_t. Reported by Jeff Chua <jeff84@silk.corp.fedex.com>.
+
+2006-04-19  Roger Leigh  <rleigh@whinlatter.ukfsn.org>
+
+       * DISTLIST: Added `util/powerpc/ieee1275/grub-install.in'.
+
+2006-04-19  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * DISTLIST: Added include/grub/efi/console.h,
+       include/grub/efi/time.h, include/grub/i386/efi/kernel.h,
+       kern/efi/init.c, kern/efi/mm.c, and term/efi/console.c.
+
+       * include/grub/efi/console.h: New file.
+       * include/grub/efi/time.h: Likewise.
+       * include/grub/i386/efi/kernel.h: Likewise.
+       * kern/efi/init.c: Likewise.
+       * kern/efi/mm.c: Likewise.
+       * term/efi/console.c: Likewise.
+
+       * kern/i386/efi/init.c: Do not include grub/machine/time.h.
+       (grub_stop): Removed.
+       (grub_get_rtc): Likewise.
+       (grub_machine_init): Simply call grub_efi_init.
+       (grub_machine_fini): Call grub_efi_fini.
+
+       * kern/efi/efi.c: Include grub/machine/time.h and grub/term.h.
+       (grub_efi_output_string): Removed.
+       (grub_efi_stall): New function.
+       (grub_stop): Likewise.
+       (grub_get_rtc): Likewise.
+
+       * include/grub/efi/efi.h (grub_efi_output_string): Removed.
+       (grub_efi_stall): New prototype.
+       (grub_efi_allocate_pages): Likewise.
+       (grub_efi_free_pages): Likewise.
+       (grub_efi_get_memory_map): Likewise.
+       (grub_efi_mm_init): Likewise.
+       (grub_efi_mm_fini): Likewise.
+       (grub_efi_init): Likewise.
+       (grub_efi_fini): Likewise.
+
+       * include/grub/i386/efi/time.h: Do not include
+       grub/symbol.h. Include grub/efi/time.h.
+       (GRUB_TICKS_PER_SECOND): Removed.
+       (grub_get_rtc): Likewise.
+
+       * include/grub/efi/api.h (struct grub_efi_memory_descriptor):
+       Added padding. The EFI spec is buggy.
+       (GRUB_EFI_BLACK): New macro.
+       (GRUB_EFI_BLUE): Likewise.
+       (GRUB_EFI_GREEN): Likewise.
+       (GRUB_EFI_CYAN): Likewise.
+       (GRUB_EFI_RED): Likewise.
+       (GRUB_EFI_MAGENTA): Likewise.
+       (GRUB_EFI_BROWN): Likewise.
+       (GRUB_EFI_LIGHTGRAY): Likewise.
+       (GRUB_EFI_BRIGHT): Likewise.
+       (GRUB_EFI_DARKGRAY): Likewise.
+       (GRUB_EFI_LIGHTBLUE): Likewise.
+       (GRUB_EFI_LIGHTGREEN): Likewise.
+       (GRUB_EFI_LIGHTCYAN): Likewise.
+       (GRUB_EFI_LIGHTRED): Likewise.
+       (GRUB_EFI_LIGHTMAGENTA): Likewise.
+       (GRUB_EFI_YELLOW): Likewise.
+       (GRUB_EFI_WHITE): Likewise.
+       (GRUB_EFI_BACKGROUND_BLACK): Likewise.
+       (GRUB_EFI_BACKGROUND_BLUE): Likewise.
+       (GRUB_EFI_BACKGROUND_GREEN): Likewise.
+       (GRUB_EFI_BACKGROUND_CYAN): Likewise.
+       (GRUB_EFI_BACKGROUND_RED): Likewise.
+       (GRUB_EFI_BACKGROUND_MAGENTA): Likewise.
+       (GRUB_EFI_BACKGROUND_BROWN): Likewise.
+       (GRUB_EFI_BACKGROUND_LIGHTGRAY): Likewise.
+       (GRUB_EFI_TEXT_ATTR): Likewise.
+
+       * conf/i386-efi.rmk (kernel_mod_SOURCES): Added kern/efi/efi.c,
+       kern/efi/init.c, kern/efi/mm.c, and term/efi/console.c.
+       (kernel_mod_HEADERS): Added efi/time.h.
+
+2006-04-18  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * DISTLIST: Added conf/i386-efi.mk, conf/i386-efi.rmk,
+       include/grub/efi/api.h, include/grub/efi/console_control.h,
+       include/grub/efi/efi.h, include/grub/efi/pe32.h,
+       include/grub/i386/efi/time.h, kern/efi/efi.c,
+       kern/i386/efi/init.c, kern/i386/efi/startup.S,
+       and util/i386/efi/grub-mkimage.c.
+
+       * Makefile.in (RMKFILES): Added i386-efi.rmk.
+
+       * genmk.rb (PModule#rule): Do not export symbols if
+       #{prefix}_EXPORTS is set to "no".
+
+       * conf/i386-efi.mk: New file.
+       * conf/i386-efi.rmk: Likewise.
+       * include/grub/efi/api.h: Likewise.
+       * include/grub/efi/console_control.h: Likewise.
+       * include/grub/efi/efi.h: Likewise.
+       * include/grub/efi/pe32.h: Likewise.
+       * include/grub/i386/efi/time.h: Likewise.
+       * kern/efi/efi.c: Likewise.
+       * kern/i386/efi/init.c: Likewise.
+       * kern/i386/efi/startup.S: Likewise.
+       * util/i386/efi/grub-mkimage.c: Likewise.
+
+2006-04-17  Marco Gerards  <marco@gnu.org>
+
+       * include/grub/script.h: Include <grub/parser.h> and
+       "grub_script.tab.h".
+       (struct grub_lexer_param): New struct.
+       (struct grub_parser_param): Likewise.
+       (grub_script_create_arglist): Pass the state in an argument.
+       (grub_script_add_arglist): Likewise.
+       (grub_script_create_cmdline): Likewise.
+       (grub_script_create_cmdblock): Likewise.
+       (grub_script_create_cmdif): Likewise.
+       (grub_script_create_cmdmenu): Likewise.
+       (grub_script_add_cmd): Likewise.
+       (grub_script_arg_add): Likewise.
+       (grub_script_lexer_ref): Likewise.
+       (grub_script_lexer_deref): Likewise.
+       (grub_script_lexer_record_start): Likewise.
+       (grub_script_lexer_record_stop): Likewise.
+       (grub_script_mem_record): Likewise.
+       (grub_script_mem_record_stop): Likewise.
+       (grub_script_malloc): Likewise.
+       (grub_script_yylex): Likewise.
+       (grub_script_yyparse): Likewise.
+       (grub_script_yyerror): Likewise.
+       (grub_script_yylex): Likewise.
+       (grub_script_lexer_init): Return the state.
+
+       * normal/lexer.c (grub_script_lexer_state): Removed variable.
+       (grub_script_lexer_done): Likewise.
+       (grub_script_lexer_getline): Likewise.
+       (grub_script_lexer_refs): Likewise.
+       (script): Likewise.
+       (newscript): Likewise.
+       (record): Likewise.
+       (recording): Likewise.
+       (recordpos): Likewise.
+       (recordlen): Likewise.
+       (grub_script_lexer_init): Return the state instead of setting
+       global variables.
+       (grub_script_lexer_ref): Use the newly added argument for state
+       instead of globals.
+       (grub_script_lexer_deref): Likewise.
+       (grub_script_lexer_record_start): Likewise.
+       (grub_script_lexer_record_stop): Likewise.
+       (recordchar): Likewise.
+       (nextchar): Likewise.
+       (grub_script_yylex2): Likewise.
+       (grub_script_yylex): Likewise.
+       (grub_script_yyerror): Likewise.
+
+       * normal/parser.y (func_mem): Removed variable.
+       (menu_entry): Likewise.
+       (err): Likewise.
+       (%lex-param): New parser option.
+       (%parse-param): Likewise.
+       (script): Always return the AST.
+       (argument): Pass the state around.
+       (arguments): Likewise.
+       (grubcmd): Likewise.
+       (commands): Likewise.
+       (function): Likewise.
+       (menuentry): Likewise.
+       (if_statement): Likewise.
+       (if): Likewise.
+
+       * normal/script.c (grub_script_memused): Removed variable.
+       (grub_script_parsed): Likewise.
+       (grub_script_malloc): Added a state argument.  Use that instead of
+       global variables.
+       (grub_script_mem_record): Likewise.
+       (grub_script_mem_record_stop): Likewise.
+       (grub_script_arg_add): Likewise.
+       (grub_script_add_arglist): Likewise.
+       (grub_script_create_cmdline): Likewise.
+       (grub_script_create_cmdif): Likewise.
+       (grub_script_create_cmdmenu): Likewise.
+       (grub_script_add_cmd): Likewise.
+       (grub_script_parse): Setup the state before calling the parser.
+
+2006-04-16  Marco Gerards  <marco@gnu.org>
+
+       * normal/command.c (grub_command_init): Remove the title command.
+
+       * normal/lexer.c (grub_script_yylex): Renamed from this...
+       (grub_script_yylex2): ... to this.
+       (grub_script_yylex): New function.  Temporary
+       introduced to filter some tokens.
+       (grub_script_yyerror): Print a newline.
+
+       * normal/main.c (read_config_file): Output information about the
+       lines that contain errors.  Wait for a key after all lines have
+       been processed.  Don't return an empty menu.
+
+       * normal/parser.y (func_mem): Don't initialize.
+       (menu_entry): Likewise.
+       (err): New variable.
+       (script): Don't return anything when an error was encountered.
+       (ws, returns): Removed rules.
+       (argument): Disabled concatenated variable support.
+       (arguments): Remove explicit separators.
+       (grubcmd): Likewise.
+       (function): Likewise.
+       (menuentry): Likewise.
+       (if): Likewise.
+       (commands): Likewise.  Add error handling.
+
+       * normal/script.c (grub_script_create_cmdline): If
+       `grub_script_parsed' is 0, assume the parser encountered an error.
+
+2006-04-02  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * configure.ac: Add support for EFI. Fix the typo
+       BUILD_LDDFLAGS. Restore the LDFLAGS after testing.
+
+2006-04-01  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * util/unifont2pff.rb: Removed unnecessary byte ordering.  Now
+       foreign multibyte characters should be shown correctly.
+
+2006-04-01  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * normal/main.c (grub_normal_menu_addentry): Fixed menu size
+       calculation.
+       (read_config_file): Made it to close file before returning.
+
+2006-03-31  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * DISTLIST: Added include/grub/i386/pc/vbeblit.h,
+       include/grub/i386/pc/vbefill.h, video/i386/pc/vbeblit.c,
+       video/i386/pc/vbefill.c.
+
+       * conf/i386-pc.rmk (vbe_mod_SOURCES): Added video/i386/pc/vbeblit.c,
+       video/i386/pc/vbefill.c.
+
+       * include/grub/video.h (grub_video_blit_format): New enum.
+       (grub_video_mode_info): Added new member blit_format.
+       (grub_video_get_blit_format): New function prototype.
+
+       * include/grub/i386/pc/vbe.h (grub_video_vbe_get_video_ptr): New
+       function prototype.
+       (grub_video_vbe_map_rgb): Likewise.
+       (grub_video_vbe_unmap_color): Likewise.
+
+       * include/grub/i386/pc/vbeblit.h: New file.
+
+       * include/grub/i386/pc/vbefill.h: New file.
+
+       * video/video.c (grub_video_get_blit_format): New function.
+       (grub_video_vbe_get_video_ptr): Re-declared as non-static.
+       (grub_video_vbe_map_rgb): Likewise.
+       (grub_video_vbe_unmap_color): Likewise.
+
+       * video/i386/pc/vbe.c (grub_video_vbe_fill_rect): Changed to use more
+       optimized fills.
+       (grub_video_vbe_blit_render_target): Changed to use more optimized
+       blits.
+       (grub_video_vbe_setup): Added detection for optimized settings.
+       (grub_video_vbe_create_render_target): Likewise.
+
+       * video/i386/pc/vbeblit.c: New file.
+
+       * video/i386/pc/vbefill.c: New file.
+
+2006-03-30  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * font/manager.c (grub_font_get_glyph): Removed font fixup from
+       here...
+
+       * util/unifont2pff.rb: ... and moved it to here.  Improved argument
+       parsing to support both hex and dec ranges.  If filename was missing
+       show usage information.
+
+2006-03-14  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * DISTLIST: Added include/grub/video.h, term/gfxterm.c,
+       video/video.c, commands/videotest.c.  Removed term/i386/pc/vesafb.c.
+
+       * conf/i386-pc.rmk (pkgdata_MODULES): Added video.mod,
+       gfxterm.mod, videotest.mod.  Removed vga.mod, vesafb.mod.
+       (video_mod_SOURCES): Added.
+       (video_mod_CFLAGS): Likewise.
+       (video_mod_LDFLAGS): Likewise.
+       (gfxterm_mod_SOURCES): Likewise.
+       (gfxterm_mod_CFLAGS): Likewise.
+       (gfxterm_mod_LDFLAGS): Likewise.
+       (videotest_mod_SOURCES): Likewise.
+       (videotest_mod_CFLAGS): Likewise.
+       (videotest_mod_LDFLAGS): Likewise.
+       (vesafb_mod_SOURCES): Removed.
+       (vesafb_mod_CFLAGS): Likewise.
+       (vesafb_mod_LDFLAGS): Likewise.
+       (vga_mod_SOURCES): Likewise.
+       (vga_mod_CFLAGS): Likewise.
+       (vga_mod_LDFLAGS): Likewise.
+
+       * commands/videotest.c: New file.
+
+       * font/manager.c (fill_with_default_glyph): Modified to use
+       grub_font_glyph.
+       (grub_font_get_glyph): Likewise.
+       (fontmanager): Renamed from this...
+       (font_manager): ... to this.
+
+       * include/grub/font.h (grub_font_glyph): Added new structure.
+       (grub_font_get_glyph): Modified to use grub_font_glyph.
+
+       * include/grub/misc.h (grub_abs): Added as inline function.
+
+       * include/grub/video.h: New file.
+
+       * include/grub/i386/pc/vbe.h (GRUB_VBE_STATUS_OK): New macro.
+       (GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL): Likewise.
+       (GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR): Likewise.
+       (grub_vbe_get_controller_info): Renamed from this...
+       (grub_vbe_bios_get_controller_info): ... to this.
+       (grub_vbe_get_mode_info): Renamed from this...
+       (grub_vbe_bios_get_mode_info): ... to this.
+       (grub_vbe_set_mode): Renamed from this...
+       (grub_vbe_bios_set_mode): ... to this.
+       (grub_vbe_get_mode): Renamed from this...
+       (grub_vbe_bios_get_mode): ... to this.
+       (grub_vbe_set_memory_window): Renamed from this...
+       (grub_vbe_bios_set_memory_window): ... to this.
+       (grub_vbe_get_memory_window): Renamed from this...
+       (grub_vbe_bios_get_memory_window): ... to this.
+       (grub_vbe_set_scanline_length): Renamed from this...
+       (grub_vbe_set_scanline_length): ... to this.
+       (grub_vbe_get_scanline_length): Renamed from this...
+       (grub_vbe_bios_get_scanline_length): ... to this.
+       (grub_vbe_set_display_start): Renamed from this...
+       (grub_vbe_bios_set_display_start): ... to this.
+       (grub_vbe_get_display_start): Renamed from this...
+       (grub_vbe_bios_get_display_start): ... to this.
+       (grub_vbe_set_palette_data): Renamed from this...
+       (grub_vbe_bios_set_palette_data): ... to this.
+       (grub_vbe_set_pixel_rgb): Removed.
+       (grub_vbe_set_pixel_index): Likewise.
+
+       * kern/i386/pc/startup.S (grub_vbe_get_controller_info): Renamed
+       from this...
+       (grub_vbe_bios_get_controller_info): ... to this.
+       (grub_vbe_get_mode_info): Renamed from this...
+       (grub_vbe_bios_get_mode_info): ... to this.
+       (grub_vbe_set_mode): Renamed from this...
+       (grub_vbe_bios_set_mode): ... to this.
+       (grub_vbe_get_mode): Renamed from this...
+       (grub_vbe_bios_get_mode): ... to this.
+       (grub_vbe_set_memory_window): Renamed from this...
+       (grub_vbe_bios_set_memory_window): ... to this.
+       (grub_vbe_get_memory_window): Renamed from this...
+       (grub_vbe_bios_get_memory_window): ... to this.
+       (grub_vbe_set_scanline_length): Renamed from this...
+       (grub_vbe_set_scanline_length): ... to this.
+       (grub_vbe_get_scanline_length): Renamed from this...
+       (grub_vbe_bios_get_scanline_length): ... to this.
+       (grub_vbe_set_display_start): Renamed from this...
+       (grub_vbe_bios_set_display_start): ... to this.
+       (grub_vbe_get_display_start): Renamed from this...
+       (grub_vbe_bios_get_display_start): ... to this.
+       (grub_vbe_set_palette_data): Renamed from this...
+       (grub_vbe_bios_set_palette_data): ... to this.
+       (grub_vbe_bios_get_controller_info): Fixed problem with registers
+       getting corrupted after calling it.  Added more pushes and pops.
+       (grub_vbe_bios_set_mode): Likewise.
+       (grub_vbe_bios_get_mode): Likewise.
+       (grub_vbe_bios_get_memory_window): Likewise.
+       (grub_vbe_bios_set_scanline_length): Likewise.
+       (grub_vbe_bios_get_scanline_length): Likewise.
+       (grub_vbe_bios_get_display_start): Likewise.
+       (grub_vbe_bios_set_palette_data): Likewise.
+
+       * normal/cmdline.c (cl_set_pos): Refresh the screen.
+       (cl_insert): Likewise.
+       (cl_delete): Likewise.
+
+       * term/gfxterm.c: New file.
+
+       * term/i386/pc/vesafb.c: Removed file.
+
+       * video/video.c: New file.
+
+       * video/i386/pc/vbe.c (real2pm): Added new function.
+       (grub_video_vbe_draw_pixel): Likewise.
+       (grub_video_vbe_get_video_ptr): Likewise.
+       (grub_video_vbe_get_pixel): Likewise
+       (grub_video_vbe_init): Likewise.
+       (grub_video_vbe_fini): Likewise.
+       (grub_video_vbe_setup): Likewise.
+       (grub_video_vbe_get_info): Likewise.
+       (grub_video_vbe_set_palette): Likewise.
+       (grub_video_vbe_get_palette): Likewise.
+       (grub_video_vbe_set_viewport): Likewise.
+       (grub_video_vbe_get_viewport): Likewise.
+       (grub_video_vbe_map_color): Likewise.
+       (grub_video_vbe_map_rgb): Likewise.
+       (grub_video_vbe_map_rgba): Likewise.
+       (grub_video_vbe_unmap_color): Likewise.
+       (grub_video_vbe_fill_rect): Likewise.
+       (grub_video_vbe_blit_glyph): Likewise.
+       (grub_video_vbe_blit_bitmap): Likewise.
+       (grub_video_vbe_blit_render_target): Likewise.
+       (grub_video_vbe_scroll): Likewise.
+       (grub_video_vbe_swap_buffers): Likewise.
+       (grub_video_vbe_create_render_target): Likewise.
+       (grub_video_vbe_delete_render_target): Likewise.
+       (grub_video_vbe_set_active_render_target): Likewise.
+       (grub_vbe_set_pixel_rgb): Remove function.
+       (grub_vbe_set_pixel_index): Likewise.
+       (index_color_mode): Remove static variable.
+       (active_mode): Likewise.
+       (framebuffer): Likewise.
+       (bytes_per_scan_line): Likewise.
+       (grub_video_vbe_adapter): Added new static variable.
+       (framebuffer): Likewise.
+       (render_target): Likewise.
+       (initial_mode): Likewise.
+       (mode_in_use): Likewise.
+       (mode_list): Likewise.
+
+2006-03-10  Marco Gerards  <marco@gnu.org>
+
+       * configure.ac (AC_INIT): Bumped to 1.93.
+
+       * DISTLIST: Added `include/grub/hfs.h'.
+
+2006-02-01  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * boot/i386/pc/boot.S (general_error): Before looping, try INT
+       18H, which might help the BIOS falling back to next boot media.
+
+2006-01-25  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * util/i386/pc/grub-install.in: Escape a backslash. Reported by
+       Poe Chen <poe.poechen@gmail.com>.
+
+2006-01-17  Marco Gerards  <marco@gnu.org>
+
+       * include/grub/normal.h: Include <grub/script.h>.
+       (grub_command_list): Removed struct.
+       (grub_command_list_t): Removed type.
+       (grub_menu_entry): Remove members `num' and `command_list'.  Add
+       members `commands' and `sourcecode'.
+       * include/grub/script.h: Add inclusion guards.
+       (grub_script_cmd_menuentry): New struct.
+       (grub_script_execute_menuentry): New prototype.
+       (grub_script_lexer_record_start): Likewise.
+       (grub_script_lexer_record_stop): Likewise.
+       * normal/execute.c (grub_script_execute_menuentry): New function.
+       * normal/lexer.c (record, recording, recordpos, recordlen): New
+       variables.
+       (grub_script_lexer_record_start): New function.
+       (grub_script_lexer_record_stop): Likewise.
+       (recordchar): Likewise.
+       (nextchar): Likewise.
+       (grub_script_yylex): Use `nextchar' to fetch new characters.  Use
+       2048 as the buffer size.  Add the tokens `menuentry' and `@'.
+       * normal/main.c: Include <grub/parser.h> and <grub/script.h>
+       (current_menu): New variable.
+       (free_menu): Mainly rewritten.
+       (grub_normal_menu_addentry): New function.
+       (read_config_file): Rewritten.
+       * normal/menu.c (run_menu_entry): Mainly rewritten.
+       * normal/menu_entry.c (make_screen): Rewritten the code to insert
+       the menu entry.
+       (run): Mainly rewritten.
+       * normal/parser.y (menu_entry): New variable.
+       (GRUB_PARSER_TOKEN_MENUENTRY): New token.
+       (menuentry): New rule.
+       (command): Add `menuentry'.
+       (if_statement): Allow additional returns before `fi'.
+       * normal/script.c (grub_script_create_cmdmenu): New function.
+
+2006-01-03  Marco Gerards  <marco@gnu.org>
+
+       * INSTALL: GNU Bison is required.
+       * configure.ac: Rewritten the test to detect Bison.
+       * Makefile.in (YACC): New variable.  Reported by Xun Sun
+       <xun.sun.cn@gmail.com>.
+
+2006-01-03  Marco Gerards  <marco@gnu.org>
+
+       * fs/hfsplus.c (grub_hfsplus_read_block): Convert the offset of
+       the HFS+ filesystem to filesystem blocks.
+       (grub_hfsplus_iterate_dir): Cast the `fileinfo' assignment so a
+       GCC warning is silenced.
+
+2006-01-03  Marco Gerards  <marco@gnu.org>
+
+       * partmap/apple.c (apple_partition_map_iterate): Convert the data
+       read from disk from big endian to host byte order.
+
+2006-01-03  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * fs/hfs.c: Include <grub/hfs.h>.  Added reference to the official
+       documentation.
+       (GRUB_HFS_EMBED_HFSPLUS_SIG): New macro.
+       (grub_hfs_mount): Grammar fix in error. Make sure this is not an
+       embedded HFS+ filesystem.
+       (GRUB_HFS_MAGIC, grub_hfs_extent, grub_hfs_datarecord_t)
+       (grub_hfs_sblock): Move from here...
+       * include/grub/hfs.h: To here...  New file.
+       * fs/hfsplus.c: Include <grub/hfs.h>.  Added reference to the official
+       documentation.
+       (GRUB_HFSPLUS_MAGIC, GRUB_HFSPLUSX_MAGIC, GRUB_HFSPLUS_SBLOCK):
+       New macros.
+       (grub_hfsplus_volheader): Change type of member `magic' to
+       `grub_uint16_t'.
+       (grub_hfsplus_data): Add new member `embedded_offset'.
+       (grub_hfsplus_read_block): Add the HFS+ wrapper offset to the
+       returned block.
+       (grub_hfsplus_mount): Read the HFS+ wrapper if it exists.
+       Calculate the offset.
+
+2005-12-25  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_DRP_ADDR):
+       Removed.
+       (GRUB_BOOT_MACHINE_DRP_SIZE): Likewise.
+
+2005-12-25  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/env.c (grub_env_set): Check if ENV->VALUE instead of
+       ENV->NAME is NULL after allocating ENV->VALUE.
+
+2005-12-25  Marco Gerards  <marco@gnu.org>
+
+       * kern/env.c (grub_env_set): Rewritten the error handling code.
+
+2005-12-25  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * geninit.sh: Made more robust, and more portable.
+
+2005-12-25  Marco Gerards  <marco@gnu.org>
+
+       Add support for Apple HFS+ filesystems.
+
+       * fs/hfsplus.c: New file.
+
+       * DISTLIST: Added `fs/hfsplus.c'.
+
+       * conf/common.rmk (pkgdata_MODULES): Add `hfsplus.mod'.
+       (hfsplus_mod_SOURCES): New variable.
+       (hfsplus_mod_CFLAGS): Likewise.
+       (hfsplus_mod_LDFLAGS): Likewise.
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Add `fs/hfsplus.c'.
+       (grub_setup_SOURCES): Likewise.
+       (grub_mkdevicemap_SOURCES): Likewise.
+       (grub_emu_SOURCES): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+
+       * fs/fshelp.c (grub_fshelp_log2blksize): New function.
+
+       * include/grub/fshelp.h (grub_fshelp_log2blksize): new prototype.
+
+2005-12-25  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * DISTLIST: Added geninitheader.sh, geninit.sh, commands/test.c,
+       commands/i386/pc/play.c, conf/common.mk, conf/common.rmk,
+       include/grub/parser.h, include/grub/script.h, kern/parser.c,
+       kern/sparc64/cache.S, normal/execute.c, normal/function.c,
+       normal/lexer.c, normal/parser.y, normal/script.c, and
+       partmap/gpt.c.
+       Removed kern/sparc64/cache.c.
+
+       * conf/common.rmk (DISTCLEANFILES): Added grub_script.tab.c,
+       grub_script.tab.h, grub_modules_init.lst, grub_modules_init.h,
+       grub_emu_init.c.
+
+       * configure.ac (AC_INIT): Bumped to 1.92.
+
+2005-12-24  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * kern/err.c (grub_error_push): Added new function to support error
+       stacks.
+       (grub_error_pop): Likewise.
+       (grub_error_stack_items): New local variable to support error stacks.
+       (grub_error_stack_pos): Likewise.
+       (grub_error_stack_assert): Likewise.
+       (GRUB_ERROR_STACK_SIZE): Added new define to configure maximum error
+       stack depth.
+       (grub_print_error): Added support to print errors from error stack.
+
+       * include/grub/err.h (grub_error_push): Added function prototype.
+       (grub_error_pop): Likewise.
+
+2005-12-09  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * configure.ac: Accept `powerpc64' as host_cpu.
+       (amd64): Rename to `biarch32'.
+
+       * kern/powerpc/cache.S (grub_arch_sync_caches): Handle
+       non-cacheline-aligned addresses.
+
+       * kern/dl.c (grub_dl_load_core): Add grub_dprintf messages.
+       (grub_dl_flush_cache): Likewise.  Only call `grub_arch_sync_caches'
+       if `size' is non-zero.
+
+2005-12-03  Marco Gerards  <mgerards@xs4all.nl>
+
+       * conf/common.rmk (grub_modules_init.lst): Use `-printf "%P\n"'
+       and `cd' to make sure the filename is not prefixed with a
+       directory name.
+       (pkgdata_MODULES): Add `gpt.mod'.
+       (gpt_mod_SOURCES): New variable.
+       (gpt_mod_CFLAGS): Likewise.
+       (gpt_mod_LDFLAGS): Likewise.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Add `partmap/gpt.c'.
+
+       * include/grub/pc_partition.h (GRUB_PC_PARTITION_TYPE_GPT_DISK):
+       New macro.
+
+       * partmap/gpt.c: New file.
+
+       * partmap/pc.c (pc_partition_map_iterate): Don't continue when a
+       GPT partition map is detected.
+
+2005-12-03  Vincent Pelletier  <subdino2004@yahoo.fr>
+
+       * commands/i386/pc/play.c: New file.
+       * conf/i386-pc.rmk (pkgdata_MODULES): Added play.mod.
+       (play_mod_SOURCES, play_mod_CFLAGS, play_mod_LDFLAGS): New
+       macros.
+
+2005-11-27  Marco Gerards  <mgerards@xs4all.nl>
+
+       * include/grub/dl.h (GRUB_MOD_INIT): Use `__attribute__
+       ((unused))' to silence gcc warning.
+
+2005-11-26  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * configure.ac: Correct `AC_PROG_YACC' test.
+
+2005-11-22  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * util/powerpc/ieee1275/grub-install.in: Run the mount point
+       check before installing files.
+
+2005-11-22  Mike Small  <smallm@panix.com>
+
+       * util/powerpc/ieee1275/grub-install.in (grubdir): Fixed partition
+       number regex so multidigit numbers are recognized correctly.
+
+2005-11-22  Mike Small  <smallm@panix.com>
+
+       * loader/powerpc/ieee1275/linux.c (grub_rescue_cmd_linux): Add a
+       debugging message before attempting to claim memory.
+       (grub_rescue_cmd_initrd): Add a claim debugging message and try
+       multiple addresses in case of failure.
+
+2005-11-22  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * term/tparm.c (get_space): Remove empty `if' statement.
+
+       * fs/ufs.c (grub_ufs_find_file): Remove `grub_le_to_cpu32'.
+
+       * kern/parser.c (check_varstate): Rename `state' to 's'.
+
+2005-11-22  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * partmap/acorn.c: Change `unsigned' to `unsigned int'.  Move all
+       variable definitions to the beginning of each function.  Sort stack
+       variables by size.
+       (find): Rename to `acorn_partition_map_find'.  Cast `grub_disk_read'
+       `buf' argument to `char *'.
+
+2005-11-22  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * conf/powerpc-ieee1275.rmk: Include conf/common.mk.
+       (pkgdata_MODULES): Removed fshelp.mod, fat.mod, ext2.mod, ufs.mod,
+       minix.mod, hfs.mod, jfs.mod, xfs.mod, affs.mod, sfs.mod,
+       hello.mod, boot.mod, terminal.mod, ls.mod, cmp.mod, cat.mod,
+       help.mod, font.mod, terminfo.mod, amiga.mod, apple.mod, pc.mod,
+       sun.mod, acorn.mod, loopback.mod, default.mod, timeout.mod,
+       configfile.mod, search.mod, gzio.mod and test.mod.
+       (symlist.c, grub_script.tab.c, grub_script.tab.h, kernel_syms.lst)
+       (grub_modules_init.lst, grub_modules_init.h, grub_emu_init.c)
+       (fshelp_mod_SOURCES, fshelp_mod_CFLAGS, fshelp_mod_LDFLAGS)
+       (fat_mod_SOURCES, fat_mod_CFLAGS, fat_mod_LDFLAGS)
+       (ext2_mod_SOURCES, ext2_mod_CFLAGS, ext2_mod_LDFLAGS)
+       (ufs_mod_SOURCES, ufs_mod_CFLAGS, ufs_mod_LDFLAGS)
+       (minix_mod_SOURCES, minix_mod_CFLAGS, minix_mod_LDFLAGS)
+       (hfs_mod_SOURCES, hfs_mod_CFLAGS, hfs_mod_LDFLAGS, jfs_mod_SOURCES)
+       (jfs_mod_CFLAGS, jfs_mod_LDFLAGS, iso9660_mod_SOURCES)
+       (iso9660_mod_CFLAGS, iso9660_mod_LDFLAGS, xfs_mod_SOURCES)
+       (xfs_mod_CFLAGS, xfs_mod_LDFLAGS, affs_mod_SOURCES)
+       (affs_mod_CFLAGS, affs_mod_LDFLAGS, sfs_mod_SOURCES)
+       (sfs_mod_CFLAGS, sfs_mod_LDFLAGS, hello_mod_SOURCES)
+       (hello_mod_CFLAGS, hello_mod_LDFLAGS, boot_mod_SOURCES)
+       (boot_mod_CFLAGS, boot_mod_LDFLAGS, terminal_mod_SOURCES)
+       (terminal_mod_CFLAGS, terminal_mod_LDFLAGS, ls_mod_SOURCES)
+       (ls_mod_CFLAGS, ls_mod_LDFLAGS, cmp_mod_SOURCES, cmp_mod_CFLAGS)
+       (cmp_mod_LDFLAGS, cat_mod_SOURCES, cat_mod_CFLAGS, cat_mod_LDFLAGS)
+       (help_mod_SOURCES, help_mod_CFLAGS, help_mod_LDFLAGS)
+       (font_mod_SOURCES, font_mod_CFLAGS, font_mod_LDFLAGS)
+       (terminfo_mod_SOURCES, terminfo_mod_CFLAGS, terminfo_mod_LDFLAGS)
+       (amiga_mod_SOURCES, amiga_mod_CFLAGS, amiga_mod_LDFLAGS)
+       (apple_mod_SOURCES, apple_mod_CFLAGS, apple_mod_LDFLAG): Removed.
+
+       * conf/common.mk (grub_modules_init.lst): Use `find' instead of
+       `grep --include'.
+       (pkgdata_MODULES): Add test.mod.
+
+2005-11-18  Timothy Baldwin  <T.E.Baldwin99@members.leeds.ac.uk>
+
+       * genmk.rb: Fixed list rules moved to Makefile.in.  Recognise
+       appending to variables with "+=".
+       (PModule): Use full pathname to generate *.lst filenames.
+
+       * Makefile.in: Fixed list rules moved from genmk.rb.
+       (.DELETE_ON_ERROR): New special target.
+       (RMKFILES): Add common.rmk and sparc64-ieee1275.rmk.
+
+       * conf/i386-pc.rmk: Include conf/common.mk.
+       (pkgdata_MODULES): Removed fshelp.mod, fat.mod, ext2.mod, ufs.mod,
+       minix.mod, hfs.mod, jfs.mod, xfs.mod, affs.mod, sfs.mod,
+       hello.mod, boot.mod, terminal.mod, ls.mod, cmp.mod, cat.mod,
+       help.mod, font.mod, terminfo.mod, amiga.mod, apple.mod, pc.mod,
+       sun.mod, acorn.mod, loopback.mod, default.mod, timeout.mod,
+       configfile.mod, search.mod, gzio.mod and test.mod.
+       (symlist.c, grub_script.tab.c, grub_script.tab.h, kernel_syms.lst)
+       (grub_modules_init.lst, grub_modules_init.h, grub_emu_init.c)
+       (fshelp_mod_SOURCES, fshelp_mod_CFLAGS, fshelp_mod_LDFLAGS)
+       (fat_mod_SOURCES, fat_mod_CFLAGS, fat_mod_LDFLAGS)
+       (ext2_mod_SOURCES, ext2_mod_CFLAGS, ext2_mod_LDFLAGS)
+       (ufs_mod_SOURCES, ufs_mod_CFLAGS, ufs_mod_LDFLAGS)
+       (minix_mod_SOURCES, minix_mod_CFLAGS, minix_mod_LDFLAGS)
+       (hfs_mod_SOURCES, hfs_mod_CFLAGS, hfs_mod_LDFLAGS, jfs_mod_SOURCES)
+       (jfs_mod_CFLAGS, jfs_mod_LDFLAGS, iso9660_mod_SOURCES)
+       (iso9660_mod_CFLAGS, iso9660_mod_LDFLAGS, xfs_mod_SOURCES)
+       (xfs_mod_CFLAGS, xfs_mod_LDFLAGS, affs_mod_SOURCES)
+       (affs_mod_CFLAGS, affs_mod_LDFLAGS, sfs_mod_SOURCES)
+       (sfs_mod_CFLAGS, sfs_mod_LDFLAGS, hello_mod_SOURCES)
+       (hello_mod_CFLAGS, hello_mod_LDFLAGS, boot_mod_SOURCES)
+       (boot_mod_CFLAGS, boot_mod_LDFLAGS, terminal_mod_SOURCES)
+       (terminal_mod_CFLAGS, terminal_mod_LDFLAGS, ls_mod_SOURCES)
+       (ls_mod_CFLAGS, ls_mod_LDFLAGS, cmp_mod_SOURCES, cmp_mod_CFLAGS)
+       (cmp_mod_LDFLAGS, cat_mod_SOURCES, cat_mod_CFLAGS, cat_mod_LDFLAGS)
+       (help_mod_SOURCES, help_mod_CFLAGS, help_mod_LDFLAGS)
+       (font_mod_SOURCES, font_mod_CFLAGS, font_mod_LDFLAGS)
+       (terminfo_mod_SOURCES, terminfo_mod_CFLAGS, terminfo_mod_LDFLAGS)
+       (amiga_mod_SOURCES, amiga_mod_CFLAGS, amiga_mod_LDFLAGS)
+       (apple_mod_SOURCES, apple_mod_CFLAGS, apple_mod_LDFLAG): Move from
+       here...
+       * conf/common.rmk: ... to here.  New file.
+
+       * conf/common.mk: New file.
+
+2005-11-18  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * conf/powerpc-ieee1275.rmk (grub_script.tab.h): Unified to ...
+       (grub_script.tab.c): ... here.
+
+       * conf/sparc64-ieee1275.rmk (grub_script.tab.h): Unified to ...
+       (grub_script.tab.c): ... here.
+
+       * conf/i386-pc.rmk (grub_script.tab.h): Unified to ...
+       (grub_script.tab.c): ... here.
+
+       * normal/command.c (grub_command_find): Fixed a memory leak of
+       MODULE_NAME. Reported by Mike Small <smallm@panix.com>.
+
+2005-11-13  Timothy Baldwin  <T.E.Baldwin99@members.leeds.ac.uk>
+
+       * include/grub/symbol.h: (FUNCTION): Use double quotes instead of
+       "@" which marks the start of a comment on ARM.
+       (VARIABLE): Likewise.
+
+2005-11-13  Timothy Baldwin  <T.E.Baldwin99@members.leeds.ac.uk>
+
+       Add support for Linux/ADFS partition tables.
+
+       * partmap/acorn.c: New file.
+
+       * include/grub/acorn_filecore.h: Likewise.
+
+       * DISTLIST: Added `partmap/acorn.c' and
+       `include/grub/acorn_filecore.h'.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add
+       `partmap/acorn.c'.
+       (pkgdata_MODULES): Add `acorn.mod'.
+       (acorn_mod_SOURCES): New variable.
+       (acorn_mod_CFLAGS): Likewise.
+
+       * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Add
+       `partmap/acorn.c'.
+       (pkgdata_MODULES): Add `acorn.mod'.
+       (acorn_mod_SOURCES): New variable.
+       (acorn_mod_CFLAGS): Likewise.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Add `partmap/acorn.c'.
+       (pkgdata_MODULES): Add `acorn.mod'.
+       (acorn_mod_SOURCES): New variable.
+       (acorn_mod_CFLAGS): Likewise.
+       (acorn_mod_LDFLAGS): Likewise.
+
+       * include/types.h (grub_disk_addr_t): New typedef.
+
+2005-11-13  Marco Gerards  <mgerards@xs4all.nl>
+
+       * geninit.sh: New file.
+
+       * geninitheader.sh: Likewise.
+
+       * commands/boot.c (grub_boot_init, grub_boot_fini): Removed.
+       * commands/cat.c (grub_cat_init, grub_cat_fini): Likewise.
+       * commands/cmp.c (grub_cmp_init, grub_cmp_fini): Likewise.
+       * commands/configfile.c (grub_configfile_init)
+       (grub_configfile_fini): Likewise.
+       * commands/default.c (grub_default_init, grub_default_fini):
+       Likewise.
+       * commands/help.c (grub_help_init, grub_help_fini): Likewise.
+       * commands/ls.c (grub_ls_init, grub_ls_fini): Likewise.
+       * commands/search.c (grub_search_init, grub_search_fini): Likewise.
+       * commands/terminal.c (grub_terminal_init, grub_terminal_fini):
+       Likewise.
+       * commands/test.c (grub_test_init, grub_test_fini): Likewise.
+       * commands/timeout.c (grub_timeout_init, grub_timeout_fini):
+       Likewise.
+       * commands/i386/pc/halt.c (grub_halt_init, grub_halt_fini): Likewise.
+       * commands/ieee1275/halt.c (grub_halt_init, grub_halt_fini):
+       Likewise.
+       * commands/i386/pc/reboot.c (grub_reboot_init, grub_reboot_fini):
+       Likewise.
+       * commands/ieee1275/reboot.c (grub_reboot_init, grub_reboot_fini):
+       Likewise.
+       * disk/loopback.c (grub_loop_init, grub_loop_fini): Likewise.
+       * fs/affs.c (grub_affs_init, grub_affs_fini): Likewise.
+       * fs/ext2.c (grub_ext2_init, grub_ext2_fini): Likewise.
+       * fs/fat.c (grub_fat_init, grub_fat_fini): Likewise.
+       * fs/hfs.c (grub_hfs_init, grub_hfs_fini): Likewise.
+       * fs/iso9660.c (grub_iso9660_init, grub_iso9660_fini): Likewise.
+       * fs/jfs.c (grub_jfs_init, grub_jfs_fini): Likewise.
+       * fs/minix.c (grub_minix_init, grub_minix_fini): Likewise.
+       * fs/sfs.c (grub_sfs_init, grub_sfs_fini): Likewise.
+       * fs/ufs.c (grub_ufs_init, grub_ufs_fini): Likewise.
+       * fs/xfs.c (grub_xfs_init, grub_xfs_fini): Likewise.
+       * normal/main.c (grub_normal_init, grub_normal_fini): Likewise.
+       * partmap/amiga.c (grub_amiga_partition_map_init)
+       (grub_amiga_partition_map_fini): Likewise.
+       * partmap/apple.c (grub_apple_partition_map_init)
+       (grub_apple_partition_map_fini): Likewise.
+       * partmap/pc.c (grub_pc_partition_map_init)
+       (grub_pc_partition_map_fini): Likewise.
+       * partmap/sun.c (grub_sun_partition_map_init,
+       grub_sun_partition_map_fini): Likewise.
+       * term/terminfo.c (grub_terminal_init, grub_terminal_fini):
+       Likewise.
+
+       * util/grub-emu.c: Include <grub_modules_init.h>.
+       (main): Don't initialize and de-initialize any modules directly,
+       use `grub_init_all' and `grub_fini_all' instead.
+
+       * term/i386/pc/vesafb.c (grub_vesafb_init): Renamed to
+       `grub_vesafb_mod_init'.
+       (grub_vesafb_fini): Renamed to `grub_vesafb_mod_fini'.  Updated
+       all users.
+       * term/i386/pc/vga.c (grub_vga_init): Renamed to
+       `grub_vga_mod_init'.  Updated all users.
+       (grub_vga_fini): Renamed to `grub_vga_mod_fini'.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Add `grub_emu_init.c'.
+       (grub_modules_init.lst, grub_modules_init.h, grub_emu_init.c): New
+       rules.
+
+       * include/grub/dl.h (GRUB_MOD_INIT): Add argument `name'.
+       Generate a function to initialize the module in utilities.
+       Updated all callers.
+       (GRUB_MOD_FINI): Add argument `name'.  Generate a function to
+       initialize the module in utilities.  Updated all callers.
+
+2005-11-09  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * term/ieee1275/ofconsole.c (grub_ofconsole_cls): Use both the ANSI
+       escape sequence and a literal ^L to clear the screen.
+
+       * commands/ieee1275/suspend.c (grub_cmd_suspend): Clear the screen
+       when returning from Open Firmware.
+
+2005-11-09  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * term/ieee1275/ofconsole.c (grub_ofconsole_width): New variable.
+       (grub_ofconsole_height): Likewise.
+       (grub_ofconsole_putchar): If `grub_curr_x' exceeds console width,
+       manually insert a '\n'.
+       (grub_ofconsole_getwh): Set and return `grub_ofconsole_width' and
+       `grub_ofconsole_height'.  Return early if these are already set.
+
+2005-11-07  Vincent Pelletier  <subdino2004@yahoo.fr>
+
+       * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Add
+       `commands/test.c', `fs/affs.c', `fs/sfs.c', `fs/xfs.c',
+       `normal/execute.c', `normal/lexer.c', `io/gzio.c',
+       `kern/parser.c', `grub_script.tab.c', `normal/function.c'
+       and `normal/script.c'.
+       (normal_mod_SOURCES): `normal/execute.c', `normal/lexer.c',
+       `grub_script.tab.c', `normal/function.c' and `normal/script.c'.
+       (test_mod_SOURCES): New variable.
+       (test_mod_CFLAGS): Likewise.
+       (test_mod_LDFLAGS): Likewise.
+       (pkgdata_MODULES): Add `test.mod'.
+       (grub_script.tab.c): New rule.
+       (grub_script.tab.h): Likewise.
+
+2005-11-07  Marco Gerards  <mgerards@xs4all.nl>
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add
+       `commands/test.c', `normal/execute.c', `normal/lexer.c',
+       `grub_script.tab.c', `normal/function.c' and `normal/script.c'.
+       (normal_mod_SOURCES): `normal/execute.c', `normal/lexer.c',
+       `grub_script.tab.c', `normal/function.c' and `normal/script.c'.
+       (test_mod_SOURCES): New variable.
+       (test_mod_CFLAGS): Likewise.
+       (pkgdata_MODULES): Add `test.mod'.
+       (grub_script.tab.c): New rule.
+       (grub_script.tab.h): Likewise.
+
+2005-11-06  Marco Gerards  <mgerards@xs4all.nl>
+
+       Add initial scripting support.
+
+       * commands/test.c: New file.
+       * include/grub/script.h: Likewise.
+       * normal/execute.c: Likewise.
+       * normal/function.c: Likewise.
+       * normal/lexer.c: Likewise.
+       * normal/parser.y: Likewise.
+       * normal/script.c: Likewise.
+
+       * configure.ac: Add `AC_PROG_YACC' test.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Add `commands/test.c',
+       `normal/execute.c', `normal/lexer.c', `grub_script.tab.c',
+       `normal/function.c' and `normal/script.c'.
+       (normal_mod_SOURCES): `normal/execute.c', `normal/lexer.c',
+       `grub_script.tab.c', `normal/function.c' and `normal/script.c'.
+       (test_mod_SOURCES, test_mod_CFLAGS, test_mod_LDFLAGS): New
+       variables.
+       (pkgdata_MODULES): Add `test.mod'.
+       (grub_script.tab.c): New rule.
+       (grub_script.tab.h): Likewise.
+
+       * include/grub/err.h (grub_err_t): Add `GRUB_ERR_TEST_FAILURE'.
+
+       * include/grub/normal.h (grub_test_init): New prototype.
+       (grub_test_fini): Likewise.
+
+       * normal/command.c: Include <grub/script.h>.
+       (grub_command_execute): Rewritten.
+
+       * util/grub-emu.c (main): Call `grub_test_init' and
+       `grub_test_fini'.
+
+2005-11-03  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/powerpc/ieee1275/init.c (grub_get_rtc): Initialize `msecs'
+       to 0.
+       * term/ieee1275/ofconsole.c (grub_ofconsole_checkkey): Return -1 if
+       there are no pending characters.
+
+2005-11-03  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/powerpc/ieee1275/openfw.c (grub_ieee1275_get_devname): Use
+       `grub_strndup' to drop device arguments. Replace unnecessary
+       `grub_strndup' with `grub_strdup'.
+
+2005-11-03  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/term.c (grub_cls): Do not call grub_cur_term->cls() if the
+       `debug' environment variable has been set.
+
+2005-11-02  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * Makefile.in (install-local): Use $(DATA).
+       (uninstall): Likewise.
+       * conf/powerpc-ieee1275.rmk (bin_UTILITIES): Move grub-mkimage...
+       (sbin_UTILITIES): ... to here.
+       (sbin_SCRIPTS): New variable.
+       (grub_install_SOURCES): New variable.
+       * util/powerpc/ieee1275/grub-install.in: New file.
+       * util/powerpc/ieee1275/grub-mkimage.c (kernel_path): Remove
+       variable.
+       (add_segments): Call `grub_util_get_path'.
+
+2005-10-28  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       From Timothy Baldwin:
+       * commands/ls.c (grub_ls_list_files): Close FILE with
+       grub_file_close.
+       * kern/misc.c (grub_vsprintf): Terminate the string S with NUL.
+
+2005-10-24  Marco Gerards  <mgerards@xs4all.nl>
+
+       * include/grub/parser.h: New file.
+
+       * kern/parser.c: Likewise.
+
+       * conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/parser.c'.
+       (grub_setup_SOURCES): Likewise.
+       (grub_probefs_SOURCES): Likewise.
+       (grub_emu_SOURCES): Likewise.
+       (kernel_img_HEADERS): Add `parser.h'.
+
+       * conf/powerpc-ieee1275.rmk (grubof_HEADERS): Add `parser.h'.
+       (grub_emu_SOURCES): Add `kern/parser.c'.
+       (grubof_SOURCES): Likewise.
+
+       * conf/sparc64-ieee1275.rmk (grubof_HEADERS): Add `parser.h'.
+       (grubof_SOURCES): Add `kern/parser.c'.
+
+       * include/grub/misc.h (grub_split_cmdline): Removed prototype.
+
+       * kern/misc.c (grub_split_cmdline): Removed function.
+
+       * kern/rescue.c: Include <grub/parser.h>.
+       (grub_enter_rescue_mode): Use `grub_parser_split_cmdline' instead
+       of `grub_split_cmdline'.
+
+       * normal/command.c: Include <grub/parser.h>.
+       (grub_command_execute):  Use `grub_parser_split_cmdline' instead
+       of `grub_split_cmdline'.
+
+       * normal/completion.c: Include <grub/parser.h>.
+       (cmdline_state): New variable.
+       (iterate_dir): End the filename with a quote depending on the
+       command line state.
+       (get_state): new function.
+       (grub_normal_do_completion): Use `grub_parser_split_cmdline' to
+       split the arguments and determine the current argument.  When the
+       argument string is not quoted, escape all spaces.
+
+2005-10-23  Vincent Pelletier  <subdino2004@yahoo.fr>
+
+       * normal/sparc64/setjmp.S: New file.
+
+2005-10-23  Vincent Pelletier  <subdino2004@yahoo.fr>
+
+       * include/grub/sparc64/libgcc.h: New file.
+       * conf/sparc64-ieee1275.rmk (COMMON_ASFLAGS): Remove -Av9.
+       (normal_mod_SOURCES): Use normal/sparc64/setjmp.S instead of
+       normal/sparc64/setjmp.c.
+
+2005-10-23  Vincent Pelletier  <subdino2004@yahoo.fr>
+
+       * kern/sparc64/dl.c: Rewritten for SPARCV9 ELF.
+       * kern/sparc64/cache.S: New file.
+       * kern/sparc64/cache.c: Removed.
+       * conf/sparc64-ieee1275.rmk (COMMON_ASFLAGS): Add -Av9.
+       (COMMON_CFLAGS): Add -mno-app-regs.  Remove -mcpu=v9 and
+       -mtune=ultrasparc.
+       (COMMON_LDFLAGS): Add -melf64_sparc.
+       (grubof_HEADERS): Add sparc64/libgcc.h and machine/kernel.h.
+       (grubof_SOURCES): Use cache.S instead of cache.c.
+       (grubof_LDFLAGS): Add -mno-app-regs.  Replace "-Xlinker
+       --oformat -Xlinker elf64-sparc" by "-Bstatic,-melf64_sparc".
+       (pkgdata_MODULES): Uncomment. Leave linux.mod and _linux.mod
+       commented though.
+       (normal_mod_SOURCES): Add normal/completion.c and normal/misc.c.
+       (_linux_mod_SOURCES, _linux_mod_CFLAGS, linux_mod_SOURCES)
+       (linux_mod_CFLAGS): Commented out.
+       (_linux_mod_LDFLAGS, linux_mod_LDFLAGS): New macro, commented
+       out because module isn't built.
+       (fshelp_mod_LDFLAGS, fat_mod_LDFLAGS, ext2_mod_LDFLAGS)
+       (ufs_mod_LDFLAGS, minix_mod_LDFLAGS, hfs_mod_LDFLAGS)
+       (jfs_mod_LDFLAGS, iso9660_mod_LDFLAGS, normal_mod_LDFLAGS)
+       (hello_mod_LDFLAGS, boot_mod_LDFLAGS, terminal_mod_LDFLAGS)
+       (ls_mod_LDFLAGS, cmp_mod_LDFLAGS, cat_mod_LDFLAGS)
+       (font_mod_LDFLAGS, amiga_mod_LDFLAGS, apple_mod_LDFLAGS)
+       (pc_mod_LDFLAGS, sun_mod_LDFLAGS, loopback_mod_LDFLAGS)
+       (suspend_mod_LDFLAGS, reboot_mod_LDFLAGS, halt_mod_LDFLAGS)
+       (help_mod_LDFLAGS, default_mod_LDFLAGS, timeout_mod_LDFLAGS)
+       (configfile_mod_LDFLAGS, search_mod_LDFLAGS, xfs_mod_SOURCES)
+       (xfs_mod_CFLAGS, xfs_mod_LDFLAGS, affs_mod_SOURCES)
+       (affs_mod_CFLAGS, affs_mod_LDFLAGS, sfs_mod_SOURCES)
+       (sfs_mod_CFLAGS, sfs_mod_LDFLAGS, gzio_mod_SOURCES)
+       (gzio_mod_CFLAGS, gzio_mod_LDFLAGS): New macro.
+
+2005-10-20  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * util/i386/pc/grub-probefs.c (main): Call grub_xfs_init and
+       grub_xfs_fini. Do not call grub_hfs_init or grub_hfs_fini any
+       longer, because HFS should not be used on PC.
+
+2005-10-20  Timothy Baldwin  <T.E.Baldwin99@members.leeds.ac.uk>
+
+       * io/gzio.c (grub_gzio_read): Use OFFSET instead of FILE->OFFSET
+       consistently within the loop.
+
+2005-10-15  Marco Gerards  <mgerards@xs4all.nl>
+
+       * fs/xfs.c (grub_xfs_iterate_dir): Detect an error if part of a
+       directory can not be read.
+
+2005-10-15  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * configure.ac (AC_INIT): Increase the version number to 1.91.
+
+       * DISTLIST: Added include/grub/terminfo.h, include/grub/tparm.h,
+       include/grub/i386/pc/serial.h, term/terminfo.c, term/tparm.c and
+       term/i386/pc/serial.c.
+
+2005-10-15  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/file.c (grub_file_seek): Seeking to an offset equal to a
+       file size must be permitted.
+
+       * kern/i386/pc/startup.S (multiboot_trampoline): Fix a mistake
+       between %ah and %al.
+
+2005-10-15  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * fs/xfs.c (grub_xfs_iterate_dir): Change the type of BLK to
+       grub_uint64_t.
+       Call the hook with a NUL-terminated filename.
+       (grub_xfs_mount): Use grub_be_to_cpu32 instead of
+       grub_cpu_to_be32.
+
+       * kern/term.c (cursor_state): New variable.
+       (grub_term_set_current): Reset the cursor state on a new
+       terminal.
+       (grub_setcursor): Rewritten to use CURSOR_STATE.
+       (grub_getcursor): New function.
+
+       * include/grub/term.h (grub_getcursor): New prototype.
+
+       * io/gzio.c (test_header): Align BUF for accessing it as 32-bit
+       integers on ARM. Reported by Timothy Baldwin
+       <T.E.Baldwin99@members.leeds.ac.uk>.
+
+2005-10-11  Marco Gerards  <mgerards@xs4all.nl>
+
+       * fs/sfs.c (grub_sfs_open): Don't free `data->label' if it is not
+       allocated.
+       (grub_sfs_dir): Likewise.
+
+2005-10-09  Marco Gerards  <mgerards@xs4all.nl>
+
+       Add support for the SFS filesystem.
+
+       * fs/sfs.c: New file.
+
+       * DISTLIST: Added `fs/sfs.c'.
+
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Add `fs/sfs.c'.
+       (grub_probefs_SOURCES): Likewise.
+       (grub_emu_SOURCES): Likewise.
+       (pkgdata_MODULES): Add `sfs.mod'.
+       (sfs_mod_SOURCES): New variable.
+       (sfs_mod_CFLAGS): Likewise.
+       (sfs_mod_LDFLAGS): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add `fs/sfs.c'.
+       (pkgdata_MODULES): Add `sfs.mod'.
+       (sfs_mod_SOURCES): New variable.
+       (sfs_mod_CFLAGS): Likewise.
+
+       * util/grub-emu.c (main): Call `grub_sfs_init' and
+       `grub_sfs_fini'.
+
+       * include/grub/fs.h (grub_sfs_init): New prototype.
+       (grub_sfs_fini): Likewise.
+
+2005-10-07  Marco Gerards  <mgerards@xs4all.nl>
+
+       Add support for the AFFS filesystem.
+
+       * fs/affs.c: New file.
+
+       * DISTLIST: Added `fs/affs.c'.
+
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Add `fs/affs.c'.
+       (grub_probefs_SOURCES): Likewise.
+       (grub_emu_SOURCES): Likewise.
+       (pkgdata_MODULES): Add `affs.mod'.
+       (affs_mod_SOURCES): New variable.
+       (affs_mod_CFLAGS): Likewise.
+       (affs_mod_LDFLAGS): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add `fs/affs.c'.
+       (pkgdata_MODULES): Add `affs.mod'.
+       (affs_mod_SOURCES): New variable.
+       (affs_mod_CFLAGS): Likewise.
+
+       * util/grub-emu.c (main): Call `grub_affs_init' and
+       `grub_affs_fini'.
+
+       * include/grub/fs.h (grub_affs_init): New prototype.
+       (grub_affs_fini): Likewise.
+
+2005-10-01  Marco Gerards  <mgerards@xs4all.nl>
+
+       * fs/xfs.c (grub_xfs_iterate_dir): Add parentheses.
+
+2005-10-01  Marco Gerards  <mgerards@xs4all.nl>
+
+       * configure.ac: Accept `x86_64' as host_cpu.  In that case add
+       `-m32' to CFLAGS.
+
+       * genmk.rb (class PModule): Always use `$(#{prefix}_LDFLAGS)' when
+       linking.
+
+       * conf/i386-pc.rmk (COMMON_CFLAGS): Add `-m32'.
+       (COMMON_LDFLAGS): New variable.
+       (kernel_img_LDFLAGS): Include `COMMON_FLAGS'.
+       (_chain_mod_LDFLAGS, fshelp_mod_LDFLAGS, fat_mod_LDFLAGS)
+       (ext2_mod_LDFLAGS, ufs_mod_LDFLAGS, minix_mod_LDFLAGS)
+       (hfs_mod_LDFLAGS, jfs_mod_LDFLAGS, iso9660_mod_LDFLAGS)
+       (xfs_mod_LDFLAGS, _linux_mod_LDFLAGS, linux_mod_LDFLAGS)
+       (normal_mod_LDFLAGS, hello_mod_LDFLAGS, boot_mod_LDFLAGS)
+       (terminal_mod_LDFLAGS, ls_mod_LDFLAGS, cmp_mod_LDFLAGS)
+       (cat_mod_LDFLAGS, help_mod_LDFLAGS, reboot_mod_LDFLAGS)
+       (halt_mod_LDFLAGS, vga_mod_LDFLAGS, font_mod_LDFLAGS)
+       (terminfo_mod_LDFLAGS, serial_mod_LDFLAGS, _multiboot_mod_LDFLAGS)
+       (multiboot_mod_LDFLAGS, amiga_mod_LDFLAGS, apple_mod_LDFLAGS)
+       (pc_mod_LDFLAGS, sun_mod_LDFLAGS, loopback_mod_LDFLAGS)
+       (default_mod_LDFLAGS, timeout_mod_LDFLAGS, configfile_mod_LDFLAGS)
+       (vbe_mod_LDFLAGS, vesafb_mod_LDFLAGS, vbeinfo_mod_LDFLAGS)
+       (vbetest_mod_LDFLAGS, search_mod_LDFLAGS, gzio_mod_LDFLAGS): New
+       variables.
+       (normal_mod_ASFLAGS): Add `-m32'.
+
+       * include/grub/types.h (grub_host_addr_t, grub_host_off_t)
+       (grub_host_size_t, grub_host_ssize_t): New types.
+       (grub_addr_t, grub_off_t, grub_size_t, grub_ssize_t): Make type
+       dependent of `GRUB_CPU_SIZEOF_VOID_P' instead on
+       `GRUB_HOST_SIZEOF_VOID_P'.
+
+       * include/grub/kernel.h (struct grub_module_header): Type of
+       member offset changed to `grub_host_off_t'.  Type of member size
+       changed to `grub_host_size_t'.
+       (struct grub_module_info): Type of member offset changed to
+       `grub_host_off_t'.  Type of member size changed to
+       `grub_host_size_t'.
+
+2005-09-29  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Make GRUB's kernel compliant to Multiboot Specification.
+
+       * kern/i386/pc/startup.S (multiboot_header): New label.
+       (multiboot_entry): Likewise.
+       (multiboot_trampoline): Likewise.
+
+       * include/grub/i386/pc/kernel.h (GRUB_KERNEL_MACHINE_RAW_SIZE):
+       Increased to 0x4A0.
+
+       * fs/xfs.c (grub_xfs_iterate_dir): Fix a syntax error. You may not
+       put parentheses after a question mark.
+       [!GRUB_UTIL] (my_mod): New variable.
+
+       * util/grub-emu.c (main): Call grub_xfs_init and grub_xfs_fini.
+
+2005-09-28  Marco Gerards  <mgerards@xs4all.nl>
+
+       Adds support for the XFS filesystem.  Btrees are not supported
+       yet.
+
+       * fs/xfs.c: New file.
+
+       * DISTLIST: Added `fs/xfs.c'.
+
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Add `fs/xfs.c'.
+       (grub_probefs_SOURCES): Likewise.
+       (grub_emu_SOURCES): Likewise.
+       (pkgdata_MODULES): Add `xfs.mod'.
+       (xfs_mod_SOURCES): New variable.
+       (xfs_mod_CFLAGS): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add `fs/xfs.c'.
+       (pkgdata_MODULES): Add `xfs.mod'.
+       (xfs_mod_SOURCES): New variable.
+       (xfs_mod_CFLAGS): Likewise.
+
+       * util/grub-emu.c (main): Call `grub_xfs_init' and
+       `grub_xfs_fini'.
+
+       * include/grub/fs.h (grub_xfs_init): New prototype.
+       (grub_xfs_fini): Likewise.
+
+
+2005-09-18  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * video/i386/pc/vbe.c (grub_vbe_set_video_mode): In indexed
+       color modes, allow greater than 16 colors to be configured as
+       a default palette.
+
+2005-09-03  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * normal/completion.c (complete_arguments): Add the qualifier
+       const into OPTIONS.
+
+       From Omniflux <omniflux+lists@omniflux.com>:
+       * include/grub/terminfo.h: New file.
+       * include/grub/tparm.h: Likewise.
+       * include/grub/i386/pc/serial.h: Likewise.
+       * term/terminfo.c: Likewise.
+       * term/tparm.c: Likewise.
+       * term/i386/pc/serial.c: Likewise.
+       * conf/i386-pc.rmk (pkgdata_MODULES): Added terminfo.mod and
+       serial.mod.
+       (terminfo_mod_SOURCES): New variable.
+       (terminfo_mod_CFLAGS): Likewise.
+       (serial_mod_SOURCES): Likewise.
+       (serial_mod_CFLAGS): Likewise.
+
+2005-08-31  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * DISTLIST: Replaced boot/powerpc/ieee1275/crt0.S and
+       boot/powerpc/ieee1275/cmain.c with kern/powerpc/ieee1275/crt0.S
+       and kern/powerpc/ieee1275/cmain.c, respectively.
+
+       * boot/powerpc/ieee1275/crt0.S: Moved to ...
+       * kern/powerpc/ieee1275/crt0.S: ... here.
+
+       * boot/powerpc/ieee1275/cmain.c: Moved to ...
+       * kern/powerpc/ieee1275/cmain.c: ... here.
+
+       * conf/powerpc-ieee1275.rmk (grubof_SOURCES): Use
+       kern/powerpc/ieee1275/crt0.S and kern/powerpc/ieee1275/cmain.c
+       instead of boot/powerpc/ieee1275/crt0.S and
+       boot/powerpc/ieee1275/cmain.c, respectively.
+
+       * boot/i386/pc/boot.S (lba_mode): Do not store the total number of
+       sectors. It was not used anyway.
+
+2005-08-30  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * term/ieee1275/ofconsole.c (grub_ofconsole_getcharwidth): Fix
+       `unused parameter' warning.
+
+2005-08-30  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * term/ieee1275/ofconsole.c (grub_ofconsole_getcharwidth): New
+       function.
+       (grub_ofconsole_term): Specify grub_ofconsole_getcharwidth as
+       getcharwidth.
+
+2005-08-28  Marco Gerards  <metgerards@student.han.nl>
+
+       * include/grub/normal.h (enum grub_completion_type): Added
+       `GRUB_COMPLETION_TYPE_ARGUMENT'.
+
+       * normal/cmdline.c (print_completion): Handle
+       the `GRUB_COMPLETION_TYPE_ARGUMENT' type.
+       * normal/menu_entry.c (store_completion): Likewise.
+
+       * normal/completion.c (complete_arguments): New function.
+       (grub_normal_do_completion): Call `complete_arguments' when the
+       current words start with a dash.
+
+2005-08-27  Marco Gerards  <metgerards@student.han.nl>
+
+       * conf/powerpc-ieee1275.rmk (pkgdata_MODULES): Fix typo (use
+       `gzio.mod' instead of `io.mod').
+
+2005-08-22  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * gendistlist.sh (EXTRA_DISTFILES): Added genfslist.sh.
+       (DISTDIRS): Added io and video.
+       Rewrite the search routine to make an output consistently.
+
+       * DISTLIST: Added conf/sparc64-ieee1275.mk,
+       conf/sparc64-ieee1275.rmk, include/grub/gzio.h,
+       include/grub/ieee1275/ieee1275.h, include/grub/ieee1275/ofdisk.h,
+       io/gzio.c, kern/sparc64/cache.c, kern/sparc64/dl.c,
+       kern/sparc64/ieee1275/init.c, kern/sparc64/ieee1275/openfw.c and
+       util/powerpc/ieee1275/misc.c.
+
+       * include/grub/gzio.h: New file.
+       * io/gzio.c: Likewise.
+
+       * kern/file.c (grub_file_close): Call grub_device_close only if
+       FILE->DEVICE is not NULL.
+
+       * include/grub/mm.h [!NULL] (NULL): New macro.
+
+       * include/grub/err.h (GRUB_ERR_BAD_GZIP_DATA): New constant.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Added io/gzip.c.
+       (pkgdata_MODULES): Added gzio.mod.
+       (gzio_mod_SOURCES): New variable.
+       (gzio_mod_CFLAGS): Likewise.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Added io/gzip.c.
+       (pkgdata_MODULES): Added gzio.mod.
+       (gzio_mod_SOURCES): New variable.
+       (gzio_mod_CFLAGS): Likewise.
+
+       * commands/cat.c: Include grub/gzio.h.
+       (grub_cmd_cat): Use grub_gzfile_open instead of
+       grub_file_open.
+
+       * commands/cmp.c: Include grub/gzio.h.
+       (grub_cmd_cmp): Use grub_gzfile_open instead of
+       grub_file_open.
+
+       * loader/i386/pc/multiboot.c: Include grub/gzio.h.
+       (grub_rescue_cmd_multiboot): Use grub_gzfile_open instead of
+       grub_file_open.
+       (grub_rescue_cmd_module): Likewise.
+
+2005-08-21  Vincent Pelletier  <subdino2004@yahoo.fr>
+
+       * conf/sparc64-ieee1275.rmk (grubof_SOURCES): The first file must be
+       kern/sparc64/ieee1275/init.c because it contains _start.
+       * conf/sparc64-ieee1275.mk: Generated from conf/sparc64-ieee1275.rmk.
+
+2005-08-21  Vincent Pelletier  <subdino2004@yahoo.fr>
+
+       * configure.ac: Add support for sparc64 host with ieee1275
+       firmware.
+       * configure: Generated from configure.ac.
+       * disk/ieee1275/ofdisk.c (grub_ofdisk_open): Use grub_ssize_t
+       instead of int.
+       (grub_ofdisk_read): Likewise.
+       (grub_ofdisk_open): Use %p to print pointer values, and cast the
+       pointers as (void *) to remove a warning.
+       (grub_ofdisk_close): Likewise.
+       (grub_ofdisk_read): Likewise.
+       * kern/ieee1275/ieee1275.c (grub_ieee1275_exit): This never
+       returns, so make it return void to remove a warning.
+       * include/grub/ieee1275/ieee1275.h (grub_ieee1275_exit):
+       Corresponding prototype change.
+       * kern/mm.c (grub_mm_init_region): Use %p to print pointer
+       values, and cast the pointers as (void *) to remove a warning.
+       (grub_mm_dump): Likewise.
+       * conf/sparc64-ieee1275.mk: New file.
+       * conf/sparc64-ieee1275.rmk: Likewise.
+       * include/grub/sparc64/setjmp.h: Likewise.
+       * include/grub/sparc64/types.h: Likewise.
+       * include/grub/sparc64/ieee1275/console.h: Likewise.
+       * include/grub/sparc64/ieee1275/ieee1275.h: Likewise.
+       * include/grub/sparc64/ieee1275/kernel.h: Likewise.
+       * include/grub/sparc64/ieee1275/time.h: Likewise.
+       * kern/sparc64/cache.c: Likewise.
+       * kern/sparc64/dl.c: Likewise.
+       * kern/sparc64/ieee1275/init.c: Likewise.
+       * kern/sparc64/ieee1275/openfw.c: Likewise.
+
+2005-08-21  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * util/console.c (grub_ncurses_putchar): If C is greater than
+       0x7f, set C to a question mark.
+       (grub_ncurses_getcharwidth): New function.
+       (grub_ncurses_term): Specify grub_ncurses_getcharwidth as
+       getcharwidth.
+
+       * normal/menu.c (print_entry): Made aware of Unicode. First,
+       convert TITLE to UCS-4, and predict the cursor position by
+       grub_getcharwidth.
+
+       * include/grub/misc.h (grub_utf8_to_ucs4): Specify the qualifier
+       const to SRC.
+       * kern/misc.c (grub_utf16_to_utf8): Likewise.
+
+2005-08-20  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * loader/powerpc/ieee1275/linux.c (grub_rescue_cmd_linux): Specify
+       the boot file by the option BOOT_IMAGE. Use grub_stpcpy instead of
+       grub_strcat.
+
+       * loader/i386/pc/linux.c (grub_rescue_cmd_linux): Specify the boot
+       file by the option BOOT_IMAGE. Use grub_stpcpy instead of
+       grub_strcpy and grub_strlen. Take it into account that a space
+       character is inserted as a delimiter.
+
+2005-08-20  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * partmap/pc.c (pc_partition_map_iterate): Include the value of an
+       invalid magic in the error.
+
+       * commands/search.c: New file.
+
+       * util/grub-emu.c (main): Call grub_search_init and
+       grub_search_fini.
+
+       * kern/rescue.c (grub_rescue_print_disks): Removed.
+       (grub_rescue_print_devices): New function.
+       (grub_rescue_cmd_ls): Use grub_device_iterate with
+       grub_rescue_print_devices instead of grub_disk_dev_iterate with
+       grub_rescue_print_disks.
+
+       * kern/partition.c (grub_partition_iterate): Return the result of
+       PARTMAP->ITERATE instead of GRUB_ERRNO.
+
+       * kern/device.c: Include grub/partition.h.
+       (grub_device_iterate): New function.
+
+       * include/grub/partition.h (grub_partition_iterate): Return int
+       instead of grub_err_t.
+
+       * include/grub/normal.h [GRUB_UTIL] (grub_search_init): New
+       prototype.
+       [GRUB_UTIL] (grub_search_fini): Likewise.
+
+       * include/grub/device.h (grub_device_iterate): New prototype.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Added
+       commands/search.c.
+       (pkgdata_MODULES): Added search.mod.
+       (search_mod_SOURCES): New variable.
+       (search_mod_CFLAGS): Likewise.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Added commands/search.c.
+       (pkgdata_MODULES): Added search.mod.
+       (search_mod_SOURCES): New variable.
+       (search_mod_CFLAGS): Likewise.
+
+       * commands/ls.c (grub_ls_list_disks): Renamed to ...
+       (grub_ls_list_devices): ... this, and use grub_device_iterate.
+       All callers changed.
+
+       * DISTLIST: Added commands/search.c.
+
+2005-08-20  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/term.c (grub_putchar): Use grub_utf8_to_ucs4 for the
+       conversion.
+       (grub_getcharwidth): New function.
+
+       * kern/misc.c (grub_utf8_to_ucs4): New function.
+
+       * include/grub/term.h (struct grub_term): Added a new member
+       "getcharwidth".
+       (grub_getcharwidth): New prototype.
+
+       * include/grub/misc.h (grub_utf8_to_ucs4): New prototype.
+
+       * term/i386/pc/console.c (map_char): New function. Segregated from
+       grub_console_putchar.
+       (grub_console_putchar): Use map_char.
+       (grub_console_getcharwidth): New function.
+       (grub_console_term): Specified grub_console_getcharwidth as
+       getcharwidth.
+
+       * term/i386/pc/vga.c (grub_vga_getcharwidth): New function.
+       (grub_vga_term): Specified grub_vga_getcharwidth as getcharwidth.
+
+       * term/i386/pc/vesafb.c (grub_virtual_screen_setup): Return
+       GRUB_ERRNO.
+       (grub_vesafb_init): Do not use RC. Instead, use GRUB_ERRNO. Rely
+       on grub_strtoul completely.
+       (write_char): Declare local variables in the beginning of the
+       function.
+       (grub_vesafb_getcharwidth): New function.
+       (grub_vesafb_term): Specified grub_vesafb_getcharwidth as
+       getcharwidth.
+
+2005-08-19  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * DISTLIST: Replace commands/i386/pc/vbe_list_modes.c and
+       commands/i386/pc/vbe_test.c with commands/i386/pc/vbeinfo.c and
+       commands/i386/pc/vbetest.c.
+
+       * video/i386/pc/vbe.c (grub_vbe_probe): If INFOBLOCK is not NULL,
+       call grub_vbe_get_controller_info again, because the returned
+       information is volatile.
+       (grub_vbe_set_video_mode): Mostly rewritten.
+       (grub_vbe_get_video_mode): Use grub_vbe_probe and use
+       grub_vbe_status_t correctly.
+       (grub_vbe_get_video_mode_info): Likewise.
+       (grub_vbe_set_pixel_rgb): Use a switch statement rather than
+       several if statements.
+
+       * commands/i386/pc/vbe_list_modes.c: Renamed to ...
+       * commands/i386/pc/vbeinfo.c: ... this.
+
+       * commands/i386/pc/vbe_test.c: Renamed to ...
+       * commands/i386/pc/vbetest.c: ... this.
+
+       * commands/i386/pc/vbeinfo.c (grub_cmd_vbe_list_modes): Renamed to
+       ...
+       (grub_cmd_vbeinfo): ... this. Save video modes before
+       iterating. Skip a video mode, if it is not available, not enough
+       information is given or it is monochrome. Show the memory
+       model. Leave the interpretation of MODEVAR to grub_strtoul
+       completely.
+       (GRUB_MOD_INIT): Rename vbe_list_modes to vbeinfo.
+       (GRUB_MOD_FINI): Likewise.
+
+       * commands/i386/pc/vbetest.c (grub_cmd_vbe_test): Renamed to ...
+       (grub_cmd_vbetest): ... this. Don't print unnecessarily. Use
+       grub_err_t instead of grub_uint32_t. Don't use SPTR. Remove a
+       duplicated grub_env_get. Leave the interpretation of MODEVAR to
+       grub_strtoul completely.
+       (real2pm): Removed.
+       (GRUB_MOD_INIT): Rename vbe_test to vbetest.
+       (GRUB_MOD_FINI): Likewise.
+
+       * normal/misc.c: Include grub/mm.h.
+
+       * conf/i386-pc.rmk (pkgdata_MODULES): Replaced vbe_test.mod and
+       vbe_list_modes with vbetest.mod and vbeinfo.mod.
+       (vbe_list_modes_mod_SOURCES): Removed.
+       (vbe_list_modes_mod_CFLAGS): Likewise.
+       (vbe_test_mod_SOURCES): Likewise.
+       (vbe_test_mod_CFLAGS): Likewise.
+       (vbeinfo_mod_SOURCES): New variable.
+       (vbeinfo_mod_CFLAGS): Likewise.
+       (vbetest_mod_SOURCES): Likewise.
+       (vbetest_mod_CFLAGS): Likewise.
+
+2005-08-18  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * normal/misc.c: New file.
+
+       * DISTLIST: Added normal/misc.c.
+
+       * partmap/amiga.c (amiga_partition_map_iterate): Add an argument
+       DISK to HOOK. Call HOOK with DISK.
+       * partmap/apple.c (apple_partition_map_iterate): Likewise.
+       * partmap/pc.c (pc_partition_map_iterate): Likewise.
+       * partmap/sun.c (sun_partition_map_iterate): Likewise.
+
+       * normal/menu_entry.c (struct screen): Added a new member
+       "completion_shown".
+       (completion_buffer): New global variable.
+       (make_screen): Set SCREEN->COMPLETION_SHOWN to zero.
+       (store_completion): New function.
+       (complete): Likewise.
+       (clear_completions): Likewise.
+       (grub_menu_entry_run): If SCREEN->COMPLETION_SHOWN is non-zero,
+       call clear_completions and reset SCREEN->COMPLETION_SHOWN. If C is
+       a tab, call complete.
+
+       * normal/completion.c (disk_dev): Removed.
+       (print_simple_completion): Likewise.
+       (print_partition_completion): Likewise.
+       (print_func): New global variable.
+       (add_completion): Do not take the arguments WHAT or PRINT any
+       longer. Added a new argument TYPE. Instead of printing directly,
+       call PRINT_FUNC if not NULL.
+       All callers changed.
+       (complete_device): Use a local variable DEV instead of
+       DISK_DEV. Do not move CURRENT_WORD to the end of a device name.
+       (grub_normal_do_completion): Take a new argument HOOK. Do not
+       initialize DISK_DEV. Initialize PRINT_FUNC to HOOK. If RET is an
+       empty string, return NULL instead.
+       All callers changed.
+
+       * normal/cmdline.c (print_completion): New function.
+
+       * kern/partition.c (grub_partition_iterate): Add an argument DISK
+       to HOOK.
+       All callers changed.
+
+       * kern/disk.c (grub_print_partinfo): Removed.
+
+       * include/grub/partition.h (struct grub_partition_map): Add a new
+       argument DISK into HOOK of ITERATE.
+       (grub_partition_iterate): Add a new argument DISK to HOOK.
+
+       * include/grub/normal.h (enum grub_completion_type): New enum.
+       (grub_completion_type_t): New type.
+       (GRUB_COMPLETION_TYPE_COMMAND): New constant.
+       (GRUB_COMPLETION_TYPE_DEVICE): Likewise.
+       (GRUB_COMPLETION_TYPE_PARTITION): Likewise.
+       (GRUB_COMPLETION_TYPE_FILE): Likewise.
+       (grub_normal_do_completion): Added a new argument HOOK.
+       (grub_normal_print_device_info): New prototype.
+
+       * include/grub/disk.h (grub_print_partinfo): Removed.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Added normal/misc.c.
+       (normal_mod_SOURCES): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       (normal_mod_SOURCES): Likewise.
+
+       * commands/ls.c (grub_ls_list_disks): Use
+       grub_normal_print_device_info instead of grub_print_partinfo. Free
+       PNAME.
+       (grub_ls_list_files): Use grub_normal_print_device_info instead of
+       duplicating the code.
+
+2005-08-16  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * commands/i386/pc/vbe_list_modes.c: Update source formatting to
+       follow GCS more precisely.
+       * commands/i386/pc/vbe_test.c: Likewise.
+       * include/grub/i386/pc/vbe.h: Likewise.
+       * term/i386/pc/vesafb.c: Likewise.
+       * video/i386/pc/vbe.c: Likewise.
+
+2005-08-16  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * DISTLIST: Added term/i386/pc/vesafb.c
+       DISTLIST: Added video/i386/pc/vbe.c
+       DISTLIST: Added commands/i386/pc/vbe_list_modes.c.
+       DISTLIST: Added commands/i386/pc/vbe_test.c.
+       * commands/i386/pc/vbe_list_modes.c: New file.
+       * commands/i386/pc/vbe_test.c: Likewise.
+       * term/i386/pc/vesafb.c: Likewise.
+       * video/i386/pc/vbe.c: Likewise.
+       * include/grub/i386/pc/vbe.h (GRUB_VBE_DEFAULT_VIDEO_MODE): Added define.
+       (grub_vbe_probe) Added prototype.
+       (grub_vbe_set_video_mode) Likewise.
+       (grub_vbe_get_video_mode) Likewise.
+       (grub_vbe_get_video_mode_info) Likewise.
+       (grub_vbe_set_pixel_rgb) Likewise.
+       (grub_vbe_set_pixel_index) Likewise.
+       * conf/i386-pc.rmk (pkgdata_MODULES): Added vbe.mod.
+       (pkgdata_MODULES): Added vesafb.mod.
+       (pkgdata_MODULES): Added vbe_list_modes.mod.
+       (pkgdata_MODULES): Added vbe_test.mod.
+       (vbe_mod_SOURCES): Added.
+       (vbe_mod_CFLAGS): Likewise.
+       (vesafb_mod_SOURCES): Likewise.
+       (vesafb_mod_CFLAGS): Likewise.
+       (vbe_list_modes_mod_SOURCES): Likewise.
+       (vbe_list_modes_mod_CFLAGS): Likewise.
+       (vbe_test_mod_SOURCES): Likewise.
+       (vbe_test_mod_CFLAGS): Likewise.
+
+2005-08-14  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * normal/command.c (grub_command_execute): If INTERACTIVE is
+       false and GRUB_COMMAND_FLAG_NO_ECHO is not specified, print
+       CMDLINE. Disable the pager if INTERACTIVE is true.
+       All callers are changed.
+
+       * normal/main.c (grub_normal_execute): Read command.lst and fs.lst
+       before reading a config file.
+       * normal/main.c (read_config_file): Even if a command is not
+       found, register it if it is within an entry.
+
+       * util/grub-emu.c: Include sys/types.h and unistd.h.
+       (options): Added --hold.
+       (struct arguments): Added a new member "hold".
+       (parse_opt): If KEY is 'H', set ARGS->HOLD to ARG or -1 if ARG is
+       missing.
+       (main): Initialize ARGS.HOLD to zero. Wait until ARGS.HOLD is
+       cleared by a debugger, if it is not zero.
+
+       * include/grub/normal.h (grub_command_execute): Add an argument
+       INTERACTIVE.
+
+2005-08-14  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * DISTLIST: Added include/grub/i386/pc/vbe.h.
+
+2005-08-13  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * aclocal.m4 (grub_I386_CHECK_REGPARM_BUG): Replace the test
+       program with another one, because the old one didn't detect a bug
+       in gcc-3.4. Always use regparm 2, because the new test is still
+       not enough for gcc-4.0. Someone must investigate a simple test
+       case which detects a bug in gcc-4.0.
+
+2005-08-12  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * DISTLIST: Added normal/completion.c.
+
+       * normal/completion.c: New file.
+
+       * term/i386/pc/console.c (grub_console_getwh): New function.
+       (grub_console_term): Assign grub_console_getwh to getwh.
+
+       * normal/cmdline.c (grub_tab_complete): Removed. Now the same
+       function is defined in normal/completion.c as
+       grub_normal_do_completion.
+       (grub_cmdline_get): Use grub_normal_do_completion instead of
+       grub_tab_complete.
+
+       * kern/partition.c (grub_partition_map_iterate): Return 1 if HOOK
+       returns non-zero, otherwise return 0.
+       (grub_partition_iterate): First, probe the partition map. Then,
+       call ITERATE only for this partition map.
+
+       * kern/misc.c (grub_strncmp): Rewritten.
+
+       * kern/disk.c (grub_disk_dev_iterate): Return 1 if P->ITERATE
+       returns non-zero. Otherwise return 0.
+
+       * include/grub/partition.h (grub_partition_map_iterate): Return
+       int instead of void.
+
+       * include/grub/normal.h (grub_normal_do_completion): New prototype.
+
+       * include/grub/misc.h (grub_strncmp): Change the type of N to
+       grub_size_t.
+
+       * include/grub/disk.h (grub_disk_dev_iterate): Return int instead
+       of void.
+
+       * normal/menu.c (draw_border): Cast GRUB_TERM_BORDER_WIDTH to
+       unsigned explicitly before comparing it with I.
+
+       * kern/main.c (grub_env_write_root): Add the attribute unused into
+       VAR.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Added
+       normal/completion.c.
+       (normal_mod_SOURCES): Likewise.
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise.
+       (normal_mod_SOURCES): Likewise.
+
+       * normal/command.c (grub_iterate_commands): If ITERATE returns
+       non-zero, return one immediately.
+
+2005-08-09  Vesa Jaaskelainen  <chaac@nic.fi>
+
+       * conf/i386-pc.rmk (kernel_img_HEADERS): Added machine/vbe.h.
+       * kern/i386/pc/startup.S: Updated Global Descriptor table's
+       descriptions.
+       (grub_vbe_get_controller_info): New function.
+       (grub_vbe_get_mode_info): Likewise.
+       (grub_vbe_set_mode): Likewise.
+       (grub_vbe_get_mode): Likewise.
+       (grub_vbe_set_memory_window): Likewise.
+       (grub_vbe_get_memory_window): Likewise.
+       (grub_vbe_set_scanline_length): Likewise.
+       (grub_vbe_get_scanline_length): Likewise.
+       (grub_vbe_set_display_start): Likewise.
+       (grub_vbe_get_display_start): Likewise.
+       (grub_vbe_set_palette_data): Likewise.
+       * include/grub/i386/pc/vbe.h: New file.
+
+2005-08-08  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * conf/powerpc-ieee1275.rmk (grubof_SOURCES): Replaced
+       kern/ieee1275/of.c with kern/ieee1275/ieee1275.c.
+       * DISTLIST: Likewise.
+       * kern/ieee1275/of.c: Moved to ...
+       * kern/ieee1275/ieee1275.c: ... here.
+
+2005-08-08  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * term/ieee1275/ofconsole.c: Include <grub/mm.h>.
+       (grub_ofconsole_getwh): Cast -1 to type grub_ieee1275_ihandle_t.
+       Pass 0 as `end' parameter to grub_strtoul().
+
+2005-08-08  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * include/grub/powerpc/ieee1275/console.h: Do not include
+       <grub/types.h>.  Do not include <grub/symbol.h>.  Remove ASM_FILE
+       ifdef.
+       (grub_console_cur_color): Remove i386-specific prototype.
+       (grub_console_real_putchar): Likewise.
+       (grub_console_checkkey): Likewise.
+       (grub_console_getkey): Likewise.
+       (grub_console_getxy): Likewise.
+       (grub_console_gotoxy): Likewise.
+       (grub_console_cls): Likewise.
+       (grub_console_setcursor): Likewise.
+       * kern/powerpc/ieee1275/init.c: Don't include <grub/console.h>.
+       Include <grub/machine/console.h>.
+       * term/ieee1275/ofconsole.c: Likewise.
+
+2005-08-08  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * Makefile.in (LIBLZO): New variable.
+
+       * configure.ac: Check for LZO version 2.
+
+       * util/i386/pc/grub-mkimage.c [HAVE_LZO_LZO1X_H]: Include
+       lzo/lzo1x.h instead of lzo1x.h.
+
+       * conf/i386-pc.rmk (grub_mkimage_LDFLAGS): Use $(LIBLZO) instead
+       of -llzo.
+
+       * util/i386/pc/grub-setup.c (main): Do not free PREFIX
+       twice. Reported by Vladimir Serbinenko <phcoder@gmail.com>.
+
+       * partmap/pc.c (pc_partition_map_probe): Restore P->DATA after
+       copying the data from PARTITION to P.
+
+2005-08-07  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/rescue.c (grub_rescue_cmd_rmmod): If the reference count is
+       negative, unload the module.
+
+       * util/i386/pc/grub-setup.c (setup): The name of the PC partition
+       map is "pc_partition_map" but not "pc".
+       (usage): Fix the description. The options are --boot-image and
+       --core-image but not --boot-file or --core-file.
+       (main): If not specified explicitly, make BOOT_FILE and CORE_FILE
+       based on DEFAULT_BOOT_FILE and DEFAULT_CORE_FILE with DIR or
+       DEFAULT_DIRECTORY.
+
+       * util/i386/pc/grub-install.in: Do not specify --boot-file or
+       --core-file. Specify INSTALL_DEVICE as an argument.
+
+       * util/console.c: Include config.h.
+       [HAVE_NCURSeS_CURSES_H]: Include ncurses/curses.h.
+       [HAVE_NCURSES_H]: Include ncurses.h.
+       [HAVE_CURSES_H]: Include curses.h.
+       [!A_NORMAL] (A_NORMAL): Defined as zero.
+       [!A_STANDOUT] (A_STANDOUT): Likewise.
+
+       * conf/i386-pc.rmk (grub_emu_LDFLAGS): Use $(LIBCURSES) instead of
+       -lncurses.
+       * conf/powerpc-ieee1275.rmk (grub_emu_LDFLAGS): Likewise.
+
+       * configure.ac: Check for curses libraries and headers.
+
+       * Makefile.in (LIBCURSES): New variable.
+
+       * genmk.rb (Script::rule): Set the executable bits.
+
+       * util/i386/pc/biosdisk.c (grub_util_biosdisk_get_grub_dev): The
+       name of the PC partition map is "pc_partition_map" but not "pc".
+
+2005-08-07  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * util/i386/pc/grub-install.in (grub_probefs): New variable.
+       (modules): Likewise.
+       (usage): Added descriptions for --modules and --grub-probefs.
+       Handle --modules and --grub-probefs. Save the arguments in MODULES
+       and GRUB_PROBEFS, respectively.
+       Auto-detect a filesystem module against GRUBDIR. If the result is
+       empty and modules are not specified explicitly, abort the
+       installation. Add the result to MODULES.
+
+       * DISTLIST: Removed boot/powerpc/ieee1275/ieee1275.c,
+       disk/powerpc/ieee1275/ofdisk.c,
+       include/grub/powerpc/ieee1275/init.h and
+       term/powerpc/ieee1275/ofconsole.c.
+       Added disk/ieee1275/ofdisk.c, kern/ieee1275/of.c and
+       term/ieee1275/ofconsole.c.
+
+       * include/grub/powerpc/ieee1275/console.h: Resurrected.
+
+       * COPYING: Upgraded to the latest version. Only the address of the
+       FSF office has changed.
+
+2005-08-07  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * conf/powerpc-ieee1275.rmk (grubof_SOURCES): Replaced
+       kern/ieee1275.c with kern/ieee1275/of.c.
+
+       * kern/ieee1275.c: Moved to ...
+       * kern/ieee1275/of.c: ... here.
+
+2005-08-06  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * conf/i386-pc.rmk (kernel_img_HEADERS): Reordered for
+       readability.
+
+       * config.guess: Updated to the latest version from gnulib.
+       * config.sub: Likewise.
+       * install.sh: Likewise.
+       * mkinstalldirs: Likewise.
+
+       * include/grub/console.h: Removed. This file is arch-specific. Do
+       not put this in include/grub.
+
+       * include/grub/i386/pc/console.h: Resurrected.
+
+       * util/console.c: Include grub/machine/console.h instead of
+       grub/console.h.
+       * util/grub-emu.c: Likewise.
+
+2005-08-04  Marco Gerards  <metgerards@student.han.nl>
+
+       * kern/term.c (grub_putcode): Use `grub_getwh' instead of
+       hardcoded value.
+
+       From Vincent Pelletier  <subdino2004@yahoo.fr>
+       * include/grub/term.h (GRUB_TERM_WIDTH, GRUB_TERM_HEIGHT):
+       Redefined to use grub_getwh.
+       (grub_term): New member named getwh.
+       (grub_getwh): New prototype.
+       * kern/term.c (grub_getwh): New function.
+       * term/i386/pc/console.c (grub_console_getwh): New function.
+       (grub_console_term): New member `getwh'.
+       * term/i386/pc/vga.c (grub_vga_getwh): New function.
+       (grub_vga_term): New member `getwh'.
+       * term/ieee1275/ofconsole.c (grub_ofconsole_readkey): Use
+       grub_ssize_t.
+       (grub_ofconsole_getw): New function.
+       (grub_ofconsole_init): Use grub_ssize_t and unsigned char.
+       (grub_ofconsole_term): New field named getwh and new initial
+       value.
+
+2005-08-03  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * include/grub/powerpc/ieee1275/ieee1275.h: Move ...
+       * include/grub/ieee1275/ieee1275.h: ... to here.  All users updated.
+       Move `abort', `grub_reboot', and `grub_halt' prototypes ...
+       * include/grub/powerpc/ieee1275/kernel.h: ... to here.
+       * commands/ieee1275/halt.c: Include <grub/machine/kernel.h> instead
+       of <grub/machine/ieee1275.h>.
+       * commands/ieee1275/reboot.c: Likewise.
+       * boot/powerpc/ieee1275/ieee1275.c: Move ...
+       * kern/ieee1275.c: ... to here.  All users updated.  Change all
+       parameter structs to use new type `grub_ieee1275_cell_t'.
+       * term/powerpc/ieee1275/ofconsole.c: Move ...
+       * term/ieee1275/ofconsole.c: ... to here.  All users updated.
+       * disk/powerpc/ieee1275/ofdisk.c: Move ...
+       * disk/ieee1275/ofdisk.c: ... to here.  All users updated.
+       * boot/powerpc/ieee1275/cmain.c: Change `grub_ieee1275_entry_fn' type
+       to return int.
+       * include/grub/i386/pc/console.h: Move to include/grub/console.h.
+       Remove unused prototypes.  All users updated.
+       * include/grub/powerpc/ieee1275/console.h: Removed.
+       * include/grub/powerpc/ieee1275/ieee1275.h: Define
+       `grub_ieee1275_cell_t'.
+       * kern/powerpc/ieee1275/openfw.c: Include <grub/machine/kernel.h>.
+       Cast comparisons with -1 to the correct type.
+       * loader/powerpc/ieee1275/linux.c (kernel_entry_t): Change parameter
+       type to match `grub_ieee1275_entry_fn'.
+
+2005-08-01  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * DISTLIST: Added util/i386/pc/grub-probefs.c.
+
+       * conf/i386-pc.rmk (sbin_UTILITIES): Added grub-probefs.
+       (grub_setup_SOURCES): Removed partmap/amiga.c, partmap/apple.c and
+       partmap/sun.c.
+       (grub_probefs_SOURCES): New variable.
+
+       * util/i386/pc/grub-probefs.c: New file.
+
+       * util/i386/pc/grub-setup.c (main): Call
+       grub_pc_partition_map_init, grub_ufs_init, grub_minix_init,
+       grub_hfs_init and grub_jfs_init to initialize the system. Call
+       grub_ufs_fini, grub_minix_fini, grub_hfs_fini, grub_jfs_init and
+       grub_pc_partition_map_fini to finish the system.
+
+2005-07-31  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * loader/i386/pc/multiboot.c (grub_multiboot_is_elf32): New
+       function.
+       (grub_multiboot_load_elf32): Likewise.
+       (grub_multiboot_is_elf64): Likewise.
+       (grub_multiboot_load_elf64): Likewise.
+       (grub_multiboot_load_elf): Likewise.
+       (grub_rescue_cmd_multiboot): Call grub_multiboot_load_elf to load
+       an ELF32 or ELF64 file.
+       This is based on a patch from Ruslan Nikolaev <nruslan@mail.com>.
+
+       From Serbinenko Vladimir <serbinenko.vova@list.ru>:
+       * kern/disk.c (grub_print_partinfo): Check if FS->LABEL is not
+       NULL before calling FS->LABEL.
+       * fs/fat.c (grub_fat_dir): Initialize DIRNAME to NULL.
+       * commands/ls.c (grub_ls_list_files): Show labels, if possible.
+       (grub_ls_list_disks): Check if FS and FS->LABEL are not NULL
+       before calling FS->LABEL.
+
+2005-07-26  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * util/i386/pc/grub-install.in (datadir): New variable.
+       (libdir): Removed.
+       (pkgdatadir): New variable.
+       (pkglibdir): Removed.
+
+2005-07-24  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * DISTLIST: Added util/i386/pc/grub-install.in.
+
+       * util/i386/pc/grub-install.in: New file.
+
+       * conf/i386-pc.rmk (sbin_SCRIPTS): New variable.
+       (grub_install_SOURCES): Likewise.
+
+       * genmk.rb: Added support for scripts.
+       (Script): New class.
+       (scripts): New variable.
+
+       * Makefile.in (install-local): Install sbin_SCRIPTS by
+       INSTALL_SCRIPT.
+       (uninstall): Remove sbin_SCRIPTS.
+
+       * util/i386/pc/grub-setup.c (main): If the argument is not a GRUB
+       device, try to get a GRUB device by
+       grub_util_biosdisk_get_grub_dev.
+       Free DEST_DEV.
+
+       * util/i386/pc/grub-mkdevicemap.c (usage): Remove a duplicated
+       description for --device-map.
+
+2005-07-20  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Change the semantics of variable hooks. They now return strings
+       instead of error values.
+
+       * util/i386/pc/grub-setup.c: Include grub/env.h.
+       (setup): Use grub_device_set_root instead of grub_env_set.
+
+       * kern/rescue.c (grub_rescue_cmd_root): Use grub_env_set and
+       grub_env_get instead of grub_device_set_root and
+       grub_device_get_root, respectively.
+
+       * kern/main.c (grub_env_write_root): New function.
+       (grub_set_root_dev): Register grub_env_write_hook for "root". Use
+       grub_env_set instead of grub_device_set_root.
+
+       * kern/env.c (HASHSZ): Reduced to 13, because GRUB does not need
+       many variables.
+       (grub_env_set): Set ENV->VALUE to the result of ENV->WRITE_HOOK
+       rather than calling ENV->WRITE_HOOK afterwards.
+       (grub_env_get): Return the result of ENV->READ_HOOK rather than
+       passing a pointer of a pointer.
+       (grub_register_variable_hook): Change the types of "read_hook" and
+       "write_hook" to grub_env_read_hook_t and grub_env_write_hook_t,
+       respectively.
+       Allocate the default empty string on the heap, because this string
+       may be freed later.
+
+       * kern/device.c: Include grub/env.h.
+       (grub_device_set_root): Removed.
+       (grub_device_get_root): Likewise.
+       (grub_device_open): Use grub_env_get instead of
+       grub_device_get_root.
+
+       * include/grub/env.h (grub_env_read_hook_t): New type.
+       (grub_env_write_hook_t): Likewise.
+       (grub_env_var): Change the types of "read_hook" and "write_hook"
+       to grub_env_read_hook_t and grub_env_write_hook_t, respectively.
+       (grub_register_variable_hook): Likewise.
+
+       * include/grub/device.h (grub_device_set_root): Removed.
+       (grub_device_set_root): Likewise.
+
+       * fs/fat.c (grub_fat_dir): Make a copy of PATH in DIRNAME, and
+       make sure that DIRNAME terminates with '/', so that
+       grub_fat_find_dir will fail if PATH is not a directory.
+
+       * commands/ls.c (grub_ls_list_files): Remove the qualifier const
+       from DIRNAME.
+       Use the qualifier auto for print_files and print_files_long.
+       If FS->DIR sets GRUB_ERRNO to GRUB_ERR_BAD_FILE_TYPE, try DIRNAME
+       as a regular file.
+       Put a newline only if there is no error.
+       (grub_cmd_ls): Remove grub_ls_print_files, because this is not
+       used.
+
+2005-07-20  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/partition.c (grub_partition_probe): Initialize PART to
+       NULL. Otherwise, when no partition map is registered, this returns
+       a garbage.
+
+2005-07-19  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * partmap/apple.c (apple_partition_map_iterate): Check if POS
+       equals GRUB_DISK_SECTOR_SIZE to see if the partition table is
+       valid.
+
+2005-07-18  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * commands/ls.c (grub_ls_list_disks): Print the filesystem
+       information on each device, if it does not have partitions. Print
+       "Device" instead of "Disk", because this function is not specific
+       to disk devices.
+
+       * normal/main.c (grub_rescue_cmd_normal): Make the variable CONFIG
+       static to ensure that it is put on the memory rather than a
+       register.
+
+2005-07-17  Yoshinori Okuji  <okuji@enbug.org>
+
+       * commands/cat.c (GRUB_MOD_INIT): Use better documentation.
+       (grub_cat_init): Likewise.
+       * loader/i386/pc/chainloader_normal.c (GRUB_MOD_INIT): Likewise.
+       (options): Likewise.
+       * commands/configfile.c (GRUB_MOD_INIT): Likewise.
+       (grub_configfile_init): Likewise.
+       * font/manager.c (GRUB_MOD_INIT): Likewise.
+       * commands/help.c (GRUB_MOD_INIT): Likewise.
+       (grub_help_init): Likewise.
+       * normal/command.c (grub_command_init): Likewise.
+       * loader/i386/pc/linux_normal.c (GRUB_MOD_INIT): Likewise.
+       * disk/loopback.c (grub_loop_init): Likewise.
+       (GRUB_MOD_INIT): Likewise.
+       * commands/ls.c (grub_ls_init): Likewise.
+       (GRUB_MOD_INIT): Likewise.
+       (options): Likewise.
+       * commands/boot.c (grub_boot_init): Likewise.
+       (GRUB_MOD_INIT): Likewise.
+       * loader/i386/pc/multiboot_normal.c (GRUB_MOD_INIT): Likewise.
+       * commands/i386/pc/reboot.c (grub_reboot_init): Likewise.
+       (GRUB_MOD_INIT): Likewise.
+       * commands/cmp.c (grub_cmp_init): Likewise.
+       (GRUB_MOD_INIT): Likewise.
+
+       * normal/arg.c: Use <> instead of "" to include header files.
+       (SHORT_ARG_HELP): New macro.
+       (SHORT_ARG_USAGE): Likewise.
+       (help_options): Specify SHORT_ARG_HELP and SHORT_ARG_USAGE instead
+       of 'h' and 'u' for help and usage, respectively. Use more GNU-like
+       descriptions.
+       (find_short): Check if C is 'h' or 'u' explicitly.
+       (grub_arg_show_help): Use space characters instead of tabs. Treat
+       SHORT_ARG_HELP and SHORT_ARG_USAGE exceptionally so that -h and -u
+       are shown with --help and --usage only if they are not used for
+       the command itself.
+       (parse_option): Use SHORT_ARG_HELP and SHORT_ARG_USAGE instead of
+       'h' and 'u'.
+
+       * include/grub/arg.h (struct grub_arg_option): Add the qualifier
+       const into "longarg". Change the type of "shortarg" to int.
+
+2005-07-17  Yoshinori Okuji  <okuji@enbug.org>
+
+       * boot/i386/pc/boot.S (boot_drive_check): New label.
+
+       * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_DRIVE_CHECK): New
+       macro.
+
+       * util/i386/pc/grub-setup.c (setup): Added a workaround for BIOSes
+       which do not pass a boot drive correctly. Copied from GRUB Legacy.
+
+2005-07-17  Yoshinori Okuji  <okuji@enbug.org>
+
+       * kern/i386/pc/startup.S (gate_a20_try_system_control_port_a):
+       When turning off Gate A20, skip the check and return immediately,
+       because this is not fatal usually.
+
+2005-07-17  Yoshinori Okuji  <okuji@enbug.org>
+
+       * conf/i386-pc.rmk (pxeboot_img_LDFLAGS): The text address should
+       be 0x7C00 instead of 0x8000.
+
+       * boot/i386/pc/pxeboot.S: Rewritten.
+
+       * kern/i386/pc/startup.S (gate_a20_try_bios): No need to specify
+       EXT_C.
+       (gate_a20_check_state): Read a byte from 0x108000. Invert the
+       result.
+
+2005-07-16  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/i386/pc/startup.S (grub_gate_a20): Rewritten for
+       robustness. This routine now supports a BIOS call and System
+       Control Port A to modify the gate A20.
+
+       * include/grub/i386/pc/kernel.h (GRUB_KERNEL_MACHINE_RAW_SIZE):
+       Increased to 0x440.
+
+2005-07-12  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * disk/powerpc/ieee1275/ofdisk.c (grub_ofdisk_open): dprintf the
+       device path and resulting ihandle.
+       (grub_ofdisk_close): dprintf the ihandle being closed.
+       (grub_ofdisk_read): dprintf function parameters.
+       * kern/mm.c (grub_mm_init_region): Likewise.
+       * loader/powerpc/ieee1275/linux.c: Remove extra whitespace.
+       (grub_linux_boot): dprintf the Linux entry point, initrd address and
+       size, and boot arguments.
+       (grub_rescue_cmd_linux): dprintf each ELF segment's address and size
+       before loading into memory.
+       (grub_rescue_cmd_initrd): dprintf the initrd's address and size
+       before loading into memory.
+
+2005-07-12  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/mm.c: Added much documentation.
+       (GRUB_MM_ALIGN_LOG2): When GRUB_CPU_SIZEOF_VOID_P is
+       8, set to 5 instead of 8.
+
+2005-07-10  Yoshinori Okuji  <okuji@enbug.org>
+
+       * DISTLIST: Added util/i386/pc/grub-mkimage.c.
+
+       * conf/i386-pc.rmk (sbin_UTILITIES): Added grub-mkdevicemap.
+       (grub_mkdevicemap_SOURCES): New variable.
+
+       * util/i386/pc/grub-mkdevicemap.c: New file. Mostly copied from
+       lib/device.c of GRUB Legacy.
+
+2005-07-10  Yoshinori Okuji  <okuji@enbug.org>
+
+       * commands/ls.c (grub_ls_list_files): Check if *PATH is NUL
+       instead of PATH is NULL.
+
+2005-07-09  Vincent Pelletier  <subdino2004@yahoo.fr>
+
+       * commands/cmp.c (BUFFER_SIZE): New macro.
+       (grub_cmd_cmp): Close the right file at the right time.  Compare
+       only data just read.  Don't report files of different  size as
+       identical.  Dynamically allocate buffers.  Move variable
+       declarations at the beginning of function.
+
+2005-07-09  Yoshinori Okuji  <okuji@enbug.org>
+
+       * aclocal.m4 (grub_I386_CHECK_REGPARM_BUG): The return value was
+       reverse.
+
+2004-07-04  Vincent Pelletier  <subdino2004@yahoo.fr>
+
+       * normal/cmdline.c (grub_cmdline_get): Don't fallback on ctrl-d
+       when backspace is pressed at beginning of line.
+
+2005-07-03  Yoshinori Okuji  <okuji@enbug.org>
+
+       * DISTLIST: Added genfslist.sh.
+
+       * normal/main.c (fs_module_list): New variable.
+       (autoload_fs_module): New function.
+       (read_fs_list): Likewise.
+       (grub_normal_execute): Call read_fs_list.
+
+       * kern/fs.c (grub_fs_autoload_hook): New variable.
+       (grub_fs_probe): Added support for auto-loading.
+
+       * include/grub/normal.h (struct grub_fs_module_list): New struct.
+       (grub_fs_module_list_t): New type.
+
+       * include/grub/fs.h (grub_fs_autoload_hook_t): New type.
+       (grub_fs_autoload_hook): New prototype.
+
+       * genfslist.sh: New file.
+
+       * genmk.rb: Added a rule to generate a filesystem list.
+
+2005-06-30  Marco Gerards  <metgerards@student.han.nl>
+
+       * configure.ac: Fix the test for cross-compiling.
+
+       * genmk.rb (Program): Use `$(CC)' instead of `$(BUILD_CC)'.  Don't
+       define GRUB_UTIL anymore.
+
+       * util/powerpc/ieee1275/grub-mkimage.c (load_note): Endian fixes
+       so this function works on other systems than just big endian.
+       (load_modules): Likewise.
+       (add_segments): Likewise.
+
+2005-06-23  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/misc.c (grub_vsprintf): Add `longfmt'.  If format string
+       contains `l' modifier, get a long from va_arg().
+
+2005-06-23  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/mm.c (grub_free): If the next free block which is being
+       merged is the first free block, set the first block to the block
+       being freed.
+       Reported by Vincent Guffens <guffens@inma.ucl.ac.be>.
+
+2005-05-08  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * boot/powerpc/ieee1275/cmain.c (cmain): Initialize
+       `grub_ieee1275_chosen'.
+
+2005-05-08  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * boot/powerpc/ieee1275/cmain.c (module_info): Remove definition.
+       (grub_ieee1275_chosen): New variable.
+       (cmain): Initialize and use `grub_ieee1275_chosen' instead of
+       `chosen'.
+       * boot/powerpc/ieee1275/crt0.S (init_stack): Remove stack space.
+       * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_get_property):
+       Rename first argument to `phandle' for consistency.
+       (grub_ieee1275_get_property_length): Likewise.
+       (grub_ieee1275_next_property): Likewise.  Change type of first argument
+       to grub_ieee1275_phandle_t.
+       * include/grub/powerpc/ieee1275/ieee1275.h (grub_ieee1275_entry_fn):
+       Move export next to declaration.
+       (grub_ieee1275_chosen): New variable.
+       * include/grub/powerpc/ieee1275/kernel.h (GRUB_IEEE1275_MODULE_BASE):
+       Correct cosmetic typo.
+       * kern/powerpc/ieee1275/init.c (grub_set_prefix): Use
+       `grub_ieee1275_chosen'.
+       * kern/powerpc/ieee1275/openfw.c (grub_map): Likewise.
+       * loader/powerpc/ieee1275/linux.c (grub_linux_boot): Likewise.
+       (grub_rescue_cmd_linux): Set `initrd_addr' to 0.
+       * term/powerpc/ieee1275/ofconsole.c (grub_ofconsole_refresh): Use
+       `grub_ieee1275_chosen'.
+
+2005-05-10  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * boot/powerpc/ieee1275/cmain.c (cmain): Remove code to parse
+       /chosen/bootargs.
+       * kern/powerpc/ieee1275/init.c (grub_machine_init): Parse
+       /chosen/bootargs as "variable=value" pairs.
+
+2005-05-08  Vincent Pelletier  <subdino2004@yahoo.fr>
+
+       * include/grub/misc.h (grub_dprintf): New macro.
+       (grub_real_dprintf): New prototype.
+       (grub_strword): Likewise.
+       (grub_iswordseparator): Likewise.
+       * kern/misc.c (grub_real_dprintf): New function.
+       (grub_strword): Likewise.
+       (grub_iswordseparator): Likewise.
+
+2005-04-30  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * boot/powerpc/ieee1275/cmain.c: Don't include grub/machine/init.h.
+       (roundup): Remove macro.
+       (grub_ieee1275_flags): Make static.
+       (grub_ieee1275_realmode): Remove.
+       (grub_ieee1275_test_flag): New function.
+       (grub_ieee1275_set_flag): Likewise.
+       (find_options): Rename to `grub_ieee1275_find_options'; update
+       callers. Set GRUB_IEEE1275_FLAG_REAL_MODE and
+       GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS.
+       (cmain): New prototype.
+       (cmain): Use `grub_ieee1275_set_flag' instead of accessing
+       `grub_ieee1275_flags' directly.
+       * conf/powerpc-ieee1275.rmk (grubof_HEADERS): Remove
+       machine/biosdisk.h.
+       * disk/powerpc/ieee1275/ofdisk.c: Include grub/machine/ofdisk.h.
+       Don't include grub/machine/init.h.
+       (grub_ofdisk_open): Call `grub_ieee1275_test_flag'.
+       * include/grub/powerpc/ieee1275/ieee1275.h (grub_ieee1275_flags):
+       Remove prototype.
+       (grub_ieee1275_realmode): Likewise.
+       (grub_ieee1275_flag): New enum.
+       (grub_ieee1275_test_flag): New prototype.
+       (grub_ieee1275_set_flag): New prototype.
+       * include/grub/powerpc/ieee1275/init.h: Remove file.
+       * include/grub/powerpc/ieee1275/ofdisk.h: New file.
+       * kern/powerpc/ieee1275/init.c: Don't include grub/machine/init.h.
+       Include grub/machine/console.h.  Include grub/machine/ofdisk.h.
+       (grub_machine_fini): Don't call `grub_ieee1275_release'.  Remove
+       comment.
+       * kern/powerpc/ieee1275/openfw.c (grub_claimmap): Call
+       `grub_ieee1275_test_flag'.
+       (grub_ieee1275_encode_devname): Likewise.
+
+2005-04-21  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * include/grub/powerpc/ieee1275/ieee1275.h
+       (grub_ieee1275_encode_devname): New prototype.
+       (grub_ieee1275_get_filename): Likewise.
+       * kern/powerpc/ieee1275/init.c (grub_translate_ieee175_path): New
+       function.
+       (grub_set_prefix): Likewise.
+       (grub_machine_init): Call grub_set_prefix.
+       * kern/powerpc/ieee1275/openfw.c: Fix typos.
+       (grub_parse_type): New enum.
+       (grub_ieee1275_get_devargs): New function.
+       (grub_ieee1275_get_devname): Likewise.
+       (grub_ieee1275_parse_args): Likewise.
+       (grub_ieee1275_get_filename): Likewise.
+       (grub_ieee1275_encode_devname): Likewise.
+
+2005-03-30  Marco Gerards  <metgerards@student.han.nl>
+
+       * kern/powerpc/ieee1275/init.c (grub_machine_fini): Don't call
+       `grub_loader_unset'.
+
+2005-03-26  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * commands/ieee1275/halt.c (grub_cmd_halt): Call grub_halt
+       instead of grub_ieee1275_interpret.
+       (grub_halt_init): New function.
+       (grub_halt_fini): Likewise.
+       (GRUB_MOD_INIT): Correct message grammar.
+       * commands/ieee1275/reboot.c (grub_cmd_reboot): Call grub_reboot
+       instead of grub_ieee1275_interpret.
+       (grub_reboot_init): New function.
+       (grub_reboot_fini): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Replace
+       commands/i386/pc/halt.c, commands/i386/pc/reboot.c, and
+       util/i386/pc/misc.c with commands/ieee1275/halt.c,
+       commands/ieee1275/reboot.c, and util/powerpc/ieee1275/misc.c.
+       * disk/powerpc/ieee1275/ofdisk.c (grub_ofdisk_fini): New
+       function.
+       * include/grub/powerpc/ieee1275/console.h (grub_console_fini):
+       Add prototype.
+       * include/grub/powerpc/ieee1275/ieee1275.h (grub_reboot): Add
+       prototype.
+       (grub_halt): Likewise.
+       * include/grub/powerpc/ieee1275/init.h: Remove inaccurate comment.
+       (cmain): Remove __attribute__((unused)).
+       * kern/powerpc/ieee1275/init.c (grub_heap_start): New variable.
+       (grub_heap_len): Likewise.
+       (grub_machine_fini): New function.
+       * kern/powerpc/ieee1275/openfw.c (grub_reboot): New function.
+       (grub_halt): Likewise.
+       * term/powerpc/ieee1275/ofconsole.c (grub_console_fini): New
+       function.
+       * util/powerpc/ieee1275/misc.c: New file.
+
+2005-03-19  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * DISTLIST: New file.
+       * gendistlist.sh: Likewise.
+
+       * Makefile.in (COMMON_DISTFILES): Removed.
+       (BOOT_DISTFILES): Likewise.
+       (CONF_DISTFILES): Likewise.
+       (DISK_DISTFILES): Likewise.
+       (FS_DISTFILES): Likewise.
+       (INCLUDE_DISTFILES): Likewise.
+       (KERN_DISTFILES): Likewise.
+       (LOADER_DISTFILES): Likewise.
+       (TERM_DISTFILES): Likewise.
+       (UTIL_DISTFILES): Likewise.
+       (DISTFILES): Likewise.
+       (uninstall): Uninstall files in $(pkgdata_DATA).
+       (DISTLIST): New target.
+       (distdir): Use the contents of the file DISTLIST to get a list of
+       distributed files.
+
+2005-03-18  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * fs/fat.c (grub_fat_mount): Ignore the 3rd bit of a media
+       descriptor. This is ported from GRUB Legacy.
+
+       * gencmdlist.sh: Added an extra semicolon to make it work with
+       old sed versions. Reported by Robert Bihlmeyer
+       <robbe@orcus.priv.at>.
+
+2005-03-08  Yoshinori Okuji  <okuji@enbug.org>
+
+       Automatic loading of commands is supported.
+
+       * normal/main.c (read_command_list): New function.
+       (grub_normal_execute): Call read_command_list.
+
+       * normal/command.c (grub_register_command): Return zero or CMD.
+       Allocate CMD->NAME from the heap.
+       Initialize CMD->MODULE_NAME to zero.
+       Find the same name as well. If the same command is found and it is
+       a dummy command, overwrite members. If it is not a dummy command,
+       return zero.
+       (grub_unregister_command): Free Q->NAME and Q->MODULE_NAME.
+       (grub_command_find): If a dummy command is found, load a module
+       and retry to find a command only once.
+
+       * normal/cmdline.c (grub_tab_complete): Call grub_command_find to
+       make sure that each command is loaded.
+
+       * include/grub/normal.h (GRUB_COMMAND_FLAG_NOT_LOADED): New
+       macro.
+       (struct grub_command): Remove const from the member `name'.
+       Add a new member `module_name'.
+       (grub_register_command): Return grub_command_t.
+
+       * commands/help.c (grub_cmd_help): Call grub_command_find to make
+       sure that each command is loaded.
+
+       * genmk.rb (PModule::rule): Specify a module name without the
+       suffix ".mod" to gencmdlist.sh.
+
+2005-03-02  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * gencmdlist.sh: New file.
+
+       * genmk.rb (PModule::rule): Generate a rule for a command list.
+       Clean command.lst.
+       Generate command.lst from $(COMMANDFILES).
+
+       * Makefile.in (COMMON_DISTFILES): Added gencmdlist.sh.
+       (DATA): Added $(pkgdata_DATA).
+       (install-local): Install files in $(pkgdata_DATA).
+
+2005-03-02  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * term/i386/pc/vga.c (debug_command): Removed.
+       (GRUB_MOD_INIT): Do not register the command "debug".
+
+       From Hollis Blanchard:
+       * commands/configfile.c: New file.
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Added
+       commands/configfile.c.
+       (pkgdata_MODULES): Added configfile.mod.
+       (configfile_mod_SOURCES): New variable.
+       (configfile_mod_CFLAGS): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Added
+       commands/configfile.c.
+       (pkgdata_MODULES): Added configfile.mod.
+       (configfile_mod_SOURCES): New variable.
+       (configfile_mod_CFLAGS): Likewise.
+       * util/grub-emu.c (main): Call grub_configfile_init and
+       grub_configfile_fini.
+       * include/grub/normal.h [GRUB_UTIL] (grub_configfile_init): New
+       prototype.
+       [GRUB_UTIL] (grub_configfile_fini): Likewise.
+
+2005-02-27  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * normal/arg.c (grub_arg_show_help): Do not show the bug report
+       address.
+
+       * commands/help.c (grub_cmd_help): Do not print newlines after
+       the last command in print_command_help.
+
+2005-02-27  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * commands/default.h: New file.
+       * commands/timeout.h: Likewise.
+       * normal/context.c: Likewise.
+
+       * util/misc.c: Do not include sys/times.h.
+       Include sys/time.h and grub/machine/time.h.
+       (grub_get_rtc): Rewritten with gettimeofday.
+
+       * util/grub-emu.c (main): Call grub_default_init and
+       grub_timeout_init before grub_normal_init, and call
+       grub_timeout_fini and grub_default_fini after grub_main.
+
+       * util/console.c (grub_ncurses_checkkey): Return the read
+       character or -1.
+
+       * normal/menu.c (run_menu): Set MENU->TIMEOUT to -1 once it
+       timeouts.
+
+       * normal/main.c (read_config_file): Push MENU. If this fails,
+       print an error and wait for a user input.
+       Print an error only if GRUB_ERRNO is not GRUB_ERR_NONE.
+       If a menu is empty or an error occurs, pop MENU.
+       (grub_normal_execute): Pop and free MENU after grub_menu_run
+       returns.
+
+       * kern/loader.c (grub_loader_boot): Call grub_machine_fini.
+
+       * include/grub/powerpc/ieee1275/time.h [GRUB_UTIL]: Do not
+       include time.h.
+       [GRUB_UTIL] (GRUB_TICKS_PER_SECOND): Use the same definition as
+       without GRUB_UTIL.
+       * include/grub/i386/pc/time.h [GRUB_UTIL]: Do not include
+       time.h.
+       [GRUB_UTIL] (GRUB_TICKS_PER_SECOND): Use the same definition as
+       without GRUB_UTIL.
+
+       * include/grub/normal.h (struct grub_menu_list): New struct.
+       (grub_menu_list_t): New type.
+       (struct grub_context): New struct.
+       (grub_context_t): New type.
+       (grub_register_command): Got rid of EXPORT_FUNC.
+       (grub_unregister_command): Likewise.
+       (grub_context_get): New prototype.
+       (grub_context_get_current_menu): Likewise.
+       (grub_context_push_menu): Likewise.
+       (grub_context_pop_menu): Likewise.
+       [GRUB_UTIL] (grub_default_init): Likewise.
+       [GRUB_UTIL] (grub_default_fini): Likewise.
+       [GRUB_UTIL] (grub_timeout_init): Likewise.
+       [GRUB_UTIL] (grub_timeout_fini): Likewise.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Added commands/default.c,
+       commands/timeout.c and normal/context.c.
+       (pkgdata_MODULES): Added default.mod and timeout.mod.
+       (normal_mod_SOURCES): Added normal/context.c.
+       (default_mod_SOURCES): New variable.
+       (default_mod_CFLAGS): Likewise.
+       (timeout_mod_SOURCES): Likewise.
+       (timeout_mod_CFLAGS): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Copied from
+       conf/i386-pc.rmk.
+       (pkgdata_MODULES): Added default.mod and timeout.mod.
+       (normal_mod_SOURCES): Added normal/context.c.
+       (default_mod_SOURCES): New variable.
+       (default_mod_CFLAGS): Likewise.
+       (timeout_mod_SOURCES): Likewise.
+       (timeout_mod_CFLAGS): Likewise.
+
+       * Makefile.in (all-local): Added $(MKFILES).
+
+2005-02-21  Vincent Pelletier  <subdino2004@yahoo.fr>
+
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Add `partmap/sun.c'.
+       (grub_emu_SOURCES): Likewise.
+       (pkgdata_MODULES): Add `sun.mod'.
+       (sun_mod_SOURCES, sun_mod_CFLAGS): New variables.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add
+       `partmap/sun.c'.
+       (pkgdata_MODULES): Add `sun.mod'.
+       (sun_mod_SOURCES, sun_mod_CFLAGS): New variables.
+       * include/grub/partition.h (grub_sun_partition_map_init): New
+       prototype.
+       (grub_sun_partition_map_fini): Likewise.
+       * partmap/sun.c: New file.
+       * util/grub-emu.c (main): Initialize and de-initialize the sun
+       partitionmap support.
+
+2005-02-19  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       This implements an Emacs-like menu entry editor.
+
+       * normal/menu_entry.c: New file.
+
+       * util/console.c (grub_ncurses_putchar): Translate some Unicode
+       characters to ASCII.
+       (saved_char): New variable.
+       (grub_ncurses_checkkey): Rewritten completely.
+       (grub_ncurses_getkey): Likewise.
+       (grub_ncurses_init): Call raw instead of cbreak.
+
+       * normal/menu.c (print_entry): Do not put a space.
+       (init_page): Renamed to ...
+       (grub_menu_init_page): ... this. All callers changed.
+       (edit_menu_entry): Removed.
+       (run_menu): Call grub_menu_entry_run instead of edit_menu_entry.
+
+       * normal/cmdline.c (grub_cmdline_run): Call grub_setcursor.
+
+       * kern/misc.c (grub_vprintf): Call grub_refresh.
+
+       * normal/menu.c (DISP_LEFT): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_LEFT): ... this.
+       * normal/menu.c (DISP_UP): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_UP): ... this.
+       * normal/menu.c (DISP_RIGHT): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_RIGHT): ... this.
+       * normal/menu.c (DISP_DOWN): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_DOWN): ... this.
+       * normal/menu.c (DISP_HLINE): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_HLINE): ... this.
+       * normal/menu.c (DISP_VLINE): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_VLINE): ... this.
+       * normal/menu.c (DISP_UL): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_UL): ... this.
+       * normal/menu.c (DISP_UR): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_UR): ... this.
+       * normal/menu.c (DISP_LL): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_LL): ... this.
+       * normal/menu.c (DISP_LR): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_DISP_LR): ... this.
+       * normal/menu.c (TERM_WIDTH): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_WIDTH): ... this.
+       * normal/menu.c (TERM_HEIGHT): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_HEIGHT): ... this.
+       * normal/menu.c (TERM_INFO_HEIGHT): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_INFO_HEIGHT): ... this.
+       * normal/menu.c (TERM_MARGIN): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_MARGIN): ... this.
+       * normal/menu.c (TERM_SCROLL_WIDTH): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_SCROLL_WIDTH): ... this.
+       * normal/menu.c (TERM_TOP_BORDER_Y): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_TOP_BORDER_Y): ... this.
+       * normal/menu.c (TERM_LEFT_BORDER_X): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_LEFT_BORDER_X): ... this.
+       * normal/menu.c (TERM_BORDER_WIDTH): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_BORDER_WIDTH): ... this.
+       * normal/menu.c (TERM_MESSAGE_HEIGHT): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_MESSAGE_HEIGHT): ... this.
+       * normal/menu.c (TERM_BORDER_HEIGHT): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_BORDER_HEIGHT): ... this.
+       * normal/menu.c (TERM_NUM_ENTRIES): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_NUM_ENTRIES): ... this.
+       * normal/menu.c (TERM_FIRST_ENTRY_Y): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_FIRST_ENTRY_Y): ... this.
+       * normal/menu.c (TERM_ENTRY_WIDTH): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_ENTRY_WIDTH): ... this.
+       * normal/menu.c (TERM_CURSOR_X): Renamed to ...
+       * include/grub/term.h (GRUB_TERM_CURSOR_X): ... this.
+       All callers changed.
+
+       * include/grub/normal.h: New prototype.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Added
+       normal/menu_entry.c.
+       (normal_mod_SOURCES): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       (normal_mod_SOURCES): Likewise.
+
+2005-02-15  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * include/grub/normal.h (grub_halt_init): New prototype.
+       (grub_halt_fini): Likewise.
+       (grub_reboot_init): Likewise.
+       (grub_reboot_fini): Likewise.
+
+       * util/grub-emu.c: Include signal.h.
+       (main_env): New global variable.
+       (grub_machine_init): Ignore SIGINT. Otherwise grub-emu cannot
+       catch C-c.
+       (grub_machine_fini): New function.
+       (main): Call grub_halt_init and grub_reboot_init before
+       grub_main, and grub_reboot_fini and grub_halt_fini after it.
+       Call setjmp with MAIN_ENV to go back afterwards.
+       Call grub_machine_fini right before return.
+
+       * include/grub/util/misc.h: Include setjmp.h.
+       (main_env): New prototype.
+
+       * include/grub/kernel.h (grub_machine_fini): New prototype.
+       * include/grub/i386/pc/biosdisk.h (grub_biosdisk_fini): Likewise.
+       * include/grub/i386/pc/console.h (grub_console_fini): Likewise.
+
+       * disk/i386/pc/biosdisk.c (grub_biosdisk_fini): New function.
+       * kern/i386/pc/init.c (grub_machine_fini): Likewise.
+       * term/i386/pc/console.c (grub_console_fini): Likewise.
+
+       * util/i386/pc/misc.c: New file.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Added
+       util/i386/pc/misc.c, commands/i386/pc/halt.c and
+       commands/i386/pc/reboot.c.
+
+2005-02-14  Guillem Jover  <guillem@hadrons.org>
+
+       * include/grub/dl.h (grub_dl_check_header): New prototype.
+       (grub_arch_dl_check_header): Change return type to grub_err_t,
+       remove size parameter and export function.  Update all callers.
+       * kern/dl.c (grub_dl_check_header): New function.
+       (grub_dl_load_core): Use `grub_dl_check_header' instead of
+       `grub_arch_dl_check_header'.  Check ELF type.  Check if sections
+       are inside the core.
+       * kern/i386/dl.c (grub_arch_dl_check_header): Remove arch
+       independent ELF header checks.
+       * kern/powerpc/dl.c (grub_arch_dl_check_header): Likewise.
+       * loader/i386/pc/multiboot.c (grub_rescue_cmd_multiboot): Use
+       `grub_dl_check_header' instead of explicit checks.  Check for the
+       ELF type.
+       * loader/powerpc/ieee1275/linux.c (grub_rescue_cmd_linux): Use
+       `grub_dl_check_header' instead of explicit checks.  Remove arch
+       specific ELF header checks.
+
+       * util/grub-emu.c (grub_arch_dl_check_header): Remove the
+       argument SIZE.
+
+2005-02-13  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * conf/powerpc-ieee1275.rmk (pkgdata_MODULES): Add ls.mod.
+       * include/grub/powerpc/libgcc.h (__mulsf3): New prototype.
+
+2005-02-12  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/partition.c (grub_partition_probe): Clear `grub_errno' and
+       return 0 if `grub_errno' is GRUB_ERR_BAD_PART_TABLE.
+       (part_map_iterate): Clear `grub_errno' and return 0 if
+       `partmap->iterate' returns GRUB_ERR_BAD_PART_TABLE.
+       * partmap/amiga.c (amiga_partition_map_iterate): Return
+       GRUB_ERR_BAD_PART_TABLE if no partition map magic is found.
+       * partmap/apple.c (apple_partition_map_iterate): Likewise.
+
+2005-02-01  Guillem Jover  <guillem@hadrons.org>
+
+       * loader/i386/pc/multiboot_normal.c (GRUB_MOD_INIT): Fix module
+       help info.
+
+2005-01-31  Marco Gerards  <metgerards@student.han.nl>
+
+       * include/grub/powerpc/ieee1275/loader.h (grub_load_linux):
+       Removed prototype.
+       (grub_rescue_cmd_linux): New prototype.
+       (grub_rescue_cmd_initrd): Likewise.
+       * powerpc/ieee1275/linux.c (grub_linux_boot): Remove struct
+       `bi_rec'.
+       (grub_linux_release_mem): Release the memory for the initrd.
+       (grub_load_linux): Renamed from this...
+       (grub_rescue_cmd_linux): ...To this.  Changed all callers.
+       Changed `entry' not to be static.  Loop over memory regions to
+       find another one when the default fails.
+       (grub_rescue_cmd_initrd): New function.
+       (grub_linux_init): Remove function.
+       (grub_linux_fini): Likewise.
+       (GRUB_MOD_INIT): Register `initrd'.
+       (GRUB_MOD_FINI): Unregister `initrd'.
+       * powerpc/ieee1275/linux_normal.c (grub_linux_normal_init):
+       Function removed.
+       (grub_linux_normal_fini): Likewise.
+       (GRUB_MOD_INIT): Register `initrd'.
+       (GRUB_MOD_FINI): Unregister `initrd'.
+
+2005-01-31  Marco Gerards  <metgerards@student.han.nl>
+
+       * commands/help.c: New file.
+       * normal/arg.c (show_help): Renamed to...
+       (grub_arg_show_help): ... this.
+       * commands/i386/pc/halt.c: New file.
+       * commands/i386/pc/reboot.c: Likewise.
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Add `commands/help.c'.
+       (pkgdata_MODULES): Add `reboot.mod', `halt.mod' and `help.mod'.
+       (help_mod_SOURCES, help_mod_CFLAGS, reboot_mod_SOURCES)
+       (reboot_mod_CFLAGS, halt_mod_SOURCES, halt_mod_CFLAGS): New
+       variables.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add
+       `commands/help.c'.
+       (pkgdata_MODULES): Add `help.mod'.
+       (help_mod_SOURCES, help_mod_CFLAGS): New variables.
+       * grub/i386/pc/init.h (grub_reboot): New prototype.
+       (grub_halt): Likewise.
+       * include/grub/normal.h (grub_arg_show_help): New prototype.
+       (grub_help_init): Likewise.
+       (grub_help_fini): Likewise.
+       * util/grub-emu.c (main): Initialize and deinitialize the help
+       command.
+
+       * normal/cmdline.c (grub_cmdline_get): Doc fix.
+
+       * normal/command.c (grub_command_init): Fixed the description of
+       the `set' and `unset' commands.
+
+2005-01-31  Marco Gerards  <metgerards@student.han.nl>
+
+       * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_interpret): New
+       function.
+       * commands/ieee1275/halt.c: New file.
+       * commands/ieee1275/reboot.c: Likewise.
+       * commands/ieee1275/suspend.c (grub_cmd_suspend): Use
+       `__attribute__ ((unused))'.  Some GCS related fixed.
+       (grub_suspend_init) [GRUB_UTIL]: Function removed.
+       (grub_suspend_fini): Likewise.
+       * conf/powerpc-ieee1275.rmk (pkgdata_MODULES): Add `reboot.mod'
+       and `halt.mod'.
+       (reboot_mod_SOURCES, reboot_mod_CFLAGS, halt_mod_SOURCES)
+       (halt_mod_CFLAGS): New variables.
+       * include/grub/powerpc/ieee1275/ieee1275.h
+       (grub_ieee1275_interpret): New prototype.
+
+2005-01-29  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * include/grub/misc.h (memmove): New prototype.
+       (memcpy): Likewise.
+
+2005-01-22  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * disk/powerpc/ieee1275/ofdisk.c (grub_ofdisk_open): Don't initialize
+       `devpath' to 0.  Use `name' instead of `devpath' with `grub_strndup'.
+
+2005-01-22  Marco Gerards  <metgerards@student.han.nl>
+
+       * kern/misc.c (grub_strndup): Function rewritten.
+
+2005-01-22  Vincent Pelletier  <subdino2004@yahoo.fr>
+
+       * normal/menu.c (TERM_WIDTH): Macro redefined.
+       (TERM_TOP_BORDER_Y): Likewise.
+       (draw_border): Replaced while-loop by a for-loop.  Make the number
+       of lines consistent with the number of lines displayed in
+       print_entries.  Added a margin below the rectangle.
+       (print_entry): Make the entry fit in the rectangle.
+       (print_entries): Display the scroll arrows next to the right
+       border.
+
+2005-01-21  Marco Gerards  <metgerards@student.han.nl>
+
+       * fs/minix.c (grub_minix_find_file): Reserve more space for
+       `fpath' so the \0 can be stored.  Use `grub_strcpy' instead of
+       `grub_strncpy' to copy `path' into it.
+
+2005-01-21  Marco Gerards  <metgerards@student.han.nl>
+
+       Add the loopback device, a device via which files can be accessed
+       as devices.
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Add `disk/loopback.c'.
+       (pkgdata_MODULES): Add loopback.mod.
+       (loopback_mod_SOURCES): New variable.
+       (loopback_mod_CFLAGS): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add
+       `disk/loopback.c'.
+       (pkgdata_MODULES): Add loopback.mod.
+       (loopback_mod_SOURCES): New variable.
+       (loopback_mod_CFLAGS): Likewise.
+       * disk/loopback.c: new file.
+       * include/grub/normal.h (grub_loop_init): New prototype.
+       (grub_loop_fini): New prototype.
+       * util/grub-emu.c (main): Initialize and de-initialize loopback
+       support.
+       * include/grub/disk.h (grub_disk_dev_id): Add
+       `GRUB_DISK_DEVICE_LOOPBACK_ID'.
+
+2005-01-20  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_enter): New
+       function.
+       * conf/powerpc-ieee1275.rmk (pkgdata_MODULES): Add suspend.mod.
+       (suspend_mod_SOURCES): New variable.
+       (suspend_mod_CFLAGS): Likewise.
+       * include/grub/powerpc/ieee1275/ieee1275.h (grub_ieee1275_enter):
+       New prototype.
+       * commands/ieee1275/suspend.c: New file.
+
+2005-01-20  Timothy Baldwin  <T.E.Baldwin99@members.leeds.ac.uk>
+
+       * include/grub/dl.h (GRUB_MOD_INIT): Changed `__attribute__
+       ((unused))' to `__attribute__ ((used))'.
+       (GRUB_MOD_FINI): Likewise.
+       * kern/dl.c (grub_dl_load_file): Fix null pointer dereference.
+       * genmk.rb (PModule): Assign space to common symbols when linking
+       modules.
+
+2005-01-20  Marco Gerards  <metgerards@student.han.nl>
+
+       * include/grub/mm.h (grub_mm_init_region): Change the type of the
+       `unsigned' arguments to `grub_size_t'.
+       (grub_malloc): Likewise.
+       (grub_realloc): Likewise.
+       (grub_memalign): Likewise.
+       * kern/i386/dl.c (grub_arch_dl_check_header): Likewise.
+       * kern/powerpc/dl.c (grub_arch_dl_check_header): Likewise.
+       * util/misc.c (grub_malloc): Likewise.
+       (grub_realloc): Likewise.
+       * kern/mm.c (get_header_from_pointer): Change the casts to
+       `unsigned' into a cast to `grub_size_t'.
+
+       * fs/fshelp.c (grub_fshelp_find_file): The `oldnode' should always
+       point to `currnode' when `currnode' is changed.
+
+       * util/grub-emu.c (main): Initialize `progname'.  Reported by Nico
+       Schottelius <nico-linux@schottelius.org>.
+
+2005-01-09  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * util/powerpc/ieee1275/grub-mkimage.c: Include <string.h>.
+       (note_path): Remove variable.
+       (GRUB_IEEE1275_NOTE_NAME): New macro.
+       (GRUB_IEEE1275_NOTE_TYPE): Likewise.
+       (grub_ieee1275_note_hdr): New structure.
+       (grub_ieee1275_note_desc): Likewise.
+       (grub_ieee1275_note): Likewise.
+       (load_note): Remove `dir' argument.  All callers updated.  Remove
+       `note_img' and `path'.  Do not load a file from `note_path'.
+       Initialize a struct grub_ieee1275_note and write that to `out'.
+       Use GRUB_IEEE1275_MODULE_BASE instead of MODULE_BASE.
+
+2005-01-05  Marco Gerards  <metgerards@student.han.nl>
+
+       * util/misc.c (grub_util_read_image): Revert last change.  It
+       called `grub_util_read_at', which seeks from the beginning of the
+       file.
+
+2005-01-04  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * TODO: Add note about endianness in grub-mkimage.
+       * boot/powerpc/ieee1275/crt0.S (note): Remove unused .note
+       section.
+       * conf/powerpc-ieee1275.rmk (bin_UTILITIES): Add grub-mkimage.
+       (grub_mkimage_SOURCES): New target.
+       * include/grub/kernel.h (grub_start_addr): Remove variable.
+       (grub_end_addr): Likewise.
+       (grub_total_module_size): Likewise.
+       (grub_kernel_image_size): Likewise.
+       (GRUB_MODULE_MAGIC): New constant.
+       (grub_module_info): New structure.
+       (grub_arch_modules_addr): New prototype.
+       (grub_get_end_addr): Remove prototype.
+       * include/grub/i386/pc/kernel.h (grub_end_addr): New prototype.
+       * include/grub/powerpc/ieee1275/kernel.h: New file.
+       * include/grub/util/misc.h (grub_util_get_fp_size): New
+       prototype.
+       (grub_util_read_at): Likewise.
+       (grub_util_write_image_at): Likewise.
+       * kern/main.c (grub_get_end_addr): Remove function.
+       (grub_load_modules): Call grub_arch_modules_addr instead of using
+       grub_end_addr.  Look for a grub_module_info struct in memory.  Use
+       the grub_module_info fields instead of calling grub_get_end_addr
+       as loop conditions.  Move grub_add_unused_region code here.
+       (grub_add_unused_region): Remove function.
+       * kern/i386/pc/init.c: Include grub/cache.h.
+       (grub_machine_init): Remove call to grub_get_end_addr.  Remove
+       one call to add_mem_region.
+       (grub_arch_modules_addr): New function.
+       * kern/powerpc/ieee1275/init.c (grub_end_addr): Remove variable.
+       (grub_total_module_size): Likewise.
+       Include grub/machine/kernel.h.
+       (grub_arch_modules_addr): New function.
+       * util/grub-emu.c (grub_end_addr): Remove variable.
+       (grub_total_module_size): Likewise.
+       (grub_arch_modules_addr): New function.
+       * util/misc.c: Include unistd.h.
+       (grub_util_get_fp_size): New function.
+       (grub_util_read_at): Likewise.
+       (grub_util_write_image_at): Likewise.
+       (grub_util_read_image): Call grub_util_read_at.
+       (grub_util_write_image): Call grub_util_write_image_at.
+       * util/i386/pc/grub-mkimage.c (generate_image): Allocate
+       additional memory in kernel_img for a struct grub_module_info.
+       Fill in that grub_module_info.
+       * util/powerpc/ieee1275/grub-mkimage.c: New file.
+
+2005-01-03  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_milliseconds):
+       New function.
+       * include/grub/powerpc/ieee1275/ieee1275.h
+       (grub_ieee1275_milliseconds): New prototype.
+       * include/grub/powerpc/ieee1275/time.h (GRUB_TICKS_PER_SECOND):
+       Change to 1000.
+       * kern/powerpc/ieee1275/init.c (grub_get_rtc): Call
+       grub_ieee1275_milliseconds.
+
+2005-01-03  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * boot/powerpc/ieee1275/cmain.c (grub_ieee1275_realmode): New
+       variable.
+       (find_options): New function.
+       (cmain): Call find_options.
+       * include/grub/powerpc/ieee1275/ieee1275.h
+       (grub_ieee1275_realmode): New extern variable.
+       * kern/powerpc/ieee1275/openfw.c (grub_claimmap): Only call
+       grub_map if grub_ieee1275_realmode is false.
+
+2004-12-29  Marco Gerards  <metgerards@student.han.nl>
+
+       * normal/cmdline.c (grub_cmdline_get): Redone logic so no empty
+       lines are inserted and make it work like readline.  Reported by
+       Vincent Pelletier <subdino2004@yahoo.fr>.
+
+2004-12-28  Marco Gerards  <metgerards@student.han.nl>
+
+       * boot/powerpc/ieee1275/crt0.S (_start): Don't set up the stack.
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCE): Remove
+       `kern/powerpc/cache.S'.
+
+2004-12-27  Marco Gerards  <metgerards@student.han.nl>
+
+       * genmk.rb: Handle the `Program' class in the main loop.  Written
+       by Johan Rydberg <jrydberg@gnu.org>.
+       (Program): New class.
+       (programs): New variable.
+       * boot/powerpc/ieee1275/cmain.c: Include <grub/machine/ieee1275.h>
+       instead of "grub/machine/ieee1275.h".  Include <grub/kernel.h>
+       instead of "grub/kernel.h".  Include <grub/machine/init.h>.
+       (help_arch): Function removed.
+       * conf/powerpc-ieee1275.rmk (grubof_HEADERS): Add
+       `powerpc/libgcc.h' and `loader.h'.
+       (pkgdata_PROGRAMS): New variable.
+       (sbin_UTILITIES): Variable removed.
+       (grub_emu_SOURCES): Added kern/powerpc/cache.S.
+       (grubof_SOURCES): Variable re-defined so it only includes the
+       core functionality.
+       (grubof_CFLAGS): Remove `-DGRUBOF'.
+       (pkgdata_MODULES, fshelp_mod_SOURCES, fshelp_mod_CFLAGS,
+       (fat_mod_SOURCES, fat_mod_CFLAGS, ext2_mod_SOURCES)
+       (ext2_mod_CFLAGS, ufs_mod_SOURCES, ufs_mod_CFLAGS)
+       (minix_mod_SOURCES, minix_mod_CFLAGS, hfs_mod_SOURCES)
+       (hfs_mod_CFLAGS, jfs_mod_SOURCES, jfs_mod_CFLAGS)
+       (iso9660_mod_SOURCES, iso9660_mod_CFLAGS, _linux_mod_SOURCES)
+       (_linux_mod_CFLAGS, linux_mod_SOURCES, linux_mod_CFLAGS)
+       (normal_mod_SOURCES, normal_mod_CFLAGS, normal_mod_ASFLAGS)
+       (hello_mod_SOURCES, hello_mod_CFLAGS, boot_mod_SOURCES)
+       (boot_mod_CFLAGS, terminal_mod_SOURCES, terminal_mod_CFLAGS)
+       (ls_mod_SOURCES, ls_mod_CFLAGS, cmp_mod_SOURCES, cmp_mod_CFLAGS)
+       (cat_mod_SOURCES, cat_mod_CFLAGS, font_mod_SOURCES)
+       (font_mod_CFLAGS, amiga_mod_SOURCES, amiga_mod_CFLAGS)
+       (apple_mod_SOURCES, apple_mod_CFLAGS, pc_mod_SOURCES)
+       (pc_mod_CFLAGS): New variables.
+       * disk/powerpc/ieee1275/ofdisk.c: Include <grub/machine/init.h>.
+       (grub_ofdisk_iterate): Add a prototype for `dev_iterate'.
+       * include/grub/dl.h (grub_arch_dl_sync_caches): New prototype.
+       * include/grub/loader.h (grub_os_area_addr, grub_os_area_size):
+       Moved from here...
+       * include/grub/i386/pc/init.h (grub_os_area_addr)
+       (rub_os_area_size): ... to here.
+       * include/grub/powerpc/ieee1275/ieee1275.h
+       (grub_ieee1275_entry_fn): Export symbol.
+       * include/grub/powerpc/ieee1275/init.h: New file.
+       * include/grub/powerpc/libgcc.h: Likewise.
+       * include/grub/cache.h: Likewise.
+       * kern/powerpc/cache.S: Likewise.  Written by Hollis Blanchard
+       <hollis@penguinppc.org>.
+       * kern/dl.c: Include <grub/cache.h>.
+       (grub_dl_flush_cache): New function.
+       (grub_dl_load_core): Call `grub_dl_flush_cache' to flush the cache
+       for this module.
+       * kern/powerpc/ieee1275/init.c (grub_ofdisk_init)
+       (grub_console_init): Removed prototypes.
+       (grub_machine_init): Don't initialize the modules anymore.
+       * kern/powerpc/ieee1275/openfw.c (grub_map): Make the function
+       static.
+       * include/grub/powerpc/types.h (GRUB_HOST_WORDS_LITTLEENDIAN):
+       Macro undef removed.
+       (GRUB_HOST_WORDS_BIGENDIAN): New macro.
+       * kern/powerpc/dl.c (grub_arch_dl_relocate_symbols): Add
+       relocation `R_PPC_REL32'.  Return an error when the relocation is
+       unknown.
+       * Makefile.in (DATA): Add `$(pkgdata_PROGRAMS)'.
+       * kern/i386/pc/init.c (grub_arch_sync_caches): New function.
+       * util/misc.c (grub_arch_sync_caches): Likewise.
+
+2004-12-19  Marco Gerards  <metgerards@student.han.nl>
+
+       * conf/powerpc-ieee1275.rmk (MOSTLYCLEANFILES): Remove
+       `symlist.c', add `grubof_symlist.c'.
+       (symlist.c): Variable removed.
+       (grubof_HEADERS): Variable added.
+       (grubof_symlist.c): New target.
+       (kernel_syms.lst): Use `grubof_HEADERS' instead of
+       `kernel_img_HEADERS'.
+       (grubof_SOURCES): Add `kern/powerpc/dl.c' and `grubof_symlist.c'.
+       * kern/powerpc/dl.c: New file.
+       * kern/powerpc/ieee1275/init.c (grub_arch_dl_check_header):
+       Function removed.
+       (grub_arch_dl_relocate_symbols): Likewise.
+       (grub_register_exported_symbols): Likewise.
+
+2004-12-13  Marco Gerards  <metgerards@student.han.nl>
+
+       * fs/ext2.c (grub_ext2_open): Don't use data after freeing it.
+       (grub_ext2_dir): Likewise.  Don't return in case of an error, jump
+       to fail instead.  Reported by Vincent Pelletier
+       <subdino2004@yahoo.fr>.
+
+       * fs/fshelp.c (grub_fshelp_find_file): Don't free `oldnode' when
+       it is not allocated.  Reported by Vincent Pelletier
+       <subdino2004@yahoo.fr>.
+
+       * normal/cmdline.c (grub_tab_complete): Add a blank line to the
+       output so the output looks better.
+
+2004-12-04  Marco Gerards  <metgerards@student.han.nl>
+
+       Modulize the partition map support and add support for the amiga
+       partition map.
+
+       * commands/ls.c: Include <grub/partition.h> instead of
+       <grub/machine/partition.h>.
+       * kern/disk.c: Likewise.
+       * kern/rescue.c: Likewise.
+       * loader/i386/pc/chainloader.c: Likewise.
+       * normal/cmdline.c: Likewise.
+       * kern/powerpc/ieee1275/init.c: Likewise.
+       (grub_machine_init): Call `grub_pc_partition_map_init',
+       `grub_amiga_partition_map_init' and
+       `grub_apple_partition_map_init'.
+       * conf/i386-pc.rmk (kernel_img_SOURCES): Remove
+       `disk/i386/pc/partition.c'.  Add `kern/partition.c'.
+       (kernel_img_HEADERS): Remove `machine/partition.h'.  Add
+       `partition.h' and `pc_partition.h'.
+       (grub_setup_SOURCES): Remove
+       `disk/i386/pc/partition.c'.  Add `kern/partition.c',
+       `partmap/amiga.c', `partmap/apple.c' and `partmap/pc.c'.
+       (grub_emu_SOURCES): Likewise.
+       (pkgdata_MODULES): Add `amiga.mod', `apple.mod' and `pc.mod'.
+       (amiga_mod_SOURCES, amiga_mod_CFLAGS, apple_mod_SOURCES)
+       (apple_mod_CFLAGS, pc_mod_SOURCES, pc_mod_CFLAGS): New variables.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Remove
+       `disk/powerpc/ieee1275/partition.c'.  Add `kern/partition.c',
+       `partmap/amiga.c', `partmap/apple.c' and `partmap/pc.c'.
+       (grubof_SOURCES): Likewise.
+       * disk/i386/pc/partition.c: File removed.
+       * disk/powerpc/ieee1275/partition.c: Likewise.
+       * include/grub/powerpc/ieee1275/partition.h: Likewise.
+       * include/grub/i386/pc/partition.h: Likewise.
+       * kern/partition.c: New file.
+       * partmap/amiga.c: Likewise.
+       * partmap/apple.c: Likewise.
+       * partmap/pc.c: Likewise.
+       * include/grub/partition.h: Likewise..
+       * include/grub/pc_partition.h: Likewise.
+       * util/grub-emu.c: Include <grub/partition.h> instead of
+       <grub/machine/partition.h>.
+       (main): Call `grub_pc_partition_map_init',
+       `grub_amiga_partition_map_init' and
+       `grub_apple_partition_map_init' and deinitialize afterwards.
+       * util/i386/pc/biosdisk.c: Include `#include
+       <grub/partition.h>' and `include <grub/pc_partition.h>' instead of
+       `<grub/machine/partition.h>'.
+       * util/i386/pc/grub-setup.c: Likewise.
+       * util/i386/pc/biosdisk.c: Likewise.
+       (grub_util_biosdisk_get_grub_dev): Only access the PC specific
+       partition information in case of a PC partition.
+       * util/i386/pc/grub-setup.c: Include `#include
+       <grub/partition.h>' and `include <grub/pc_partition.h>' instead of
+       `<grub/machine/partition.h>'.
+       (setup): Only access the PC specific partition information in case
+       of a PC partition.
+
+2004-11-17  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/powerpc/ieee1275/init.c (grub_setjmp): Remove function.
+       (grub_longjmp): Likewise.
+       * include/grub/powerpc/setjmp.h (grub_jmp_buf): Set array size to
+       20.
+       * normal/powerpc/setjmp.S: New file.
+       * conf/powerpc-ieee1275.rmk (grubof_SOURCES): Add
+       `normal/powerpc/setjmp.S'.
+       (grubof_CFLAGS): Add `-DGRUBOF'.
+       * include/grub/setjmp.h [GRUB_UTIL]: Changed condition to
+       [GRUB_UTIL && !GRUBOF].
+
+2004-11-16  Marco Gerards  <metgerards@student.han.nl>
+
+       * kern/powerpc/ieee1275/openfw.c (grub_devalias_iterate): Skip any
+       property named `name'.  Correctly handle the error returned by
+       `grub_ieee1275_finddevice' if a device can not be opened.
+
+2004-11-02  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * term/powerpc/ieee1275/ofconsole.c (grub_ofconsole_readkey): Test
+       `actual' for negativity.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Remove
+       kern/fshelp.c.
+
+2004-11-01  Marco Gerards  <metgerards@student.han.nl>
+
+       * term/i386/pc/vga.c (VGA_HEIGHT): Changed to 350.
+       (PAGE_OFFSET): New macro.
+       (CRTC_ADDR_PORT): Likewise.
+       (CRTC_DATA_PORT): Likewise.
+       (START_ADDR_HIGH_REGISTER): Likewise.
+       (START_ADDR_LOW_REGISTER): Likewise.
+       (GRAPHICS_ADDR_PORT): Likewise.
+       (GRAPHICS_DATA_PORT): Likewise.
+       (READ_MAP_REGISTER): Likewise.
+       (INPUT_STATUS1_REGISTER): Likewise.
+       (INPUT_STATUS1_VERTR_BIT): Likewise.
+       (page): New variable.
+       (wait_vretrace): New function.
+       (set_read_map): Likewise.
+       (set_start_address): Likewise.
+       (grub_vga_init): Use mode 0x10 instead of mode 0x12.  Switch to
+       the right page.
+       (check_vga_mem): Take the page into account.
+       (write_char): Likewise.
+       (write_cursor): Likewise.
+       (scroll_up): Likewise.  Copy the page to the page that is not
+       shown and switch between both pages.
+       (grub_vga_putchar): Fix off by one error.
+       (grub_vga_cls): Wait for the vertical retrace.  Take the page into
+       account.
+
+2004-11-01  Marco Gerards  <metgerards@student.han.nl>
+
+       Add support for iso9660 (including rockridge).
+
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Add fs/iso9660.c.
+       (iso9660_mod_SOURCES): New variable.
+       (iso9660_mod_CFLAGS): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add fs/iso9660.c.
+       * include/grub/fs.h (grub_iso9660_init): New prototype.
+       * util/grub-emu.c (main): Call `grub_iso9660_init'.
+       * fs/iso9660.c: New file.
+
+       * include/grub/misc.h (grub_strncat): New prototype.
+       * kern/misc.c (grub_strncat): New function.
+
+       * fs/hfs.c (grub_hfs_mount): Translate the error
+       `GRUB_ERR_OUT_OF_RANGE' to `GRUB_ERR_BAD_FS'.
+       * fs/jfs.c (grub_jfs_mount): Likewise.
+       * fs/ufs.c (grub_ufs_mount): Likewise.
+
+2004-10-28  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * boot/powerpc/ieee1275/cmain.c (cmain): Remove asm statements
+       which initialized BAT registers.
+       * boot/powerpc/ieee1275/ieee1275.c (IEEE1275_CALL_ENTRY_FN,
+       grub_ieee1275_common_hdr, INIT_IEEE1275_COMMON):
+       Move from here...
+       * include/grub/powerpc/ieee1275/ieee1275.h (IEEE1275_CALL_ENTRY_FN,
+       grub_ieee1275_common_hdr, INIT_IEEE1275_COMMON):
+       ... to here.
+       * kern/powerpc/ieee1275/openfw.c (grub_map): New function.
+       (grub_mapclaim): Likewise.
+       * loader/powerpc/ieee1275/linux.c (grub_load_linux): Use
+       grub_mapclaim instead of grub_ieee1275_claim.  Assign linux_addr by
+       hand.
+
+2004-10-19  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * conf/powerpc-ieee1275.rmk (COMMON_ASFLAGS): Remove -fno-builtin.
+       (COMMON_CFLAGS): Remove -fno-builtin and -D__ASSEMBLY__. Add
+       -ffreestanding and -msoft-float.
+
+2004-10-15  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * disk/powerpc/ieee1275/ofdisk.c (grub_ofdisk_open): Do not
+       append ":0" to devpath if the GRUB_IEEE1275_NO_PARTITION_0 flag is
+       set in grub_ieee1275_flags.
+
+2004-10-14  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * include/grub/powerpc/ieee1275/ieee1275.h (abort): Add function
+       prototype.
+       * kern/powerpc/ieee1275/init.c (grub_machine_init): Call
+       grub_console_init first.
+       Change the memory range used for grub_ieee1275_claim and
+       grub_mm_init_region.
+       Print an error message if the claim fails.
+       Include <grub/misc.h>.
+
+2004-10-13  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * disk/powerpc/ieee1275/ofdisk.c (grub_ofdisk_iterate):
+       Call grub_children_iterate for device nodes of type `scsi',
+       `ide', or `ata'.
+       (grub_ofdisk_open): Remove manual device alias resolution.
+       Fix memory leak when device cannot be opened.
+       * include/grub/powerpc/ieee1275/ieee1275.h
+       (grub_children_iterate): New prototype.
+       * kern/powerpc/ieee1275/openfw.c (grub_children_iterate):
+       New function.
+       * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_get_property):
+       Return -1 if args.size was -1.
+
+2004-10-11  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * boot/powerpc/ieee1275/cmain.c (grub_ieee1275_flags): New global.
+       (cmain): Accept 3 parameters. Test for 0xdeadbeef, indicating Old
+       World Macintosh. If Old Wold, set flag in grub_ieee1275_flags; claim
+       Open Firmware's memory for it; claim memory from _start to _end.
+       * boot/powerpc/ieee1275/crt0.S (__bss_start): New extern.
+       (_end): New extern.
+       (_start): Zero BSS from __bss_start to _end.
+       * include/grub/powerpc/ieee1275/ieee1275.h (grub_ieee1275_flags):
+       New extern.
+       (GRUB_IEEE1275_NO_PARTITION_0): New #define.
+
+2004-10-11  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_claim): Return
+       -1 if args.base was -1.
+
+2004-10-08  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * term/powerpc/ieee1275/ieee1275.c (grub_ofconsole_cls): Use an ANSI
+       escape sequence instead of a literal ^L. Also call
+       grub_ofconsole_gotoxy.
+
+2004-10-03  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_claim): change
+       void *  arguments to grub_addr_t.  All callers updated.  Also make
+       the `result' argument optional.
+       (grub_ieee1275_release): change void * arguments to grub_addr_t.
+       All callers updated.
+
+2004-09-22  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * commands/ls.c (grub_ls_list_files): Use the string following the
+       initial ')', if present, as the filesystem path.
+       * kern/rescue.c (grub_rescue_cmd_ls): Likewise.
+
+       * conf/powerpc-ieee1275.rmk (grubof_SOURCES): List crt0.S first.
+
+2004-09-18  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Make the source code of the menu interface more readable.
+
+       * normal/menu.c: Include grub/mm.h.
+       (TERM_WIDTH): New macro.
+       (TERM_HEIGHT): Likewise.
+       (TERM_INFO_HEIGHT): Likewise.
+       (TERM_MARGIN): Likewise.
+       (TERM_SCROLL_WIDTH): Likewise.
+       (TERM_TOP_BORDER_Y): Likewise.
+       (TERM_LEFT_BORDER_X): Likewise.
+       (TERM_BORDER_WIDTH): Likewise.
+       (TERM_MESSAGE_HEIGHT): Likewise.
+       (TERM_BORDER_HEIGHT): Likewise.
+       (TERM_NUM_ENTRIES): Likewise.
+       (TERM_FIRST_ENTRY_Y): Likewise.
+       (TERM_ENTRY_WIDTH): Likewise.
+       (TERM_CURSOR_X): Likewise.
+       (draw_border): Use macros instead of magic numbers.
+       (print_entry): Likewise.
+       (print_entries): Likewise.
+       (run_menu): Likewise. Also, handle the key 'e'.
+       (run_menu_entry): Ignore empty command lines.
+       (print_message): Added a new argument EDIT. If EDIT is true,
+       print a different message.
+       (init_page): Likewise.
+       (edit_menu_entry): New function. Not implemented yet.
+
+2004-09-17  Marco Gerards  <metgerards@student.han.nl>
+
+       Add `linux.mod' and `multiboot.mod' so linux and multiboot kernels
+       can be loaded from normal mode.
+
+       * conf/i386-pc.rmk (pkgdata_MODULES): Add `linux.mod' and
+       `multiboot.mod'.
+       (linux_mod_SOURCES, linux_mod_CFLAGS, multiboot_mod_SOURCES)
+       (multiboot_mod_CFLAGS): New variables.
+       * loader/i386/pc/linux_normal.c: New file.
+       * loader/i386/pc/multiboot_normal.c: Likewise.
+
+       * loader/i386/pc/linux.c (grub_rescue_cmd_initrd): Don't use the
+       attribute `unused'.
+
+       * fs/ext2.c (grub_ext2_iterate_dir): Fix typos in inode type.  Use
+       `fdiro' to read the mode information from instead of `diro'.
+
+       * fs/fshelp.c (grub_fshelp_find_file): Set type to foundtype after
+       looking up a symlink.
+
+       * include/grub/normal.h (GRUB_COMMAND_FLAG_NO_ARG_PARSE): New
+       macro.
+       * normal/command.c (grub_command_execute): Don't parse the
+       arguments when `GRUB_COMMAND_FLAG_NO_ARG_PARSE' is set in the
+       flags of the command.
+
+       * normal/menu.c (grub_menu_run): Fix typo.
+
+2004-09-14  Hollis Blanchard  <hollis@penguinppc.org>
+
+       * kern/powerpc/ieee1275/init.c (abort): Trap into Open Firmware.
+
+       * term/powerpc/ieee1275/ofconsole.c (grub_ofconsole_gotoxy): Use
+       `y + 1' instead of `y - 1'.
+
+       * conf/powerpc-ieee1275.rmk (grubof_LDFLAGS): Add `-N' and `-S'.
+
+2004-09-14  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       From Hollis Blanchard <hollis@penguinppc.org>:
+       * kern/misc.c (memmove): New alias for grub_memmove.
+       (memcmp): New alias for grub_memcmp.
+       (memset): New alias for grub_memset.
+       * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_get_property):
+       Change "int handle" to "grub_ieee1275_phandle_t handle".
+       * include/grub/powerpc/ieee1275/ieee1275.h
+       (grub_ieee1275_get_property): Likewise.
+
+2004-09-12  Tomas Ebenlendr  <ebik@ucw.cz>
+
+       Added normal mode command `chainloader' as module chain.mod, which
+       depends on normal.mod and _chain.mod.
+
+       * conf/i386-pc.rmk (pkgdata_MODULES): Add `chain.mod'.
+       (chain_mod_SOURCES, chain_mod_CFLAGS): Variables added.
+       * include/grub/i386/pc/loader.h (grub_rescue_cmd_chainloader):
+       Deleted prototype.
+       * loader/i386/pc/chainloader.c (grub_rescue_cmd_chainloader): All
+       but arguments parsing moved to ...
+       (grub_chainloader_cmd): ... here.  New function.
+       * include/grub/i386/pc/chainloader.h: New file.
+       * loader/i386/pc/chainloader_normal.c: Likewise.
+
+2004-09-11  Marco Gerards  <metgerards@student.han.nl>
+
+       * conf/i386-pc.rmk (kernel_img_SOURCES): Added kern/fshelp.c.
+       (grub_mkimage_LDFLAGS): Likewise.
+       (grub_emu_SOURCES): Likewise.
+       (kernel_img_HEADERS): Added fshelp.h.
+       * fs/ext2.c: Include <grub/fshelp.h>.
+       (FILETYPE_REG): New macro.
+       (FILETYPE_INO_REG): Likewise.
+       (grub_ext_sblock): Renamed to `grub_ext2_sblock'.
+       Changed all users.
+       (ext2_block_group): Renamed to `grub_ext2_block_group'.  Changed
+       all users.
+       (grub_fshelp_node): New struct.
+       (grub_ext2_data): Added member `diropen'.  Changed member `inode'
+       to a pointer.
+       (grub_ext2_get_file_block): Removed function.
+       (grub_ext2_read_block): New function.
+       (grub_ext2_read_file): Replaced parameter `data' by `node'.
+       This function was written.
+       (grub_ext2_mount): Read the root inode.  Create a diropen struct.
+       (grub_ext2_find_file): Removed function.
+       (grub_ext2_read_symlink): New function.
+       (grub_ext2_iterate_dir): Likewise.
+       (grub_ext2_open): Rewritten.
+       (grub_ext2_dir): Rewritten.
+       * include/grub/fshelp.h: New file.
+       * fs/fshelp.c: Likewise.
+
+2004-09-10  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * normal/menu.c: Include grub/loader.h and grub/machine/time.h.
+       (print_message): Add a missing newline.
+       (run_menu): Added timeout support.
+       (run_menu_entry): New local function.
+       (grub_menu_run): Added support for booting.
+
+       * kern/loader.c (grub_loader_is_loaded): New function.
+
+       * include/grub/powerpc/ieee1275/time.h: Include grub/symbol.h.
+       (grub_get_rtc): Exported.
+
+       * include/grub/i386/pc/time.h: Include grub/symbol.h.
+       (grub_get_rtc): Exported.
+
+       * include/grub/normal.h (struct grub_command_list): Remove
+       constant from the member `command'.
+
+       * include/grub/loader.h (grub_loader_is_loaded): Declared.
+
+       * include/grub/err.h (GRUB_ERR_INVALID_COMMAND): New constant.
+
+       * conf/i386-pc.rmk (kernel_img_HEADERS): Added machine/time.h.
+
+2004-08-28  Marco Gerards  <metgerards@student.han.nl>
+
+       Add support for the JFS filesystem.
+
+       * fs/jfs.c: New file.
+       * include/grub/fs.h (grub_jfs_init): New prototype.
+       (grub_jfs_fini): New prototype.
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/jfs.c.
+       (grub_emu_SOURCES): Likewise.
+       (pkgdata_MODULES): Add jfs.mod.
+       (jfs_mod_SOURCES): New variable.
+       (jfs_mod_CFLAGS): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add fs.jfs.c.
+       (grubof_SOURCES): Likewise.
+       * util/grub-emu.c (main): Initialize and deinitialize JFS support.
+
+       * fs/fat.c (grub_fat_find_dir): Convert the filename little
+       endian to the host endian.
+       (grub_fat_utf16_to_utf8): Move function from there...
+       * kern/misc.c (grub_utf16_to_utf8): ...to here.  Do not convert
+       the endianness of the source string anymore.
+       * include/grub/misc.h (grub_utf16_to_utf8): New prototype.
+
+2004-08-24  Marco Gerards  <metgerards@student.han.nl>
+
+       * commands/boot.c (grub_boot_init) [GRUB_UTIL]: Make conditional.
+       (grub_boot_fini) [GRUB_UTIL]: Likewise.
+       (GRUB_MOD_INIT) [!GRUB_UTIL]: Likewise.
+       (GRUB_MOD_FINI) [!GRUB_UTIL]: Likewise.
+
+       * fs/hfs.c (grub_hfs_find_node): Add a prototype for `node_found'.
+       (grub_hfs_iterate_dir): Make the function static.  Add prototypes
+       for `node_found' and `it_dir'.
+       (grub_hfs_dir): Add prototype for `dir_hook'.
+
+       * fs/minix.c (grub_minix_get_file_block): Add prototype for
+       `grub_get_indir'.  Rename `indir' in two blocks to `indir16'
+       and `indir32' to silence a gcc warning.
+
+       * include/grub/fs.h (grub_hfs_init): New prototype.
+       (grub_hfs_fini): Likewise.
+
+
+2004-08-21  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Each disk device has its own id now. This is useful to make use
+       of multiple disk devices.
+
+       * include/grub/disk.h (grub_disk_dev_id): New enum.
+       (GRUB_DISK_DEVICE_BIOSDISK_ID): New constant.
+       (GRUB_DISK_DEVICE_OFDISK_ID): Likewise.
+
+       * disk/i386/pc/biosdisk.c (grub_biosdisk_dev): Specify
+       GRUB_DISK_DEVICE_BIOSDISK_ID as an id.
+
+       * disk/powerpc/ieee1275/ofdisk.c (grub_ofdisk_dev): Specify
+       GRUB_DISK_DEVICE_OFDISK_ID as an id.
+
+       * util/i386/pc/biosdisk.c (grub_util_biosdisk_dev): Specify
+       GRUB_DISK_DEVICE_BIOSDISK_ID as an id.
+
+       * include/grub/disk.h (struct grub_disk_dev): Added a new member
+       "id" which is used by the cache manager.
+
+       * normal/main.c (grub_normal_init_page): Use "GNU GRUB" instead
+       of just "GRUB".
+
+2004-08-18  Marco Gerards  <metgerards@student.han.nl>
+
+       * fs/hfs.c: New file.
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/hfs.c.
+       (grub_emu_SOURCES): Likewise.
+       (pkgdata_MODULES): Add hfs.mod.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add fs/hfs.c.
+       (grubof_SOURCES): Likewise.
+       * util/grub-emu.c (main): Initialize and deinitialize HFS support.
+
+       * include/grub/misc.h (grub_strncasecmp): Add prototype.
+       * kern/misc.c (grub_strncasecmp): Add function.
+
+2004-08-14  Marco Gerards  <metgerards@student.han.nl>
+
+       * include/grub/arg.h (GRUB_ARG_OPTION_OPTIONAL): Surround macro
+       with parentheses.
+
+       * fs/ext2.c (FILETYPE_UNKNOWN): New macro.
+       (grub_ext2_dir): In case the directory entry type is unknown, read
+       it from the inode.
+
+2004-08-02  Peter Bruin  <pjbruin@dds.nl>
+
+       * loader/powerpc/ieee1275/linux.c (grub_linux_init): Pass
+       grub_load_linux instead of grub_rescue_cmd_linux as second
+       argument of grub_rescue_register_command.
+
+       * Makefile.in (RMKFILES): Add conf/powerpc-ieee1275.rmk.
+
+2004-07-27  Marco Gerards  <metgerards@student.han.nl>
+
+       * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_release): New
+       function.
+       * commands/boot.c: Remove the check for `GRUB_UTIL'.
+       * conf/powerpc-ieee1275.rmk (grubof_SOURCES): Add
+       `loader/powerpc/ieee1275/linux.c',
+       `loader/powerpc/ieee1275/linux_normal.c' and `commands/boot.c'.
+       * include/grub/powerpc/ieee1275/ieee1275.h
+       (grub_ieee1275_release): New prototype.
+       * include/grub/powerpc/ieee1275/loader.h: Rewritten.
+       * kern/powerpc/ieee1275/init.c (grub_machine_init): Initialize
+       normal, boot, linux and linux_normal.
+       * loader/powerpc/ieee1275/linux.c: New file.
+       * loader/powerpc/ieee1275/linux_normal.c: Likewise.
+
+2004-07-12  Marco Gerards  <metgerards@student.han.nl>
+
+       * normal/arg.c (grub_arg_parse): Correct error handling after
+       reallocating the argumentlist (check if `argl' is not null instead
+       of checking if `args' is not null).
+       * kern/mm.c (grub_realloc): Return the same pointer when using the
+       same region, instead of returning the header address.
+
+2004-07-11  Marco Gerards  <metgerards@student.han.nl>
+
+       * disk/powerpc/ieee1275/partition.c (grub_partition_iterate): Skip
+       one block instead of two when looking for the initial partition.
+       (grub_partition_probe): Initialize the local variable `p' with 0.
+       Use base 10 for the grub_strtoul call.
+       * kern/misc.c (grub_strncpy): Fix off by one bug.  Eliminated the
+       need for one local variable.
+       (grub_strtoul): Don't add the new value to `num', instead of that
+       just assign it.
+
+2004-07-11  Marco Gerards  <metgerards@student.han.nl>
+
+       * conf/i386-pc.rmk (pkgdata_IMAGE): Add pxeboot.img.
+       (pxeboot_img_SOURCES): New variable.
+       (pxeboot_img_ASFLAGS): Likewise.
+       (pxeboot_img_LDFLAGS): Likewise.
+       * boot/i386/pc/pxeboot.S: New file.  Based on pxeloader.S from
+       GRUB Legacy and boot.S.  Adopted for GRUB 2 by lode leroy
+       <lode_leroy@hotmail.com>.
+
+2004-06-27  Tomas Ebenlendr  <ebik@ucw.cz>
+
+       * kern/rescue.c (grub_enter_rescue_mode): Don't continue when
+       there was no input.
+
+2004-06-27  Tomas Ebenlendr  <ebik@ucw.cz>
+
+       * normal/cmdline.c (grub_set_history): Fix off by one bug.  Fixed
+       the history buffer logic.
+
+2004-06-27  Tomas Ebenlendr  <ebik@ucw.cz>
+
+       * fs/ext2.c (FILETYPE_INO_MASK, FILETYPE_INO_DIRECTORY)
+       (FILETYPE_INO_SYMLINK): New macros.
+       (grub_ext2_find_file): Check if the node is a directory using the
+       inode stat information instead of using the filetype in the
+       dirent.  Exclude the first character of an absolute symlink.
+       (grub_ext2_dir): Mask out the filetype part of the mode member of
+       the inode.
+
+2004-05-24  Marco Gerards  <metgerards@student.han.nl>
+
+       Add support for UFS version 1 and 2.  Add support for the minix
+       filesystem version 1 and 2, both the variants with 14 and 30 long
+       filenames.
+
+       * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/ufs.c and
+       fs/minix.c.
+       (grub_emu_SOURCES): Likewise.
+       (pkgdata_MODULES): Add ufs.mod and minix.mod.
+       (ufs_mod_SOURCES): New variable.
+       (ufs_mod_CFLAGS): Likewise.
+       (minix_mod_SOURCES): Likewise.
+       (minix_mod_CFLAGS): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add fs/ufs.c and
+       fs/minix.c.
+       (grubof_SOURCES): Likewise.
+       * fs/ufs.c: New file.
+       * fs/minix.c: New file.
+       * include/grub/fs.h (grub_ufs_init): New prototype.
+       (grub_ufs_fini): Likewise.
+       (grub_minix_init): Likewise.
+       (grub_minix_fini): Likewise.
+       * util/grub-emu.c (main): Initialize and deinitialize UFS and
+       minix fs.
+
+2004-04-30  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add normal/arg.c,
+       commands/ls.c, commands/terminal.c, commands/boot.c,
+       commands/cmp.c and commands/cat.c.
+       (grubof_LDFLAGS): Add -nostdlib -static-libgcc -lgcc.
+
+       * kern/powerpc/ieee1275/init.c: Include "grub/env.h" instead of
+       "env.h"
+
+2004-04-04  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       All symbols prefixed with PUPA_ and pupa_ are renamed to GRUB_
+       and grub_, respectively. Because the conversion is trivial and
+       mechanical, I omit the details here. Please refer to the CVS
+       if you need more information.
+
+2004-04-04  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * include/pupa: Renamed to ...
+       * include/grub: ... this.
+       * util/i386/pc/pupa-mkimage.c: Renamed to ...
+       * util/i386/pc/grub-mkimage.c: ... this.
+       * util/i386/pc/pupa-setup.c: Renamed to ...
+       * util/i386/pc/grub-setup.c: ... this.
+       * util/pupa-emu.c: Renamed to ...
+       * util/grub-emu.c: ... this.
+
+2004-03-29  Marco Gerards  <metgerards@student.han.nl>
+
+       Add support for the newworld apple macintosh (PPC).  This has been
+       tested on the powerbook 2000 only.  It only adds support for
+       generic ieee1275 functions, console and disk support.  This should
+       be easy to port to other architectures with support for Open
+       Firmware.
+
+       * configure.ac: Accept the powerpc as host_cpu.  In the case of
+       the powerpc cpu set the host_vendor to ieee1275.  Make sure the i386
+       specific tests are only executed while building for the i386.
+       Inverse test for crosscompile.
+       * genmk.rb (Utility): Allow assembler files.
+       * normal/cmdline.c (pupa_tab_complete): Reset pupa_errno.
+       * conf/powerpc-ieee1275.rmk: New file.
+       * disk/powerpc/ieee1275/ofdisk.c: Likewise.
+       * disk/powerpc/ieee1275/partition.c: Likewise.
+       * include/pupa/powerpc/ieee1275/biosdisk.h: Likewise.
+       * include/pupa/powerpc/ieee1275/console.h: Likewise.
+       * include/pupa/powerpc/ieee1275/partition.h: Likewise.
+       * include/pupa/powerpc/ieee1275/time.h: Likewise.
+       * include/pupa/powerpc/ieee1275/util/biosdisk.h: Likewise.
+       * include/pupa/powerpc/ieee1275/multiboot.h: Likewise.
+       * include/pupa/powerpc/ieee1275/loader.h
+       * include/pupa/powerpc/setjmp.h: Likewise.
+       * include/pupa/powerpc/types.h: Likewise.
+       * kern/powerpc/ieee1275/init.c: Likewise.
+       * kern/powerpc/ieee1275/openfw.c: Likewise.
+       * term/powerpc/ieee1275/ofconsole.c: Likewise.
+
+       These files were written by Johan Rydberg
+       (jrydberg@night.trouble.net) and I only modified them slightly.
+
+       * boot/powerpc/ieee1275/cmain.c: New file.
+       * boot/powerpc/ieee1275/crt0.S: Likewise.
+       * boot/powerpc/ieee1275/ieee1275.c: Likewise.
+       * include/pupa/powerpc/ieee1275/ieee1275.h: Likewise.
+
+2004-03-14  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * Makefile.in: Update copyright.
+       * genmodsrc.sh: Likewise.
+       * gensymlist.sh: Likewise.
+       * term/i386/pc/vga.c: Indent correctly.
+
+       * util/i386/pc/pupa-mkimage.c (usage): Use PACKAGE_BUGREPORT as
+       bugreporting address.
+       * util/i386/pc/pupa-setup.c (usage): Likewise,
+       (main): Call pupa_ext2_init and pupa_ext2_fini.
+
+       * fs/fat.c (log2): Renamed to ...
+       (fat_log2): ... this.
+       All callers changed.
+       * kern/misc.c (memcpy): Alias to pupa_memmove.
+       * loader/i386/pc/multiboot.c (pupa_rescue_cmd_multiboot): Fix
+       lvalue cast.
+       * util/console.c (pupa_ncurses_fini): Return 0.
+
+       * util/i386/pc/biosdisk.c (pupa_util_biosdisk_open)[__linux__]:
+       Move fail label here.
+       [__GNU__]: Don't warn when using stat.
+       (open_device)[!__linux__]: Check if FD < 0 instead of !FD.
+       (pupa_util_biosdisk_get_pupa_dev)[__GNU__]: Change type of N to
+       long int. Use strtol instead of strtoul.
+
+2004-03-14  Marco Gerards  <metgerards@student.han.nl>
+
+       * commands/boot.c: New file.
+       * commands/cat.c: Likewise.
+       * commands/cmp.c: Likewise.
+       * commands/ls.c: Likewise.
+       * commands/terminal.c: Likewise.
+       * normal/command.c: Include <pupa/env.h> and <pupa/dl.h>.
+       (pupa_register_command): Changed interface to match the new
+       argument parser.
+       (pupa_command_execute): Changed (almost rewritten) so it uses
+       pupa_split_command.  Added support for setting variables using the
+       syntax `foo=bar'.
+       (rescue_command): Changed to work with the new argument parser.
+       (terminal_command): Moved from here to commands/terminal.c.
+       (set_command): New function.
+       (unset_command): New function.
+       (insmod_command): New function.
+       (rmmod_command): New function.
+       (lsmod_command): New function.
+       (pupa_command_init): Don't initialize the command terminal
+       anymore.  Initialize the commands set, unset, insmod, rmmod and
+       lsmod.
+       * conf/i386-pc.rmk (kernel_img_SOURCES): Add kern/env.c.
+       (kernel_img_HEADERS): Add arg.h and env.h.
+       (pupa_mkimage_LDFLAGS): Add kern/env.c.
+       (pupa_emu_SOURCES): Add kern/env.c, commands/ls.c,
+       commands/terminal.c commands/boot.c commands/cmp.c commands/cat.c,
+       normal/arg.c.
+       (pkgdata_MODULES): Add ls.mod, boot.mod, cmp.mod, cat.mod and
+       terminal.mod.
+       (normal_mod_SOURCES): Add normal/arg.c and normal/arg.c.
+       (boot_mod_SOURCES): New variable.
+       (terminal_mod_SOURCES): Likewise.
+       (ls_mod_SOURCES): Likewise.
+       (cmp_mod_SOURCES): Likewise.
+       (cat_mod_SOURCES): Likewise.
+
+       * normal/arg.c: New file.
+       * kern/env.c: Likewise.
+       * include/pupa/arg.h: Likewise.
+       * include/pupa/env.h: Likewise.
+       * font/manager.c (font_command): Changed to match argument parsing
+       interface changes.
+       (PUPA_MOD_INIT): Likewise.
+       * hello/hello.c (pupa_cmd_hello): Likewise.
+       (PUPA_MOD_INIT): Likewise.
+       * include/pupa/disk.h: Include <pupa/device.h>.
+       (pupa_print_partinfo): New prototype.
+       * include/pupa/dl.h (pupa_dl_set_prefix): Prototype removed.
+       (pupa_dl_get_prefix): Likewise.
+       * include/pupa/misc.h: Include <pupa/err.h>.
+       (pupa_isgraph): New prototype.
+       (pupa_isdigit): Likewise.
+       (pupa_split_cmdline): Likewise.
+       * include/pupa/normal.h: Include <pupa/arg.h>.
+       (pupa_command): Changed the prototype of the member `func' to
+       match the argument parsing interface.  Added member `options'.
+       (pupa_register_command): Updated to match function.
+       (pupa_arg_parse): New prototype.
+       (pupa_hello_init) [PUPA_UTIL]: New prototype.
+       (pupa_hello_fini) [PUPA_UTIL]: Likewise.
+       (pupa_ls_init) [PUPA_UTIL]: Likewise.
+       (pupa_ls_fini) [PUPA_UTIL]: Likewise.
+       (pupa_cat_init) [PUPA_UTIL]: Likewise.
+       (pupa_cat_fini) [PUPA_UTIL]: Likewise.
+       (pupa_boot_init) [PUPA_UTIL]: Likewise.
+       (pupa_boot_fini) [PUPA_UTIL]: Likewise.
+       (pupa_cmp_init) [PUPA_UTIL]: Likewise.
+       (pupa_cmp_fini) [PUPA_UTIL]: Likewise.
+       (pupa_terminal_init) [PUPA_UTIL]: Likewise.
+       (pupa_terminal_fini) [PUPA_UTIL]: Likewise.
+       * kern/disk.c: Include <pupa/file.h>.
+       (pupa_print_partinfo): New function.
+       * kern/dl.c: Include <pupa/env.h>.
+       (pupa_dl_dir): Variable removed.
+       (pupa_dl_load): Use the environment variable `prefix' instead of
+       the variable pupa_dl_dir.
+       (pupa_dl_set_prefix): Function removed.
+       (pupa_dl_get_prefix): Likewise.
+       * kern/i386/pc/init.c: Include <pupa/env.h>.
+       (pupa_machine_init): Use the environment variable `prefix' instead of
+       using pupa_dl_set_prefix to set the prefix.
+       * kern/main.c: Include <pupa/env.h>.
+       (pupa_set_root_dev): Use the environment variable `prefix' instead of
+       using pupa_dl_get_prefix to get the prefix.
+       * kern/misc.c: Include <pupa/env.h>.
+       (pupa_isdigit): New function.
+       (pupa_isgraph): Likewise.
+       (pupa_ftoa): Likewise.
+       (pupa_vsprintf): Added support for printing values of the type
+       `double'.  Make it possible to format variable output when using
+       formatting like `%1.2%f'.
+       (pupa_split_cmdline): New function.
+       * kern/rescue.c: Include <pupa/env.h>.
+       (next_word): Removed function.
+       (pupa_rescue_cmd_prefix): Likewise.
+       (pupa_rescue_cmd_set): New function.
+       (pupa_rescue_cmd_unset): New function.
+       (pupa_enter_rescue_mode): Use the `pupa_split_cmdline' function to
+       split the command line instead of splitting it here.  Added
+       support for setting variables using the syntax `foo=bar'.  Don't
+       initialize the prefix command anymore.  Initialized the set and
+       unset commands.
+       * normal/cmdline.c: Include <pupa/env.h>.
+       (pupa_tab_complete): Added prototypes for print_simple_completion,
+       print_partition_completion, add_completion, iterate_commands,
+       iterate_dev, iterate_part and iterate_dir. Moved code to print
+       partition information from here to kern/disk.c.
+       (pupa_cmdline_run): Don't check if the function exists anymore.
+       * normal/main.c: Include <pupa/env.h>.
+       (pupa_rescue_cmd_normal): Use the environment variable `prefix'
+       instead of using pupa_dl_get_prefix to get the prefix.
+       * term/i386/pc/vga.c: Include <pupa/arg.h>.
+       (check_vga_mem): Cast pointers to `void *' to silence a gcc
+       warning.
+       (pupa_vga_putchar) [! DEBUG_VGA]: Removed for this case.
+       (pupa_vga_setcolor): Declare unused variables with `__attribute__
+       ((unused))' to silence a gcc warning.
+       (pupa_vga_setcolor): Likewise.
+       (debug_command): Changed to match argument parsing
+       interface changes.
+       * util/pupa-emu.c: Include <pupa/env.h>.
+       (options): Added 0's for unused fields to silence a gcc warning.
+       (argp): Likewise.
+       (main): Use the environment variable `prefix' instead of using
+       pupa_dl_set_prefix to set the prefix.  Initialize the commands ls,
+       boot, cmp, cat and terminal.  Finish the commands boot, cmp, cat
+       and terminal.
+
+       * util/i386/pc/getroot.c: Include <pupa/i386/pc/util/biosdisk.h>.
+       * util/misc.c: Include <malloc.h>.
+       (pupa_malloc): Rewritten so errors are correctly reported.
+       (pupa_realloc): Likewise.
+       (pupa_memalign): Likewise.
+       (pupa_mm_init_region): Declare unused variables with
+       `__attribute__ ((unused))' to silence a gcc warning.
+       * normal/i386/setjmp.S: Remove tab at the end of the file to
+       silence a gcc warning.
+       * loader/i386/pc/linux.c (pupa_rescue_cmd_initrd): Declare unused
+       variables with `__attribute__ ((unused))' to silence a gcc
+       warning.
+       * loader/i386/pc/multiboot.c (pupa_multiboot_unload): Make the
+       local variable i unsigned to silence a gcc warning.
+
+       * kern/term.c: Include <pupa/misc.h>.
+       (pupa_more_lines): New variable.
+       (pupa_more): Likewise.
+       (pupa_putcode): When the pager is active pause at the end of every
+       screen.
+       (pupa_set_more): New function.
+       * include/pupa/term.h (pupa_set_more): New prototype.
+
+
+2004-03-07  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Now this project is GRUB 2 rather than PUPA. The location of
+       the CVS repository was moved to GRUB's.
+
+       * configure.ac: Use bug-grub as the reporting address.
+       Use GRUB instead of PUPA.
+       Change the version number to 1.90.
+
+2004-02-24  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * genkernsyms.sh: Updated copyright information.
+       * genmk.rb: Likewise.
+       * genmodsrc.sh: Likewise.
+       * gensymlist.sh: Likewise.
+       * boot/i386/pc/boot.S: Likewise.
+       * boot/i386/pc/diskboot.S: Likewise.
+       * disk/i386/pc/biosdisk.c: Likewise.
+       * disk/i386/pc/partition.c: Likewise.
+       * font/manager.c: Likewise.
+       * fs/ext2.c: Likewise.
+       * fs/fat.c: Likewise.
+       * include/pupa/boot.h: Likewise.
+       * include/pupa/device.h: Likewise.
+       * include/pupa/disk.h: Likewise.
+       * include/pupa/dl.h: Likewise.
+       * include/pupa/elf.h: Likewise.
+       * include/pupa/err.h: Likewise.
+       * include/pupa/file.h: Likewise.
+       * include/pupa/font.h: Likewise.
+       * include/pupa/fs.h: Likewise.
+       * include/pupa/kernel.h: Likewise.
+       * include/pupa/loader.h: Likewise.
+       * include/pupa/misc.h: Likewise.
+       * include/pupa/mm.h: Likewise.
+       * include/pupa/net.h: Likewise.
+       * include/pupa/normal.h: Likewise.
+       * include/pupa/rescue.h: Likewise.
+       * include/pupa/setjmp.h: Likewise.
+       * include/pupa/symbol.h: Likewise.
+       * include/pupa/term.h: Likewise.
+       * include/pupa/types.h: Likewise.
+       * include/pupa/i386/setjmp.h: Likewise.
+       * include/pupa/i386/types.h: Likewise.
+       * include/pupa/i386/pc/biosdisk.h: Likewise.
+       * include/pupa/i386/pc/boot.h: Likewise.
+       * include/pupa/i386/pc/console.h: Likewise.
+       * include/pupa/i386/pc/init.h: Likewise.
+       * include/pupa/i386/pc/kernel.h: Likewise.
+       * include/pupa/i386/pc/linux.h: Likewise.
+       * include/pupa/i386/pc/loader.h: Likewise.
+       * include/pupa/i386/pc/memory.h: Likewise.
+       * include/pupa/i386/pc/multiboot.h: Likewise.
+       * include/pupa/i386/pc/partition.h: Likewise.
+       * include/pupa/i386/pc/time.h: Likewise.
+       * include/pupa/i386/pc/vga.h: Likewise.
+       * include/pupa/i386/pc/util/biosdisk.h: Likewise.
+       * include/pupa/util/getroot.h: Likewise.
+       * include/pupa/util/misc.h: Likewise.
+       * include/pupa/util/resolve.h: Likewise.
+       * kern/device.c: Likewise.
+       * kern/disk.c: Likewise.
+       * kern/dl.c: Likewise.
+       * kern/err.c: Likewise.
+       * kern/file.c: Likewise.
+       * kern/fs.c: Likewise.
+       * kern/loader.c: Likewise.
+       * kern/main.c: Likewise.
+       * kern/misc.c: Likewise.
+       * kern/mm.c: Likewise.
+       * kern/rescue.c: Likewise.
+       * kern/term.c: Likewise.
+       * kern/i386/dl.c: Likewise.
+       * kern/i386/pc/init.c: Likewise.
+       * kern/i386/pc/lzo1x.S: Likewise.
+       * kern/i386/pc/startup.S: Likewise.
+       * loader/i386/pc/chainloader.c: Likewise.
+       * loader/i386/pc/linux.c: Likewise.
+       * loader/i386/pc/multiboot.c: Likewise.
+       * normal/cmdline.c: Likewise.
+       * normal/command.c: Likewise.
+       * normal/main.c: Likewise.
+       * normal/menu.c: Likewise.
+       * normal/i386/setjmp.S: Likewise.
+       * term/i386/pc/console.c: Likewise.
+       * term/i386/pc/vga.c: Likewise.
+       * util/console.c: Likewise.
+       * util/genmoddep.c: Likewise.
+       * util/misc.c: Likewise.
+       * util/pupa-emu.c: Likewise.
+       * util/resolve.c: Likewise.
+       * util/unifont2pff.rb: Likewise.
+       * util/i386/pc/biosdisk.c: Likewise.
+       * util/i386/pc/getroot.c: Likewise.
+       * util/i386/pc/pupa-mkimage.c: Likewise.
+       * util/i386/pc/pupa-setup.c: Likewise.
+
+2004-02-15  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * fs/ext2.c (pupa_ext2_read_file): Correct the value of BLOCKEND
+       when it is EXT2_BLOCK_SIZE (data).  New argument READ_HOOK, all
+       callers changed.  Set DATA->DISK->READ_HOOK to READ_HOOK before
+       reading and reset it after reading.
+       (pupa_ext2_close): Return PUPA_ERR_NONE.
+
+       * include/pupa/i386/pc/linux.h (PUPA_LINUX_INITRD_MAX_ADDRESS):
+       Correct value.
+       (struct linux_kernel_header): Add kernel_version and
+       initrd_addr_max.
+       * loader/i386/pc/linux.c (pupa_rescue_cmd_linux): Check whether
+       pupa_file_read succeeds.
+       (pupa_rescue_cmd_initrd): Implement.
+
+2003-12-03  Marco Gerards  <metgerards@student.han.nl>
+
+       * fs/ext2.c (pupa_ext2_label): New function.
+       (pupa_ext2_fs): Added label.
+       * fs/fat.c (pupa_fat_label): New function.
+       (pupa_fat_fs): Added label.
+       * include/pupa/fs.h (struct pupa_fs): Added prototype label.
+
+       * kern/misc.c (pupa_strndup): New function.
+       * include/pupa/misc.h (pupa_strndup): New prototype.
+
+       * include/pupa/normal.h: Include <pupa/err.h>.
+       (pupa_set_history): New prototype.
+       (pupa_iterate_commands): New prototype.
+       * normal/cmdline.c: Include <pupa/machine/partition.h>,
+       <pupa/disk.h>, <pupa/file.h>.
+       (hist_size): New variable.
+       (hist_lines): Likewise.
+       (hist_end): Likewise.
+       (hist_used): Likewise.
+       (pupa_set_history): New function.
+       (pupa_history_get): Likewise.
+       (pupa_history_add): Likewise.
+       (pupa_history_replace): Likewise.
+       (pupa_tab_complete): Likewise.
+       (pupa_cmdline_run): Added tab completion and history buffer.  Tab
+       completion shows partitionnames while completing partitions, this
+       feature was suggested by Jeff Bailey.
+       * normal/command.c (pupa_iterate_commands): New function.
+       * normal/main.c (PUPA_DEFAULT_HISTORY_SIZE): New macro.
+       (pupa_normal_init): Initialize history buffer.
+       (PUPA_MOD_INIT): Likewise.
+       (pupa_normal_fini): Free the history buffer.
+       (PUPA_MOD_FINI): Likewise.
+
+       * util/console.c (pupa_ncurses_getkey): Accept 127 as backspace
+       key.
+
+       * aclocal.m4 (pupa_I386_CHECK_REGPARM_BUG): New DEFUN.
+       * configure.ac [i386]: Check for regparam bug.
+       (NESTED_FUNC_ATTR) [! i386]: Defined.
+
+2003-11-17  Marco Gerards  <metgerards@student.han.nl>
+
+       * conf/i386-pc.rmk (sbin_UTILITIES): Added pupa-emu.
+       (pupa_setup_SOURCES): Added util/i386/pc/getroot.c.
+       (pupa_emu_SOURCES): New variable.
+       (pupa_emu_LDFLAGS): Likewise.
+       * include/pupa/fs.h (pupa_ext2_init) [PUPA_UTIL]: New prototype.
+       (pupa_ext2_fini) [PUPA_UTIL]: Likewise.
+       * include/pupa/normal.h (pupa_normal_init) [PUPA_UTIL]: Likewise.
+       (pupa_normal_fini) [PUPA_UTIL]: Likewise.
+       * include/pupa/setjmp.h [PUPA_UTIL]: Include <setjmp.h>.
+       (pupa_jmp_buf): New typedef.
+       (pupa_setjmp) [PUPA_UTIL]: New macro.
+       (pupa_longjmp) [PUPA_UTIL]: Likewise.
+       * include/pupa/term.h (struct pupa_term): New member `refresh'.
+       (pupa_refresh): New prototype.
+       * include/pupa/util/getroot.h: New file.
+       * kern/misc.c (pupa_vsprintf): Refresh the screen after updating
+       it.
+       * kern/rescue.c (pupa_rescue_get_command_line): Likewise.
+       (pupa_rescue_cmd_cat): Likewise.
+       (pupa_rescue_cmd_ls): Likewise.
+       (pupa_rescue_cmd_testload): Likewise.
+       (pupa_rescue_cmd_lsmod): Likewise.
+       * normal/cmdline.c (pupa_cmdline_get): Likewise.
+       * normal/menu.c (run_menu): Likewise.
+       * kern/term.c (pupa_cls): Likewise.
+       (pupa_refresh): New function.
+       * normal/normal.c (pupa_normal_init) [PUPA_UTIL]: New function.
+       (pupa_normal_fini) [PUPA_UTIL]: Likewise.
+       * util/console.c: New file.
+
+       * util/i386/pc/getroot.c: New file.
+       * util/i386/pc/pupa-setup.c: Include <pupa/util/getroot.h>.
+       (pupa_putchar): New function.
+       (pupa_refresh): Likewise.
+       (xgetcwd): Function moved to ...
+       (strip_extra_slashes): Likewise.
+       (get_prefix): Likewise.
+       * util/i386/pc/getroot.c: ... here.
+       (find_root_device): Function moved and renamed to...
+       * util/i386/pc/getroot.c (pupa_find_root_device): ... here.
+       Changed all callers.
+       * util/i386/pc/pupa-setup.c (guess_root_device): Function moved
+       and renamed to...
+       * util/i386/pc/getroot.c (pupa_guess_root_device): ... here.
+       Changed all callers.
+       * util/misc.c (pupa_memalign): New function.
+       (pupa_mm_init_region): Likewise.
+       (pupa_register_exported_symbols): Likewise.
+       (pupa_putchar): Function removed.
+       * util/pupa-emu.c: New file.
+
+2003-11-16  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * conf/i386-pc.rmk (pkgdata_MODULES): Add _multiboot.mod.
+       (_multiboot_mod_SOURCES): New variable.
+       (_multiboot_mod_CFLAGS): Likewise.
+       * loader/i386/pc/multiboot.c: New file.
+       * include/pupa/i386/pc/multiboot.h: Likewise.
+       * kern/i386/pc/startup.S: Include pupa/machine/multiboot.h.
+       (pupa_multiboot_real_boot): New function.
+       * include/pupa/i386/pc/loader.h: Include pupa/machine/multiboot.h.
+       (pupa_multiboot_real_boot): New prototype.
+       (pupa_rescue_cmd_multiboot): Likewise
+       (pupa_rescue_cmd_module): Likewise.
+
+       * kern/loader.c (pupa_loader_set): Continue when
+       pupa_loader_unload_func() fails.
+       (pupa_loader_unset): New function.
+       * include/pupa/loader.h (pupa_loader_unset): New prototype.
+
+       * kern/misc.c (pupa_stpcpy): New function.
+       * include/pupa/misc.h (pupa_stpcpy): New prototype.
+
+2003-11-12  Marco Gerards  <metgerards@student.han.nl>
+
+       * disk/i386/pc/biosdisk.c (pupa_biosdisk_open): Correctly check
+       for available extensions.
+
+       * include/pupa/i386/pc/time.h: New file.
+       * kern/disk.c: Include <pupa/machine/time.h>.
+       (PUPA_CACHE_TIMEOUT): New macro.
+       (pupa_last_time): New variable.
+       (pupa_disk_open): Flush the cache when there was a timeout.
+       (pupa_disk_close): Reset the timer.
+       * kern/i386/pc/startup.S (pupa_get_rtc): Renamed from
+       pupa_currticks.
+       * util/misc.c: Include <sys/times.h>
+       (pupa_get_rtc): New function.
+
+2003-11-09  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+       * fs/ext2.c (struct pupa_ext2_inode): Declare struct datablocks
+       as blocks.
+       (pupa_ext2_get_file_block): Use blocks member.
+
+       * fs/ext2.c (pupa_ext2_read_file): Only set skipfirst for the
+       first block. Return -1 instead of pupa_errno on error.
+
+2003-10-27  Marco Gerards  <metgerards@student.han.nl>
+
+       * README: In the pupa-mkimage example use _chain instead of chain
+       and ext2 instead of fat.
+       * TODO: Replace ext2fs with jfs as an example.  Add an item for
+       adding journal playback for ext2fs.
+       * conf/i386-pc.rmk (pupa_setup_SOURCES): Added fs/ext2.c.
+       (pkgdata_MODULES): Added ext2.mod.
+       (ext2_mod_SOURCES): New variable.
+       (ext2_mod_CFLAGS): Likewise.
+       * include/pupa/err.h (pupa_err_t): Added PUPA_ERR_SYMLINK_LOOP.
+       * include/pupa/misc.h (pupa_strncpy): New prototype.
+       (pupa_strcat): Likewise.
+       (pupa_strncmp): Likewise.
+       * kern/misc.c (pupa_strcat): Enable function.
+       (pupa_strncpy): New function.
+       (pupa_strncmp): Likewise.
+       * fs/ext2.c: New file.
+
+       * kern/disk.c (pupa_disk_read): Set pupa_errno to PUPA_ERR_NONE
+       when the read failed before retrying.
+       * util/i386/pc/biosdisk.c (_LARGEFILE_SOURCE): Removed.
+       (_FILE_OFFSET_BITS): Likewise.
+       * configure.ac: Added AC_SYS_LARGEFILE.
+
+2003-09-25  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * genmk.rb (PModule#rule): Make sure to get only symbol names
+       from the output of nm.
+       Reported by Robert Millan <zeratul2@wanadoo.es>.
+
+2003-09-25  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       I forgot to check in these changes for a long time. This adds
+       incomplete support for VGA console, and this is still very
+       buggy. Also, a lot of consideration is required for I18N,
+       UNICODE, and VGA font issues. Therefore, assume that this is
+       such that "better than nothing".
+
+       * font/manager.c: New file.
+       * include/pupa/font.h: Likewise.
+       * include/pupa/i386/pc/vga.h: Likewise.
+       * term/i386/pc/vga.c: Likewise.
+       * util/unifont2pff.rb: Likewise.
+
+       * conf/i386-pc.rmk (kernel_img_HEADERS): Added machine/vga.h.
+       (pkgdata_MODULES): Added vga.mod and font.mod.
+       (vga_mod_SOURCES): New variables.
+       (vga_mod_CFLAGS): Likewise.
+       (font_mod_SOURCES): Likewise.
+       (font_mod_CFLAGS): Likewise.
+
+       * include/pupa/err.h (PUPA_ERR_BAD_FONT): New constant.
+
+       * include/pupa/term.h: Include pupa/err.h.
+       (struct pupa_term): Added init and fini.
+       Changed the argument of putchar to pupa_uint32_t.
+
+       * include/pupa/i386/pc/console.h: Include pupa/symbol.h.
+       (pupa_console_real_putchar): New prototype.
+       (pupa_console_putchar): Removed.
+       (pupa_console_checkkey): Exported.
+       (pupa_console_getkey): Likewise.
+
+       * kern/misc.c (pupa_vsprintf): Add support for UNICODE
+       characters.
+
+       * kern/term.c (pupa_term_set_current): Rewritten.
+       (pupa_putchar): Likewise.
+       (pupa_putcode): New function.
+
+       * kern/i386/pc/startup.S (pupa_console_putchar): Renamed to ...
+       (pupa_console_real_putchar): ... this.
+       (pupa_vga_set_mode): New function.
+       (pupa_vga_get_font): Likewise.
+
+       * normal/command.c: Include pupa/term.h.
+       (terminal_command): New function.
+       (pupa_command_init): Register the command "terminal".
+
+       * normal/menu.c (DISP_LEFT): Changed to a UNICODE value.
+       (DISP_UP): Likewise.
+       (DISP_RIGHT): Likewise.
+       (DISP_DOWN): Likewise.
+       (DISP_HLINE): Likewise.
+       (DISP_VLINE): Likewise.
+       (DISP_UL): Likewise.
+       (DISP_UR): Likewise.
+       (DISP_LL): Likewise.
+       (DISP_LR): Likewise.
+
+       * term/i386/pc/console.c (pupa_console_putchar): New function.
+
+2003-02-08  NIIBE Yutaka  <gniibe@m17n.org>
+
+       * util/resolve.c (pupa_util_resolve_dependencies): BUG
+       FIX. Reverse the path_list.
+
+       * include/pupa/normal.h: Export pupa_register_command and
+       pupa_unregister_command.
+
+       * hello/hello.c (pupa_cmd_hello): New module.
+       * conf/i386-pc.rmk: Added hello.mod.
+
+2003-01-31  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/i386/pc/lzo1x.S: New file.
+
+       * util/i386/pc/pupa-mkimage.c: Include lzo1x.h.
+       (compress_kernel): New variable.
+       (generate_image): Heavily modified to support compressing a
+       large part of the core image.
+
+       * util/misc.c (pupa_util_read_image): Fix a file descriptor
+       leak.
+       (pupa_util_load_image): New function.
+
+       * kern/i386/pc/startup.S: Include pupa/machine/kernel.h.
+       (pupa_compressed_size): New variable.
+       (codestart): Enable Gate A20 here.
+       Decompress the compressed part of the core image.
+       Rearrange the code to put functions and variables which are
+       required for initialization in the non-compressed part.
+       Include lzo1x.S.
+
+       * kern/i386/pc/init.c (pupa_machine_init): Don't enable Gate A20
+       here.
+
+       * include/pupa/util/misc.h (pupa_util_write_image): Declared.
+
+       * include/pupa/i386/pc/kernel.h
+       (PUPA_KERNEL_MACHINE_COMPRESSED_SIZE): New macro.
+       (PUPA_KERNEL_MACHINE_INSTALL_DOS_PART): Increased by 4.
+       (PUPA_KERNEL_MACHINE_INSTALL_BSD_PART): Likewise.
+       (PUPA_KERNEL_MACHINE_PREFIX): Likewise.
+       (PUPA_KERNEL_MACHINE_RAW_SIZE): New macro.
+
+       * conf/i386-pc.rmk (pupa_mkimage_LDFLAGS): New variable.
+
+       * genmk.rb (Image#rule): Put LDFLAGS at the end of a line.
+       (Utility#rule): Likewise.
+
+       * configure.ac: Check if LZO is available.
+
+2003-01-20  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * include/pupa/normal.h: New file.
+       * include/pupa/setjmp.h: Likewise.
+       * include/pupa/i386/setjmp.h: Likewise.
+       * normal/cmdline.c: Likewise.
+       * normal/command.c: Likewise.
+       * normal/main.c: Likewise.
+       * normal/menu.c: Likewise.
+       * normal/i386/setjmp.S: Likewise.
+
+       * loader/i386/pc/linux.c (pupa_rescue_cmd_linux): Made global.
+       (pupa_rescue_cmd_initrd): Likewise.
+
+       * loader/i386/pc/chainloader.c (pupa_rescue_cmd_chainloader):
+       Likewise.
+
+       * kern/i386/pc/startup.S (translation_table): New variable.
+       (translate_keycode): New function.
+       (pupa_console_getkey): Call translate_keycode.
+
+       * kern/rescue.c (attempt_normal_mode): New function.
+       (pupa_enter_rescue_mode): Attempt to execute the normal mode. If
+       it failed, print a message.
+
+       * kern/mm.c (pupa_real_malloc): Print more information when a
+       free magic is broken.
+       (pupa_free): If the first free header is not free actually, set
+       it to P.
+
+       * kern/main.c (pupa_load_normal_mode): Just load the module
+       "normal".
+       (pupa_main): Don't print the message
+       "Entering into rescue mode..." here.
+
+       * include/pupa/i386/pc/loader.h (pupa_rescue_cmd_initrd):
+       Declared.
+       (pupa_rescue_cmd_initrd): Likewise.
+       (pupa_rescue_cmd_initrd): Likewise.
+
+       * include/pupa/symbol.h (FUNCTION): Specify the type.
+       (VARIABLE): Likewise.
+
+       * include/pupa/err.h (pupa_err_t): Added
+       PUPA_ERR_UNKNOWN_COMMAND.
+
+       * include/pupa/dl.h (pupa_dl_set_prefix): Exported.
+       (pupa_dl_get_prefix): Likewise.
+
+       * conf/i386-pc.rmk (pkgdata_MODULES): Added normal.mod.
+       Added _chain.mod and _linux.mod instead of chain.mod and
+       linux.mod.
+       (chain_mod_SOURCES): Renamed to ...
+       (_chain_mod_SOURCES): ... this.
+       (chain_mod_CFLAGS): Renamed to ...
+       (_chain_mod_CFLAGS): ... this.
+       (linux_mod_SOURCES): Renamed to ...
+       (_linux_mod_SOURCES): ... this.
+       (linux_mod_CFLAGS): Renamed to ...
+       (_linux_mod_CFLAGS): ... this.
+       (normal_mod_SOURCES): New variable.
+       (normal_mod_CFLAGS): Likewise.
+       (normal_mod_ASFLAGS): Likewise.
+
+2003-01-18  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/rescue.c (pupa_rescue_cmd_rmmod): Call pupa_dl_unload, if
+       possible.
+
+       * kern/dl.c (pupa_dl_ref): Refer depending modules
+       recursively.
+       (pupa_dl_unref): Unrefer depending modules recursively.
+       Don't call pupa_dl_unload implicitly, because PUPA can crash if
+       a module is unloaded before one depending on that module is
+       unloaded.
+       (pupa_dl_unload): Unload depending modules explicitly,
+       if possible.
+
+2003-01-17  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * include/pupa/i386/pc/linux.h: New file.
+       * loader/i386/pc/linux.c: Likewise.
+
+       * loader/i386/pc/chainloader.c (pupa_chainloader_boot_sector):
+       Removed.
+       (pupa_chainloader_unload): Return PUPA_ERR_NONE.
+       (pupa_rescue_cmd_chainloader): Read the image to 0x7C00 instead
+       of PUPA_CHAINLOADER_BOOT_SECTOR.
+
+       * kern/i386/pc/startup.S: Include pupa/machine/linux.h.
+       (pupa_linux_prot_size): New variable.
+       (pupa_linux_tmp_addr): Likewise.
+       (pupa_linux_real_addr): Likewise.
+       (pupa_linux_boot_zimage): New function.
+       (pupa_linux_boot_bzimage): Likewise.
+
+       * kern/i386/pc/init.c (struct mem_region): New structure.
+       (MAX_REGIONS): New macro.
+       (mem_regions): New variable.
+       (num_regions): Likewise.
+       (pupa_os_area_addr): Likewise.
+       (pupa_os_area_size): Likewise.
+       (pupa_lower_mem): Likewise.
+       (pupa_upper_mem): Likewise.
+       (add_mem_region): New function.
+       (compact_mem_regions): Likewise.
+       (pupa_machine_init): Set PUPA_LOWER_MEM and PUPA_UPPER_MEM to
+       the size of the conventional memory and that of so-called upper
+       memory (before the first memory hole).
+       Instead of adding each found region to free memory, use
+       add_mem_region and add them after removing overlaps.
+       Also, add only 1/4 of the upper memory to free memory. The rest
+       is used for loading OS images. Maybe this is ad hoc, but this
+       makes it much easier to relocate OS images when booting.
+
+       * kern/rescue.c (pupa_rescue_cmd_module): Removed.
+       (pupa_enter_rescue_mode): Don't register initrd and module.
+
+       * kern/mm.c: Include pupa/dl.h.
+
+       * kern/main.c: Include pupa/file.h and pupa/device.h.
+
+       * kern/loader.c (pupa_loader_load_module_func): Removed.
+       (pupa_loader_load_module): Likewise.
+
+       * kern/dl.c (pupa_dl_load): Use the suffix ``.mod'' instead of
+       ``.o''.
+
+       * include/pupa/i386/pc/loader.h (pupa_linux_prot_size): Declared.
+       (pupa_linux_tmp_addr): Likewise.
+       (pupa_linux_real_addr): Likewise.
+       (pupa_linux_boot_zimage): Likewise.
+       (pupa_linux_boot_bzimage): Likewise.
+
+       * include/pupa/i386/pc/init.h (pupa_lower_mem): Declared.
+       (pupa_upper_mem): Likewise.
+       (pupa_gate_a20): Don't export, because turning off Gate A20 in a
+       module is too dangerous.
+
+       * include/pupa/loader.h (pupa_os_area_addr): Declared.
+       (pupa_os_area_size): Likewise.
+       (pupa_loader_set): Remove the first argument. Loader doesn't
+       manage modules or initrd any longer.
+       (pupa_loader_load_module): Removed.
+
+       * conf/i386-pc.rmk (pkgdata_MODULES): Added linux.mod.
+       (linux_mod_SOURCES): New variable.
+       (linux_mod_CFLAGS): Likewise.
+
+2003-01-07  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * util/i386/pc/pupa-setup.c (setup): Convert the endianness of
+       the length of a blocklist correctly.
+
+       * util/i386/pc/biosdisk.c (pupa_util_biosdisk_open) [__linux__]:
+       Use ioctl only if the OS file is a block device.
+       (pupa_util_biosdisk_open): Don't use ST.ST_BLOCKS, because it is
+       not very useful for normal files.
+
+       * kern/main.c (pupa_set_root_dev): New function.
+       (pupa_load_normal_mode): Likewise.
+       (pupa_main): Call those above.
+
+       * include/pupa/types.h (pupa_swap_bytes16): Cast the result to
+       pupa_uint16_t.
+
+       * include/pupa/kernel.h (pupa_enter_normal_mode): Removed.
+
+2003-01-06  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * util/i386/pc/pupa-setup.c: Include pupa/machine/kernel.h.
+       (setup): Configure the installed partition information and the
+       dl prefix.
+
+       * loader/i386/pc/chainloader.c (my_mod): New variable.
+       (pupa_chainloader_unload): New function.
+       (pupa_rescue_cmd_chainloader): Refer itself.
+       (PUPA_MOD_INIT): Save its own module in MY_MOD.
+
+       * kern/i386/pc/startup.S (install_partition): Removed.
+       (version_string): Likewise.
+       (config_file): Likewise.
+       (pupa_install_dos_part): New variable.
+       (pupa_install_bsd_part): Likewise.
+       (pupa_prefix): Likewise.
+       (pupa_chainloader_real_boot): Call pupa_dl_unload_all.
+
+       * kern/i386/pc/init.c: Include pupa/machine/kernel.h, pupa/dl.h
+       and pupa/misc.h.
+       (make_install_device): New function.
+       (pupa_machine_init): Set the dl prefix.
+
+       * kern/rescue.c: Include pupa/rescue.h and pupa/dl.h.
+       (buf): Renamed to ...
+       (linebuf): ... this.
+       (pupa_rescue_cmd_prefix): New function.
+       (pupa_rescue_cmd_insmod): Likewise.
+       (pupa_rescue_cmd_rmmod): Likewise.
+       (pupa_rescue_cmd_lsmod): Likewise.
+       (pupa_enter_rescue_mode): Register new commands: prefix, insmod,
+       rmmod and lsmod.
+
+       * kern/mm.c (pupa_memalign): If failed even after invalidating
+       disk caches, unload unneeded modules and retry.
+
+       * kern/misc.c (pupa_memmove): New function.
+       (pupa_memcpy): Removed.
+       (pupa_strcpy): New function.
+       (pupa_itoa): Made static.
+
+       * kern/dl.c (pupa_dl_iterate): New function.
+       (pupa_dl_ref): Likewise.
+       (pupa_dl_unref): Likewise.
+       (pupa_dl_unload): Return if succeeded or not.
+       (pupa_dl_unload_unneeded): New function.
+       (pupa_dl_unload_all): Likewise.
+       (pupa_dl_init): Renamed to ...
+       (pupa_dl_set_prefix): ... this.
+       (pupa_dl_get_prefix): New function.
+
+       * include/pupa/i386/pc/kernel.h: Include pupa/types.h.
+       (PUPA_KERNEL_MACHINE_INSTALL_DOS_PART): New macro.
+       (PUPA_KERNEL_MACHINE_INSTALL_BSD_PART): Likewise.
+       (PUPA_KERNEL_MACHINE_PREFIX): Likewise.
+       (pupa_install_dos_part): Declared.
+       (pupa_install_bsd_part): Likewise.
+       (pupa_prefix): Likewise.
+       (pupa_boot_drive): Likewise.
+
+       * include/pupa/types.h: Fix a typo.
+
+       * include/pupa/misc.h (pupa_memcpy): New macro. Just an alias to
+       pupa_memmove.
+       (pupa_memmove): Declared.
+       (pupa_strcpy): Likewise.
+
+       * include/pupa/dl.h (PUPA_MOD_INIT): Change the prototype. Now
+       pupa_mod_init takes one argument, its own module.
+       (pupa_dl_unload_unneeded): Declared.
+       (pupa_dl_unload_all): Likewise.
+       (pupa_dl_ref): Likewise.
+       (pupa_dl_unref): Likewise.
+       (pupa_dl_iterate): Likewise.
+       (pupa_dl_init): Renamed to ...
+       (pupa_dl_set_prefix): ... this.
+       (pupa_dl_get_prefix): Declared.
+
+       * fs/fat.c [!PUPA_UTIL] (my_mod): New variable.
+       (pupa_fat_dir) [!PUPA_UTIL]: Prevent the fat module from being
+       unloaded.
+       (pupa_fat_open) [!PUPA_UTIL]: Refer itself if succeeded.
+       (pupa_fat_close) [!PUPA_UTIL]: Unrefer itself.
+
+       * configure.ac (tmp_CFLAGS): Added -Wshadow, -Wpointer-arith,
+       -Wmissing-prototypes, -Wundef and -Wstrict-prototypes.
+
+2003-01-03  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * util/i386/pc/pupa-setup.c (setup): Define the internal
+       function find_first_partition_start at the top level, because GCC
+       3.0.x cannot compile internal functions in deeper scopes
+       correctly.
+       (find_root_device): Use lstat instead of stat.
+       Don't follow symbolic links.
+       Fix the path-constructing code.
+
+       * util/i386/pc/biosdisk.c [__linux__] (BLKFLSBUF): New macro.
+       (pupa_util_biosdisk_open) [__linux__]: Get the size of a device
+       by a BLKGETSIZE ioctl first, because block devices don't fill
+       the member st_mode of the structure stat on Linux.
+       [__linux__] (linux_find_partition): Use a temporary buffer
+       REAL_DEV for the working space. Copy it to DEV before returning.
+       (open_device) [__linux__]: Call ioctl with BLKFLSBUF to make the
+       buffer cache consistent.
+       (get_os_disk) [__linux__]: Use the length 5 instead of 4 for
+       strncmp. The previous value was merely wrong.
+       (pupa_util_biosdisk_get_pupa_dev): Use stat instead of lstat.
+
+       * fs/fat.c (pupa_fat_read_data): Shift 4 instead of 12 when the
+       FAT size is 12. The previous value was merely wrong.
+
+       * kern/main.c (pupa_main): Don't split the starting message from
+       newlines.
+
+       * kern/term.c (pupa_putchar): Put CR after LF instead of before
+       LF, because BIOS goes crazy about character attributes in this
+       case.
+
+2003-01-03  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * include/i386/pc/util/biosdisk.h: New file.
+       * util/i386/pc/biosdisk.c: Likewise.
+       * util/i386/pc/pupa-setup.c: Likewise.
+
+       * Makefile.in (INCLUDE_DISTFILES): Added
+       include/pupa/i386/pc/util/biosdisk.h.
+       (UTIL_DISTFILES): Added biosdisk.c and pupa-setup.c under the
+       directory util/i386/pc.
+       (install-local): Added a rule for sbin_UTILITIES.
+       (uninstall): Likewise.
+
+       * util/i386/pc/pupa-mkimage.c (usage): Fix a typo in the doc.
+
+       * util/misc.c (xrealloc): New function.
+       (pupa_malloc): Likewise.
+       (pupa_free): Likewise.
+       (pupa_realloc): Likewise.
+       (pupa_stop): Likewise.
+       (pupa_putchar): Likewise.
+
+       * kern/disk.c (pupa_disk_read): Prevent L from underflowing.
+
+       * include/pupa/util/misc.h (xrealloc): Declared.
+
+       * include/pupa/i386/pc/boot.h (PUPA_BOOT_MACHINE_BPB_START): New
+       macro.
+       (PUPA_BOOT_MACHINE_BPBEND): Renamed to ...
+       (PUPA_BOOT_MACHINE_BPB_END): ... this.
+
+       * include/pupa/fs.h [PUPA_UTIL] (pupa_fat_init): Declared.
+       [PUPA_UTIL] (pupa_fat_fini): Likewise.
+
+       * fs/fat.c [PUPA_UTIL] (pupa_fat_init): Defined. Maybe a better
+       way should be implemented.
+       [PUPA_UTIL] (pupa_fat_fini): Likewise.
+
+       * disk/i386/pc/biosdisk.c (pupa_biosdisk_call_hook): Increase
+       the size of NAME for safety.
+       (pupa_biosdisk_iterate): Search hard disks to 0x90 instead of
+       0x88.
+
+       * conf/i386-pc.rmk (sbin_UTILITIES): New variable.
+       (pupa_setup_SOURCES): Likewise.
+
+       * genmk.rb (Utility#rule): Add $(BUILD_CFLAGS) into the rules.
+
+2002-12-28  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * kern/i386/pc/startup.S (push_get_mmap_entry): Revert to a
+       bunch of pushl's from pusha, because this destroys the return
+       value.
+
+2002-12-28  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       Use -mrtd and -mregparm=3 to reduce the generated code sizes.
+       This means that any missing prototypes could be fatal. Also, you
+       must take care when writing assembly code. See the comments at
+       the beginning of startup.S, for more details.
+
+       * kern/i386/pc/startup.S (pupa_halt): Modified for the new
+       compilation mechanism.
+       (pupa_chainloader_real_boot): Likewise.
+       (pupa_biosdisk_rw_int13_extensions): Likewise.
+       (pupa_biosdisk_rw_standard): Likewise.
+       (pupa_biosdisk_check_int13_extensions): Likewise.
+       (pupa_biosdisk_get_diskinfo_int13_extensions): Likewise.
+       (pupa_biosdisk_get_diskinfo_standard): Likewise.
+       (pupa_get_memsize): Likewise.
+       (pupa_get_mmap_entry): Likewise.
+       (pupa_console_putchar): Likewise.
+       (pupa_console_setcursor): Likewise.
+       (pupa_getrtsecs): Use pushl instead of push.
+
+       * kern/i386/pc/init.c (pupa_machine_init): Use the scratch
+       memory instead of the stack for a mmap entry, because some
+       BIOSes may ignore the maximum size and overflow.
+
+       * conf/i386-pc.rmk (COMMON_CFLAGS): Added -mrtd and -mregparm=3.
+
+       * genmk.rb (PModule#rule): Compile automatically generated
+       sources with module-specific CFLAGS as well as other sources.
+
+2002-12-27  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * configure.ac: Check ld.
+       Replace CFLAGS and CPPFLAGS with BUILD_CFLAGS and BUILD_CPPFLAGS
+       respectively, before checking endianness and sizes.
+
+       * Makefile.in (LD): New variable.
+
+2002-12-27  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * Makefile.in (BUILD_CC): CC -> BUILD_CC.
+
+2002-12-27  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * Changelog: New file.
+
diff --git a/DISTLIST b/DISTLIST
new file mode 100644 (file)
index 0000000..a92f733
--- /dev/null
+++ b/DISTLIST
@@ -0,0 +1,484 @@
+AUTHORS
+COPYING
+ChangeLog
+DISTLIST
+INSTALL
+NEWS
+README
+THANKS
+TODO
+Makefile.in
+aclocal.m4
+autogen.sh
+config.guess
+config.h.in
+config.sub
+configure
+configure.ac
+gencmdlist.sh
+gendistlist.sh
+genfslist.sh
+geninit.sh
+geninitheader.sh
+genkernsyms.sh.in
+genmk.rb
+genmoddep.awk
+genmodsrc.sh
+genpartmaplist.sh
+gensymlist.sh.in
+install-sh
+mkinstalldirs
+stamp-h.in
+boot/i386/pc/boot.S
+boot/i386/pc/cdboot.S
+boot/i386/pc/diskboot.S
+boot/i386/pc/lnxboot.S
+boot/i386/pc/pxeboot.S
+bus/pci.c
+bus/usb/ohci.c
+bus/usb/uhci.c
+bus/usb/usb.c
+bus/usb/usbhub.c
+bus/usb/usbtrans.c
+commands/blocklist.c
+commands/boot.c
+commands/cat.c
+commands/cmp.c
+commands/configfile.c
+commands/crc.c
+commands/date.c
+commands/echo.c
+commands/halt.c
+commands/hdparm.c
+commands/help.c
+commands/hexdump.c
+commands/loadenv.c
+commands/ls.c
+commands/lsmmap.c
+commands/lspci.c
+commands/read.c
+commands/reboot.c
+commands/search.c
+commands/sleep.c
+commands/terminal.c
+commands/test.c
+commands/usbtest.c
+commands/videotest.c
+commands/i386/cpuid.c
+commands/i386/pc/halt.c
+commands/i386/pc/play.c
+commands/i386/pc/pxecmd.c
+commands/i386/pc/vbeinfo.c
+commands/i386/pc/vbetest.c
+commands/ieee1275/suspend.c
+conf/common.mk
+conf/common.rmk
+conf/i386-coreboot.mk
+conf/i386-coreboot.rmk
+conf/i386-efi.mk
+conf/i386-efi.rmk
+conf/i386-ieee1275.mk
+conf/i386-ieee1275.rmk
+conf/i386-pc-cygwin-img-ld.sc
+conf/i386-pc.mk
+conf/i386-pc.rmk
+conf/i386.mk
+conf/i386.rmk
+conf/powerpc-ieee1275.mk
+conf/powerpc-ieee1275.rmk
+conf/sparc64-ieee1275.mk
+conf/sparc64-ieee1275.rmk
+conf/x86_64-efi.mk
+conf/x86_64-efi.rmk
+disk/ata.c
+disk/ata_pthru.c
+disk/dmraid_nvidia.c
+disk/fs_uuid.c
+disk/host.c
+disk/loopback.c
+disk/lvm.c
+disk/mdraid_linux.c
+disk/memdisk.c
+disk/raid.c
+disk/raid5_recover.c
+disk/raid6_recover.c
+disk/scsi.c
+disk/usbms.c
+disk/efi/efidisk.c
+disk/i386/pc/biosdisk.c
+disk/ieee1275/nand.c
+disk/ieee1275/ofdisk.c
+docs/fdl.texi
+docs/grub.cfg
+docs/grub.texi
+docs/texinfo.tex
+font/font.c
+font/font_cmd.c
+fs/affs.c
+fs/afs.c
+fs/cpio.c
+fs/ext2.c
+fs/fat.c
+fs/fshelp.c
+fs/hfs.c
+fs/hfsplus.c
+fs/iso9660.c
+fs/jfs.c
+fs/minix.c
+fs/ntfs.c
+fs/ntfscomp.c
+fs/reiserfs.c
+fs/sfs.c
+fs/tar.c
+fs/udf.c
+fs/ufs.c
+fs/xfs.c
+fs/i386/pc/pxe.c
+hello/hello.c
+hook/datehook.c
+include/multiboot.h
+include/multiboot2.h
+include/grub/acorn_filecore.h
+include/grub/aout.h
+include/grub/arg.h
+include/grub/ata.h
+include/grub/bitmap.h
+include/grub/boot.h
+include/grub/bufio.h
+include/grub/cache.h
+include/grub/device.h
+include/grub/disk.h
+include/grub/dl.h
+include/grub/elf.h
+include/grub/elfload.h
+include/grub/env.h
+include/grub/err.h
+include/grub/file.h
+include/grub/font.h
+include/grub/fs.h
+include/grub/fshelp.h
+include/grub/gpt_partition.h
+include/grub/gzio.h
+include/grub/hfs.h
+include/grub/kernel.h
+include/grub/loader.h
+include/grub/lvm.h
+include/grub/menu.h
+include/grub/menu_viewer.h
+include/grub/misc.h
+include/grub/mm.h
+include/grub/multiboot.h
+include/grub/multiboot2.h
+include/grub/multiboot_loader.h
+include/grub/net.h
+include/grub/normal.h
+include/grub/ntfs.h
+include/grub/parser.h
+include/grub/partition.h
+include/grub/pc_partition.h
+include/grub/pci.h
+include/grub/raid.h
+include/grub/rescue.h
+include/grub/script.h
+include/grub/scsi.h
+include/grub/scsicmd.h
+include/grub/setjmp.h
+include/grub/symbol.h
+include/grub/term.h
+include/grub/terminfo.h
+include/grub/time.h
+include/grub/tparm.h
+include/grub/types.h
+include/grub/usb.h
+include/grub/usbdesc.h
+include/grub/usbtrans.h
+include/grub/video.h
+include/grub/efi/api.h
+include/grub/efi/chainloader.h
+include/grub/efi/console.h
+include/grub/efi/console_control.h
+include/grub/efi/disk.h
+include/grub/efi/efi.h
+include/grub/efi/pe32.h
+include/grub/efi/time.h
+include/grub/efi/uga_draw.h
+include/grub/i386/at_keyboard.h
+include/grub/i386/bsd.h
+include/grub/i386/cmos.h
+include/grub/i386/halt.h
+include/grub/i386/io.h
+include/grub/i386/kernel.h
+include/grub/i386/linux.h
+include/grub/i386/loader.h
+include/grub/i386/pci.h
+include/grub/i386/pit.h
+include/grub/i386/reboot.h
+include/grub/i386/setjmp.h
+include/grub/i386/time.h
+include/grub/i386/tsc.h
+include/grub/i386/types.h
+include/grub/i386/vga_common.h
+include/grub/i386/coreboot/boot.h
+include/grub/i386/coreboot/console.h
+include/grub/i386/coreboot/init.h
+include/grub/i386/coreboot/kernel.h
+include/grub/i386/coreboot/loader.h
+include/grub/i386/coreboot/machine.h
+include/grub/i386/coreboot/memory.h
+include/grub/i386/coreboot/serial.h
+include/grub/i386/coreboot/time.h
+include/grub/i386/efi/kernel.h
+include/grub/i386/efi/loader.h
+include/grub/i386/efi/machine.h
+include/grub/i386/efi/time.h
+include/grub/i386/ieee1275/console.h
+include/grub/i386/ieee1275/ieee1275.h
+include/grub/i386/ieee1275/kernel.h
+include/grub/i386/ieee1275/loader.h
+include/grub/i386/ieee1275/machine.h
+include/grub/i386/ieee1275/memory.h
+include/grub/i386/ieee1275/serial.h
+include/grub/i386/ieee1275/time.h
+include/grub/i386/pc/biosdisk.h
+include/grub/i386/pc/boot.h
+include/grub/i386/pc/chainloader.h
+include/grub/i386/pc/console.h
+include/grub/i386/pc/init.h
+include/grub/i386/pc/kernel.h
+include/grub/i386/pc/loader.h
+include/grub/i386/pc/machine.h
+include/grub/i386/pc/memory.h
+include/grub/i386/pc/pxe.h
+include/grub/i386/pc/serial.h
+include/grub/i386/pc/time.h
+include/grub/i386/pc/vbe.h
+include/grub/i386/pc/vbeblit.h
+include/grub/i386/pc/vbefill.h
+include/grub/i386/pc/vbeutil.h
+include/grub/i386/pc/vga.h
+include/grub/ieee1275/ieee1275.h
+include/grub/ieee1275/ofdisk.h
+include/grub/lib/LzFind.h
+include/grub/lib/LzHash.h
+include/grub/lib/LzmaDec.h
+include/grub/lib/LzmaEnc.h
+include/grub/lib/LzmaTypes.h
+include/grub/lib/crc.h
+include/grub/lib/datetime.h
+include/grub/lib/envblk.h
+include/grub/lib/hexdump.h
+include/grub/powerpc/kernel.h
+include/grub/powerpc/libgcc.h
+include/grub/powerpc/setjmp.h
+include/grub/powerpc/time.h
+include/grub/powerpc/types.h
+include/grub/powerpc/ieee1275/biosdisk.h
+include/grub/powerpc/ieee1275/console.h
+include/grub/powerpc/ieee1275/ieee1275.h
+include/grub/powerpc/ieee1275/kernel.h
+include/grub/powerpc/ieee1275/loader.h
+include/grub/powerpc/ieee1275/machine.h
+include/grub/powerpc/ieee1275/memory.h
+include/grub/powerpc/ieee1275/time.h
+include/grub/powerpc/ieee1275/util/biosdisk.h
+include/grub/sparc64/libgcc.h
+include/grub/sparc64/setjmp.h
+include/grub/sparc64/time.h
+include/grub/sparc64/types.h
+include/grub/sparc64/ieee1275/console.h
+include/grub/sparc64/ieee1275/ieee1275.h
+include/grub/sparc64/ieee1275/kernel.h
+include/grub/sparc64/ieee1275/machine.h
+include/grub/sparc64/ieee1275/time.h
+include/grub/util/getroot.h
+include/grub/util/hostdisk.h
+include/grub/util/lvm.h
+include/grub/util/misc.h
+include/grub/util/raid.h
+include/grub/util/resolve.h
+include/grub/x86_64/kernel.h
+include/grub/x86_64/linux.h
+include/grub/x86_64/pci.h
+include/grub/x86_64/setjmp.h
+include/grub/x86_64/time.h
+include/grub/x86_64/types.h
+include/grub/x86_64/efi/kernel.h
+include/grub/x86_64/efi/loader.h
+include/grub/x86_64/efi/machine.h
+include/grub/x86_64/efi/time.h
+io/bufio.c
+io/gzio.c
+kern/device.c
+kern/disk.c
+kern/dl.c
+kern/elf.c
+kern/env.c
+kern/err.c
+kern/file.c
+kern/fs.c
+kern/loader.c
+kern/main.c
+kern/misc.c
+kern/mm.c
+kern/parser.c
+kern/partition.c
+kern/rescue.c
+kern/term.c
+kern/time.c
+kern/efi/efi.c
+kern/efi/init.c
+kern/efi/mm.c
+kern/generic/millisleep.c
+kern/generic/rtc_get_time_ms.c
+kern/i386/dl.c
+kern/i386/halt.c
+kern/i386/loader.S
+kern/i386/multiboot_mmap.c
+kern/i386/pit.c
+kern/i386/realmode.S
+kern/i386/reboot.c
+kern/i386/tsc.c
+kern/i386/coreboot/init.c
+kern/i386/coreboot/mmap.c
+kern/i386/coreboot/startup.S
+kern/i386/efi/init.c
+kern/i386/efi/startup.S
+kern/i386/ieee1275/init.c
+kern/i386/ieee1275/startup.S
+kern/i386/pc/init.c
+kern/i386/pc/lzma_decode.S
+kern/i386/pc/lzo1x.S
+kern/i386/pc/mmap.c
+kern/i386/pc/startup.S
+kern/ieee1275/cmain.c
+kern/ieee1275/ieee1275.c
+kern/ieee1275/init.c
+kern/ieee1275/mmap.c
+kern/ieee1275/openfw.c
+kern/powerpc/cache.S
+kern/powerpc/dl.c
+kern/powerpc/ieee1275/startup.S
+kern/sparc64/cache.S
+kern/sparc64/dl.c
+kern/sparc64/ieee1275/init.c
+kern/sparc64/ieee1275/openfw.c
+kern/x86_64/dl.c
+kern/x86_64/efi/callwrap.S
+kern/x86_64/efi/startup.S
+lib/LzFind.c
+lib/LzmaDec.c
+lib/LzmaEnc.c
+lib/crc.c
+lib/datetime.c
+lib/envblk.c
+lib/hexdump.c
+lib/efi/datetime.c
+lib/i386/datetime.c
+loader/aout.c
+loader/linux_normal.c
+loader/multiboot2.c
+loader/multiboot_loader.c
+loader/multiboot_loader_normal.c
+loader/efi/appleloader.c
+loader/efi/chainloader.c
+loader/efi/chainloader_normal.c
+loader/i386/bsd.c
+loader/i386/bsd_normal.c
+loader/i386/linux.c
+loader/i386/efi/linux.c
+loader/i386/ieee1275/linux.c
+loader/i386/pc/chainloader.c
+loader/i386/pc/chainloader_normal.c
+loader/i386/pc/linux.c
+loader/i386/pc/multiboot.c
+loader/i386/pc/multiboot2.c
+loader/i386/pc/multiboot_normal.c
+loader/ieee1275/multiboot2.c
+loader/powerpc/ieee1275/linux.c
+loader/powerpc/ieee1275/linux_normal.c
+normal/arg.c
+normal/cmdline.c
+normal/color.c
+normal/command.c
+normal/completion.c
+normal/execute.c
+normal/function.c
+normal/lexer.c
+normal/main.c
+normal/menu.c
+normal/menu_entry.c
+normal/menu_text.c
+normal/menu_viewer.c
+normal/misc.c
+normal/parser.y
+normal/script.c
+normal/i386/setjmp.S
+normal/powerpc/setjmp.S
+normal/sparc64/setjmp.S
+normal/x86_64/setjmp.S
+partmap/acorn.c
+partmap/amiga.c
+partmap/apple.c
+partmap/gpt.c
+partmap/pc.c
+partmap/sun.c
+term/gfxterm.c
+term/terminfo.c
+term/tparm.c
+term/usb_keyboard.c
+term/efi/console.c
+term/i386/vga_common.c
+term/i386/pc/at_keyboard.c
+term/i386/pc/console.c
+term/i386/pc/serial.c
+term/i386/pc/vesafb.c
+term/i386/pc/vga.c
+term/i386/pc/vga_text.c
+term/ieee1275/ofconsole.c
+util/console.c
+util/getroot.c
+util/grub-editenv.c
+util/grub-emu.c
+util/grub-fstest.c
+util/grub-mkconfig.in
+util/grub-mkconfig_lib.in
+util/grub-mkdevicemap.c
+util/grub-mkfont.c
+util/grub-pe2elf.c
+util/grub-probe.c
+util/hostdisk.c
+util/hostfs.c
+util/lvm.c
+util/misc.c
+util/raid.c
+util/resolve.c
+util/update-grub_lib.in
+util/usb.c
+util/elf/grub-mkimage.c
+util/grub.d/00_header.in
+util/grub.d/10_freebsd.in
+util/grub.d/10_hurd.in
+util/grub.d/10_linux.in
+util/grub.d/10_windows.in
+util/grub.d/30_os-prober.in
+util/grub.d/40_custom.in
+util/grub.d/README
+util/i386/efi/grub-install.in
+util/i386/efi/grub-mkimage.c
+util/i386/pc/grub-install.in
+util/i386/pc/grub-mkimage.c
+util/i386/pc/grub-mkrescue.in
+util/i386/pc/grub-setup.c
+util/i386/pc/misc.c
+util/ieee1275/grub-install.in
+util/powerpc/ieee1275/grub-mkrescue.in
+util/powerpc/ieee1275/misc.c
+video/bitmap.c
+video/video.c
+video/i386/pc/vbe.c
+video/i386/pc/vbeblit.c
+video/i386/pc/vbefill.c
+video/i386/pc/vbeutil.c
+video/readers/jpeg.c
+video/readers/png.c
+video/readers/tga.c
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..e2b7c00
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,159 @@
+-*- Text -*-
+
+This is the GRUB.  Welcome.
+
+This file contains instructions for compiling and installing the GRUB.
+
+The Requirements
+================
+
+GRUB depends on some software packages installed into your system. If
+you don't have any of them, please obtain and install them before
+configuring the GRUB.
+
+* GCC 2.95 or later
+* GNU Make
+* GNU Bison
+* GNU binutils 2.9.1.0.23 or later
+* Other standard GNU/Unix tools
+* LZO 1.02 or later (optional)
+
+If you'd like to develop GRUB, these below are also required.
+
+* Ruby 1.6 or later
+* Autoconf 2.59 or later
+
+Configuring the GRUB
+====================
+
+The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a
+file `config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+If you need to do unusual things to compile the package, please try to
+figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+The file `configure.ac' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+
+Building the GRUB
+=================
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and
+     type `./configure' to configure the package for your system.  If
+     you're using `csh' on an old version of System V, you might need
+     to type `sh ./configure' instead to prevent `csh' from trying to
+     execute `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  `cd' to the directory where you want the object files
+and executables to go and run the `configure' script.  `configure'
+automatically checks for the source code in the directory that
+`configure' is in and in `..'.
+
+
+Installation Names
+==================
+
+By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix by giving `configure' the option `--prefix=PATH'.
+
+You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If
+you give `configure' the option `--exec-prefix=PATH', the package will
+use PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for
+particular kinds of files.  Run `configure --help' for a list of the
+directories you can set and what kinds of files go in them.
+
+If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure'
+the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Please note, however, that the GRUB knows where it is located in the
+filesystem.  If you have installed it in an unusual location, the
+system might not work properly, or at all.  The chief utility of these
+options for the GRUB is to allow you to "install" in some alternate
+location, and then copy these to the actual root filesystem later.
+
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..44dc577
--- /dev/null
@@ -0,0 +1,396 @@
+# -*- makefile -*-
+#
+# Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2001,2002,2004,2005,2006,2007,2008,2009,2008 Free Software Foundation, Inc.
+#
+# This Makefile.in is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+### The configure script will replace these variables.
+
+SHELL = /bin/sh
+
+@SET_MAKE@
+
+transform = @program_transform_name@
+
+srcdir = @srcdir@
+builddir = @builddir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+pkgdatadir = $(datadir)/`echo @PACKAGE_TARNAME@ | sed '$(transform)'`
+pkglibdir =  $(libdir)/`echo @PACKAGE_TARNAME@/$(target_cpu)-$(platform) | sed '$(transform)'`
+
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+
+host_os = @host_os@
+host_cpu = @host_cpu@
+
+target_cpu = @target_cpu@
+platform = @platform@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+
+mkinstalldirs = $(srcdir)/mkinstalldirs
+
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+CPPFLAGS = @CPPFLAGS@ -I$(builddir) -I$(builddir)/include -I$(srcdir)/include -Wall -W \
+        -DGRUB_LIBDIR=\"$(pkglibdir)\"
+TARGET_CC = @TARGET_CC@
+TARGET_CFLAGS = @TARGET_CFLAGS@
+TARGET_CPPFLAGS = @TARGET_CPPFLAGS@ -I$(builddir) -I$(builddir)/include -I$(srcdir)/include \
+       -Wall -W
+TARGET_LDFLAGS = @TARGET_LDFLAGS@
+TARGET_IMG_LDSCRIPT = @TARGET_IMG_LDSCRIPT@
+TARGET_IMG_LDFLAGS = @TARGET_IMG_LDFLAGS@
+TARGET_OBJ2ELF = @TARGET_OBJ2ELF@
+MODULE_LDFLAGS = @MODULE_LDFLAGS@
+EXEEXT = @EXEEXT@
+OBJCOPY = @OBJCOPY@
+STRIP = @STRIP@
+NM = @NM@
+RUBY = @RUBY@
+HELP2MAN = @HELP2MAN@
+ifeq (, $(HELP2MAN))
+HELP2MAN = true
+else
+HELP2MAN := LANG=C $(HELP2MAN) --no-info --source=FSF
+endif
+AWK = @AWK@
+LIBCURSES = @LIBCURSES@
+LIBLZO = @LIBLZO@
+YACC = @YACC@
+UNIFONT_BDF = @UNIFONT_BDF@
+
+# Options.
+enable_grub_emu = @enable_grub_emu@
+enable_grub_emu_usb = @enable_grub_emu_usb@
+enable_grub_fstest = @enable_grub_fstest@
+enable_grub_pe2elf = @enable_grub_pe2elf@
+enable_lzo = @enable_lzo@
+enable_grub_mkfont = @enable_grub_mkfont@
+freetype_cflags = @freetype_cflags@
+freetype_libs = @freetype_libs@
+
+### General variables.
+
+RMKFILES = $(addprefix conf/,common.rmk i386-coreboot.rmk i386-efi.rmk \
+       i386-ieee1275.rmk i386-pc.rmk i386.rmk powerpc-ieee1275.rmk \
+       sparc64-ieee1275.rmk x86_64-efi.rmk)
+
+MKFILES = $(patsubst %.rmk,%.mk,$(RMKFILES))
+
+PKGLIB = $(pkglib_IMAGES) $(pkglib_MODULES) $(pkglib_PROGRAMS) \
+       $(pkglib_DATA) $(lib_DATA) $(pkglib_BUILDDIR)
+PKGDATA = $(pkgdata_DATA) $(pkgdata_SRCDIR)
+PROGRAMS = $(bin_UTILITIES) $(sbin_UTILITIES)
+SCRIPTS = $(bin_SCRIPTS) $(sbin_SCRIPTS) $(grub-mkconfig_SCRIPTS)
+
+CLEANFILES =
+MOSTLYCLEANFILES = 
+DISTCLEANFILES = config.status config.cache config.log config.h \
+       Makefile stamp-h include/grub/cpu include/grub/machine \
+       gensymlist.sh genkernsyms.sh build_env.mk
+MAINTAINER_CLEANFILES = $(srcdir)/configure $(addprefix $(srcdir)/,$(MKFILES))
+
+# The default target.
+all: all-local
+
+### Include an arch-specific Makefile.
+$(addprefix $(srcdir)/,$(MKFILES)): %.mk: %.rmk genmk.rb
+       if test "x$(RUBY)" = x; then \
+         touch $@; \
+       else \
+         $(RUBY) $(srcdir)/genmk.rb < $< > $@; \
+       fi
+
+include $(srcdir)/conf/$(target_cpu)-$(platform).mk
+
+### General targets.
+
+CLEANFILES += $(pkglib_DATA) $(pkgdata_DATA)
+pkglib_DATA += moddep.lst command.lst fs.lst partmap.lst
+moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep.awk
+       cat $(DEFSYMFILES) /dev/null \
+         | $(AWK) -f $(srcdir)/genmoddep.awk $(UNDSYMFILES) > $@ \
+         || (rm -f $@; exit 1)
+
+command.lst: $(COMMANDFILES)
+       cat $^ /dev/null | sort > $@
+
+fs.lst: $(FSFILES)
+       cat $^ /dev/null | sort > $@
+
+partmap.lst: $(PARTMAPFILES)
+       cat $^ /dev/null | sort > $@
+
+ifeq (, $(UNIFONT_BDF))
+else
+
+ifeq ($(enable_grub_mkfont),yes)
+
+pkgdata_DATA += unicode.pf2 ascii.pf2
+
+# Arrows and lines are needed to draw the menu, so we always include them
+UNICODE_ARROWS=0x2190-0x2193
+UNICODE_LINES=0x2501-0x251B
+
+unicode.pf2: $(UNIFONT_BDF) grub-mkfont
+       $(builddir)/grub-mkfont -o $@ $(UNIFONT_BDF)
+
+ascii.pf2: $(UNIFONT_BDF) grub-mkfont
+       $(builddir)/grub-mkfont -o $@ $(UNIFONT_BDF) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES)
+endif
+endif
+
+# Used for building modules externally
+pkglib_BUILDDIR += build_env.mk
+build_env.mk: Makefile
+       (\
+       echo "TARGET_CC=$(TARGET_CC)" ; \
+       echo "TARGET_CFLAGS=$(TARGET_CFLAGS)" ; \
+       echo "TARGET_CPPFLAGS=$(TARGET_CPPFLAGS) -I$(pkglibdir)" ; \
+       echo "STRIP=$(STRIP)" ; \
+       echo "COMMON_ASFLAGS=$(COMMON_ASFLAGS)" ; \
+       echo "COMMON_CFLAGS=$(COMMON_CFLAGS)" ; \
+       echo "COMMON_LDFLAGS=$(COMMON_LDFLAGS)"\
+       ) > $@
+pkglib_BUILDDIR += config.h grub_script.tab.h
+pkgdata_SRCDIR += genmodsrc.sh genmk.rb
+include_DATA += $(shell find $(srcdir)/include -name \*.h | sed -e "s,^$(srcdir)/,,g") include/grub/cpu
+
+all-local: $(PROGRAMS) $(PKGLIB) $(PKGDATA) $(SCRIPTS) $(MKFILES)
+
+install: install-local
+
+install-local: all
+       $(mkinstalldirs) $(DESTDIR)$(pkglibdir)
+       @list='$(PKGLIB)'; \
+       for file in $$list; do \
+         if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \
+         dest="`echo $$file | sed 's,.*/,,'`"; \
+         $(INSTALL_DATA) $$dir$$file $(DESTDIR)$(pkglibdir)/$$dest; \
+       done
+       $(mkinstalldirs) $(DESTDIR)$(includedir)
+       @list='$(include_DATA)'; \
+       for file in $$list; do \
+         if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \
+         dest="`echo $$file | sed 's,include/,,'`"; \
+         destdir="`echo $$dest | sed 's,\(^\|/\)[^/]*$$,,g'`"; \
+         $(mkinstalldirs) $(DESTDIR)$(includedir)/$$destdir; \
+         if test -f "$$dir$$file"; then \
+           $(INSTALL_DATA) $$dir$$file $(DESTDIR)$(includedir)/$$dest; \
+         elif test -L "$$dir$$file"; then \
+           cp -d $$dir$$file $(DESTDIR)$(includedir)/$$dest; \
+         fi; \
+       done
+       $(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
+       @list='$(PKGDATA)'; \
+       for file in $$list; do \
+         if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \
+         dest="`echo $$file | sed 's,.*/,,'`"; \
+         $(INSTALL_DATA) $$dir$$file $(DESTDIR)$(pkgdatadir)/$$dest; \
+       done
+       $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1
+       @list='$(bin_UTILITIES)'; for file in $$list; do \
+         if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \
+         dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \
+         $(INSTALL_PROGRAM) $$dir$$file $(DESTDIR)$(bindir)/$$dest; \
+         $(HELP2MAN) --section=1 $(builddir)/$$file > $(DESTDIR)$(mandir)/man1/$$dest.1; \
+       done
+       $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(mandir)/man8
+       @list='$(sbin_UTILITIES)'; for file in $$list; do \
+         if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \
+         dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \
+         $(INSTALL_PROGRAM) $$dir$$file $(DESTDIR)$(sbindir)/$$dest; \
+         $(HELP2MAN) --section=8 $(builddir)/$$file > $(DESTDIR)$(mandir)/man8/$$dest.8; \
+       done
+       @list='$(bin_SCRIPTS)'; for file in $$list; do \
+         if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \
+         dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \
+         $(INSTALL_SCRIPT) $$dir$$file $(DESTDIR)$(bindir)/$$dest; \
+         $(HELP2MAN) --section=1 $(builddir)/$$file > $(DESTDIR)$(mandir)/man1/$$dest.1; \
+       done
+       @list='$(sbin_SCRIPTS)'; for file in $$list; do \
+         if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \
+         dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \
+         $(INSTALL_SCRIPT) $$dir$$file $(DESTDIR)$(sbindir)/$$dest; \
+         $(HELP2MAN) --section=8 $(builddir)/$$file > $(DESTDIR)$(mandir)/man8/$$dest.8; \
+       done
+       $(mkinstalldirs) $(DESTDIR)$(sysconfdir)/grub.d
+       @list='$(grub-mkconfig_SCRIPTS)'; for file in $$list; do \
+         if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \
+         dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \
+         $(INSTALL_SCRIPT) $$dir$$file $(DESTDIR)$(sysconfdir)/grub.d/$$dest; \
+       done
+       @list='$(grub-mkconfig_DATA)'; for file in $$list; do \
+         if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \
+         dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \
+         $(INSTALL_DATA) $$dir$$file $(DESTDIR)$(sysconfdir)/grub.d/$$dest; \
+       done
+       $(mkinstalldirs) $(DESTDIR)$(libdir)/grub
+       @list='$(lib_DATA)'; \
+       for file in $$list; do \
+         if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \
+         dest="`echo $$file | sed 's,.*/,,'`"; \
+         $(INSTALL_DATA) $$dir$$file $(DESTDIR)$(libdir)/grub/$$dest; \
+       done
+
+install-strip:
+       $(MAKE) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" install
+
+uninstall:
+       @list='$(PKGLIB)'; \
+       for file in $$list; do \
+         dest="`echo $$file | sed 's,.*/,,'`"; \
+         rm -f $(DESTDIR)$(pkglibdir)/$$dest; \
+       done
+       @list='$(PKGDATA)'; \
+       for file in $$list; do \
+         dest="`echo $$file | sed 's,.*/,,'`"; \
+         rm -f $(DESTDIR)$(pkgdatadir)/$$dest; \
+       done
+       @list='$(bin_UTILITIES) $(bin_SCRIPTS)'; for file in $$list; do \
+         dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \
+         rm -f $(DESTDIR)$(bindir)/$$dest; \
+       done
+       @list='$(sbin_UTILITIES) $(sbin_SCRIPTS)'; for file in $$list; do \
+         dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \
+         rm -f $(DESTDIR)$(sbindir)/$$dest; \
+       done
+       @list='$(grub-mkconfig_SCRIPTS) $(grub-mkconfig_DATA)'; for file in $$list; do \
+         dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \
+         rm -f $(DESTDIR)$(sysconfdir)/grub.d/$$dest; \
+       done
+
+clean:
+       -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+mostlyclean: clean
+       -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+distclean: mostlyclean
+       -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+       -rm -rf $(srcdir)/autom4te.cache
+
+maintainer-clean: distclean
+       -test -z "$(MAINTAINER_CLEANFILES)" || rm -f $(MAINTAINER_CLEANFILES)
+
+info:
+
+dvi:
+
+distdir=$(PACKAGE_TARNAME)-$(PACKAGE_VERSION)
+
+DISTLIST: gendistlist.sh
+       sh $(srcdir)/gendistlist.sh > $(srcdir)/DISTLIST
+
+distdir: DISTLIST
+       -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
+       $(mkinstalldirs) $(distdir)
+       for i in `cat $(srcdir)/DISTLIST`; do \
+         dir=`echo "$$i" | sed 's:/[^/]*$$::'`; \
+         if test -d $(srcdir)/$$dir; then \
+           $(mkinstalldirs) $(distdir)/$$dir; \
+         fi; \
+         cp -p $(srcdir)/$$i $(distdir)/$$i || exit 1; \
+       done
+       chmod -R a+r $(distdir)
+
+GZIP_ENV = --best
+
+dist: distdir
+       tar chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
+
+distcheck: dist
+       -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
+       GZIP=$(GZIP_ENV) gzip -cd $(distdir).tar.gz | tar xf -
+       chmod -R a-w $(distdir)
+       chmod a+w $(distdir)
+       mkdir $(distdir)/=build
+       mkdir $(distdir)/=inst
+       chmod a-w $(distdir)
+       dc_instdir=`CDPATH=: && cd $(distdir)/=inst && pwd` \
+         && cd $(distdir)/=build \
+         && ../configure --srcdir=.. --prefix=$$dc_instdir \
+         && $(MAKE) all dvi check install && $(MAKE) uninstall \
+         && (test `find $$dc_instdir -type f -print | wc -l` -le 1 \
+            || (echo "Error: files left after uninstall" 1>&2; \
+                exit 1)) \
+         && $(MAKE) dist && $(MAKE) distclean \
+         && rm -f $(distdir).tar.gz \
+         && (test `find . -type f -print | wc -l` -eq 0 \
+            || (echo "Error: files left after distclean" 1>&2; \
+                exit 1))
+       -chmod -R a+w $(distdir) > /dev/null 2>&1; rm -rf $(distdir)
+       @echo "$(distdir).tar.gz is ready for distribution" | \
+         sed 'h;s/./=/g;p;x;p;x'
+
+check:
+
+.SUFFIX:
+.SUFFIX: .c .o .S .d
+
+# Regenerate configure and Makefile automatically.
+$(srcdir)/configure: configure.ac aclocal.m4
+       cd $(srcdir) && autoconf
+
+$(srcdir)/config.h.in: stamp-h.in
+$(srcdir)/stamp-h.in: configure.ac aclocal.m4
+       cd $(srcdir) && autoheader
+       echo timestamp > $(srcdir)/stamp-h.in
+
+config.h: stamp-h
+stamp-h: config.h.in config.status
+       ./config.status
+
+Makefile: Makefile.in config.status
+       ./config.status
+
+config.status: configure
+       ./config.status --recheck
+
+gensymlist.sh: gensymlist.sh.in config.status
+       ./config.status
+
+genkernsyms.sh: genkernsyms.sh.in config.status
+       ./config.status
+
+.PHONY: all install install-strip uninstall clean mostlyclean distclean
+.PHONY: maintainer-clean info dvi dist check
+
+# Prevent an overflow.
+.NOEXPORT:
+
+.DELETE_ON_ERROR:
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..e223cdb
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,223 @@
+New in 1.97 - :
+
+* update-grub is renamed to grub-mkconfig.
+
+* When booting from PXE, PXE can be used to load files.
+
+* High resolution timer support.
+
+* Image loaders now support IO buffering.
+
+* Add `crc' command.
+
+* Add Cygwin support.
+
+* Add grub-pe2elf to convert PE modules to ELF modules.
+
+* Add x86_64 EFI support.
+
+* Add support for LZMA compression.
+
+* Support for saving the environment from and loading the environment
+  from a file.
+
+* Allow the UUID to be used as device name.
+
+* The `search' command can use UUIDs now.
+
+* Add support for IEEE 1275 on i386.
+
+* Create partmap.lst and use it to automatically load partition map
+  modules.
+
+* grub-mkconfig supports os-prober to add operating systems to the
+  boot menu.
+
+* The ATA driver supports filesystems bigger than 2TB.
+
+* Add support for the UDF, AFS and EXT4 filesystems.
+
+* The ISO9660 filesystem supports the Joliet extension
+
+* Add aout and BSD kernel loaders.
+
+* Add new command `sleep'.
+
+* Support for direct access to AT keyboards.
+
+* New utility `grub-fstest'.
+
+New in 1.96 - 2008-02-03:
+
+* The license term is changed to GNU General Public License Version 3.
+
+* grub-emu is made optional.  Now you have to use
+  `--enable-grub-emu' to enable it.
+
+* Add Multiboot2 support.
+
+* grub-emu can access the host filesystem now.
+
+* Add support for the NTFS, cpio/tar and Reiserfs filesystems.
+
+* Add support for ATA/ATAPI.
+
+* Add update-grub script to generate grub.cfg.
+
+* Add grub-mkrescue script to generate floppy or ElTorito images
+  (i386-pc only).
+
+* Add support for background images in gfxterm (background_image command).
+
+* Add support for detection of 64-bit support in CPU (cpuid command).
+
+* GPT is now enabled in i386-pc target.
+
+* Add grub-install for EFI.
+
+* Ported to the following new platforms: Efika, coreboot (a.k.a. LinuxBIOS),
+  OLPC XO.
+
+* Add support for colored menu (menu_color_normal and menu_color_highlight
+  variables).
+
+* Fix support for loading Linux zImages (such as memtest86).
+
+New in 1.95 - 2006-10-15:
+
+* Number partitions from 1 instead of 0. For instance, the first
+  partition of "hd0" is now "hd0,1" but not "hd0,0".
+
+* grub-probefs is renamed to grub-probe, and supports printing a
+  guessed OS device name and a GRUB drive name.
+
+* RAID and LVM support is added.
+
+* New command, echo.
+
+* The disk API is changed to support 64-bit addressing.
+
+* A TGA loader is added for the video API.
+
+New in 1.94 - 2006-06-04:
+
+* Fix several serious bugs in HFS+.
+
+* Add experimental EFI support. Chainloading and Linux loading are
+  supported at the moment.
+
+* Add a new command "blocklist" to show a block list.
+
+* Use --with-platform to specify a boot environment. For now, efi,
+  ieee1275 and pc are supported.
+
+* Use the filename "kernel.elf" instead of "grubof" on ieee1275.
+
+* Install GRUB into pkglibdir instead of pkgdatadir.
+
+* Support environmental variables. You can export variables by the
+  command "export".
+
+* Remove the commands "default" and "timeout". They are now variables.
+
+* Add the commands "source" and "." to include a file.
+
+* Implement experimental Video API and a new terminal "gfxterm" based
+  on the Video API.
+
+
+New in 1.93 - 2006-03-10:
+
+* Add support for the HFS+ wrapper.
+
+* Major improvements to scripting support.
+
+* Menu entries are now scriptable.
+
+
+New in 1.92 - 2005-12-25:
+
+* Add support for GPT partition table format.
+
+* Add a new command "play" to play an audio file on PC.
+
+* Add support for Linux/ADFS partition table format.
+
+* Add support for BASH-like scripting.
+
+* Add support for Apple HFS+ filesystems.
+
+
+New in 1.91 - 2005-10-15:
+
+* Add support for LZO version 2.
+
+* Support completion in the entry editor.
+
+* Add VBE support.
+
+* New commands, "search", "vbetest" and "vbeinfo".
+
+* The option BOOT_IMAGE is passed to Linux.
+
+* Add support for automatic decompression for gzip.
+
+* Add support for terminfo and serial.
+
+* Add support for x86_64.
+
+* GRUB itself is a Multiboot-compliant kernel.
+
+* Add new filesystems: XFS, SFS, and AFFS.
+
+
+New in 1.90 - 2005-08-07:
+
+* Rename the project name PUPA to GRUB. Now this version is the
+  developmental version of GRUB officially.
+
+* The GRUB emulator ``grub-emu'' is added.
+
+* Add support for newworld Mac. This should work with other
+  PowerPC-based machines as well, if they use IEEE 1275
+  (Open Firmware).
+
+* Too many changes to describe. Look at ChangeLog for more details.
+
+
+New in 0.7:
+
+* Problems in cross-compiling PUPA are fixed.
+
+* Use -mrtd and -mregparm=3 to reduce the generated code sizes.        This
+  means that any missing prototypes could be fatal. Also, you must take
+  care when writing assembly code. See the comments at the beginning of
+  startup.S, for more details.
+
+* New utility, ``pupa-setup''. This sets up PUPA to make it bootable
+  from a real disk.
+
+* New commands, "prefix", "insmod", "rmmod" and "lsmod" are added into
+  the rescue mode to manipulate PUPA modules.
+
+* Linux support is added. Initrd is not support yet.
+
+* Reduce the size of a core image significantly by compressing a large
+  part of the core image and decompressing itself at boot time. The
+  currently used algorithm is LZO (more precisely, LZO1X-999). So you
+  have to install LZO to build PUPA. See
+  <http://www.oberhumer.com/opensource/lzo/>, for more information.
+
+
+New in 0.6 - 2002-12-27, Yoshinori K. Okuji:
+
+* The chainloader and the FAT filesystem are modularized.
+
+* The structure of the source tree is a bit changed.
+
+* Support for building loadable modules is added.
+
+* Some generic parts of pupa-mkimage are segregated.
+
+* Some documentation files are added, according to the GNU Coding
+  Standards.
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..b6c7fd6
--- /dev/null
+++ b/README
@@ -0,0 +1,14 @@
+This is GRUB 2, the second version of the GRand Unified Bootloader.
+GRUB 2 is rewritten from scratch to make GNU GRUB cleaner, safer, more
+robust, more powerful, and more portable.
+
+See the file NEWS for a description of recent changes to GRUB 2.
+
+See the file INSTALL for instructions on how to build and install the
+GRUB 2 data and program files.
+
+Please visit the official web page of GRUB 2, for more information.
+The URL is <http://www.gnu.org/software/grub/grub.html>.
+
+For now, there is not much documentation yet. Please look at the GRUB
+Wiki <http://grub.enbug.org> for testing procedures.
diff --git a/THANKS b/THANKS
new file mode 100644 (file)
index 0000000..445bb6f
--- /dev/null
+++ b/THANKS
@@ -0,0 +1,37 @@
+GRUB 2 would not be what it is today without the invaluable help of
+everybody who was kind enough to spend time testing it and reporting
+bugs.
+
+The following people made especially gracious contributions of their
+time and energy in helping to track down bugs, add new features, and
+generally assist in the GRUB 2 maintainership process:
+
+Andrey Shuvikov <mr_hyro@yahoo.com>
+Bibo Mao <bibo.mao@intel.com>
+Guillem Jover <guillem@hadrons.org>
+Harley D. Eades III <hde@foobar-qux.org>
+Hitoshi Ozeki <h-ozeki@ck2.so-net.ne.jp>
+Hollis Blanchard <hollis@penguinppc.org>
+Jeroen Dekkers <jeroen@dekkers.cx>
+Johan Rydberg <jrydberg@gnu.org>
+Marco Gerards <marco@gnu.org>
+Michael Guntsche <mike@it-loops.com>
+NIIBE Yutaka <gniibe@m17n.org>
+Omniflux <omniflux@omniflux.com>
+Robert Bihlmeyer <robbe@orcus.priv.at>
+Roger Leigh <rleigh@whinlatter.ukfsn.org>
+Ruslan Nikolaev <nruslan@mail.com>
+Timothy Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
+Tomas Ebenlendr <ebik@ucw.cz>
+Tristan Gingold  <tristan.gingold@bull.net>
+Tsuneyoshi Yasuo <tuneyoshi@naic.co.jp>
+Vesa Jaaskelainen  <chaac@nic.fi>
+Vincent Guffens <guffens@inma.ucl.ac.be>
+Vincent Pelletier <subdino2004@yahoo.fr>
+Vladimir Serbinenko <phcoder@gmail.com>
+
+Also, we thank the projects GNU Automake and LZO. Some code
+was stolen from them.
+
+This project was supported by Information-technology Promotion Agency,
+Japan.
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..6ec1521
--- /dev/null
+++ b/TODO
@@ -0,0 +1,13 @@
+
+Before working on improving GRUB, it's very important that you
+make contact with the core GRUB developers. Things herein might be
+slightly out of date or otherwise not easy to understand at first
+glance. So write to <grub-devel@gnu.org> first.
+
+For bug tracking, refer to:
+
+  http://savannah.gnu.org/bugs/?group=grub
+
+Our wiki also lists some areas that need work:
+
+  http://grub.enbug.org/
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644 (file)
index 0000000..1dd5ffb
--- /dev/null
@@ -0,0 +1,450 @@
+dnl Check whether target compiler is working
+AC_DEFUN(grub_PROG_TARGET_CC,
+[AC_MSG_CHECKING([whether target compiler is working])
+AC_CACHE_VAL(grub_cv_prog_target_cc,
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
+               [grub_cv_prog_target_cc=yes],
+               [grub_cv_prog_target_cc=no])
+])
+AC_MSG_RESULT([$grub_cv_prog_target_cc])
+
+if test "x$grub_cv_prog_target_cc" = xno; then
+  AC_MSG_ERROR([cannot compile for the target])
+fi
+])
+
+
+dnl grub_ASM_USCORE checks if C symbols get an underscore after
+dnl compiling to assembler.
+dnl Written by Pavel Roskin. Based on grub_ASM_EXT_C written by
+dnl Erich Boleyn and modified by Yoshinori K. Okuji.
+AC_DEFUN(grub_ASM_USCORE,
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING([if C symbols get an underscore after compilation])
+AC_CACHE_VAL(grub_cv_asm_uscore,
+[cat > conftest.c <<\EOF
+int
+func (int *list)
+{
+  *list = 0;
+  return *list;
+}
+EOF
+
+if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -S conftest.c]) && test -s conftest.s; then
+  true
+else
+  AC_MSG_ERROR([${CC-cc} failed to produce assembly code])
+fi
+
+if grep _func conftest.s >/dev/null 2>&1; then
+  grub_cv_asm_uscore=yes
+else
+  grub_cv_asm_uscore=no
+fi
+
+rm -f conftest*])
+
+if test "x$grub_cv_asm_uscore" = xyes; then
+  AC_DEFINE_UNQUOTED([HAVE_ASM_USCORE], $grub_cv_asm_uscore,
+    [Define if C symbols get an underscore after compilation])
+fi
+
+AC_MSG_RESULT([$grub_cv_asm_uscore])
+])
+
+
+dnl Some versions of `objcopy -O binary' vary their output depending
+dnl on the link address.
+AC_DEFUN(grub_PROG_OBJCOPY_ABSOLUTE,
+[AC_MSG_CHECKING([whether ${OBJCOPY} works for absolute addresses])
+AC_CACHE_VAL(grub_cv_prog_objcopy_absolute,
+[cat > conftest.c <<\EOF
+void
+cmain (void)
+{
+   *((int *) 0x1000) = 2;
+}
+EOF
+
+if AC_TRY_EVAL(ac_compile) && test -s conftest.o; then :
+else
+  AC_MSG_ERROR([${CC-cc} cannot compile C source code])
+fi
+grub_cv_prog_objcopy_absolute=yes
+for link_addr in 2000 8000 7C00; do
+  if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -nostdlib ${TARGET_IMG_LDFLAGS_AC} -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec]); then :
+  else
+    AC_MSG_ERROR([${CC-cc} cannot link at address $link_addr])
+  fi
+  if AC_TRY_COMMAND([${OBJCOPY-objcopy} --only-section=.text -O binary conftest.exec conftest]); then :
+  else
+    AC_MSG_ERROR([${OBJCOPY-objcopy} cannot create binary files])
+  fi
+  if test ! -f conftest.old || AC_TRY_COMMAND([cmp -s conftest.old conftest]); then
+    mv -f conftest conftest.old
+  else
+    grub_cv_prog_objcopy_absolute=no
+    break
+  fi
+done
+rm -f conftest*])
+AC_MSG_RESULT([$grub_cv_prog_objcopy_absolute])
+
+if test "x$grub_cv_prog_objcopy_absolute" = xno; then
+  AC_MSG_ERROR([GRUB requires a working absolute objcopy; upgrade your binutils])
+fi
+])
+
+
+dnl Supply --build-id=none to ld if building modules.
+dnl This suppresses warnings from ld on some systems
+AC_DEFUN(grub_PROG_LD_BUILD_ID_NONE,
+[AC_MSG_CHECKING([whether linker accepts --build-id=none])
+AC_CACHE_VAL(grub_cv_prog_ld_build_id_none,
+[save_LDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS -Wl,--build-id=none"
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
+              [grub_cv_prog_ld_build_id_none=yes],
+              [grub_cv_prog_ld_build_id_none=no])
+LDFLAGS="$save_LDFLAGS"
+])
+AC_MSG_RESULT([$grub_cv_prog_ld_build_id_none])
+
+if test "x$grub_cv_prog_ld_build_id_none" = xyes; then
+  MODULE_LDFLAGS="$MODULE_LDFLAGS -Wl,--build-id=none"
+fi
+])
+
+
+dnl Mass confusion!
+dnl Older versions of GAS interpret `.code16' to mean ``generate 32-bit
+dnl instructions, but implicitly insert addr32 and data32 bytes so
+dnl that the code works in real mode''.
+dnl
+dnl Newer versions of GAS interpret `.code16' to mean ``generate 16-bit
+dnl instructions,'' which seems right.  This requires the programmer
+dnl to explicitly insert addr32 and data32 instructions when they want
+dnl them.
+dnl
+dnl We only support the newer versions, because the old versions cause
+dnl major pain, by requiring manual assembly to get 16-bit instructions into
+dnl asm files.
+AC_DEFUN(grub_I386_ASM_ADDR32,
+[AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([grub_I386_ASM_PREFIX_REQUIREMENT])
+AC_MSG_CHECKING([for .code16 addr32 assembler support])
+AC_CACHE_VAL(grub_cv_i386_asm_addr32,
+[cat > conftest.s.in <<\EOF
+       .code16
+l1:    @ADDR32@        movb    %al, l1
+EOF
+
+if test "x$grub_cv_i386_asm_prefix_requirement" = xyes; then
+  sed -e s/@ADDR32@/addr32/ < conftest.s.in > conftest.s
+else
+  sed -e s/@ADDR32@/addr32\;/ < conftest.s.in > conftest.s
+fi
+
+if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then
+  grub_cv_i386_asm_addr32=yes
+else
+  grub_cv_i386_asm_addr32=no
+fi
+
+rm -f conftest*])
+
+AC_MSG_RESULT([$grub_cv_i386_asm_addr32])])
+
+
+dnl Later versions of GAS requires that addr32 and data32 prefixes
+dnl appear in the same lines as the instructions they modify, while
+dnl earlier versions requires that they appear in separate lines.
+AC_DEFUN(grub_I386_ASM_PREFIX_REQUIREMENT,
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING(dnl
+[whether addr32 must be in the same line as the instruction])
+AC_CACHE_VAL(grub_cv_i386_asm_prefix_requirement,
+[cat > conftest.s <<\EOF
+       .code16
+l1:    addr32  movb    %al, l1
+EOF
+
+if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then
+  grub_cv_i386_asm_prefix_requirement=yes
+else
+  grub_cv_i386_asm_prefix_requirement=no
+fi
+
+rm -f conftest*])
+
+if test "x$grub_cv_i386_asm_prefix_requirement" = xyes; then
+  grub_tmp_addr32="addr32"
+  grub_tmp_data32="data32"
+else
+  grub_tmp_addr32="addr32;"
+  grub_tmp_data32="data32;"
+fi
+
+AC_DEFINE_UNQUOTED([ADDR32], $grub_tmp_addr32,
+  [Define it to \"addr32\" or \"addr32;\" to make GAS happy])
+AC_DEFINE_UNQUOTED([DATA32], $grub_tmp_data32,
+  [Define it to \"data32\" or \"data32;\" to make GAS happy])
+
+AC_MSG_RESULT([$grub_cv_i386_asm_prefix_requirement])])
+
+
+dnl Older versions of GAS require that absolute indirect calls/jumps are
+dnl not prefixed with `*', while later versions warn if not prefixed.
+AC_DEFUN(grub_I386_ASM_ABSOLUTE_WITHOUT_ASTERISK,
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING(dnl
+[whether an absolute indirect call/jump must not be prefixed with an asterisk])
+AC_CACHE_VAL(grub_cv_i386_asm_absolute_without_asterisk,
+[cat > conftest.s <<\EOF
+       lcall   *(offset)       
+offset:
+       .long   0
+       .word   0
+EOF
+
+if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then
+  grub_cv_i386_asm_absolute_without_asterisk=no
+else
+  grub_cv_i386_asm_absolute_without_asterisk=yes
+fi
+
+rm -f conftest*])
+
+if test "x$grub_cv_i386_asm_absolute_without_asterisk" = xyes; then
+  AC_DEFINE([ABSOLUTE_WITHOUT_ASTERISK], 1,
+           [Define it if GAS requires that absolute indirect calls/jumps are not prefixed with an asterisk])
+fi
+
+AC_MSG_RESULT([$grub_cv_i386_asm_absolute_without_asterisk])])
+
+
+dnl Check what symbol is defined as a start symbol.
+dnl Written by Yoshinori K. Okuji.
+AC_DEFUN(grub_CHECK_START_SYMBOL,
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING([if start is defined by the compiler])
+AC_CACHE_VAL(grub_cv_check_start_symbol,
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
+               [[asm ("incl start")]])],
+               [grub_cv_check_start_symbol=yes],
+               [grub_cv_check_start_symbol=no])])
+
+AC_MSG_RESULT([$grub_cv_check_start_symbol])
+
+AC_MSG_CHECKING([if _start is defined by the compiler])
+AC_CACHE_VAL(grub_cv_check_uscore_start_symbol,
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
+               [[asm ("incl _start")]])],
+               [grub_cv_check_uscore_start_symbol=yes],
+               [grub_cv_check_uscore_start_symbol=no])])
+
+AC_MSG_RESULT([$grub_cv_check_uscore_start_symbol])
+
+AH_TEMPLATE([START_SYMBOL], [Define it to either start or _start])
+
+if test "x$grub_cv_check_start_symbol" = xyes; then
+  AC_DEFINE([START_SYMBOL], [start])
+elif test "x$grub_cv_check_uscore_start_symbol" = xyes; then
+  AC_DEFINE([START_SYMBOL], [_start])
+else
+  AC_MSG_ERROR([neither start nor _start is defined])
+fi
+])
+
+dnl Check what symbol is defined as a bss start symbol.
+dnl Written by Michael Hohmoth and Yoshinori K. Okuji.
+AC_DEFUN(grub_CHECK_BSS_START_SYMBOL,
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING([if __bss_start is defined by the compiler])
+AC_CACHE_VAL(grub_cv_check_uscore_uscore_bss_start_symbol,
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
+               [[asm ("incl __bss_start")]])],
+               [grub_cv_check_uscore_uscore_bss_start_symbol=yes],
+               [grub_cv_check_uscore_uscore_bss_start_symbol=no])])
+
+AC_MSG_RESULT([$grub_cv_check_uscore_uscore_bss_start_symbol])
+
+AC_MSG_CHECKING([if edata is defined by the compiler])
+AC_CACHE_VAL(grub_cv_check_edata_symbol,
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
+               [[asm ("incl edata")]])],
+               [grub_cv_check_edata_symbol=yes],
+               [grub_cv_check_edata_symbol=no])])
+
+AC_MSG_RESULT([$grub_cv_check_edata_symbol])
+
+AC_MSG_CHECKING([if _edata is defined by the compiler])
+AC_CACHE_VAL(grub_cv_check_uscore_edata_symbol,
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
+               [[asm ("incl _edata")]])],
+               [grub_cv_check_uscore_edata_symbol=yes],
+               [grub_cv_check_uscore_edata_symbol=no])])
+
+AC_MSG_RESULT([$grub_cv_check_uscore_edata_symbol])
+
+AH_TEMPLATE([BSS_START_SYMBOL], [Define it to one of __bss_start, edata and _edata])
+
+if test "x$grub_cv_check_uscore_uscore_bss_start_symbol" = xyes; then
+  AC_DEFINE([BSS_START_SYMBOL], [__bss_start])
+elif test "x$grub_cv_check_edata_symbol" = xyes; then
+  AC_DEFINE([BSS_START_SYMBOL], [edata])
+elif test "x$grub_cv_check_uscore_edata_symbol" = xyes; then
+  AC_DEFINE([BSS_START_SYMBOL], [_edata])
+else
+  AC_MSG_ERROR([none of __bss_start, edata or _edata is defined])
+fi
+])
+
+dnl Check what symbol is defined as an end symbol.
+dnl Written by Yoshinori K. Okuji.
+AC_DEFUN(grub_CHECK_END_SYMBOL,
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING([if end is defined by the compiler])
+AC_CACHE_VAL(grub_cv_check_end_symbol,
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
+               [[asm ("incl end")]])],
+               [grub_cv_check_end_symbol=yes],
+               [grub_cv_check_end_symbol=no])])
+
+AC_MSG_RESULT([$grub_cv_check_end_symbol])
+
+AC_MSG_CHECKING([if _end is defined by the compiler])
+AC_CACHE_VAL(grub_cv_check_uscore_end_symbol,
+[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
+               [[asm ("incl _end")]])],
+               [grub_cv_check_uscore_end_symbol=yes],
+               [grub_cv_check_uscore_end_symbol=no])])
+
+AC_MSG_RESULT([$grub_cv_check_uscore_end_symbol])
+
+AH_TEMPLATE([END_SYMBOL], [Define it to either end or _end])
+
+if test "x$grub_cv_check_end_symbol" = xyes; then
+  AC_DEFINE([END_SYMBOL], [end])
+elif test "x$grub_cv_check_uscore_end_symbol" = xyes; then
+  AC_DEFINE([END_SYMBOL], [_end])
+else
+  AC_MSG_ERROR([neither end nor _end is defined])
+fi
+])
+
+dnl Check if the C compiler has a bug while using nested functions when
+dnl mregparm is used on the i386.  Some gcc versions do not pass the third
+dnl parameter correctly to the nested function.
+dnl Written by Marco Gerards.
+AC_DEFUN(grub_I386_CHECK_REGPARM_BUG,
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING([if GCC has the regparm=3 bug])
+AC_CACHE_VAL(grub_cv_i386_check_nested_functions,
+[AC_RUN_IFELSE([AC_LANG_SOURCE(
+[[
+static int
+test (int *n)
+{
+  return *n == -1;
+}
+
+static int
+testfunc (int __attribute__ ((__regparm__ (3))) (*hook) (int a, int b, int *c))
+{
+  int a = 0;
+  int b = 0;
+  int c = -1;
+  return hook (a, b, &c);
+}
+
+int
+main (void)
+{
+  int __attribute__ ((__regparm__ (3))) nestedfunc (int a, int b, int *c)
+    {
+      return a == b && test (c);
+    }
+  return testfunc (nestedfunc) ? 0 : 1;
+}
+]])],
+       [grub_cv_i386_check_nested_functions=no],
+       [grub_cv_i386_check_nested_functions=yes])])
+
+AC_MSG_RESULT([$grub_cv_i386_check_nested_functions])
+
+if test "x$grub_cv_i386_check_nested_functions" = xyes; then
+  AC_DEFINE([NESTED_FUNC_ATTR], 
+       [__attribute__ ((__regparm__ (1)))],
+       [Catch gcc bug])
+else
+dnl Unfortunately, the above test does not detect a bug in gcc-4.0.
+dnl So use regparm 2 until a better test is found.
+  AC_DEFINE([NESTED_FUNC_ATTR], 
+       [__attribute__ ((__regparm__ (1)))],
+       [Catch gcc bug])
+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([[
+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
+  AC_MSG_ERROR([${CC-cc} failed to produce assembly code])
+fi
+if grep __enable_execute_stack conftest.s >/dev/null 2>&1; then
+  AC_DEFINE([NEED_ENABLE_EXECUTE_STACK], 1,
+           [Define to 1 if GCC generates calls to __enable_execute_stack()])
+  AC_MSG_RESULT([yes])
+else
+  AC_MSG_RESULT([no])
+fi
+rm -f conftest*
+])
+
+\f
+dnl Check if the C compiler supports `-fstack-protector'.
+AC_DEFUN(grub_CHECK_STACK_PROTECTOR,[
+[# Smashing 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]; }]])
+[# `$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]
+  AC_MSG_RESULT([yes])
+  [# Should we clear up other files as well, having called `AC_LANG_CONFTEST'?
+  rm -f conftest.s
+else
+  ssp_possible=no]
+  AC_MSG_RESULT([no])
+[fi]
+])
+
+dnl Check if the C compiler supports `-mstack-arg-probe' (Cygwin).
+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]; }]])
+[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'?
+  rm -f conftest.s
+else
+  sap_possible=no]
+  AC_MSG_RESULT([no])
+[fi]
+])
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..6895de2
--- /dev/null
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+set -e
+
+autoconf
+autoheader
+echo timestamp > stamp-h.in
+for rmk in conf/*.rmk; do
+  ruby genmk.rb < $rmk > `echo $rmk | sed 's/\.rmk$/.mk/'`
+done
+./gendistlist.sh > DISTLIST
+
+exit 0
diff --git a/boot/i386/pc/boot.S b/boot/i386/pc/boot.S
new file mode 100644 (file)
index 0000000..8056731
--- /dev/null
@@ -0,0 +1,489 @@
+/* -*-Asm-*- */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2005,2006,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/>.
+ */
+
+#include <grub/boot.h>
+#include <grub/machine/boot.h>
+       
+/*
+ *  defines for the code go here
+ */
+
+       /* Absolute addresses
+          This makes the assembler generate the address without support
+          from the linker. (ELF can't relocate 16-bit addresses!) */
+#define ABS(x) (x-_start+0x7c00)
+
+       /* Print message string */
+#define MSG(x) movw $ABS(x), %si; call message
+
+       .file   "boot.S"
+
+       .text
+
+       /* Tell GAS to generate 16-bit instructions so that this code works
+          in real mode. */
+       .code16
+
+.globl _start; _start:
+       /*
+        * _start is loaded at 0x7c00 and is jumped to with CS:IP 0:0x7c00
+        */
+
+       /*
+        * Beginning of the sector is compatible with the FAT/HPFS BIOS
+        * parameter block.
+        */
+
+       jmp     after_BPB
+       nop     /* do I care about this ??? */
+
+       /*
+        * This space is for the BIOS parameter block!!!!  Don't change
+        * the first jump, nor start the code anywhere but right after
+        * this area.
+        */
+
+       . = _start + 4
+
+       /* scratch space */
+mode:
+       .byte   0
+disk_address_packet:   
+sectors:
+       .long   0
+heads:
+       .long   0
+cylinders:
+       .word   0
+sector_start:
+       .byte   0
+head_start:
+       .byte   0
+cylinder_start:
+       .word   0
+       /* more space... */
+
+       . = _start + GRUB_BOOT_MACHINE_BPB_END
+
+       /*
+        * End of BIOS parameter block.
+        */
+
+boot_version:  
+       .byte   GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
+kernel_address:
+       .word   GRUB_BOOT_MACHINE_KERNEL_ADDR
+kernel_segment:
+       .word   GRUB_BOOT_MACHINE_KERNEL_SEG
+kernel_sector:
+       .long   1, 0
+boot_drive:    
+       .byte 0xff      /* the disk to load kernel from */
+                       /* 0xff means use the boot drive */
+root_drive:
+        .byte 0xff
+
+after_BPB:
+
+/* general setup */
+       cli             /* we're not safe here! */
+
+        /*
+         * This is a workaround for buggy BIOSes which don't pass boot
+         * drive correctly. If GRUB is installed into a HDD, check if
+         * DL is masked correctly. If not, assume that the BIOS passed
+         * a bogus value and set DL to 0x80, since this is the only
+         * possible boot drive. If GRUB is installed into a floppy,
+         * this does nothing (only jump).
+         */
+boot_drive_check:
+        jmp     1f     /* grub-setup may overwrite this jump */
+        testb   $0x80, %dl
+        jnz     1f
+        movb    $0x80, %dl
+1:
+       
+       /*
+        * ljmp to the next instruction because some bogus BIOSes
+        * jump to 07C0:0000 instead of 0000:7C00.
+        */
+       ljmp    $0, $ABS(real_start)
+
+real_start:    
+
+       /* set up %ds and %ss as offset from 0 */
+       xorw    %ax, %ax
+       movw    %ax, %ds
+       movw    %ax, %ss
+
+       /* set up the REAL stack */
+       movw    $GRUB_BOOT_MACHINE_STACK_SEG, %sp
+
+       sti             /* we're safe again */
+
+       /*
+        *  Check if we have a forced disk reference here
+        */
+        /* assign root_drive at the same time */
+        movw    ABS(boot_drive), %ax
+        movb    %ah, %dh
+       cmpb    $0xff, %al
+       je      1f
+       movb    %al, %dl
+1:
+       /* save drive reference first thing! */
+       pushw   %dx
+
+       /* print a notification message on the screen */
+       MSG(notification_string)
+
+       /* set %si to the disk address packet */
+       movw    $ABS(disk_address_packet), %si
+       
+       /* do not probe LBA if the drive is a floppy */
+       testb   $GRUB_BOOT_MACHINE_BIOS_HD_FLAG, %dl
+       jz      chs_mode
+                       
+       /* check if LBA is supported */
+       movb    $0x41, %ah
+       movw    $0x55aa, %bx
+       int     $0x13
+
+       /* 
+        *  %dl may have been clobbered by INT 13, AH=41H.
+        *  This happens, for example, with AST BIOS 1.04.
+        */
+       popw    %dx
+       pushw   %dx
+
+       /* use CHS if fails */
+       jc      chs_mode
+       cmpw    $0xaa55, %bx
+       jne     chs_mode
+
+       andw    $1, %cx
+       jz      chs_mode
+       
+lba_mode:
+       xorw    %ax, %ax
+       movw    %ax, 4(%si)
+
+       incw    %ax     
+       /* set the mode to non-zero */
+       movb    %al, -1(%si)
+       
+       /* the blocks */
+       movw    %ax, 2(%si)
+
+       /* the size and the reserved byte */
+       movw    $0x0010, (%si)
+
+       /* the absolute address */
+       movl    ABS(kernel_sector), %ebx
+       movl    %ebx, 8(%si)
+       movl    ABS(kernel_sector + 4), %ebx
+       movl    %ebx, 12(%si)
+
+       /* the segment of buffer address */
+       movw    $GRUB_BOOT_MACHINE_BUFFER_SEG, 6(%si)
+
+/*
+ * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
+ *     Call with       %ah = 0x42
+ *                     %dl = drive number
+ *                     %ds:%si = segment:offset of disk address packet
+ *     Return:
+ *                     %al = 0x0 on success; err code on failure
+ */
+
+       movb    $0x42, %ah
+       int     $0x13
+
+       /* LBA read is not supported, so fallback to CHS.  */
+       jc      chs_mode
+
+       movw    $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
+       jmp     copy_buffer
+               
+chs_mode:      
+       /*
+        *  Determine the hard disk geometry from the BIOS!
+        *  We do this first, so that LS-120 IDE floppies work correctly.
+        */
+       movb    $8, %ah
+       int     $0x13
+       jnc     final_init
+
+       /*
+        *  The call failed, so maybe use the floppy probe instead.
+        */
+       testb   $GRUB_BOOT_MACHINE_BIOS_HD_FLAG, %dl
+       jz      floppy_probe
+
+       /* Nope, we definitely have a hard disk, and we're screwed. */
+       jmp     hd_probe_error
+
+final_init:
+       /* set the mode to zero */
+       movzbl  %dh, %eax
+       movb    %ah, -1(%si)
+       
+       /* save number of heads */
+       incw    %ax
+       movl    %eax, 4(%si)
+
+       movzbw  %cl, %dx
+       shlw    $2, %dx
+       movb    %ch, %al
+       movb    %dh, %ah
+
+       /* save number of cylinders */
+       incw    %ax
+       movw    %ax, 8(%si)
+
+       movzbw  %dl, %ax
+       shrb    $2, %al
+
+       /* save number of sectors */
+       movl    %eax, (%si)
+
+setup_sectors:
+       /* load logical sector start (top half) */
+       movl    ABS(kernel_sector + 4), %eax
+       orl     %eax, %eax
+       jnz     geometry_error
+       
+       /* load logical sector start (bottom half) */
+       movl    ABS(kernel_sector), %eax
+
+       /* zero %edx */
+       xorl    %edx, %edx
+
+       /* divide by number of sectors */
+       divl    (%si)
+
+       /* save sector start */
+       movb    %dl, %cl
+
+       xorw    %dx, %dx        /* zero %edx */
+       divl    4(%si)          /* divide by number of heads */
+
+       /* do we need too many cylinders? */
+       cmpw    8(%si), %ax
+       jge     geometry_error
+
+       /* normalize sector start (1-based) */
+       incb    %cl
+
+       /* low bits of cylinder start */
+       movb    %al, %ch
+
+       /* high bits of cylinder start */
+       xorb    %al, %al
+       shrw    $2, %ax
+       orb     %al, %cl
+
+       /* save head start */
+       movb    %dl, %al
+
+       /* restore %dl */
+       popw    %dx
+        pushw   %dx
+
+       /* head start */
+       movb    %al, %dh
+
+/*
+ * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
+ *     Call with       %ah = 0x2
+ *                     %al = number of sectors
+ *                     %ch = cylinder
+ *                     %cl = sector (bits 6-7 are high bits of "cylinder")
+ *                     %dh = head
+ *                     %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
+ *                     %es:%bx = segment:offset of buffer
+ *     Return:
+ *                     %al = 0x0 on success; err code on failure
+ */
+
+       movw    $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
+       movw    %bx, %es        /* load %es segment with disk buffer */
+
+       xorw    %bx, %bx        /* %bx = 0, put it at 0 in the segment */
+       movw    $0x0201, %ax    /* function 2 */
+       int     $0x13
+
+       jc      read_error
+
+       movw    %es, %bx
+       
+copy_buffer:
+       movw    ABS(kernel_segment), %es
+
+       /*
+        * We need to save %cx and %si because the startup code in
+        * kernel uses them without initializing them.
+        */
+       pusha
+       pushw   %ds
+       
+       movw    $0x100, %cx
+       movw    %bx, %ds
+       xorw    %si, %si
+       xorw    %di, %di
+       
+       cld
+       
+       rep
+       movsw
+
+       popw    %ds
+       popa
+        popw    %dx
+
+       /* boot kernel */
+       jmp     *(kernel_address)
+
+/* END OF MAIN LOOP */
+
+/*
+ * BIOS Geometry translation error (past the end of the disk geometry!).
+ */
+geometry_error:
+       MSG(geometry_error_string)
+       jmp     general_error
+
+/*
+ * Disk probe failure.
+ */
+hd_probe_error:
+       MSG(hd_probe_error_string)
+       jmp     general_error
+
+/*
+ * Read error on the disk.
+ */
+read_error:
+       MSG(read_error_string)
+
+general_error:
+       MSG(general_error_string)
+
+/* go here when you need to stop the machine hard after an error condition */
+        /* tell the BIOS a boot failure, which may result in no effect */
+        int    $0x18
+stop:  jmp     stop
+
+notification_string:   .string "GRUB "
+geometry_error_string: .string "Geom"
+hd_probe_error_string: .string "Hard Disk"
+read_error_string:     .string "Read"
+general_error_string:  .string " Error"
+
+/*
+ * message: write the string pointed to by %si
+ *
+ *   WARNING: trashes %si, %ax, and %bx
+ */
+
+       /*
+        * Use BIOS "int 10H Function 0Eh" to write character in teletype mode
+        *      %ah = 0xe       %al = character
+        *      %bh = page      %bl = foreground color (graphics modes)
+        */
+1:
+       movw    $0x0001, %bx
+       movb    $0xe, %ah
+       int     $0x10           /* display a byte */
+message:
+       lodsb
+       cmpb    $0, %al
+       jne     1b      /* if not end of string, jmp to display */
+       ret
+
+       /*
+        *  Windows NT breaks compatibility by embedding a magic
+        *  number here.
+        */
+
+       . = _start + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
+nt_magic:      
+       .long 0
+       .word 0
+
+       /*
+        *  This is where an MBR would go if on a hard disk.  The code
+        *  here isn't even referenced unless we're on a floppy.  Kinda
+        *  sneaky, huh?
+        */
+
+part_start:    
+       . = _start + GRUB_BOOT_MACHINE_PART_START
+
+probe_values:
+       .byte   36, 18, 15, 9, 0
+
+floppy_probe:
+/*
+ *  Perform floppy probe.
+ */
+
+       movw    $ABS(probe_values-1), %si
+
+probe_loop:
+       /* reset floppy controller INT 13h AH=0 */
+       xorw    %ax, %ax
+       int     $0x13
+
+       incw    %si
+       movb    (%si), %cl
+
+       /* if number of sectors is 0, display error and die */
+       cmpb    $0, %cl
+       jne     1f
+
+/*
+ * Floppy disk probe failure.
+ */
+       MSG(fd_probe_error_string)
+       jmp     general_error
+
+fd_probe_error_string: .string "Floppy"
+
+1:
+       /* perform read */
+       movw    $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
+       movw    $0x201, %ax
+       movb    $0, %ch
+       movb    $0, %dh
+       int     $0x13
+
+       /* if error, jump to "probe_loop" */
+       jc      probe_loop
+
+       /* %cl is already the correct value! */
+       movb    $1, %dh
+       movb    $79, %ch
+
+       jmp     final_init
+
+       . = _start + GRUB_BOOT_MACHINE_PART_END
+
+/* the last 2 bytes in the sector 0 contain the signature */
+       .word   GRUB_BOOT_MACHINE_SIGNATURE
diff --git a/boot/i386/pc/cdboot.S b/boot/i386/pc/cdboot.S
new file mode 100644 (file)
index 0000000..02d4fce
--- /dev/null
@@ -0,0 +1,175 @@
+/* -*-Asm-*- */
+/*
+ *  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/boot.h>
+#include <grub/machine/boot.h>
+#include <grub/machine/kernel.h>
+#include <multiboot.h>
+
+        .file   "cdboot.S"
+
+#define CODE_ADDR      0x6000
+#define DATA_ADDR      ((GRUB_BOOT_MACHINE_KERNEL_ADDR) + 0x200)
+
+#define CDSEC_SHIFT    11
+#define CDBLK_LENG     16
+
+       .text
+
+        .code16
+
+        .globl  start, _start
+
+start:
+_start:
+       call    next
+
+next:
+       jmp     1f
+
+       . = start + 8
+
+bi_pvd:
+       .long 0         /* LBA of primary volume descript.  */
+bi_file:
+       .long 0         /* LBA of boot file. */
+bi_length:
+       .long 0         /* Length of boot file. */
+bi_csum:
+       .long 0         /* Checksum of boot file */
+bi_reserved:
+       .space (10*4)   /* Reserved */
+
+1:
+       popw    %bx
+
+       /* Boot from CDROM.  */
+
+       xorw    %ax, %ax
+       movw    %ax, %ss
+       movw    $(CODE_ADDR), %sp
+       movw    %ax, %ds
+       movw    %ax, %es
+
+       movw    $(0x7C00 + err_noboot_msg - start), %si
+       movl    %cs: bi_length - next(%bx), %ecx
+       orl     %ecx, %ecx
+       jz      fail
+
+       addl    $((1 << CDSEC_SHIFT) - 1), %ecx
+       shrl    $CDSEC_SHIFT, %ecx
+
+       movl    %cs: bi_file - next(%bx), %esi
+
+       call    read_cdrom
+
+        /* Root drive will default to boot drive */
+        movb    $0xFF, %dh
+        
+       ljmp    $(DATA_ADDR >> 4), $0
+
+/*
+ * Parameters:
+ *   esi: start sector
+ *   ecx: number of sectors
+ */
+read_cdrom:
+       xorl    %eax, %eax
+
+       /* Number of blocks to read.  */
+       pushw   $CDBLK_LENG
+
+       /* Block number.  */
+       pushl   %eax
+       pushl   %esi
+
+       /* Buffer address.  */
+       pushw   $((DATA_ADDR - 0x400)>> 4)
+       pushl   %eax
+       pushw   $0x10
+
+       xorl    %edi, %edi
+       movw    %sp, %si
+
+1:
+       movw    0x10(%si), %di
+       cmpl    %ecx, %edi
+       jbe     2f
+       movl    %ecx, %edi
+
+2:
+       mov     %di, 2(%si)
+
+       pushl   %ecx
+
+       movb    $0x42, %ah
+       int     $0x13
+
+       jnc     3f
+
+       movb    $0x42, %ah              /* Try again.  */
+       int     $0x13
+
+       jnc     3f
+
+2:
+       shrw    $1, %di                 /* Reduce transfer size.  */
+       jz      cdrom_fail
+       movw    %di, 0x10(%si)
+       movw    %di, 2(%si)
+       movb    $0x42, %ah
+       int     $0x13
+       jc      2b
+
+3:
+
+       movw    %di, %ax
+       shlw    $(CDSEC_SHIFT - 4), %ax
+       addw    %ax, 6(%si)
+       addl    %edi, 8(%si)
+
+       popl    %ecx
+       subl    %edi, %ecx
+       jnz     1b
+
+       addw    $0x12, %sp
+       ret
+
+cdrom_fail:
+       movw    $(0x7C00 + err_cdfail_msg - start), %si
+
+fail:
+       movb    $0x0e, %ah
+       xorw    %bx, %bx
+1:
+       lodsb   (%si), %al
+       int     $0x10
+       cmpb    $0, %al
+       jne     1b
+1:     jmp     1b
+
+err_noboot_msg:
+       .ascii  "no boot info\0"
+
+err_cdfail_msg:
+       .ascii  "cdrom read fails\0"
+
+       . = start + 0x1FF
+
+       .byte   0
diff --git a/boot/i386/pc/diskboot.S b/boot/i386/pc/diskboot.S
new file mode 100644 (file)
index 0000000..95f87a0
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,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/>.
+ */
+
+#include <grub/machine/boot.h>
+       
+/*
+ *  defines for the code go here
+ */
+
+       /* Absolute addresses
+          This makes the assembler generate the address without support
+          from the linker. (ELF can't relocate 16-bit addresses!) */
+#define ABS(x) (x-_start+GRUB_BOOT_MACHINE_KERNEL_ADDR)
+       
+       /* Print message string */
+#define MSG(x) movw $ABS(x), %si; call message
+
+       .file   "diskboot.S"
+
+       .text
+
+       /* Tell GAS to generate 16-bit instructions so that this code works
+          in real mode. */
+       .code16
+
+       .globl  start, _start
+start:
+_start:        
+       /*
+        * _start is loaded at 0x2000 and is jumped to with
+        * CS:IP 0:0x2000 in kernel.
+        */
+
+       /* 
+        * we continue to use the stack for boot.img and assume that
+        * some registers are set to correct values. See boot.S
+        * for more information.
+        */
+       
+       /* save drive reference first thing! */
+       pushw   %dx
+
+       /* print a notification message on the screen */
+       pushw   %si
+       MSG(notification_string)
+       popw    %si
+       
+       /* this sets up for the first run through "bootloop" */
+       movw    $ABS(firstlist - GRUB_BOOT_MACHINE_LIST_SIZE), %di
+
+       /* save the sector number of the second sector in %ebp */
+       movl    (%di), %ebp
+
+        /* this is the loop for reading the rest of the kernel in */
+bootloop:
+
+       /* check the number of sectors to read */
+       cmpw    $0, 8(%di)
+
+       /* if zero, go to the start function */
+       je      bootit
+
+setup_sectors: 
+       /* check if we use LBA or CHS */
+       cmpb    $0, -1(%si)
+
+       /* jump to chs_mode if zero */
+       je      chs_mode
+
+lba_mode:      
+       /* load logical sector start */
+       movl    (%di), %ebx
+       movl    4(%di), %ecx
+
+       /* the maximum is limited to 0x7f because of Phoenix EDD */
+       xorl    %eax, %eax
+       movb    $0x7f, %al
+
+       /* how many do we really want to read? */
+       cmpw    %ax, 8(%di)     /* compare against total number of sectors */
+
+       /* which is greater? */
+       jg      1f
+
+       /* if less than, set to total */
+       movw    8(%di), %ax
+
+1:     
+       /* subtract from total */
+       subw    %ax, 8(%di)
+
+       /* add into logical sector start */
+       addl    %eax, (%di)
+       adcl    $0, 4(%di)
+
+       /* set up disk address packet */
+
+       /* the size and the reserved byte */
+       movw    $0x0010, (%si)
+
+       /* the number of sectors */
+       movw    %ax, 2(%si)
+
+       /* the absolute address */
+       movl    %ebx, 8(%si)
+       movl    %ecx, 12(%si)
+
+       /* the segment of buffer address */
+       movw    $GRUB_BOOT_MACHINE_BUFFER_SEG, 6(%si)
+
+       /* save %ax from destruction! */
+       pushw   %ax
+
+       /* the offset of buffer address */
+       movw    $0, 4(%si)
+
+/*
+ * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
+ *     Call with       %ah = 0x42
+ *                     %dl = drive number
+ *                     %ds:%si = segment:offset of disk address packet
+ *     Return:
+ *                     %al = 0x0 on success; err code on failure
+ */
+
+       movb    $0x42, %ah
+       int     $0x13
+
+       jc      read_error
+
+       movw    $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
+       jmp     copy_buffer
+                       
+chs_mode:      
+       /* load logical sector start (top half) */
+       movl    4(%di), %eax
+       orl     %eax, %eax
+       jnz     geometry_error
+
+       /* load logical sector start (bottom half) */
+       movl    (%di), %eax
+
+       /* zero %edx */
+       xorl    %edx, %edx
+
+       /* divide by number of sectors */
+       divl    (%si)
+
+       /* save sector start */
+       movb    %dl, 10(%si)
+
+       xorl    %edx, %edx      /* zero %edx */
+       divl    4(%si)          /* divide by number of heads */
+
+       /* save head start */
+       movb    %dl, 11(%si)
+
+       /* save cylinder start */
+       movw    %ax, 12(%si)
+
+       /* do we need too many cylinders? */
+       cmpw    8(%si), %ax
+       jge     geometry_error
+
+       /* determine the maximum sector length of this read */
+       movw    (%si), %ax      /* get number of sectors per track/head */
+
+       /* subtract sector start */
+       subb    10(%si), %al
+
+       /* how many do we really want to read? */
+       cmpw    %ax, 8(%di)     /* compare against total number of sectors */
+
+
+       /* which is greater? */
+       jg      2f
+
+       /* if less than, set to total */
+       movw    8(%di), %ax
+
+2:     
+       /* subtract from total */
+       subw    %ax, 8(%di)
+
+       /* add into logical sector start */
+       addl    %eax, (%di)
+       adcl    $0, 4(%di)
+
+/*
+ *  This is the loop for taking care of BIOS geometry translation (ugh!)
+ */
+
+       /* get high bits of cylinder */
+       movb    13(%si), %dl
+
+       shlb    $6, %dl         /* shift left by 6 bits */
+       movb    10(%si), %cl    /* get sector */
+
+       incb    %cl             /* normalize sector (sectors go
+                                       from 1-N, not 0-(N-1) ) */
+       orb     %dl, %cl        /* composite together */
+       movb    12(%si), %ch    /* sector+hcyl in cl, cylinder in ch */
+
+       /* restore %dx */
+       popw    %dx
+       pushw   %dx
+
+       /* head number */
+       movb    11(%si), %dh
+
+       pushw   %ax     /* save %ax from destruction! */
+
+/*
+ * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
+ *     Call with       %ah = 0x2
+ *                     %al = number of sectors
+ *                     %ch = cylinder
+ *                     %cl = sector (bits 6-7 are high bits of "cylinder")
+ *                     %dh = head
+ *                     %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
+ *                     %es:%bx = segment:offset of buffer
+ *     Return:
+ *                     %al = 0x0 on success; err code on failure
+ */
+
+       movw    $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
+       movw    %bx, %es        /* load %es segment with disk buffer */
+
+       xorw    %bx, %bx        /* %bx = 0, put it at 0 in the segment */
+       movb    $0x2, %ah       /* function 2 */
+       int     $0x13
+
+       jc      read_error
+
+       /* save source segment */
+       movw    %es, %bx
+       
+copy_buffer:   
+
+       /* load addresses for copy from disk buffer to destination */
+       movw    10(%di), %es    /* load destination segment */
+
+       /* restore %ax */
+       popw    %ax
+
+       /* determine the next possible destination address (presuming
+               512 byte sectors!) */
+       shlw    $5, %ax         /* shift %ax five bits to the left */
+       addw    %ax, 10(%di)    /* add the corrected value to the destination
+                                  address for next time */
+
+       /* save addressing regs */
+       pusha
+       pushw   %ds
+
+       /* get the copy length */
+       shlw    $3, %ax
+       movw    %ax, %cx
+
+       xorw    %di, %di        /* zero offset of destination addresses */
+       xorw    %si, %si        /* zero offset of source addresses */
+       movw    %bx, %ds        /* restore the source segment */
+
+       cld             /* sets the copy direction to forward */
+
+       /* perform copy */
+       rep             /* sets a repeat */
+       movsw           /* this runs the actual copy */
+
+       /* restore addressing regs and print a dot with correct DS 
+          (MSG modifies SI, which is saved, and unused AX and BX) */
+       popw    %ds
+       MSG(notification_step)
+       popa
+
+       /* check if finished with this dataset */
+       cmpw    $0, 8(%di)
+       jne     setup_sectors
+
+       /* update position to load from */
+       subw    $GRUB_BOOT_MACHINE_LIST_SIZE, %di
+
+       /* jump to bootloop */
+       jmp     bootloop
+
+/* END OF MAIN LOOP */
+
+bootit:
+       /* print a newline */
+       MSG(notification_done)
+       popw    %dx     /* this makes sure %dl is our "boot" drive */
+       ljmp    $0, $(GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
+
+
+/*
+ * BIOS Geometry translation error (past the end of the disk geometry!).
+ */
+geometry_error:
+       MSG(geometry_error_string)
+       jmp     general_error
+
+/*
+ * Read error on the disk.
+ */
+read_error:
+       MSG(read_error_string)
+
+general_error:
+       MSG(general_error_string)
+
+/* go here when you need to stop the machine hard after an error condition */
+stop:  jmp     stop
+
+notification_string:   .string "loading"
+
+notification_step:     .string "."
+notification_done:     .string "\r\n"
+       
+geometry_error_string: .string "Geom"
+read_error_string:     .string "Read"
+general_error_string:  .string " Error"
+
+/*
+ * message: write the string pointed to by %si
+ *
+ *   WARNING: trashes %si, %ax, and %bx
+ */
+
+       /*
+        * Use BIOS "int 10H Function 0Eh" to write character in teletype mode
+        *      %ah = 0xe       %al = character
+        *      %bh = page      %bl = foreground color (graphics modes)
+        */
+1:
+       movw    $0x0001, %bx
+       movb    $0xe, %ah
+       int     $0x10           /* display a byte */
+
+       incw    %si
+message:
+       movb    (%si), %al
+       cmpb    $0, %al
+       jne     1b      /* if not end of string, jmp to display */
+       ret
+lastlist:
+
+/*
+ *  This area is an empty space between the main body of code below which
+ *  grows up (fixed after compilation, but between releases it may change
+ *  in size easily), and the lists of sectors to read, which grows down
+ *  from a fixed top location.
+ */
+
+       .word 0
+       .word 0
+
+       . = _start + 0x200 - GRUB_BOOT_MACHINE_LIST_SIZE
+       
+        /* fill the first data listing with the default */
+blocklist_default_start:
+       /* this is the sector start parameter, in logical sectors from
+          the start of the disk, sector 0 */
+       .long 2, 0
+blocklist_default_len:
+       /* this is the number of sectors to read the command "install"
+          will fill this up */
+       .word 0
+blocklist_default_seg:
+       /* this is the segment of the starting address to load the data into */
+       .word (GRUB_BOOT_MACHINE_KERNEL_SEG + 0x20)
+       
+firstlist:     /* this label has to be after the list data!!! */
diff --git a/boot/i386/pc/lnxboot.S b/boot/i386/pc/lnxboot.S
new file mode 100644 (file)
index 0000000..e7f55df
--- /dev/null
@@ -0,0 +1,296 @@
+/* -*-Asm-*- */
+/*
+ *  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/>.
+ */
+
+#include <config.h>
+#include <grub/boot.h>
+#include <grub/machine/boot.h>
+#include <grub/machine/kernel.h>
+#include <multiboot.h>
+
+        .file   "lnxboot.S"
+
+#define CODE_ADDR      0x6000
+#define CODE_LENG      (code_end - start)
+#define DATA_ADDR      ((GRUB_BOOT_MACHINE_KERNEL_ADDR) + 0x200)
+
+#define BLCK_LENG      0x4000
+
+       .text
+
+        .code16
+
+        .globl  start, _start
+
+data_start:
+       xorl    %ebp, %ebp
+       jmp     linux_next
+
+       . = data_start + 0x1F1
+
+setup_sects:
+       .byte   (CODE_LENG >> 9)
+root_flags:
+       .word   0
+syssize:
+       .word   0
+swap_dev:
+       .word   0
+ram_size:
+       .word   0
+vid_mode:
+       .word   0
+root_dev:
+       .word   0
+boot_flag:
+       .word   0xAA55
+
+start:
+_start:
+
+       jmp linux_init
+
+       .ascii  "HdrS"                  /* Header signature.  */
+       .word   0x0203                  /* Header version number.  */
+
+realmode_swtch:
+       .word   0, 0                    /* default_switch, SETUPSEG.  */
+start_sys_seg:
+       .word   0x1000                  /* Obsolete.  */
+version_ptr:
+       .word   0                       /* Version string ptr.  */
+type_of_loader:
+       .byte   0                       /* Filled in by boot loader.  */
+loadflags:
+       .byte   1                       /* Please load high.  */
+setup_move_size:
+       .word   0                       /* Unused.  */
+code32_start:
+       .long   0x100000                /* 32-bit start address.  */
+ramdisk_image:
+       .long   0                       /* Loaded ramdisk image address.  */
+ramdisk_size:
+       .long   0                       /* Size of loaded ramdisk.  */
+bootsect_kludge:
+       .word   0, 0
+heap_end_ptr:
+       .word   0
+pad1:
+       .word   0
+cmd_line_ptr:
+       .long   0                       /* Command line.  */
+ramdisk_max:
+       .long   0xffffffff              /* Highest allowed ramdisk address.  */
+
+gdt:
+       .long   0, 0, 0, 0              /* Must be zero.  */
+       .word   0xffff                  /* 64 K segment size.  */
+gdt_src1:
+       .byte   0, 0 ,0                 /* Low 24 bits of source address.  */
+       .byte   0x93                    /* Access rights.  */
+       .byte   0                       /* Extended access rights.  */
+gdt_src2:
+       .byte   0                       /* High 8 bits of source address.  */
+       .word   0xffff                  /* 64 K segment size.  */
+gdt_dst1:
+       .byte   0, 0, 0                 /* Low 24 bits of target address.  */
+       .byte   0x93                    /* Access rights.  */
+       .byte   0                       /* Extended access rights.  */
+gdt_dst2:
+       .byte   0                       /* High 8 bits of source address.  */
+       .long   0, 0, 0, 0              /* More space for the BIOS.  */
+
+reg_edx:
+       .byte   0x80, 0, 0xFF, 0xFF
+
+data_leng:
+       .long   0
+
+linux_init:
+
+       movw    %cs:(reg_edx - start), %dx
+       movl    %cs:(code32_start - start), %ebp
+
+linux_next:
+
+       call    normalize
+
+normalize:
+       popw    %bx
+       subw    $(normalize - start), %bx
+       shrw    $4, %bx
+       movw    %cs, %ax
+       addw    %bx, %ax
+       pushw   %ax
+       pushw   $(real_code - start)
+       lret                            /* Jump to real_code.  */
+
+real_code:
+       subw    $0x20, %ax
+       movw    %ax, %ds
+       movw    (setup_sects - data_start), %cx
+       shlw    $7, %cx
+
+       /* Setup stack.  */
+
+       xorw    %si, %si
+       movw    %si, %ss
+       movw    $(CODE_ADDR), %sp
+
+       /* Move itself to 0:CODE_ADDR.  */
+
+       cld
+       movw    %cs, %ax
+       movw    %ax, %ds
+       movw    $(CODE_ADDR >> 4), %ax
+       movw    %ax, %es
+       movw    %si, %di
+
+       rep
+       movsl
+
+       ljmp    $(CODE_ADDR >> 4), $(real_code_2  - start)
+
+real_code_2:
+
+       xchgl   %ebp, %esi
+       orl     %esi, %esi
+       jnz     1f
+       movw    %ds, %si
+       shll    $4, %esi
+       addl    %ebp, %esi
+1:
+
+       pushw   %es
+       popw    %ds
+
+       movl    $0x200, %ecx
+       addl    %ecx, %esi
+       movl    $DATA_ADDR, %edi
+
+       call    move_memory
+
+       /* Check for multiboot signature.  */
+       cmpl    $MULTIBOOT_MAGIC, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_DATA_END)
+       jz      1f
+
+       movl    (ramdisk_image - start), %esi
+       movl    (ramdisk_size - start), %ecx
+       movl    $(DATA_ADDR - 0x200), %edi
+       jmp     2f
+
+1:
+
+       movl    %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE), %ecx
+       addl    $(GRUB_KERNEL_MACHINE_RAW_SIZE - 0x200), %ecx
+
+2:
+       call    move_memory
+
+       movsbl  %dh, %eax
+       movl    %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART)
+
+       movsbl  (reg_edx + 2 - start), %eax
+       movl    %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART)
+
+       movb    $0xFF, %dh
+
+       ljmp    $(DATA_ADDR >> 4), $0
+
+/*
+ * Parameters:
+ *   esi: source address
+ *   edi: target address
+ *   ecx: number of bytes
+ */
+
+move_memory:
+       incl    %ecx
+       andb    $0xFE, %cl
+       pushw   %dx
+1:
+       pushl   %esi
+       pushl   %edi
+       pushl   %ecx
+       cmpl    $BLCK_LENG, %ecx
+       jbe     2f
+       movl    $BLCK_LENG, %ecx
+2:
+       pushl   %ecx
+
+       movl    %esi, %eax
+       movw    %si, (gdt_src1 - start)
+       shrl    $16, %eax
+       movb    %al, (gdt_src1 + 2 - start)
+       movb    %ah, (gdt_src2 - start)
+
+       movl    %edi, %eax
+       movw    %di, (gdt_dst1 - start)
+       shrl    $16, %eax
+       movb    %al, (gdt_dst1 + 2 - start)
+       movb    %ah, (gdt_dst2 - start)
+
+       movw    $(gdt - start), %si
+       movb    $0x87, %ah
+       shrw    $1, %cx
+
+       int     $0x15
+
+       popl    %eax
+       popl    %ecx
+       popl    %edi
+       popl    %esi
+
+       jnc     2f
+       movw    $(err_int15_msg - start), %si
+       jmp     fail
+
+2:
+
+       addl    %eax, %esi
+       addl    %eax, %edi
+       subl    %eax, %ecx
+       jnz     1b
+
+
+       popw    %dx
+       ret
+
+/*
+ * Parameters:
+ *   si: message
+ */
+
+fail:
+       movb    $0x0e, %ah
+       xorw    %bx, %bx
+1:
+       lodsb   (%si), %al
+       int     $0x10
+       cmpb    $0, %al
+       jne     1b
+1:     jmp     1b
+
+err_int15_msg:
+       .ascii  "move memory fails\0"
+
+       . = (.  & (~0x1FF)) + 0x1FF
+
+       .byte   0
+
+code_end:
diff --git a/boot/i386/pc/pxeboot.S b/boot/i386/pc/pxeboot.S
new file mode 100644 (file)
index 0000000..4fdff76
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2000,2005,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/>.
+ */
+
+       .file   "pxeboot.S"
+       .text
+
+       /* Start with the prehistoric environment... */
+       .code16
+       
+       /* Let's go */
+.globl _start; _start:
+
+        /* Root drive will default to boot drive */
+        movb   $0xFF, %dh
+        movb   $0x7F, %dl
+        
+       /* Jump to the real world */
+       ljmp    $0, $0x8200
+
+       /* This region is a junk. Do you say that this is wasteful?
+          But I like that the memory layout of the body is consistent
+          among different kernels rather than scamping just for 1.5KB. */
+       . = _start + 0x8200 - 0x7C00 - 0x200 - 1
+       .byte   0
diff --git a/bus/pci.c b/bus/pci.c
new file mode 100644 (file)
index 0000000..2c29c03
--- /dev/null
+++ b/bus/pci.c
@@ -0,0 +1,66 @@
+/* pci.c - Generic PCI interfaces.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/pci.h>
+
+grub_pci_address_t
+grub_pci_make_address (int bus, int device, int function, int reg)
+{
+  return (1 << 31) | (bus << 16) | (device << 11) | (function << 8) | (reg << 2);
+}
+
+void
+grub_pci_iterate (grub_pci_iteratefunc_t hook)
+{
+  int bus;
+  int dev;
+  int func;
+  grub_pci_address_t addr;
+  grub_pci_id_t id;
+  grub_uint32_t hdr;
+
+  for (bus = 0; bus < 256; bus++)
+    {
+      for (dev = 0; dev < 32; dev++)
+       {
+         for (func = 0; func < 8; func++)
+           {
+             addr = grub_pci_make_address (bus, dev, func, 0);
+             id = grub_pci_read (addr);
+
+             /* Check if there is a device present.  */
+             if (id >> 16 == 0xFFFF)
+               continue;
+
+             if (hook (bus, dev, func, id))
+               return;
+
+             /* Probe only func = 0 if the device if not multifunction */
+             if (func == 0)
+               {
+                 addr = grub_pci_make_address (bus, dev, func, 3);
+                 hdr = grub_pci_read (addr);
+                 if (!(hdr & 0x800000))
+                   break;
+               }
+           }
+       }
+    }
+}
diff --git a/bus/usb/ohci.c b/bus/usb/ohci.c
new file mode 100644 (file)
index 0000000..d2e78d4
--- /dev/null
@@ -0,0 +1,608 @@
+/* ohci.c - OHCI Support.  */
+/*
+ *  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/dl.h>
+#include <grub/mm.h>
+#include <grub/usb.h>
+#include <grub/usbtrans.h>
+#include <grub/misc.h>
+#include <grub/pci.h>
+#include <grub/cpu/pci.h>
+#include <grub/i386/io.h>
+#include <grub/time.h>
+
+struct grub_ohci_hcca
+{
+  /* Pointers to Interrupt Endpoint Descriptors.  Not used by
+     GRUB.  */
+  grub_uint32_t inttable[32];
+
+  /* Current frame number.  */
+  grub_uint16_t framenumber;
+
+  grub_uint16_t pad;
+
+  /* List of completed TDs.  */
+  grub_uint32_t donehead;
+
+  grub_uint8_t reserved[116];
+} __attribute__((packed));
+
+/* OHCI Endpoint Descriptor.  */
+struct grub_ohci_ed
+{
+  grub_uint32_t target;
+  grub_uint32_t td_tail;
+  grub_uint32_t td_head;
+  grub_uint32_t next_ed;
+} __attribute__((packed));
+
+struct grub_ohci_td
+{
+  /* Information used to construct the TOKEN packet.  */
+  grub_uint32_t token;
+
+  grub_uint32_t buffer;
+  grub_uint32_t next_td;
+  grub_uint32_t buffer_end;
+} __attribute__((packed));
+
+typedef struct grub_ohci_td *grub_ohci_td_t;
+typedef struct grub_ohci_ed *grub_ohci_ed_t;
+
+struct grub_ohci
+{
+  volatile grub_uint32_t *iobase;
+  volatile struct grub_ohci_hcca *hcca;
+  struct grub_ohci *next;
+};
+
+static struct grub_ohci *ohci;
+
+typedef enum
+{
+  GRUB_OHCI_REG_REVISION = 0x00,
+  GRUB_OHCI_REG_CONTROL,
+  GRUB_OHCI_REG_CMDSTATUS,
+  GRUB_OHCI_REG_INTSTATUS,
+  GRUB_OHCI_REG_INTENA,
+  GRUB_OHCI_REG_INTDIS,
+  GRUB_OHCI_REG_HCCA,
+  GRUB_OHCI_REG_PERIODIC,
+  GRUB_OHCI_REG_CONTROLHEAD,
+  GRUB_OHCI_REG_CONTROLCURR,
+  GRUB_OHCI_REG_BULKHEAD,
+  GRUB_OHCI_REG_BULKCURR,
+  GRUB_OHCI_REG_DONEHEAD,
+  GRUB_OHCI_REG_FRAME_INTERVAL,
+  GRUB_OHCI_REG_RHUBA = 18,
+  GRUB_OHCI_REG_RHUBPORT = 21
+} grub_ohci_reg_t;
+
+static grub_uint32_t
+grub_ohci_readreg32 (struct grub_ohci *o, grub_ohci_reg_t reg)
+{
+  return grub_le_to_cpu32 (*(o->iobase + reg));
+}
+
+static void
+grub_ohci_writereg32 (struct grub_ohci *o,
+                     grub_ohci_reg_t reg, grub_uint32_t val)
+{
+  *(o->iobase + reg) = grub_cpu_to_le32 (val);
+}
+
+\f
+
+/* Iterate over all PCI devices.  Determine if a device is an OHCI
+   controller.  If this is the case, initialize it.  */
+static int grub_ohci_pci_iter (int bus, int device, int func,
+                              grub_pci_id_t pciid __attribute__((unused)))
+{
+  grub_uint32_t class;
+  grub_uint32_t subclass;
+  int interf;
+  grub_uint32_t base;
+  grub_pci_address_t addr;
+  struct grub_ohci *o;
+  grub_uint32_t revision;
+  grub_uint32_t frame_interval;
+
+  addr = grub_pci_make_address (bus, device, func, 2);
+  class = grub_pci_read (addr);
+  addr = grub_pci_make_address (bus, device, func, 2);
+  class = grub_pci_read (addr);
+
+  interf = class & 0xFF;
+  subclass = (class >> 16) & 0xFF;
+  class >>= 24;
+
+  /* If this is not an OHCI controller, just return.  */
+  if (class != 0x0c || subclass != 0x03)
+    return 0;
+
+  /* Determine IO base address.  */
+  addr = grub_pci_make_address (bus, device, func, 4);
+  base = grub_pci_read (addr);
+
+#if 0
+  /* Stop if there is no IO space base address defined.  */
+  if (! (base & 1))
+    return 0;
+#endif
+
+  /* Allocate memory for the controller and register it.  */
+  o = grub_malloc (sizeof (*o));
+  if (! o)
+    return 1;
+
+  /* Link in the OHCI.  */
+  o->next = ohci;
+  ohci = o;
+  o->iobase = (grub_uint32_t *) base;
+
+  /* Reserve memory for the HCCA.  */
+  o->hcca = (struct grub_ohci_hcca *) grub_memalign (256, 256);
+
+  /* Check if the OHCI revision is actually 1.0 as supported.  */
+  revision = grub_ohci_readreg32 (o, GRUB_OHCI_REG_REVISION);
+  grub_dprintf ("ohci", "OHCI revision=0x%02x\n", revision & 0xFF);
+  if ((revision & 0xFF) != 0x10)
+    goto fail;
+
+  /* Backup the frame interval register.  */
+  frame_interval = grub_ohci_readreg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL);
+
+  /* Suspend the OHCI by issuing a reset.  */
+  grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic.
+                                                         */
+  grub_millisleep (1);
+  grub_dprintf ("ohci", "OHCI reset\n");
+
+  /* Restore the frame interval register.  */
+  grub_ohci_writereg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL, frame_interval);
+
+  /* Setup the HCCA.  */
+  grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, (grub_uint32_t) o->hcca);
+  grub_dprintf ("ohci", "OHCI HCCA\n");
+  /* Enable the OHCI.  */
+  grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL,
+                       (2 << 6));
+  grub_dprintf ("ohci", "OHCI enable: 0x%02x\n",
+               (grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL) >> 6) & 3);
+  return 0;
+
+ fail:
+  if (o)
+    grub_free ((void *) o->hcca);
+  grub_free (o);
+
+  return 1;
+}
+
+
+static void
+grub_ohci_inithw (void)
+{
+  grub_pci_iterate (grub_ohci_pci_iter);
+}
+
+\f
+
+static int
+grub_ohci_iterate (int (*hook) (grub_usb_controller_t dev))
+{
+  struct grub_ohci *o;
+  struct grub_usb_controller dev;
+
+  for (o = ohci; o; o = o->next)
+    {
+      dev.data = o;
+      if (hook (&dev))
+       return 1;
+    }
+
+  return 0;
+}
+
+static void
+grub_ohci_transaction (grub_ohci_td_t td, 
+                      grub_transfer_type_t type, unsigned int toggle,
+                      grub_size_t size, char *data)
+{
+  grub_uint32_t token;
+  grub_uint32_t buffer;
+  grub_uint32_t buffer_end;
+
+ grub_dprintf ("ohci", "OHCI transaction td=0x%02x type=%d, toggle=%d, size=%d\n",
+              td, type, toggle, size);
+  switch (type)
+    {
+    case GRUB_USB_TRANSFER_TYPE_SETUP:
+      token = 0 << 19;
+      break;
+    case GRUB_USB_TRANSFER_TYPE_IN:
+      token = 2 << 19;
+      break;
+    case GRUB_USB_TRANSFER_TYPE_OUT:
+      token = 1 << 19;
+      break;
+    default:
+      token = 0;
+      break;
+    }
+
+  /* Generate no interrupts.  */
+  token |= 7 << 21;
+
+  /* Set the token.  */
+  token |= toggle << 24;
+  token |= 1 << 25;
+
+  buffer = (grub_uint32_t) data;
+  buffer_end = buffer + size - 1;
+
+  td->token = grub_cpu_to_le32 (token);
+  td->buffer = grub_cpu_to_le32 (buffer);
+  td->next_td = 0;
+  td->buffer_end = grub_cpu_to_le32 (buffer_end);
+}
+
+static grub_usb_err_t
+grub_ohci_transfer (grub_usb_controller_t dev,
+                   grub_usb_transfer_t transfer)
+{
+  struct grub_ohci *o = (struct grub_ohci *) dev->data;
+  grub_ohci_ed_t ed;
+  grub_ohci_td_t td_list;
+  grub_uint32_t target;
+  grub_uint32_t td_tail;
+  grub_uint32_t td_head;
+  grub_uint32_t status;
+  grub_uint32_t control;
+  grub_usb_err_t err;
+  int i;
+
+  /* Allocate an Endpoint Descriptor.  */
+  ed = grub_memalign (16, sizeof (*ed));
+  if (! ed)
+    return GRUB_USB_ERR_INTERNAL;
+
+  td_list = grub_memalign (16, sizeof (*td_list) * (transfer->transcnt + 1));
+  if (! td_list)
+    {
+      grub_free ((void *) ed);
+      return GRUB_USB_ERR_INTERNAL;
+    }
+
+  grub_dprintf ("ohci", "alloc=0x%08x\n", td_list);
+
+  /* Setup all Transfer Descriptors.  */
+  for (i = 0; i < transfer->transcnt; i++)
+    {
+      grub_usb_transaction_t tr = &transfer->transactions[i];
+
+      grub_ohci_transaction (&td_list[i], tr->pid, tr->toggle,
+                            tr->size, tr->data); 
+
+      td_list[i].next_td = grub_cpu_to_le32 (&td_list[i + 1]);
+    }
+
+  /* Setup the Endpoint Descriptor.  */
+
+  /* Set the device address.  */
+  target = transfer->devaddr;
+
+  /* Set the endpoint.  */
+  target |= transfer->endpoint << 7;
+
+  /* Set the device speed.  */
+  target |= (transfer->dev->speed == GRUB_USB_SPEED_LOW) << 13;
+
+  /* Set the maximum packet size.  */
+  target |= transfer->max << 16;
+
+  td_head = (grub_uint32_t) td_list;
+
+  td_tail = (grub_uint32_t) &td_list[transfer->transcnt];
+
+  ed->target = grub_cpu_to_le32 (target);
+  ed->td_head = grub_cpu_to_le32 (td_head);
+  ed->td_tail = grub_cpu_to_le32 (td_tail);
+  ed->next_ed = grub_cpu_to_le32 (0);
+
+  grub_dprintf ("ohci", "program OHCI\n");
+
+  /* Program the OHCI to actually transfer.  */
+  switch (transfer->type)
+    {
+    case GRUB_USB_TRANSACTION_TYPE_BULK:
+      {
+       grub_dprintf ("ohci", "add to bulk list\n");
+
+       status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
+       control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL);
+
+       /* Disable the Control and Bulk lists.  */
+       control &= ~(3 << 4);
+       grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
+
+       /* Clear BulkListFilled.  */
+       status &= ~(1 << 2);
+       grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
+
+       grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, (grub_uint32_t) ed);
+
+       /* Enable the Bulk list.  */
+       control |= 1 << 5;
+       grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
+
+       /* Set BulkListFilled.  */
+       status |= 1 << 2;
+       grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
+
+       break;
+      }
+
+    case GRUB_USB_TRANSACTION_TYPE_CONTROL:
+      {
+       grub_dprintf ("ohci", "add to control list\n");
+       status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
+       control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL);
+
+       /* Disable the Control and Bulk lists.  */
+       control &= ~(3 << 4);
+       grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
+
+       /* Clear ControlListFilled.  */
+       status &= ~(1 << 1);
+       grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
+
+       grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD,
+                             (grub_uint32_t) ed);
+       grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD+1,
+                             (grub_uint32_t) ed);
+
+       /* Enable the Control list.  */
+       control |= 1 << 4;
+       grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
+
+       /* Set ControlListFilled.  */
+       status |= 1 << 1;
+       grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
+       break;
+      }
+    }
+
+  grub_dprintf ("ohci", "wait for completion\n");
+  grub_dprintf ("ohci", "control=0x%02x status=0x%02x\n",
+               grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL),
+               grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS));
+
+  /* Wait until the transfer is completed or STALLs.  */
+  while ((ed->td_head & ~0xf) != (ed->td_tail & ~0xf))
+    {
+      grub_cpu_idle ();
+
+      grub_dprintf ("ohci", "head=0x%02x tail=0x%02x\n", ed->td_head, ed->td_tail);
+
+      /* Detected a STALL.  */
+      if (ed->td_head & 1)
+       break;
+    }
+
+  grub_dprintf ("ohci", "complete\n");
+
+/*   if (ed->td_head & 1) */
+/*     err = GRUB_USB_ERR_STALL; */
+/*   else if (ed->td */
+
+
+  if (ed->td_head & 1)
+    {
+      grub_uint8_t errcode;
+      grub_ohci_td_t tderr;
+
+      tderr = (grub_ohci_td_t) grub_ohci_readreg32 (o,
+                                                   GRUB_OHCI_REG_DONEHEAD);
+      errcode = tderr->token >> 28;
+
+      switch (errcode)
+       {
+       case 0:
+         /* XXX: Should not happen!  */
+         grub_error (GRUB_ERR_IO, "OHCI without reporting the reason");
+         err = GRUB_USB_ERR_INTERNAL;
+         break;
+
+       case 1:
+         /* XXX: CRC error.  */
+         err = GRUB_USB_ERR_TIMEOUT;
+         break;
+
+       case 2:
+         err = GRUB_USB_ERR_BITSTUFF;
+         break;
+
+       case 3:
+         /* XXX: Data Toggle error.  */
+         err = GRUB_USB_ERR_DATA;
+         break;
+
+       case 4:
+         err = GRUB_USB_ERR_STALL;
+         break;
+
+       case 5:
+         /* XXX: Not responding.  */
+         err = GRUB_USB_ERR_TIMEOUT;
+         break;
+
+       case 6:
+         /* XXX: PID Check bits failed.  */
+         err = GRUB_USB_ERR_BABBLE;
+         break;
+
+       case 7:
+         /* XXX: PID unexpected failed.  */
+         err = GRUB_USB_ERR_BABBLE;
+         break;
+
+       case 8:
+         /* XXX: Data overrun error.  */
+         err = GRUB_USB_ERR_DATA;
+         break;
+
+       case 9:
+         /* XXX: Data underrun error.  */
+         err = GRUB_USB_ERR_DATA;
+         break;
+
+       case 10:
+         /* XXX: Reserved.  */
+         err = GRUB_USB_ERR_NAK;
+         break;
+
+       case 11:
+         /* XXX: Reserved.  */
+         err = GRUB_USB_ERR_NAK;
+         break;
+
+       case 12:
+         /* XXX: Buffer overrun.  */
+         err = GRUB_USB_ERR_DATA;
+         break;
+
+       case 13:
+         /* XXX: Buffer underrun.  */
+         err = GRUB_USB_ERR_DATA;
+         break;
+
+       default:
+         err = GRUB_USB_ERR_NAK;
+         break;
+       }
+    }
+  else
+    err = GRUB_USB_ERR_NONE;
+
+  /* Disable the Control and Bulk lists.  */
+  control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL);
+  control &= ~(3 << 4);
+  grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control);
+
+  /* Clear BulkListFilled and ControlListFilled.  */
+  status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
+  status &= ~((1 << 2) | (1 << 3));
+  grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status);
+
+  /* XXX */
+  grub_free (td_list);
+  grub_free (ed);
+
+  return err;
+}
+
+static grub_err_t
+grub_ohci_portstatus (grub_usb_controller_t dev,
+                     unsigned int port, unsigned int enable)
+{
+   struct grub_ohci *o = (struct grub_ohci *) dev->data;
+   grub_uint32_t status;
+
+   /* Reset the port.  */
+   status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
+   status |= (1 << 4); /* XXX: Magic.  */
+   grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, status);
+   grub_millisleep (100);
+
+   /* End the reset signaling.  */
+   status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
+   status |= (1 << 20); /* XXX: Magic.  */
+   grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, status);
+   grub_millisleep (10);
+
+   /* Enable the port.  */
+   status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
+   status |= (enable << 1); /* XXX: Magic.  */
+   grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, status);
+
+   status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
+   grub_dprintf ("ohci", "portstatus=0x%02x\n", status);
+
+   return GRUB_ERR_NONE;
+}
+
+static grub_usb_speed_t
+grub_ohci_detect_dev (grub_usb_controller_t dev, int port)
+{
+   struct grub_ohci *o = (struct grub_ohci *) dev->data;
+   grub_uint32_t status;
+
+   status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
+
+   grub_dprintf ("ohci", "detect_dev status=0x%02x\n", status);
+
+   if (! (status & 1))
+     return GRUB_USB_SPEED_NONE;
+   else if (status & (1 << 9))
+     return GRUB_USB_SPEED_LOW;
+   else
+     return GRUB_USB_SPEED_FULL;
+}
+
+static int
+grub_ohci_hubports (grub_usb_controller_t dev)
+{
+  struct grub_ohci *o = (struct grub_ohci *) dev->data;
+  grub_uint32_t portinfo;
+
+  portinfo = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBA);
+
+  grub_dprintf ("ohci", "root hub ports=%d\n", portinfo & 0xFF);
+
+  /* The root hub has exactly two ports.  */
+  return portinfo & 0xFF;
+}
+
+
+\f
+static struct grub_usb_controller_dev usb_controller =
+{
+  .name = "ohci",
+  .iterate = grub_ohci_iterate,
+  .transfer = grub_ohci_transfer,
+  .hubports = grub_ohci_hubports,
+  .portstatus = grub_ohci_portstatus,
+  .detect_dev = grub_ohci_detect_dev
+};
+
+GRUB_MOD_INIT(ohci)
+{
+  grub_ohci_inithw ();
+  grub_usb_controller_dev_register (&usb_controller);
+}
+
+GRUB_MOD_FINI(ohci)
+{
+  grub_usb_controller_dev_unregister (&usb_controller);  
+}
diff --git a/bus/usb/uhci.c b/bus/usb/uhci.c
new file mode 100644 (file)
index 0000000..c59c0ca
--- /dev/null
@@ -0,0 +1,675 @@
+/* uhci.c - UHCI Support.  */
+/*
+ *  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/dl.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/usb.h>
+#include <grub/usbtrans.h>
+#include <grub/pci.h>
+#include <grub/cpu/pci.h>
+#include <grub/i386/io.h>
+#include <grub/time.h>
+
+#define GRUB_UHCI_IOMASK       (0x7FF << 5)
+
+typedef enum
+  {
+    GRUB_UHCI_REG_USBCMD = 0x00,
+    GRUB_UHCI_REG_FLBASEADD = 0x08,
+    GRUB_UHCI_REG_PORTSC1 = 0x10,
+    GRUB_UHCI_REG_PORTSC2 = 0x12
+  } grub_uhci_reg_t;
+
+#define GRUB_UHCI_LINK_TERMINATE       1
+#define GRUB_UHCI_LINK_QUEUE_HEAD      2
+
+
+/* UHCI Queue Head.  */
+struct grub_uhci_qh
+{
+  /* Queue head link pointer which points to the next queue head.  */
+  grub_uint32_t linkptr;
+
+  /* Queue element link pointer which points to the first data object
+     within the queue.  */
+  grub_uint32_t elinkptr;
+
+  /* Queue heads are aligned on 16 bytes, pad so a queue head is 16
+     bytes so we can store many in a 4K page.  */
+  grub_uint8_t pad[8];
+} __attribute__ ((packed));
+
+/* UHCI Tranfer Descriptor.  */
+struct grub_uhci_td
+{
+  /* Pointer to the next TD in the list.  */
+  grub_uint32_t linkptr;
+
+  /* Control and status bits.  */
+  grub_uint32_t ctrl_status;
+
+  /* All information required to transfer the Token packet.  */
+  grub_uint32_t token;
+
+  /* A pointer to the data buffer, UHCI requires this pointer to be 32
+     bits.  */
+  grub_uint32_t buffer;
+
+  /* Another linkptr that is not overwritten by the Host Controller.
+     This is GRUB specific.  */
+  grub_uint32_t linkptr2;
+
+  /* 3 additional 32 bits words reserved for the Host Controller Driver.  */
+  grub_uint32_t data[3];
+} __attribute__ ((packed));
+
+typedef volatile struct grub_uhci_td *grub_uhci_td_t;
+typedef volatile struct grub_uhci_qh *grub_uhci_qh_t;
+
+struct grub_uhci
+{
+  int iobase;
+  grub_uint32_t *framelist;
+
+  /* 256 Queue Heads.  */
+  grub_uhci_qh_t qh;
+
+  /* 256 Transfer Descriptors.  */
+  grub_uhci_td_t td;
+
+  /* Free Transfer Descriptors.  */
+  grub_uhci_td_t tdfree;
+
+  struct grub_uhci *next;
+};
+
+static struct grub_uhci *uhci;
+
+static grub_uint16_t
+grub_uhci_readreg16 (struct grub_uhci *u, grub_uhci_reg_t reg)
+{
+  return grub_inw (u->iobase + reg);
+}
+
+#if 0
+static grub_uint32_t
+grub_uhci_readreg32 (struct grub_uhci *u, grub_uhci_reg_t reg)
+{
+  return grub_inl (u->iobase + reg);
+}
+#endif
+
+static void
+grub_uhci_writereg16 (struct grub_uhci *u,
+                     grub_uhci_reg_t reg, grub_uint16_t val)
+{
+  grub_outw (val, u->iobase + reg);
+}
+
+static void
+grub_uhci_writereg32 (struct grub_uhci *u,
+                   grub_uhci_reg_t reg, grub_uint32_t val)
+{
+  grub_outl (val, u->iobase + reg);
+}
+
+static grub_err_t
+grub_uhci_portstatus (grub_usb_controller_t dev,
+                     unsigned int port, unsigned int enable);
+
+
+/* Iterate over all PCI devices.  Determine if a device is an UHCI
+   controller.  If this is the case, initialize it.  */
+static int grub_uhci_pci_iter (int bus, int device, int func,
+                              grub_pci_id_t pciid __attribute__((unused)))
+{
+  grub_uint32_t class;
+  grub_uint32_t subclass;
+  grub_uint32_t base;
+  grub_uint32_t fp;
+  grub_pci_address_t addr;
+  struct grub_uhci *u;
+  int i;
+
+  addr = grub_pci_make_address (bus, device, func, 2);
+  class = grub_pci_read (addr);
+  addr = grub_pci_make_address (bus, device, func, 2);
+  class = grub_pci_read (addr);
+
+  subclass = (class >> 16) & 0xFF;
+  class >>= 24;
+
+  /* If this is not an UHCI controller, just return.  */
+  if (class != 0x0c || subclass != 0x03)
+    return 0;
+
+  /* Determine IO base address.  */
+  addr = grub_pci_make_address (bus, device, func, 8);
+  base = grub_pci_read (addr);
+  /* Stop if there is no IO space base address defined.  */
+  if (! (base & 1))
+    return 0;
+
+  /* Allocate memory for the controller and register it.  */
+  u = grub_malloc (sizeof (*u));
+  if (! u)
+    return 1;
+
+  u->next = uhci;
+  uhci = u;
+  u->iobase = base & GRUB_UHCI_IOMASK;
+  u->framelist = 0;
+  u->qh = 0;
+  u->td = 0;
+  grub_dprintf ("uhci", "class=0x%02x 0x%02x base=0x%x\n",
+               class, subclass, u->iobase);
+
+  /* Reserve a page for the frame list.  */
+  u->framelist = grub_memalign (4096, 4096);
+  if (! u->framelist)
+    goto fail;
+
+  /* The framelist pointer of UHCI is only 32 bits, make sure this
+     code works on on 64 bits architectures.  */
+#if GRUB_CPU_SIZEOF_VOID_P == 8
+  if ((grub_uint64_t) u->framelist >> 32)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY,
+                 "allocated frame list memory not <4GB");
+      goto fail;
+    }
+#endif
+
+  /* The QH pointer of UHCI is only 32 bits, make sure this
+     code works on on 64 bits architectures.  */
+  u->qh = (grub_uhci_qh_t) grub_memalign (4096, 4096);
+  if (! u->qh)
+    goto fail;
+
+#if GRUB_CPU_SIZEOF_VOID_P == 8
+  if ((grub_uint64_t) u->qh >> 32)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, "allocated QH memory not <4GB");
+      goto fail;
+    }
+#endif
+
+  /* The TD pointer of UHCI is only 32 bits, make sure this
+     code works on on 64 bits architectures.  */
+  u->td = (grub_uhci_td_t) grub_memalign (4096, 4096*2);
+  if (! u->td)
+    goto fail;
+
+#if GRUB_CPU_SIZEOF_VOID_P == 8
+  if ((grub_uint64_t) u->td >> 32)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, "allocated TD memory not <4GB");
+      goto fail;
+    }
+#endif
+
+  /* Link all Transfer Descriptors in a list of available Transfer
+     Descriptors.  */
+  for (i = 0; i < 256; i++)
+    u->td[i].linkptr = (grub_uint32_t) &u->td[i + 1];
+  u->td[255 - 1].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.  */
+  fp = (grub_uint32_t) u->qh & (~15);
+  /* Mark this as a queue head.  */
+  fp |= 2;
+  for (i = 0; i < 1024; i++)
+    u->framelist[i] = fp;
+  /* Program the framelist address into the UHCI controller.  */
+  grub_uhci_writereg32 (u, GRUB_UHCI_REG_FLBASEADD,
+                       (grub_uint32_t) u->framelist);
+
+  /* Make the Queue Heads point to eachother.  */
+  for (i = 0; i < 256; i++)
+    {
+      /* Point to the next QH.  */
+      u->qh[i].linkptr = (grub_uint32_t) (&u->qh[i + 1]) & (~15);
+
+      /* This is a QH.  */
+      u->qh[i].linkptr |= GRUB_UHCI_LINK_QUEUE_HEAD;
+
+      /* For the moment, do not point to a Transfer Descriptor.  These
+        are set at transfer time, so just terminate it.  */
+      u->qh[i].elinkptr = 1;
+    }
+
+  /* The last Queue Head should terminate.  256 are too many QHs so
+     just use 50.  */
+  u->qh[50 - 1].linkptr = 1;
+
+  /* Enable UHCI again.  */
+  grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 1 | (1 << 7));
+
+  /* UHCI is initialized and ready for transfers.  */
+  grub_dprintf ("uhci", "UHCI initialized\n");
+
+
+#if 0
+  {
+    int i;
+    for (i = 0; i < 10; i++)
+      {
+       grub_uint16_t frnum;
+
+       frnum = grub_uhci_readreg16 (u, 6);
+       grub_dprintf ("uhci", "Framenum=%d\n", frnum);
+       grub_millisleep (100);
+      }
+  }
+#endif
+
+  return 0;
+
+ fail:
+  if (u)
+    {
+      grub_free ((void *) u->qh);
+      grub_free (u->framelist);
+    }
+  grub_free (u);
+
+  return 1;
+}
+
+static void
+grub_uhci_inithw (void)
+{
+  grub_pci_iterate (grub_uhci_pci_iter);
+}
+
+static grub_uhci_td_t
+grub_alloc_td (struct grub_uhci *u)
+{
+  grub_uhci_td_t ret;
+
+  /* Check if there is a Transfer Descriptor available.  */
+  if (! u->tdfree)
+    return NULL;
+
+  ret = u->tdfree;
+  u->tdfree = (grub_uhci_td_t) u->tdfree->linkptr;
+
+  return ret;
+}
+
+static void
+grub_free_td (struct grub_uhci *u, grub_uhci_td_t td)
+{
+  td->linkptr = (grub_uint32_t) u->tdfree;
+  u->tdfree = td;
+}
+
+static void
+grub_free_queue (struct grub_uhci *u, grub_uhci_td_t td)
+{
+  /* Free the TDs in this queue.  */
+  while (td)
+    {
+      grub_uhci_td_t tdprev;
+
+      /* Unlink the queue.  */
+      tdprev = td;
+      td = (grub_uhci_td_t) td->linkptr2;
+
+      /* Free the TD.  */
+      grub_free_td (u, tdprev);
+    }
+}
+
+static grub_uhci_qh_t
+grub_alloc_qh (struct grub_uhci *u,
+              grub_transaction_type_t tr __attribute__((unused)))
+{
+  int i;
+  grub_uhci_qh_t qh;
+
+  /* Look for a Queue Head for this transfer.  Skip the first QH if
+     this is a Interrupt Transfer.  */
+#if 0
+  if (tr == GRUB_USB_TRANSACTION_TYPE_INTERRUPT)
+    i = 0;
+  else
+#endif
+    i = 1;
+
+  for (; i < 255; i++)
+    {
+      if (u->qh[i].elinkptr & 1)
+       break;
+    }
+  qh = &u->qh[i];
+  if (! (qh->elinkptr & 1))
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY,
+                 "no free queue heads available");
+      return NULL;
+    }
+
+  return qh;
+}
+
+static grub_uhci_td_t
+grub_uhci_transaction (struct grub_uhci *u, unsigned int endp,
+                      grub_transfer_type_t type, unsigned int addr,
+                      unsigned int toggle, grub_size_t size,
+                      char *data)
+{
+  grub_uhci_td_t td;
+  static const unsigned int tf[] = { 0x69, 0xE1, 0x2D };
+
+  /* XXX: Check if data is <4GB.  If it isn't, just copy stuff around.
+     This is only relevant for 64 bits architectures.  */
+
+  /* Grab a free Transfer Descriptor and initialize it.  */
+  td = grub_alloc_td (u);
+  if (! td)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY,
+                 "no transfer descriptors available for UHCI transfer");
+      return 0;
+    }
+
+  grub_dprintf ("uhci",
+               "transaction: endp=%d, type=%d, addr=%d, toggle=%d, size=%d data=%p td=%p\n",
+               endp, type, addr, toggle, size, data, td);
+
+  /* Don't point to any TD, just terminate.  */
+  td->linkptr = 1;
+
+  /* Active!  Only retry a transfer 3 times.  */
+  td->ctrl_status = (1 << 23) | (3 << 27);
+
+  /* If zero bytes are transmitted, size is 0x7FF.  Otherwise size is
+     size-1.  */
+  if (size == 0)
+    size = 0x7FF;
+  else
+    size = size - 1;
+
+  /* Setup whatever is required for the token packet.  */
+  td->token = ((size << 21) | (toggle << 19) | (endp << 15)
+              | (addr << 8) | tf[type]);
+
+  td->buffer = (grub_uint32_t) data;
+
+  return td;
+}
+
+static grub_usb_err_t
+grub_uhci_transfer (grub_usb_controller_t dev,
+                   grub_usb_transfer_t transfer)
+{
+  struct grub_uhci *u = (struct grub_uhci *) dev->data;
+  grub_uhci_qh_t qh;
+  grub_uhci_td_t td;
+  grub_uhci_td_t td_first = NULL;
+  grub_uhci_td_t td_prev = NULL;
+  grub_usb_err_t err = GRUB_USB_ERR_NONE;
+  int i;
+
+  /* Allocate a queue head for the transfer queue.  */
+  qh = grub_alloc_qh (u, GRUB_USB_TRANSACTION_TYPE_CONTROL);
+  if (! qh)
+    return grub_errno;
+
+  for (i = 0; i < transfer->transcnt; i++)
+    {
+      grub_usb_transaction_t tr = &transfer->transactions[i];
+
+      td = grub_uhci_transaction (u, transfer->endpoint, tr->pid,
+                                 transfer->devaddr, tr->toggle,
+                                 tr->size, tr->data); 
+      if (! td)
+       {
+         /* Terminate and free.  */
+         td_prev->linkptr2 = 0;
+         td_prev->linkptr = 1;
+
+         if (td_first)
+           grub_free_queue (u, td_first);
+
+         return GRUB_USB_ERR_INTERNAL;
+       }
+
+      if (! td_first)
+       td_first = td;
+      else
+       {
+         td_prev->linkptr2 = (grub_uint32_t) td;
+         td_prev->linkptr = (grub_uint32_t) td;
+         td_prev->linkptr |= 4;
+       }
+      td_prev = td;
+    }
+  td_prev->linkptr2 = 0;
+  td_prev->linkptr = 1;
+
+  grub_dprintf ("uhci", "setup transaction %d\n", transfer->type);
+
+  /* Link it into the queue and terminate.  Now the transaction can
+     take place.  */
+  qh->elinkptr = (grub_uint32_t) td_first;
+
+  grub_dprintf ("uhci", "initiate transaction\n");
+
+  /* Wait until either the transaction completed or an error
+     occured.  */
+  for (;;)
+    {
+      grub_uhci_td_t errtd;
+
+      errtd = (grub_uhci_td_t) (qh->elinkptr & ~0x0f);
+
+      grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p\n",
+                   errtd->ctrl_status, errtd->buffer & (~15), errtd);
+
+      /* Check if the transaction completed.  */
+      if (qh->elinkptr & 1)
+       break;
+
+      grub_dprintf ("uhci", "t status=0x%02x\n", errtd->ctrl_status);
+
+      /* Check if the TD is not longer active.  */
+      if (! (errtd->ctrl_status & (1 << 23)))
+       {
+         grub_dprintf ("uhci", ">>t status=0x%02x\n", errtd->ctrl_status);
+
+         /* Check if the endpoint is stalled.  */
+         if (errtd->ctrl_status & (1 << 22))
+           err = GRUB_USB_ERR_STALL;
+
+         /* Check if an error related to the data buffer occured.  */
+         if (errtd->ctrl_status & (1 << 21))
+           err = GRUB_USB_ERR_DATA;
+
+         /* Check if a babble error occured.  */
+         if (errtd->ctrl_status & (1 << 20))
+           err = GRUB_USB_ERR_BABBLE;
+         /* Check if a NAK occured.  */
+         if (errtd->ctrl_status & (1 << 19))
+           err = GRUB_USB_ERR_NAK;
+
+         /* Check if a timeout occured.  */
+         if (errtd->ctrl_status & (1 << 18))
+           err = GRUB_USB_ERR_TIMEOUT;
+
+         /* Check if a bitstuff error occured.  */
+         if (errtd->ctrl_status & (1 << 17))
+           err = GRUB_USB_ERR_BITSTUFF;
+
+         if (err)
+           goto fail;
+
+         /* Fall through, no errors occured, so the QH might be
+            updated.  */
+         grub_dprintf ("uhci", "transaction fallthrough\n");
+       }
+    }
+
+  grub_dprintf ("uhci", "transaction complete\n");
+
+ fail:
+
+  grub_dprintf ("uhci", "transaction failed\n");
+
+  /* Place the QH back in the free list and deallocate the associated
+     TDs.  */
+  qh->elinkptr = 1;
+  grub_free_queue (u, td_first);
+
+  return err;
+}
+
+static int
+grub_uhci_iterate (int (*hook) (grub_usb_controller_t dev))
+{
+  struct grub_uhci *u;
+  struct grub_usb_controller dev;
+
+  for (u = uhci; u; u = u->next)
+    {
+      dev.data = u;
+      if (hook (&dev))
+       return 1;
+    }
+
+  return 0;
+}
+
+static grub_err_t
+grub_uhci_portstatus (grub_usb_controller_t dev,
+                     unsigned int port, unsigned int enable)
+{
+  struct grub_uhci *u = (struct grub_uhci *) dev->data;
+  int reg;
+  unsigned int status;
+
+  grub_dprintf ("uhci", "enable=%d port=%d\n", enable, port);
+
+  if (port == 0)
+    reg = GRUB_UHCI_REG_PORTSC1;
+  else if (port == 1)
+    reg = GRUB_UHCI_REG_PORTSC2;
+  else
+    return grub_error (GRUB_ERR_OUT_OF_RANGE,
+                      "UHCI Root Hub port does not exist");
+
+  status = grub_uhci_readreg16 (u, reg);
+  grub_dprintf ("uhci", "detect=0x%02x\n", status);
+
+  /* Reset the port.  */
+  grub_uhci_writereg16 (u, reg, enable << 9);
+
+  /* Wait for the reset to complete.  XXX: How long exactly?  */
+  grub_millisleep (10);
+  status = grub_uhci_readreg16 (u, reg);
+  grub_uhci_writereg16 (u, reg, status & ~(1 << 9));
+  grub_dprintf ("uhci", "reset completed\n");
+
+  /* Enable the port.  */
+  grub_uhci_writereg16 (u, reg, enable << 2);
+  grub_millisleep (10);
+
+  grub_dprintf ("uhci", "waiting for the port to be enabled\n");
+
+  while (! (grub_uhci_readreg16 (u, reg) & (1 << 2)));
+
+  status = grub_uhci_readreg16 (u, reg);
+  grub_dprintf ("uhci", ">3detect=0x%02x\n", status);
+
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_usb_speed_t
+grub_uhci_detect_dev (grub_usb_controller_t dev, int port)
+{
+  struct grub_uhci *u = (struct grub_uhci *) dev->data;
+  int reg;
+  unsigned int status;
+
+  if (port == 0)
+    reg = GRUB_UHCI_REG_PORTSC1;
+  else if (port == 1)
+    reg = GRUB_UHCI_REG_PORTSC2;
+  else
+    return grub_error (GRUB_ERR_OUT_OF_RANGE,
+                      "UHCI Root Hub port does not exist");
+
+  status = grub_uhci_readreg16 (u, reg);
+
+  grub_dprintf ("uhci", "detect=0x%02x port=%d\n", status, port);
+
+  if (! (status & 1))
+    return GRUB_USB_SPEED_NONE;
+  else if (status & (1 << 8))
+    return GRUB_USB_SPEED_LOW;
+  else
+    return GRUB_USB_SPEED_FULL;
+}
+
+static int
+grub_uhci_hubports (grub_usb_controller_t dev __attribute__((unused)))
+{
+  /* The root hub has exactly two ports.  */
+  return 2;
+}
+
+\f
+static struct grub_usb_controller_dev usb_controller =
+{
+  .name = "uhci",
+  .iterate = grub_uhci_iterate,
+  .transfer = grub_uhci_transfer,
+  .hubports = grub_uhci_hubports,
+  .portstatus = grub_uhci_portstatus,
+  .detect_dev = grub_uhci_detect_dev
+};
+
+GRUB_MOD_INIT(uhci)
+{
+  grub_uhci_inithw ();
+  grub_usb_controller_dev_register (&usb_controller);
+  grub_dprintf ("uhci", "registed\n");
+}
+
+GRUB_MOD_FINI(uhci)
+{
+  struct grub_uhci *u;
+
+  /* Disable all UHCI controllers.  */
+  for (u = uhci; u; u = u->next)
+    grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 0);
+
+  /* Unregister the controller.  */
+  grub_usb_controller_dev_unregister (&usb_controller);
+}
diff --git a/bus/usb/usb.c b/bus/usb/usb.c
new file mode 100644 (file)
index 0000000..a30598f
--- /dev/null
@@ -0,0 +1,263 @@
+/* usb.c - Generic USB interfaces.  */
+/*
+ *  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/dl.h>
+#include <grub/mm.h>
+#include <grub/usb.h>
+#include <grub/misc.h>
+
+static grub_usb_controller_dev_t grub_usb_list;
+
+void
+grub_usb_controller_dev_register (grub_usb_controller_dev_t usb)
+{
+  auto int iterate_hook (grub_usb_controller_t dev);
+
+  /* Iterate over all controllers found by the driver.  */
+  int iterate_hook (grub_usb_controller_t dev)
+    {
+      dev->dev = usb;
+
+      /* Enable the ports of the USB Root Hub.  */
+      grub_usb_root_hub (dev);
+
+      return 0;
+    }
+
+  usb->next = grub_usb_list;
+  grub_usb_list = usb;
+
+  if (usb->iterate)
+    usb->iterate (iterate_hook);
+}
+
+void
+grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb)
+{
+  grub_usb_controller_dev_t *p, q;
+
+  for (p = &grub_usb_list, q = *p; q; p = &(q->next), q = q->next)
+    if (q == usb)
+      {
+       *p = q->next;
+       break;
+      }
+}
+
+#if 0
+int
+grub_usb_controller_iterate (int (*hook) (grub_usb_controller_t dev))
+{
+  grub_usb_controller_dev_t p;
+
+  auto int iterate_hook (grub_usb_controller_t dev);
+
+  int iterate_hook (grub_usb_controller_t dev)
+    {
+      dev->dev = p;
+      if (hook (dev))
+       return 1;
+      return 0;
+    }
+
+  /* Iterate over all controller drivers.  */
+  for (p = grub_usb_list; p; p = p->next)
+    {
+      /* Iterate over the busses of the controllers.  XXX: Actually, a
+        hub driver should do this.  */
+      if (p->iterate (iterate_hook))
+       return 1;
+    }
+
+  return 0;
+}
+#endif
+
+\f
+grub_usb_err_t
+grub_usb_clear_halt (grub_usb_device_t dev, int endpoint)
+{
+  dev->toggle[endpoint] = 0;
+  return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
+                                    | GRUB_USB_REQTYPE_STANDARD
+                                    | GRUB_USB_REQTYPE_TARGET_ENDP),
+                              GRUB_USB_REQ_CLEAR_FEATURE,
+                              GRUB_USB_FEATURE_ENDP_HALT,
+                              endpoint, 0, 0);
+}
+
+grub_usb_err_t
+grub_usb_set_configuration (grub_usb_device_t dev, int configuration)
+{
+  int i;
+
+  for (i = 0; i < 16; i++)
+    dev->toggle[i] = 0;
+
+  return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
+                                    | GRUB_USB_REQTYPE_STANDARD
+                                    | GRUB_USB_REQTYPE_TARGET_DEV),
+                              GRUB_USB_REQ_SET_CONFIGURATION, configuration,
+                              0, 0, NULL);
+}
+
+grub_usb_err_t
+grub_usb_get_descriptor (grub_usb_device_t dev,
+                        grub_uint8_t type, grub_uint8_t index,
+                        grub_size_t size, char *data)
+{
+  return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
+                                    | GRUB_USB_REQTYPE_STANDARD
+                                    | GRUB_USB_REQTYPE_TARGET_DEV),
+                              GRUB_USB_REQ_GET_DESCRIPTOR,
+                              (type << 8) | index,
+                              0, size, data);
+}
+
+struct grub_usb_desc_endp *
+grub_usb_get_endpdescriptor (grub_usb_device_t usbdev, int addr)
+{
+  int i;
+
+  for (i = 0; i < usbdev->config[0].descconf->numif; i++)
+    {
+      struct grub_usb_desc_if *interf;
+      int j;
+
+      interf = usbdev->config[0].interf[i].descif;
+
+      for (j = 0; j < interf->endpointcnt; j++)
+       {
+         struct grub_usb_desc_endp *endp;
+         endp = &usbdev->config[0].interf[i].descendp[j];
+
+         if (endp->endp_addr == addr)
+           return endp;
+       }
+    }
+
+  return NULL;
+}
+
+grub_usb_err_t
+grub_usb_get_string (grub_usb_device_t dev, grub_uint8_t index, int langid,
+                    char **string)
+{
+  struct grub_usb_desc_str descstr;
+  struct grub_usb_desc_str *descstrp;
+  grub_usb_err_t err;
+
+  /* Only get the length.  */
+  err = grub_usb_control_msg (dev, 1 << 7,
+                             0x06, (3 << 8) | index,
+                             langid, 1, (char *) &descstr);
+  if (err)
+    return err;
+
+  descstrp = grub_malloc (descstr.length);
+  if (! descstrp)
+    return GRUB_USB_ERR_INTERNAL;
+  err = grub_usb_control_msg (dev, 1 << 7,
+                             0x06, (3 << 8) | index,
+                             langid, descstr.length, (char *) descstrp);
+
+  *string = grub_malloc (descstr.length / 2);
+  if (! *string)
+    {
+      grub_free (descstrp);
+      return GRUB_USB_ERR_INTERNAL;
+    }
+
+  grub_utf16_to_utf8 ((grub_uint8_t *) *string, descstrp->str, descstrp->length / 2 - 1);
+  (*string)[descstr.length / 2 - 1] = '\0';
+  grub_free (descstrp);
+
+  return GRUB_USB_ERR_NONE;
+}
+
+grub_usb_err_t
+grub_usb_device_initialize (grub_usb_device_t dev)
+{
+  struct grub_usb_desc_device *descdev;
+  struct grub_usb_desc_config config;
+  grub_usb_err_t err;
+  int i;
+
+  err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_DEVICE,
+                                0, sizeof (struct grub_usb_desc_device),
+                                (char *) &dev->descdev);
+  if (err)
+    return err;
+  descdev = &dev->descdev;
+
+  for (i = 0; i < 8; i++)
+    dev->config[i].descconf = NULL;
+
+  for (i = 0; i < descdev->configcnt; i++)
+    {
+      int pos;
+      int currif;
+      char *data;
+
+      /* First just read the first 4 bytes of the configuration
+        descriptor, after that it is known how many bytes really have
+        to be read.  */
+      err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_CONFIG, i, 4,
+                                    (char *) &config);
+
+      data = grub_malloc (config.totallen);
+      if (! data)
+       {
+         err = GRUB_USB_ERR_INTERNAL;
+         goto fail;
+       }
+
+      dev->config[i].descconf = (struct grub_usb_desc_config *) data;
+      err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_CONFIG, i,
+                                    config.totallen, data);
+      if (err)
+       goto fail;
+
+      /* Skip the configuration descriptor.  */
+      pos = sizeof (struct grub_usb_desc_config);
+      
+      /* Read all interfaces.  */
+      for (currif = 0; currif < dev->config[i].descconf->numif; currif++)
+       {
+         dev->config[i].interf[currif].descif
+           = (struct grub_usb_desc_if *) &data[pos];
+         pos += sizeof (struct grub_usb_desc_if);
+
+         /* Point to the first endpoint.  */
+         dev->config[i].interf[currif].descendp
+           = (struct grub_usb_desc_endp *) &data[pos];
+         pos += (sizeof (struct grub_usb_desc_endp)
+                 * dev->config[i].interf[currif].descif->endpointcnt);
+       }
+    }
+
+  return GRUB_USB_ERR_NONE;
+
+ fail:
+
+  for (i = 0; i < 8; i++)
+    grub_free (dev->config[i].descconf);
+
+  return err;
+}
diff --git a/bus/usb/usbhub.c b/bus/usb/usbhub.c
new file mode 100644 (file)
index 0000000..ba0925a
--- /dev/null
@@ -0,0 +1,193 @@
+/* usb.c - USB Hub Support.  */
+/*
+ *  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/dl.h>
+#include <grub/mm.h>
+#include <grub/usb.h>
+#include <grub/misc.h>
+
+/* USB Supports 127 devices, with device 0 as special case.  */
+static struct grub_usb_device *grub_usb_devs[128];
+
+/* Add a device that currently has device number 0 and resides on
+   CONTROLLER, the Hub reported that the device speed is SPEED.  */
+static grub_usb_device_t
+grub_usb_hub_add_dev (grub_usb_controller_t controller, grub_usb_speed_t speed)
+{
+  grub_usb_device_t dev;
+  int i;
+
+  dev = grub_malloc (sizeof (struct grub_usb_device));
+  if (! dev)
+    return NULL;
+
+  dev->controller = *controller;
+  dev->addr = 0;
+  dev->initialized = 0;
+  dev->speed = speed;
+
+  grub_usb_device_initialize (dev);
+
+  /* Assign a new address to the device.  */
+  for (i = 1; i < 128; i++)
+    {
+      if (! grub_usb_devs[i])
+       break;
+    }
+  if (grub_usb_devs[i])
+    {
+      grub_error (GRUB_ERR_IO, "Can't assign address to USB device");
+      return NULL;
+    }
+
+  grub_usb_control_msg (dev,
+                       (GRUB_USB_REQTYPE_OUT
+                        | GRUB_USB_REQTYPE_STANDARD
+                        | GRUB_USB_REQTYPE_TARGET_DEV),
+                       GRUB_USB_REQ_SET_ADDRESS,
+                       i, 0, 0, NULL);
+  dev->addr = i;
+  dev->initialized = 1;
+  grub_usb_devs[i] = dev;
+
+  return dev;
+}
+
+\f
+static grub_err_t
+grub_usb_add_hub (grub_usb_device_t dev)
+{
+  struct grub_usb_usb_hubdesc hubdesc;
+  grub_err_t err;
+  int i;
+
+  grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
+                             | GRUB_USB_REQTYPE_CLASS
+                             | GRUB_USB_REQTYPE_TARGET_DEV),
+                       GRUB_USB_REQ_GET_DESCRIPTOR,
+                       (GRUB_USB_DESCRIPTOR_HUB << 8) | 0,
+                       0, sizeof (hubdesc), (char *) &hubdesc);
+
+  /* Iterate over the Hub ports.  */
+  for (i = 1; i <= hubdesc.portcnt; i++)
+    {
+      grub_uint32_t status;
+
+      /* Get the port status.  */
+      err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
+                                       | GRUB_USB_REQTYPE_CLASS
+                                       | GRUB_USB_REQTYPE_TARGET_OTHER),
+                                 GRUB_USB_REQ_HUB_GET_PORT_STATUS,
+                                 0, i, sizeof (status), (char *) &status);
+
+      /* Just ignore the device if the Hub does not report the
+        status.  */
+      if (err)
+       continue;
+
+      /* If connected, reset and enable the port.  */
+      if (status & GRUB_USB_HUB_STATUS_CONNECTED)
+       {
+         grub_usb_speed_t speed;
+
+         /* Determine the device speed.  */
+         if (status & GRUB_USB_HUB_STATUS_LOWSPEED)
+           speed = GRUB_USB_SPEED_LOW;
+         else
+           {
+             if (status & GRUB_USB_HUB_STATUS_HIGHSPEED)
+               speed = GRUB_USB_SPEED_HIGH;
+             else
+               speed = GRUB_USB_SPEED_FULL;
+           }
+
+         /* A device is actually connected to this port, not enable
+            the port.  XXX: Why 0x03?  According to some docs it
+            should be 0x0.  Check the specification!  */
+         err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
+                                           | GRUB_USB_REQTYPE_CLASS
+                                           | GRUB_USB_REQTYPE_TARGET_OTHER),
+                                     0x3, 0x4, i, 0, 0);
+
+         /* If the Hub does not cooperate for this port, just skip
+            the port.  */
+         if (err)
+           continue;
+
+         /* Add the device and assign a device address to it.  */
+         grub_usb_hub_add_dev (&dev->controller, speed);
+       }
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+grub_usb_err_t
+grub_usb_root_hub (grub_usb_controller_t controller)
+{
+  grub_err_t err;
+  int ports;
+  int i;
+
+  /* Query the number of ports the root Hub has.  */
+  ports = controller->dev->hubports (controller);
+
+  for (i = 0; i < ports; i++)
+    {
+      grub_usb_speed_t speed = controller->dev->detect_dev (controller, i);
+
+      if (speed != GRUB_USB_SPEED_NONE)
+       {
+         grub_usb_device_t dev;
+
+         /* Enable the port.  */
+         err = controller->dev->portstatus (controller, i, 1);
+         if (err)
+           continue;
+
+         /* Enable the port and create a device.  */
+         dev = grub_usb_hub_add_dev (controller, speed);
+         if (! dev)
+           continue;
+
+         /* If the device is a Hub, scan it for more devices.  */
+         if (dev->descdev.class == 0x09)
+           grub_usb_add_hub (dev);
+       }
+    }
+
+  return GRUB_USB_ERR_NONE;
+}
+
+int
+grub_usb_iterate (int (*hook) (grub_usb_device_t dev))
+{
+  int i;
+
+  for (i = 0; i < 128; i++)
+    {
+      if (grub_usb_devs[i])
+       {
+         if (hook (grub_usb_devs[i]))
+             return 1;
+       }
+    }
+
+  return 0;
+}
diff --git a/bus/usb/usbtrans.c b/bus/usb/usbtrans.c
new file mode 100644 (file)
index 0000000..8b2d5ad
--- /dev/null
@@ -0,0 +1,212 @@
+/* usbtrans.c - USB Transfers and Transactions.  */
+/*
+ *  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/dl.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/usb.h>
+#include <grub/usbtrans.h>
+
+grub_usb_err_t
+grub_usb_control_msg (grub_usb_device_t dev,
+                     grub_uint8_t reqtype,
+                     grub_uint8_t request,
+                     grub_uint16_t value,
+                     grub_uint16_t index,
+                     grub_size_t size, char *data)
+{
+  int i;
+  grub_usb_transfer_t transfer;
+  int datablocks;
+  struct grub_usb_packet_setup setupdata;
+  grub_usb_err_t err;
+  int max;
+
+  grub_dprintf ("usb",
+               "control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%d\n",
+               reqtype, request,  value, index, size);
+
+  /* Create a transfer.  */
+  transfer = grub_malloc (sizeof (struct grub_usb_transfer));
+  if (! transfer)
+    return grub_errno;
+
+  /* Determine the maximum packet size.  */
+  if (dev->initialized)
+    max = dev->descdev.maxsize0;
+  else
+    max = 64;
+
+  datablocks = (size + max - 1) / max;
+  
+  /* XXX: Discriminate between different types of control
+     messages.  */
+  transfer->transcnt = datablocks + 2;
+  transfer->size = size; /* XXX ? */
+  transfer->endpoint = 0;
+  transfer->devaddr = dev->addr;
+  transfer->type = GRUB_USB_TRANSACTION_TYPE_CONTROL;
+  transfer->max = max;
+  transfer->dev = dev;
+
+  /* Allocate an array of transfer data structures.  */
+  transfer->transactions = grub_malloc (transfer->transcnt
+                                       * sizeof (struct grub_usb_transfer));
+  if (! transfer->transactions)
+    {
+      grub_free (transfer);
+      return grub_errno;
+    }
+
+  /* Build a Setup packet.  XXX: Endianess.  */
+  setupdata.reqtype = reqtype;
+  setupdata.request = request;
+  setupdata.value = value;
+  setupdata.index = index;
+  setupdata.length = size;
+  transfer->transactions[0].size = sizeof (setupdata);
+  transfer->transactions[0].pid = GRUB_USB_TRANSFER_TYPE_SETUP;
+  transfer->transactions[0].data = (char *) &setupdata;
+  transfer->transactions[0].toggle = 0;
+
+  /* Now the data...  XXX: Is this the right way to transfer control
+     transfers?  */
+  for (i = 0; i < datablocks; i++)
+    {
+      grub_usb_transaction_t tr = &transfer->transactions[i + 1];
+
+      tr->size = (size > max) ? max : size;
+      /* Use the right most bit as the data toggle.  Simple and
+        effective.  */
+      tr->toggle = !(i & 1);
+      if (reqtype & 128)
+       tr->pid = GRUB_USB_TRANSFER_TYPE_IN;
+      else
+       tr->pid = GRUB_USB_TRANSFER_TYPE_OUT;
+      tr->data = &data[i * max];
+      size -= max;
+    }
+
+  /* End with an empty OUT transaction.  */
+  transfer->transactions[datablocks + 1].size = 0;
+  transfer->transactions[datablocks + 1].data = NULL;
+  if (reqtype & 128)
+    transfer->transactions[datablocks + 1].pid = GRUB_USB_TRANSFER_TYPE_OUT;
+  else
+    transfer->transactions[datablocks + 1].pid = GRUB_USB_TRANSFER_TYPE_IN;
+  
+  transfer->transactions[datablocks + 1].toggle = 1;
+
+  err = dev->controller.dev->transfer (&dev->controller, transfer);
+
+  grub_free (transfer->transactions);
+  grub_free (transfer);
+
+  return err;
+}
+
+static grub_usb_err_t
+grub_usb_bulk_readwrite (grub_usb_device_t dev,
+                        int endpoint, grub_size_t size, char *data,
+                        grub_transfer_type_t type)
+{
+  int i;
+  grub_usb_transfer_t transfer;
+  int datablocks;
+  unsigned int max;
+  grub_usb_err_t err;
+  int toggle = dev->toggle[endpoint];
+
+  /* Use the maximum packet size given in the endpoint descriptor.  */
+  if (dev->initialized)
+    {
+      struct grub_usb_desc_endp *endpdesc;
+      endpdesc = grub_usb_get_endpdescriptor (dev, 0);
+
+      if (endpdesc)
+       max = endpdesc->maxpacket;
+      else
+       max = 64;
+    }
+  else
+    max = 64;
+
+  /* Create a transfer.  */
+  transfer = grub_malloc (sizeof (struct grub_usb_transfer));
+  if (! transfer)
+    return grub_errno;
+
+  datablocks = ((size + max - 1) / max);
+  transfer->transcnt = datablocks;
+  transfer->size = size - 1;
+  transfer->endpoint = endpoint;
+  transfer->devaddr = dev->addr;
+  transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK;
+  transfer->max = max;
+  transfer->dev = dev;
+
+  /* Allocate an array of transfer data structures.  */
+  transfer->transactions = grub_malloc (transfer->transcnt
+                                       * sizeof (struct grub_usb_transfer));
+  if (! transfer->transactions)
+    {
+      grub_free (transfer);
+      return grub_errno;
+    }
+
+  /* Set up all transfers.  */
+  for (i = 0; i < datablocks; i++)
+    {
+      grub_usb_transaction_t tr = &transfer->transactions[i];
+
+      tr->size = (size > max) ? max : size;
+      /* XXX: Use the right most bit as the data toggle.  Simple and
+        effective.  */
+      tr->toggle = toggle;
+      toggle = toggle ? 0 : 1;
+      tr->pid = type;
+      tr->data = &data[i * max];
+      size -= tr->size;
+    }
+  err = dev->controller.dev->transfer (&dev->controller, transfer);
+  grub_dprintf ("usb", "toggle=%d\n", toggle);
+  dev->toggle[endpoint] = toggle;
+
+  grub_free (transfer->transactions);
+  grub_free (transfer);
+
+  return err;
+}
+
+grub_usb_err_t
+grub_usb_bulk_write (grub_usb_device_t dev,
+                    int endpoint, grub_size_t size, char *data)
+{
+  return grub_usb_bulk_readwrite (dev, endpoint, size, data,
+                                 GRUB_USB_TRANSFER_TYPE_OUT);
+}
+
+grub_usb_err_t
+grub_usb_bulk_read (grub_usb_device_t dev,
+                   int endpoint, grub_size_t size, char *data)
+{
+  return grub_usb_bulk_readwrite (dev, endpoint, size, data,
+                                 GRUB_USB_TRANSFER_TYPE_IN);
+}
diff --git a/commands/blocklist.c b/commands/blocklist.c
new file mode 100644 (file)
index 0000000..c797a5f
--- /dev/null
@@ -0,0 +1,122 @@
+/* blocklist.c - print the block list of a file */
+/*
+ *  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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/misc.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/disk.h>
+#include <grub/partition.h>
+
+static grub_err_t
+grub_cmd_blocklist (struct grub_arg_list *state __attribute__ ((unused)),
+                   int argc, char **args)
+{
+  grub_file_t file;
+  char buf[GRUB_DISK_SECTOR_SIZE];
+  unsigned long start_sector = 0;
+  unsigned num_sectors = 0;
+  int num_entries = 0;
+  grub_disk_addr_t part_start = 0;
+  auto void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset,
+                           unsigned length);
+  auto void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num,
+                            unsigned offset, unsigned length);
+  
+  void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset,
+                      unsigned length)
+    {
+      if (num_sectors > 0)
+       {
+         if (start_sector + num_sectors == sector
+             && offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
+           {
+             num_sectors++;
+             return;
+           }
+         
+         print_blocklist (start_sector, num_sectors, 0, 0);
+         num_sectors = 0;
+       }
+
+      if (offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
+       {
+         start_sector = sector;
+         num_sectors++;
+       }
+      else
+       print_blocklist (sector, 0, offset, length);
+    }
+  
+  void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num,
+                       unsigned offset, unsigned length)
+    {
+      if (num_entries++)
+       grub_printf (",");
+
+      grub_printf ("%llu", (unsigned long long) (sector - part_start));
+      if (num > 0)
+       grub_printf ("+%u", num);
+      if (offset != 0 || length != 0)
+       grub_printf ("[%u-%u]", offset, offset + length);
+    }
+  
+  if (argc < 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
+
+  file = grub_file_open (args[0]);
+  if (! file)
+    return grub_errno;
+
+  if (! file->device->disk)
+    return grub_error (GRUB_ERR_BAD_DEVICE,
+                      "this command is available only for disk devices.");
+
+  if (file->device->disk->partition)
+    part_start = grub_partition_get_start (file->device->disk->partition);
+  
+  file->read_hook = read_blocklist;
+
+  while (grub_file_read (file, buf, sizeof (buf)) > 0)
+    ;
+
+  if (num_sectors > 0)
+    print_blocklist (start_sector, num_sectors, 0, 0);
+  
+  grub_file_close (file);
+
+  return grub_errno;
+}
+
+\f
+GRUB_MOD_INIT(blocklist)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("blocklist", grub_cmd_blocklist,
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "blocklist FILE",
+                        "Print a block list.", 0);
+}
+
+GRUB_MOD_FINI(blocklist)
+{
+  grub_unregister_command ("blocklist");
+}
diff --git a/commands/boot.c b/commands/boot.c
new file mode 100644 (file)
index 0000000..e24a3a4
--- /dev/null
@@ -0,0 +1,50 @@
+/* boot.c - command to boot an operating system */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/misc.h>
+#include <grub/loader.h>
+
+static grub_err_t
+grub_cmd_boot (struct grub_arg_list *state __attribute__ ((unused)),
+              int argc, char **args __attribute__ ((unused)))
+{
+  if (argc)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many arguments");
+  
+  grub_loader_boot ();
+  
+  return 0;
+}
+
+\f
+
+GRUB_MOD_INIT(boot)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("boot", grub_cmd_boot, GRUB_COMMAND_FLAG_BOTH,
+                        "boot", "Boot an operating system.", 0);
+}
+
+GRUB_MOD_FINI(boot)
+{
+  grub_unregister_command ("boot");
+}
diff --git a/commands/cat.c b/commands/cat.c
new file mode 100644 (file)
index 0000000..b5dda4d
--- /dev/null
@@ -0,0 +1,88 @@
+/* cat.c - command to show the contents of a file  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2005,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+
+static grub_err_t
+grub_cmd_cat (struct grub_arg_list *state __attribute__ ((unused)),
+             int argc, char **args)
+
+{
+  grub_file_t file;
+  char buf[GRUB_DISK_SECTOR_SIZE];
+  grub_ssize_t size;
+  int key = 0;
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
+
+  file = grub_gzfile_open (args[0], 1);
+  if (! file)
+    return 0;
+  
+  while ((size = grub_file_read (file, buf, sizeof (buf))) > 0
+        && key != GRUB_TERM_ESC)
+    {
+      int i;
+      
+      for (i = 0; i < size; i++)
+       {
+         unsigned char c = buf[i];
+         
+         if ((grub_isprint (c) || grub_isspace (c)) && c != '\r')
+           grub_putchar (c);
+         else
+           {
+             grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
+             grub_printf ("<%x>", (int) c);
+             grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
+           }
+       }
+
+      while (grub_checkkey () >= 0 &&
+            (key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != GRUB_TERM_ESC)
+       ;
+    }
+
+  grub_putchar ('\n');
+  grub_refresh ();
+  grub_file_close (file);
+  
+  return 0;
+}
+
+\f
+GRUB_MOD_INIT(cat)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("cat", grub_cmd_cat, GRUB_COMMAND_FLAG_BOTH,
+                        "cat FILE", "Show the contents of a file.", 0);
+}
+
+GRUB_MOD_FINI(cat)
+{
+  grub_unregister_command ("cat");
+}
diff --git a/commands/cmp.c b/commands/cmp.c
new file mode 100644 (file)
index 0000000..87620b6
--- /dev/null
@@ -0,0 +1,119 @@
+/* cmd.c - command to cmp an operating system */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2005,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/misc.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/gzio.h>
+
+#define BUFFER_SIZE 512
+
+static grub_err_t
+grub_cmd_cmp (struct grub_arg_list *state __attribute__ ((unused)),
+             int argc, char **args)
+{
+  grub_ssize_t rd1, rd2;
+  grub_off_t pos;
+  grub_file_t file1 = 0;
+  grub_file_t file2 = 0;
+  char *buf1 = 0;
+  char *buf2 = 0;
+
+  if (argc != 2)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required");
+
+  grub_printf ("Compare `%s' and `%s':\n", args[0],
+              args[1]);
+
+  file1 = grub_gzfile_open (args[0], 1);
+  file2 = grub_gzfile_open (args[1], 1);
+  if (! file1 || ! file2)
+    goto cleanup;
+
+  if (grub_file_size (file1) != grub_file_size (file2))
+    grub_printf ("Differ in size: %llu [%s], %llu [%s]\n", 
+                (unsigned long long) grub_file_size (file1), args[0],
+                (unsigned long long) grub_file_size (file2), args[1]);
+  else
+    {
+      pos = 0;
+
+      buf1 = grub_malloc (BUFFER_SIZE);
+      buf2 = grub_malloc (BUFFER_SIZE);
+      
+      if (! buf1 || ! buf2)
+        goto cleanup;
+      
+      do
+       {
+         int i;
+         
+         rd1 = grub_file_read (file1, buf1, BUFFER_SIZE);
+         rd2 = grub_file_read (file2, buf2, BUFFER_SIZE);
+
+         if (rd1 != rd2)
+           goto cleanup;
+
+         for (i = 0; i < rd2; i++)
+           {
+             if (buf1[i] != buf2[i])
+               {
+                 grub_printf ("Differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n",
+                              (unsigned long long) (i + pos), buf1[i], args[0],
+                              buf2[i], args[1]);
+                 goto cleanup;
+               }
+           }
+         pos += BUFFER_SIZE;
+         
+       }
+      while (rd2);
+      
+      grub_printf ("The files are identical.\n");
+    }
+
+cleanup:
+  
+  if (buf1)
+    grub_free (buf1);
+  if (buf2)
+    grub_free (buf2);
+  if (file1)
+    grub_file_close (file1);
+  if (file2)
+    grub_file_close (file2);
+
+  return grub_errno;
+}
+
+\f
+GRUB_MOD_INIT(cmp)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("cmp", grub_cmd_cmp, GRUB_COMMAND_FLAG_BOTH,
+                        "cmp FILE1 FILE2", "Compare two files.", 0);
+}
+
+GRUB_MOD_FINI(cmp)
+{
+  grub_unregister_command ("cmp");
+}
diff --git a/commands/configfile.c b/commands/configfile.c
new file mode 100644 (file)
index 0000000..2d1fb67
--- /dev/null
@@ -0,0 +1,78 @@
+/* configfile.c - command to manually load config file  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+
+static grub_err_t
+grub_cmd_configfile (struct grub_arg_list *state __attribute__ ((unused)),
+             int argc, char **args)
+
+{
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
+
+  grub_cls ();
+  grub_env_context_open ();
+  grub_normal_execute (args[0], 1);
+  grub_env_context_close ();
+
+  return 0;
+}
+
+static grub_err_t
+grub_cmd_source (struct grub_arg_list *state __attribute__ ((unused)),
+                int argc, char **args)
+
+{
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
+
+  grub_normal_execute (args[0], 1);
+
+  return 0;
+}
+
+\f
+GRUB_MOD_INIT(configfile)
+{
+  (void) mod;                   /* To stop warning. */
+  grub_register_command ("configfile", grub_cmd_configfile,
+                        GRUB_COMMAND_FLAG_BOTH, "configfile FILE",
+                        "Load another config file.", 0);
+  grub_register_command ("source", grub_cmd_source,
+                        GRUB_COMMAND_FLAG_BOTH, "source FILE",
+                        "Load another config file without changing context.",
+                        0);
+  grub_register_command (".", grub_cmd_source,
+                        GRUB_COMMAND_FLAG_BOTH, ". FILE",
+                        "Load another config file without changing context.",
+                        0);
+}
+
+GRUB_MOD_FINI(configfile)
+{
+  grub_unregister_command ("configfile");
+  grub_unregister_command ("source");
+  grub_unregister_command (".");
+}
diff --git a/commands/crc.c b/commands/crc.c
new file mode 100644 (file)
index 0000000..5148648
--- /dev/null
@@ -0,0 +1,66 @@
+/* crc.c - command to calculate the crc32 checksum of a file  */
+/*
+ *  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/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/disk.h>
+#include <grub/file.h>
+#include <grub/misc.h>
+#include <grub/lib/crc.h>
+
+static grub_err_t
+grub_cmd_crc (struct grub_arg_list *state __attribute__ ((unused)),
+             int argc, char **args)
+
+{
+  grub_file_t file;
+  char buf[GRUB_DISK_SECTOR_SIZE];
+  grub_ssize_t size;
+  grub_uint32_t crc;
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
+
+  file = grub_file_open (args[0]);
+  if (! file)
+    return 0;
+
+  crc = 0;
+  while ((size = grub_file_read (file, buf, sizeof (buf))) > 0)
+    crc = grub_getcrc32 (crc, buf, size);
+
+  grub_file_close (file);
+
+  grub_printf ("%08x\n", crc);
+
+  return 0;
+}
+
+GRUB_MOD_INIT(crc)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("crc", grub_cmd_crc, GRUB_COMMAND_FLAG_BOTH,
+                        "crc FILE", "Calculate the crc32 checksum of a file.", 0);
+}
+
+GRUB_MOD_FINI(crc)
+{
+  grub_unregister_command ("crc");
+}
diff --git a/commands/date.c b/commands/date.c
new file mode 100644 (file)
index 0000000..2331918
--- /dev/null
@@ -0,0 +1,145 @@
+/* date.c - command to display/set current datetime.  */
+/*
+ *  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/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/lib/datetime.h>
+
+#define GRUB_DATETIME_SET_YEAR         1
+#define GRUB_DATETIME_SET_MONTH                2
+#define GRUB_DATETIME_SET_DAY          4
+#define GRUB_DATETIME_SET_HOUR         8
+#define GRUB_DATETIME_SET_MINUTE       16
+#define GRUB_DATETIME_SET_SECOND       32
+
+static grub_err_t
+grub_cmd_date (struct grub_arg_list *state __attribute__ ((unused)),
+               int argc, char **args)
+{
+  struct grub_datetime datetime;
+  int limit[6][2] = {{1980, 2079}, {1, 12}, {1, 31}, {0, 23}, {0, 59}, {0, 59}};
+  int value[6], mask;
+
+  if (argc == 0)
+    {
+      if (grub_get_datetime (&datetime))
+        return grub_errno;
+
+      grub_printf ("%d-%02d-%02d %02d:%02d:%02d %s\n",
+                   datetime.year, datetime.month, datetime.day,
+                   datetime.hour, datetime.minute, datetime.second,
+                   grub_get_weekday_name (&datetime));
+
+      return 0;
+    }
+
+  grub_memset (&value, 0, sizeof (value));
+  mask = 0;
+
+  for (; argc; argc--, args++)
+    {
+      char *p, c;
+      int m1, ofs, n, cur_mask;
+
+      p = args[0];
+      m1 = grub_strtoul (p, &p, 10);
+
+      c = *p;
+      if (c == '-')
+        ofs = 0;
+      else if (c == ':')
+        ofs = 3;
+      else
+        goto fail;
+
+      value[ofs] = m1;
+      cur_mask = (1 << ofs);
+      mask &= ~(cur_mask * (1 + 2 + 4));
+
+      for (n = 1; (n < 3) && (*p); n++)
+        {
+          if (*p != c)
+            goto fail;
+
+          value[ofs + n] = grub_strtoul (p + 1, &p, 10);
+          cur_mask |= (1 << (ofs + n));
+        }
+
+      if (*p)
+        goto fail;
+
+      if ((ofs == 0) && (n == 2))
+        {
+          value[ofs + 2] = value[ofs + 1];
+          value[ofs + 1] = value[ofs];
+          ofs++;
+          cur_mask <<= 1;
+        }
+
+      for (; n; n--, ofs++)
+        if ((value [ofs] < limit[ofs][0]) ||
+            (value [ofs] > limit[ofs][1]))
+          goto fail;
+
+      mask |= cur_mask;
+    }
+
+  if (grub_get_datetime (&datetime))
+    return grub_errno;
+
+  if (mask & GRUB_DATETIME_SET_YEAR)
+    datetime.year = value[0];
+
+  if (mask & GRUB_DATETIME_SET_MONTH)
+    datetime.month = value[1];
+
+  if (mask & GRUB_DATETIME_SET_DAY)
+    datetime.day = value[2];
+
+  if (mask & GRUB_DATETIME_SET_HOUR)
+    datetime.hour = value[3];
+
+  if (mask & GRUB_DATETIME_SET_MINUTE)
+    datetime.minute = value[4];
+
+  if (mask & GRUB_DATETIME_SET_SECOND)
+    datetime.second = value[5];
+
+  return grub_set_datetime (&datetime);
+
+fail:
+  return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid datetime");
+}
+
+GRUB_MOD_INIT(date)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("date", grub_cmd_date,
+                         GRUB_COMMAND_FLAG_BOTH,
+                        "date [[year-]month-day] [hour:minute[:second]]",
+                         "Command to display/set current datetime.", 0);
+}
+
+GRUB_MOD_FINI(date)
+{
+  grub_unregister_command ("date");
+}
diff --git a/commands/echo.c b/commands/echo.c
new file mode 100644 (file)
index 0000000..e2a483c
--- /dev/null
@@ -0,0 +1,124 @@
+/* echo.c - Command to display a line of text  */
+/*
+ *  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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/misc.h>
+
+static const struct grub_arg_option options[] =
+  {
+    {0, 'n', 0, "do not output the trailing newline", 0, 0},
+    {0, 'e', 0, "enable interpretation of backslash escapes", 0, 0},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+
+static grub_err_t
+grub_cmd_echo (struct grub_arg_list *state, int argc, char **args)
+{
+  int newline = 1;
+  int i;
+
+  /* Check if `-n' was used.  */
+  if (state[0].set)
+    newline = 0;
+
+  for (i = 0; i < argc; i++)
+    {
+      char *arg = *args;
+      args++;
+
+      while (*arg)
+       {
+         /* In case `-e' is used, parse backslashes.  */
+         if (*arg == '\\' && state[1].set)
+           {
+             arg++;
+             if (*arg == '\0')
+               break;
+
+             switch (*arg)
+               {
+               case '\\':
+                 grub_printf ("\\");
+                 break;
+
+               case 'a':
+                 grub_printf ("\a");
+                 break;
+
+               case 'c':
+                 newline = 0;
+                 break;
+
+               case 'f':
+                 grub_printf ("\f");
+                 break;
+
+               case 'n':
+                 grub_printf ("\n");
+                 break;
+
+               case 'r':
+                 grub_printf ("\r");
+                 break;
+
+               case 't':
+                 grub_printf ("\t");
+                 break;
+
+               case 'v':
+                 grub_printf ("\v");
+                 break;
+               }
+             arg++;
+             continue;
+           }
+         
+         /* This was not an escaped character, or escaping is not
+            enabled.  */
+         grub_printf ("%c", *arg);
+         arg++;
+       }
+
+      /* If another argument follows, insert a space.  */
+      if (i != argc - 1)
+       grub_printf (" " );
+    }
+
+  if (newline)
+    grub_printf ("\n");
+
+  return 0;
+}
+
+\f
+GRUB_MOD_INIT(echo)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("echo", grub_cmd_echo, GRUB_COMMAND_FLAG_BOTH,
+                        "echo [-e|-n] FILE", "Display a line of text.",
+                        options);
+}
+
+GRUB_MOD_FINI(echo)
+{
+  grub_unregister_command ("echo");
+}
diff --git a/commands/halt.c b/commands/halt.c
new file mode 100644 (file)
index 0000000..c12c9d2
--- /dev/null
@@ -0,0 +1,54 @@
+/* halt.c - command to halt the computer.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/machine/machine.h>
+
+#if defined(GRUB_MACHINE_IEEE1275)
+#include <grub/machine/kernel.h>
+#elif defined(GRUB_MACHINE_EFI)
+#include <grub/efi/efi.h>
+#else
+/* Platforms shipping standalone halt, such as coreboot.  */
+#include <grub/cpu/halt.h>
+#endif
+
+static grub_err_t
+grub_cmd_halt (struct grub_arg_list *state __attribute__ ((unused)),
+              int argc __attribute__ ((unused)),
+              char **args __attribute__ ((unused)))
+{
+  grub_halt ();
+  return 0;
+}
+
+\f
+GRUB_MOD_INIT(halt)
+{
+  (void)mod;                   /* To stop warning. */
+  grub_register_command ("halt", grub_cmd_halt, GRUB_COMMAND_FLAG_BOTH,
+                        "halt", "halts the computer.  This command does not"
+                        " work on all firmware.", 0);
+}
+
+GRUB_MOD_FINI(halt)
+{
+  grub_unregister_command ("halt");
+}
diff --git a/commands/hdparm.c b/commands/hdparm.c
new file mode 100644 (file)
index 0000000..9f2ba90
--- /dev/null
@@ -0,0 +1,421 @@
+/* hdparm.c - command to get/set ATA disk parameters.  */
+/*
+ *  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/arg.h>
+#include <grub/ata.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/mm.h>
+#include <grub/lib/hexdump.h>
+
+
+static const struct grub_arg_option options[] = {
+  {"apm",             'B', 0, "set Advanced Power Management\n"
+                             "(1=low, ..., 254=high, 255=off)",
+                             0, ARG_TYPE_INT},
+  {"power",           'C', 0, "check power mode", 0, ARG_TYPE_NONE},
+  {"security-freeze", 'F', 0, "freeze ATA security settings until reset",
+                             0, ARG_TYPE_NONE},
+  {"health",          'H', 0, "check SMART health status", 0, ARG_TYPE_NONE},
+  {"aam",             'M', 0, "set Automatic Acoustic Management\n"
+                             "(0=off, 128=quiet, ..., 254=fast)",
+                             0, ARG_TYPE_INT},
+  {"standby-timeout", 'S', 0, "set standby timeout\n"
+                             "(0=off, 1=5s, 2=10s, ..., 240=20m, 241=30m, ...)",
+                             0, ARG_TYPE_INT},
+  {"standby",         'y', 0, "set drive to standby mode", 0, ARG_TYPE_NONE},
+  {"sleep",           'Y', 0, "set drive to sleep mode", 0, ARG_TYPE_NONE},
+  {"identify",        'i', 0, "print drive identity and settings",
+                             0, ARG_TYPE_NONE},
+  {"dumpid",          'I', 0, "dump contents of ATA IDENTIFY sector",
+                              0, ARG_TYPE_NONE},
+  {"smart",            -1, 0, "disable/enable SMART (0/1)", 0, ARG_TYPE_INT},
+  {"quiet",           'q', 0, "do not print messages", 0, ARG_TYPE_NONE},
+  {0, 0, 0, 0, 0, 0}
+};
+
+enum grub_ata_smart_commands
+  {
+    GRUB_ATA_FEAT_SMART_ENABLE  = 0xd8,
+    GRUB_ATA_FEAT_SMART_DISABLE = 0xd9,
+    GRUB_ATA_FEAT_SMART_STATUS  = 0xda,
+  };
+
+static int quiet = 0;
+
+static grub_err_t
+grub_hdparm_do_ata_cmd (grub_disk_t disk, 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.buffer = buffer;
+  apt.size = size;
+
+  if (grub_disk_ata_pass_through (disk, &apt))
+    return grub_errno;
+
+  return GRUB_ERR_NONE;
+}
+
+static int
+grub_hdparm_do_check_powermode_cmd (grub_disk_t disk)
+{
+  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;
+
+  if (grub_disk_ata_pass_through (disk, &apt))
+    return -1;
+
+  return apt.taskfile[GRUB_ATA_REG_SECTORS];
+}
+
+static int
+grub_hdparm_do_smart_cmd (grub_disk_t disk, 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;
+
+  if (grub_disk_ata_pass_through (disk, &apt))
+    return -1;
+
+  if (features == GRUB_ATA_FEAT_SMART_STATUS)
+    {
+      if (   apt.taskfile[GRUB_ATA_REG_LBAMID]  == 0x4f
+          && apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0xc2)
+       return 0; /* Good SMART status.  */
+      else if (   apt.taskfile[GRUB_ATA_REG_LBAMID]  == 0xf4
+              && apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0x2c)
+       return 1; /* Bad SMART status.  */
+      else
+       return -1;
+    }
+  return 0;
+}
+
+static grub_err_t
+grub_hdparm_simple_cmd (const char * msg,
+                       grub_disk_t disk, 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);
+
+  if (! quiet && msg)
+    grub_printf ("%s\n", ! err ? "" : ": not supported");
+  return err;
+}
+
+static grub_err_t
+grub_hdparm_set_val_cmd (const char * msg, int val,
+                        grub_disk_t disk, grub_uint8_t cmd,
+                        grub_uint8_t features, grub_uint8_t sectors)
+{
+  if (! quiet && msg && *msg)
+    {
+      if (val >= 0)
+       grub_printf ("Set %s to %d", msg, val);
+      else
+       grub_printf ("Disable %s", msg);
+    }
+
+  grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, features, sectors,
+                                          NULL, 0);
+
+  if (! quiet && msg)
+    grub_printf ("%s\n", ! err ? "" : ": not supported");
+  return err;
+}
+
+static const char *
+le16_to_char (char *dest, const grub_uint16_t * src16, unsigned bytes)
+{
+  grub_uint16_t * dest16 = (grub_uint16_t *) dest;
+  unsigned i;
+  for (i = 0; i < bytes / 2; i++)
+    dest16[i] = grub_be_to_cpu16 (src16[i]);
+  return dest;
+}
+
+static void
+grub_hdparm_print_identify (const char * idbuf)
+{
+  const grub_uint16_t * idw = (const grub_uint16_t *) idbuf;
+
+  /* Print identity strings.  */
+  char tmp[40];
+  grub_printf ("Model:    \"%.40s\"\n", le16_to_char (tmp, &idw[27], 40));
+  grub_printf ("Firmware: \"%.8s\"\n",  le16_to_char (tmp, &idw[23], 8));
+  grub_printf ("Serial:   \"%.20s\"\n", le16_to_char (tmp, &idw[10], 20));
+
+  /* Print AAM, APM and SMART settings.  */
+  grub_uint16_t features1 = grub_le_to_cpu16 (idw[82]);
+  grub_uint16_t features2 = grub_le_to_cpu16 (idw[83]);
+  grub_uint16_t enabled1  = grub_le_to_cpu16 (idw[85]);
+  grub_uint16_t enabled2  = grub_le_to_cpu16 (idw[86]);
+
+  grub_printf ("Automatic Acoustic Management: ");
+  if (features2 & 0x0200)
+    {
+      if (enabled2 & 0x0200)
+       {
+         grub_uint16_t aam = grub_le_to_cpu16 (idw[94]);
+         grub_printf ("%u (128=quiet, ..., 254=fast, recommended=%u)\n",
+                      aam & 0xff, (aam >> 8) & 0xff);
+       }
+      else
+       grub_printf ("disabled\n");
+    }
+  else
+    grub_printf ("not supported\n");
+
+  grub_printf ("Advanced Power Management: ");
+  if (features2 & 0x0008)
+    {
+      if (enabled2 & 0x0008)
+       grub_printf ("%u (1=low, ..., 254=high)\n",
+                    grub_le_to_cpu16 (idw[91]) & 0xff);
+      else
+       grub_printf ("disabled\n");
+    }
+  else
+    grub_printf ("not supported\n");
+
+  grub_printf ("SMART Feature Set: ");
+  if (features1 & 0x0001)
+    grub_printf ("%sabled\n", (enabled1 & 0x0001 ? "en" : "dis"));
+  else
+    grub_printf ("not supported\n");
+
+  /* Print security settings.  */
+  grub_uint16_t security = grub_le_to_cpu16 (idw[128]);
+
+  grub_printf ("ATA Security: ");
+  if (security & 0x0001)
+    grub_printf ("%s, %s, %s, %s\n",
+                (security & 0x0002 ? "ENABLED" : "disabled"),
+                (security & 0x0004 ? "**LOCKED**"  : "not locked"),
+                (security & 0x0008 ? "frozen" : "NOT FROZEN"),
+                (security & 0x0010 ? "COUNT EXPIRED" : "count not expired"));
+  else
+    grub_printf ("not supported\n");
+}
+
+static void
+grub_hdparm_print_standby_tout (int timeout)
+{
+  if (timeout == 0)
+    grub_printf ("off");
+  else if (timeout <= 252 || timeout == 255)
+    {
+      int h = 0, m = 0 , s = 0;
+      if (timeout == 255)
+       {
+         m = 21;
+         s = 15;
+       }
+      else if (timeout == 252)
+       m = 21;
+      else if (timeout <= 240)
+       {
+         s = timeout * 5;
+         m = s / 60;
+         s %= 60;
+       }
+      else
+       {
+         m = (timeout - 240) * 30;
+         h  = m / 60;
+         m %= 60;
+       }
+      grub_printf ("%02d:%02d:%02d", h, m, s);
+    }
+  else
+    grub_printf ("invalid or vendor-specific");
+}
+
+static int get_int_arg (const struct grub_arg_list *state)
+{
+  return (state->set ? (int)grub_strtoul (state->arg, 0, 0) : -1);
+}
+
+
+static grub_err_t
+grub_cmd_hdparm (struct grub_arg_list *state, int argc, char **args) // state????
+{
+  /* Check command line.  */
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing device name argument");
+
+  grub_size_t len = grub_strlen (args[0]);
+  if (! (args[0][0] == '(' && args[0][len - 1] == ')'))
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "argument is not a device name");
+  args[0][len - 1] = 0;
+
+  if (! grub_disk_ata_pass_through)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "ATA pass through not available");
+
+  int i = 0;
+  int apm          = get_int_arg (&state[i++]);
+  int power        = state[i++].set;
+  int sec_freeze   = state[i++].set;
+  int health       = state[i++].set;
+  int aam          = get_int_arg (&state[i++]);
+  int standby_tout = get_int_arg (&state[i++]);
+  int standby_now  = state[i++].set;
+  int sleep_now    = state[i++].set;
+  int ident        = state[i++].set;
+  int dumpid       = state[i++].set;
+  int enable_smart = get_int_arg (&state[i++]);
+  quiet            = state[i++].set;
+
+  /* Open disk.  */
+  grub_disk_t disk = grub_disk_open (&args[0][1]);
+  if (! disk)
+    return grub_errno;
+
+  if (disk->partition)
+    {
+      grub_disk_close (disk);
+      return grub_error (GRUB_ERR_BAD_ARGUMENT, "partition not allowed");
+    }
+
+  /* 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);
+
+  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));
+
+  if (standby_tout >= 0)
+    {
+      if (! quiet)
+       {
+         grub_printf ("Set standby timeout to %d (", standby_tout);
+         grub_hdparm_print_standby_tout (standby_tout);
+         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);
+    }
+
+  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 ?
+                 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_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,
+          0, 0, buf, sizeof (buf)))
+       grub_printf ("Cannot read ATA IDENTIFY data\n");
+      else
+       {
+         if (ident)
+           grub_hdparm_print_identify (buf);
+         if (dumpid)
+           hexdump (0, buf, sizeof (buf));
+       }
+    }
+
+  /* Check power mode.  */
+  if (power)
+    {
+      grub_printf ("Disk power mode is: ");
+      int mode = grub_hdparm_do_check_powermode_cmd (disk);
+      if (mode < 0)
+        grub_printf ("unknown\n");
+      else
+       grub_printf ("%s (0x%02x)\n",
+                    (mode == 0xff ? "active/idle" :
+                     mode == 0x80 ? "idle" :
+                     mode == 0x00 ? "standby" : "unknown"), mode);
+    }
+
+  /* Check health.  */
+  int status = 0;
+  if (health)
+    {
+      if (! quiet)
+       grub_printf ("SMART status is: ");
+      int err = grub_hdparm_do_smart_cmd (disk, GRUB_ATA_FEAT_SMART_STATUS);
+      if (! quiet)
+       grub_printf ("%s\n", (err  < 0 ? "unknown" :
+                             err == 0 ? "OK" : "*BAD*"));
+      status = (err > 0);
+    }
+
+  /* Change power mode.  */
+  if (standby_now)
+    grub_hdparm_simple_cmd ("Set disk to standby mode", disk,
+                           GRUB_ATA_CMD_STANDBY_IMMEDIATE);
+
+  if (sleep_now)
+    grub_hdparm_simple_cmd ("Set disk to sleep mode", disk,
+                           GRUB_ATA_CMD_SLEEP);
+
+  grub_disk_close (disk);
+
+  grub_errno = GRUB_ERR_NONE;
+  return status;
+}
+
+
+GRUB_MOD_INIT(hdparm)
+{
+  (void) mod;
+
+  grub_register_command ("hdparm", grub_cmd_hdparm, GRUB_COMMAND_FLAG_BOTH,
+                        "hdparm [OPTIONS] DISK",
+                        "Get/set ATA disk parameters.", options);
+}
+
+GRUB_MOD_FINI(hdparm)
+{
+  grub_unregister_command ("hdparm");
+}
diff --git a/commands/help.c b/commands/help.c
new file mode 100644 (file)
index 0000000..3e78cb9
--- /dev/null
@@ -0,0 +1,103 @@
+/* help.c - command to show a help text.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/misc.h>
+#include <grub/term.h>
+
+static grub_err_t
+grub_cmd_help (struct grub_arg_list *state __attribute__ ((unused)), int argc,
+              char **args)
+
+{
+  int cnt = 0;
+  char *currarg;
+  
+  auto int print_command_info (grub_command_t cmd);
+  auto int print_command_help (grub_command_t cmd);
+
+  int print_command_info (grub_command_t cmd)
+    {
+      if (grub_command_find (cmd->name))
+       {
+         if (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE)
+           {
+             char description[GRUB_TERM_WIDTH / 2];
+             int desclen = grub_strlen (cmd->summary);
+             
+             /* Make a string with a length of GRUB_TERM_WIDTH / 2 - 1 filled
+                with the description followed by spaces.  */
+             grub_memset (description, ' ', GRUB_TERM_WIDTH / 2 - 1);
+             description[GRUB_TERM_WIDTH / 2 - 1] = '\0';
+             grub_memcpy (description, cmd->summary,
+                          (desclen < GRUB_TERM_WIDTH / 2 - 1 
+                           ? desclen : GRUB_TERM_WIDTH / 2 - 1));
+             
+             grub_printf ("%s%s", description, (cnt++) % 2 ? "\n" : " ");
+           }
+       }
+      return 0;
+    }
+
+  int print_command_help (grub_command_t cmd)
+    {
+      if (grub_command_find (cmd->name))
+       {
+         if (! grub_strncmp (cmd->name, currarg, grub_strlen (currarg)))
+           {
+             if (cnt++ > 0)
+               grub_printf ("\n\n");
+             
+             grub_arg_show_help (cmd);
+           }
+       }
+      return 0;
+    }
+  
+  if (argc == 0)
+    grub_iterate_commands (print_command_info);
+  else
+    {
+      int i;
+      
+      for (i = 0; i < argc; i++)
+       {
+         currarg = args[i];
+         grub_iterate_commands (print_command_help);     
+       }
+    }
+  
+  return 0;
+}
+
+
+\f
+GRUB_MOD_INIT(help)
+{
+  (void)mod;                   /* To stop warning. */
+  grub_register_command ("help", grub_cmd_help, GRUB_COMMAND_FLAG_CMDLINE,
+                        "help [PATTERN ...]", "Show a help message.", 0);
+}
+
+GRUB_MOD_FINI(help)
+{
+  grub_unregister_command ("help");
+}
diff --git a/commands/hexdump.c b/commands/hexdump.c
new file mode 100644 (file)
index 0000000..10b6320
--- /dev/null
@@ -0,0 +1,136 @@
+/* hexdump.c - command to dump the contents of a file or memory */
+/*
+ *  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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+#include <grub/partition.h>
+#include <grub/lib/hexdump.h>
+
+static const struct grub_arg_option options[] = {
+  {"skip", 's', 0, "skip offset bytes from the beginning of file.", 0,
+   ARG_TYPE_INT},
+  {"length", 'n', 0, "read only length bytes", 0, ARG_TYPE_INT},
+  {0, 0, 0, 0, 0, 0}
+};
+
+static grub_err_t
+grub_cmd_hexdump (struct grub_arg_list *state, int argc, char **args)
+{
+  char buf[GRUB_DISK_SECTOR_SIZE * 4];
+  grub_ssize_t size, length;
+  grub_addr_t skip;
+  int namelen;
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
+
+  namelen = grub_strlen (args[0]);
+  skip = (state[0].set) ? grub_strtoul (state[0].arg, 0, 0) : 0;
+  length = (state[1].set) ? grub_strtoul (state[1].arg, 0, 0) : 256;
+
+  if (!grub_strcmp (args[0], "(mem)"))
+    hexdump (skip, (char *) skip, length);
+  else if ((args[0][0] == '(') && (args[0][namelen - 1] == ')'))
+    {
+      grub_disk_t disk;
+      grub_disk_addr_t sector;
+      grub_size_t ofs;
+
+      args[0][namelen - 1] = 0;
+      disk = grub_disk_open (&args[0][1]);
+      if (! disk)
+        return 0;
+
+      if (disk->partition)
+        skip += grub_partition_get_start (disk->partition) << GRUB_DISK_SECTOR_BITS;
+
+      sector = (skip >> (GRUB_DISK_SECTOR_BITS + 2)) * 4;
+      ofs = skip & (GRUB_DISK_SECTOR_SIZE * 4 - 1);
+      while (length)
+        {
+          grub_size_t len, n;
+
+          len = length;
+          if (ofs + len > sizeof (buf))
+            len = sizeof (buf) - ofs;
+
+          n = ((ofs + len + GRUB_DISK_SECTOR_SIZE - 1)
+               >> GRUB_DISK_SECTOR_BITS);
+          if (disk->dev->read (disk, sector, n, buf))
+            break;
+
+          hexdump (skip, &buf[ofs], len);
+
+          ofs = 0;
+          skip += len;
+          length -= len;
+          sector += 4;
+        }
+
+      grub_disk_close (disk);
+    }
+  else
+    {
+      grub_file_t file;
+
+      file = grub_gzfile_open (args[0], 1);
+      if (! file)
+       return 0;
+
+      file->offset = skip;
+
+      while ((size = grub_file_read (file, buf, sizeof (buf))) > 0)
+       {
+         unsigned long len;
+
+         len = ((length) && (size > length)) ? length : size;
+         hexdump (skip, buf, len);
+         skip += len;
+         if (length)
+           {
+             length -= len;
+             if (!length)
+               break;
+           }
+       }
+
+      grub_file_close (file);
+    }
+
+  return 0;
+}
+\f
+
+GRUB_MOD_INIT (hexdump)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("hexdump", grub_cmd_hexdump, GRUB_COMMAND_FLAG_BOTH,
+                        "hexdump [OPTIONS] FILE_OR_DEVICE",
+                        "Dump the contents of a file or memory.", options);
+}
+
+GRUB_MOD_FINI (hexdump)
+{
+  grub_unregister_command ("hexdump");
+}
diff --git a/commands/i386/cpuid.c b/commands/i386/cpuid.c
new file mode 100644 (file)
index 0000000..87873d2
--- /dev/null
@@ -0,0 +1,93 @@
+/* cpuid.c - test for CPU features */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006, 2007  Free Software Foundation, Inc.
+ *  Based on gcc/gcc/config/i386/driver-i386.c
+ *
+ *  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/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+
+#define cpuid(num,a,b,c,d) \
+  asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
+               : "=a" (a), "=r" (b), "=c" (c), "=d" (d)  \
+               : "0" (num))
+
+#define bit_LM (1 << 29)
+
+static unsigned char has_longmode = 0;
+
+static const struct grub_arg_option options[] =
+  {
+    {"long-mode", 'l', 0, "check for long mode flag (default)", 0, 0},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+static grub_err_t
+grub_cmd_cpuid (struct grub_arg_list *state __attribute__ ((unused)),
+              int argc __attribute__ ((unused)),
+              char **args __attribute__ ((unused)))
+{
+  return !has_longmode;
+}
+
+GRUB_MOD_INIT(cpuid)
+{
+#ifdef __x86_64__
+  /* grub-emu */
+  has_longmode = 1;
+#else
+  unsigned int eax, ebx, ecx, edx;
+  unsigned int max_level;
+  unsigned int ext_level;
+
+  /* See if we can use cpuid.  */
+  asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
+               "pushl %0; popfl; pushfl; popl %0; popfl"
+               : "=&r" (eax), "=&r" (ebx)
+               : "i" (0x00200000));
+  if (((eax ^ ebx) & 0x00200000) == 0)
+    goto done;
+
+  /* Check the highest input value for eax.  */
+  cpuid (0, eax, ebx, ecx, edx);
+  /* We only look at the first four characters.  */
+  max_level = eax;
+  if (max_level == 0)
+    goto done;
+
+  cpuid (0x80000000, eax, ebx, ecx, edx);
+  ext_level = eax;
+  if (ext_level < 0x80000000)
+    goto done;
+
+  cpuid (0x80000001, eax, ebx, ecx, edx);
+  has_longmode = !!(edx & bit_LM);
+done:
+#endif
+
+  grub_register_command ("cpuid", grub_cmd_cpuid, GRUB_COMMAND_FLAG_CMDLINE,
+                        "cpuid", "Check for CPU features", options);
+}
+
+GRUB_MOD_FINI(cpuid)
+{
+  grub_unregister_command ("cpuid");
+}
diff --git a/commands/i386/pc/halt.c b/commands/i386/pc/halt.c
new file mode 100644 (file)
index 0000000..c3660c5
--- /dev/null
@@ -0,0 +1,57 @@
+/* halt.c - command to halt the computer.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/machine/init.h>
+
+static const struct grub_arg_option options[] =
+  {
+    {"no-apm", 'n', 0, "do not use APM to halt the computer", 0, 0},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+static grub_err_t
+grub_cmd_halt (struct grub_arg_list *state,
+              int argc __attribute__ ((unused)),
+              char **args __attribute__ ((unused)))
+
+{
+  int no_apm = 0;
+  if (state[0].set)
+    no_apm = 1;
+  grub_halt (no_apm);
+  return 0;
+}
+
+
+\f
+GRUB_MOD_INIT(halt)
+{
+  (void)mod;                   /* To stop warning. */
+  grub_register_command ("halt", grub_cmd_halt, GRUB_COMMAND_FLAG_BOTH,
+                        "halt [-n]",
+                        "Halt the system, if possible using APM", options);
+}
+
+GRUB_MOD_FINI(halt)
+{
+  grub_unregister_command ("halt");
+}
diff --git a/commands/i386/pc/play.c b/commands/i386/pc/play.c
new file mode 100644 (file)
index 0000000..4fbae08
--- /dev/null
@@ -0,0 +1,217 @@
+/* play.c - command to play a tune  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+/* Lots of this file is borrowed from GNU/Hurd generic-speaker driver.  */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/machine/time.h>
+#include <grub/cpu/io.h>
+
+#define BASE_TEMPO 120
+
+/* The speaker port.  */
+#define SPEAKER                        0x61
+
+/* If 0, follow state of SPEAKER_DATA bit, otherwise enable output
+   from timer 2.  */
+#define SPEAKER_TMR2           0x01
+
+/* If SPEAKER_TMR2 is not set, this provides direct input into the
+   speaker.  Otherwise, this enables or disables the output from the
+   timer.  */
+#define SPEAKER_DATA           0x02
+
+/* The PIT channel value ports.  You can write to and read from them.
+   Do not mess with timer 0 or 1.  */
+#define PIT_COUNTER_0          0x40
+#define PIT_COUNTER_1          0x41
+#define PIT_COUNTER_2          0x42
+
+/* The frequency of the PIT clock.  */
+#define PIT_FREQUENCY          0x1234dd
+
+/* The PIT control port.  You can only write to it.  Do not mess with
+   timer 0 or 1.  */
+#define PIT_CTRL               0x43
+#define PIT_CTRL_SELECT_MASK   0xc0
+#define PIT_CTRL_SELECT_0      0x00
+#define PIT_CTRL_SELECT_1      0x40
+#define PIT_CTRL_SELECT_2      0x80
+
+/* Read and load control.  */
+#define PIT_CTRL_READLOAD_MASK 0x30
+#define PIT_CTRL_COUNTER_LATCH 0x00    /* Hold timer value until read.  */
+#define PIT_CTRL_READLOAD_LSB  0x10    /* Read/load the LSB.  */
+#define PIT_CTRL_READLOAD_MSB  0x20    /* Read/load the MSB.  */
+#define PIT_CTRL_READLOAD_WORD 0x30    /* Read/load the LSB then the MSB.  */
+
+/* Mode control.  */
+#define PIT_CTRL_MODE_MASK     0x0e
+
+/* Interrupt on terminal count.  Setting the mode sets output to low.
+   When counter is set and terminated, output is set to high.  */
+#define PIT_CTRL_INTR_ON_TERM  0x00
+
+/* Programmable one-shot.  When loading counter, output is set to
+   high.  When counter terminated, output is set to low.  Can be
+   triggered again from that point on by setting the gate pin to
+   high.  */
+#define PIT_CTRL_PROGR_ONE_SHOT        0x02
+
+/* Rate generator.  Output is low for one period of the counter, and
+   high for the other.  */
+#define PIT_CTRL_RATE_GEN      0x04
+
+/* Square wave generator.  Output is low for one half of the period,
+   and high for the other half.  */
+#define PIT_CTRL_SQUAREWAVE_GEN        0x06
+
+/* Software triggered strobe.  Setting the mode sets output to high.
+   When counter is set and terminated, output is set to low.  */
+#define PIT_CTRL_SOFTSTROBE    0x08
+
+/* Hardware triggered strobe.  Like software triggered strobe, but
+   only starts the counter when the gate pin is set to high.  */
+#define PIT_CTRL_HARDSTROBE    0x0a
+
+/* Count mode.  */
+#define PIT_CTRL_COUNT_MASK    0x01
+#define PIT_CTRL_COUNT_BINARY  0x00    /* 16-bit binary counter.  */
+#define PIT_CTRL_COUNT_BCD     0x01    /* 4-decade BCD counter.  */
+
+#define T_REST                 ((short) 0)
+#define T_FINE                 ((short) -1)
+
+struct note
+{
+  short pitch;
+  short duration;
+};
+
+static void
+beep_off (void)
+{
+  unsigned char status;
+
+  status = grub_inb (SPEAKER);
+  grub_outb (status & ~(SPEAKER_TMR2 | SPEAKER_DATA), SPEAKER);
+}
+
+static void
+beep_on (short pitch)
+{
+  unsigned char status;
+  unsigned int counter;
+
+  if (pitch < 20)
+    pitch = 20;
+  else if (pitch > 20000)
+    pitch = 20000;
+
+  counter = PIT_FREQUENCY / pitch;
+
+  /* Program timer 2.  */
+  grub_outb (PIT_CTRL_SELECT_2 | PIT_CTRL_READLOAD_WORD
+       | PIT_CTRL_SQUAREWAVE_GEN | PIT_CTRL_COUNT_BINARY, PIT_CTRL);
+  grub_outb (counter & 0xff, PIT_COUNTER_2);           /* LSB */
+  grub_outb ((counter >> 8) & 0xff, PIT_COUNTER_2);    /* MSB */
+
+  /* Start speaker.  */
+  status = grub_inb (SPEAKER);
+  grub_outb (status | SPEAKER_TMR2 | SPEAKER_DATA, SPEAKER);
+}
+
+static grub_err_t
+grub_cmd_play (struct grub_arg_list *state __attribute__ ((unused)),
+              int argc, char **args)
+{
+  grub_file_t file;
+  struct note buf;
+  int tempo;
+  unsigned int to;
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
+
+  file = grub_file_open (args[0]);
+  if (! file)
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+
+  if (grub_file_read (file, (void *) &tempo, sizeof(tempo)) != sizeof(tempo))
+    {
+      grub_file_close (file);
+      return grub_error (GRUB_ERR_FILE_READ_ERROR,
+                         "file doesn't even contains a full tempo record");
+    }
+
+  grub_dprintf ("play","tempo = %d\n", tempo);
+
+  while (grub_file_read (file, (void *) &buf,
+                         sizeof (struct note)) == sizeof (struct note)
+         && buf.pitch != T_FINE && grub_checkkey () < 0)
+    {
+      
+      grub_dprintf ("play", "pitch = %d, duration = %d\n", buf.pitch,
+                    buf.duration);
+
+      switch (buf.pitch)
+        {
+          case T_REST:
+            beep_off ();
+            break;
+
+          default:
+            beep_on (buf.pitch);
+            break;
+        }
+
+      to = grub_get_rtc () + BASE_TEMPO * buf.duration / tempo;
+      while (((unsigned int) grub_get_rtc () <= to) && (grub_checkkey () < 0))
+        ;
+
+    }
+
+  beep_off ();
+
+  grub_file_close (file);
+
+  while (grub_checkkey () > 0)
+    grub_getkey ();
+
+  return 0;
+}
+
+\f
+GRUB_MOD_INIT(play)
+{
+  (void)mod;                   /* To stop warning. */
+  grub_register_command ("play", grub_cmd_play, GRUB_COMMAND_FLAG_BOTH,
+                        "play FILE", "Play a tune", 0);
+}
+
+GRUB_MOD_FINI(play)
+{
+  grub_unregister_command ("play");
+}
diff --git a/commands/i386/pc/pxecmd.c b/commands/i386/pc/pxecmd.c
new file mode 100644 (file)
index 0000000..2a2aadc
--- /dev/null
@@ -0,0 +1,97 @@
+/* pxe.c - command to control the pxe driver  */
+/*
+ *  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/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/machine/pxe.h>
+
+static const struct grub_arg_option options[] =
+{
+    {"info", 'i', 0, "show PXE information.", 0, 0},
+    {"bsize", 'b', 0, "set PXE block size", 0, ARG_TYPE_INT},
+    {"unload", 'u', 0, "unload PXE stack.", 0, 0},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+static void
+print_ip (grub_uint32_t ip)
+{
+  int i;
+
+  for (i = 0; i < 3; i++)
+    {
+      grub_printf ("%d.", ip & 0xFF);
+      ip >>= 8;
+    }
+  grub_printf ("%d", ip);
+}
+
+static grub_err_t
+grub_cmd_pxe (struct grub_arg_list *state, int argc __attribute__ ((unused)),
+             char **args __attribute__ ((unused)))
+{
+  if (! grub_pxe_pxenv)
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no pxe environment");
+
+  if (state[1].set)
+    {
+      int size;
+
+      size = grub_strtoul (state[1].arg, 0, 0);
+      if (size < GRUB_PXE_MIN_BLKSIZE)
+        size = GRUB_PXE_MIN_BLKSIZE;
+      else if (size > GRUB_PXE_MAX_BLKSIZE)
+        size = GRUB_PXE_MAX_BLKSIZE;
+
+      grub_pxe_blksize = size;
+    }
+
+  if (state[0].set)
+    {
+      grub_printf ("blksize : %d\n", grub_pxe_blksize);
+      grub_printf ("client ip  : ");
+      print_ip (grub_pxe_your_ip);
+      grub_printf ("\nserver ip  : ");
+      print_ip (grub_pxe_server_ip);
+      grub_printf ("\ngateway ip : ");
+      print_ip (grub_pxe_gateway_ip);
+      grub_printf ("\n");
+    }
+
+  if (state[2].set)
+    grub_pxe_unload ();
+
+  return 0;
+}
+
+GRUB_MOD_INIT(pxecmd)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("pxe", grub_cmd_pxe, GRUB_COMMAND_FLAG_BOTH,
+                        "pxe [-i|-b|-u]",
+                         "Command to control the PXE device.", options);
+}
+
+GRUB_MOD_FINI(pxecmd)
+{
+  grub_unregister_command ("pxe");
+}
diff --git a/commands/i386/pc/vbeinfo.c b/commands/i386/pc/vbeinfo.c
new file mode 100644 (file)
index 0000000..237ecdd
--- /dev/null
@@ -0,0 +1,187 @@
+/* vbeinfo.c - command to list compatible VBE video modes.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/machine/init.h>
+#include <grub/machine/vbe.h>
+#include <grub/mm.h>
+
+static void *
+real2pm (grub_vbe_farptr_t ptr)
+{
+  return (void *) ((((unsigned long) ptr & 0xFFFF0000) >> 12UL)
+                  + ((unsigned long) ptr & 0x0000FFFF));
+}
+
+static grub_err_t
+grub_cmd_vbeinfo (struct grub_arg_list *state __attribute__ ((unused)),
+                 int argc __attribute__ ((unused)),
+                 char **args __attribute__ ((unused)))
+{
+  struct grub_vbe_info_block controller_info;
+  struct grub_vbe_mode_info_block mode_info_tmp;
+  grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE;
+  grub_uint16_t *video_mode_list;
+  grub_uint16_t *p;
+  grub_uint16_t *saved_video_mode_list;
+  grub_size_t video_mode_list_size;
+  grub_err_t err;
+  char *modevar;
+
+  err = grub_vbe_probe (&controller_info);
+  if (err != GRUB_ERR_NONE)
+    return err;
+
+  grub_printf ("VBE info:   version: %d.%d  OEM software rev: %d.%d\n",
+               controller_info.version >> 8, 
+               controller_info.version & 0xFF,
+               controller_info.oem_software_rev >> 8,
+               controller_info.oem_software_rev & 0xFF);
+
+  /* The total_memory field is in 64 KiB units.  */
+  grub_printf ("            total memory: %d KiB\n",
+               (controller_info.total_memory << 16) / 1024);
+
+  /* Because the information on video modes is stored in a temporary place,
+     it is better to copy it to somewhere safe.  */
+  p = video_mode_list = real2pm (controller_info.video_mode_ptr);
+  while (*p++ != 0xFFFF)
+    ;
+  
+  video_mode_list_size = (grub_addr_t) p - (grub_addr_t) video_mode_list;
+  saved_video_mode_list = grub_malloc (video_mode_list_size);
+  if (! saved_video_mode_list)
+    return grub_errno;
+
+  grub_memcpy (saved_video_mode_list, video_mode_list, video_mode_list_size);
+  
+  grub_printf ("List of compatible video modes:\n");
+  grub_printf ("Legend: P=Packed pixel, D=Direct color, "
+               "mask/pos=R/G/B/reserved\n"); 
+
+  /* Walk through all video modes listed.  */
+  for (p = saved_video_mode_list; *p != 0xFFFF; p++)
+    {
+      const char *memory_model = 0;
+      grub_uint32_t mode = (grub_uint32_t) *p;
+      
+      err = grub_vbe_get_video_mode_info (mode, &mode_info_tmp);
+      if (err != GRUB_ERR_NONE)
+       {
+         grub_errno = GRUB_ERR_NONE;
+         continue;
+       }
+
+      if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_SUPPORTED) == 0)
+       /* If not available, skip it.  */
+       continue;
+
+      if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_RESERVED_1) == 0)
+       /* Not enough information.  */
+       continue;
+
+      if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_COLOR) == 0)
+       /* Monochrome is unusable.  */
+       continue;
+
+      if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_LFB_AVAIL) == 0)
+       /* We support only linear frame buffer modes.  */
+       continue;
+
+      if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_GRAPHICS) == 0)
+       /* We allow only graphical modes.  */
+       continue;
+
+      switch (mode_info_tmp.memory_model)
+       {
+       case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL:
+         memory_model = "Packed";
+         break;
+       case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR:
+         memory_model = "Direct";
+         break;
+
+       default:
+         break;
+       }
+
+      if (! memory_model)
+       continue;
+
+      grub_printf ("0x%03x:  %4d x %4d x %2d  %s", 
+                   mode,
+                   mode_info_tmp.x_resolution,
+                   mode_info_tmp.y_resolution,
+                   mode_info_tmp.bits_per_pixel,
+                   memory_model);
+
+      /* Show mask and position details for direct color modes.  */
+      if (mode_info_tmp.memory_model == GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR)
+        grub_printf (", mask: %d/%d/%d/%d  pos: %d/%d/%d/%d",
+                     mode_info_tmp.red_mask_size,
+                     mode_info_tmp.green_mask_size,
+                     mode_info_tmp.blue_mask_size,
+                     mode_info_tmp.rsvd_mask_size,
+                     mode_info_tmp.red_field_position,
+                     mode_info_tmp.green_field_position,
+                     mode_info_tmp.blue_field_position,
+                     mode_info_tmp.rsvd_field_position);
+      grub_printf ("\n");
+    }
+
+  grub_free (saved_video_mode_list);
+  
+  /* Check existence of vbe_mode environment variable.  */
+  modevar = grub_env_get ("vbe_mode");
+
+  if (modevar != 0)
+    {
+      unsigned long value;
+
+      value = grub_strtoul (modevar, 0, 0);
+      if (grub_errno == GRUB_ERR_NONE)
+       use_mode = value;
+      else
+       grub_errno = GRUB_ERR_NONE;
+    }
+
+  grub_printf ("Configured VBE mode (vbe_mode) = 0x%03x\n", use_mode);
+
+  return 0;
+}
+
+GRUB_MOD_INIT(vbeinfo)
+{
+  (void) mod;                  /* To stop warning.  */
+  grub_register_command ("vbeinfo",
+                         grub_cmd_vbeinfo,
+                         GRUB_COMMAND_FLAG_BOTH,
+                         "vbeinfo",
+                         "List compatible VESA BIOS extension video modes.",
+                         0);
+}
+
+GRUB_MOD_FINI(vbeinfo)
+{
+  grub_unregister_command ("vbeinfo");
+}
diff --git a/commands/i386/pc/vbetest.c b/commands/i386/pc/vbetest.c
new file mode 100644 (file)
index 0000000..570421d
--- /dev/null
@@ -0,0 +1,179 @@
+/* vbetest.c - command to test VESA BIOS Extension 2.0+ support.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/term.h>
+#include <grub/machine/init.h>
+#include <grub/machine/vbe.h>
+#include <grub/err.h>
+
+static grub_err_t
+grub_cmd_vbetest (struct grub_arg_list *state __attribute__ ((unused)),
+                 int argc __attribute__ ((unused)),
+                 char **args __attribute__ ((unused)))
+{
+  grub_err_t err;
+  char *modevar;
+  struct grub_vbe_mode_info_block mode_info;
+  struct grub_vbe_info_block controller_info;
+  grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE;
+  grub_uint32_t old_mode;
+  grub_uint8_t *framebuffer = 0;
+  grub_uint32_t bytes_per_scan_line = 0;
+  unsigned char *ptr;
+  int i;
+
+  grub_printf ("Probing for VESA BIOS Extension ... ");
+
+  /* Check if VESA BIOS exists.  */
+  err = grub_vbe_probe (&controller_info);
+  if (err != GRUB_ERR_NONE)
+    return err;
+
+  grub_printf ("found!\n");
+
+  /* Dump out controller information.  */
+  grub_printf ("VBE signature = %c%c%c%c\n",
+              controller_info.signature[0],
+              controller_info.signature[1],
+              controller_info.signature[2],
+              controller_info.signature[3]);
+
+  grub_printf ("VBE version = %d.%d\n",
+              controller_info.version >> 8,
+              controller_info.version & 0xFF);
+  grub_printf ("OEM string ptr = %08x\n",
+              controller_info.oem_string_ptr);
+  grub_printf ("Total memory = %d\n",
+              controller_info.total_memory);
+
+  err = grub_vbe_get_video_mode (&old_mode);
+  grub_printf ("Get video mode err = %04x\n", err);
+
+  if (err == GRUB_ERR_NONE)
+    grub_printf ("Old video mode = %04x\n", old_mode);
+  else
+    grub_errno = GRUB_ERR_NONE;
+  
+  /* Check existence of vbe_mode environment variable.  */
+  modevar = grub_env_get ("vbe_mode");
+  if (modevar != 0)
+    {
+      unsigned long value;
+
+      value = grub_strtoul (modevar, 0, 0);
+      if (grub_errno == GRUB_ERR_NONE)
+       use_mode = value;
+      else
+       grub_errno = GRUB_ERR_NONE;
+    }
+
+  err = grub_vbe_get_video_mode_info (use_mode, &mode_info);
+  if (err != GRUB_ERR_NONE)
+    return err;
+  
+  /* Dump out details about the mode being tested.  */
+  grub_printf ("mode: 0x%03x\n",
+               use_mode);
+  grub_printf ("width : %d\n",
+               mode_info.x_resolution);
+  grub_printf ("height: %d\n",
+               mode_info.y_resolution);
+  grub_printf ("memory model: %02x\n",
+               mode_info.memory_model);
+  grub_printf ("bytes/scanline: %d\n",
+               mode_info.bytes_per_scan_line);
+  grub_printf ("bytes/scanline (lin): %d\n",
+               mode_info.lin_bytes_per_scan_line);
+  grub_printf ("base address: %08x\n",
+               mode_info.phys_base_addr);
+  grub_printf ("red mask/pos: %d/%d\n",
+               mode_info.red_mask_size,
+               mode_info.red_field_position);
+  grub_printf ("green mask/pos: %d/%d\n",
+               mode_info.green_mask_size,
+               mode_info.green_field_position);
+  grub_printf ("blue mask/pos: %d/%d\n",
+               mode_info.blue_mask_size,
+               mode_info.blue_field_position);
+
+  grub_printf ("Press any key to continue.\n");
+
+  grub_getkey ();
+
+  /* Setup GFX mode.  */
+  err = grub_vbe_set_video_mode (use_mode, &mode_info);
+  if (err != GRUB_ERR_NONE)
+    return err;
+
+  /* Determine framebuffer address and how many bytes are in scan line.  */
+  framebuffer = (grub_uint8_t *) mode_info.phys_base_addr;
+  ptr = framebuffer;
+
+  if (controller_info.version >= 0x300)
+    {
+      bytes_per_scan_line = mode_info.lin_bytes_per_scan_line;
+    }
+  else
+    {
+      bytes_per_scan_line = mode_info.bytes_per_scan_line;
+    }
+
+  /* Draw some random data to screen.  */
+  for (i = 0; i < 256 * 256; i++)
+    {
+      ptr[i] = i & 0x0F;
+    }
+
+  /* Draw white line to screen.  */
+  for (i = 0; i < 100; i++)
+    {
+      ptr[mode_info.bytes_per_scan_line * 50 + i] = 0x0F;
+    }
+
+  /* Draw another white line to screen.  */
+  grub_memset (ptr + bytes_per_scan_line * 51, 0x0f, bytes_per_scan_line);
+
+  grub_getkey ();
+
+  /* Restore old video mode.  */
+  grub_vbe_set_video_mode (old_mode, 0);
+
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(vbetest)
+{
+  (void) mod;                  /* To stop warning.  */
+  grub_register_command ("vbetest",
+                         grub_cmd_vbetest,
+                         GRUB_COMMAND_FLAG_BOTH,
+                         "vbetest",
+                         "Test VESA BIOS Extension 2.0+ support",
+                         0);
+}
+
+GRUB_MOD_FINI(vbetest)
+{
+  grub_unregister_command ("vbetest");
+}
diff --git a/commands/ieee1275/suspend.c b/commands/ieee1275/suspend.c
new file mode 100644 (file)
index 0000000..e6b9feb
--- /dev/null
@@ -0,0 +1,48 @@
+/* suspend.c - command to suspend GRUB and return to Open Firmware  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/term.h>
+#include <grub/ieee1275/ieee1275.h>
+
+static grub_err_t
+grub_cmd_suspend (struct grub_arg_list *state  __attribute__ ((unused)),
+                 int argc __attribute__ ((unused)),
+                 char **args __attribute__ ((unused)))
+{
+  grub_printf ("Run 'go' to resume GRUB.\n");
+  grub_ieee1275_enter ();
+  grub_cls ();
+  return 0;
+}
+
+\f
+GRUB_MOD_INIT(ieee1275_suspend)
+{
+  (void)mod;                   /* To stop warning. */
+  grub_register_command ("suspend", grub_cmd_suspend, GRUB_COMMAND_FLAG_BOTH,
+                        "suspend", "Return to Open Firmware prompt", 0);
+}
+
+GRUB_MOD_FINI(ieee1275_suspend)
+{
+  grub_unregister_command ("suspend");
+}
diff --git a/commands/loadenv.c b/commands/loadenv.c
new file mode 100644 (file)
index 0000000..4dbf1d9
--- /dev/null
@@ -0,0 +1,257 @@
+/* loadenv.c - command to load/save environment variable.  */
+/*
+ *  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/normal.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/arg.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/partition.h>
+#include <grub/lib/envblk.h>
+
+static const struct grub_arg_option options[] =
+  {
+    {"file", 'f', 0, "specify filename", 0, ARG_TYPE_PATHNAME},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+char buffer[GRUB_ENVBLK_MAXLEN];
+grub_envblk_t envblk;
+
+static grub_file_t
+read_envblk_file (char *filename, void NESTED_FUNC_ATTR read_hook (grub_disk_addr_t sector, unsigned offset, unsigned length))
+{
+  char *buf = 0;
+  grub_file_t file;
+
+  if (! filename)
+    {
+      char *prefix;
+
+      prefix = grub_env_get ("prefix");
+      if (prefix)
+        {
+          int len;
+
+          len = grub_strlen (prefix);
+          buf = grub_malloc (len + 1 + sizeof (GRUB_ENVBLK_DEFCFG));
+          grub_strcpy (buf, prefix);
+          buf[len] = '/';
+          grub_strcpy (buf + len + 1, GRUB_ENVBLK_DEFCFG);
+          filename = buf;
+        }
+      else
+        {
+          grub_error (GRUB_ERR_FILE_NOT_FOUND, "prefix is not found");
+          return 0;
+        }
+    }
+
+  file = grub_file_open (filename);
+  grub_free (buf);
+  if (! file)
+    return 0;
+
+  if (read_hook)
+    {
+      if (! file->device->disk)
+        {
+          grub_file_close (file);
+          grub_error (GRUB_ERR_BAD_DEVICE,
+                      "this command is available only for disk devices.");
+          return 0;
+        }
+      file->read_hook = read_hook;
+    }
+
+  if (grub_file_read (file, buffer, GRUB_ENVBLK_MAXLEN) != GRUB_ENVBLK_MAXLEN)
+    {
+      grub_file_close (file);
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "file too short");
+      return 0;
+    }
+
+  envblk = grub_envblk_find (buffer);
+  if (! envblk)
+    {
+      grub_file_close (file);
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "environment block not found");
+      return 0;
+    }
+
+  return file;
+}
+
+static grub_err_t
+grub_cmd_load_env (struct grub_arg_list *state,
+                   int argc __attribute__ ((unused)), char **args __attribute__ ((unused)))
+
+{
+  grub_file_t file;
+
+  auto int hook (char *name, char *value);
+  int hook (char *name, char *value)
+    {
+      grub_env_set (name, value);
+
+      return 0;
+    }
+
+  file = read_envblk_file ((state[0].set) ? state[0].arg : 0, 0);
+  if (! file)
+    return grub_errno;
+
+  grub_file_close (file);
+
+  grub_envblk_iterate (envblk, hook);
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_cmd_list_env (struct grub_arg_list *state,
+                   int argc __attribute__ ((unused)), char **args __attribute__ ((unused)))
+{
+  grub_file_t file;
+
+  auto int hook (char *name, char *value);
+  int hook (char *name, char *value)
+    {
+      grub_printf ("%s=%s\n", name, value);
+
+      return 0;
+    }
+
+  file = read_envblk_file ((state[0].set) ? state[0].arg : 0, 0);
+  if (! file)
+    return grub_errno;
+
+  grub_file_close (file);
+
+  grub_envblk_iterate (envblk, hook);
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_cmd_save_env (struct grub_arg_list *state, int argc, char **args)
+{
+  grub_file_t file;
+  grub_disk_t disk;
+  grub_disk_addr_t addr[GRUB_ENVBLK_MAXLEN >> GRUB_DISK_SECTOR_BITS];
+  char buf[GRUB_DISK_SECTOR_SIZE];
+  grub_disk_addr_t part_start = 0;
+  int num = 0;
+
+  auto void NESTED_FUNC_ATTR hook (grub_disk_addr_t sector, unsigned offset,
+                                   unsigned length);
+
+  void NESTED_FUNC_ATTR hook (grub_disk_addr_t sector,
+                              unsigned offset, unsigned length)
+    {
+      if ((offset != 0) || (length != GRUB_DISK_SECTOR_SIZE))
+        return;
+
+      if (num < (GRUB_ENVBLK_MAXLEN >> GRUB_DISK_SECTOR_BITS))
+        addr[num++] = sector;
+    }
+
+  if (! argc)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "No variable is specified");
+
+  file = read_envblk_file ((state[0].set) ? state[0].arg : 0, hook);
+  if (! file)
+    return grub_errno;
+
+  file->read_hook = 0;
+
+  if (num != GRUB_ENVBLK_MAXLEN >> GRUB_DISK_SECTOR_BITS)
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, "invalid blocklist");
+      goto quit;
+    }
+
+  disk = file->device->disk;
+  if (disk->partition)
+    part_start = grub_partition_get_start (disk->partition);
+
+  for (num = 0; num < (GRUB_ENVBLK_MAXLEN >> GRUB_DISK_SECTOR_BITS); num++)
+    {
+      if (grub_disk_read (disk, addr[num] - part_start, 0,
+                          GRUB_DISK_SECTOR_SIZE,  buf))
+        goto quit;
+
+      if (grub_memcmp (&buffer[num << GRUB_DISK_SECTOR_BITS], buf,
+                       GRUB_DISK_SECTOR_SIZE))
+        {
+          grub_error (GRUB_ERR_BAD_DEVICE, "invalid blocklist");
+          goto quit;
+        }
+    }
+
+  while (argc)
+    {
+      char *value;
+
+      value = grub_env_get (args[0]);
+      if (value)
+        {
+          if (grub_envblk_insert (envblk, args[0], value))
+            {
+              grub_error (GRUB_ERR_BAD_ARGUMENT, "environment block too small");
+              goto quit;
+            }
+        }
+
+      argc--;
+      args++;
+    }
+
+  for (num = 0; num < (GRUB_ENVBLK_MAXLEN >> GRUB_DISK_SECTOR_BITS); num++)
+    if (grub_disk_write (disk, addr[num] - part_start, 0,
+                         GRUB_DISK_SECTOR_SIZE,
+                         &buffer[num << GRUB_DISK_SECTOR_BITS]))
+      goto quit;
+
+quit:
+  grub_file_close (file);
+
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(loadenv)
+{
+  (void) mod;
+  grub_register_command ("load_env", grub_cmd_load_env, GRUB_COMMAND_FLAG_BOTH,
+                        "load_env [-f FILE]", "Load variables from environment block file.", options);
+  grub_register_command ("list_env", grub_cmd_list_env, GRUB_COMMAND_FLAG_BOTH,
+                        "list_env [-f FILE]", "List variables from environment block file.", options);
+  grub_register_command ("save_env", grub_cmd_save_env, GRUB_COMMAND_FLAG_BOTH,
+                        "save_env [-f FILE] variable_name [...]", "Save variables to environment block file.", options);
+}
+
+GRUB_MOD_FINI(loadenv)
+{
+  grub_unregister_command ("load_env");
+  grub_unregister_command ("list_env");
+  grub_unregister_command ("save_env");
+}
diff --git a/commands/ls.c b/commands/ls.c
new file mode 100644 (file)
index 0000000..7f5a609
--- /dev/null
@@ -0,0 +1,245 @@
+/* ls.c - command to list files and devices */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2005,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/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/arg.h>
+#include <grub/disk.h>
+#include <grub/device.h>
+#include <grub/term.h>
+#include <grub/partition.h>
+#include <grub/file.h>
+
+static const struct grub_arg_option options[] =
+  {
+    {"long", 'l', 0, "show a long list with more detailed information", 0, 0},
+    {"human-readable", 'h', 0, "print sizes in a human readable format", 0, 0},
+    {"all", 'a', 0, "list all files", 0, 0},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+static const char grub_human_sizes[] = {' ', 'K', 'M', 'G', 'T'};
+
+static grub_err_t
+grub_ls_list_devices (int longlist)
+{
+  auto int grub_ls_print_devices (const char *name);
+  int grub_ls_print_devices (const char *name)
+    {
+      if (longlist)
+       grub_normal_print_device_info (name);
+      else
+       grub_printf ("(%s) ", name);
+  
+      return 0;
+    }
+  
+  grub_device_iterate (grub_ls_print_devices);
+  grub_putchar ('\n');
+  grub_refresh ();
+
+  return 0;
+}
+
+static grub_err_t
+grub_ls_list_files (char *dirname, int longlist, int all, int human)
+{
+  char *device_name;
+  grub_fs_t fs;
+  const char *path;
+  grub_device_t dev;
+  auto int print_files (const char *filename, int dir);
+  auto int print_files_long (const char *filename, int dir);
+  
+  int print_files (const char *filename, int dir)
+    {
+      if (all || filename[0] != '.')
+       grub_printf ("%s%s ", filename, dir ? "/" : "");
+      
+      return 0;
+    }
+     
+  int print_files_long (const char *filename, int dir)
+    {
+      char pathname[grub_strlen (dirname) + grub_strlen (filename) + 1];
+
+      if ((! all) && (filename[0] == '.'))
+       return 0;
+
+      if (! dir)
+       {
+         grub_file_t file;
+         
+         if (dirname[grub_strlen (dirname) - 1] == '/')
+           grub_sprintf (pathname, "%s%s", dirname, filename);
+         else
+           grub_sprintf (pathname, "%s/%s", dirname, filename);
+
+         /* XXX: For ext2fs symlinks are detected as files while they
+            should be reported as directories.  */
+         file = grub_file_open (pathname);
+         if (! file)
+           {
+             grub_errno = 0;
+             return 0;
+           }
+
+         if (! human)
+           grub_printf ("%-12llu", (unsigned long long) file->size);
+         else
+           {
+             grub_uint64_t fsize = file->size * 100ULL;
+             int fsz = file->size;
+             int units = 0;
+             char buf[20];
+             
+             while (fsz / 1024)
+               {
+                 fsize = (fsize + 512) / 1024;
+                 fsz /= 1024;
+                 units++;
+               }
+
+             if (units)
+               {
+                 grub_uint32_t whole, fraction;
+
+                 whole = grub_divmod64 (fsize, 100, &fraction);
+                 grub_sprintf (buf, "%u.%02u%c", whole, fraction,
+                               grub_human_sizes[units]);
+                 grub_printf ("%-12s", buf);
+               }
+             else
+               grub_printf ("%-12llu", (unsigned long long) file->size);
+             
+           }
+         grub_file_close (file);
+       }
+      else
+       grub_printf ("%-12s", "DIR");
+
+      grub_printf ("%s%s\n", filename, dir ? "/" : "");
+
+      return 0;
+    }
+
+  device_name = grub_file_get_device_name (dirname);
+  dev = grub_device_open (device_name);
+  if (! dev)
+    goto fail;
+
+  fs = grub_fs_probe (dev);
+  path = grub_strchr (dirname, ')');
+  if (! path)
+    path = dirname;
+  else
+    path++;
+  
+  if (! path && ! device_name)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument");
+      goto fail;
+    }
+      
+  if (! *path)
+    {
+      if (grub_errno == GRUB_ERR_UNKNOWN_FS)
+       grub_errno = GRUB_ERR_NONE;
+
+      grub_normal_print_device_info (device_name);
+    }
+  else if (fs)
+    {
+      if (longlist)
+       (fs->dir) (dev, path, print_files_long);
+      else
+       (fs->dir) (dev, path, print_files);
+
+      if (grub_errno == GRUB_ERR_BAD_FILE_TYPE
+         && path[grub_strlen (path) - 1] != '/')
+       {
+         /* PATH might be a regular file.  */
+         char *p;
+         grub_file_t file;
+
+         grub_errno = 0;
+         
+         file = grub_file_open (dirname);
+         if (! file)
+           goto fail;
+         
+         grub_file_close (file);
+         
+         p = grub_strrchr (dirname, '/') + 1;
+         dirname = grub_strndup (dirname, p - dirname);
+         if (! dirname)
+           goto fail;
+
+         all = 1;
+         if (longlist)
+           print_files_long (p, 0);
+         else
+           print_files (p, 0);
+
+         grub_free (dirname);
+       }
+
+      if (grub_errno == GRUB_ERR_NONE)
+       grub_putchar ('\n');
+      
+      grub_refresh ();
+    }
+
+ fail:
+  if (dev)
+    grub_device_close (dev);
+      
+  grub_free (device_name);
+
+  return 0;
+}
+
+static grub_err_t
+grub_cmd_ls (struct grub_arg_list *state, int argc, char **args)
+{
+  if (argc == 0)
+    grub_ls_list_devices (state[0].set);
+  else
+    grub_ls_list_files (args[0], state[0].set, state[2].set,
+                       state[1].set);
+
+  return 0;
+}
+
+GRUB_MOD_INIT(ls)
+{
+  (void)mod;                   /* To stop warning. */
+  grub_register_command ("ls", grub_cmd_ls, GRUB_COMMAND_FLAG_BOTH,
+                        "ls [-l|-h|-a] [FILE]",
+                        "List devices and files.", options);
+}
+
+GRUB_MOD_FINI(ls)
+{
+  grub_unregister_command ("ls");
+}
diff --git a/commands/lsmmap.c b/commands/lsmmap.c
new file mode 100644 (file)
index 0000000..c705591
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  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/machine/memory.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/misc.h>
+
+static grub_err_t
+grub_cmd_lsmmap (struct grub_arg_list *state __attribute__ ((unused)),
+                int argc __attribute__ ((unused)), char **args __attribute__ ((unused)))
+
+{
+  auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
+    {
+      grub_printf ("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n",
+                  addr, size, type);
+      return 0;
+    }
+  grub_machine_mmap_iterate (hook);
+
+  return 0;
+}
+
+\f
+GRUB_MOD_INIT(lsmmap)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("lsmmap", grub_cmd_lsmmap, GRUB_COMMAND_FLAG_BOTH,
+                        "lsmmap", "List memory map provided by firmware.", 0);
+}
+
+GRUB_MOD_FINI(lsmmap)
+{
+  grub_unregister_command ("lsmmap");
+}
diff --git a/commands/lspci.c b/commands/lspci.c
new file mode 100644 (file)
index 0000000..9791800
--- /dev/null
@@ -0,0 +1,171 @@
+/* lspci.c - List PCI devices.  */
+/*
+ *  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/pci.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/misc.h>
+
+struct grub_pci_classname
+{
+  int class;
+  int subclass;
+  char *desc;
+};
+
+static const struct grub_pci_classname grub_pci_classes[] =
+  {
+    { 0, 0, "" },
+    { 1, 0, "SCSI Controller" },
+    { 1, 1, "IDE Controller" },
+    { 1, 2, "Floppy Controller" },
+    { 1, 3, "IPI Controller" },
+    { 1, 4, "RAID Controller" },
+    { 1, 6, "SATA Controller" },
+    { 1, 0x80, "Mass storage Controller" },
+    { 2, 0, "Ethernet Controller" },
+    { 2, 1, "Token Ring Controller" },
+    { 2, 2, "FDDI Controller" },
+    { 2, 3, "ATM Controller" },
+    { 2, 4, "ISDN Controller" },
+    { 2, 0x80, "Network controller" },
+    { 3, 0, "VGA Controller" },
+    { 3, 1, "XGA Controller" },
+    { 3, 2, "3D Controller" },
+    { 3, 0x80, "Display Controller" },
+    { 4, 0, "Multimedia Video Device" },
+    { 4, 1, "Multimedia Audio Device" },
+    { 4, 2, "Multimedia Telephony Device" },
+    { 4, 0x80, "Multimedia device" },
+    { 5, 0, "RAM Controller" },
+    { 5, 1, "Flash Memory Controller" },
+    { 5, 0x80, "Memory Controller" },
+    { 6, 0, "Host Bridge" },
+    { 6, 1, "ISA Bridge" },
+    { 6, 2, "EISA Bride" },
+    { 6, 3, "MCA Bridge" },
+    { 6, 4, "PCI-PCI Bridge" },
+    { 6, 5, "PCMCIA Bridge" },
+    { 6, 6, "NuBus Bridge" },
+    { 6, 7, "CardBus Bridge" },
+    { 6, 8, "Raceway Bridge" },
+    { 6, 0x80, "Unknown Bridge" },
+    { 7, 0x80, "Communication controller" },
+    { 8, 0x80, "System hardware" },
+    { 9, 0, "Keyboard Controller" },
+    { 9, 1, "Digitizer" },
+    { 9, 2, "Mouse Controller" },
+    { 9, 3, "Scanner Controller" },
+    { 9, 4, "Gameport Controller" },
+    { 9, 0x80, "Unknown Input Device" },
+    { 10, 0, "Generic Docking Station" },
+    { 10, 0x80, "Unknown Docking Station" },
+    { 11, 0, "80386 Processor" },
+    { 11, 1, "80486 Processor" },
+    { 11, 2, "Pentium Processor" },
+    { 11, 0x10, "Alpha Processor" },
+    { 11, 0x20, "PowerPC Processor" },
+    { 11, 0x30, "MIPS Processor" },
+    { 11, 0x40, "Co-Processor" },
+    { 11, 0x80, "Unknown Processor" },
+    { 12, 0x80, "Serial Bus Controller" },
+    { 13, 0x80, "Wireless Controller" },
+    { 14, 0, "I2O" },
+    { 15, 0, "IrDA Controller" },
+    { 15, 1, "Consumer IR" },
+    { 15, 0x10, "RF-Controller" },
+    { 15, 0x80, "Satellite Communication Controller" },
+    { 16, 0, "Network Decryption" },
+    { 16, 1, "Entertainment Decryption" },
+    { 16, 0x80, "Unknown Decryption Controller" },
+    { 17, 0, "Digital IO Module" },
+    { 17, 0x80, "Unknown Data Input System" },
+    { 0, 0, 0 },
+  };
+
+static const char *
+grub_pci_get_class (int class, int subclass)
+{
+  const struct grub_pci_classname *curr = grub_pci_classes;
+
+  while (curr->desc)
+    {
+      if (curr->class == class && curr->subclass == subclass)
+       return curr->desc;
+      curr++;
+    }
+
+  return 0;
+}
+
+static int
+grub_lspci_iter (int bus, int dev, int func, grub_pci_id_t pciid)
+{
+  grub_uint32_t class;
+  const char *sclass;
+  grub_pci_address_t addr;
+
+  grub_printf ("%02x:%02x.%x %04x:%04x", bus, dev, func, pciid & 0xFFFF,
+              pciid >> 16);
+  addr = grub_pci_make_address (bus, dev, func, 2);
+  class = grub_pci_read (addr);
+
+  /* Lookup the class name, if there isn't a specific one,
+     retry with 0x80 to get the generic class name.  */
+  sclass = grub_pci_get_class (class >> 24, (class >> 16) & 0xFF);
+  if (! sclass)
+    sclass = grub_pci_get_class (class >> 24, 0x80);
+  if (! sclass)
+    sclass = "";
+
+  grub_printf (" [%04x] %s", (class >> 16) & 0xffff, sclass);
+
+  grub_uint8_t pi = (class >> 8) & 0xff;
+  if (pi)
+    grub_printf (" [PI %02x]", pi);
+
+  grub_printf ("\n");
+
+  return 0;
+}
+
+static grub_err_t
+grub_cmd_lspci (struct grub_arg_list *state __attribute__ ((unused)),
+               int argc __attribute__ ((unused)),
+               char **args __attribute__ ((unused)))
+{
+  grub_pci_iterate (grub_lspci_iter);
+  return GRUB_ERR_NONE;
+}
+
+
+\f
+
+GRUB_MOD_INIT(pci)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("lspci", grub_cmd_lspci, GRUB_COMMAND_FLAG_BOTH,
+                        "lspci", "List PCI devices", 0);
+}
+
+
+GRUB_MOD_FINI(pci)
+{
+  grub_unregister_command ("lspci");
+}
diff --git a/commands/read.c b/commands/read.c
new file mode 100644 (file)
index 0000000..4aa4f76
--- /dev/null
@@ -0,0 +1,86 @@
+/* read.c - Command to read variables from user.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/normal.h>
+#include <grub/term.h>
+#include <grub/types.h>
+
+static char *
+grub_getline (void)
+{
+  int i;
+  char *line;
+  char *tmp;
+  char c;
+
+  i = 0;
+  line = grub_malloc (1 + i + sizeof('\0'));
+  if (! line)
+    return NULL;
+
+  while (1)
+    {
+      c = grub_getkey ();
+      if ((c == '\n') || (c == '\r'))
+       break;
+
+      line[i] = c;
+      if (grub_isprint (c))
+       grub_putchar (c);
+      i++;
+      tmp = grub_realloc (line, 1 + i + sizeof('\0'));
+      if (! tmp)
+       {
+         grub_free (line);
+         return NULL;
+       }
+      line = tmp;
+    }
+  line[i] = '\0';
+
+  return line;
+}
+
+static grub_err_t
+grub_cmd_read (struct grub_arg_list *state UNUSED, int argc, char **args)
+{
+  char *line = grub_getline ();
+  if (! line)
+    return grub_errno;
+  if (argc > 0)
+    grub_env_set (args[0], line);
+
+  grub_free (line);
+  return 0;
+}
+
+\f
+GRUB_MOD_INIT(read)
+{
+  grub_register_command ("read", grub_cmd_read, GRUB_COMMAND_FLAG_CMDLINE,
+                        "read [ENVVAR]", "Set variable with user input", 0);
+}
+
+GRUB_MOD_FINI(read)
+{
+  grub_unregister_command ("read");
+}
diff --git a/commands/reboot.c b/commands/reboot.c
new file mode 100644 (file)
index 0000000..bff7a57
--- /dev/null
@@ -0,0 +1,56 @@
+/* reboot.c - command to reboot the computer.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/machine/machine.h>
+
+#if defined(GRUB_MACHINE_IEEE1275)
+#include <grub/machine/kernel.h>
+#elif defined(GRUB_MACHINE_EFI)
+#include <grub/efi/efi.h>
+#elif defined(GRUB_MACHINE_PCBIOS)
+#include <grub/machine/init.h>
+#else
+/* Platforms shipping standalone reboot, such as coreboot.  */
+#include <grub/cpu/reboot.h>
+#endif
+
+
+static grub_err_t
+grub_cmd_reboot (struct grub_arg_list *state __attribute__ ((unused)),
+                int argc __attribute__ ((unused)),
+                char **args __attribute__ ((unused)))
+{
+  grub_reboot ();
+  return 0;
+}
+
+\f
+GRUB_MOD_INIT(reboot)
+{
+  (void)mod;                   /* To stop warning. */
+  grub_register_command ("reboot", grub_cmd_reboot, GRUB_COMMAND_FLAG_BOTH,
+                        "reboot", "Reboot the computer", 0);
+}
+
+GRUB_MOD_FINI(reboot)
+{
+  grub_unregister_command ("reboot");
+}
diff --git a/commands/search.c b/commands/search.c
new file mode 100644 (file)
index 0000000..a07259a
--- /dev/null
@@ -0,0 +1,234 @@
+/* search.c - search devices based on a file or a filesystem label */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,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/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/arg.h>
+#include <grub/device.h>
+#include <grub/file.h>
+#include <grub/env.h>
+
+static const struct grub_arg_option options[] =
+  {
+    {"file", 'f', 0, "search devices by a file (default)", 0, 0},
+    {"label", 'l', 0, "search devices by a filesystem label", 0, 0},
+    {"fs-uuid", 'u', 0, "search devices by a filesystem UUID", 0, 0},
+    {"set", 's', GRUB_ARG_OPTION_OPTIONAL, "set a variable to the first device found", "VAR", ARG_TYPE_STRING},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+static void
+search_label (const char *key, const char *var)
+{
+  int count = 0;
+  auto int iterate_device (const char *name);
+
+  int iterate_device (const char *name)
+    {
+      grub_device_t dev;
+      int abort = 0;
+      
+      dev = grub_device_open (name);
+      if (dev)
+       {
+         grub_fs_t fs;
+         
+         fs = grub_fs_probe (dev);
+         if (fs && fs->label)
+           {
+             char *label;
+             
+             (fs->label) (dev, &label);
+             if (grub_errno == GRUB_ERR_NONE && label)
+               {
+                 if (grub_strcmp (label, key) == 0)
+                   {
+                     /* Found!  */
+                     count++;
+                     if (var)
+                       {
+                         grub_env_set (var, name);
+                         abort = 1;
+                       }
+                     else
+                         grub_printf (" %s", name);
+                   }
+                 
+                 grub_free (label);
+               }
+           }
+         
+         grub_device_close (dev);
+       }
+
+      grub_errno = GRUB_ERR_NONE;
+      return abort;
+    }
+  
+  grub_device_iterate (iterate_device);
+  
+  if (count == 0)
+    grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key);
+}
+
+static void
+search_fs_uuid (const char *key, const char *var)
+{
+  int count = 0;
+  auto int iterate_device (const char *name);
+
+  int iterate_device (const char *name)
+    {
+      grub_device_t dev;
+      int abort = 0;
+
+      dev = grub_device_open (name);
+      if (dev)
+       {
+         grub_fs_t fs;
+         
+         fs = grub_fs_probe (dev);
+         if (fs && fs->uuid)
+           {
+             char *uuid;
+             
+             (fs->uuid) (dev, &uuid);
+             if (grub_errno == GRUB_ERR_NONE && uuid)
+               {
+                 if (grub_strcasecmp (uuid, key) == 0)
+                   {
+                     /* Found!  */
+                     count++;
+                     if (var)
+                       {
+                         grub_env_set (var, name);
+                         abort = 1;
+                       }
+                     else
+                       grub_printf (" %s", name);
+                   }
+                 
+                 grub_free (uuid);
+               }
+           }
+         
+         grub_device_close (dev);
+       }
+
+      grub_errno = GRUB_ERR_NONE;
+      return abort;
+    }
+  
+  grub_device_iterate (iterate_device);
+  
+  if (count == 0)
+    grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key);
+}
+
+static void
+search_file (const char *key, const char *var)
+{
+  int count = 0;
+  char *buf = 0;
+  auto int iterate_device (const char *name);
+
+  int iterate_device (const char *name)
+    {
+      grub_size_t len;
+      char *p;
+      grub_file_t file;
+      int abort = 0;
+      
+      len = grub_strlen (name) + 2 + grub_strlen (key) + 1;
+      p = grub_realloc (buf, len);
+      if (! p)
+       return 1;
+
+      buf = p;
+      grub_sprintf (buf, "(%s)%s", name, key);
+      
+      file = grub_file_open (buf);
+      if (file)
+       {
+         /* Found!  */
+         count++;
+         if (var)
+           {
+             grub_env_set (var, name);
+             abort = 1;
+           }
+         else
+           grub_printf (" %s", name);
+
+         grub_file_close (file);
+       }
+      
+      grub_errno = GRUB_ERR_NONE;
+      return abort;
+    }
+  
+  grub_device_iterate (iterate_device);
+  
+  grub_free (buf);
+  
+  if (grub_errno == GRUB_ERR_NONE && count == 0)
+    grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device");
+}
+
+static grub_err_t
+grub_cmd_search (struct grub_arg_list *state, int argc, char **args)
+{
+  const char *var = 0;
+  
+  if (argc == 0)
+    return grub_error (GRUB_ERR_INVALID_COMMAND, "no argument specified");
+
+  if (state[3].set)
+    var = state[3].arg ? state[3].arg : "root";
+  
+  if (state[1].set)
+    search_label (args[0], var);
+  else if (state[2].set)
+    search_fs_uuid (args[0], var);
+  else
+    search_file (args[0], var);
+
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(search)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("search", grub_cmd_search, GRUB_COMMAND_FLAG_BOTH,
+                        "search [-f|-l|-u|-s] NAME",
+                        "Search devices by file, filesystem label or filesystem UUID."
+                        " If --set is specified, the first device found is"
+                        " set to a variable. If no variable name is"
+                        " specified, \"root\" is used.",
+                        options);
+}
+
+GRUB_MOD_FINI(search)
+{
+  grub_unregister_command ("search");
+}
diff --git a/commands/sleep.c b/commands/sleep.c
new file mode 100644 (file)
index 0000000..46c1326
--- /dev/null
@@ -0,0 +1,112 @@
+/* sleep.c - Command to wait a specified number of seconds.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/term.h>
+#include <grub/time.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/machine/time.h>
+
+static const struct grub_arg_option options[] =
+  {
+    {"verbose", 'v', 0, "verbose countdown", 0, 0},
+    {"interruptible", 'i', 0, "interruptible with ESC", 0, 0},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+static grub_uint8_t x, y;
+
+static void
+do_print (int n)
+{
+  grub_gotoxy (x, y);
+  /* NOTE: Do not remove the trailing space characters.
+     They are required to clear the line.  */
+  grub_printf ("%d    ", n);
+}
+
+/* Based on grub_millisleep() from kern/generic/millisleep.c.  */
+static int
+grub_interruptible_millisleep (grub_uint32_t ms)
+{
+  grub_uint64_t start;
+
+  start = grub_get_time_ms ();
+
+  while (grub_get_time_ms () - start < ms)
+    if (grub_checkkey () >= 0 &&
+       GRUB_TERM_ASCII_CHAR (grub_getkey ()) == GRUB_TERM_ESC)
+      return 1;
+
+  return 0;
+}
+
+static grub_err_t
+grub_cmd_sleep (struct grub_arg_list *state, int argc, char **args)
+{
+  grub_uint16_t xy;
+  int n;
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing operand");
+
+  n = grub_strtoul (args[0], 0, 10);
+
+  if (n == 0)
+    {
+      /* Either `0' or broken input.  */
+      return 0;
+    }
+
+  xy = grub_getxy ();
+  x = xy >> 8;
+  y = xy & 0xff;
+
+  for (; n; n--)
+    {
+      if (state[0].set)
+       do_print (n);
+
+      if (state[1].set)
+       {
+         if (grub_interruptible_millisleep (1000))
+           return 1;
+       }
+      else
+       grub_millisleep (1000);
+    }
+  if (state[0].set)
+    do_print (0);
+
+  return 0;
+}
+
+\f
+GRUB_MOD_INIT(sleep)
+{
+  grub_register_command ("sleep", grub_cmd_sleep, GRUB_COMMAND_FLAG_BOTH,
+                        "sleep NUMBER_OF_SECONDS", "Wait for a specified number of seconds", options);
+}
+
+GRUB_MOD_FINI(sleep)
+{
+  grub_unregister_command ("sleep");
+}
diff --git a/commands/terminal.c b/commands/terminal.c
new file mode 100644 (file)
index 0000000..98e6d11
--- /dev/null
@@ -0,0 +1,132 @@
+/* terminal.c - command to show and select a terminal */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2005,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/misc.h>
+#include <grub/term.h>
+
+static grub_err_t
+grub_cmd_terminal_input (struct grub_arg_list *state __attribute__ ((unused)),
+                        int argc, char **args)
+{
+  grub_term_input_t term = 0;
+  
+  auto int print_terminal (grub_term_input_t);
+  auto int find_terminal (grub_term_input_t);
+  
+  int print_terminal (grub_term_input_t t)
+    {
+      grub_printf (" %s", t->name);
+      return 0;
+    }
+
+  int find_terminal (grub_term_input_t t)
+    {
+      if (grub_strcmp (t->name, args[0]) == 0)
+       {
+         term = t;
+         return 1;
+       }
+
+      return 0;
+    }
+  
+  if (argc == 0)
+    {
+      grub_printf ("Available input terminal(s):");
+      grub_term_iterate_input (print_terminal);
+      grub_putchar ('\n');
+      
+      grub_printf ("Current input terminal: %s\n", grub_term_get_current_input ()->name);
+    }
+  else
+    {
+      grub_term_iterate_input (find_terminal);
+      if (! term)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such input terminal");
+
+      grub_term_set_current_input (term);
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_terminal_output (struct grub_arg_list *state __attribute__ ((unused)),
+                         int argc, char **args)
+{
+  grub_term_output_t term = 0;
+  
+  auto int print_terminal (grub_term_output_t);
+  auto int find_terminal (grub_term_output_t);
+  
+  int print_terminal (grub_term_output_t t)
+    {
+      grub_printf (" %s", t->name);
+      return 0;
+    }
+
+  int find_terminal (grub_term_output_t t)
+    {
+      if (grub_strcmp (t->name, args[0]) == 0)
+       {
+         term = t;
+         return 1;
+       }
+
+      return 0;
+    }
+  
+  if (argc == 0)
+    {
+      grub_printf ("Available output terminal(s):");
+      grub_term_iterate_output (print_terminal);
+      grub_putchar ('\n');
+      
+      grub_printf ("Current output terminal: %s\n", grub_term_get_current_output ()->name);
+    }
+  else
+    {
+      grub_term_iterate_output (find_terminal);
+      if (! term)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such output terminal");
+
+      grub_term_set_current_output (term);
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+\f
+GRUB_MOD_INIT(terminal)
+{
+  (void)mod;                   /* To stop warning. */
+  grub_register_command ("terminal_input", grub_cmd_terminal_input, GRUB_COMMAND_FLAG_BOTH,
+                        "terminal_input [TERM...]", "Select an input terminal.", 0);
+  grub_register_command ("terminal_output", grub_cmd_terminal_output, GRUB_COMMAND_FLAG_BOTH,
+                        "terminal_output [TERM...]", "Select an output terminal.", 0);
+}
+
+GRUB_MOD_FINI(terminal)
+{
+  grub_unregister_command ("terminal_input");
+  grub_unregister_command ("terminal_output");
+}
diff --git a/commands/test.c b/commands/test.c
new file mode 100644 (file)
index 0000000..3d273db
--- /dev/null
@@ -0,0 +1,70 @@
+/* test.c -- The test command..  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+
+static grub_err_t
+grub_cmd_test (struct grub_arg_list *state __attribute__ ((unused)), int argc,
+              char **args)
+
+{
+  char *eq;
+  char *eqis;
+
+  /* XXX: No fancy expression evaluation yet.  */
+  
+  if (argc == 0)
+    return 0;
+  
+  eq = grub_strdup (args[0]);
+  eqis = grub_strchr (eq, '=');
+  if (! eqis)
+    return 0;
+
+  *eqis = '\0';
+  eqis++;
+  /* Check an expression in the form `A=B'.  */
+  if (grub_strcmp (eq, eqis))
+    grub_error (GRUB_ERR_TEST_FAILURE, "false");
+  grub_free (eq);
+
+  return grub_errno;
+}
+
+
+\f
+GRUB_MOD_INIT(test)
+{
+  (void)mod;                   /* To stop warning. */
+  grub_register_command ("[", grub_cmd_test, GRUB_COMMAND_FLAG_CMDLINE,
+                        "[ EXPRESSION ]", "Evaluate an expression", 0);
+  grub_register_command ("test", grub_cmd_test, GRUB_COMMAND_FLAG_CMDLINE,
+                        "test EXPRESSION", "Evaluate an expression", 0);
+}
+
+GRUB_MOD_FINI(test)
+{
+  grub_unregister_command ("[");
+  grub_unregister_command ("test");
+}
diff --git a/commands/usbtest.c b/commands/usbtest.c
new file mode 100644 (file)
index 0000000..8262b2e
--- /dev/null
@@ -0,0 +1,160 @@
+/* usbtest.c - test module for USB */
+/*
+ *  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/err.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/usb.h>
+
+static const char *usb_classes[] =
+  {
+    "",
+    "Audio",
+    "Communication Interface",
+    "HID",
+    "",
+    "Physical",
+    "Image",
+    "Printer",
+    "Mass Storage",
+    "Hub",
+    "Data Interface",
+    "Smart Card",
+    "Content Security",
+    "Video"
+  };
+
+static const char *usb_endp_type[] =
+  {
+    "Control",
+    "Isochronous",
+    "Bulk",
+    "Interrupt"
+  };
+
+static const char *usb_devspeed[] = 
+  {
+    "",
+    "Low",
+    "Full",
+    "High"
+  };
+
+static void
+usb_print_str (const char *description, grub_usb_device_t dev, int idx)
+{
+  char *name;
+  /* XXX: LANGID  */
+
+  if (! idx)
+    return;
+
+  grub_usb_get_string (dev, idx, 0x0409, &name);
+  grub_printf ("%s: `%s'\n", description, name);
+  grub_free (name);
+}
+
+static int
+usb_iterate (grub_usb_device_t dev)
+{
+  struct grub_usb_desc_device *descdev;
+  int i;
+
+  descdev = &dev->descdev;
+
+  usb_print_str ("Product", dev, descdev->strprod);
+  usb_print_str ("Vendor", dev, descdev->strvendor);
+  usb_print_str ("Serial", dev, descdev->strserial);
+  
+  if (descdev->class > 0 && descdev->class <= 0x0E)
+    grub_printf ("Class: (0x%02x) %s, Subclass: 0x%02x, Protocol: 0x%02x\n",
+                descdev->class, usb_classes[descdev->class],
+                descdev->subclass, descdev->protocol);
+  grub_printf ("USB version %d.%d, VendorID: 0x%02x, ProductID: 0x%02x, #conf: %d\n",
+              descdev->usbrel >> 8, (descdev->usbrel >> 4) & 0x0F,
+              descdev->vendorid, descdev->prodid, descdev->configcnt);
+
+  grub_printf ("%s speed device\n", usb_devspeed[dev->speed]);
+
+  for (i = 0; i < descdev->configcnt; i++)
+    {
+      struct grub_usb_desc_config *config;
+
+      config = dev->config[i].descconf;
+      usb_print_str ("Configuration:", dev, config->strconfig);
+    }
+
+  for (i = 0; i < dev->config[0].descconf->numif; i++)
+    {
+      int j;
+      struct grub_usb_desc_if *interf;
+      interf = dev->config[0].interf[i].descif;
+
+      grub_printf ("Interface #%d: #Endpoints: %d   ",
+                  i, interf->endpointcnt);
+      if (interf->class > 0 && interf->class <= 0x0E)
+       grub_printf ("Class: (0x%02x) %s, Subclass: 0x%02x, Protocol: 0x%02x\n",
+                    interf->class, usb_classes[interf->class],
+                    interf->subclass, interf->protocol);
+
+      usb_print_str ("Interface", dev, interf->strif);
+
+      for (j = 0; j < interf->endpointcnt; j++)
+       {
+         struct grub_usb_desc_endp *endp;
+         endp = &dev->config[0].interf[i].descendp[j];
+
+         grub_printf ("Endpoint #%d: %s, max packed size: %d, transfer type: %s, latency: %d\n",
+                      endp->endp_addr & 15,
+                      (endp->endp_addr & 128) ? "IN" : "OUT",
+                      endp->maxpacket, usb_endp_type[endp->attrib & 3],
+                      endp->interval);
+       }
+    }
+
+  grub_printf("\n");
+
+  return 0;
+}
+
+static grub_err_t
+grub_cmd_usbtest (struct grub_arg_list *state __attribute__ ((unused)),
+                 int argc __attribute__ ((unused)),
+                 char **args __attribute__ ((unused)))
+{
+  grub_printf ("USB devices:\n\n");
+  grub_usb_iterate (usb_iterate);
+
+  return 0;
+}
+
+GRUB_MOD_INIT(usbtest)
+{
+  (void)mod;                   /* To stop warning. */
+  grub_register_command ("usb", grub_cmd_usbtest, GRUB_COMMAND_FLAG_BOTH,
+                        "usb", "Test USB support", 0);
+}
+
+GRUB_MOD_FINI(usbtest)
+{
+  grub_unregister_command ("usb");
+}
diff --git a/commands/videotest.c b/commands/videotest.c
new file mode 100644 (file)
index 0000000..a9ead81
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/video.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/arg.h>
+#include <grub/mm.h>
+#include <grub/font.h>
+#include <grub/term.h>
+
+static grub_err_t
+grub_cmd_videotest (struct grub_arg_list *state __attribute__ ((unused)),
+                    int argc __attribute__ ((unused)),
+                    char **args __attribute__ ((unused)))
+{
+  if (grub_video_setup (1024, 768,
+                        GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != GRUB_ERR_NONE)
+    return grub_errno;
+
+  grub_video_color_t color;
+  unsigned int x;
+  unsigned int y;
+  unsigned int width;
+  unsigned int height;
+  int i;
+  grub_font_t sansbig;
+  grub_font_t sans;
+  grub_font_t sanssmall;
+  grub_font_t fixed;
+  struct grub_font_glyph *glyph;
+  struct grub_video_render_target *text_layer;
+  grub_video_color_t palette[16];
+  const char *str;
+  int texty;
+
+  grub_video_get_viewport (&x, &y, &width, &height);
+
+  grub_video_create_render_target (&text_layer, width, height,
+                                   GRUB_VIDEO_MODE_TYPE_RGB
+                                   | GRUB_VIDEO_MODE_TYPE_ALPHA);
+
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+  color = grub_video_map_rgb (0, 0, 0);
+  grub_video_fill_rect (color, 0, 0, width, height);
+
+  color = grub_video_map_rgb (255, 0, 0);
+  grub_video_fill_rect (color, 0, 0, 100, 100);
+
+  color = grub_video_map_rgb (0, 255, 255);
+  grub_video_fill_rect (color, 100, 100, 100, 100);
+
+  sansbig = grub_font_get ("Helvetica Bold 24");
+  sans = grub_font_get ("Helvetica Bold 14");
+  sanssmall = grub_font_get ("Helvetica 8");
+  fixed = grub_font_get ("Fixed 20");
+  if (! sansbig || ! sans || ! sanssmall || ! fixed)
+    return grub_error (GRUB_ERR_BAD_FONT, "No font loaded.");
+
+  glyph = grub_font_get_glyph (fixed, '*');
+  grub_font_draw_glyph (glyph, color, 200 ,0);
+
+  grub_video_set_viewport (x + 150, y + 150,
+                           width - 150 * 2, height - 150 * 2);
+  color = grub_video_map_rgb (77, 33, 77);
+  grub_video_fill_rect (color, 0, 0, width, height);
+
+  grub_video_set_active_render_target (text_layer);
+
+  color = grub_video_map_rgb (255, 255, 255);
+
+  texty = 32;
+  grub_font_draw_string ("The quick brown fox jumped over the lazy dog.",
+                         sans, color, 16, texty);
+  texty += grub_font_get_descent (sans) + grub_font_get_leading (sans);
+
+  texty += grub_font_get_ascent (fixed);
+  grub_font_draw_string ("The quick brown fox jumped over the lazy dog.",
+                         fixed, color, 16, texty);
+  texty += grub_font_get_descent (fixed) + grub_font_get_leading (fixed);
+
+  /* To convert Unicode characters into UTF-8 for this test, the following
+     command is useful:
+       echo -ne '\x00\x00\x26\x3A' | iconv -f UTF-32BE -t UTF-8 | od -t x1
+     This converts the Unicode character U+263A to UTF-8.  */
+
+  /* Characters used:
+     Code point  Description                    UTF-8 encoding
+     ----------- ------------------------------ --------------
+     U+263A      unfilled smiley face           E2 98 BA
+     U+00A1      inverted exclamation point     C2 A1
+     U+00A3      British pound currency symbol  C2 A3
+     U+03C4      Greek tau                      CF 84
+     U+00E4      lowercase letter a with umlaut C3 A4
+     U+2124      set 'Z' symbol (integers)      E2 84 A4
+     U+2287      subset symbol                  E2 8A 87
+     U+211D      set 'R' symbol (real numbers)  E2 84 9D  */
+
+  str =
+    "Unicode test: happy\xE2\x98\xBA \xC2\xA3 5.00"
+    " \xC2\xA1\xCF\x84\xC3\xA4u! "
+    " \xE2\x84\xA4\xE2\x8A\x87\xE2\x84\x9D";
+  color = grub_video_map_rgb (128, 128, 255);
+
+  /* All characters in the string exist in the 'Fixed 20' (10x20) font.  */
+  texty += grub_font_get_ascent(fixed);
+  grub_font_draw_string (str, fixed, color, 16, texty);
+  texty += grub_font_get_descent (fixed) + grub_font_get_leading (fixed);
+
+  /* Some character don't exist in the Helvetica font, so the font engine
+     will fall back to using glyphs from another font that does contain them.
+     TODO The font engine should be smart about selecting a replacement font
+     and prioritize fonts with similar sizes.  */
+
+  texty += grub_font_get_ascent(sansbig);
+  grub_font_draw_string (str, sansbig, color, 16, texty);
+  texty += grub_font_get_descent (sansbig) + grub_font_get_leading (sansbig);
+
+  texty += grub_font_get_ascent(sans);
+  grub_font_draw_string (str, sans, color, 16, texty);
+  texty += grub_font_get_descent (sans) + grub_font_get_leading (sans);
+
+  texty += grub_font_get_ascent(sanssmall);
+  grub_font_draw_string (str, sanssmall, color, 16, texty);
+  texty += (grub_font_get_descent (sanssmall)
+            + grub_font_get_leading (sanssmall));
+
+  glyph = grub_font_get_glyph (fixed, '*');
+
+  for (i = 0; i < 16; i++)
+    {
+      color = grub_video_map_color (i);
+      palette[i] = color;
+      grub_font_draw_glyph (glyph, color, 16 + i * 16, 220);
+    }
+
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+  for (i = 0; i < 255; i++)
+    {
+      color = grub_video_map_rgb (i, 33, 77);
+      grub_video_fill_rect (color, 0, 0, width, height);
+      grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, 0, 0,
+                                     0, 0, width, height);
+    }
+
+  grub_getkey ();
+
+  grub_video_delete_render_target (text_layer);
+
+  grub_video_restore ();
+
+  for (i = 0; i < 16; i++)
+    grub_printf("color %d: %08x\n", i, palette[i]);
+
+  grub_errno = GRUB_ERR_NONE;
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(videotest)
+{
+  grub_register_command ("videotest",
+                         grub_cmd_videotest,
+                         GRUB_COMMAND_FLAG_BOTH,
+                         "videotest",
+                         "Test video subsystem",
+                         0);
+}
+
+GRUB_MOD_FINI(videotest)
+{
+  grub_unregister_command ("videotest");
+}
diff --git a/conf/common.mk b/conf/common.mk
new file mode 100644 (file)
index 0000000..9b67944
--- /dev/null
@@ -0,0 +1,4303 @@
+# -*- makefile -*-
+# Generated by genmk.rb, please don't edit!
+
+# For grub-mkelfimage.
+bin_UTILITIES += grub-mkelfimage
+grub_mkelfimage_SOURCES = util/elf/grub-mkimage.c util/misc.c \
+       util/resolve.c
+CLEANFILES += grub-mkelfimage$(EXEEXT) grub_mkelfimage-util_elf_grub_mkimage.o grub_mkelfimage-util_misc.o grub_mkelfimage-util_resolve.o
+MOSTLYCLEANFILES += grub_mkelfimage-util_elf_grub_mkimage.d grub_mkelfimage-util_misc.d grub_mkelfimage-util_resolve.d
+
+grub-mkelfimage: $(grub_mkelfimage_DEPENDENCIES) grub_mkelfimage-util_elf_grub_mkimage.o grub_mkelfimage-util_misc.o grub_mkelfimage-util_resolve.o
+       $(CC) -o $@ grub_mkelfimage-util_elf_grub_mkimage.o grub_mkelfimage-util_misc.o grub_mkelfimage-util_resolve.o $(LDFLAGS) $(grub_mkelfimage_LDFLAGS)
+
+grub_mkelfimage-util_elf_grub_mkimage.o: util/elf/grub-mkimage.c $(util/elf/grub-mkimage.c_DEPENDENCIES)
+       $(CC) -Iutil/elf -I$(srcdir)/util/elf $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkelfimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkelfimage-util_elf_grub_mkimage.d
+
+grub_mkelfimage-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkelfimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkelfimage-util_misc.d
+
+grub_mkelfimage-util_resolve.o: util/resolve.c $(util/resolve.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkelfimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkelfimage-util_resolve.d
+
+util/elf/grub-mkimage.c_DEPENDENCIES = Makefile
+
+# For grub-probe.
+sbin_UTILITIES += grub-probe
+util/grub-probe.c_DEPENDENCIES = grub_probe_init.h
+grub_probe_SOURCES = util/grub-probe.c \
+       util/hostdisk.c util/misc.c util/getroot.c              \
+       kern/device.c kern/disk.c kern/err.c kern/misc.c        \
+       kern/parser.c kern/partition.c kern/file.c              \
+       \
+       fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c         \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c  \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c          \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                     \
+       \
+       partmap/pc.c partmap/apple.c partmap/gpt.c              \
+       kern/fs.c kern/env.c fs/fshelp.c                        \
+       disk/raid.c disk/mdraid_linux.c disk/lvm.c grub_probe_init.c
+CLEANFILES += grub-probe$(EXEEXT) grub_probe-util_grub_probe.o grub_probe-util_hostdisk.o grub_probe-util_misc.o grub_probe-util_getroot.o grub_probe-kern_device.o grub_probe-kern_disk.o grub_probe-kern_err.o grub_probe-kern_misc.o grub_probe-kern_parser.o grub_probe-kern_partition.o grub_probe-kern_file.o grub_probe-fs_affs.o grub_probe-fs_cpio.o grub_probe-fs_fat.o grub_probe-fs_ext2.o grub_probe-fs_hfs.o grub_probe-fs_hfsplus.o grub_probe-fs_iso9660.o grub_probe-fs_udf.o grub_probe-fs_jfs.o grub_probe-fs_minix.o grub_probe-fs_ntfs.o grub_probe-fs_ntfscomp.o grub_probe-fs_reiserfs.o grub_probe-fs_sfs.o grub_probe-fs_ufs.o grub_probe-fs_xfs.o grub_probe-fs_afs.o grub_probe-fs_tar.o grub_probe-partmap_pc.o grub_probe-partmap_apple.o grub_probe-partmap_gpt.o grub_probe-kern_fs.o grub_probe-kern_env.o grub_probe-fs_fshelp.o grub_probe-disk_raid.o grub_probe-disk_mdraid_linux.o grub_probe-disk_lvm.o grub_probe-grub_probe_init.o
+MOSTLYCLEANFILES += grub_probe-util_grub_probe.d grub_probe-util_hostdisk.d grub_probe-util_misc.d grub_probe-util_getroot.d grub_probe-kern_device.d grub_probe-kern_disk.d grub_probe-kern_err.d grub_probe-kern_misc.d grub_probe-kern_parser.d grub_probe-kern_partition.d grub_probe-kern_file.d grub_probe-fs_affs.d grub_probe-fs_cpio.d grub_probe-fs_fat.d grub_probe-fs_ext2.d grub_probe-fs_hfs.d grub_probe-fs_hfsplus.d grub_probe-fs_iso9660.d grub_probe-fs_udf.d grub_probe-fs_jfs.d grub_probe-fs_minix.d grub_probe-fs_ntfs.d grub_probe-fs_ntfscomp.d grub_probe-fs_reiserfs.d grub_probe-fs_sfs.d grub_probe-fs_ufs.d grub_probe-fs_xfs.d grub_probe-fs_afs.d grub_probe-fs_tar.d grub_probe-partmap_pc.d grub_probe-partmap_apple.d grub_probe-partmap_gpt.d grub_probe-kern_fs.d grub_probe-kern_env.d grub_probe-fs_fshelp.d grub_probe-disk_raid.d grub_probe-disk_mdraid_linux.d grub_probe-disk_lvm.d grub_probe-grub_probe_init.d
+
+grub-probe: $(grub_probe_DEPENDENCIES) grub_probe-util_grub_probe.o grub_probe-util_hostdisk.o grub_probe-util_misc.o grub_probe-util_getroot.o grub_probe-kern_device.o grub_probe-kern_disk.o grub_probe-kern_err.o grub_probe-kern_misc.o grub_probe-kern_parser.o grub_probe-kern_partition.o grub_probe-kern_file.o grub_probe-fs_affs.o grub_probe-fs_cpio.o grub_probe-fs_fat.o grub_probe-fs_ext2.o grub_probe-fs_hfs.o grub_probe-fs_hfsplus.o grub_probe-fs_iso9660.o grub_probe-fs_udf.o grub_probe-fs_jfs.o grub_probe-fs_minix.o grub_probe-fs_ntfs.o grub_probe-fs_ntfscomp.o grub_probe-fs_reiserfs.o grub_probe-fs_sfs.o grub_probe-fs_ufs.o grub_probe-fs_xfs.o grub_probe-fs_afs.o grub_probe-fs_tar.o grub_probe-partmap_pc.o grub_probe-partmap_apple.o grub_probe-partmap_gpt.o grub_probe-kern_fs.o grub_probe-kern_env.o grub_probe-fs_fshelp.o grub_probe-disk_raid.o grub_probe-disk_mdraid_linux.o grub_probe-disk_lvm.o grub_probe-grub_probe_init.o
+       $(CC) -o $@ grub_probe-util_grub_probe.o grub_probe-util_hostdisk.o grub_probe-util_misc.o grub_probe-util_getroot.o grub_probe-kern_device.o grub_probe-kern_disk.o grub_probe-kern_err.o grub_probe-kern_misc.o grub_probe-kern_parser.o grub_probe-kern_partition.o grub_probe-kern_file.o grub_probe-fs_affs.o grub_probe-fs_cpio.o grub_probe-fs_fat.o grub_probe-fs_ext2.o grub_probe-fs_hfs.o grub_probe-fs_hfsplus.o grub_probe-fs_iso9660.o grub_probe-fs_udf.o grub_probe-fs_jfs.o grub_probe-fs_minix.o grub_probe-fs_ntfs.o grub_probe-fs_ntfscomp.o grub_probe-fs_reiserfs.o grub_probe-fs_sfs.o grub_probe-fs_ufs.o grub_probe-fs_xfs.o grub_probe-fs_afs.o grub_probe-fs_tar.o grub_probe-partmap_pc.o grub_probe-partmap_apple.o grub_probe-partmap_gpt.o grub_probe-kern_fs.o grub_probe-kern_env.o grub_probe-fs_fshelp.o grub_probe-disk_raid.o grub_probe-disk_mdraid_linux.o grub_probe-disk_lvm.o grub_probe-grub_probe_init.o $(LDFLAGS) $(grub_probe_LDFLAGS)
+
+grub_probe-util_grub_probe.o: util/grub-probe.c $(util/grub-probe.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-util_grub_probe.d
+
+grub_probe-util_hostdisk.o: util/hostdisk.c $(util/hostdisk.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-util_hostdisk.d
+
+grub_probe-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-util_misc.d
+
+grub_probe-util_getroot.o: util/getroot.c $(util/getroot.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-util_getroot.d
+
+grub_probe-kern_device.o: kern/device.c $(kern/device.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-kern_device.d
+
+grub_probe-kern_disk.o: kern/disk.c $(kern/disk.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-kern_disk.d
+
+grub_probe-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-kern_err.d
+
+grub_probe-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-kern_misc.d
+
+grub_probe-kern_parser.o: kern/parser.c $(kern/parser.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-kern_parser.d
+
+grub_probe-kern_partition.o: kern/partition.c $(kern/partition.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-kern_partition.d
+
+grub_probe-kern_file.o: kern/file.c $(kern/file.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-kern_file.d
+
+grub_probe-fs_affs.o: fs/affs.c $(fs/affs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_affs.d
+
+grub_probe-fs_cpio.o: fs/cpio.c $(fs/cpio.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_cpio.d
+
+grub_probe-fs_fat.o: fs/fat.c $(fs/fat.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_fat.d
+
+grub_probe-fs_ext2.o: fs/ext2.c $(fs/ext2.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_ext2.d
+
+grub_probe-fs_hfs.o: fs/hfs.c $(fs/hfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_hfs.d
+
+grub_probe-fs_hfsplus.o: fs/hfsplus.c $(fs/hfsplus.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_hfsplus.d
+
+grub_probe-fs_iso9660.o: fs/iso9660.c $(fs/iso9660.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_iso9660.d
+
+grub_probe-fs_udf.o: fs/udf.c $(fs/udf.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_udf.d
+
+grub_probe-fs_jfs.o: fs/jfs.c $(fs/jfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_jfs.d
+
+grub_probe-fs_minix.o: fs/minix.c $(fs/minix.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_minix.d
+
+grub_probe-fs_ntfs.o: fs/ntfs.c $(fs/ntfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_ntfs.d
+
+grub_probe-fs_ntfscomp.o: fs/ntfscomp.c $(fs/ntfscomp.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_ntfscomp.d
+
+grub_probe-fs_reiserfs.o: fs/reiserfs.c $(fs/reiserfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_reiserfs.d
+
+grub_probe-fs_sfs.o: fs/sfs.c $(fs/sfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_sfs.d
+
+grub_probe-fs_ufs.o: fs/ufs.c $(fs/ufs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_ufs.d
+
+grub_probe-fs_xfs.o: fs/xfs.c $(fs/xfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_xfs.d
+
+grub_probe-fs_afs.o: fs/afs.c $(fs/afs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_afs.d
+
+grub_probe-fs_tar.o: fs/tar.c $(fs/tar.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_tar.d
+
+grub_probe-partmap_pc.o: partmap/pc.c $(partmap/pc.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-partmap_pc.d
+
+grub_probe-partmap_apple.o: partmap/apple.c $(partmap/apple.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-partmap_apple.d
+
+grub_probe-partmap_gpt.o: partmap/gpt.c $(partmap/gpt.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-partmap_gpt.d
+
+grub_probe-kern_fs.o: kern/fs.c $(kern/fs.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-kern_fs.d
+
+grub_probe-kern_env.o: kern/env.c $(kern/env.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-kern_env.d
+
+grub_probe-fs_fshelp.o: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-fs_fshelp.d
+
+grub_probe-disk_raid.o: disk/raid.c $(disk/raid.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-disk_raid.d
+
+grub_probe-disk_mdraid_linux.o: disk/mdraid_linux.c $(disk/mdraid_linux.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-disk_mdraid_linux.d
+
+grub_probe-disk_lvm.o: disk/lvm.c $(disk/lvm.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-disk_lvm.d
+
+grub_probe-grub_probe_init.o: grub_probe_init.c $(grub_probe_init.c_DEPENDENCIES)
+       $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_probe_CFLAGS) -MD -c -o $@ $<
+-include grub_probe-grub_probe_init.d
+
+
+ifeq ($(enable_grub_fstest), yes)
+bin_UTILITIES += grub-fstest
+endif
+
+# For grub-fstest.
+util/grub-fstest.c_DEPENDENCIES = grub_fstest_init.h
+grub_fstest_SOURCES = util/grub-fstest.c util/hostfs.c util/misc.c     \
+       kern/file.c kern/device.c kern/disk.c kern/err.c kern/misc.c    \
+       disk/host.c disk/loopback.c  normal/arg.c normal/misc.c         \
+       lib/hexdump.c lib/crc.c commands/blocklist.c commands/ls.c      \
+       \
+       fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c                 \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c          \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c                  \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                             \
+       \
+       kern/partition.c partmap/pc.c partmap/apple.c partmap/gpt.c     \
+       kern/fs.c kern/env.c fs/fshelp.c disk/raid.c                    \
+       disk/raid5_recover.c disk/raid6_recover.c                       \
+       disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c             \
+       grub_fstest_init.c
+CLEANFILES += grub-fstest$(EXEEXT) grub_fstest-util_grub_fstest.o grub_fstest-util_hostfs.o grub_fstest-util_misc.o grub_fstest-kern_file.o grub_fstest-kern_device.o grub_fstest-kern_disk.o grub_fstest-kern_err.o grub_fstest-kern_misc.o grub_fstest-disk_host.o grub_fstest-disk_loopback.o grub_fstest-normal_arg.o grub_fstest-normal_misc.o grub_fstest-lib_hexdump.o grub_fstest-lib_crc.o grub_fstest-commands_blocklist.o grub_fstest-commands_ls.o grub_fstest-fs_affs.o grub_fstest-fs_cpio.o grub_fstest-fs_fat.o grub_fstest-fs_ext2.o grub_fstest-fs_hfs.o grub_fstest-fs_hfsplus.o grub_fstest-fs_iso9660.o grub_fstest-fs_udf.o grub_fstest-fs_jfs.o grub_fstest-fs_minix.o grub_fstest-fs_ntfs.o grub_fstest-fs_ntfscomp.o grub_fstest-fs_reiserfs.o grub_fstest-fs_sfs.o grub_fstest-fs_ufs.o grub_fstest-fs_xfs.o grub_fstest-fs_afs.o grub_fstest-fs_tar.o grub_fstest-kern_partition.o grub_fstest-partmap_pc.o grub_fstest-partmap_apple.o grub_fstest-partmap_gpt.o grub_fstest-kern_fs.o grub_fstest-kern_env.o grub_fstest-fs_fshelp.o grub_fstest-disk_raid.o grub_fstest-disk_raid5_recover.o grub_fstest-disk_raid6_recover.o grub_fstest-disk_mdraid_linux.o grub_fstest-disk_dmraid_nvidia.o grub_fstest-disk_lvm.o grub_fstest-grub_fstest_init.o
+MOSTLYCLEANFILES += grub_fstest-util_grub_fstest.d grub_fstest-util_hostfs.d grub_fstest-util_misc.d grub_fstest-kern_file.d grub_fstest-kern_device.d grub_fstest-kern_disk.d grub_fstest-kern_err.d grub_fstest-kern_misc.d grub_fstest-disk_host.d grub_fstest-disk_loopback.d grub_fstest-normal_arg.d grub_fstest-normal_misc.d grub_fstest-lib_hexdump.d grub_fstest-lib_crc.d grub_fstest-commands_blocklist.d grub_fstest-commands_ls.d grub_fstest-fs_affs.d grub_fstest-fs_cpio.d grub_fstest-fs_fat.d grub_fstest-fs_ext2.d grub_fstest-fs_hfs.d grub_fstest-fs_hfsplus.d grub_fstest-fs_iso9660.d grub_fstest-fs_udf.d grub_fstest-fs_jfs.d grub_fstest-fs_minix.d grub_fstest-fs_ntfs.d grub_fstest-fs_ntfscomp.d grub_fstest-fs_reiserfs.d grub_fstest-fs_sfs.d grub_fstest-fs_ufs.d grub_fstest-fs_xfs.d grub_fstest-fs_afs.d grub_fstest-fs_tar.d grub_fstest-kern_partition.d grub_fstest-partmap_pc.d grub_fstest-partmap_apple.d grub_fstest-partmap_gpt.d grub_fstest-kern_fs.d grub_fstest-kern_env.d grub_fstest-fs_fshelp.d grub_fstest-disk_raid.d grub_fstest-disk_raid5_recover.d grub_fstest-disk_raid6_recover.d grub_fstest-disk_mdraid_linux.d grub_fstest-disk_dmraid_nvidia.d grub_fstest-disk_lvm.d grub_fstest-grub_fstest_init.d
+
+grub-fstest: $(grub_fstest_DEPENDENCIES) grub_fstest-util_grub_fstest.o grub_fstest-util_hostfs.o grub_fstest-util_misc.o grub_fstest-kern_file.o grub_fstest-kern_device.o grub_fstest-kern_disk.o grub_fstest-kern_err.o grub_fstest-kern_misc.o grub_fstest-disk_host.o grub_fstest-disk_loopback.o grub_fstest-normal_arg.o grub_fstest-normal_misc.o grub_fstest-lib_hexdump.o grub_fstest-lib_crc.o grub_fstest-commands_blocklist.o grub_fstest-commands_ls.o grub_fstest-fs_affs.o grub_fstest-fs_cpio.o grub_fstest-fs_fat.o grub_fstest-fs_ext2.o grub_fstest-fs_hfs.o grub_fstest-fs_hfsplus.o grub_fstest-fs_iso9660.o grub_fstest-fs_udf.o grub_fstest-fs_jfs.o grub_fstest-fs_minix.o grub_fstest-fs_ntfs.o grub_fstest-fs_ntfscomp.o grub_fstest-fs_reiserfs.o grub_fstest-fs_sfs.o grub_fstest-fs_ufs.o grub_fstest-fs_xfs.o grub_fstest-fs_afs.o grub_fstest-fs_tar.o grub_fstest-kern_partition.o grub_fstest-partmap_pc.o grub_fstest-partmap_apple.o grub_fstest-partmap_gpt.o grub_fstest-kern_fs.o grub_fstest-kern_env.o grub_fstest-fs_fshelp.o grub_fstest-disk_raid.o grub_fstest-disk_raid5_recover.o grub_fstest-disk_raid6_recover.o grub_fstest-disk_mdraid_linux.o grub_fstest-disk_dmraid_nvidia.o grub_fstest-disk_lvm.o grub_fstest-grub_fstest_init.o
+       $(CC) -o $@ grub_fstest-util_grub_fstest.o grub_fstest-util_hostfs.o grub_fstest-util_misc.o grub_fstest-kern_file.o grub_fstest-kern_device.o grub_fstest-kern_disk.o grub_fstest-kern_err.o grub_fstest-kern_misc.o grub_fstest-disk_host.o grub_fstest-disk_loopback.o grub_fstest-normal_arg.o grub_fstest-normal_misc.o grub_fstest-lib_hexdump.o grub_fstest-lib_crc.o grub_fstest-commands_blocklist.o grub_fstest-commands_ls.o grub_fstest-fs_affs.o grub_fstest-fs_cpio.o grub_fstest-fs_fat.o grub_fstest-fs_ext2.o grub_fstest-fs_hfs.o grub_fstest-fs_hfsplus.o grub_fstest-fs_iso9660.o grub_fstest-fs_udf.o grub_fstest-fs_jfs.o grub_fstest-fs_minix.o grub_fstest-fs_ntfs.o grub_fstest-fs_ntfscomp.o grub_fstest-fs_reiserfs.o grub_fstest-fs_sfs.o grub_fstest-fs_ufs.o grub_fstest-fs_xfs.o grub_fstest-fs_afs.o grub_fstest-fs_tar.o grub_fstest-kern_partition.o grub_fstest-partmap_pc.o grub_fstest-partmap_apple.o grub_fstest-partmap_gpt.o grub_fstest-kern_fs.o grub_fstest-kern_env.o grub_fstest-fs_fshelp.o grub_fstest-disk_raid.o grub_fstest-disk_raid5_recover.o grub_fstest-disk_raid6_recover.o grub_fstest-disk_mdraid_linux.o grub_fstest-disk_dmraid_nvidia.o grub_fstest-disk_lvm.o grub_fstest-grub_fstest_init.o $(LDFLAGS) $(grub_fstest_LDFLAGS)
+
+grub_fstest-util_grub_fstest.o: util/grub-fstest.c $(util/grub-fstest.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-util_grub_fstest.d
+
+grub_fstest-util_hostfs.o: util/hostfs.c $(util/hostfs.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-util_hostfs.d
+
+grub_fstest-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-util_misc.d
+
+grub_fstest-kern_file.o: kern/file.c $(kern/file.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-kern_file.d
+
+grub_fstest-kern_device.o: kern/device.c $(kern/device.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-kern_device.d
+
+grub_fstest-kern_disk.o: kern/disk.c $(kern/disk.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-kern_disk.d
+
+grub_fstest-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-kern_err.d
+
+grub_fstest-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-kern_misc.d
+
+grub_fstest-disk_host.o: disk/host.c $(disk/host.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-disk_host.d
+
+grub_fstest-disk_loopback.o: disk/loopback.c $(disk/loopback.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-disk_loopback.d
+
+grub_fstest-normal_arg.o: normal/arg.c $(normal/arg.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-normal_arg.d
+
+grub_fstest-normal_misc.o: normal/misc.c $(normal/misc.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-normal_misc.d
+
+grub_fstest-lib_hexdump.o: lib/hexdump.c $(lib/hexdump.c_DEPENDENCIES)
+       $(CC) -Ilib -I$(srcdir)/lib $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-lib_hexdump.d
+
+grub_fstest-lib_crc.o: lib/crc.c $(lib/crc.c_DEPENDENCIES)
+       $(CC) -Ilib -I$(srcdir)/lib $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-lib_crc.d
+
+grub_fstest-commands_blocklist.o: commands/blocklist.c $(commands/blocklist.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-commands_blocklist.d
+
+grub_fstest-commands_ls.o: commands/ls.c $(commands/ls.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-commands_ls.d
+
+grub_fstest-fs_affs.o: fs/affs.c $(fs/affs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_affs.d
+
+grub_fstest-fs_cpio.o: fs/cpio.c $(fs/cpio.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_cpio.d
+
+grub_fstest-fs_fat.o: fs/fat.c $(fs/fat.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_fat.d
+
+grub_fstest-fs_ext2.o: fs/ext2.c $(fs/ext2.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_ext2.d
+
+grub_fstest-fs_hfs.o: fs/hfs.c $(fs/hfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_hfs.d
+
+grub_fstest-fs_hfsplus.o: fs/hfsplus.c $(fs/hfsplus.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_hfsplus.d
+
+grub_fstest-fs_iso9660.o: fs/iso9660.c $(fs/iso9660.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_iso9660.d
+
+grub_fstest-fs_udf.o: fs/udf.c $(fs/udf.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_udf.d
+
+grub_fstest-fs_jfs.o: fs/jfs.c $(fs/jfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_jfs.d
+
+grub_fstest-fs_minix.o: fs/minix.c $(fs/minix.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_minix.d
+
+grub_fstest-fs_ntfs.o: fs/ntfs.c $(fs/ntfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_ntfs.d
+
+grub_fstest-fs_ntfscomp.o: fs/ntfscomp.c $(fs/ntfscomp.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_ntfscomp.d
+
+grub_fstest-fs_reiserfs.o: fs/reiserfs.c $(fs/reiserfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_reiserfs.d
+
+grub_fstest-fs_sfs.o: fs/sfs.c $(fs/sfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_sfs.d
+
+grub_fstest-fs_ufs.o: fs/ufs.c $(fs/ufs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_ufs.d
+
+grub_fstest-fs_xfs.o: fs/xfs.c $(fs/xfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_xfs.d
+
+grub_fstest-fs_afs.o: fs/afs.c $(fs/afs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_afs.d
+
+grub_fstest-fs_tar.o: fs/tar.c $(fs/tar.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_tar.d
+
+grub_fstest-kern_partition.o: kern/partition.c $(kern/partition.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-kern_partition.d
+
+grub_fstest-partmap_pc.o: partmap/pc.c $(partmap/pc.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-partmap_pc.d
+
+grub_fstest-partmap_apple.o: partmap/apple.c $(partmap/apple.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-partmap_apple.d
+
+grub_fstest-partmap_gpt.o: partmap/gpt.c $(partmap/gpt.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-partmap_gpt.d
+
+grub_fstest-kern_fs.o: kern/fs.c $(kern/fs.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-kern_fs.d
+
+grub_fstest-kern_env.o: kern/env.c $(kern/env.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-kern_env.d
+
+grub_fstest-fs_fshelp.o: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-fs_fshelp.d
+
+grub_fstest-disk_raid.o: disk/raid.c $(disk/raid.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-disk_raid.d
+
+grub_fstest-disk_raid5_recover.o: disk/raid5_recover.c $(disk/raid5_recover.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-disk_raid5_recover.d
+
+grub_fstest-disk_raid6_recover.o: disk/raid6_recover.c $(disk/raid6_recover.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-disk_raid6_recover.d
+
+grub_fstest-disk_mdraid_linux.o: disk/mdraid_linux.c $(disk/mdraid_linux.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-disk_mdraid_linux.d
+
+grub_fstest-disk_dmraid_nvidia.o: disk/dmraid_nvidia.c $(disk/dmraid_nvidia.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-disk_dmraid_nvidia.d
+
+grub_fstest-disk_lvm.o: disk/lvm.c $(disk/lvm.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-disk_lvm.d
+
+grub_fstest-grub_fstest_init.o: grub_fstest_init.c $(grub_fstest_init.c_DEPENDENCIES)
+       $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_fstest_CFLAGS) -MD -c -o $@ $<
+-include grub_fstest-grub_fstest_init.d
+
+
+# For grub-mkfont.
+ifeq ($(enable_grub_mkfont), yes)
+bin_UTILITIES += grub-mkfont
+grub_mkfont_SOURCES = util/grub-mkfont.c util/misc.c
+CLEANFILES += grub-mkfont$(EXEEXT) grub_mkfont-util_grub_mkfont.o grub_mkfont-util_misc.o
+MOSTLYCLEANFILES += grub_mkfont-util_grub_mkfont.d grub_mkfont-util_misc.d
+
+grub-mkfont: $(grub_mkfont_DEPENDENCIES) grub_mkfont-util_grub_mkfont.o grub_mkfont-util_misc.o
+       $(CC) -o $@ grub_mkfont-util_grub_mkfont.o grub_mkfont-util_misc.o $(LDFLAGS) $(grub_mkfont_LDFLAGS)
+
+grub_mkfont-util_grub_mkfont.o: util/grub-mkfont.c $(util/grub-mkfont.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkfont_CFLAGS) -MD -c -o $@ $<
+-include grub_mkfont-util_grub_mkfont.d
+
+grub_mkfont-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkfont_CFLAGS) -MD -c -o $@ $<
+-include grub_mkfont-util_misc.d
+
+grub_mkfont_CFLAGS = $(freetype_cflags)
+grub_mkfont_LDFLAGS = $(freetype_libs)
+endif
+
+# For the parser.
+grub_script.tab.c grub_script.tab.h: normal/parser.y
+       $(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/normal/parser.y
+DISTCLEANFILES += grub_script.tab.c grub_script.tab.h
+
+# For grub-emu.
+grub_emu_init.lst: geninit.sh $(filter-out grub_emu_init.c,$(grub_emu_SOURCES))
+       rm -f $@; grep GRUB_MOD_INIT $(filter %.c,$^) /dev/null > $@
+DISTCLEANFILES += grub_emu_init.lst
+
+grub_emu_init.h: grub_emu_init.lst $(filter-out grub_emu_init.c,$(grub_emu_SOURCES)) geninitheader.sh
+       rm -f $@; sh $(srcdir)/geninitheader.sh $< > $@
+DISTCLEANFILES += grub_emu_init.h
+
+grub_emu_init.c: grub_emu_init.lst $(filter-out grub_emu_init.c,$(grub_emu_SOURCES)) geninit.sh grub_emu_init.h
+       rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@
+DISTCLEANFILES += grub_emu_init.c
+
+# For grub-probe.
+grub_probe_init.lst: geninit.sh $(filter-out grub_probe_init.c,$(grub_probe_SOURCES))
+       rm -f $@; grep GRUB_MOD_INIT $(filter %.c,$^) /dev/null > $@
+DISTCLEANFILES += grub_probe_init.lst
+
+grub_probe_init.h: grub_probe_init.lst $(filter-out grub_probe_init.c,$(grub_probe_SOURCES)) geninitheader.sh
+       rm -f $@; sh $(srcdir)/geninitheader.sh $< > $@
+DISTCLEANFILES += grub_probe_init.h
+
+grub_probe_init.c: grub_probe_init.lst $(filter-out grub_probe_init.c,$(grub_probe_SOURCES)) geninit.sh grub_probe_init.h
+       rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@
+DISTCLEANFILES += grub_probe_init.c
+
+# For grub-setup.
+grub_setup_init.lst: geninit.sh $(filter-out grub_setup_init.c,$(grub_setup_SOURCES))
+       rm -f $@; grep GRUB_MOD_INIT $(filter %.c,$^) /dev/null > $@
+DISTCLEANFILES += grub_setup_init.lst
+
+grub_setup_init.h: grub_setup_init.lst $(filter-out grub_setup_init.c,$(grub_setup_SOURCES)) geninitheader.sh
+       rm -f $@; sh $(srcdir)/geninitheader.sh $< > $@
+DISTCLEANFILES += grub_setup_init.h
+
+grub_setup_init.c: grub_setup_init.lst $(filter-out grub_setup_init.c,$(grub_setup_SOURCES)) geninit.sh grub_setup_init.h
+       rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@
+DISTCLEANFILES += grub_setup_init.c
+
+# For grub-fstest.
+grub_fstest_init.lst: geninit.sh $(filter-out grub_fstest_init.c,$(grub_fstest_SOURCES))
+       rm -f $@; grep GRUB_MOD_INIT $(filter %.c,$^) /dev/null > $@
+DISTCLEANFILES += grub_fstest_init.lst
+
+grub_fstest_init.h: grub_fstest_init.lst $(filter-out grub_fstest_init.c,$(grub_fstest_SOURCES)) geninitheader.sh
+       rm -f $@; sh $(srcdir)/geninitheader.sh $< > $@
+DISTCLEANFILES += grub_fstest_init.h
+
+grub_fstest_init.c: grub_fstest_init.lst $(filter-out grub_fstest_init.c,$(grub_fstest_SOURCES)) geninit.sh grub_fstest_init.h
+       rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@
+DISTCLEANFILES += grub_fstest_init.c
+
+# for grub-editenv
+bin_UTILITIES += grub-editenv
+grub_editenv_SOURCES = util/grub-editenv.c lib/envblk.c util/misc.c kern/misc.c kern/err.c
+CLEANFILES += grub-editenv$(EXEEXT) grub_editenv-util_grub_editenv.o grub_editenv-lib_envblk.o grub_editenv-util_misc.o grub_editenv-kern_misc.o grub_editenv-kern_err.o
+MOSTLYCLEANFILES += grub_editenv-util_grub_editenv.d grub_editenv-lib_envblk.d grub_editenv-util_misc.d grub_editenv-kern_misc.d grub_editenv-kern_err.d
+
+grub-editenv: $(grub_editenv_DEPENDENCIES) grub_editenv-util_grub_editenv.o grub_editenv-lib_envblk.o grub_editenv-util_misc.o grub_editenv-kern_misc.o grub_editenv-kern_err.o
+       $(CC) -o $@ grub_editenv-util_grub_editenv.o grub_editenv-lib_envblk.o grub_editenv-util_misc.o grub_editenv-kern_misc.o grub_editenv-kern_err.o $(LDFLAGS) $(grub_editenv_LDFLAGS)
+
+grub_editenv-util_grub_editenv.o: util/grub-editenv.c $(util/grub-editenv.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_editenv_CFLAGS) -MD -c -o $@ $<
+-include grub_editenv-util_grub_editenv.d
+
+grub_editenv-lib_envblk.o: lib/envblk.c $(lib/envblk.c_DEPENDENCIES)
+       $(CC) -Ilib -I$(srcdir)/lib $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_editenv_CFLAGS) -MD -c -o $@ $<
+-include grub_editenv-lib_envblk.d
+
+grub_editenv-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_editenv_CFLAGS) -MD -c -o $@ $<
+-include grub_editenv-util_misc.d
+
+grub_editenv-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_editenv_CFLAGS) -MD -c -o $@ $<
+-include grub_editenv-kern_misc.d
+
+grub_editenv-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_editenv_CFLAGS) -MD -c -o $@ $<
+-include grub_editenv-kern_err.d
+
+CLEANFILES += grub-editenv
+
+# for grub-pe2elf
+ifeq ($(enable_grub_pe2elf), yes)
+bin_UTILITIES += grub-pe2elf
+endif
+
+grub_pe2elf_SOURCES = util/grub-pe2elf.c util/misc.c
+CLEANFILES += grub-pe2elf$(EXEEXT) grub_pe2elf-util_grub_pe2elf.o grub_pe2elf-util_misc.o
+MOSTLYCLEANFILES += grub_pe2elf-util_grub_pe2elf.d grub_pe2elf-util_misc.d
+
+grub-pe2elf: $(grub_pe2elf_DEPENDENCIES) grub_pe2elf-util_grub_pe2elf.o grub_pe2elf-util_misc.o
+       $(CC) -o $@ grub_pe2elf-util_grub_pe2elf.o grub_pe2elf-util_misc.o $(LDFLAGS) $(grub_pe2elf_LDFLAGS)
+
+grub_pe2elf-util_grub_pe2elf.o: util/grub-pe2elf.c $(util/grub-pe2elf.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_pe2elf_CFLAGS) -MD -c -o $@ $<
+-include grub_pe2elf-util_grub_pe2elf.d
+
+grub_pe2elf-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_pe2elf_CFLAGS) -MD -c -o $@ $<
+-include grub_pe2elf-util_misc.d
+
+CLEANFILES += grub-pe2elf
+
+# For grub-mkconfig
+grub-mkconfig: util/grub-mkconfig.in config.status
+       ./config.status --file=$@:$<
+       chmod +x $@
+sbin_SCRIPTS += grub-mkconfig
+CLEANFILES += grub-mkconfig
+
+grub-mkconfig_lib: util/grub-mkconfig_lib.in config.status
+       ./config.status --file=$@:$<
+       chmod +x $@
+lib_DATA += grub-mkconfig_lib
+CLEANFILES += grub-mkconfig_lib
+
+update-grub_lib: util/update-grub_lib.in config.status
+       ./config.status --file=$@:$<
+       chmod +x $@
+lib_DATA += update-grub_lib
+CLEANFILES += update-grub_lib
+
+%: util/grub.d/%.in config.status
+       ./config.status --file=$@:$<
+       chmod +x $@
+grub-mkconfig_SCRIPTS = 00_header 10_linux 10_hurd 10_freebsd 30_os-prober 40_custom
+ifeq ($(host_os), cygwin)
+grub-mkconfig_SCRIPTS += 10_windows
+endif
+
+CLEANFILES += $(grub-mkconfig_SCRIPTS)
+
+grub-mkconfig_DATA += util/grub.d/README
+
+
+# Filing systems.
+pkglib_MODULES += fshelp.mod fat.mod ufs.mod ext2.mod ntfs.mod         \
+       ntfscomp.mod minix.mod hfs.mod jfs.mod iso9660.mod xfs.mod      \
+       affs.mod sfs.mod hfsplus.mod reiserfs.mod cpio.mod tar.mod      \
+       udf.mod afs.mod
+
+# For fshelp.mod.
+fshelp_mod_SOURCES = fs/fshelp.c
+CLEANFILES += fshelp.mod mod-fshelp.o mod-fshelp.c pre-fshelp.o fshelp_mod-fs_fshelp.o und-fshelp.lst
+ifneq ($(fshelp_mod_EXPORTS),no)
+CLEANFILES += def-fshelp.lst
+DEFSYMFILES += def-fshelp.lst
+endif
+MOSTLYCLEANFILES += fshelp_mod-fs_fshelp.d
+UNDSYMFILES += und-fshelp.lst
+
+fshelp.mod: pre-fshelp.o mod-fshelp.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(fshelp_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-fshelp.o mod-fshelp.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-fshelp.o: $(fshelp_mod_DEPENDENCIES) fshelp_mod-fs_fshelp.o
+       -rm -f $@
+       $(TARGET_CC) $(fshelp_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ fshelp_mod-fs_fshelp.o
+
+mod-fshelp.o: mod-fshelp.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fshelp_mod_CFLAGS) -c -o $@ $<
+
+mod-fshelp.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'fshelp' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(fshelp_mod_EXPORTS),no)
+def-fshelp.lst: pre-fshelp.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 fshelp/' > $@
+endif
+
+und-fshelp.lst: pre-fshelp.o
+       echo 'fshelp' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+fshelp_mod-fs_fshelp.o: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(fshelp_mod_CFLAGS) -MD -c -o $@ $<
+-include fshelp_mod-fs_fshelp.d
+
+CLEANFILES += cmd-fshelp_mod-fs_fshelp.lst fs-fshelp_mod-fs_fshelp.lst partmap-fshelp_mod-fs_fshelp.lst
+COMMANDFILES += cmd-fshelp_mod-fs_fshelp.lst
+FSFILES += fs-fshelp_mod-fs_fshelp.lst
+PARTMAPFILES += partmap-fshelp_mod-fs_fshelp.lst
+
+cmd-fshelp_mod-fs_fshelp.lst: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fshelp_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh fshelp > $@ || (rm -f $@; exit 1)
+
+fs-fshelp_mod-fs_fshelp.lst: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fshelp_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh fshelp > $@ || (rm -f $@; exit 1)
+
+partmap-fshelp_mod-fs_fshelp.lst: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fshelp_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh fshelp > $@ || (rm -f $@; exit 1)
+
+
+fshelp_mod_CFLAGS = $(COMMON_CFLAGS)
+fshelp_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For fat.mod.
+fat_mod_SOURCES = fs/fat.c
+CLEANFILES += fat.mod mod-fat.o mod-fat.c pre-fat.o fat_mod-fs_fat.o und-fat.lst
+ifneq ($(fat_mod_EXPORTS),no)
+CLEANFILES += def-fat.lst
+DEFSYMFILES += def-fat.lst
+endif
+MOSTLYCLEANFILES += fat_mod-fs_fat.d
+UNDSYMFILES += und-fat.lst
+
+fat.mod: pre-fat.o mod-fat.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(fat_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-fat.o mod-fat.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-fat.o: $(fat_mod_DEPENDENCIES) fat_mod-fs_fat.o
+       -rm -f $@
+       $(TARGET_CC) $(fat_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ fat_mod-fs_fat.o
+
+mod-fat.o: mod-fat.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fat_mod_CFLAGS) -c -o $@ $<
+
+mod-fat.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'fat' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(fat_mod_EXPORTS),no)
+def-fat.lst: pre-fat.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 fat/' > $@
+endif
+
+und-fat.lst: pre-fat.o
+       echo 'fat' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+fat_mod-fs_fat.o: fs/fat.c $(fs/fat.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(fat_mod_CFLAGS) -MD -c -o $@ $<
+-include fat_mod-fs_fat.d
+
+CLEANFILES += cmd-fat_mod-fs_fat.lst fs-fat_mod-fs_fat.lst partmap-fat_mod-fs_fat.lst
+COMMANDFILES += cmd-fat_mod-fs_fat.lst
+FSFILES += fs-fat_mod-fs_fat.lst
+PARTMAPFILES += partmap-fat_mod-fs_fat.lst
+
+cmd-fat_mod-fs_fat.lst: fs/fat.c $(fs/fat.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fat_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh fat > $@ || (rm -f $@; exit 1)
+
+fs-fat_mod-fs_fat.lst: fs/fat.c $(fs/fat.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fat_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh fat > $@ || (rm -f $@; exit 1)
+
+partmap-fat_mod-fs_fat.lst: fs/fat.c $(fs/fat.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fat_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh fat > $@ || (rm -f $@; exit 1)
+
+
+fat_mod_CFLAGS = $(COMMON_CFLAGS)
+fat_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ufs.mod.
+ufs_mod_SOURCES = fs/ufs.c
+CLEANFILES += ufs.mod mod-ufs.o mod-ufs.c pre-ufs.o ufs_mod-fs_ufs.o und-ufs.lst
+ifneq ($(ufs_mod_EXPORTS),no)
+CLEANFILES += def-ufs.lst
+DEFSYMFILES += def-ufs.lst
+endif
+MOSTLYCLEANFILES += ufs_mod-fs_ufs.d
+UNDSYMFILES += und-ufs.lst
+
+ufs.mod: pre-ufs.o mod-ufs.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(ufs_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-ufs.o mod-ufs.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-ufs.o: $(ufs_mod_DEPENDENCIES) ufs_mod-fs_ufs.o
+       -rm -f $@
+       $(TARGET_CC) $(ufs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ ufs_mod-fs_ufs.o
+
+mod-ufs.o: mod-ufs.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ufs_mod_CFLAGS) -c -o $@ $<
+
+mod-ufs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'ufs' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(ufs_mod_EXPORTS),no)
+def-ufs.lst: pre-ufs.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 ufs/' > $@
+endif
+
+und-ufs.lst: pre-ufs.o
+       echo 'ufs' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+ufs_mod-fs_ufs.o: fs/ufs.c $(fs/ufs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(ufs_mod_CFLAGS) -MD -c -o $@ $<
+-include ufs_mod-fs_ufs.d
+
+CLEANFILES += cmd-ufs_mod-fs_ufs.lst fs-ufs_mod-fs_ufs.lst partmap-ufs_mod-fs_ufs.lst
+COMMANDFILES += cmd-ufs_mod-fs_ufs.lst
+FSFILES += fs-ufs_mod-fs_ufs.lst
+PARTMAPFILES += partmap-ufs_mod-fs_ufs.lst
+
+cmd-ufs_mod-fs_ufs.lst: fs/ufs.c $(fs/ufs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ufs_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh ufs > $@ || (rm -f $@; exit 1)
+
+fs-ufs_mod-fs_ufs.lst: fs/ufs.c $(fs/ufs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ufs_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh ufs > $@ || (rm -f $@; exit 1)
+
+partmap-ufs_mod-fs_ufs.lst: fs/ufs.c $(fs/ufs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ufs_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh ufs > $@ || (rm -f $@; exit 1)
+
+
+ufs_mod_CFLAGS = $(COMMON_CFLAGS)
+ufs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ext2.mod.
+ext2_mod_SOURCES = fs/ext2.c
+CLEANFILES += ext2.mod mod-ext2.o mod-ext2.c pre-ext2.o ext2_mod-fs_ext2.o und-ext2.lst
+ifneq ($(ext2_mod_EXPORTS),no)
+CLEANFILES += def-ext2.lst
+DEFSYMFILES += def-ext2.lst
+endif
+MOSTLYCLEANFILES += ext2_mod-fs_ext2.d
+UNDSYMFILES += und-ext2.lst
+
+ext2.mod: pre-ext2.o mod-ext2.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(ext2_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-ext2.o mod-ext2.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-ext2.o: $(ext2_mod_DEPENDENCIES) ext2_mod-fs_ext2.o
+       -rm -f $@
+       $(TARGET_CC) $(ext2_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ ext2_mod-fs_ext2.o
+
+mod-ext2.o: mod-ext2.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ext2_mod_CFLAGS) -c -o $@ $<
+
+mod-ext2.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'ext2' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(ext2_mod_EXPORTS),no)
+def-ext2.lst: pre-ext2.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 ext2/' > $@
+endif
+
+und-ext2.lst: pre-ext2.o
+       echo 'ext2' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+ext2_mod-fs_ext2.o: fs/ext2.c $(fs/ext2.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(ext2_mod_CFLAGS) -MD -c -o $@ $<
+-include ext2_mod-fs_ext2.d
+
+CLEANFILES += cmd-ext2_mod-fs_ext2.lst fs-ext2_mod-fs_ext2.lst partmap-ext2_mod-fs_ext2.lst
+COMMANDFILES += cmd-ext2_mod-fs_ext2.lst
+FSFILES += fs-ext2_mod-fs_ext2.lst
+PARTMAPFILES += partmap-ext2_mod-fs_ext2.lst
+
+cmd-ext2_mod-fs_ext2.lst: fs/ext2.c $(fs/ext2.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ext2_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh ext2 > $@ || (rm -f $@; exit 1)
+
+fs-ext2_mod-fs_ext2.lst: fs/ext2.c $(fs/ext2.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ext2_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh ext2 > $@ || (rm -f $@; exit 1)
+
+partmap-ext2_mod-fs_ext2.lst: fs/ext2.c $(fs/ext2.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ext2_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh ext2 > $@ || (rm -f $@; exit 1)
+
+
+ext2_mod_CFLAGS = $(COMMON_CFLAGS)
+ext2_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ntfs.mod.
+ntfs_mod_SOURCES = fs/ntfs.c
+CLEANFILES += ntfs.mod mod-ntfs.o mod-ntfs.c pre-ntfs.o ntfs_mod-fs_ntfs.o und-ntfs.lst
+ifneq ($(ntfs_mod_EXPORTS),no)
+CLEANFILES += def-ntfs.lst
+DEFSYMFILES += def-ntfs.lst
+endif
+MOSTLYCLEANFILES += ntfs_mod-fs_ntfs.d
+UNDSYMFILES += und-ntfs.lst
+
+ntfs.mod: pre-ntfs.o mod-ntfs.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(ntfs_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-ntfs.o mod-ntfs.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-ntfs.o: $(ntfs_mod_DEPENDENCIES) ntfs_mod-fs_ntfs.o
+       -rm -f $@
+       $(TARGET_CC) $(ntfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ ntfs_mod-fs_ntfs.o
+
+mod-ntfs.o: mod-ntfs.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ntfs_mod_CFLAGS) -c -o $@ $<
+
+mod-ntfs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'ntfs' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(ntfs_mod_EXPORTS),no)
+def-ntfs.lst: pre-ntfs.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 ntfs/' > $@
+endif
+
+und-ntfs.lst: pre-ntfs.o
+       echo 'ntfs' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+ntfs_mod-fs_ntfs.o: fs/ntfs.c $(fs/ntfs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(ntfs_mod_CFLAGS) -MD -c -o $@ $<
+-include ntfs_mod-fs_ntfs.d
+
+CLEANFILES += cmd-ntfs_mod-fs_ntfs.lst fs-ntfs_mod-fs_ntfs.lst partmap-ntfs_mod-fs_ntfs.lst
+COMMANDFILES += cmd-ntfs_mod-fs_ntfs.lst
+FSFILES += fs-ntfs_mod-fs_ntfs.lst
+PARTMAPFILES += partmap-ntfs_mod-fs_ntfs.lst
+
+cmd-ntfs_mod-fs_ntfs.lst: fs/ntfs.c $(fs/ntfs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ntfs_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh ntfs > $@ || (rm -f $@; exit 1)
+
+fs-ntfs_mod-fs_ntfs.lst: fs/ntfs.c $(fs/ntfs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ntfs_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh ntfs > $@ || (rm -f $@; exit 1)
+
+partmap-ntfs_mod-fs_ntfs.lst: fs/ntfs.c $(fs/ntfs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ntfs_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh ntfs > $@ || (rm -f $@; exit 1)
+
+
+ntfs_mod_CFLAGS = $(COMMON_CFLAGS)
+ntfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ntfscomp.mod.
+ntfscomp_mod_SOURCES = fs/ntfscomp.c
+CLEANFILES += ntfscomp.mod mod-ntfscomp.o mod-ntfscomp.c pre-ntfscomp.o ntfscomp_mod-fs_ntfscomp.o und-ntfscomp.lst
+ifneq ($(ntfscomp_mod_EXPORTS),no)
+CLEANFILES += def-ntfscomp.lst
+DEFSYMFILES += def-ntfscomp.lst
+endif
+MOSTLYCLEANFILES += ntfscomp_mod-fs_ntfscomp.d
+UNDSYMFILES += und-ntfscomp.lst
+
+ntfscomp.mod: pre-ntfscomp.o mod-ntfscomp.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(ntfscomp_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-ntfscomp.o mod-ntfscomp.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-ntfscomp.o: $(ntfscomp_mod_DEPENDENCIES) ntfscomp_mod-fs_ntfscomp.o
+       -rm -f $@
+       $(TARGET_CC) $(ntfscomp_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ ntfscomp_mod-fs_ntfscomp.o
+
+mod-ntfscomp.o: mod-ntfscomp.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ntfscomp_mod_CFLAGS) -c -o $@ $<
+
+mod-ntfscomp.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'ntfscomp' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(ntfscomp_mod_EXPORTS),no)
+def-ntfscomp.lst: pre-ntfscomp.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 ntfscomp/' > $@
+endif
+
+und-ntfscomp.lst: pre-ntfscomp.o
+       echo 'ntfscomp' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+ntfscomp_mod-fs_ntfscomp.o: fs/ntfscomp.c $(fs/ntfscomp.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(ntfscomp_mod_CFLAGS) -MD -c -o $@ $<
+-include ntfscomp_mod-fs_ntfscomp.d
+
+CLEANFILES += cmd-ntfscomp_mod-fs_ntfscomp.lst fs-ntfscomp_mod-fs_ntfscomp.lst partmap-ntfscomp_mod-fs_ntfscomp.lst
+COMMANDFILES += cmd-ntfscomp_mod-fs_ntfscomp.lst
+FSFILES += fs-ntfscomp_mod-fs_ntfscomp.lst
+PARTMAPFILES += partmap-ntfscomp_mod-fs_ntfscomp.lst
+
+cmd-ntfscomp_mod-fs_ntfscomp.lst: fs/ntfscomp.c $(fs/ntfscomp.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ntfscomp_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh ntfscomp > $@ || (rm -f $@; exit 1)
+
+fs-ntfscomp_mod-fs_ntfscomp.lst: fs/ntfscomp.c $(fs/ntfscomp.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ntfscomp_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh ntfscomp > $@ || (rm -f $@; exit 1)
+
+partmap-ntfscomp_mod-fs_ntfscomp.lst: fs/ntfscomp.c $(fs/ntfscomp.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ntfscomp_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh ntfscomp > $@ || (rm -f $@; exit 1)
+
+
+ntfscomp_mod_CFLAGS = $(COMMON_CFLAGS)
+ntfscomp_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For minix.mod.
+minix_mod_SOURCES = fs/minix.c
+CLEANFILES += minix.mod mod-minix.o mod-minix.c pre-minix.o minix_mod-fs_minix.o und-minix.lst
+ifneq ($(minix_mod_EXPORTS),no)
+CLEANFILES += def-minix.lst
+DEFSYMFILES += def-minix.lst
+endif
+MOSTLYCLEANFILES += minix_mod-fs_minix.d
+UNDSYMFILES += und-minix.lst
+
+minix.mod: pre-minix.o mod-minix.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(minix_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-minix.o mod-minix.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-minix.o: $(minix_mod_DEPENDENCIES) minix_mod-fs_minix.o
+       -rm -f $@
+       $(TARGET_CC) $(minix_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ minix_mod-fs_minix.o
+
+mod-minix.o: mod-minix.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(minix_mod_CFLAGS) -c -o $@ $<
+
+mod-minix.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'minix' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(minix_mod_EXPORTS),no)
+def-minix.lst: pre-minix.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 minix/' > $@
+endif
+
+und-minix.lst: pre-minix.o
+       echo 'minix' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+minix_mod-fs_minix.o: fs/minix.c $(fs/minix.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(minix_mod_CFLAGS) -MD -c -o $@ $<
+-include minix_mod-fs_minix.d
+
+CLEANFILES += cmd-minix_mod-fs_minix.lst fs-minix_mod-fs_minix.lst partmap-minix_mod-fs_minix.lst
+COMMANDFILES += cmd-minix_mod-fs_minix.lst
+FSFILES += fs-minix_mod-fs_minix.lst
+PARTMAPFILES += partmap-minix_mod-fs_minix.lst
+
+cmd-minix_mod-fs_minix.lst: fs/minix.c $(fs/minix.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(minix_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh minix > $@ || (rm -f $@; exit 1)
+
+fs-minix_mod-fs_minix.lst: fs/minix.c $(fs/minix.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(minix_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh minix > $@ || (rm -f $@; exit 1)
+
+partmap-minix_mod-fs_minix.lst: fs/minix.c $(fs/minix.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(minix_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh minix > $@ || (rm -f $@; exit 1)
+
+
+minix_mod_CFLAGS = $(COMMON_CFLAGS)
+minix_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For hfs.mod.
+hfs_mod_SOURCES = fs/hfs.c
+CLEANFILES += hfs.mod mod-hfs.o mod-hfs.c pre-hfs.o hfs_mod-fs_hfs.o und-hfs.lst
+ifneq ($(hfs_mod_EXPORTS),no)
+CLEANFILES += def-hfs.lst
+DEFSYMFILES += def-hfs.lst
+endif
+MOSTLYCLEANFILES += hfs_mod-fs_hfs.d
+UNDSYMFILES += und-hfs.lst
+
+hfs.mod: pre-hfs.o mod-hfs.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(hfs_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-hfs.o mod-hfs.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-hfs.o: $(hfs_mod_DEPENDENCIES) hfs_mod-fs_hfs.o
+       -rm -f $@
+       $(TARGET_CC) $(hfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ hfs_mod-fs_hfs.o
+
+mod-hfs.o: mod-hfs.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hfs_mod_CFLAGS) -c -o $@ $<
+
+mod-hfs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'hfs' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(hfs_mod_EXPORTS),no)
+def-hfs.lst: pre-hfs.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 hfs/' > $@
+endif
+
+und-hfs.lst: pre-hfs.o
+       echo 'hfs' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+hfs_mod-fs_hfs.o: fs/hfs.c $(fs/hfs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(hfs_mod_CFLAGS) -MD -c -o $@ $<
+-include hfs_mod-fs_hfs.d
+
+CLEANFILES += cmd-hfs_mod-fs_hfs.lst fs-hfs_mod-fs_hfs.lst partmap-hfs_mod-fs_hfs.lst
+COMMANDFILES += cmd-hfs_mod-fs_hfs.lst
+FSFILES += fs-hfs_mod-fs_hfs.lst
+PARTMAPFILES += partmap-hfs_mod-fs_hfs.lst
+
+cmd-hfs_mod-fs_hfs.lst: fs/hfs.c $(fs/hfs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hfs_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh hfs > $@ || (rm -f $@; exit 1)
+
+fs-hfs_mod-fs_hfs.lst: fs/hfs.c $(fs/hfs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh hfs > $@ || (rm -f $@; exit 1)
+
+partmap-hfs_mod-fs_hfs.lst: fs/hfs.c $(fs/hfs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh hfs > $@ || (rm -f $@; exit 1)
+
+
+hfs_mod_CFLAGS = $(COMMON_CFLAGS)
+hfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For jfs.mod.
+jfs_mod_SOURCES = fs/jfs.c
+CLEANFILES += jfs.mod mod-jfs.o mod-jfs.c pre-jfs.o jfs_mod-fs_jfs.o und-jfs.lst
+ifneq ($(jfs_mod_EXPORTS),no)
+CLEANFILES += def-jfs.lst
+DEFSYMFILES += def-jfs.lst
+endif
+MOSTLYCLEANFILES += jfs_mod-fs_jfs.d
+UNDSYMFILES += und-jfs.lst
+
+jfs.mod: pre-jfs.o mod-jfs.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(jfs_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-jfs.o mod-jfs.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-jfs.o: $(jfs_mod_DEPENDENCIES) jfs_mod-fs_jfs.o
+       -rm -f $@
+       $(TARGET_CC) $(jfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ jfs_mod-fs_jfs.o
+
+mod-jfs.o: mod-jfs.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(jfs_mod_CFLAGS) -c -o $@ $<
+
+mod-jfs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'jfs' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(jfs_mod_EXPORTS),no)
+def-jfs.lst: pre-jfs.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 jfs/' > $@
+endif
+
+und-jfs.lst: pre-jfs.o
+       echo 'jfs' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+jfs_mod-fs_jfs.o: fs/jfs.c $(fs/jfs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(jfs_mod_CFLAGS) -MD -c -o $@ $<
+-include jfs_mod-fs_jfs.d
+
+CLEANFILES += cmd-jfs_mod-fs_jfs.lst fs-jfs_mod-fs_jfs.lst partmap-jfs_mod-fs_jfs.lst
+COMMANDFILES += cmd-jfs_mod-fs_jfs.lst
+FSFILES += fs-jfs_mod-fs_jfs.lst
+PARTMAPFILES += partmap-jfs_mod-fs_jfs.lst
+
+cmd-jfs_mod-fs_jfs.lst: fs/jfs.c $(fs/jfs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(jfs_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh jfs > $@ || (rm -f $@; exit 1)
+
+fs-jfs_mod-fs_jfs.lst: fs/jfs.c $(fs/jfs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(jfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh jfs > $@ || (rm -f $@; exit 1)
+
+partmap-jfs_mod-fs_jfs.lst: fs/jfs.c $(fs/jfs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(jfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh jfs > $@ || (rm -f $@; exit 1)
+
+
+jfs_mod_CFLAGS = $(COMMON_CFLAGS)
+jfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For iso9660.mod.
+iso9660_mod_SOURCES = fs/iso9660.c
+CLEANFILES += iso9660.mod mod-iso9660.o mod-iso9660.c pre-iso9660.o iso9660_mod-fs_iso9660.o und-iso9660.lst
+ifneq ($(iso9660_mod_EXPORTS),no)
+CLEANFILES += def-iso9660.lst
+DEFSYMFILES += def-iso9660.lst
+endif
+MOSTLYCLEANFILES += iso9660_mod-fs_iso9660.d
+UNDSYMFILES += und-iso9660.lst
+
+iso9660.mod: pre-iso9660.o mod-iso9660.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(iso9660_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-iso9660.o mod-iso9660.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-iso9660.o: $(iso9660_mod_DEPENDENCIES) iso9660_mod-fs_iso9660.o
+       -rm -f $@
+       $(TARGET_CC) $(iso9660_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ iso9660_mod-fs_iso9660.o
+
+mod-iso9660.o: mod-iso9660.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(iso9660_mod_CFLAGS) -c -o $@ $<
+
+mod-iso9660.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'iso9660' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(iso9660_mod_EXPORTS),no)
+def-iso9660.lst: pre-iso9660.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 iso9660/' > $@
+endif
+
+und-iso9660.lst: pre-iso9660.o
+       echo 'iso9660' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+iso9660_mod-fs_iso9660.o: fs/iso9660.c $(fs/iso9660.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(iso9660_mod_CFLAGS) -MD -c -o $@ $<
+-include iso9660_mod-fs_iso9660.d
+
+CLEANFILES += cmd-iso9660_mod-fs_iso9660.lst fs-iso9660_mod-fs_iso9660.lst partmap-iso9660_mod-fs_iso9660.lst
+COMMANDFILES += cmd-iso9660_mod-fs_iso9660.lst
+FSFILES += fs-iso9660_mod-fs_iso9660.lst
+PARTMAPFILES += partmap-iso9660_mod-fs_iso9660.lst
+
+cmd-iso9660_mod-fs_iso9660.lst: fs/iso9660.c $(fs/iso9660.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(iso9660_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh iso9660 > $@ || (rm -f $@; exit 1)
+
+fs-iso9660_mod-fs_iso9660.lst: fs/iso9660.c $(fs/iso9660.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(iso9660_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh iso9660 > $@ || (rm -f $@; exit 1)
+
+partmap-iso9660_mod-fs_iso9660.lst: fs/iso9660.c $(fs/iso9660.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(iso9660_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh iso9660 > $@ || (rm -f $@; exit 1)
+
+
+iso9660_mod_CFLAGS = $(COMMON_CFLAGS)
+iso9660_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For xfs.mod.
+xfs_mod_SOURCES = fs/xfs.c
+CLEANFILES += xfs.mod mod-xfs.o mod-xfs.c pre-xfs.o xfs_mod-fs_xfs.o und-xfs.lst
+ifneq ($(xfs_mod_EXPORTS),no)
+CLEANFILES += def-xfs.lst
+DEFSYMFILES += def-xfs.lst
+endif
+MOSTLYCLEANFILES += xfs_mod-fs_xfs.d
+UNDSYMFILES += und-xfs.lst
+
+xfs.mod: pre-xfs.o mod-xfs.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(xfs_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-xfs.o mod-xfs.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-xfs.o: $(xfs_mod_DEPENDENCIES) xfs_mod-fs_xfs.o
+       -rm -f $@
+       $(TARGET_CC) $(xfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ xfs_mod-fs_xfs.o
+
+mod-xfs.o: mod-xfs.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(xfs_mod_CFLAGS) -c -o $@ $<
+
+mod-xfs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'xfs' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(xfs_mod_EXPORTS),no)
+def-xfs.lst: pre-xfs.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 xfs/' > $@
+endif
+
+und-xfs.lst: pre-xfs.o
+       echo 'xfs' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+xfs_mod-fs_xfs.o: fs/xfs.c $(fs/xfs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(xfs_mod_CFLAGS) -MD -c -o $@ $<
+-include xfs_mod-fs_xfs.d
+
+CLEANFILES += cmd-xfs_mod-fs_xfs.lst fs-xfs_mod-fs_xfs.lst partmap-xfs_mod-fs_xfs.lst
+COMMANDFILES += cmd-xfs_mod-fs_xfs.lst
+FSFILES += fs-xfs_mod-fs_xfs.lst
+PARTMAPFILES += partmap-xfs_mod-fs_xfs.lst
+
+cmd-xfs_mod-fs_xfs.lst: fs/xfs.c $(fs/xfs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(xfs_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh xfs > $@ || (rm -f $@; exit 1)
+
+fs-xfs_mod-fs_xfs.lst: fs/xfs.c $(fs/xfs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(xfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh xfs > $@ || (rm -f $@; exit 1)
+
+partmap-xfs_mod-fs_xfs.lst: fs/xfs.c $(fs/xfs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(xfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh xfs > $@ || (rm -f $@; exit 1)
+
+
+xfs_mod_CFLAGS = $(COMMON_CFLAGS)
+xfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For affs.mod.
+affs_mod_SOURCES = fs/affs.c
+CLEANFILES += affs.mod mod-affs.o mod-affs.c pre-affs.o affs_mod-fs_affs.o und-affs.lst
+ifneq ($(affs_mod_EXPORTS),no)
+CLEANFILES += def-affs.lst
+DEFSYMFILES += def-affs.lst
+endif
+MOSTLYCLEANFILES += affs_mod-fs_affs.d
+UNDSYMFILES += und-affs.lst
+
+affs.mod: pre-affs.o mod-affs.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(affs_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-affs.o mod-affs.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-affs.o: $(affs_mod_DEPENDENCIES) affs_mod-fs_affs.o
+       -rm -f $@
+       $(TARGET_CC) $(affs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ affs_mod-fs_affs.o
+
+mod-affs.o: mod-affs.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(affs_mod_CFLAGS) -c -o $@ $<
+
+mod-affs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'affs' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(affs_mod_EXPORTS),no)
+def-affs.lst: pre-affs.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 affs/' > $@
+endif
+
+und-affs.lst: pre-affs.o
+       echo 'affs' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+affs_mod-fs_affs.o: fs/affs.c $(fs/affs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(affs_mod_CFLAGS) -MD -c -o $@ $<
+-include affs_mod-fs_affs.d
+
+CLEANFILES += cmd-affs_mod-fs_affs.lst fs-affs_mod-fs_affs.lst partmap-affs_mod-fs_affs.lst
+COMMANDFILES += cmd-affs_mod-fs_affs.lst
+FSFILES += fs-affs_mod-fs_affs.lst
+PARTMAPFILES += partmap-affs_mod-fs_affs.lst
+
+cmd-affs_mod-fs_affs.lst: fs/affs.c $(fs/affs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(affs_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh affs > $@ || (rm -f $@; exit 1)
+
+fs-affs_mod-fs_affs.lst: fs/affs.c $(fs/affs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(affs_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh affs > $@ || (rm -f $@; exit 1)
+
+partmap-affs_mod-fs_affs.lst: fs/affs.c $(fs/affs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(affs_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh affs > $@ || (rm -f $@; exit 1)
+
+
+affs_mod_CFLAGS = $(COMMON_CFLAGS)
+affs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For sfs.mod.
+sfs_mod_SOURCES = fs/sfs.c
+CLEANFILES += sfs.mod mod-sfs.o mod-sfs.c pre-sfs.o sfs_mod-fs_sfs.o und-sfs.lst
+ifneq ($(sfs_mod_EXPORTS),no)
+CLEANFILES += def-sfs.lst
+DEFSYMFILES += def-sfs.lst
+endif
+MOSTLYCLEANFILES += sfs_mod-fs_sfs.d
+UNDSYMFILES += und-sfs.lst
+
+sfs.mod: pre-sfs.o mod-sfs.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(sfs_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-sfs.o mod-sfs.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-sfs.o: $(sfs_mod_DEPENDENCIES) sfs_mod-fs_sfs.o
+       -rm -f $@
+       $(TARGET_CC) $(sfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ sfs_mod-fs_sfs.o
+
+mod-sfs.o: mod-sfs.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sfs_mod_CFLAGS) -c -o $@ $<
+
+mod-sfs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'sfs' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(sfs_mod_EXPORTS),no)
+def-sfs.lst: pre-sfs.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 sfs/' > $@
+endif
+
+und-sfs.lst: pre-sfs.o
+       echo 'sfs' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+sfs_mod-fs_sfs.o: fs/sfs.c $(fs/sfs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(sfs_mod_CFLAGS) -MD -c -o $@ $<
+-include sfs_mod-fs_sfs.d
+
+CLEANFILES += cmd-sfs_mod-fs_sfs.lst fs-sfs_mod-fs_sfs.lst partmap-sfs_mod-fs_sfs.lst
+COMMANDFILES += cmd-sfs_mod-fs_sfs.lst
+FSFILES += fs-sfs_mod-fs_sfs.lst
+PARTMAPFILES += partmap-sfs_mod-fs_sfs.lst
+
+cmd-sfs_mod-fs_sfs.lst: fs/sfs.c $(fs/sfs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sfs_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh sfs > $@ || (rm -f $@; exit 1)
+
+fs-sfs_mod-fs_sfs.lst: fs/sfs.c $(fs/sfs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh sfs > $@ || (rm -f $@; exit 1)
+
+partmap-sfs_mod-fs_sfs.lst: fs/sfs.c $(fs/sfs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh sfs > $@ || (rm -f $@; exit 1)
+
+
+sfs_mod_CFLAGS = $(COMMON_CFLAGS)
+sfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For hfsplus.mod.
+hfsplus_mod_SOURCES = fs/hfsplus.c
+CLEANFILES += hfsplus.mod mod-hfsplus.o mod-hfsplus.c pre-hfsplus.o hfsplus_mod-fs_hfsplus.o und-hfsplus.lst
+ifneq ($(hfsplus_mod_EXPORTS),no)
+CLEANFILES += def-hfsplus.lst
+DEFSYMFILES += def-hfsplus.lst
+endif
+MOSTLYCLEANFILES += hfsplus_mod-fs_hfsplus.d
+UNDSYMFILES += und-hfsplus.lst
+
+hfsplus.mod: pre-hfsplus.o mod-hfsplus.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(hfsplus_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-hfsplus.o mod-hfsplus.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-hfsplus.o: $(hfsplus_mod_DEPENDENCIES) hfsplus_mod-fs_hfsplus.o
+       -rm -f $@
+       $(TARGET_CC) $(hfsplus_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ hfsplus_mod-fs_hfsplus.o
+
+mod-hfsplus.o: mod-hfsplus.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hfsplus_mod_CFLAGS) -c -o $@ $<
+
+mod-hfsplus.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'hfsplus' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(hfsplus_mod_EXPORTS),no)
+def-hfsplus.lst: pre-hfsplus.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 hfsplus/' > $@
+endif
+
+und-hfsplus.lst: pre-hfsplus.o
+       echo 'hfsplus' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+hfsplus_mod-fs_hfsplus.o: fs/hfsplus.c $(fs/hfsplus.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(hfsplus_mod_CFLAGS) -MD -c -o $@ $<
+-include hfsplus_mod-fs_hfsplus.d
+
+CLEANFILES += cmd-hfsplus_mod-fs_hfsplus.lst fs-hfsplus_mod-fs_hfsplus.lst partmap-hfsplus_mod-fs_hfsplus.lst
+COMMANDFILES += cmd-hfsplus_mod-fs_hfsplus.lst
+FSFILES += fs-hfsplus_mod-fs_hfsplus.lst
+PARTMAPFILES += partmap-hfsplus_mod-fs_hfsplus.lst
+
+cmd-hfsplus_mod-fs_hfsplus.lst: fs/hfsplus.c $(fs/hfsplus.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hfsplus_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh hfsplus > $@ || (rm -f $@; exit 1)
+
+fs-hfsplus_mod-fs_hfsplus.lst: fs/hfsplus.c $(fs/hfsplus.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hfsplus_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh hfsplus > $@ || (rm -f $@; exit 1)
+
+partmap-hfsplus_mod-fs_hfsplus.lst: fs/hfsplus.c $(fs/hfsplus.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hfsplus_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh hfsplus > $@ || (rm -f $@; exit 1)
+
+
+hfsplus_mod_CFLAGS = $(COMMON_CFLAGS)
+hfsplus_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reiserfs.mod.
+reiserfs_mod_SOURCES = fs/reiserfs.c
+CLEANFILES += reiserfs.mod mod-reiserfs.o mod-reiserfs.c pre-reiserfs.o reiserfs_mod-fs_reiserfs.o und-reiserfs.lst
+ifneq ($(reiserfs_mod_EXPORTS),no)
+CLEANFILES += def-reiserfs.lst
+DEFSYMFILES += def-reiserfs.lst
+endif
+MOSTLYCLEANFILES += reiserfs_mod-fs_reiserfs.d
+UNDSYMFILES += und-reiserfs.lst
+
+reiserfs.mod: pre-reiserfs.o mod-reiserfs.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(reiserfs_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-reiserfs.o mod-reiserfs.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-reiserfs.o: $(reiserfs_mod_DEPENDENCIES) reiserfs_mod-fs_reiserfs.o
+       -rm -f $@
+       $(TARGET_CC) $(reiserfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ reiserfs_mod-fs_reiserfs.o
+
+mod-reiserfs.o: mod-reiserfs.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reiserfs_mod_CFLAGS) -c -o $@ $<
+
+mod-reiserfs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'reiserfs' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(reiserfs_mod_EXPORTS),no)
+def-reiserfs.lst: pre-reiserfs.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 reiserfs/' > $@
+endif
+
+und-reiserfs.lst: pre-reiserfs.o
+       echo 'reiserfs' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+reiserfs_mod-fs_reiserfs.o: fs/reiserfs.c $(fs/reiserfs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(reiserfs_mod_CFLAGS) -MD -c -o $@ $<
+-include reiserfs_mod-fs_reiserfs.d
+
+CLEANFILES += cmd-reiserfs_mod-fs_reiserfs.lst fs-reiserfs_mod-fs_reiserfs.lst partmap-reiserfs_mod-fs_reiserfs.lst
+COMMANDFILES += cmd-reiserfs_mod-fs_reiserfs.lst
+FSFILES += fs-reiserfs_mod-fs_reiserfs.lst
+PARTMAPFILES += partmap-reiserfs_mod-fs_reiserfs.lst
+
+cmd-reiserfs_mod-fs_reiserfs.lst: fs/reiserfs.c $(fs/reiserfs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reiserfs_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh reiserfs > $@ || (rm -f $@; exit 1)
+
+fs-reiserfs_mod-fs_reiserfs.lst: fs/reiserfs.c $(fs/reiserfs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reiserfs_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh reiserfs > $@ || (rm -f $@; exit 1)
+
+partmap-reiserfs_mod-fs_reiserfs.lst: fs/reiserfs.c $(fs/reiserfs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reiserfs_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh reiserfs > $@ || (rm -f $@; exit 1)
+
+
+reiserfs_mod_CFLAGS = $(COMMON_CFLAGS)
+reiserfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For cpio.mod.
+cpio_mod_SOURCES = fs/cpio.c
+CLEANFILES += cpio.mod mod-cpio.o mod-cpio.c pre-cpio.o cpio_mod-fs_cpio.o und-cpio.lst
+ifneq ($(cpio_mod_EXPORTS),no)
+CLEANFILES += def-cpio.lst
+DEFSYMFILES += def-cpio.lst
+endif
+MOSTLYCLEANFILES += cpio_mod-fs_cpio.d
+UNDSYMFILES += und-cpio.lst
+
+cpio.mod: pre-cpio.o mod-cpio.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(cpio_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-cpio.o mod-cpio.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-cpio.o: $(cpio_mod_DEPENDENCIES) cpio_mod-fs_cpio.o
+       -rm -f $@
+       $(TARGET_CC) $(cpio_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ cpio_mod-fs_cpio.o
+
+mod-cpio.o: mod-cpio.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cpio_mod_CFLAGS) -c -o $@ $<
+
+mod-cpio.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'cpio' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(cpio_mod_EXPORTS),no)
+def-cpio.lst: pre-cpio.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 cpio/' > $@
+endif
+
+und-cpio.lst: pre-cpio.o
+       echo 'cpio' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+cpio_mod-fs_cpio.o: fs/cpio.c $(fs/cpio.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(cpio_mod_CFLAGS) -MD -c -o $@ $<
+-include cpio_mod-fs_cpio.d
+
+CLEANFILES += cmd-cpio_mod-fs_cpio.lst fs-cpio_mod-fs_cpio.lst partmap-cpio_mod-fs_cpio.lst
+COMMANDFILES += cmd-cpio_mod-fs_cpio.lst
+FSFILES += fs-cpio_mod-fs_cpio.lst
+PARTMAPFILES += partmap-cpio_mod-fs_cpio.lst
+
+cmd-cpio_mod-fs_cpio.lst: fs/cpio.c $(fs/cpio.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cpio_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh cpio > $@ || (rm -f $@; exit 1)
+
+fs-cpio_mod-fs_cpio.lst: fs/cpio.c $(fs/cpio.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cpio_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh cpio > $@ || (rm -f $@; exit 1)
+
+partmap-cpio_mod-fs_cpio.lst: fs/cpio.c $(fs/cpio.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cpio_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh cpio > $@ || (rm -f $@; exit 1)
+
+
+cpio_mod_CFLAGS = $(COMMON_CFLAGS)
+cpio_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For tar.mod.
+tar_mod_SOURCES = fs/cpio.c
+CLEANFILES += tar.mod mod-tar.o mod-tar.c pre-tar.o tar_mod-fs_cpio.o und-tar.lst
+ifneq ($(tar_mod_EXPORTS),no)
+CLEANFILES += def-tar.lst
+DEFSYMFILES += def-tar.lst
+endif
+MOSTLYCLEANFILES += tar_mod-fs_cpio.d
+UNDSYMFILES += und-tar.lst
+
+tar.mod: pre-tar.o mod-tar.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(tar_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-tar.o mod-tar.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-tar.o: $(tar_mod_DEPENDENCIES) tar_mod-fs_cpio.o
+       -rm -f $@
+       $(TARGET_CC) $(tar_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ tar_mod-fs_cpio.o
+
+mod-tar.o: mod-tar.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(tar_mod_CFLAGS) -c -o $@ $<
+
+mod-tar.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'tar' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(tar_mod_EXPORTS),no)
+def-tar.lst: pre-tar.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 tar/' > $@
+endif
+
+und-tar.lst: pre-tar.o
+       echo 'tar' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+tar_mod-fs_cpio.o: fs/cpio.c $(fs/cpio.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(tar_mod_CFLAGS) -MD -c -o $@ $<
+-include tar_mod-fs_cpio.d
+
+CLEANFILES += cmd-tar_mod-fs_cpio.lst fs-tar_mod-fs_cpio.lst partmap-tar_mod-fs_cpio.lst
+COMMANDFILES += cmd-tar_mod-fs_cpio.lst
+FSFILES += fs-tar_mod-fs_cpio.lst
+PARTMAPFILES += partmap-tar_mod-fs_cpio.lst
+
+cmd-tar_mod-fs_cpio.lst: fs/cpio.c $(fs/cpio.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(tar_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh tar > $@ || (rm -f $@; exit 1)
+
+fs-tar_mod-fs_cpio.lst: fs/cpio.c $(fs/cpio.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(tar_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh tar > $@ || (rm -f $@; exit 1)
+
+partmap-tar_mod-fs_cpio.lst: fs/cpio.c $(fs/cpio.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(tar_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh tar > $@ || (rm -f $@; exit 1)
+
+
+tar_mod_CFLAGS = $(COMMON_CFLAGS) -DMODE_USTAR
+tar_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For udf.mod.
+udf_mod_SOURCES = fs/udf.c
+CLEANFILES += udf.mod mod-udf.o mod-udf.c pre-udf.o udf_mod-fs_udf.o und-udf.lst
+ifneq ($(udf_mod_EXPORTS),no)
+CLEANFILES += def-udf.lst
+DEFSYMFILES += def-udf.lst
+endif
+MOSTLYCLEANFILES += udf_mod-fs_udf.d
+UNDSYMFILES += und-udf.lst
+
+udf.mod: pre-udf.o mod-udf.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(udf_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-udf.o mod-udf.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-udf.o: $(udf_mod_DEPENDENCIES) udf_mod-fs_udf.o
+       -rm -f $@
+       $(TARGET_CC) $(udf_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ udf_mod-fs_udf.o
+
+mod-udf.o: mod-udf.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(udf_mod_CFLAGS) -c -o $@ $<
+
+mod-udf.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'udf' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(udf_mod_EXPORTS),no)
+def-udf.lst: pre-udf.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 udf/' > $@
+endif
+
+und-udf.lst: pre-udf.o
+       echo 'udf' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+udf_mod-fs_udf.o: fs/udf.c $(fs/udf.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(udf_mod_CFLAGS) -MD -c -o $@ $<
+-include udf_mod-fs_udf.d
+
+CLEANFILES += cmd-udf_mod-fs_udf.lst fs-udf_mod-fs_udf.lst partmap-udf_mod-fs_udf.lst
+COMMANDFILES += cmd-udf_mod-fs_udf.lst
+FSFILES += fs-udf_mod-fs_udf.lst
+PARTMAPFILES += partmap-udf_mod-fs_udf.lst
+
+cmd-udf_mod-fs_udf.lst: fs/udf.c $(fs/udf.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(udf_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh udf > $@ || (rm -f $@; exit 1)
+
+fs-udf_mod-fs_udf.lst: fs/udf.c $(fs/udf.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(udf_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh udf > $@ || (rm -f $@; exit 1)
+
+partmap-udf_mod-fs_udf.lst: fs/udf.c $(fs/udf.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(udf_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh udf > $@ || (rm -f $@; exit 1)
+
+
+udf_mod_CFLAGS = $(COMMON_CFLAGS)
+udf_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For afs.mod.
+afs_mod_SOURCES = fs/afs.c
+CLEANFILES += afs.mod mod-afs.o mod-afs.c pre-afs.o afs_mod-fs_afs.o und-afs.lst
+ifneq ($(afs_mod_EXPORTS),no)
+CLEANFILES += def-afs.lst
+DEFSYMFILES += def-afs.lst
+endif
+MOSTLYCLEANFILES += afs_mod-fs_afs.d
+UNDSYMFILES += und-afs.lst
+
+afs.mod: pre-afs.o mod-afs.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(afs_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-afs.o mod-afs.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-afs.o: $(afs_mod_DEPENDENCIES) afs_mod-fs_afs.o
+       -rm -f $@
+       $(TARGET_CC) $(afs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ afs_mod-fs_afs.o
+
+mod-afs.o: mod-afs.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(afs_mod_CFLAGS) -c -o $@ $<
+
+mod-afs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'afs' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(afs_mod_EXPORTS),no)
+def-afs.lst: pre-afs.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 afs/' > $@
+endif
+
+und-afs.lst: pre-afs.o
+       echo 'afs' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+afs_mod-fs_afs.o: fs/afs.c $(fs/afs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(afs_mod_CFLAGS) -MD -c -o $@ $<
+-include afs_mod-fs_afs.d
+
+CLEANFILES += cmd-afs_mod-fs_afs.lst fs-afs_mod-fs_afs.lst partmap-afs_mod-fs_afs.lst
+COMMANDFILES += cmd-afs_mod-fs_afs.lst
+FSFILES += fs-afs_mod-fs_afs.lst
+PARTMAPFILES += partmap-afs_mod-fs_afs.lst
+
+cmd-afs_mod-fs_afs.lst: fs/afs.c $(fs/afs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(afs_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh afs > $@ || (rm -f $@; exit 1)
+
+fs-afs_mod-fs_afs.lst: fs/afs.c $(fs/afs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(afs_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh afs > $@ || (rm -f $@; exit 1)
+
+partmap-afs_mod-fs_afs.lst: fs/afs.c $(fs/afs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(afs_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh afs > $@ || (rm -f $@; exit 1)
+
+
+afs_mod_CFLAGS = $(COMMON_CFLAGS)
+afs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# Partition maps.
+pkglib_MODULES += amiga.mod apple.mod pc.mod sun.mod acorn.mod gpt.mod
+
+# For amiga.mod
+amiga_mod_SOURCES = partmap/amiga.c
+CLEANFILES += amiga.mod mod-amiga.o mod-amiga.c pre-amiga.o amiga_mod-partmap_amiga.o und-amiga.lst
+ifneq ($(amiga_mod_EXPORTS),no)
+CLEANFILES += def-amiga.lst
+DEFSYMFILES += def-amiga.lst
+endif
+MOSTLYCLEANFILES += amiga_mod-partmap_amiga.d
+UNDSYMFILES += und-amiga.lst
+
+amiga.mod: pre-amiga.o mod-amiga.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(amiga_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-amiga.o mod-amiga.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-amiga.o: $(amiga_mod_DEPENDENCIES) amiga_mod-partmap_amiga.o
+       -rm -f $@
+       $(TARGET_CC) $(amiga_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ amiga_mod-partmap_amiga.o
+
+mod-amiga.o: mod-amiga.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(amiga_mod_CFLAGS) -c -o $@ $<
+
+mod-amiga.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'amiga' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(amiga_mod_EXPORTS),no)
+def-amiga.lst: pre-amiga.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 amiga/' > $@
+endif
+
+und-amiga.lst: pre-amiga.o
+       echo 'amiga' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+amiga_mod-partmap_amiga.o: partmap/amiga.c $(partmap/amiga.c_DEPENDENCIES)
+       $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(amiga_mod_CFLAGS) -MD -c -o $@ $<
+-include amiga_mod-partmap_amiga.d
+
+CLEANFILES += cmd-amiga_mod-partmap_amiga.lst fs-amiga_mod-partmap_amiga.lst partmap-amiga_mod-partmap_amiga.lst
+COMMANDFILES += cmd-amiga_mod-partmap_amiga.lst
+FSFILES += fs-amiga_mod-partmap_amiga.lst
+PARTMAPFILES += partmap-amiga_mod-partmap_amiga.lst
+
+cmd-amiga_mod-partmap_amiga.lst: partmap/amiga.c $(partmap/amiga.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(amiga_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh amiga > $@ || (rm -f $@; exit 1)
+
+fs-amiga_mod-partmap_amiga.lst: partmap/amiga.c $(partmap/amiga.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(amiga_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh amiga > $@ || (rm -f $@; exit 1)
+
+partmap-amiga_mod-partmap_amiga.lst: partmap/amiga.c $(partmap/amiga.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(amiga_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh amiga > $@ || (rm -f $@; exit 1)
+
+
+amiga_mod_CFLAGS = $(COMMON_CFLAGS)
+amiga_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For apple.mod
+apple_mod_SOURCES = partmap/apple.c
+CLEANFILES += apple.mod mod-apple.o mod-apple.c pre-apple.o apple_mod-partmap_apple.o und-apple.lst
+ifneq ($(apple_mod_EXPORTS),no)
+CLEANFILES += def-apple.lst
+DEFSYMFILES += def-apple.lst
+endif
+MOSTLYCLEANFILES += apple_mod-partmap_apple.d
+UNDSYMFILES += und-apple.lst
+
+apple.mod: pre-apple.o mod-apple.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(apple_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-apple.o mod-apple.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-apple.o: $(apple_mod_DEPENDENCIES) apple_mod-partmap_apple.o
+       -rm -f $@
+       $(TARGET_CC) $(apple_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ apple_mod-partmap_apple.o
+
+mod-apple.o: mod-apple.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(apple_mod_CFLAGS) -c -o $@ $<
+
+mod-apple.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'apple' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(apple_mod_EXPORTS),no)
+def-apple.lst: pre-apple.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 apple/' > $@
+endif
+
+und-apple.lst: pre-apple.o
+       echo 'apple' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+apple_mod-partmap_apple.o: partmap/apple.c $(partmap/apple.c_DEPENDENCIES)
+       $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(apple_mod_CFLAGS) -MD -c -o $@ $<
+-include apple_mod-partmap_apple.d
+
+CLEANFILES += cmd-apple_mod-partmap_apple.lst fs-apple_mod-partmap_apple.lst partmap-apple_mod-partmap_apple.lst
+COMMANDFILES += cmd-apple_mod-partmap_apple.lst
+FSFILES += fs-apple_mod-partmap_apple.lst
+PARTMAPFILES += partmap-apple_mod-partmap_apple.lst
+
+cmd-apple_mod-partmap_apple.lst: partmap/apple.c $(partmap/apple.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(apple_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh apple > $@ || (rm -f $@; exit 1)
+
+fs-apple_mod-partmap_apple.lst: partmap/apple.c $(partmap/apple.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(apple_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh apple > $@ || (rm -f $@; exit 1)
+
+partmap-apple_mod-partmap_apple.lst: partmap/apple.c $(partmap/apple.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(apple_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh apple > $@ || (rm -f $@; exit 1)
+
+
+apple_mod_CFLAGS = $(COMMON_CFLAGS)
+apple_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pc.mod
+pc_mod_SOURCES = partmap/pc.c
+CLEANFILES += pc.mod mod-pc.o mod-pc.c pre-pc.o pc_mod-partmap_pc.o und-pc.lst
+ifneq ($(pc_mod_EXPORTS),no)
+CLEANFILES += def-pc.lst
+DEFSYMFILES += def-pc.lst
+endif
+MOSTLYCLEANFILES += pc_mod-partmap_pc.d
+UNDSYMFILES += und-pc.lst
+
+pc.mod: pre-pc.o mod-pc.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(pc_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-pc.o mod-pc.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-pc.o: $(pc_mod_DEPENDENCIES) pc_mod-partmap_pc.o
+       -rm -f $@
+       $(TARGET_CC) $(pc_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pc_mod-partmap_pc.o
+
+mod-pc.o: mod-pc.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pc_mod_CFLAGS) -c -o $@ $<
+
+mod-pc.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'pc' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(pc_mod_EXPORTS),no)
+def-pc.lst: pre-pc.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 pc/' > $@
+endif
+
+und-pc.lst: pre-pc.o
+       echo 'pc' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+pc_mod-partmap_pc.o: partmap/pc.c $(partmap/pc.c_DEPENDENCIES)
+       $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(pc_mod_CFLAGS) -MD -c -o $@ $<
+-include pc_mod-partmap_pc.d
+
+CLEANFILES += cmd-pc_mod-partmap_pc.lst fs-pc_mod-partmap_pc.lst partmap-pc_mod-partmap_pc.lst
+COMMANDFILES += cmd-pc_mod-partmap_pc.lst
+FSFILES += fs-pc_mod-partmap_pc.lst
+PARTMAPFILES += partmap-pc_mod-partmap_pc.lst
+
+cmd-pc_mod-partmap_pc.lst: partmap/pc.c $(partmap/pc.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pc_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh pc > $@ || (rm -f $@; exit 1)
+
+fs-pc_mod-partmap_pc.lst: partmap/pc.c $(partmap/pc.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pc_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh pc > $@ || (rm -f $@; exit 1)
+
+partmap-pc_mod-partmap_pc.lst: partmap/pc.c $(partmap/pc.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pc_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh pc > $@ || (rm -f $@; exit 1)
+
+
+pc_mod_CFLAGS = $(COMMON_CFLAGS)
+pc_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For sun.mod
+sun_mod_SOURCES = partmap/sun.c
+CLEANFILES += sun.mod mod-sun.o mod-sun.c pre-sun.o sun_mod-partmap_sun.o und-sun.lst
+ifneq ($(sun_mod_EXPORTS),no)
+CLEANFILES += def-sun.lst
+DEFSYMFILES += def-sun.lst
+endif
+MOSTLYCLEANFILES += sun_mod-partmap_sun.d
+UNDSYMFILES += und-sun.lst
+
+sun.mod: pre-sun.o mod-sun.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(sun_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-sun.o mod-sun.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-sun.o: $(sun_mod_DEPENDENCIES) sun_mod-partmap_sun.o
+       -rm -f $@
+       $(TARGET_CC) $(sun_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ sun_mod-partmap_sun.o
+
+mod-sun.o: mod-sun.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sun_mod_CFLAGS) -c -o $@ $<
+
+mod-sun.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'sun' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(sun_mod_EXPORTS),no)
+def-sun.lst: pre-sun.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 sun/' > $@
+endif
+
+und-sun.lst: pre-sun.o
+       echo 'sun' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+sun_mod-partmap_sun.o: partmap/sun.c $(partmap/sun.c_DEPENDENCIES)
+       $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(sun_mod_CFLAGS) -MD -c -o $@ $<
+-include sun_mod-partmap_sun.d
+
+CLEANFILES += cmd-sun_mod-partmap_sun.lst fs-sun_mod-partmap_sun.lst partmap-sun_mod-partmap_sun.lst
+COMMANDFILES += cmd-sun_mod-partmap_sun.lst
+FSFILES += fs-sun_mod-partmap_sun.lst
+PARTMAPFILES += partmap-sun_mod-partmap_sun.lst
+
+cmd-sun_mod-partmap_sun.lst: partmap/sun.c $(partmap/sun.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sun_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh sun > $@ || (rm -f $@; exit 1)
+
+fs-sun_mod-partmap_sun.lst: partmap/sun.c $(partmap/sun.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sun_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh sun > $@ || (rm -f $@; exit 1)
+
+partmap-sun_mod-partmap_sun.lst: partmap/sun.c $(partmap/sun.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sun_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh sun > $@ || (rm -f $@; exit 1)
+
+
+sun_mod_CFLAGS = $(COMMON_CFLAGS)
+sun_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For acorn.mod
+acorn_mod_SOURCES = partmap/acorn.c
+CLEANFILES += acorn.mod mod-acorn.o mod-acorn.c pre-acorn.o acorn_mod-partmap_acorn.o und-acorn.lst
+ifneq ($(acorn_mod_EXPORTS),no)
+CLEANFILES += def-acorn.lst
+DEFSYMFILES += def-acorn.lst
+endif
+MOSTLYCLEANFILES += acorn_mod-partmap_acorn.d
+UNDSYMFILES += und-acorn.lst
+
+acorn.mod: pre-acorn.o mod-acorn.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(acorn_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-acorn.o mod-acorn.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-acorn.o: $(acorn_mod_DEPENDENCIES) acorn_mod-partmap_acorn.o
+       -rm -f $@
+       $(TARGET_CC) $(acorn_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ acorn_mod-partmap_acorn.o
+
+mod-acorn.o: mod-acorn.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(acorn_mod_CFLAGS) -c -o $@ $<
+
+mod-acorn.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'acorn' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(acorn_mod_EXPORTS),no)
+def-acorn.lst: pre-acorn.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 acorn/' > $@
+endif
+
+und-acorn.lst: pre-acorn.o
+       echo 'acorn' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+acorn_mod-partmap_acorn.o: partmap/acorn.c $(partmap/acorn.c_DEPENDENCIES)
+       $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(acorn_mod_CFLAGS) -MD -c -o $@ $<
+-include acorn_mod-partmap_acorn.d
+
+CLEANFILES += cmd-acorn_mod-partmap_acorn.lst fs-acorn_mod-partmap_acorn.lst partmap-acorn_mod-partmap_acorn.lst
+COMMANDFILES += cmd-acorn_mod-partmap_acorn.lst
+FSFILES += fs-acorn_mod-partmap_acorn.lst
+PARTMAPFILES += partmap-acorn_mod-partmap_acorn.lst
+
+cmd-acorn_mod-partmap_acorn.lst: partmap/acorn.c $(partmap/acorn.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(acorn_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh acorn > $@ || (rm -f $@; exit 1)
+
+fs-acorn_mod-partmap_acorn.lst: partmap/acorn.c $(partmap/acorn.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(acorn_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh acorn > $@ || (rm -f $@; exit 1)
+
+partmap-acorn_mod-partmap_acorn.lst: partmap/acorn.c $(partmap/acorn.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(acorn_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh acorn > $@ || (rm -f $@; exit 1)
+
+
+acorn_mod_CFLAGS = $(COMMON_CFLAGS)
+acorn_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For gpt.mod
+gpt_mod_SOURCES = partmap/gpt.c
+CLEANFILES += gpt.mod mod-gpt.o mod-gpt.c pre-gpt.o gpt_mod-partmap_gpt.o und-gpt.lst
+ifneq ($(gpt_mod_EXPORTS),no)
+CLEANFILES += def-gpt.lst
+DEFSYMFILES += def-gpt.lst
+endif
+MOSTLYCLEANFILES += gpt_mod-partmap_gpt.d
+UNDSYMFILES += und-gpt.lst
+
+gpt.mod: pre-gpt.o mod-gpt.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(gpt_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-gpt.o mod-gpt.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-gpt.o: $(gpt_mod_DEPENDENCIES) gpt_mod-partmap_gpt.o
+       -rm -f $@
+       $(TARGET_CC) $(gpt_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ gpt_mod-partmap_gpt.o
+
+mod-gpt.o: mod-gpt.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gpt_mod_CFLAGS) -c -o $@ $<
+
+mod-gpt.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'gpt' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(gpt_mod_EXPORTS),no)
+def-gpt.lst: pre-gpt.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 gpt/' > $@
+endif
+
+und-gpt.lst: pre-gpt.o
+       echo 'gpt' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+gpt_mod-partmap_gpt.o: partmap/gpt.c $(partmap/gpt.c_DEPENDENCIES)
+       $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(gpt_mod_CFLAGS) -MD -c -o $@ $<
+-include gpt_mod-partmap_gpt.d
+
+CLEANFILES += cmd-gpt_mod-partmap_gpt.lst fs-gpt_mod-partmap_gpt.lst partmap-gpt_mod-partmap_gpt.lst
+COMMANDFILES += cmd-gpt_mod-partmap_gpt.lst
+FSFILES += fs-gpt_mod-partmap_gpt.lst
+PARTMAPFILES += partmap-gpt_mod-partmap_gpt.lst
+
+cmd-gpt_mod-partmap_gpt.lst: partmap/gpt.c $(partmap/gpt.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gpt_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh gpt > $@ || (rm -f $@; exit 1)
+
+fs-gpt_mod-partmap_gpt.lst: partmap/gpt.c $(partmap/gpt.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gpt_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh gpt > $@ || (rm -f $@; exit 1)
+
+partmap-gpt_mod-partmap_gpt.lst: partmap/gpt.c $(partmap/gpt.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gpt_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh gpt > $@ || (rm -f $@; exit 1)
+
+
+gpt_mod_CFLAGS = $(COMMON_CFLAGS)
+gpt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# Special disk structures and generic drivers
+
+pkglib_MODULES += raid.mod raid5rec.mod raid6rec.mod mdraid.mod dm_nv.mod \
+       lvm.mod scsi.mod
+
+# For raid.mod
+raid_mod_SOURCES = disk/raid.c
+CLEANFILES += raid.mod mod-raid.o mod-raid.c pre-raid.o raid_mod-disk_raid.o und-raid.lst
+ifneq ($(raid_mod_EXPORTS),no)
+CLEANFILES += def-raid.lst
+DEFSYMFILES += def-raid.lst
+endif
+MOSTLYCLEANFILES += raid_mod-disk_raid.d
+UNDSYMFILES += und-raid.lst
+
+raid.mod: pre-raid.o mod-raid.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(raid_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-raid.o mod-raid.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-raid.o: $(raid_mod_DEPENDENCIES) raid_mod-disk_raid.o
+       -rm -f $@
+       $(TARGET_CC) $(raid_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ raid_mod-disk_raid.o
+
+mod-raid.o: mod-raid.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(raid_mod_CFLAGS) -c -o $@ $<
+
+mod-raid.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'raid' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(raid_mod_EXPORTS),no)
+def-raid.lst: pre-raid.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 raid/' > $@
+endif
+
+und-raid.lst: pre-raid.o
+       echo 'raid' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+raid_mod-disk_raid.o: disk/raid.c $(disk/raid.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(raid_mod_CFLAGS) -MD -c -o $@ $<
+-include raid_mod-disk_raid.d
+
+CLEANFILES += cmd-raid_mod-disk_raid.lst fs-raid_mod-disk_raid.lst partmap-raid_mod-disk_raid.lst
+COMMANDFILES += cmd-raid_mod-disk_raid.lst
+FSFILES += fs-raid_mod-disk_raid.lst
+PARTMAPFILES += partmap-raid_mod-disk_raid.lst
+
+cmd-raid_mod-disk_raid.lst: disk/raid.c $(disk/raid.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(raid_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh raid > $@ || (rm -f $@; exit 1)
+
+fs-raid_mod-disk_raid.lst: disk/raid.c $(disk/raid.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(raid_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh raid > $@ || (rm -f $@; exit 1)
+
+partmap-raid_mod-disk_raid.lst: disk/raid.c $(disk/raid.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(raid_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh raid > $@ || (rm -f $@; exit 1)
+
+
+raid_mod_CFLAGS = $(COMMON_CFLAGS)
+raid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For raid5rec.mod
+raid5rec_mod_SOURCES = disk/raid5_recover.c
+CLEANFILES += raid5rec.mod mod-raid5rec.o mod-raid5rec.c pre-raid5rec.o raid5rec_mod-disk_raid5_recover.o und-raid5rec.lst
+ifneq ($(raid5rec_mod_EXPORTS),no)
+CLEANFILES += def-raid5rec.lst
+DEFSYMFILES += def-raid5rec.lst
+endif
+MOSTLYCLEANFILES += raid5rec_mod-disk_raid5_recover.d
+UNDSYMFILES += und-raid5rec.lst
+
+raid5rec.mod: pre-raid5rec.o mod-raid5rec.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(raid5rec_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-raid5rec.o mod-raid5rec.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-raid5rec.o: $(raid5rec_mod_DEPENDENCIES) raid5rec_mod-disk_raid5_recover.o
+       -rm -f $@
+       $(TARGET_CC) $(raid5rec_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ raid5rec_mod-disk_raid5_recover.o
+
+mod-raid5rec.o: mod-raid5rec.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(raid5rec_mod_CFLAGS) -c -o $@ $<
+
+mod-raid5rec.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'raid5rec' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(raid5rec_mod_EXPORTS),no)
+def-raid5rec.lst: pre-raid5rec.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 raid5rec/' > $@
+endif
+
+und-raid5rec.lst: pre-raid5rec.o
+       echo 'raid5rec' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+raid5rec_mod-disk_raid5_recover.o: disk/raid5_recover.c $(disk/raid5_recover.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(raid5rec_mod_CFLAGS) -MD -c -o $@ $<
+-include raid5rec_mod-disk_raid5_recover.d
+
+CLEANFILES += cmd-raid5rec_mod-disk_raid5_recover.lst fs-raid5rec_mod-disk_raid5_recover.lst partmap-raid5rec_mod-disk_raid5_recover.lst
+COMMANDFILES += cmd-raid5rec_mod-disk_raid5_recover.lst
+FSFILES += fs-raid5rec_mod-disk_raid5_recover.lst
+PARTMAPFILES += partmap-raid5rec_mod-disk_raid5_recover.lst
+
+cmd-raid5rec_mod-disk_raid5_recover.lst: disk/raid5_recover.c $(disk/raid5_recover.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(raid5rec_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh raid5rec > $@ || (rm -f $@; exit 1)
+
+fs-raid5rec_mod-disk_raid5_recover.lst: disk/raid5_recover.c $(disk/raid5_recover.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(raid5rec_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh raid5rec > $@ || (rm -f $@; exit 1)
+
+partmap-raid5rec_mod-disk_raid5_recover.lst: disk/raid5_recover.c $(disk/raid5_recover.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(raid5rec_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh raid5rec > $@ || (rm -f $@; exit 1)
+
+
+raid5rec_mod_CFLAGS = $(COMMON_CFLAGS)
+raid5rec_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For raid6rec.mod
+raid6rec_mod_SOURCES = disk/raid6_recover.c
+CLEANFILES += raid6rec.mod mod-raid6rec.o mod-raid6rec.c pre-raid6rec.o raid6rec_mod-disk_raid6_recover.o und-raid6rec.lst
+ifneq ($(raid6rec_mod_EXPORTS),no)
+CLEANFILES += def-raid6rec.lst
+DEFSYMFILES += def-raid6rec.lst
+endif
+MOSTLYCLEANFILES += raid6rec_mod-disk_raid6_recover.d
+UNDSYMFILES += und-raid6rec.lst
+
+raid6rec.mod: pre-raid6rec.o mod-raid6rec.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(raid6rec_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-raid6rec.o mod-raid6rec.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-raid6rec.o: $(raid6rec_mod_DEPENDENCIES) raid6rec_mod-disk_raid6_recover.o
+       -rm -f $@
+       $(TARGET_CC) $(raid6rec_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ raid6rec_mod-disk_raid6_recover.o
+
+mod-raid6rec.o: mod-raid6rec.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(raid6rec_mod_CFLAGS) -c -o $@ $<
+
+mod-raid6rec.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'raid6rec' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(raid6rec_mod_EXPORTS),no)
+def-raid6rec.lst: pre-raid6rec.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 raid6rec/' > $@
+endif
+
+und-raid6rec.lst: pre-raid6rec.o
+       echo 'raid6rec' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+raid6rec_mod-disk_raid6_recover.o: disk/raid6_recover.c $(disk/raid6_recover.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(raid6rec_mod_CFLAGS) -MD -c -o $@ $<
+-include raid6rec_mod-disk_raid6_recover.d
+
+CLEANFILES += cmd-raid6rec_mod-disk_raid6_recover.lst fs-raid6rec_mod-disk_raid6_recover.lst partmap-raid6rec_mod-disk_raid6_recover.lst
+COMMANDFILES += cmd-raid6rec_mod-disk_raid6_recover.lst
+FSFILES += fs-raid6rec_mod-disk_raid6_recover.lst
+PARTMAPFILES += partmap-raid6rec_mod-disk_raid6_recover.lst
+
+cmd-raid6rec_mod-disk_raid6_recover.lst: disk/raid6_recover.c $(disk/raid6_recover.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(raid6rec_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh raid6rec > $@ || (rm -f $@; exit 1)
+
+fs-raid6rec_mod-disk_raid6_recover.lst: disk/raid6_recover.c $(disk/raid6_recover.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(raid6rec_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh raid6rec > $@ || (rm -f $@; exit 1)
+
+partmap-raid6rec_mod-disk_raid6_recover.lst: disk/raid6_recover.c $(disk/raid6_recover.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(raid6rec_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh raid6rec > $@ || (rm -f $@; exit 1)
+
+
+raid6rec_mod_CFLAGS = $(COMMON_CFLAGS)
+raid6rec_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For mdraid.mod
+mdraid_mod_SOURCES = disk/mdraid_linux.c
+CLEANFILES += mdraid.mod mod-mdraid.o mod-mdraid.c pre-mdraid.o mdraid_mod-disk_mdraid_linux.o und-mdraid.lst
+ifneq ($(mdraid_mod_EXPORTS),no)
+CLEANFILES += def-mdraid.lst
+DEFSYMFILES += def-mdraid.lst
+endif
+MOSTLYCLEANFILES += mdraid_mod-disk_mdraid_linux.d
+UNDSYMFILES += und-mdraid.lst
+
+mdraid.mod: pre-mdraid.o mod-mdraid.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(mdraid_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-mdraid.o mod-mdraid.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-mdraid.o: $(mdraid_mod_DEPENDENCIES) mdraid_mod-disk_mdraid_linux.o
+       -rm -f $@
+       $(TARGET_CC) $(mdraid_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ mdraid_mod-disk_mdraid_linux.o
+
+mod-mdraid.o: mod-mdraid.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(mdraid_mod_CFLAGS) -c -o $@ $<
+
+mod-mdraid.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'mdraid' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(mdraid_mod_EXPORTS),no)
+def-mdraid.lst: pre-mdraid.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 mdraid/' > $@
+endif
+
+und-mdraid.lst: pre-mdraid.o
+       echo 'mdraid' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+mdraid_mod-disk_mdraid_linux.o: disk/mdraid_linux.c $(disk/mdraid_linux.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(mdraid_mod_CFLAGS) -MD -c -o $@ $<
+-include mdraid_mod-disk_mdraid_linux.d
+
+CLEANFILES += cmd-mdraid_mod-disk_mdraid_linux.lst fs-mdraid_mod-disk_mdraid_linux.lst partmap-mdraid_mod-disk_mdraid_linux.lst
+COMMANDFILES += cmd-mdraid_mod-disk_mdraid_linux.lst
+FSFILES += fs-mdraid_mod-disk_mdraid_linux.lst
+PARTMAPFILES += partmap-mdraid_mod-disk_mdraid_linux.lst
+
+cmd-mdraid_mod-disk_mdraid_linux.lst: disk/mdraid_linux.c $(disk/mdraid_linux.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(mdraid_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh mdraid > $@ || (rm -f $@; exit 1)
+
+fs-mdraid_mod-disk_mdraid_linux.lst: disk/mdraid_linux.c $(disk/mdraid_linux.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(mdraid_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh mdraid > $@ || (rm -f $@; exit 1)
+
+partmap-mdraid_mod-disk_mdraid_linux.lst: disk/mdraid_linux.c $(disk/mdraid_linux.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(mdraid_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh mdraid > $@ || (rm -f $@; exit 1)
+
+
+mdraid_mod_CFLAGS = $(COMMON_CFLAGS)
+mdraid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For dm_nv.mod
+dm_nv_mod_SOURCES = disk/dmraid_nvidia.c
+CLEANFILES += dm_nv.mod mod-dm_nv.o mod-dm_nv.c pre-dm_nv.o dm_nv_mod-disk_dmraid_nvidia.o und-dm_nv.lst
+ifneq ($(dm_nv_mod_EXPORTS),no)
+CLEANFILES += def-dm_nv.lst
+DEFSYMFILES += def-dm_nv.lst
+endif
+MOSTLYCLEANFILES += dm_nv_mod-disk_dmraid_nvidia.d
+UNDSYMFILES += und-dm_nv.lst
+
+dm_nv.mod: pre-dm_nv.o mod-dm_nv.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(dm_nv_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-dm_nv.o mod-dm_nv.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-dm_nv.o: $(dm_nv_mod_DEPENDENCIES) dm_nv_mod-disk_dmraid_nvidia.o
+       -rm -f $@
+       $(TARGET_CC) $(dm_nv_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ dm_nv_mod-disk_dmraid_nvidia.o
+
+mod-dm_nv.o: mod-dm_nv.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(dm_nv_mod_CFLAGS) -c -o $@ $<
+
+mod-dm_nv.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'dm_nv' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(dm_nv_mod_EXPORTS),no)
+def-dm_nv.lst: pre-dm_nv.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 dm_nv/' > $@
+endif
+
+und-dm_nv.lst: pre-dm_nv.o
+       echo 'dm_nv' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+dm_nv_mod-disk_dmraid_nvidia.o: disk/dmraid_nvidia.c $(disk/dmraid_nvidia.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(dm_nv_mod_CFLAGS) -MD -c -o $@ $<
+-include dm_nv_mod-disk_dmraid_nvidia.d
+
+CLEANFILES += cmd-dm_nv_mod-disk_dmraid_nvidia.lst fs-dm_nv_mod-disk_dmraid_nvidia.lst partmap-dm_nv_mod-disk_dmraid_nvidia.lst
+COMMANDFILES += cmd-dm_nv_mod-disk_dmraid_nvidia.lst
+FSFILES += fs-dm_nv_mod-disk_dmraid_nvidia.lst
+PARTMAPFILES += partmap-dm_nv_mod-disk_dmraid_nvidia.lst
+
+cmd-dm_nv_mod-disk_dmraid_nvidia.lst: disk/dmraid_nvidia.c $(disk/dmraid_nvidia.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(dm_nv_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh dm_nv > $@ || (rm -f $@; exit 1)
+
+fs-dm_nv_mod-disk_dmraid_nvidia.lst: disk/dmraid_nvidia.c $(disk/dmraid_nvidia.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(dm_nv_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh dm_nv > $@ || (rm -f $@; exit 1)
+
+partmap-dm_nv_mod-disk_dmraid_nvidia.lst: disk/dmraid_nvidia.c $(disk/dmraid_nvidia.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(dm_nv_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh dm_nv > $@ || (rm -f $@; exit 1)
+
+
+dm_nv_mod_CFLAGS = $(COMMON_CFLAGS)
+dm_nv_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lvm.mod
+lvm_mod_SOURCES = disk/lvm.c
+CLEANFILES += lvm.mod mod-lvm.o mod-lvm.c pre-lvm.o lvm_mod-disk_lvm.o und-lvm.lst
+ifneq ($(lvm_mod_EXPORTS),no)
+CLEANFILES += def-lvm.lst
+DEFSYMFILES += def-lvm.lst
+endif
+MOSTLYCLEANFILES += lvm_mod-disk_lvm.d
+UNDSYMFILES += und-lvm.lst
+
+lvm.mod: pre-lvm.o mod-lvm.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(lvm_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-lvm.o mod-lvm.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-lvm.o: $(lvm_mod_DEPENDENCIES) lvm_mod-disk_lvm.o
+       -rm -f $@
+       $(TARGET_CC) $(lvm_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ lvm_mod-disk_lvm.o
+
+mod-lvm.o: mod-lvm.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lvm_mod_CFLAGS) -c -o $@ $<
+
+mod-lvm.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'lvm' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(lvm_mod_EXPORTS),no)
+def-lvm.lst: pre-lvm.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 lvm/' > $@
+endif
+
+und-lvm.lst: pre-lvm.o
+       echo 'lvm' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+lvm_mod-disk_lvm.o: disk/lvm.c $(disk/lvm.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(lvm_mod_CFLAGS) -MD -c -o $@ $<
+-include lvm_mod-disk_lvm.d
+
+CLEANFILES += cmd-lvm_mod-disk_lvm.lst fs-lvm_mod-disk_lvm.lst partmap-lvm_mod-disk_lvm.lst
+COMMANDFILES += cmd-lvm_mod-disk_lvm.lst
+FSFILES += fs-lvm_mod-disk_lvm.lst
+PARTMAPFILES += partmap-lvm_mod-disk_lvm.lst
+
+cmd-lvm_mod-disk_lvm.lst: disk/lvm.c $(disk/lvm.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lvm_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh lvm > $@ || (rm -f $@; exit 1)
+
+fs-lvm_mod-disk_lvm.lst: disk/lvm.c $(disk/lvm.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lvm_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh lvm > $@ || (rm -f $@; exit 1)
+
+partmap-lvm_mod-disk_lvm.lst: disk/lvm.c $(disk/lvm.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lvm_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh lvm > $@ || (rm -f $@; exit 1)
+
+
+lvm_mod_CFLAGS = $(COMMON_CFLAGS)
+lvm_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For scsi.mod
+scsi_mod_SOURCES = disk/scsi.c
+CLEANFILES += scsi.mod mod-scsi.o mod-scsi.c pre-scsi.o scsi_mod-disk_scsi.o und-scsi.lst
+ifneq ($(scsi_mod_EXPORTS),no)
+CLEANFILES += def-scsi.lst
+DEFSYMFILES += def-scsi.lst
+endif
+MOSTLYCLEANFILES += scsi_mod-disk_scsi.d
+UNDSYMFILES += und-scsi.lst
+
+scsi.mod: pre-scsi.o mod-scsi.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(scsi_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-scsi.o mod-scsi.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-scsi.o: $(scsi_mod_DEPENDENCIES) scsi_mod-disk_scsi.o
+       -rm -f $@
+       $(TARGET_CC) $(scsi_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ scsi_mod-disk_scsi.o
+
+mod-scsi.o: mod-scsi.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(scsi_mod_CFLAGS) -c -o $@ $<
+
+mod-scsi.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'scsi' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(scsi_mod_EXPORTS),no)
+def-scsi.lst: pre-scsi.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 scsi/' > $@
+endif
+
+und-scsi.lst: pre-scsi.o
+       echo 'scsi' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+scsi_mod-disk_scsi.o: disk/scsi.c $(disk/scsi.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(scsi_mod_CFLAGS) -MD -c -o $@ $<
+-include scsi_mod-disk_scsi.d
+
+CLEANFILES += cmd-scsi_mod-disk_scsi.lst fs-scsi_mod-disk_scsi.lst partmap-scsi_mod-disk_scsi.lst
+COMMANDFILES += cmd-scsi_mod-disk_scsi.lst
+FSFILES += fs-scsi_mod-disk_scsi.lst
+PARTMAPFILES += partmap-scsi_mod-disk_scsi.lst
+
+cmd-scsi_mod-disk_scsi.lst: disk/scsi.c $(disk/scsi.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(scsi_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh scsi > $@ || (rm -f $@; exit 1)
+
+fs-scsi_mod-disk_scsi.lst: disk/scsi.c $(disk/scsi.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(scsi_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh scsi > $@ || (rm -f $@; exit 1)
+
+partmap-scsi_mod-disk_scsi.lst: disk/scsi.c $(disk/scsi.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(scsi_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh scsi > $@ || (rm -f $@; exit 1)
+
+
+scsi_mod_CFLAGS = $(COMMON_CFLAGS)
+scsi_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# Commands.
+pkglib_MODULES += hello.mod boot.mod terminal.mod ls.mod       \
+       cmp.mod cat.mod help.mod search.mod                                     \
+       loopback.mod fs_uuid.mod configfile.mod echo.mod        \
+       terminfo.mod test.mod blocklist.mod hexdump.mod         \
+       read.mod sleep.mod loadenv.mod crc.mod
+
+# For hello.mod.
+hello_mod_SOURCES = hello/hello.c
+CLEANFILES += hello.mod mod-hello.o mod-hello.c pre-hello.o hello_mod-hello_hello.o und-hello.lst
+ifneq ($(hello_mod_EXPORTS),no)
+CLEANFILES += def-hello.lst
+DEFSYMFILES += def-hello.lst
+endif
+MOSTLYCLEANFILES += hello_mod-hello_hello.d
+UNDSYMFILES += und-hello.lst
+
+hello.mod: pre-hello.o mod-hello.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(hello_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-hello.o mod-hello.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-hello.o: $(hello_mod_DEPENDENCIES) hello_mod-hello_hello.o
+       -rm -f $@
+       $(TARGET_CC) $(hello_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ hello_mod-hello_hello.o
+
+mod-hello.o: mod-hello.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hello_mod_CFLAGS) -c -o $@ $<
+
+mod-hello.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'hello' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(hello_mod_EXPORTS),no)
+def-hello.lst: pre-hello.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 hello/' > $@
+endif
+
+und-hello.lst: pre-hello.o
+       echo 'hello' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+hello_mod-hello_hello.o: hello/hello.c $(hello/hello.c_DEPENDENCIES)
+       $(TARGET_CC) -Ihello -I$(srcdir)/hello $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(hello_mod_CFLAGS) -MD -c -o $@ $<
+-include hello_mod-hello_hello.d
+
+CLEANFILES += cmd-hello_mod-hello_hello.lst fs-hello_mod-hello_hello.lst partmap-hello_mod-hello_hello.lst
+COMMANDFILES += cmd-hello_mod-hello_hello.lst
+FSFILES += fs-hello_mod-hello_hello.lst
+PARTMAPFILES += partmap-hello_mod-hello_hello.lst
+
+cmd-hello_mod-hello_hello.lst: hello/hello.c $(hello/hello.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ihello -I$(srcdir)/hello $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hello_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh hello > $@ || (rm -f $@; exit 1)
+
+fs-hello_mod-hello_hello.lst: hello/hello.c $(hello/hello.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ihello -I$(srcdir)/hello $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hello_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh hello > $@ || (rm -f $@; exit 1)
+
+partmap-hello_mod-hello_hello.lst: hello/hello.c $(hello/hello.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ihello -I$(srcdir)/hello $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hello_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh hello > $@ || (rm -f $@; exit 1)
+
+
+hello_mod_CFLAGS = $(COMMON_CFLAGS)
+hello_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For boot.mod.
+boot_mod_SOURCES = commands/boot.c
+CLEANFILES += boot.mod mod-boot.o mod-boot.c pre-boot.o boot_mod-commands_boot.o und-boot.lst
+ifneq ($(boot_mod_EXPORTS),no)
+CLEANFILES += def-boot.lst
+DEFSYMFILES += def-boot.lst
+endif
+MOSTLYCLEANFILES += boot_mod-commands_boot.d
+UNDSYMFILES += und-boot.lst
+
+boot.mod: pre-boot.o mod-boot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(boot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-boot.o mod-boot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-boot.o: $(boot_mod_DEPENDENCIES) boot_mod-commands_boot.o
+       -rm -f $@
+       $(TARGET_CC) $(boot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ boot_mod-commands_boot.o
+
+mod-boot.o: mod-boot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(boot_mod_CFLAGS) -c -o $@ $<
+
+mod-boot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'boot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(boot_mod_EXPORTS),no)
+def-boot.lst: pre-boot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 boot/' > $@
+endif
+
+und-boot.lst: pre-boot.o
+       echo 'boot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+boot_mod-commands_boot.o: commands/boot.c $(commands/boot.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(boot_mod_CFLAGS) -MD -c -o $@ $<
+-include boot_mod-commands_boot.d
+
+CLEANFILES += cmd-boot_mod-commands_boot.lst fs-boot_mod-commands_boot.lst partmap-boot_mod-commands_boot.lst
+COMMANDFILES += cmd-boot_mod-commands_boot.lst
+FSFILES += fs-boot_mod-commands_boot.lst
+PARTMAPFILES += partmap-boot_mod-commands_boot.lst
+
+cmd-boot_mod-commands_boot.lst: commands/boot.c $(commands/boot.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(boot_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh boot > $@ || (rm -f $@; exit 1)
+
+fs-boot_mod-commands_boot.lst: commands/boot.c $(commands/boot.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(boot_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh boot > $@ || (rm -f $@; exit 1)
+
+partmap-boot_mod-commands_boot.lst: commands/boot.c $(commands/boot.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(boot_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh boot > $@ || (rm -f $@; exit 1)
+
+
+boot_mod_CFLAGS = $(COMMON_CFLAGS)
+boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For terminal.mod.
+terminal_mod_SOURCES = commands/terminal.c
+CLEANFILES += terminal.mod mod-terminal.o mod-terminal.c pre-terminal.o terminal_mod-commands_terminal.o und-terminal.lst
+ifneq ($(terminal_mod_EXPORTS),no)
+CLEANFILES += def-terminal.lst
+DEFSYMFILES += def-terminal.lst
+endif
+MOSTLYCLEANFILES += terminal_mod-commands_terminal.d
+UNDSYMFILES += und-terminal.lst
+
+terminal.mod: pre-terminal.o mod-terminal.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(terminal_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-terminal.o mod-terminal.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-terminal.o: $(terminal_mod_DEPENDENCIES) terminal_mod-commands_terminal.o
+       -rm -f $@
+       $(TARGET_CC) $(terminal_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ terminal_mod-commands_terminal.o
+
+mod-terminal.o: mod-terminal.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(terminal_mod_CFLAGS) -c -o $@ $<
+
+mod-terminal.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'terminal' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(terminal_mod_EXPORTS),no)
+def-terminal.lst: pre-terminal.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 terminal/' > $@
+endif
+
+und-terminal.lst: pre-terminal.o
+       echo 'terminal' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+terminal_mod-commands_terminal.o: commands/terminal.c $(commands/terminal.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(terminal_mod_CFLAGS) -MD -c -o $@ $<
+-include terminal_mod-commands_terminal.d
+
+CLEANFILES += cmd-terminal_mod-commands_terminal.lst fs-terminal_mod-commands_terminal.lst partmap-terminal_mod-commands_terminal.lst
+COMMANDFILES += cmd-terminal_mod-commands_terminal.lst
+FSFILES += fs-terminal_mod-commands_terminal.lst
+PARTMAPFILES += partmap-terminal_mod-commands_terminal.lst
+
+cmd-terminal_mod-commands_terminal.lst: commands/terminal.c $(commands/terminal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(terminal_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh terminal > $@ || (rm -f $@; exit 1)
+
+fs-terminal_mod-commands_terminal.lst: commands/terminal.c $(commands/terminal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(terminal_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh terminal > $@ || (rm -f $@; exit 1)
+
+partmap-terminal_mod-commands_terminal.lst: commands/terminal.c $(commands/terminal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(terminal_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh terminal > $@ || (rm -f $@; exit 1)
+
+
+terminal_mod_CFLAGS = $(COMMON_CFLAGS)
+terminal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ls.mod.
+ls_mod_SOURCES = commands/ls.c
+CLEANFILES += ls.mod mod-ls.o mod-ls.c pre-ls.o ls_mod-commands_ls.o und-ls.lst
+ifneq ($(ls_mod_EXPORTS),no)
+CLEANFILES += def-ls.lst
+DEFSYMFILES += def-ls.lst
+endif
+MOSTLYCLEANFILES += ls_mod-commands_ls.d
+UNDSYMFILES += und-ls.lst
+
+ls.mod: pre-ls.o mod-ls.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(ls_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-ls.o mod-ls.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-ls.o: $(ls_mod_DEPENDENCIES) ls_mod-commands_ls.o
+       -rm -f $@
+       $(TARGET_CC) $(ls_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ ls_mod-commands_ls.o
+
+mod-ls.o: mod-ls.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ls_mod_CFLAGS) -c -o $@ $<
+
+mod-ls.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'ls' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(ls_mod_EXPORTS),no)
+def-ls.lst: pre-ls.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 ls/' > $@
+endif
+
+und-ls.lst: pre-ls.o
+       echo 'ls' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+ls_mod-commands_ls.o: commands/ls.c $(commands/ls.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(ls_mod_CFLAGS) -MD -c -o $@ $<
+-include ls_mod-commands_ls.d
+
+CLEANFILES += cmd-ls_mod-commands_ls.lst fs-ls_mod-commands_ls.lst partmap-ls_mod-commands_ls.lst
+COMMANDFILES += cmd-ls_mod-commands_ls.lst
+FSFILES += fs-ls_mod-commands_ls.lst
+PARTMAPFILES += partmap-ls_mod-commands_ls.lst
+
+cmd-ls_mod-commands_ls.lst: commands/ls.c $(commands/ls.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ls_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh ls > $@ || (rm -f $@; exit 1)
+
+fs-ls_mod-commands_ls.lst: commands/ls.c $(commands/ls.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ls_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh ls > $@ || (rm -f $@; exit 1)
+
+partmap-ls_mod-commands_ls.lst: commands/ls.c $(commands/ls.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ls_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh ls > $@ || (rm -f $@; exit 1)
+
+
+ls_mod_CFLAGS = $(COMMON_CFLAGS)
+ls_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For cmp.mod.
+cmp_mod_SOURCES = commands/cmp.c
+CLEANFILES += cmp.mod mod-cmp.o mod-cmp.c pre-cmp.o cmp_mod-commands_cmp.o und-cmp.lst
+ifneq ($(cmp_mod_EXPORTS),no)
+CLEANFILES += def-cmp.lst
+DEFSYMFILES += def-cmp.lst
+endif
+MOSTLYCLEANFILES += cmp_mod-commands_cmp.d
+UNDSYMFILES += und-cmp.lst
+
+cmp.mod: pre-cmp.o mod-cmp.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(cmp_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-cmp.o mod-cmp.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-cmp.o: $(cmp_mod_DEPENDENCIES) cmp_mod-commands_cmp.o
+       -rm -f $@
+       $(TARGET_CC) $(cmp_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ cmp_mod-commands_cmp.o
+
+mod-cmp.o: mod-cmp.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cmp_mod_CFLAGS) -c -o $@ $<
+
+mod-cmp.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'cmp' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(cmp_mod_EXPORTS),no)
+def-cmp.lst: pre-cmp.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 cmp/' > $@
+endif
+
+und-cmp.lst: pre-cmp.o
+       echo 'cmp' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+cmp_mod-commands_cmp.o: commands/cmp.c $(commands/cmp.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(cmp_mod_CFLAGS) -MD -c -o $@ $<
+-include cmp_mod-commands_cmp.d
+
+CLEANFILES += cmd-cmp_mod-commands_cmp.lst fs-cmp_mod-commands_cmp.lst partmap-cmp_mod-commands_cmp.lst
+COMMANDFILES += cmd-cmp_mod-commands_cmp.lst
+FSFILES += fs-cmp_mod-commands_cmp.lst
+PARTMAPFILES += partmap-cmp_mod-commands_cmp.lst
+
+cmd-cmp_mod-commands_cmp.lst: commands/cmp.c $(commands/cmp.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cmp_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh cmp > $@ || (rm -f $@; exit 1)
+
+fs-cmp_mod-commands_cmp.lst: commands/cmp.c $(commands/cmp.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cmp_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh cmp > $@ || (rm -f $@; exit 1)
+
+partmap-cmp_mod-commands_cmp.lst: commands/cmp.c $(commands/cmp.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cmp_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh cmp > $@ || (rm -f $@; exit 1)
+
+
+cmp_mod_CFLAGS = $(COMMON_CFLAGS)
+cmp_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For cat.mod.
+cat_mod_SOURCES = commands/cat.c
+CLEANFILES += cat.mod mod-cat.o mod-cat.c pre-cat.o cat_mod-commands_cat.o und-cat.lst
+ifneq ($(cat_mod_EXPORTS),no)
+CLEANFILES += def-cat.lst
+DEFSYMFILES += def-cat.lst
+endif
+MOSTLYCLEANFILES += cat_mod-commands_cat.d
+UNDSYMFILES += und-cat.lst
+
+cat.mod: pre-cat.o mod-cat.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(cat_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-cat.o mod-cat.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-cat.o: $(cat_mod_DEPENDENCIES) cat_mod-commands_cat.o
+       -rm -f $@
+       $(TARGET_CC) $(cat_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ cat_mod-commands_cat.o
+
+mod-cat.o: mod-cat.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cat_mod_CFLAGS) -c -o $@ $<
+
+mod-cat.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'cat' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(cat_mod_EXPORTS),no)
+def-cat.lst: pre-cat.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 cat/' > $@
+endif
+
+und-cat.lst: pre-cat.o
+       echo 'cat' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+cat_mod-commands_cat.o: commands/cat.c $(commands/cat.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(cat_mod_CFLAGS) -MD -c -o $@ $<
+-include cat_mod-commands_cat.d
+
+CLEANFILES += cmd-cat_mod-commands_cat.lst fs-cat_mod-commands_cat.lst partmap-cat_mod-commands_cat.lst
+COMMANDFILES += cmd-cat_mod-commands_cat.lst
+FSFILES += fs-cat_mod-commands_cat.lst
+PARTMAPFILES += partmap-cat_mod-commands_cat.lst
+
+cmd-cat_mod-commands_cat.lst: commands/cat.c $(commands/cat.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cat_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh cat > $@ || (rm -f $@; exit 1)
+
+fs-cat_mod-commands_cat.lst: commands/cat.c $(commands/cat.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cat_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh cat > $@ || (rm -f $@; exit 1)
+
+partmap-cat_mod-commands_cat.lst: commands/cat.c $(commands/cat.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cat_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh cat > $@ || (rm -f $@; exit 1)
+
+
+cat_mod_CFLAGS = $(COMMON_CFLAGS)
+cat_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For echo.mod
+echo_mod_SOURCES = commands/echo.c
+CLEANFILES += echo.mod mod-echo.o mod-echo.c pre-echo.o echo_mod-commands_echo.o und-echo.lst
+ifneq ($(echo_mod_EXPORTS),no)
+CLEANFILES += def-echo.lst
+DEFSYMFILES += def-echo.lst
+endif
+MOSTLYCLEANFILES += echo_mod-commands_echo.d
+UNDSYMFILES += und-echo.lst
+
+echo.mod: pre-echo.o mod-echo.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(echo_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-echo.o mod-echo.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-echo.o: $(echo_mod_DEPENDENCIES) echo_mod-commands_echo.o
+       -rm -f $@
+       $(TARGET_CC) $(echo_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ echo_mod-commands_echo.o
+
+mod-echo.o: mod-echo.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(echo_mod_CFLAGS) -c -o $@ $<
+
+mod-echo.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'echo' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(echo_mod_EXPORTS),no)
+def-echo.lst: pre-echo.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 echo/' > $@
+endif
+
+und-echo.lst: pre-echo.o
+       echo 'echo' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+echo_mod-commands_echo.o: commands/echo.c $(commands/echo.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(echo_mod_CFLAGS) -MD -c -o $@ $<
+-include echo_mod-commands_echo.d
+
+CLEANFILES += cmd-echo_mod-commands_echo.lst fs-echo_mod-commands_echo.lst partmap-echo_mod-commands_echo.lst
+COMMANDFILES += cmd-echo_mod-commands_echo.lst
+FSFILES += fs-echo_mod-commands_echo.lst
+PARTMAPFILES += partmap-echo_mod-commands_echo.lst
+
+cmd-echo_mod-commands_echo.lst: commands/echo.c $(commands/echo.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(echo_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh echo > $@ || (rm -f $@; exit 1)
+
+fs-echo_mod-commands_echo.lst: commands/echo.c $(commands/echo.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(echo_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh echo > $@ || (rm -f $@; exit 1)
+
+partmap-echo_mod-commands_echo.lst: commands/echo.c $(commands/echo.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(echo_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh echo > $@ || (rm -f $@; exit 1)
+
+
+echo_mod_CFLAGS = $(COMMON_CFLAGS)
+echo_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For help.mod.
+help_mod_SOURCES = commands/help.c
+CLEANFILES += help.mod mod-help.o mod-help.c pre-help.o help_mod-commands_help.o und-help.lst
+ifneq ($(help_mod_EXPORTS),no)
+CLEANFILES += def-help.lst
+DEFSYMFILES += def-help.lst
+endif
+MOSTLYCLEANFILES += help_mod-commands_help.d
+UNDSYMFILES += und-help.lst
+
+help.mod: pre-help.o mod-help.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(help_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-help.o mod-help.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-help.o: $(help_mod_DEPENDENCIES) help_mod-commands_help.o
+       -rm -f $@
+       $(TARGET_CC) $(help_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ help_mod-commands_help.o
+
+mod-help.o: mod-help.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(help_mod_CFLAGS) -c -o $@ $<
+
+mod-help.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'help' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(help_mod_EXPORTS),no)
+def-help.lst: pre-help.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 help/' > $@
+endif
+
+und-help.lst: pre-help.o
+       echo 'help' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+help_mod-commands_help.o: commands/help.c $(commands/help.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(help_mod_CFLAGS) -MD -c -o $@ $<
+-include help_mod-commands_help.d
+
+CLEANFILES += cmd-help_mod-commands_help.lst fs-help_mod-commands_help.lst partmap-help_mod-commands_help.lst
+COMMANDFILES += cmd-help_mod-commands_help.lst
+FSFILES += fs-help_mod-commands_help.lst
+PARTMAPFILES += partmap-help_mod-commands_help.lst
+
+cmd-help_mod-commands_help.lst: commands/help.c $(commands/help.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(help_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh help > $@ || (rm -f $@; exit 1)
+
+fs-help_mod-commands_help.lst: commands/help.c $(commands/help.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(help_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh help > $@ || (rm -f $@; exit 1)
+
+partmap-help_mod-commands_help.lst: commands/help.c $(commands/help.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(help_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh help > $@ || (rm -f $@; exit 1)
+
+
+help_mod_CFLAGS = $(COMMON_CFLAGS)
+help_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For search.mod.
+search_mod_SOURCES = commands/search.c
+CLEANFILES += search.mod mod-search.o mod-search.c pre-search.o search_mod-commands_search.o und-search.lst
+ifneq ($(search_mod_EXPORTS),no)
+CLEANFILES += def-search.lst
+DEFSYMFILES += def-search.lst
+endif
+MOSTLYCLEANFILES += search_mod-commands_search.d
+UNDSYMFILES += und-search.lst
+
+search.mod: pre-search.o mod-search.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(search_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-search.o mod-search.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-search.o: $(search_mod_DEPENDENCIES) search_mod-commands_search.o
+       -rm -f $@
+       $(TARGET_CC) $(search_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ search_mod-commands_search.o
+
+mod-search.o: mod-search.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(search_mod_CFLAGS) -c -o $@ $<
+
+mod-search.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'search' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(search_mod_EXPORTS),no)
+def-search.lst: pre-search.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 search/' > $@
+endif
+
+und-search.lst: pre-search.o
+       echo 'search' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+search_mod-commands_search.o: commands/search.c $(commands/search.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(search_mod_CFLAGS) -MD -c -o $@ $<
+-include search_mod-commands_search.d
+
+CLEANFILES += cmd-search_mod-commands_search.lst fs-search_mod-commands_search.lst partmap-search_mod-commands_search.lst
+COMMANDFILES += cmd-search_mod-commands_search.lst
+FSFILES += fs-search_mod-commands_search.lst
+PARTMAPFILES += partmap-search_mod-commands_search.lst
+
+cmd-search_mod-commands_search.lst: commands/search.c $(commands/search.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(search_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh search > $@ || (rm -f $@; exit 1)
+
+fs-search_mod-commands_search.lst: commands/search.c $(commands/search.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(search_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh search > $@ || (rm -f $@; exit 1)
+
+partmap-search_mod-commands_search.lst: commands/search.c $(commands/search.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(search_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh search > $@ || (rm -f $@; exit 1)
+
+
+search_mod_CFLAGS = $(COMMON_CFLAGS)
+search_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For test.mod.
+test_mod_SOURCES = commands/test.c
+CLEANFILES += test.mod mod-test.o mod-test.c pre-test.o test_mod-commands_test.o und-test.lst
+ifneq ($(test_mod_EXPORTS),no)
+CLEANFILES += def-test.lst
+DEFSYMFILES += def-test.lst
+endif
+MOSTLYCLEANFILES += test_mod-commands_test.d
+UNDSYMFILES += und-test.lst
+
+test.mod: pre-test.o mod-test.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(test_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-test.o mod-test.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-test.o: $(test_mod_DEPENDENCIES) test_mod-commands_test.o
+       -rm -f $@
+       $(TARGET_CC) $(test_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ test_mod-commands_test.o
+
+mod-test.o: mod-test.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(test_mod_CFLAGS) -c -o $@ $<
+
+mod-test.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'test' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(test_mod_EXPORTS),no)
+def-test.lst: pre-test.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 test/' > $@
+endif
+
+und-test.lst: pre-test.o
+       echo 'test' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+test_mod-commands_test.o: commands/test.c $(commands/test.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(test_mod_CFLAGS) -MD -c -o $@ $<
+-include test_mod-commands_test.d
+
+CLEANFILES += cmd-test_mod-commands_test.lst fs-test_mod-commands_test.lst partmap-test_mod-commands_test.lst
+COMMANDFILES += cmd-test_mod-commands_test.lst
+FSFILES += fs-test_mod-commands_test.lst
+PARTMAPFILES += partmap-test_mod-commands_test.lst
+
+cmd-test_mod-commands_test.lst: commands/test.c $(commands/test.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(test_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh test > $@ || (rm -f $@; exit 1)
+
+fs-test_mod-commands_test.lst: commands/test.c $(commands/test.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(test_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh test > $@ || (rm -f $@; exit 1)
+
+partmap-test_mod-commands_test.lst: commands/test.c $(commands/test.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(test_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh test > $@ || (rm -f $@; exit 1)
+
+
+test_mod_CFLAGS = $(COMMON_CFLAGS)
+test_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For loopback.mod
+loopback_mod_SOURCES = disk/loopback.c
+CLEANFILES += loopback.mod mod-loopback.o mod-loopback.c pre-loopback.o loopback_mod-disk_loopback.o und-loopback.lst
+ifneq ($(loopback_mod_EXPORTS),no)
+CLEANFILES += def-loopback.lst
+DEFSYMFILES += def-loopback.lst
+endif
+MOSTLYCLEANFILES += loopback_mod-disk_loopback.d
+UNDSYMFILES += und-loopback.lst
+
+loopback.mod: pre-loopback.o mod-loopback.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(loopback_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-loopback.o mod-loopback.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-loopback.o: $(loopback_mod_DEPENDENCIES) loopback_mod-disk_loopback.o
+       -rm -f $@
+       $(TARGET_CC) $(loopback_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ loopback_mod-disk_loopback.o
+
+mod-loopback.o: mod-loopback.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loopback_mod_CFLAGS) -c -o $@ $<
+
+mod-loopback.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'loopback' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(loopback_mod_EXPORTS),no)
+def-loopback.lst: pre-loopback.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 loopback/' > $@
+endif
+
+und-loopback.lst: pre-loopback.o
+       echo 'loopback' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+loopback_mod-disk_loopback.o: disk/loopback.c $(disk/loopback.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(loopback_mod_CFLAGS) -MD -c -o $@ $<
+-include loopback_mod-disk_loopback.d
+
+CLEANFILES += cmd-loopback_mod-disk_loopback.lst fs-loopback_mod-disk_loopback.lst partmap-loopback_mod-disk_loopback.lst
+COMMANDFILES += cmd-loopback_mod-disk_loopback.lst
+FSFILES += fs-loopback_mod-disk_loopback.lst
+PARTMAPFILES += partmap-loopback_mod-disk_loopback.lst
+
+cmd-loopback_mod-disk_loopback.lst: disk/loopback.c $(disk/loopback.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loopback_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh loopback > $@ || (rm -f $@; exit 1)
+
+fs-loopback_mod-disk_loopback.lst: disk/loopback.c $(disk/loopback.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loopback_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh loopback > $@ || (rm -f $@; exit 1)
+
+partmap-loopback_mod-disk_loopback.lst: disk/loopback.c $(disk/loopback.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loopback_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh loopback > $@ || (rm -f $@; exit 1)
+
+
+loopback_mod_CFLAGS = $(COMMON_CFLAGS)
+loopback_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For fs_uuid.mod
+fs_uuid_mod_SOURCES = disk/fs_uuid.c
+CLEANFILES += fs_uuid.mod mod-fs_uuid.o mod-fs_uuid.c pre-fs_uuid.o fs_uuid_mod-disk_fs_uuid.o und-fs_uuid.lst
+ifneq ($(fs_uuid_mod_EXPORTS),no)
+CLEANFILES += def-fs_uuid.lst
+DEFSYMFILES += def-fs_uuid.lst
+endif
+MOSTLYCLEANFILES += fs_uuid_mod-disk_fs_uuid.d
+UNDSYMFILES += und-fs_uuid.lst
+
+fs_uuid.mod: pre-fs_uuid.o mod-fs_uuid.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(fs_uuid_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-fs_uuid.o mod-fs_uuid.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-fs_uuid.o: $(fs_uuid_mod_DEPENDENCIES) fs_uuid_mod-disk_fs_uuid.o
+       -rm -f $@
+       $(TARGET_CC) $(fs_uuid_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ fs_uuid_mod-disk_fs_uuid.o
+
+mod-fs_uuid.o: mod-fs_uuid.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fs_uuid_mod_CFLAGS) -c -o $@ $<
+
+mod-fs_uuid.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'fs_uuid' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(fs_uuid_mod_EXPORTS),no)
+def-fs_uuid.lst: pre-fs_uuid.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 fs_uuid/' > $@
+endif
+
+und-fs_uuid.lst: pre-fs_uuid.o
+       echo 'fs_uuid' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+fs_uuid_mod-disk_fs_uuid.o: disk/fs_uuid.c $(disk/fs_uuid.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(fs_uuid_mod_CFLAGS) -MD -c -o $@ $<
+-include fs_uuid_mod-disk_fs_uuid.d
+
+CLEANFILES += cmd-fs_uuid_mod-disk_fs_uuid.lst fs-fs_uuid_mod-disk_fs_uuid.lst partmap-fs_uuid_mod-disk_fs_uuid.lst
+COMMANDFILES += cmd-fs_uuid_mod-disk_fs_uuid.lst
+FSFILES += fs-fs_uuid_mod-disk_fs_uuid.lst
+PARTMAPFILES += partmap-fs_uuid_mod-disk_fs_uuid.lst
+
+cmd-fs_uuid_mod-disk_fs_uuid.lst: disk/fs_uuid.c $(disk/fs_uuid.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fs_uuid_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh fs_uuid > $@ || (rm -f $@; exit 1)
+
+fs-fs_uuid_mod-disk_fs_uuid.lst: disk/fs_uuid.c $(disk/fs_uuid.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fs_uuid_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh fs_uuid > $@ || (rm -f $@; exit 1)
+
+partmap-fs_uuid_mod-disk_fs_uuid.lst: disk/fs_uuid.c $(disk/fs_uuid.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fs_uuid_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh fs_uuid > $@ || (rm -f $@; exit 1)
+
+
+fs_uuid_mod_CFLAGS = $(COMMON_CFLAGS)
+fs_uuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For configfile.mod
+configfile_mod_SOURCES = commands/configfile.c
+CLEANFILES += configfile.mod mod-configfile.o mod-configfile.c pre-configfile.o configfile_mod-commands_configfile.o und-configfile.lst
+ifneq ($(configfile_mod_EXPORTS),no)
+CLEANFILES += def-configfile.lst
+DEFSYMFILES += def-configfile.lst
+endif
+MOSTLYCLEANFILES += configfile_mod-commands_configfile.d
+UNDSYMFILES += und-configfile.lst
+
+configfile.mod: pre-configfile.o mod-configfile.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(configfile_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-configfile.o mod-configfile.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-configfile.o: $(configfile_mod_DEPENDENCIES) configfile_mod-commands_configfile.o
+       -rm -f $@
+       $(TARGET_CC) $(configfile_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ configfile_mod-commands_configfile.o
+
+mod-configfile.o: mod-configfile.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(configfile_mod_CFLAGS) -c -o $@ $<
+
+mod-configfile.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'configfile' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(configfile_mod_EXPORTS),no)
+def-configfile.lst: pre-configfile.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 configfile/' > $@
+endif
+
+und-configfile.lst: pre-configfile.o
+       echo 'configfile' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+configfile_mod-commands_configfile.o: commands/configfile.c $(commands/configfile.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(configfile_mod_CFLAGS) -MD -c -o $@ $<
+-include configfile_mod-commands_configfile.d
+
+CLEANFILES += cmd-configfile_mod-commands_configfile.lst fs-configfile_mod-commands_configfile.lst partmap-configfile_mod-commands_configfile.lst
+COMMANDFILES += cmd-configfile_mod-commands_configfile.lst
+FSFILES += fs-configfile_mod-commands_configfile.lst
+PARTMAPFILES += partmap-configfile_mod-commands_configfile.lst
+
+cmd-configfile_mod-commands_configfile.lst: commands/configfile.c $(commands/configfile.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(configfile_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh configfile > $@ || (rm -f $@; exit 1)
+
+fs-configfile_mod-commands_configfile.lst: commands/configfile.c $(commands/configfile.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(configfile_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh configfile > $@ || (rm -f $@; exit 1)
+
+partmap-configfile_mod-commands_configfile.lst: commands/configfile.c $(commands/configfile.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(configfile_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh configfile > $@ || (rm -f $@; exit 1)
+
+
+configfile_mod_CFLAGS = $(COMMON_CFLAGS)
+configfile_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For terminfo.mod.
+terminfo_mod_SOURCES = term/terminfo.c term/tparm.c
+CLEANFILES += terminfo.mod mod-terminfo.o mod-terminfo.c pre-terminfo.o terminfo_mod-term_terminfo.o terminfo_mod-term_tparm.o und-terminfo.lst
+ifneq ($(terminfo_mod_EXPORTS),no)
+CLEANFILES += def-terminfo.lst
+DEFSYMFILES += def-terminfo.lst
+endif
+MOSTLYCLEANFILES += terminfo_mod-term_terminfo.d terminfo_mod-term_tparm.d
+UNDSYMFILES += und-terminfo.lst
+
+terminfo.mod: pre-terminfo.o mod-terminfo.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(terminfo_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-terminfo.o mod-terminfo.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-terminfo.o: $(terminfo_mod_DEPENDENCIES) terminfo_mod-term_terminfo.o terminfo_mod-term_tparm.o
+       -rm -f $@
+       $(TARGET_CC) $(terminfo_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ terminfo_mod-term_terminfo.o terminfo_mod-term_tparm.o
+
+mod-terminfo.o: mod-terminfo.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(terminfo_mod_CFLAGS) -c -o $@ $<
+
+mod-terminfo.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'terminfo' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(terminfo_mod_EXPORTS),no)
+def-terminfo.lst: pre-terminfo.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 terminfo/' > $@
+endif
+
+und-terminfo.lst: pre-terminfo.o
+       echo 'terminfo' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+terminfo_mod-term_terminfo.o: term/terminfo.c $(term/terminfo.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(terminfo_mod_CFLAGS) -MD -c -o $@ $<
+-include terminfo_mod-term_terminfo.d
+
+CLEANFILES += cmd-terminfo_mod-term_terminfo.lst fs-terminfo_mod-term_terminfo.lst partmap-terminfo_mod-term_terminfo.lst
+COMMANDFILES += cmd-terminfo_mod-term_terminfo.lst
+FSFILES += fs-terminfo_mod-term_terminfo.lst
+PARTMAPFILES += partmap-terminfo_mod-term_terminfo.lst
+
+cmd-terminfo_mod-term_terminfo.lst: term/terminfo.c $(term/terminfo.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(terminfo_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh terminfo > $@ || (rm -f $@; exit 1)
+
+fs-terminfo_mod-term_terminfo.lst: term/terminfo.c $(term/terminfo.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(terminfo_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh terminfo > $@ || (rm -f $@; exit 1)
+
+partmap-terminfo_mod-term_terminfo.lst: term/terminfo.c $(term/terminfo.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(terminfo_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh terminfo > $@ || (rm -f $@; exit 1)
+
+
+terminfo_mod-term_tparm.o: term/tparm.c $(term/tparm.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(terminfo_mod_CFLAGS) -MD -c -o $@ $<
+-include terminfo_mod-term_tparm.d
+
+CLEANFILES += cmd-terminfo_mod-term_tparm.lst fs-terminfo_mod-term_tparm.lst partmap-terminfo_mod-term_tparm.lst
+COMMANDFILES += cmd-terminfo_mod-term_tparm.lst
+FSFILES += fs-terminfo_mod-term_tparm.lst
+PARTMAPFILES += partmap-terminfo_mod-term_tparm.lst
+
+cmd-terminfo_mod-term_tparm.lst: term/tparm.c $(term/tparm.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(terminfo_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh terminfo > $@ || (rm -f $@; exit 1)
+
+fs-terminfo_mod-term_tparm.lst: term/tparm.c $(term/tparm.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(terminfo_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh terminfo > $@ || (rm -f $@; exit 1)
+
+partmap-terminfo_mod-term_tparm.lst: term/tparm.c $(term/tparm.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(terminfo_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh terminfo > $@ || (rm -f $@; exit 1)
+
+
+terminfo_mod_CFLAGS = $(COMMON_CFLAGS)
+terminfo_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For blocklist.mod.
+blocklist_mod_SOURCES = commands/blocklist.c
+CLEANFILES += blocklist.mod mod-blocklist.o mod-blocklist.c pre-blocklist.o blocklist_mod-commands_blocklist.o und-blocklist.lst
+ifneq ($(blocklist_mod_EXPORTS),no)
+CLEANFILES += def-blocklist.lst
+DEFSYMFILES += def-blocklist.lst
+endif
+MOSTLYCLEANFILES += blocklist_mod-commands_blocklist.d
+UNDSYMFILES += und-blocklist.lst
+
+blocklist.mod: pre-blocklist.o mod-blocklist.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(blocklist_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-blocklist.o mod-blocklist.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-blocklist.o: $(blocklist_mod_DEPENDENCIES) blocklist_mod-commands_blocklist.o
+       -rm -f $@
+       $(TARGET_CC) $(blocklist_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ blocklist_mod-commands_blocklist.o
+
+mod-blocklist.o: mod-blocklist.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(blocklist_mod_CFLAGS) -c -o $@ $<
+
+mod-blocklist.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'blocklist' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(blocklist_mod_EXPORTS),no)
+def-blocklist.lst: pre-blocklist.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 blocklist/' > $@
+endif
+
+und-blocklist.lst: pre-blocklist.o
+       echo 'blocklist' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+blocklist_mod-commands_blocklist.o: commands/blocklist.c $(commands/blocklist.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(blocklist_mod_CFLAGS) -MD -c -o $@ $<
+-include blocklist_mod-commands_blocklist.d
+
+CLEANFILES += cmd-blocklist_mod-commands_blocklist.lst fs-blocklist_mod-commands_blocklist.lst partmap-blocklist_mod-commands_blocklist.lst
+COMMANDFILES += cmd-blocklist_mod-commands_blocklist.lst
+FSFILES += fs-blocklist_mod-commands_blocklist.lst
+PARTMAPFILES += partmap-blocklist_mod-commands_blocklist.lst
+
+cmd-blocklist_mod-commands_blocklist.lst: commands/blocklist.c $(commands/blocklist.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(blocklist_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh blocklist > $@ || (rm -f $@; exit 1)
+
+fs-blocklist_mod-commands_blocklist.lst: commands/blocklist.c $(commands/blocklist.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(blocklist_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh blocklist > $@ || (rm -f $@; exit 1)
+
+partmap-blocklist_mod-commands_blocklist.lst: commands/blocklist.c $(commands/blocklist.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(blocklist_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh blocklist > $@ || (rm -f $@; exit 1)
+
+
+blocklist_mod_CFLAGS = $(COMMON_CFLAGS)
+blocklist_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For hexdump.mod.
+hexdump_mod_SOURCES = commands/hexdump.c lib/hexdump.c
+CLEANFILES += hexdump.mod mod-hexdump.o mod-hexdump.c pre-hexdump.o hexdump_mod-commands_hexdump.o hexdump_mod-lib_hexdump.o und-hexdump.lst
+ifneq ($(hexdump_mod_EXPORTS),no)
+CLEANFILES += def-hexdump.lst
+DEFSYMFILES += def-hexdump.lst
+endif
+MOSTLYCLEANFILES += hexdump_mod-commands_hexdump.d hexdump_mod-lib_hexdump.d
+UNDSYMFILES += und-hexdump.lst
+
+hexdump.mod: pre-hexdump.o mod-hexdump.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(hexdump_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-hexdump.o mod-hexdump.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-hexdump.o: $(hexdump_mod_DEPENDENCIES) hexdump_mod-commands_hexdump.o hexdump_mod-lib_hexdump.o
+       -rm -f $@
+       $(TARGET_CC) $(hexdump_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ hexdump_mod-commands_hexdump.o hexdump_mod-lib_hexdump.o
+
+mod-hexdump.o: mod-hexdump.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hexdump_mod_CFLAGS) -c -o $@ $<
+
+mod-hexdump.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'hexdump' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(hexdump_mod_EXPORTS),no)
+def-hexdump.lst: pre-hexdump.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 hexdump/' > $@
+endif
+
+und-hexdump.lst: pre-hexdump.o
+       echo 'hexdump' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+hexdump_mod-commands_hexdump.o: commands/hexdump.c $(commands/hexdump.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(hexdump_mod_CFLAGS) -MD -c -o $@ $<
+-include hexdump_mod-commands_hexdump.d
+
+CLEANFILES += cmd-hexdump_mod-commands_hexdump.lst fs-hexdump_mod-commands_hexdump.lst partmap-hexdump_mod-commands_hexdump.lst
+COMMANDFILES += cmd-hexdump_mod-commands_hexdump.lst
+FSFILES += fs-hexdump_mod-commands_hexdump.lst
+PARTMAPFILES += partmap-hexdump_mod-commands_hexdump.lst
+
+cmd-hexdump_mod-commands_hexdump.lst: commands/hexdump.c $(commands/hexdump.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hexdump_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh hexdump > $@ || (rm -f $@; exit 1)
+
+fs-hexdump_mod-commands_hexdump.lst: commands/hexdump.c $(commands/hexdump.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hexdump_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh hexdump > $@ || (rm -f $@; exit 1)
+
+partmap-hexdump_mod-commands_hexdump.lst: commands/hexdump.c $(commands/hexdump.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hexdump_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh hexdump > $@ || (rm -f $@; exit 1)
+
+
+hexdump_mod-lib_hexdump.o: lib/hexdump.c $(lib/hexdump.c_DEPENDENCIES)
+       $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(hexdump_mod_CFLAGS) -MD -c -o $@ $<
+-include hexdump_mod-lib_hexdump.d
+
+CLEANFILES += cmd-hexdump_mod-lib_hexdump.lst fs-hexdump_mod-lib_hexdump.lst partmap-hexdump_mod-lib_hexdump.lst
+COMMANDFILES += cmd-hexdump_mod-lib_hexdump.lst
+FSFILES += fs-hexdump_mod-lib_hexdump.lst
+PARTMAPFILES += partmap-hexdump_mod-lib_hexdump.lst
+
+cmd-hexdump_mod-lib_hexdump.lst: lib/hexdump.c $(lib/hexdump.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hexdump_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh hexdump > $@ || (rm -f $@; exit 1)
+
+fs-hexdump_mod-lib_hexdump.lst: lib/hexdump.c $(lib/hexdump.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hexdump_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh hexdump > $@ || (rm -f $@; exit 1)
+
+partmap-hexdump_mod-lib_hexdump.lst: lib/hexdump.c $(lib/hexdump.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hexdump_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh hexdump > $@ || (rm -f $@; exit 1)
+
+
+hexdump_mod_CFLAGS = $(COMMON_CFLAGS)
+hexdump_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For read.mod.
+read_mod_SOURCES = commands/read.c
+CLEANFILES += read.mod mod-read.o mod-read.c pre-read.o read_mod-commands_read.o und-read.lst
+ifneq ($(read_mod_EXPORTS),no)
+CLEANFILES += def-read.lst
+DEFSYMFILES += def-read.lst
+endif
+MOSTLYCLEANFILES += read_mod-commands_read.d
+UNDSYMFILES += und-read.lst
+
+read.mod: pre-read.o mod-read.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(read_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-read.o mod-read.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-read.o: $(read_mod_DEPENDENCIES) read_mod-commands_read.o
+       -rm -f $@
+       $(TARGET_CC) $(read_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ read_mod-commands_read.o
+
+mod-read.o: mod-read.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(read_mod_CFLAGS) -c -o $@ $<
+
+mod-read.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'read' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(read_mod_EXPORTS),no)
+def-read.lst: pre-read.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 read/' > $@
+endif
+
+und-read.lst: pre-read.o
+       echo 'read' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+read_mod-commands_read.o: commands/read.c $(commands/read.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(read_mod_CFLAGS) -MD -c -o $@ $<
+-include read_mod-commands_read.d
+
+CLEANFILES += cmd-read_mod-commands_read.lst fs-read_mod-commands_read.lst partmap-read_mod-commands_read.lst
+COMMANDFILES += cmd-read_mod-commands_read.lst
+FSFILES += fs-read_mod-commands_read.lst
+PARTMAPFILES += partmap-read_mod-commands_read.lst
+
+cmd-read_mod-commands_read.lst: commands/read.c $(commands/read.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(read_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh read > $@ || (rm -f $@; exit 1)
+
+fs-read_mod-commands_read.lst: commands/read.c $(commands/read.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(read_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh read > $@ || (rm -f $@; exit 1)
+
+partmap-read_mod-commands_read.lst: commands/read.c $(commands/read.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(read_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh read > $@ || (rm -f $@; exit 1)
+
+
+read_mod_CFLAGS = $(COMMON_CFLAGS)
+read_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For sleep.mod.
+sleep_mod_SOURCES = commands/sleep.c
+CLEANFILES += sleep.mod mod-sleep.o mod-sleep.c pre-sleep.o sleep_mod-commands_sleep.o und-sleep.lst
+ifneq ($(sleep_mod_EXPORTS),no)
+CLEANFILES += def-sleep.lst
+DEFSYMFILES += def-sleep.lst
+endif
+MOSTLYCLEANFILES += sleep_mod-commands_sleep.d
+UNDSYMFILES += und-sleep.lst
+
+sleep.mod: pre-sleep.o mod-sleep.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(sleep_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-sleep.o mod-sleep.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-sleep.o: $(sleep_mod_DEPENDENCIES) sleep_mod-commands_sleep.o
+       -rm -f $@
+       $(TARGET_CC) $(sleep_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ sleep_mod-commands_sleep.o
+
+mod-sleep.o: mod-sleep.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sleep_mod_CFLAGS) -c -o $@ $<
+
+mod-sleep.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'sleep' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(sleep_mod_EXPORTS),no)
+def-sleep.lst: pre-sleep.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 sleep/' > $@
+endif
+
+und-sleep.lst: pre-sleep.o
+       echo 'sleep' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+sleep_mod-commands_sleep.o: commands/sleep.c $(commands/sleep.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(sleep_mod_CFLAGS) -MD -c -o $@ $<
+-include sleep_mod-commands_sleep.d
+
+CLEANFILES += cmd-sleep_mod-commands_sleep.lst fs-sleep_mod-commands_sleep.lst partmap-sleep_mod-commands_sleep.lst
+COMMANDFILES += cmd-sleep_mod-commands_sleep.lst
+FSFILES += fs-sleep_mod-commands_sleep.lst
+PARTMAPFILES += partmap-sleep_mod-commands_sleep.lst
+
+cmd-sleep_mod-commands_sleep.lst: commands/sleep.c $(commands/sleep.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sleep_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh sleep > $@ || (rm -f $@; exit 1)
+
+fs-sleep_mod-commands_sleep.lst: commands/sleep.c $(commands/sleep.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sleep_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh sleep > $@ || (rm -f $@; exit 1)
+
+partmap-sleep_mod-commands_sleep.lst: commands/sleep.c $(commands/sleep.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sleep_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh sleep > $@ || (rm -f $@; exit 1)
+
+
+sleep_mod_CFLAGS = $(COMMON_CFLAGS)
+sleep_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For loadenv.mod.
+loadenv_mod_SOURCES = commands/loadenv.c lib/envblk.c
+CLEANFILES += loadenv.mod mod-loadenv.o mod-loadenv.c pre-loadenv.o loadenv_mod-commands_loadenv.o loadenv_mod-lib_envblk.o und-loadenv.lst
+ifneq ($(loadenv_mod_EXPORTS),no)
+CLEANFILES += def-loadenv.lst
+DEFSYMFILES += def-loadenv.lst
+endif
+MOSTLYCLEANFILES += loadenv_mod-commands_loadenv.d loadenv_mod-lib_envblk.d
+UNDSYMFILES += und-loadenv.lst
+
+loadenv.mod: pre-loadenv.o mod-loadenv.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(loadenv_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-loadenv.o mod-loadenv.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-loadenv.o: $(loadenv_mod_DEPENDENCIES) loadenv_mod-commands_loadenv.o loadenv_mod-lib_envblk.o
+       -rm -f $@
+       $(TARGET_CC) $(loadenv_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ loadenv_mod-commands_loadenv.o loadenv_mod-lib_envblk.o
+
+mod-loadenv.o: mod-loadenv.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -c -o $@ $<
+
+mod-loadenv.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'loadenv' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(loadenv_mod_EXPORTS),no)
+def-loadenv.lst: pre-loadenv.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 loadenv/' > $@
+endif
+
+und-loadenv.lst: pre-loadenv.o
+       echo 'loadenv' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+loadenv_mod-commands_loadenv.o: commands/loadenv.c $(commands/loadenv.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -MD -c -o $@ $<
+-include loadenv_mod-commands_loadenv.d
+
+CLEANFILES += cmd-loadenv_mod-commands_loadenv.lst fs-loadenv_mod-commands_loadenv.lst partmap-loadenv_mod-commands_loadenv.lst
+COMMANDFILES += cmd-loadenv_mod-commands_loadenv.lst
+FSFILES += fs-loadenv_mod-commands_loadenv.lst
+PARTMAPFILES += partmap-loadenv_mod-commands_loadenv.lst
+
+cmd-loadenv_mod-commands_loadenv.lst: commands/loadenv.c $(commands/loadenv.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh loadenv > $@ || (rm -f $@; exit 1)
+
+fs-loadenv_mod-commands_loadenv.lst: commands/loadenv.c $(commands/loadenv.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh loadenv > $@ || (rm -f $@; exit 1)
+
+partmap-loadenv_mod-commands_loadenv.lst: commands/loadenv.c $(commands/loadenv.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh loadenv > $@ || (rm -f $@; exit 1)
+
+
+loadenv_mod-lib_envblk.o: lib/envblk.c $(lib/envblk.c_DEPENDENCIES)
+       $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -MD -c -o $@ $<
+-include loadenv_mod-lib_envblk.d
+
+CLEANFILES += cmd-loadenv_mod-lib_envblk.lst fs-loadenv_mod-lib_envblk.lst partmap-loadenv_mod-lib_envblk.lst
+COMMANDFILES += cmd-loadenv_mod-lib_envblk.lst
+FSFILES += fs-loadenv_mod-lib_envblk.lst
+PARTMAPFILES += partmap-loadenv_mod-lib_envblk.lst
+
+cmd-loadenv_mod-lib_envblk.lst: lib/envblk.c $(lib/envblk.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh loadenv > $@ || (rm -f $@; exit 1)
+
+fs-loadenv_mod-lib_envblk.lst: lib/envblk.c $(lib/envblk.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh loadenv > $@ || (rm -f $@; exit 1)
+
+partmap-loadenv_mod-lib_envblk.lst: lib/envblk.c $(lib/envblk.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh loadenv > $@ || (rm -f $@; exit 1)
+
+
+loadenv_mod_CFLAGS = $(COMMON_CFLAGS)
+loadenv_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For crc.mod.
+crc_mod_SOURCES = commands/crc.c lib/crc.c
+CLEANFILES += crc.mod mod-crc.o mod-crc.c pre-crc.o crc_mod-commands_crc.o crc_mod-lib_crc.o und-crc.lst
+ifneq ($(crc_mod_EXPORTS),no)
+CLEANFILES += def-crc.lst
+DEFSYMFILES += def-crc.lst
+endif
+MOSTLYCLEANFILES += crc_mod-commands_crc.d crc_mod-lib_crc.d
+UNDSYMFILES += und-crc.lst
+
+crc.mod: pre-crc.o mod-crc.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(crc_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-crc.o mod-crc.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-crc.o: $(crc_mod_DEPENDENCIES) crc_mod-commands_crc.o crc_mod-lib_crc.o
+       -rm -f $@
+       $(TARGET_CC) $(crc_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ crc_mod-commands_crc.o crc_mod-lib_crc.o
+
+mod-crc.o: mod-crc.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(crc_mod_CFLAGS) -c -o $@ $<
+
+mod-crc.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'crc' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(crc_mod_EXPORTS),no)
+def-crc.lst: pre-crc.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 crc/' > $@
+endif
+
+und-crc.lst: pre-crc.o
+       echo 'crc' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+crc_mod-commands_crc.o: commands/crc.c $(commands/crc.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(crc_mod_CFLAGS) -MD -c -o $@ $<
+-include crc_mod-commands_crc.d
+
+CLEANFILES += cmd-crc_mod-commands_crc.lst fs-crc_mod-commands_crc.lst partmap-crc_mod-commands_crc.lst
+COMMANDFILES += cmd-crc_mod-commands_crc.lst
+FSFILES += fs-crc_mod-commands_crc.lst
+PARTMAPFILES += partmap-crc_mod-commands_crc.lst
+
+cmd-crc_mod-commands_crc.lst: commands/crc.c $(commands/crc.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(crc_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh crc > $@ || (rm -f $@; exit 1)
+
+fs-crc_mod-commands_crc.lst: commands/crc.c $(commands/crc.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(crc_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh crc > $@ || (rm -f $@; exit 1)
+
+partmap-crc_mod-commands_crc.lst: commands/crc.c $(commands/crc.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(crc_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh crc > $@ || (rm -f $@; exit 1)
+
+
+crc_mod-lib_crc.o: lib/crc.c $(lib/crc.c_DEPENDENCIES)
+       $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(crc_mod_CFLAGS) -MD -c -o $@ $<
+-include crc_mod-lib_crc.d
+
+CLEANFILES += cmd-crc_mod-lib_crc.lst fs-crc_mod-lib_crc.lst partmap-crc_mod-lib_crc.lst
+COMMANDFILES += cmd-crc_mod-lib_crc.lst
+FSFILES += fs-crc_mod-lib_crc.lst
+PARTMAPFILES += partmap-crc_mod-lib_crc.lst
+
+cmd-crc_mod-lib_crc.lst: lib/crc.c $(lib/crc.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(crc_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh crc > $@ || (rm -f $@; exit 1)
+
+fs-crc_mod-lib_crc.lst: lib/crc.c $(lib/crc.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(crc_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh crc > $@ || (rm -f $@; exit 1)
+
+partmap-crc_mod-lib_crc.lst: lib/crc.c $(lib/crc.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(crc_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh crc > $@ || (rm -f $@; exit 1)
+
+
+crc_mod_CFLAGS = $(COMMON_CFLAGS)
+crc_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# Common Video Subsystem specific modules.
+pkglib_MODULES += video.mod videotest.mod bitmap.mod tga.mod jpeg.mod  \
+       png.mod font.mod gfxterm.mod
+
+# For video.mod.
+video_mod_SOURCES = video/video.c
+CLEANFILES += video.mod mod-video.o mod-video.c pre-video.o video_mod-video_video.o und-video.lst
+ifneq ($(video_mod_EXPORTS),no)
+CLEANFILES += def-video.lst
+DEFSYMFILES += def-video.lst
+endif
+MOSTLYCLEANFILES += video_mod-video_video.d
+UNDSYMFILES += und-video.lst
+
+video.mod: pre-video.o mod-video.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(video_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-video.o mod-video.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-video.o: $(video_mod_DEPENDENCIES) video_mod-video_video.o
+       -rm -f $@
+       $(TARGET_CC) $(video_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ video_mod-video_video.o
+
+mod-video.o: mod-video.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(video_mod_CFLAGS) -c -o $@ $<
+
+mod-video.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'video' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(video_mod_EXPORTS),no)
+def-video.lst: pre-video.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 video/' > $@
+endif
+
+und-video.lst: pre-video.o
+       echo 'video' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+video_mod-video_video.o: video/video.c $(video/video.c_DEPENDENCIES)
+       $(TARGET_CC) -Ivideo -I$(srcdir)/video $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(video_mod_CFLAGS) -MD -c -o $@ $<
+-include video_mod-video_video.d
+
+CLEANFILES += cmd-video_mod-video_video.lst fs-video_mod-video_video.lst partmap-video_mod-video_video.lst
+COMMANDFILES += cmd-video_mod-video_video.lst
+FSFILES += fs-video_mod-video_video.lst
+PARTMAPFILES += partmap-video_mod-video_video.lst
+
+cmd-video_mod-video_video.lst: video/video.c $(video/video.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ivideo -I$(srcdir)/video $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(video_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh video > $@ || (rm -f $@; exit 1)
+
+fs-video_mod-video_video.lst: video/video.c $(video/video.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ivideo -I$(srcdir)/video $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(video_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh video > $@ || (rm -f $@; exit 1)
+
+partmap-video_mod-video_video.lst: video/video.c $(video/video.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ivideo -I$(srcdir)/video $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(video_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh video > $@ || (rm -f $@; exit 1)
+
+
+video_mod_CFLAGS = $(COMMON_CFLAGS)
+video_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For videotest.mod.
+videotest_mod_SOURCES = commands/videotest.c
+CLEANFILES += videotest.mod mod-videotest.o mod-videotest.c pre-videotest.o videotest_mod-commands_videotest.o und-videotest.lst
+ifneq ($(videotest_mod_EXPORTS),no)
+CLEANFILES += def-videotest.lst
+DEFSYMFILES += def-videotest.lst
+endif
+MOSTLYCLEANFILES += videotest_mod-commands_videotest.d
+UNDSYMFILES += und-videotest.lst
+
+videotest.mod: pre-videotest.o mod-videotest.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(videotest_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-videotest.o mod-videotest.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-videotest.o: $(videotest_mod_DEPENDENCIES) videotest_mod-commands_videotest.o
+       -rm -f $@
+       $(TARGET_CC) $(videotest_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ videotest_mod-commands_videotest.o
+
+mod-videotest.o: mod-videotest.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(videotest_mod_CFLAGS) -c -o $@ $<
+
+mod-videotest.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'videotest' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(videotest_mod_EXPORTS),no)
+def-videotest.lst: pre-videotest.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 videotest/' > $@
+endif
+
+und-videotest.lst: pre-videotest.o
+       echo 'videotest' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+videotest_mod-commands_videotest.o: commands/videotest.c $(commands/videotest.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(videotest_mod_CFLAGS) -MD -c -o $@ $<
+-include videotest_mod-commands_videotest.d
+
+CLEANFILES += cmd-videotest_mod-commands_videotest.lst fs-videotest_mod-commands_videotest.lst partmap-videotest_mod-commands_videotest.lst
+COMMANDFILES += cmd-videotest_mod-commands_videotest.lst
+FSFILES += fs-videotest_mod-commands_videotest.lst
+PARTMAPFILES += partmap-videotest_mod-commands_videotest.lst
+
+cmd-videotest_mod-commands_videotest.lst: commands/videotest.c $(commands/videotest.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(videotest_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh videotest > $@ || (rm -f $@; exit 1)
+
+fs-videotest_mod-commands_videotest.lst: commands/videotest.c $(commands/videotest.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(videotest_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh videotest > $@ || (rm -f $@; exit 1)
+
+partmap-videotest_mod-commands_videotest.lst: commands/videotest.c $(commands/videotest.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(videotest_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh videotest > $@ || (rm -f $@; exit 1)
+
+
+videotest_mod_CFLAGS = $(COMMON_CFLAGS)
+videotest_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For bitmap.mod
+bitmap_mod_SOURCES = video/bitmap.c
+CLEANFILES += bitmap.mod mod-bitmap.o mod-bitmap.c pre-bitmap.o bitmap_mod-video_bitmap.o und-bitmap.lst
+ifneq ($(bitmap_mod_EXPORTS),no)
+CLEANFILES += def-bitmap.lst
+DEFSYMFILES += def-bitmap.lst
+endif
+MOSTLYCLEANFILES += bitmap_mod-video_bitmap.d
+UNDSYMFILES += und-bitmap.lst
+
+bitmap.mod: pre-bitmap.o mod-bitmap.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(bitmap_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-bitmap.o mod-bitmap.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-bitmap.o: $(bitmap_mod_DEPENDENCIES) bitmap_mod-video_bitmap.o
+       -rm -f $@
+       $(TARGET_CC) $(bitmap_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ bitmap_mod-video_bitmap.o
+
+mod-bitmap.o: mod-bitmap.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bitmap_mod_CFLAGS) -c -o $@ $<
+
+mod-bitmap.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'bitmap' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(bitmap_mod_EXPORTS),no)
+def-bitmap.lst: pre-bitmap.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 bitmap/' > $@
+endif
+
+und-bitmap.lst: pre-bitmap.o
+       echo 'bitmap' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+bitmap_mod-video_bitmap.o: video/bitmap.c $(video/bitmap.c_DEPENDENCIES)
+       $(TARGET_CC) -Ivideo -I$(srcdir)/video $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(bitmap_mod_CFLAGS) -MD -c -o $@ $<
+-include bitmap_mod-video_bitmap.d
+
+CLEANFILES += cmd-bitmap_mod-video_bitmap.lst fs-bitmap_mod-video_bitmap.lst partmap-bitmap_mod-video_bitmap.lst
+COMMANDFILES += cmd-bitmap_mod-video_bitmap.lst
+FSFILES += fs-bitmap_mod-video_bitmap.lst
+PARTMAPFILES += partmap-bitmap_mod-video_bitmap.lst
+
+cmd-bitmap_mod-video_bitmap.lst: video/bitmap.c $(video/bitmap.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ivideo -I$(srcdir)/video $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bitmap_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh bitmap > $@ || (rm -f $@; exit 1)
+
+fs-bitmap_mod-video_bitmap.lst: video/bitmap.c $(video/bitmap.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ivideo -I$(srcdir)/video $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bitmap_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh bitmap > $@ || (rm -f $@; exit 1)
+
+partmap-bitmap_mod-video_bitmap.lst: video/bitmap.c $(video/bitmap.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ivideo -I$(srcdir)/video $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bitmap_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh bitmap > $@ || (rm -f $@; exit 1)
+
+
+bitmap_mod_CFLAGS = $(COMMON_CFLAGS)
+bitmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For tga.mod
+tga_mod_SOURCES = video/readers/tga.c
+CLEANFILES += tga.mod mod-tga.o mod-tga.c pre-tga.o tga_mod-video_readers_tga.o und-tga.lst
+ifneq ($(tga_mod_EXPORTS),no)
+CLEANFILES += def-tga.lst
+DEFSYMFILES += def-tga.lst
+endif
+MOSTLYCLEANFILES += tga_mod-video_readers_tga.d
+UNDSYMFILES += und-tga.lst
+
+tga.mod: pre-tga.o mod-tga.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(tga_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-tga.o mod-tga.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-tga.o: $(tga_mod_DEPENDENCIES) tga_mod-video_readers_tga.o
+       -rm -f $@
+       $(TARGET_CC) $(tga_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ tga_mod-video_readers_tga.o
+
+mod-tga.o: mod-tga.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(tga_mod_CFLAGS) -c -o $@ $<
+
+mod-tga.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'tga' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(tga_mod_EXPORTS),no)
+def-tga.lst: pre-tga.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 tga/' > $@
+endif
+
+und-tga.lst: pre-tga.o
+       echo 'tga' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+tga_mod-video_readers_tga.o: video/readers/tga.c $(video/readers/tga.c_DEPENDENCIES)
+       $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(tga_mod_CFLAGS) -MD -c -o $@ $<
+-include tga_mod-video_readers_tga.d
+
+CLEANFILES += cmd-tga_mod-video_readers_tga.lst fs-tga_mod-video_readers_tga.lst partmap-tga_mod-video_readers_tga.lst
+COMMANDFILES += cmd-tga_mod-video_readers_tga.lst
+FSFILES += fs-tga_mod-video_readers_tga.lst
+PARTMAPFILES += partmap-tga_mod-video_readers_tga.lst
+
+cmd-tga_mod-video_readers_tga.lst: video/readers/tga.c $(video/readers/tga.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(tga_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh tga > $@ || (rm -f $@; exit 1)
+
+fs-tga_mod-video_readers_tga.lst: video/readers/tga.c $(video/readers/tga.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(tga_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh tga > $@ || (rm -f $@; exit 1)
+
+partmap-tga_mod-video_readers_tga.lst: video/readers/tga.c $(video/readers/tga.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(tga_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh tga > $@ || (rm -f $@; exit 1)
+
+
+tga_mod_CFLAGS = $(COMMON_CFLAGS)
+tga_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For jpeg.mod.
+jpeg_mod_SOURCES = video/readers/jpeg.c
+CLEANFILES += jpeg.mod mod-jpeg.o mod-jpeg.c pre-jpeg.o jpeg_mod-video_readers_jpeg.o und-jpeg.lst
+ifneq ($(jpeg_mod_EXPORTS),no)
+CLEANFILES += def-jpeg.lst
+DEFSYMFILES += def-jpeg.lst
+endif
+MOSTLYCLEANFILES += jpeg_mod-video_readers_jpeg.d
+UNDSYMFILES += und-jpeg.lst
+
+jpeg.mod: pre-jpeg.o mod-jpeg.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(jpeg_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-jpeg.o mod-jpeg.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-jpeg.o: $(jpeg_mod_DEPENDENCIES) jpeg_mod-video_readers_jpeg.o
+       -rm -f $@
+       $(TARGET_CC) $(jpeg_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ jpeg_mod-video_readers_jpeg.o
+
+mod-jpeg.o: mod-jpeg.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(jpeg_mod_CFLAGS) -c -o $@ $<
+
+mod-jpeg.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'jpeg' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(jpeg_mod_EXPORTS),no)
+def-jpeg.lst: pre-jpeg.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 jpeg/' > $@
+endif
+
+und-jpeg.lst: pre-jpeg.o
+       echo 'jpeg' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+jpeg_mod-video_readers_jpeg.o: video/readers/jpeg.c $(video/readers/jpeg.c_DEPENDENCIES)
+       $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(jpeg_mod_CFLAGS) -MD -c -o $@ $<
+-include jpeg_mod-video_readers_jpeg.d
+
+CLEANFILES += cmd-jpeg_mod-video_readers_jpeg.lst fs-jpeg_mod-video_readers_jpeg.lst partmap-jpeg_mod-video_readers_jpeg.lst
+COMMANDFILES += cmd-jpeg_mod-video_readers_jpeg.lst
+FSFILES += fs-jpeg_mod-video_readers_jpeg.lst
+PARTMAPFILES += partmap-jpeg_mod-video_readers_jpeg.lst
+
+cmd-jpeg_mod-video_readers_jpeg.lst: video/readers/jpeg.c $(video/readers/jpeg.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(jpeg_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh jpeg > $@ || (rm -f $@; exit 1)
+
+fs-jpeg_mod-video_readers_jpeg.lst: video/readers/jpeg.c $(video/readers/jpeg.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(jpeg_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh jpeg > $@ || (rm -f $@; exit 1)
+
+partmap-jpeg_mod-video_readers_jpeg.lst: video/readers/jpeg.c $(video/readers/jpeg.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(jpeg_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh jpeg > $@ || (rm -f $@; exit 1)
+
+
+jpeg_mod_CFLAGS = $(COMMON_CFLAGS)
+jpeg_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For png.mod.
+png_mod_SOURCES = video/readers/png.c
+CLEANFILES += png.mod mod-png.o mod-png.c pre-png.o png_mod-video_readers_png.o und-png.lst
+ifneq ($(png_mod_EXPORTS),no)
+CLEANFILES += def-png.lst
+DEFSYMFILES += def-png.lst
+endif
+MOSTLYCLEANFILES += png_mod-video_readers_png.d
+UNDSYMFILES += und-png.lst
+
+png.mod: pre-png.o mod-png.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(png_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-png.o mod-png.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-png.o: $(png_mod_DEPENDENCIES) png_mod-video_readers_png.o
+       -rm -f $@
+       $(TARGET_CC) $(png_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ png_mod-video_readers_png.o
+
+mod-png.o: mod-png.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(png_mod_CFLAGS) -c -o $@ $<
+
+mod-png.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'png' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(png_mod_EXPORTS),no)
+def-png.lst: pre-png.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 png/' > $@
+endif
+
+und-png.lst: pre-png.o
+       echo 'png' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+png_mod-video_readers_png.o: video/readers/png.c $(video/readers/png.c_DEPENDENCIES)
+       $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(png_mod_CFLAGS) -MD -c -o $@ $<
+-include png_mod-video_readers_png.d
+
+CLEANFILES += cmd-png_mod-video_readers_png.lst fs-png_mod-video_readers_png.lst partmap-png_mod-video_readers_png.lst
+COMMANDFILES += cmd-png_mod-video_readers_png.lst
+FSFILES += fs-png_mod-video_readers_png.lst
+PARTMAPFILES += partmap-png_mod-video_readers_png.lst
+
+cmd-png_mod-video_readers_png.lst: video/readers/png.c $(video/readers/png.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(png_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh png > $@ || (rm -f $@; exit 1)
+
+fs-png_mod-video_readers_png.lst: video/readers/png.c $(video/readers/png.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(png_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh png > $@ || (rm -f $@; exit 1)
+
+partmap-png_mod-video_readers_png.lst: video/readers/png.c $(video/readers/png.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ivideo/readers -I$(srcdir)/video/readers $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(png_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh png > $@ || (rm -f $@; exit 1)
+
+
+png_mod_CFLAGS = $(COMMON_CFLAGS)
+png_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For font.mod.
+font_mod_SOURCES = font/font_cmd.c font/font.c
+CLEANFILES += font.mod mod-font.o mod-font.c pre-font.o font_mod-font_font_cmd.o font_mod-font_font.o und-font.lst
+ifneq ($(font_mod_EXPORTS),no)
+CLEANFILES += def-font.lst
+DEFSYMFILES += def-font.lst
+endif
+MOSTLYCLEANFILES += font_mod-font_font_cmd.d font_mod-font_font.d
+UNDSYMFILES += und-font.lst
+
+font.mod: pre-font.o mod-font.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(font_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-font.o mod-font.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-font.o: $(font_mod_DEPENDENCIES) font_mod-font_font_cmd.o font_mod-font_font.o
+       -rm -f $@
+       $(TARGET_CC) $(font_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ font_mod-font_font_cmd.o font_mod-font_font.o
+
+mod-font.o: mod-font.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(font_mod_CFLAGS) -c -o $@ $<
+
+mod-font.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'font' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(font_mod_EXPORTS),no)
+def-font.lst: pre-font.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 font/' > $@
+endif
+
+und-font.lst: pre-font.o
+       echo 'font' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+font_mod-font_font_cmd.o: font/font_cmd.c $(font/font_cmd.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifont -I$(srcdir)/font $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(font_mod_CFLAGS) -MD -c -o $@ $<
+-include font_mod-font_font_cmd.d
+
+CLEANFILES += cmd-font_mod-font_font_cmd.lst fs-font_mod-font_font_cmd.lst partmap-font_mod-font_font_cmd.lst
+COMMANDFILES += cmd-font_mod-font_font_cmd.lst
+FSFILES += fs-font_mod-font_font_cmd.lst
+PARTMAPFILES += partmap-font_mod-font_font_cmd.lst
+
+cmd-font_mod-font_font_cmd.lst: font/font_cmd.c $(font/font_cmd.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifont -I$(srcdir)/font $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(font_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh font > $@ || (rm -f $@; exit 1)
+
+fs-font_mod-font_font_cmd.lst: font/font_cmd.c $(font/font_cmd.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifont -I$(srcdir)/font $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(font_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh font > $@ || (rm -f $@; exit 1)
+
+partmap-font_mod-font_font_cmd.lst: font/font_cmd.c $(font/font_cmd.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifont -I$(srcdir)/font $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(font_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh font > $@ || (rm -f $@; exit 1)
+
+
+font_mod-font_font.o: font/font.c $(font/font.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifont -I$(srcdir)/font $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(font_mod_CFLAGS) -MD -c -o $@ $<
+-include font_mod-font_font.d
+
+CLEANFILES += cmd-font_mod-font_font.lst fs-font_mod-font_font.lst partmap-font_mod-font_font.lst
+COMMANDFILES += cmd-font_mod-font_font.lst
+FSFILES += fs-font_mod-font_font.lst
+PARTMAPFILES += partmap-font_mod-font_font.lst
+
+cmd-font_mod-font_font.lst: font/font.c $(font/font.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifont -I$(srcdir)/font $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(font_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh font > $@ || (rm -f $@; exit 1)
+
+fs-font_mod-font_font.lst: font/font.c $(font/font.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifont -I$(srcdir)/font $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(font_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh font > $@ || (rm -f $@; exit 1)
+
+partmap-font_mod-font_font.lst: font/font.c $(font/font.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifont -I$(srcdir)/font $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(font_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh font > $@ || (rm -f $@; exit 1)
+
+
+font_mod_CFLAGS = $(COMMON_CFLAGS)
+font_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For gfxterm.mod.
+gfxterm_mod_SOURCES = term/gfxterm.c
+CLEANFILES += gfxterm.mod mod-gfxterm.o mod-gfxterm.c pre-gfxterm.o gfxterm_mod-term_gfxterm.o und-gfxterm.lst
+ifneq ($(gfxterm_mod_EXPORTS),no)
+CLEANFILES += def-gfxterm.lst
+DEFSYMFILES += def-gfxterm.lst
+endif
+MOSTLYCLEANFILES += gfxterm_mod-term_gfxterm.d
+UNDSYMFILES += und-gfxterm.lst
+
+gfxterm.mod: pre-gfxterm.o mod-gfxterm.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(gfxterm_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-gfxterm.o mod-gfxterm.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-gfxterm.o: $(gfxterm_mod_DEPENDENCIES) gfxterm_mod-term_gfxterm.o
+       -rm -f $@
+       $(TARGET_CC) $(gfxterm_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ gfxterm_mod-term_gfxterm.o
+
+mod-gfxterm.o: mod-gfxterm.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gfxterm_mod_CFLAGS) -c -o $@ $<
+
+mod-gfxterm.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'gfxterm' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(gfxterm_mod_EXPORTS),no)
+def-gfxterm.lst: pre-gfxterm.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 gfxterm/' > $@
+endif
+
+und-gfxterm.lst: pre-gfxterm.o
+       echo 'gfxterm' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+gfxterm_mod-term_gfxterm.o: term/gfxterm.c $(term/gfxterm.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(gfxterm_mod_CFLAGS) -MD -c -o $@ $<
+-include gfxterm_mod-term_gfxterm.d
+
+CLEANFILES += cmd-gfxterm_mod-term_gfxterm.lst fs-gfxterm_mod-term_gfxterm.lst partmap-gfxterm_mod-term_gfxterm.lst
+COMMANDFILES += cmd-gfxterm_mod-term_gfxterm.lst
+FSFILES += fs-gfxterm_mod-term_gfxterm.lst
+PARTMAPFILES += partmap-gfxterm_mod-term_gfxterm.lst
+
+cmd-gfxterm_mod-term_gfxterm.lst: term/gfxterm.c $(term/gfxterm.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gfxterm_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh gfxterm > $@ || (rm -f $@; exit 1)
+
+fs-gfxterm_mod-term_gfxterm.lst: term/gfxterm.c $(term/gfxterm.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gfxterm_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh gfxterm > $@ || (rm -f $@; exit 1)
+
+partmap-gfxterm_mod-term_gfxterm.lst: term/gfxterm.c $(term/gfxterm.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gfxterm_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh gfxterm > $@ || (rm -f $@; exit 1)
+
+
+gfxterm_mod_CFLAGS = $(COMMON_CFLAGS)
+gfxterm_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# Misc.
+pkglib_MODULES += gzio.mod bufio.mod elf.mod
+
+# For elf.mod.
+elf_mod_SOURCES = kern/elf.c
+CLEANFILES += elf.mod mod-elf.o mod-elf.c pre-elf.o elf_mod-kern_elf.o und-elf.lst
+ifneq ($(elf_mod_EXPORTS),no)
+CLEANFILES += def-elf.lst
+DEFSYMFILES += def-elf.lst
+endif
+MOSTLYCLEANFILES += elf_mod-kern_elf.d
+UNDSYMFILES += und-elf.lst
+
+elf.mod: pre-elf.o mod-elf.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(elf_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-elf.o mod-elf.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-elf.o: $(elf_mod_DEPENDENCIES) elf_mod-kern_elf.o
+       -rm -f $@
+       $(TARGET_CC) $(elf_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ elf_mod-kern_elf.o
+
+mod-elf.o: mod-elf.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(elf_mod_CFLAGS) -c -o $@ $<
+
+mod-elf.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'elf' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(elf_mod_EXPORTS),no)
+def-elf.lst: pre-elf.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 elf/' > $@
+endif
+
+und-elf.lst: pre-elf.o
+       echo 'elf' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+elf_mod-kern_elf.o: kern/elf.c $(kern/elf.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(elf_mod_CFLAGS) -MD -c -o $@ $<
+-include elf_mod-kern_elf.d
+
+CLEANFILES += cmd-elf_mod-kern_elf.lst fs-elf_mod-kern_elf.lst partmap-elf_mod-kern_elf.lst
+COMMANDFILES += cmd-elf_mod-kern_elf.lst
+FSFILES += fs-elf_mod-kern_elf.lst
+PARTMAPFILES += partmap-elf_mod-kern_elf.lst
+
+cmd-elf_mod-kern_elf.lst: kern/elf.c $(kern/elf.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(elf_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh elf > $@ || (rm -f $@; exit 1)
+
+fs-elf_mod-kern_elf.lst: kern/elf.c $(kern/elf.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(elf_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh elf > $@ || (rm -f $@; exit 1)
+
+partmap-elf_mod-kern_elf.lst: kern/elf.c $(kern/elf.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(elf_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh elf > $@ || (rm -f $@; exit 1)
+
+
+elf_mod_CFLAGS = $(COMMON_CFLAGS)
+elf_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For gzio.mod.
+gzio_mod_SOURCES = io/gzio.c
+CLEANFILES += gzio.mod mod-gzio.o mod-gzio.c pre-gzio.o gzio_mod-io_gzio.o und-gzio.lst
+ifneq ($(gzio_mod_EXPORTS),no)
+CLEANFILES += def-gzio.lst
+DEFSYMFILES += def-gzio.lst
+endif
+MOSTLYCLEANFILES += gzio_mod-io_gzio.d
+UNDSYMFILES += und-gzio.lst
+
+gzio.mod: pre-gzio.o mod-gzio.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(gzio_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-gzio.o mod-gzio.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-gzio.o: $(gzio_mod_DEPENDENCIES) gzio_mod-io_gzio.o
+       -rm -f $@
+       $(TARGET_CC) $(gzio_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ gzio_mod-io_gzio.o
+
+mod-gzio.o: mod-gzio.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gzio_mod_CFLAGS) -c -o $@ $<
+
+mod-gzio.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'gzio' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(gzio_mod_EXPORTS),no)
+def-gzio.lst: pre-gzio.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 gzio/' > $@
+endif
+
+und-gzio.lst: pre-gzio.o
+       echo 'gzio' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+gzio_mod-io_gzio.o: io/gzio.c $(io/gzio.c_DEPENDENCIES)
+       $(TARGET_CC) -Iio -I$(srcdir)/io $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(gzio_mod_CFLAGS) -MD -c -o $@ $<
+-include gzio_mod-io_gzio.d
+
+CLEANFILES += cmd-gzio_mod-io_gzio.lst fs-gzio_mod-io_gzio.lst partmap-gzio_mod-io_gzio.lst
+COMMANDFILES += cmd-gzio_mod-io_gzio.lst
+FSFILES += fs-gzio_mod-io_gzio.lst
+PARTMAPFILES += partmap-gzio_mod-io_gzio.lst
+
+cmd-gzio_mod-io_gzio.lst: io/gzio.c $(io/gzio.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iio -I$(srcdir)/io $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gzio_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh gzio > $@ || (rm -f $@; exit 1)
+
+fs-gzio_mod-io_gzio.lst: io/gzio.c $(io/gzio.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iio -I$(srcdir)/io $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gzio_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh gzio > $@ || (rm -f $@; exit 1)
+
+partmap-gzio_mod-io_gzio.lst: io/gzio.c $(io/gzio.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iio -I$(srcdir)/io $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gzio_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh gzio > $@ || (rm -f $@; exit 1)
+
+
+gzio_mod_CFLAGS = $(COMMON_CFLAGS)
+gzio_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For bufio.mod.
+bufio_mod_SOURCES = io/bufio.c
+CLEANFILES += bufio.mod mod-bufio.o mod-bufio.c pre-bufio.o bufio_mod-io_bufio.o und-bufio.lst
+ifneq ($(bufio_mod_EXPORTS),no)
+CLEANFILES += def-bufio.lst
+DEFSYMFILES += def-bufio.lst
+endif
+MOSTLYCLEANFILES += bufio_mod-io_bufio.d
+UNDSYMFILES += und-bufio.lst
+
+bufio.mod: pre-bufio.o mod-bufio.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(bufio_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-bufio.o mod-bufio.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-bufio.o: $(bufio_mod_DEPENDENCIES) bufio_mod-io_bufio.o
+       -rm -f $@
+       $(TARGET_CC) $(bufio_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ bufio_mod-io_bufio.o
+
+mod-bufio.o: mod-bufio.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bufio_mod_CFLAGS) -c -o $@ $<
+
+mod-bufio.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'bufio' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(bufio_mod_EXPORTS),no)
+def-bufio.lst: pre-bufio.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 bufio/' > $@
+endif
+
+und-bufio.lst: pre-bufio.o
+       echo 'bufio' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+bufio_mod-io_bufio.o: io/bufio.c $(io/bufio.c_DEPENDENCIES)
+       $(TARGET_CC) -Iio -I$(srcdir)/io $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(bufio_mod_CFLAGS) -MD -c -o $@ $<
+-include bufio_mod-io_bufio.d
+
+CLEANFILES += cmd-bufio_mod-io_bufio.lst fs-bufio_mod-io_bufio.lst partmap-bufio_mod-io_bufio.lst
+COMMANDFILES += cmd-bufio_mod-io_bufio.lst
+FSFILES += fs-bufio_mod-io_bufio.lst
+PARTMAPFILES += partmap-bufio_mod-io_bufio.lst
+
+cmd-bufio_mod-io_bufio.lst: io/bufio.c $(io/bufio.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iio -I$(srcdir)/io $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bufio_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh bufio > $@ || (rm -f $@; exit 1)
+
+fs-bufio_mod-io_bufio.lst: io/bufio.c $(io/bufio.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iio -I$(srcdir)/io $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bufio_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh bufio > $@ || (rm -f $@; exit 1)
+
+partmap-bufio_mod-io_bufio.lst: io/bufio.c $(io/bufio.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iio -I$(srcdir)/io $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bufio_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh bufio > $@ || (rm -f $@; exit 1)
+
+
+bufio_mod_CFLAGS = $(COMMON_CFLAGS)
+bufio_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/conf/common.rmk b/conf/common.rmk
new file mode 100644 (file)
index 0000000..dfd481a
--- /dev/null
@@ -0,0 +1,499 @@
+# -*- makefile -*-
+
+# For grub-mkelfimage.
+bin_UTILITIES += grub-mkelfimage
+grub_mkelfimage_SOURCES = util/elf/grub-mkimage.c util/misc.c \
+       util/resolve.c
+util/elf/grub-mkimage.c_DEPENDENCIES = Makefile
+
+# For grub-probe.
+sbin_UTILITIES += grub-probe
+util/grub-probe.c_DEPENDENCIES = grub_probe_init.h
+grub_probe_SOURCES = util/grub-probe.c \
+       util/hostdisk.c util/misc.c util/getroot.c              \
+       kern/device.c kern/disk.c kern/err.c kern/misc.c        \
+       kern/parser.c kern/partition.c kern/file.c              \
+       \
+       fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c         \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c  \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c          \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                     \
+       \
+       partmap/pc.c partmap/apple.c partmap/gpt.c              \
+       kern/fs.c kern/env.c fs/fshelp.c                        \
+       disk/raid.c disk/mdraid_linux.c disk/lvm.c grub_probe_init.c
+
+ifeq ($(enable_grub_fstest), yes)
+bin_UTILITIES += grub-fstest
+endif
+
+# For grub-fstest.
+util/grub-fstest.c_DEPENDENCIES = grub_fstest_init.h
+grub_fstest_SOURCES = util/grub-fstest.c util/hostfs.c util/misc.c     \
+       kern/file.c kern/device.c kern/disk.c kern/err.c kern/misc.c    \
+       disk/host.c disk/loopback.c  normal/arg.c normal/misc.c         \
+       lib/hexdump.c lib/crc.c commands/blocklist.c commands/ls.c      \
+       \
+       fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c                 \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c          \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c                  \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                             \
+       \
+       kern/partition.c partmap/pc.c partmap/apple.c partmap/gpt.c     \
+       kern/fs.c kern/env.c fs/fshelp.c disk/raid.c                    \
+       disk/raid5_recover.c disk/raid6_recover.c                       \
+       disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c             \
+       grub_fstest_init.c
+
+# For grub-mkfont.
+ifeq ($(enable_grub_mkfont), yes)
+bin_UTILITIES += grub-mkfont
+grub_mkfont_SOURCES = util/grub-mkfont.c util/misc.c
+grub_mkfont_CFLAGS = $(freetype_cflags)
+grub_mkfont_LDFLAGS = $(freetype_libs)
+endif
+
+# For the parser.
+grub_script.tab.c grub_script.tab.h: normal/parser.y
+       $(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/normal/parser.y
+DISTCLEANFILES += grub_script.tab.c grub_script.tab.h
+
+# For grub-emu.
+grub_emu_init.lst: geninit.sh $(filter-out grub_emu_init.c,$(grub_emu_SOURCES))
+       rm -f $@; grep GRUB_MOD_INIT $(filter %.c,$^) /dev/null > $@
+DISTCLEANFILES += grub_emu_init.lst
+
+grub_emu_init.h: grub_emu_init.lst $(filter-out grub_emu_init.c,$(grub_emu_SOURCES)) geninitheader.sh
+       rm -f $@; sh $(srcdir)/geninitheader.sh $< > $@
+DISTCLEANFILES += grub_emu_init.h
+
+grub_emu_init.c: grub_emu_init.lst $(filter-out grub_emu_init.c,$(grub_emu_SOURCES)) geninit.sh grub_emu_init.h
+       rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@
+DISTCLEANFILES += grub_emu_init.c
+
+# For grub-probe.
+grub_probe_init.lst: geninit.sh $(filter-out grub_probe_init.c,$(grub_probe_SOURCES))
+       rm -f $@; grep GRUB_MOD_INIT $(filter %.c,$^) /dev/null > $@
+DISTCLEANFILES += grub_probe_init.lst
+
+grub_probe_init.h: grub_probe_init.lst $(filter-out grub_probe_init.c,$(grub_probe_SOURCES)) geninitheader.sh
+       rm -f $@; sh $(srcdir)/geninitheader.sh $< > $@
+DISTCLEANFILES += grub_probe_init.h
+
+grub_probe_init.c: grub_probe_init.lst $(filter-out grub_probe_init.c,$(grub_probe_SOURCES)) geninit.sh grub_probe_init.h
+       rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@
+DISTCLEANFILES += grub_probe_init.c
+
+# For grub-setup.
+grub_setup_init.lst: geninit.sh $(filter-out grub_setup_init.c,$(grub_setup_SOURCES))
+       rm -f $@; grep GRUB_MOD_INIT $(filter %.c,$^) /dev/null > $@
+DISTCLEANFILES += grub_setup_init.lst
+
+grub_setup_init.h: grub_setup_init.lst $(filter-out grub_setup_init.c,$(grub_setup_SOURCES)) geninitheader.sh
+       rm -f $@; sh $(srcdir)/geninitheader.sh $< > $@
+DISTCLEANFILES += grub_setup_init.h
+
+grub_setup_init.c: grub_setup_init.lst $(filter-out grub_setup_init.c,$(grub_setup_SOURCES)) geninit.sh grub_setup_init.h
+       rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@
+DISTCLEANFILES += grub_setup_init.c
+
+# For grub-fstest.
+grub_fstest_init.lst: geninit.sh $(filter-out grub_fstest_init.c,$(grub_fstest_SOURCES))
+       rm -f $@; grep GRUB_MOD_INIT $(filter %.c,$^) /dev/null > $@
+DISTCLEANFILES += grub_fstest_init.lst
+
+grub_fstest_init.h: grub_fstest_init.lst $(filter-out grub_fstest_init.c,$(grub_fstest_SOURCES)) geninitheader.sh
+       rm -f $@; sh $(srcdir)/geninitheader.sh $< > $@
+DISTCLEANFILES += grub_fstest_init.h
+
+grub_fstest_init.c: grub_fstest_init.lst $(filter-out grub_fstest_init.c,$(grub_fstest_SOURCES)) geninit.sh grub_fstest_init.h
+       rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@
+DISTCLEANFILES += grub_fstest_init.c
+
+# for grub-editenv
+bin_UTILITIES += grub-editenv
+grub_editenv_SOURCES = util/grub-editenv.c lib/envblk.c util/misc.c kern/misc.c kern/err.c
+CLEANFILES += grub-editenv
+
+# for grub-pe2elf
+ifeq ($(enable_grub_pe2elf), yes)
+bin_UTILITIES += grub-pe2elf
+endif
+
+grub_pe2elf_SOURCES = util/grub-pe2elf.c util/misc.c
+CLEANFILES += grub-pe2elf
+
+# For grub-mkconfig
+grub-mkconfig: util/grub-mkconfig.in config.status
+       ./config.status --file=$@:$<
+       chmod +x $@
+sbin_SCRIPTS += grub-mkconfig
+CLEANFILES += grub-mkconfig
+
+grub-mkconfig_lib: util/grub-mkconfig_lib.in config.status
+       ./config.status --file=$@:$<
+       chmod +x $@
+lib_DATA += grub-mkconfig_lib
+CLEANFILES += grub-mkconfig_lib
+
+update-grub_lib: util/update-grub_lib.in config.status
+       ./config.status --file=$@:$<
+       chmod +x $@
+lib_DATA += update-grub_lib
+CLEANFILES += update-grub_lib
+
+%: util/grub.d/%.in config.status
+       ./config.status --file=$@:$<
+       chmod +x $@
+grub-mkconfig_SCRIPTS = 00_header 10_linux 10_hurd 10_freebsd 30_os-prober 40_custom
+ifeq ($(host_os), cygwin)
+grub-mkconfig_SCRIPTS += 10_windows
+endif
+
+CLEANFILES += $(grub-mkconfig_SCRIPTS)
+
+grub-mkconfig_DATA += util/grub.d/README
+
+
+# Filing systems.
+pkglib_MODULES += fshelp.mod fat.mod ufs.mod ext2.mod ntfs.mod         \
+       ntfscomp.mod minix.mod hfs.mod jfs.mod iso9660.mod xfs.mod      \
+       affs.mod sfs.mod hfsplus.mod reiserfs.mod cpio.mod tar.mod      \
+       udf.mod afs.mod
+
+# For fshelp.mod.
+fshelp_mod_SOURCES = fs/fshelp.c
+fshelp_mod_CFLAGS = $(COMMON_CFLAGS)
+fshelp_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For fat.mod.
+fat_mod_SOURCES = fs/fat.c
+fat_mod_CFLAGS = $(COMMON_CFLAGS)
+fat_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ufs.mod.
+ufs_mod_SOURCES = fs/ufs.c
+ufs_mod_CFLAGS = $(COMMON_CFLAGS)
+ufs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ext2.mod.
+ext2_mod_SOURCES = fs/ext2.c
+ext2_mod_CFLAGS = $(COMMON_CFLAGS)
+ext2_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ntfs.mod.
+ntfs_mod_SOURCES = fs/ntfs.c
+ntfs_mod_CFLAGS = $(COMMON_CFLAGS)
+ntfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ntfscomp.mod.
+ntfscomp_mod_SOURCES = fs/ntfscomp.c
+ntfscomp_mod_CFLAGS = $(COMMON_CFLAGS)
+ntfscomp_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For minix.mod.
+minix_mod_SOURCES = fs/minix.c
+minix_mod_CFLAGS = $(COMMON_CFLAGS)
+minix_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For hfs.mod.
+hfs_mod_SOURCES = fs/hfs.c
+hfs_mod_CFLAGS = $(COMMON_CFLAGS)
+hfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For jfs.mod.
+jfs_mod_SOURCES = fs/jfs.c
+jfs_mod_CFLAGS = $(COMMON_CFLAGS)
+jfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For iso9660.mod.
+iso9660_mod_SOURCES = fs/iso9660.c
+iso9660_mod_CFLAGS = $(COMMON_CFLAGS)
+iso9660_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For xfs.mod.
+xfs_mod_SOURCES = fs/xfs.c
+xfs_mod_CFLAGS = $(COMMON_CFLAGS)
+xfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For affs.mod.
+affs_mod_SOURCES = fs/affs.c
+affs_mod_CFLAGS = $(COMMON_CFLAGS)
+affs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For sfs.mod.
+sfs_mod_SOURCES = fs/sfs.c
+sfs_mod_CFLAGS = $(COMMON_CFLAGS)
+sfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For hfsplus.mod.
+hfsplus_mod_SOURCES = fs/hfsplus.c
+hfsplus_mod_CFLAGS = $(COMMON_CFLAGS)
+hfsplus_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reiserfs.mod.
+reiserfs_mod_SOURCES = fs/reiserfs.c
+reiserfs_mod_CFLAGS = $(COMMON_CFLAGS)
+reiserfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For cpio.mod.
+cpio_mod_SOURCES = fs/cpio.c
+cpio_mod_CFLAGS = $(COMMON_CFLAGS)
+cpio_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For tar.mod.
+tar_mod_SOURCES = fs/cpio.c
+tar_mod_CFLAGS = $(COMMON_CFLAGS) -DMODE_USTAR
+tar_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For udf.mod.
+udf_mod_SOURCES = fs/udf.c
+udf_mod_CFLAGS = $(COMMON_CFLAGS)
+udf_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For afs.mod.
+afs_mod_SOURCES = fs/afs.c
+afs_mod_CFLAGS = $(COMMON_CFLAGS)
+afs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# Partition maps.
+pkglib_MODULES += amiga.mod apple.mod pc.mod sun.mod acorn.mod gpt.mod
+
+# For amiga.mod
+amiga_mod_SOURCES = partmap/amiga.c
+amiga_mod_CFLAGS = $(COMMON_CFLAGS)
+amiga_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For apple.mod
+apple_mod_SOURCES = partmap/apple.c
+apple_mod_CFLAGS = $(COMMON_CFLAGS)
+apple_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pc.mod
+pc_mod_SOURCES = partmap/pc.c
+pc_mod_CFLAGS = $(COMMON_CFLAGS)
+pc_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For sun.mod
+sun_mod_SOURCES = partmap/sun.c
+sun_mod_CFLAGS = $(COMMON_CFLAGS)
+sun_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For acorn.mod
+acorn_mod_SOURCES = partmap/acorn.c
+acorn_mod_CFLAGS = $(COMMON_CFLAGS)
+acorn_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For gpt.mod
+gpt_mod_SOURCES = partmap/gpt.c
+gpt_mod_CFLAGS = $(COMMON_CFLAGS)
+gpt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# Special disk structures and generic drivers
+
+pkglib_MODULES += raid.mod raid5rec.mod raid6rec.mod mdraid.mod dm_nv.mod \
+       lvm.mod scsi.mod
+
+# For raid.mod
+raid_mod_SOURCES = disk/raid.c
+raid_mod_CFLAGS = $(COMMON_CFLAGS)
+raid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For raid5rec.mod
+raid5rec_mod_SOURCES = disk/raid5_recover.c
+raid5rec_mod_CFLAGS = $(COMMON_CFLAGS)
+raid5rec_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For raid6rec.mod
+raid6rec_mod_SOURCES = disk/raid6_recover.c
+raid6rec_mod_CFLAGS = $(COMMON_CFLAGS)
+raid6rec_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For mdraid.mod
+mdraid_mod_SOURCES = disk/mdraid_linux.c
+mdraid_mod_CFLAGS = $(COMMON_CFLAGS)
+mdraid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For dm_nv.mod
+dm_nv_mod_SOURCES = disk/dmraid_nvidia.c
+dm_nv_mod_CFLAGS = $(COMMON_CFLAGS)
+dm_nv_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lvm.mod
+lvm_mod_SOURCES = disk/lvm.c
+lvm_mod_CFLAGS = $(COMMON_CFLAGS)
+lvm_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For scsi.mod
+scsi_mod_SOURCES = disk/scsi.c
+scsi_mod_CFLAGS = $(COMMON_CFLAGS)
+scsi_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# Commands.
+pkglib_MODULES += hello.mod boot.mod terminal.mod ls.mod       \
+       cmp.mod cat.mod help.mod search.mod                                     \
+       loopback.mod fs_uuid.mod configfile.mod echo.mod        \
+       terminfo.mod test.mod blocklist.mod hexdump.mod         \
+       read.mod sleep.mod loadenv.mod crc.mod
+
+# For hello.mod.
+hello_mod_SOURCES = hello/hello.c
+hello_mod_CFLAGS = $(COMMON_CFLAGS)
+hello_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For boot.mod.
+boot_mod_SOURCES = commands/boot.c
+boot_mod_CFLAGS = $(COMMON_CFLAGS)
+boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For terminal.mod.
+terminal_mod_SOURCES = commands/terminal.c
+terminal_mod_CFLAGS = $(COMMON_CFLAGS)
+terminal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ls.mod.
+ls_mod_SOURCES = commands/ls.c
+ls_mod_CFLAGS = $(COMMON_CFLAGS)
+ls_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For cmp.mod.
+cmp_mod_SOURCES = commands/cmp.c
+cmp_mod_CFLAGS = $(COMMON_CFLAGS)
+cmp_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For cat.mod.
+cat_mod_SOURCES = commands/cat.c
+cat_mod_CFLAGS = $(COMMON_CFLAGS)
+cat_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For echo.mod
+echo_mod_SOURCES = commands/echo.c
+echo_mod_CFLAGS = $(COMMON_CFLAGS)
+echo_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For help.mod.
+help_mod_SOURCES = commands/help.c
+help_mod_CFLAGS = $(COMMON_CFLAGS)
+help_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For search.mod.
+search_mod_SOURCES = commands/search.c
+search_mod_CFLAGS = $(COMMON_CFLAGS)
+search_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For test.mod.
+test_mod_SOURCES = commands/test.c
+test_mod_CFLAGS = $(COMMON_CFLAGS)
+test_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For loopback.mod
+loopback_mod_SOURCES = disk/loopback.c
+loopback_mod_CFLAGS = $(COMMON_CFLAGS)
+loopback_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For fs_uuid.mod
+fs_uuid_mod_SOURCES = disk/fs_uuid.c
+fs_uuid_mod_CFLAGS = $(COMMON_CFLAGS)
+fs_uuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For configfile.mod
+configfile_mod_SOURCES = commands/configfile.c
+configfile_mod_CFLAGS = $(COMMON_CFLAGS)
+configfile_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For terminfo.mod.
+terminfo_mod_SOURCES = term/terminfo.c term/tparm.c
+terminfo_mod_CFLAGS = $(COMMON_CFLAGS)
+terminfo_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For blocklist.mod.
+blocklist_mod_SOURCES = commands/blocklist.c
+blocklist_mod_CFLAGS = $(COMMON_CFLAGS)
+blocklist_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For hexdump.mod.
+hexdump_mod_SOURCES = commands/hexdump.c lib/hexdump.c
+hexdump_mod_CFLAGS = $(COMMON_CFLAGS)
+hexdump_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For read.mod.
+read_mod_SOURCES = commands/read.c
+read_mod_CFLAGS = $(COMMON_CFLAGS)
+read_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For sleep.mod.
+sleep_mod_SOURCES = commands/sleep.c
+sleep_mod_CFLAGS = $(COMMON_CFLAGS)
+sleep_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For loadenv.mod.
+loadenv_mod_SOURCES = commands/loadenv.c lib/envblk.c
+loadenv_mod_CFLAGS = $(COMMON_CFLAGS)
+loadenv_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For crc.mod.
+crc_mod_SOURCES = commands/crc.c lib/crc.c
+crc_mod_CFLAGS = $(COMMON_CFLAGS)
+crc_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# Common Video Subsystem specific modules.
+pkglib_MODULES += video.mod videotest.mod bitmap.mod tga.mod jpeg.mod  \
+       png.mod font.mod gfxterm.mod
+
+# For video.mod.
+video_mod_SOURCES = video/video.c
+video_mod_CFLAGS = $(COMMON_CFLAGS)
+video_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For videotest.mod.
+videotest_mod_SOURCES = commands/videotest.c
+videotest_mod_CFLAGS = $(COMMON_CFLAGS)
+videotest_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For bitmap.mod
+bitmap_mod_SOURCES = video/bitmap.c
+bitmap_mod_CFLAGS = $(COMMON_CFLAGS)
+bitmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For tga.mod
+tga_mod_SOURCES = video/readers/tga.c
+tga_mod_CFLAGS = $(COMMON_CFLAGS)
+tga_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For jpeg.mod.
+jpeg_mod_SOURCES = video/readers/jpeg.c
+jpeg_mod_CFLAGS = $(COMMON_CFLAGS)
+jpeg_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For png.mod.
+png_mod_SOURCES = video/readers/png.c
+png_mod_CFLAGS = $(COMMON_CFLAGS)
+png_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For font.mod.
+font_mod_SOURCES = font/font_cmd.c font/font.c
+font_mod_CFLAGS = $(COMMON_CFLAGS)
+font_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For gfxterm.mod.
+gfxterm_mod_SOURCES = term/gfxterm.c
+gfxterm_mod_CFLAGS = $(COMMON_CFLAGS)
+gfxterm_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# Misc.
+pkglib_MODULES += gzio.mod bufio.mod elf.mod
+
+# For elf.mod.
+elf_mod_SOURCES = kern/elf.c
+elf_mod_CFLAGS = $(COMMON_CFLAGS)
+elf_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For gzio.mod.
+gzio_mod_SOURCES = io/gzio.c
+gzio_mod_CFLAGS = $(COMMON_CFLAGS)
+gzio_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For bufio.mod.
+bufio_mod_SOURCES = io/bufio.c
+bufio_mod_CFLAGS = $(COMMON_CFLAGS)
+bufio_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/conf/i386-coreboot.mk b/conf/i386-coreboot.mk
new file mode 100644 (file)
index 0000000..c10d16f
--- /dev/null
@@ -0,0 +1,2062 @@
+# -*- makefile -*-
+# Generated by genmk.rb, please don't edit!
+
+COMMON_ASFLAGS = -nostdinc -fno-builtin -m32
+COMMON_CFLAGS = -fno-builtin -mrtd -mregparm=3 -m32
+COMMON_LDFLAGS = -m32 -nostdlib
+
+# Used by various components.  These rules need to precede them.
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Images.
+pkglib_PROGRAMS = kernel.elf
+
+# For kernel.elf.
+kernel_elf_SOURCES = kern/i386/coreboot/startup.S \
+       kern/i386/coreboot/init.c \
+       kern/i386/multiboot_mmap.c \
+       kern/main.c kern/device.c \
+       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
+       kern/time.c \
+       kern/i386/dl.c kern/parser.c kern/partition.c \
+       kern/i386/tsc.c kern/i386/pit.c \
+       kern/generic/rtc_get_time_ms.c \
+       kern/generic/millisleep.c \
+       kern/env.c \
+       term/i386/pc/vga_text.c term/i386/vga_common.c \
+       term/i386/pc/at_keyboard.c \
+       symlist.c
+CLEANFILES += kernel.elf kernel_elf-kern_i386_coreboot_startup.o kernel_elf-kern_i386_coreboot_init.o kernel_elf-kern_i386_multiboot_mmap.o kernel_elf-kern_main.o kernel_elf-kern_device.o kernel_elf-kern_disk.o kernel_elf-kern_dl.o kernel_elf-kern_file.o kernel_elf-kern_fs.o kernel_elf-kern_err.o kernel_elf-kern_misc.o kernel_elf-kern_mm.o kernel_elf-kern_loader.o kernel_elf-kern_rescue.o kernel_elf-kern_term.o kernel_elf-kern_time.o kernel_elf-kern_i386_dl.o kernel_elf-kern_parser.o kernel_elf-kern_partition.o kernel_elf-kern_i386_tsc.o kernel_elf-kern_i386_pit.o kernel_elf-kern_generic_rtc_get_time_ms.o kernel_elf-kern_generic_millisleep.o kernel_elf-kern_env.o kernel_elf-term_i386_pc_vga_text.o kernel_elf-term_i386_vga_common.o kernel_elf-term_i386_pc_at_keyboard.o kernel_elf-symlist.o
+MOSTLYCLEANFILES += kernel_elf-kern_i386_coreboot_startup.d kernel_elf-kern_i386_coreboot_init.d kernel_elf-kern_i386_multiboot_mmap.d kernel_elf-kern_main.d kernel_elf-kern_device.d kernel_elf-kern_disk.d kernel_elf-kern_dl.d kernel_elf-kern_file.d kernel_elf-kern_fs.d kernel_elf-kern_err.d kernel_elf-kern_misc.d kernel_elf-kern_mm.d kernel_elf-kern_loader.d kernel_elf-kern_rescue.d kernel_elf-kern_term.d kernel_elf-kern_time.d kernel_elf-kern_i386_dl.d kernel_elf-kern_parser.d kernel_elf-kern_partition.d kernel_elf-kern_i386_tsc.d kernel_elf-kern_i386_pit.d kernel_elf-kern_generic_rtc_get_time_ms.d kernel_elf-kern_generic_millisleep.d kernel_elf-kern_env.d kernel_elf-term_i386_pc_vga_text.d kernel_elf-term_i386_vga_common.d kernel_elf-term_i386_pc_at_keyboard.d kernel_elf-symlist.d
+
+kernel.elf: $(kernel_elf_DEPENDENCIES) kernel_elf-kern_i386_coreboot_startup.o kernel_elf-kern_i386_coreboot_init.o kernel_elf-kern_i386_multiboot_mmap.o kernel_elf-kern_main.o kernel_elf-kern_device.o kernel_elf-kern_disk.o kernel_elf-kern_dl.o kernel_elf-kern_file.o kernel_elf-kern_fs.o kernel_elf-kern_err.o kernel_elf-kern_misc.o kernel_elf-kern_mm.o kernel_elf-kern_loader.o kernel_elf-kern_rescue.o kernel_elf-kern_term.o kernel_elf-kern_time.o kernel_elf-kern_i386_dl.o kernel_elf-kern_parser.o kernel_elf-kern_partition.o kernel_elf-kern_i386_tsc.o kernel_elf-kern_i386_pit.o kernel_elf-kern_generic_rtc_get_time_ms.o kernel_elf-kern_generic_millisleep.o kernel_elf-kern_env.o kernel_elf-term_i386_pc_vga_text.o kernel_elf-term_i386_vga_common.o kernel_elf-term_i386_pc_at_keyboard.o kernel_elf-symlist.o
+       $(TARGET_CC) -o $@ kernel_elf-kern_i386_coreboot_startup.o kernel_elf-kern_i386_coreboot_init.o kernel_elf-kern_i386_multiboot_mmap.o kernel_elf-kern_main.o kernel_elf-kern_device.o kernel_elf-kern_disk.o kernel_elf-kern_dl.o kernel_elf-kern_file.o kernel_elf-kern_fs.o kernel_elf-kern_err.o kernel_elf-kern_misc.o kernel_elf-kern_mm.o kernel_elf-kern_loader.o kernel_elf-kern_rescue.o kernel_elf-kern_term.o kernel_elf-kern_time.o kernel_elf-kern_i386_dl.o kernel_elf-kern_parser.o kernel_elf-kern_partition.o kernel_elf-kern_i386_tsc.o kernel_elf-kern_i386_pit.o kernel_elf-kern_generic_rtc_get_time_ms.o kernel_elf-kern_generic_millisleep.o kernel_elf-kern_env.o kernel_elf-term_i386_pc_vga_text.o kernel_elf-term_i386_vga_common.o kernel_elf-term_i386_pc_at_keyboard.o kernel_elf-symlist.o $(TARGET_LDFLAGS) $(kernel_elf_LDFLAGS)
+
+kernel_elf-kern_i386_coreboot_startup.o: kern/i386/coreboot/startup.S $(kern/i386/coreboot/startup.S_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386/coreboot -I$(srcdir)/kern/i386/coreboot $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_i386_coreboot_startup.d
+
+kernel_elf-kern_i386_coreboot_init.o: kern/i386/coreboot/init.c $(kern/i386/coreboot/init.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386/coreboot -I$(srcdir)/kern/i386/coreboot $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_i386_coreboot_init.d
+
+kernel_elf-kern_i386_multiboot_mmap.o: kern/i386/multiboot_mmap.c $(kern/i386/multiboot_mmap.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_i386_multiboot_mmap.d
+
+kernel_elf-kern_main.o: kern/main.c $(kern/main.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_main.d
+
+kernel_elf-kern_device.o: kern/device.c $(kern/device.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_device.d
+
+kernel_elf-kern_disk.o: kern/disk.c $(kern/disk.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_disk.d
+
+kernel_elf-kern_dl.o: kern/dl.c $(kern/dl.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_dl.d
+
+kernel_elf-kern_file.o: kern/file.c $(kern/file.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_file.d
+
+kernel_elf-kern_fs.o: kern/fs.c $(kern/fs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_fs.d
+
+kernel_elf-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_err.d
+
+kernel_elf-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_misc.d
+
+kernel_elf-kern_mm.o: kern/mm.c $(kern/mm.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_mm.d
+
+kernel_elf-kern_loader.o: kern/loader.c $(kern/loader.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_loader.d
+
+kernel_elf-kern_rescue.o: kern/rescue.c $(kern/rescue.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_rescue.d
+
+kernel_elf-kern_term.o: kern/term.c $(kern/term.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_term.d
+
+kernel_elf-kern_time.o: kern/time.c $(kern/time.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_time.d
+
+kernel_elf-kern_i386_dl.o: kern/i386/dl.c $(kern/i386/dl.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_i386_dl.d
+
+kernel_elf-kern_parser.o: kern/parser.c $(kern/parser.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_parser.d
+
+kernel_elf-kern_partition.o: kern/partition.c $(kern/partition.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_partition.d
+
+kernel_elf-kern_i386_tsc.o: kern/i386/tsc.c $(kern/i386/tsc.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_i386_tsc.d
+
+kernel_elf-kern_i386_pit.o: kern/i386/pit.c $(kern/i386/pit.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_i386_pit.d
+
+kernel_elf-kern_generic_rtc_get_time_ms.o: kern/generic/rtc_get_time_ms.c $(kern/generic/rtc_get_time_ms.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_generic_rtc_get_time_ms.d
+
+kernel_elf-kern_generic_millisleep.o: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_generic_millisleep.d
+
+kernel_elf-kern_env.o: kern/env.c $(kern/env.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_env.d
+
+kernel_elf-term_i386_pc_vga_text.o: term/i386/pc/vga_text.c $(term/i386/pc/vga_text.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-term_i386_pc_vga_text.d
+
+kernel_elf-term_i386_vga_common.o: term/i386/vga_common.c $(term/i386/vga_common.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/i386 -I$(srcdir)/term/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-term_i386_vga_common.d
+
+kernel_elf-term_i386_pc_at_keyboard.o: term/i386/pc/at_keyboard.c $(term/i386/pc/at_keyboard.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-term_i386_pc_at_keyboard.d
+
+kernel_elf-symlist.o: symlist.c $(symlist.c_DEPENDENCIES)
+       $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-symlist.d
+
+kernel_elf_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
+       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
+       partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
+       machine/boot.h machine/console.h machine/init.h \
+       machine/memory.h machine/loader.h
+kernel_elf_CFLAGS = $(COMMON_CFLAGS)
+kernel_elf_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_elf_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x8200,-Bstatic
+
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+symlist.c: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h gensymlist.sh
+       /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h genkernsyms.sh
+       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+# Utilities.
+sbin_UTILITIES = grub-mkdevicemap
+ifeq ($(enable_grub_emu), yes)
+sbin_UTILITIES += grub-emu
+endif
+
+# For grub-mkdevicemap.
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+CLEANFILES += grub-mkdevicemap$(EXEEXT) grub_mkdevicemap-util_grub_mkdevicemap.o grub_mkdevicemap-util_misc.o
+MOSTLYCLEANFILES += grub_mkdevicemap-util_grub_mkdevicemap.d grub_mkdevicemap-util_misc.d
+
+grub-mkdevicemap: $(grub_mkdevicemap_DEPENDENCIES) grub_mkdevicemap-util_grub_mkdevicemap.o grub_mkdevicemap-util_misc.o
+       $(CC) -o $@ grub_mkdevicemap-util_grub_mkdevicemap.o grub_mkdevicemap-util_misc.o $(LDFLAGS) $(grub_mkdevicemap_LDFLAGS)
+
+grub_mkdevicemap-util_grub_mkdevicemap.o: util/grub-mkdevicemap.c $(util/grub-mkdevicemap.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkdevicemap_CFLAGS) -MD -c -o $@ $<
+-include grub_mkdevicemap-util_grub_mkdevicemap.d
+
+grub_mkdevicemap-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkdevicemap_CFLAGS) -MD -c -o $@ $<
+-include grub_mkdevicemap-util_misc.d
+
+
+# For grub-emu.
+util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
+grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c       \
+       commands/configfile.c commands/echo.c commands/help.c           \
+       commands/terminal.c commands/ls.c commands/test.c               \
+       commands/search.c commands/blocklist.c commands/hexdump.c       \
+       lib/hexdump.c commands/i386/cpuid.c                             \
+       disk/host.c disk/loopback.c                                     \
+       \
+       fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c  fs/hfs.c                \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c          \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c                  \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                             \
+       \
+       fs/fshelp.c                                                     \
+       io/gzio.c                                                       \
+       kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c       \
+       kern/err.c                                                      \
+       normal/execute.c kern/file.c kern/fs.c normal/lexer.c           \
+       kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
+       grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
+       normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
+       normal/completion.c normal/main.c normal/menu_text.c            \
+       normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
+       normal/misc.c normal/script.c                                   \
+       normal/color.c                                                  \
+       partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
+       partmap/acorn.c partmap/gpt.c                                   \
+       util/console.c util/hostfs.c util/grub-emu.c util/misc.c        \
+       util/hostdisk.c util/getroot.c                                  \
+       util/i386/pc/misc.c                                             \
+       \
+       disk/raid.c disk/raid5_recover.c disk/raid6_recover.c           \
+       disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c             \
+       grub_emu_init.c
+CLEANFILES += grub-emu$(EXEEXT) grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_echo.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_i386_cpuid.o grub_emu-disk_host.o grub_emu-disk_loopback.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_fat.o grub_emu-fs_ext2.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-fs_fshelp.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_main.o grub_emu-normal_menu_text.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-normal_color.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-partmap_gpt.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_i386_pc_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_emu_init.o
+MOSTLYCLEANFILES += grub_emu-commands_boot.d grub_emu-commands_cat.d grub_emu-commands_cmp.d grub_emu-commands_configfile.d grub_emu-commands_echo.d grub_emu-commands_help.d grub_emu-commands_terminal.d grub_emu-commands_ls.d grub_emu-commands_test.d grub_emu-commands_search.d grub_emu-commands_blocklist.d grub_emu-commands_hexdump.d grub_emu-lib_hexdump.d grub_emu-commands_i386_cpuid.d grub_emu-disk_host.d grub_emu-disk_loopback.d grub_emu-fs_affs.d grub_emu-fs_cpio.d grub_emu-fs_fat.d grub_emu-fs_ext2.d grub_emu-fs_hfs.d grub_emu-fs_hfsplus.d grub_emu-fs_iso9660.d grub_emu-fs_udf.d grub_emu-fs_jfs.d grub_emu-fs_minix.d grub_emu-fs_ntfs.d grub_emu-fs_ntfscomp.d grub_emu-fs_reiserfs.d grub_emu-fs_sfs.d grub_emu-fs_ufs.d grub_emu-fs_xfs.d grub_emu-fs_afs.d grub_emu-fs_tar.d grub_emu-fs_fshelp.d grub_emu-io_gzio.d grub_emu-kern_device.d grub_emu-kern_disk.d grub_emu-kern_dl.d grub_emu-kern_elf.d grub_emu-kern_env.d grub_emu-kern_err.d grub_emu-normal_execute.d grub_emu-kern_file.d grub_emu-kern_fs.d grub_emu-normal_lexer.d grub_emu-kern_loader.d grub_emu-kern_main.d grub_emu-kern_misc.d grub_emu-kern_parser.d grub_emu-grub_script_tab.d grub_emu-kern_partition.d grub_emu-kern_rescue.d grub_emu-kern_term.d grub_emu-normal_arg.d grub_emu-normal_cmdline.d grub_emu-normal_command.d grub_emu-normal_function.d grub_emu-normal_completion.d grub_emu-normal_main.d grub_emu-normal_menu_text.d grub_emu-normal_menu.d grub_emu-normal_menu_entry.d grub_emu-normal_menu_viewer.d grub_emu-normal_misc.d grub_emu-normal_script.d grub_emu-normal_color.d grub_emu-partmap_amiga.d grub_emu-partmap_apple.d grub_emu-partmap_pc.d grub_emu-partmap_sun.d grub_emu-partmap_acorn.d grub_emu-partmap_gpt.d grub_emu-util_console.d grub_emu-util_hostfs.d grub_emu-util_grub_emu.d grub_emu-util_misc.d grub_emu-util_hostdisk.d grub_emu-util_getroot.d grub_emu-util_i386_pc_misc.d grub_emu-disk_raid.d grub_emu-disk_raid5_recover.d grub_emu-disk_raid6_recover.d grub_emu-disk_mdraid_linux.d grub_emu-disk_dmraid_nvidia.d grub_emu-disk_lvm.d grub_emu-grub_emu_init.d
+
+grub-emu: $(grub_emu_DEPENDENCIES) grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_echo.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_i386_cpuid.o grub_emu-disk_host.o grub_emu-disk_loopback.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_fat.o grub_emu-fs_ext2.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-fs_fshelp.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_main.o grub_emu-normal_menu_text.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-normal_color.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-partmap_gpt.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_i386_pc_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_emu_init.o
+       $(CC) -o $@ grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_echo.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_i386_cpuid.o grub_emu-disk_host.o grub_emu-disk_loopback.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_fat.o grub_emu-fs_ext2.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-fs_fshelp.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_main.o grub_emu-normal_menu_text.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-normal_color.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-partmap_gpt.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_i386_pc_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_emu_init.o $(LDFLAGS) $(grub_emu_LDFLAGS)
+
+grub_emu-commands_boot.o: commands/boot.c $(commands/boot.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_boot.d
+
+grub_emu-commands_cat.o: commands/cat.c $(commands/cat.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_cat.d
+
+grub_emu-commands_cmp.o: commands/cmp.c $(commands/cmp.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_cmp.d
+
+grub_emu-commands_configfile.o: commands/configfile.c $(commands/configfile.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_configfile.d
+
+grub_emu-commands_echo.o: commands/echo.c $(commands/echo.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_echo.d
+
+grub_emu-commands_help.o: commands/help.c $(commands/help.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_help.d
+
+grub_emu-commands_terminal.o: commands/terminal.c $(commands/terminal.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_terminal.d
+
+grub_emu-commands_ls.o: commands/ls.c $(commands/ls.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_ls.d
+
+grub_emu-commands_test.o: commands/test.c $(commands/test.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_test.d
+
+grub_emu-commands_search.o: commands/search.c $(commands/search.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_search.d
+
+grub_emu-commands_blocklist.o: commands/blocklist.c $(commands/blocklist.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_blocklist.d
+
+grub_emu-commands_hexdump.o: commands/hexdump.c $(commands/hexdump.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_hexdump.d
+
+grub_emu-lib_hexdump.o: lib/hexdump.c $(lib/hexdump.c_DEPENDENCIES)
+       $(CC) -Ilib -I$(srcdir)/lib $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-lib_hexdump.d
+
+grub_emu-commands_i386_cpuid.o: commands/i386/cpuid.c $(commands/i386/cpuid.c_DEPENDENCIES)
+       $(CC) -Icommands/i386 -I$(srcdir)/commands/i386 $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_i386_cpuid.d
+
+grub_emu-disk_host.o: disk/host.c $(disk/host.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_host.d
+
+grub_emu-disk_loopback.o: disk/loopback.c $(disk/loopback.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_loopback.d
+
+grub_emu-fs_affs.o: fs/affs.c $(fs/affs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_affs.d
+
+grub_emu-fs_cpio.o: fs/cpio.c $(fs/cpio.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_cpio.d
+
+grub_emu-fs_fat.o: fs/fat.c $(fs/fat.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_fat.d
+
+grub_emu-fs_ext2.o: fs/ext2.c $(fs/ext2.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ext2.d
+
+grub_emu-fs_hfs.o: fs/hfs.c $(fs/hfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_hfs.d
+
+grub_emu-fs_hfsplus.o: fs/hfsplus.c $(fs/hfsplus.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_hfsplus.d
+
+grub_emu-fs_iso9660.o: fs/iso9660.c $(fs/iso9660.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_iso9660.d
+
+grub_emu-fs_udf.o: fs/udf.c $(fs/udf.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_udf.d
+
+grub_emu-fs_jfs.o: fs/jfs.c $(fs/jfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_jfs.d
+
+grub_emu-fs_minix.o: fs/minix.c $(fs/minix.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_minix.d
+
+grub_emu-fs_ntfs.o: fs/ntfs.c $(fs/ntfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ntfs.d
+
+grub_emu-fs_ntfscomp.o: fs/ntfscomp.c $(fs/ntfscomp.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ntfscomp.d
+
+grub_emu-fs_reiserfs.o: fs/reiserfs.c $(fs/reiserfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_reiserfs.d
+
+grub_emu-fs_sfs.o: fs/sfs.c $(fs/sfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_sfs.d
+
+grub_emu-fs_ufs.o: fs/ufs.c $(fs/ufs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ufs.d
+
+grub_emu-fs_xfs.o: fs/xfs.c $(fs/xfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_xfs.d
+
+grub_emu-fs_afs.o: fs/afs.c $(fs/afs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_afs.d
+
+grub_emu-fs_tar.o: fs/tar.c $(fs/tar.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_tar.d
+
+grub_emu-fs_fshelp.o: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_fshelp.d
+
+grub_emu-io_gzio.o: io/gzio.c $(io/gzio.c_DEPENDENCIES)
+       $(CC) -Iio -I$(srcdir)/io $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-io_gzio.d
+
+grub_emu-kern_device.o: kern/device.c $(kern/device.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_device.d
+
+grub_emu-kern_disk.o: kern/disk.c $(kern/disk.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_disk.d
+
+grub_emu-kern_dl.o: kern/dl.c $(kern/dl.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_dl.d
+
+grub_emu-kern_elf.o: kern/elf.c $(kern/elf.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_elf.d
+
+grub_emu-kern_env.o: kern/env.c $(kern/env.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_env.d
+
+grub_emu-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_err.d
+
+grub_emu-normal_execute.o: normal/execute.c $(normal/execute.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_execute.d
+
+grub_emu-kern_file.o: kern/file.c $(kern/file.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_file.d
+
+grub_emu-kern_fs.o: kern/fs.c $(kern/fs.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_fs.d
+
+grub_emu-normal_lexer.o: normal/lexer.c $(normal/lexer.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_lexer.d
+
+grub_emu-kern_loader.o: kern/loader.c $(kern/loader.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_loader.d
+
+grub_emu-kern_main.o: kern/main.c $(kern/main.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_main.d
+
+grub_emu-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_misc.d
+
+grub_emu-kern_parser.o: kern/parser.c $(kern/parser.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_parser.d
+
+grub_emu-grub_script_tab.o: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES)
+       $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-grub_script_tab.d
+
+grub_emu-kern_partition.o: kern/partition.c $(kern/partition.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_partition.d
+
+grub_emu-kern_rescue.o: kern/rescue.c $(kern/rescue.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_rescue.d
+
+grub_emu-kern_term.o: kern/term.c $(kern/term.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_term.d
+
+grub_emu-normal_arg.o: normal/arg.c $(normal/arg.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_arg.d
+
+grub_emu-normal_cmdline.o: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_cmdline.d
+
+grub_emu-normal_command.o: normal/command.c $(normal/command.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_command.d
+
+grub_emu-normal_function.o: normal/function.c $(normal/function.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_function.d
+
+grub_emu-normal_completion.o: normal/completion.c $(normal/completion.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_completion.d
+
+grub_emu-normal_main.o: normal/main.c $(normal/main.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_main.d
+
+grub_emu-normal_menu_text.o: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu_text.d
+
+grub_emu-normal_menu.o: normal/menu.c $(normal/menu.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu.d
+
+grub_emu-normal_menu_entry.o: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu_entry.d
+
+grub_emu-normal_menu_viewer.o: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu_viewer.d
+
+grub_emu-normal_misc.o: normal/misc.c $(normal/misc.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_misc.d
+
+grub_emu-normal_script.o: normal/script.c $(normal/script.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_script.d
+
+grub_emu-normal_color.o: normal/color.c $(normal/color.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_color.d
+
+grub_emu-partmap_amiga.o: partmap/amiga.c $(partmap/amiga.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_amiga.d
+
+grub_emu-partmap_apple.o: partmap/apple.c $(partmap/apple.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_apple.d
+
+grub_emu-partmap_pc.o: partmap/pc.c $(partmap/pc.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_pc.d
+
+grub_emu-partmap_sun.o: partmap/sun.c $(partmap/sun.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_sun.d
+
+grub_emu-partmap_acorn.o: partmap/acorn.c $(partmap/acorn.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_acorn.d
+
+grub_emu-partmap_gpt.o: partmap/gpt.c $(partmap/gpt.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_gpt.d
+
+grub_emu-util_console.o: util/console.c $(util/console.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_console.d
+
+grub_emu-util_hostfs.o: util/hostfs.c $(util/hostfs.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_hostfs.d
+
+grub_emu-util_grub_emu.o: util/grub-emu.c $(util/grub-emu.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_grub_emu.d
+
+grub_emu-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_misc.d
+
+grub_emu-util_hostdisk.o: util/hostdisk.c $(util/hostdisk.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_hostdisk.d
+
+grub_emu-util_getroot.o: util/getroot.c $(util/getroot.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_getroot.d
+
+grub_emu-util_i386_pc_misc.o: util/i386/pc/misc.c $(util/i386/pc/misc.c_DEPENDENCIES)
+       $(CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_i386_pc_misc.d
+
+grub_emu-disk_raid.o: disk/raid.c $(disk/raid.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_raid.d
+
+grub_emu-disk_raid5_recover.o: disk/raid5_recover.c $(disk/raid5_recover.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_raid5_recover.d
+
+grub_emu-disk_raid6_recover.o: disk/raid6_recover.c $(disk/raid6_recover.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_raid6_recover.d
+
+grub_emu-disk_mdraid_linux.o: disk/mdraid_linux.c $(disk/mdraid_linux.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_mdraid_linux.d
+
+grub_emu-disk_dmraid_nvidia.o: disk/dmraid_nvidia.c $(disk/dmraid_nvidia.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_dmraid_nvidia.d
+
+grub_emu-disk_lvm.o: disk/lvm.c $(disk/lvm.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_lvm.d
+
+grub_emu-grub_emu_init.o: grub_emu_init.c $(grub_emu_init.c_DEPENDENCIES)
+       $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-grub_emu_init.d
+
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+sbin_SCRIPTS += grub-install
+grub_install_SOURCES = util/i386/pc/grub-install.in
+CLEANFILES += grub-install
+
+grub-install: util/i386/pc/grub-install.in $(util/i386/pc/grub-install.in_DEPENDENCIES) config.status
+       ./config.status --file=grub-install:util/i386/pc/grub-install.in
+       chmod +x $@
+
+
+# Modules.
+pkglib_MODULES = _linux.mod linux.mod normal.mod       \
+       _multiboot.mod multiboot.mod aout.mod           \
+       play.mod serial.mod ata.mod                     \
+       memdisk.mod pci.mod lspci.mod reboot.mod        \
+       halt.mod datetime.mod date.mod datehook.mod     \
+       lsmmap.mod
+
+# For _linux.mod.
+_linux_mod_SOURCES = loader/i386/linux.c
+CLEANFILES += _linux.mod mod-_linux.o mod-_linux.c pre-_linux.o _linux_mod-loader_i386_linux.o und-_linux.lst
+ifneq ($(_linux_mod_EXPORTS),no)
+CLEANFILES += def-_linux.lst
+DEFSYMFILES += def-_linux.lst
+endif
+MOSTLYCLEANFILES += _linux_mod-loader_i386_linux.d
+UNDSYMFILES += und-_linux.lst
+
+_linux.mod: pre-_linux.o mod-_linux.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(_linux_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-_linux.o mod-_linux.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-_linux.o: $(_linux_mod_DEPENDENCIES) _linux_mod-loader_i386_linux.o
+       -rm -f $@
+       $(TARGET_CC) $(_linux_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ _linux_mod-loader_i386_linux.o
+
+mod-_linux.o: mod-_linux.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -c -o $@ $<
+
+mod-_linux.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '_linux' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(_linux_mod_EXPORTS),no)
+def-_linux.lst: pre-_linux.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _linux/' > $@
+endif
+
+und-_linux.lst: pre-_linux.o
+       echo '_linux' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+_linux_mod-loader_i386_linux.o: loader/i386/linux.c $(loader/i386/linux.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/i386 -I$(srcdir)/loader/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -MD -c -o $@ $<
+-include _linux_mod-loader_i386_linux.d
+
+CLEANFILES += cmd-_linux_mod-loader_i386_linux.lst fs-_linux_mod-loader_i386_linux.lst partmap-_linux_mod-loader_i386_linux.lst
+COMMANDFILES += cmd-_linux_mod-loader_i386_linux.lst
+FSFILES += fs-_linux_mod-loader_i386_linux.lst
+PARTMAPFILES += partmap-_linux_mod-loader_i386_linux.lst
+
+cmd-_linux_mod-loader_i386_linux.lst: loader/i386/linux.c $(loader/i386/linux.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386 -I$(srcdir)/loader/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh _linux > $@ || (rm -f $@; exit 1)
+
+fs-_linux_mod-loader_i386_linux.lst: loader/i386/linux.c $(loader/i386/linux.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386 -I$(srcdir)/loader/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh _linux > $@ || (rm -f $@; exit 1)
+
+partmap-_linux_mod-loader_i386_linux.lst: loader/i386/linux.c $(loader/i386/linux.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386 -I$(srcdir)/loader/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh _linux > $@ || (rm -f $@; exit 1)
+
+
+_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/linux_normal.c
+CLEANFILES += linux.mod mod-linux.o mod-linux.c pre-linux.o linux_mod-loader_linux_normal.o und-linux.lst
+ifneq ($(linux_mod_EXPORTS),no)
+CLEANFILES += def-linux.lst
+DEFSYMFILES += def-linux.lst
+endif
+MOSTLYCLEANFILES += linux_mod-loader_linux_normal.d
+UNDSYMFILES += und-linux.lst
+
+linux.mod: pre-linux.o mod-linux.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(linux_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-linux.o mod-linux.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-linux.o: $(linux_mod_DEPENDENCIES) linux_mod-loader_linux_normal.o
+       -rm -f $@
+       $(TARGET_CC) $(linux_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ linux_mod-loader_linux_normal.o
+
+mod-linux.o: mod-linux.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -c -o $@ $<
+
+mod-linux.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'linux' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(linux_mod_EXPORTS),no)
+def-linux.lst: pre-linux.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 linux/' > $@
+endif
+
+und-linux.lst: pre-linux.o
+       echo 'linux' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+linux_mod-loader_linux_normal.o: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -MD -c -o $@ $<
+-include linux_mod-loader_linux_normal.d
+
+CLEANFILES += cmd-linux_mod-loader_linux_normal.lst fs-linux_mod-loader_linux_normal.lst partmap-linux_mod-loader_linux_normal.lst
+COMMANDFILES += cmd-linux_mod-loader_linux_normal.lst
+FSFILES += fs-linux_mod-loader_linux_normal.lst
+PARTMAPFILES += partmap-linux_mod-loader_linux_normal.lst
+
+cmd-linux_mod-loader_linux_normal.lst: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh linux > $@ || (rm -f $@; exit 1)
+
+fs-linux_mod-loader_linux_normal.lst: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh linux > $@ || (rm -f $@; exit 1)
+
+partmap-linux_mod-loader_linux_normal.lst: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh linux > $@ || (rm -f $@; exit 1)
+
+
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+#
+# Only arch dependant part of normal.mod will be here. Common part for
+# all architecures of normal.mod is at start and should be kept at sync
+# with other makefiles.
+# 
+# Please put arch dependant part of normal.mod at the end of list to
+# keep it simpler to update to different architectures.
+#
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/color.c                                                  \
+       normal/menu_viewer.c normal/menu_entry.c                        \
+       normal/misc.c grub_script.tab.c                                 \
+       normal/script.c                                                 \
+       normal/i386/setjmp.S
+CLEANFILES += normal.mod mod-normal.o mod-normal.c pre-normal.o normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_i386_setjmp.o und-normal.lst
+ifneq ($(normal_mod_EXPORTS),no)
+CLEANFILES += def-normal.lst
+DEFSYMFILES += def-normal.lst
+endif
+MOSTLYCLEANFILES += normal_mod-normal_arg.d normal_mod-normal_cmdline.d normal_mod-normal_command.d normal_mod-normal_completion.d normal_mod-normal_execute.d normal_mod-normal_function.d normal_mod-normal_lexer.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_menu_text.d normal_mod-normal_color.d normal_mod-normal_menu_viewer.d normal_mod-normal_menu_entry.d normal_mod-normal_misc.d normal_mod-grub_script_tab.d normal_mod-normal_script.d normal_mod-normal_i386_setjmp.d
+UNDSYMFILES += und-normal.lst
+
+normal.mod: pre-normal.o mod-normal.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(normal_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-normal.o mod-normal.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-normal.o: $(normal_mod_DEPENDENCIES) normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_i386_setjmp.o
+       -rm -f $@
+       $(TARGET_CC) $(normal_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_i386_setjmp.o
+
+mod-normal.o: mod-normal.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
+
+mod-normal.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'normal' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(normal_mod_EXPORTS),no)
+def-normal.lst: pre-normal.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 normal/' > $@
+endif
+
+und-normal.lst: pre-normal.o
+       echo 'normal' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+normal_mod-normal_arg.o: normal/arg.c $(normal/arg.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_arg.d
+
+CLEANFILES += cmd-normal_mod-normal_arg.lst fs-normal_mod-normal_arg.lst partmap-normal_mod-normal_arg.lst
+COMMANDFILES += cmd-normal_mod-normal_arg.lst
+FSFILES += fs-normal_mod-normal_arg.lst
+PARTMAPFILES += partmap-normal_mod-normal_arg.lst
+
+cmd-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_cmdline.o: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_cmdline.d
+
+CLEANFILES += cmd-normal_mod-normal_cmdline.lst fs-normal_mod-normal_cmdline.lst partmap-normal_mod-normal_cmdline.lst
+COMMANDFILES += cmd-normal_mod-normal_cmdline.lst
+FSFILES += fs-normal_mod-normal_cmdline.lst
+PARTMAPFILES += partmap-normal_mod-normal_cmdline.lst
+
+cmd-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_command.o: normal/command.c $(normal/command.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_command.d
+
+CLEANFILES += cmd-normal_mod-normal_command.lst fs-normal_mod-normal_command.lst partmap-normal_mod-normal_command.lst
+COMMANDFILES += cmd-normal_mod-normal_command.lst
+FSFILES += fs-normal_mod-normal_command.lst
+PARTMAPFILES += partmap-normal_mod-normal_command.lst
+
+cmd-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_completion.o: normal/completion.c $(normal/completion.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_completion.d
+
+CLEANFILES += cmd-normal_mod-normal_completion.lst fs-normal_mod-normal_completion.lst partmap-normal_mod-normal_completion.lst
+COMMANDFILES += cmd-normal_mod-normal_completion.lst
+FSFILES += fs-normal_mod-normal_completion.lst
+PARTMAPFILES += partmap-normal_mod-normal_completion.lst
+
+cmd-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_execute.o: normal/execute.c $(normal/execute.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_execute.d
+
+CLEANFILES += cmd-normal_mod-normal_execute.lst fs-normal_mod-normal_execute.lst partmap-normal_mod-normal_execute.lst
+COMMANDFILES += cmd-normal_mod-normal_execute.lst
+FSFILES += fs-normal_mod-normal_execute.lst
+PARTMAPFILES += partmap-normal_mod-normal_execute.lst
+
+cmd-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_function.o: normal/function.c $(normal/function.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_function.d
+
+CLEANFILES += cmd-normal_mod-normal_function.lst fs-normal_mod-normal_function.lst partmap-normal_mod-normal_function.lst
+COMMANDFILES += cmd-normal_mod-normal_function.lst
+FSFILES += fs-normal_mod-normal_function.lst
+PARTMAPFILES += partmap-normal_mod-normal_function.lst
+
+cmd-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_lexer.o: normal/lexer.c $(normal/lexer.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_lexer.d
+
+CLEANFILES += cmd-normal_mod-normal_lexer.lst fs-normal_mod-normal_lexer.lst partmap-normal_mod-normal_lexer.lst
+COMMANDFILES += cmd-normal_mod-normal_lexer.lst
+FSFILES += fs-normal_mod-normal_lexer.lst
+PARTMAPFILES += partmap-normal_mod-normal_lexer.lst
+
+cmd-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_main.o: normal/main.c $(normal/main.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_main.d
+
+CLEANFILES += cmd-normal_mod-normal_main.lst fs-normal_mod-normal_main.lst partmap-normal_mod-normal_main.lst
+COMMANDFILES += cmd-normal_mod-normal_main.lst
+FSFILES += fs-normal_mod-normal_main.lst
+PARTMAPFILES += partmap-normal_mod-normal_main.lst
+
+cmd-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu.o: normal/menu.c $(normal/menu.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu.d
+
+CLEANFILES += cmd-normal_mod-normal_menu.lst fs-normal_mod-normal_menu.lst partmap-normal_mod-normal_menu.lst
+COMMANDFILES += cmd-normal_mod-normal_menu.lst
+FSFILES += fs-normal_mod-normal_menu.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu.lst
+
+cmd-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_text.o: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_text.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_text.lst fs-normal_mod-normal_menu_text.lst partmap-normal_mod-normal_menu_text.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_text.lst
+FSFILES += fs-normal_mod-normal_menu_text.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_text.lst
+
+cmd-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_color.o: normal/color.c $(normal/color.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_color.d
+
+CLEANFILES += cmd-normal_mod-normal_color.lst fs-normal_mod-normal_color.lst partmap-normal_mod-normal_color.lst
+COMMANDFILES += cmd-normal_mod-normal_color.lst
+FSFILES += fs-normal_mod-normal_color.lst
+PARTMAPFILES += partmap-normal_mod-normal_color.lst
+
+cmd-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_viewer.o: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_viewer.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_viewer.lst fs-normal_mod-normal_menu_viewer.lst partmap-normal_mod-normal_menu_viewer.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_viewer.lst
+FSFILES += fs-normal_mod-normal_menu_viewer.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_viewer.lst
+
+cmd-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_entry.o: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_entry.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_entry.lst fs-normal_mod-normal_menu_entry.lst partmap-normal_mod-normal_menu_entry.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_entry.lst
+FSFILES += fs-normal_mod-normal_menu_entry.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_entry.lst
+
+cmd-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_misc.o: normal/misc.c $(normal/misc.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_misc.d
+
+CLEANFILES += cmd-normal_mod-normal_misc.lst fs-normal_mod-normal_misc.lst partmap-normal_mod-normal_misc.lst
+COMMANDFILES += cmd-normal_mod-normal_misc.lst
+FSFILES += fs-normal_mod-normal_misc.lst
+PARTMAPFILES += partmap-normal_mod-normal_misc.lst
+
+cmd-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-grub_script_tab.o: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES)
+       $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-grub_script_tab.d
+
+CLEANFILES += cmd-normal_mod-grub_script_tab.lst fs-normal_mod-grub_script_tab.lst partmap-normal_mod-grub_script_tab.lst
+COMMANDFILES += cmd-normal_mod-grub_script_tab.lst
+FSFILES += fs-normal_mod-grub_script_tab.lst
+PARTMAPFILES += partmap-normal_mod-grub_script_tab.lst
+
+cmd-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_script.o: normal/script.c $(normal/script.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_script.d
+
+CLEANFILES += cmd-normal_mod-normal_script.lst fs-normal_mod-normal_script.lst partmap-normal_mod-normal_script.lst
+COMMANDFILES += cmd-normal_mod-normal_script.lst
+FSFILES += fs-normal_mod-normal_script.lst
+PARTMAPFILES += partmap-normal_mod-normal_script.lst
+
+cmd-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_i386_setjmp.o: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES)
+       $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_i386_setjmp.d
+
+CLEANFILES += cmd-normal_mod-normal_i386_setjmp.lst fs-normal_mod-normal_i386_setjmp.lst partmap-normal_mod-normal_i386_setjmp.lst
+COMMANDFILES += cmd-normal_mod-normal_i386_setjmp.lst
+FSFILES += fs-normal_mod-normal_i386_setjmp.lst
+PARTMAPFILES += partmap-normal_mod-normal_i386_setjmp.lst
+
+cmd-normal_mod-normal_i386_setjmp.lst: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_i386_setjmp.lst: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<     | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_i386_setjmp.lst: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reboot.mod.
+reboot_mod_SOURCES = commands/reboot.c kern/i386/reboot.c
+CLEANFILES += reboot.mod mod-reboot.o mod-reboot.c pre-reboot.o reboot_mod-commands_reboot.o reboot_mod-kern_i386_reboot.o und-reboot.lst
+ifneq ($(reboot_mod_EXPORTS),no)
+CLEANFILES += def-reboot.lst
+DEFSYMFILES += def-reboot.lst
+endif
+MOSTLYCLEANFILES += reboot_mod-commands_reboot.d reboot_mod-kern_i386_reboot.d
+UNDSYMFILES += und-reboot.lst
+
+reboot.mod: pre-reboot.o mod-reboot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(reboot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-reboot.o mod-reboot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-reboot.o: $(reboot_mod_DEPENDENCIES) reboot_mod-commands_reboot.o reboot_mod-kern_i386_reboot.o
+       -rm -f $@
+       $(TARGET_CC) $(reboot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ reboot_mod-commands_reboot.o reboot_mod-kern_i386_reboot.o
+
+mod-reboot.o: mod-reboot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -c -o $@ $<
+
+mod-reboot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'reboot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(reboot_mod_EXPORTS),no)
+def-reboot.lst: pre-reboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 reboot/' > $@
+endif
+
+und-reboot.lst: pre-reboot.o
+       echo 'reboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+reboot_mod-commands_reboot.o: commands/reboot.c $(commands/reboot.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -MD -c -o $@ $<
+-include reboot_mod-commands_reboot.d
+
+CLEANFILES += cmd-reboot_mod-commands_reboot.lst fs-reboot_mod-commands_reboot.lst partmap-reboot_mod-commands_reboot.lst
+COMMANDFILES += cmd-reboot_mod-commands_reboot.lst
+FSFILES += fs-reboot_mod-commands_reboot.lst
+PARTMAPFILES += partmap-reboot_mod-commands_reboot.lst
+
+cmd-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh reboot > $@ || (rm -f $@; exit 1)
+
+fs-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh reboot > $@ || (rm -f $@; exit 1)
+
+partmap-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh reboot > $@ || (rm -f $@; exit 1)
+
+
+reboot_mod-kern_i386_reboot.o: kern/i386/reboot.c $(kern/i386/reboot.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -MD -c -o $@ $<
+-include reboot_mod-kern_i386_reboot.d
+
+CLEANFILES += cmd-reboot_mod-kern_i386_reboot.lst fs-reboot_mod-kern_i386_reboot.lst partmap-reboot_mod-kern_i386_reboot.lst
+COMMANDFILES += cmd-reboot_mod-kern_i386_reboot.lst
+FSFILES += fs-reboot_mod-kern_i386_reboot.lst
+PARTMAPFILES += partmap-reboot_mod-kern_i386_reboot.lst
+
+cmd-reboot_mod-kern_i386_reboot.lst: kern/i386/reboot.c $(kern/i386/reboot.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh reboot > $@ || (rm -f $@; exit 1)
+
+fs-reboot_mod-kern_i386_reboot.lst: kern/i386/reboot.c $(kern/i386/reboot.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh reboot > $@ || (rm -f $@; exit 1)
+
+partmap-reboot_mod-kern_i386_reboot.lst: kern/i386/reboot.c $(kern/i386/reboot.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh reboot > $@ || (rm -f $@; exit 1)
+
+
+reboot_mod_CFLAGS = $(COMMON_CFLAGS)
+reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For halt.mod.
+halt_mod_SOURCES = commands/halt.c kern/i386/halt.c
+CLEANFILES += halt.mod mod-halt.o mod-halt.c pre-halt.o halt_mod-commands_halt.o halt_mod-kern_i386_halt.o und-halt.lst
+ifneq ($(halt_mod_EXPORTS),no)
+CLEANFILES += def-halt.lst
+DEFSYMFILES += def-halt.lst
+endif
+MOSTLYCLEANFILES += halt_mod-commands_halt.d halt_mod-kern_i386_halt.d
+UNDSYMFILES += und-halt.lst
+
+halt.mod: pre-halt.o mod-halt.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(halt_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-halt.o mod-halt.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-halt.o: $(halt_mod_DEPENDENCIES) halt_mod-commands_halt.o halt_mod-kern_i386_halt.o
+       -rm -f $@
+       $(TARGET_CC) $(halt_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ halt_mod-commands_halt.o halt_mod-kern_i386_halt.o
+
+mod-halt.o: mod-halt.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -c -o $@ $<
+
+mod-halt.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'halt' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(halt_mod_EXPORTS),no)
+def-halt.lst: pre-halt.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 halt/' > $@
+endif
+
+und-halt.lst: pre-halt.o
+       echo 'halt' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+halt_mod-commands_halt.o: commands/halt.c $(commands/halt.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -MD -c -o $@ $<
+-include halt_mod-commands_halt.d
+
+CLEANFILES += cmd-halt_mod-commands_halt.lst fs-halt_mod-commands_halt.lst partmap-halt_mod-commands_halt.lst
+COMMANDFILES += cmd-halt_mod-commands_halt.lst
+FSFILES += fs-halt_mod-commands_halt.lst
+PARTMAPFILES += partmap-halt_mod-commands_halt.lst
+
+cmd-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh halt > $@ || (rm -f $@; exit 1)
+
+fs-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh halt > $@ || (rm -f $@; exit 1)
+
+partmap-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh halt > $@ || (rm -f $@; exit 1)
+
+
+halt_mod-kern_i386_halt.o: kern/i386/halt.c $(kern/i386/halt.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -MD -c -o $@ $<
+-include halt_mod-kern_i386_halt.d
+
+CLEANFILES += cmd-halt_mod-kern_i386_halt.lst fs-halt_mod-kern_i386_halt.lst partmap-halt_mod-kern_i386_halt.lst
+COMMANDFILES += cmd-halt_mod-kern_i386_halt.lst
+FSFILES += fs-halt_mod-kern_i386_halt.lst
+PARTMAPFILES += partmap-halt_mod-kern_i386_halt.lst
+
+cmd-halt_mod-kern_i386_halt.lst: kern/i386/halt.c $(kern/i386/halt.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh halt > $@ || (rm -f $@; exit 1)
+
+fs-halt_mod-kern_i386_halt.lst: kern/i386/halt.c $(kern/i386/halt.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh halt > $@ || (rm -f $@; exit 1)
+
+partmap-halt_mod-kern_i386_halt.lst: kern/i386/halt.c $(kern/i386/halt.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh halt > $@ || (rm -f $@; exit 1)
+
+
+halt_mod_CFLAGS = $(COMMON_CFLAGS)
+halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For serial.mod.
+serial_mod_SOURCES = term/i386/pc/serial.c
+CLEANFILES += serial.mod mod-serial.o mod-serial.c pre-serial.o serial_mod-term_i386_pc_serial.o und-serial.lst
+ifneq ($(serial_mod_EXPORTS),no)
+CLEANFILES += def-serial.lst
+DEFSYMFILES += def-serial.lst
+endif
+MOSTLYCLEANFILES += serial_mod-term_i386_pc_serial.d
+UNDSYMFILES += und-serial.lst
+
+serial.mod: pre-serial.o mod-serial.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(serial_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-serial.o mod-serial.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-serial.o: $(serial_mod_DEPENDENCIES) serial_mod-term_i386_pc_serial.o
+       -rm -f $@
+       $(TARGET_CC) $(serial_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ serial_mod-term_i386_pc_serial.o
+
+mod-serial.o: mod-serial.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(serial_mod_CFLAGS) -c -o $@ $<
+
+mod-serial.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'serial' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(serial_mod_EXPORTS),no)
+def-serial.lst: pre-serial.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 serial/' > $@
+endif
+
+und-serial.lst: pre-serial.o
+       echo 'serial' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+serial_mod-term_i386_pc_serial.o: term/i386/pc/serial.c $(term/i386/pc/serial.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(serial_mod_CFLAGS) -MD -c -o $@ $<
+-include serial_mod-term_i386_pc_serial.d
+
+CLEANFILES += cmd-serial_mod-term_i386_pc_serial.lst fs-serial_mod-term_i386_pc_serial.lst partmap-serial_mod-term_i386_pc_serial.lst
+COMMANDFILES += cmd-serial_mod-term_i386_pc_serial.lst
+FSFILES += fs-serial_mod-term_i386_pc_serial.lst
+PARTMAPFILES += partmap-serial_mod-term_i386_pc_serial.lst
+
+cmd-serial_mod-term_i386_pc_serial.lst: term/i386/pc/serial.c $(term/i386/pc/serial.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(serial_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh serial > $@ || (rm -f $@; exit 1)
+
+fs-serial_mod-term_i386_pc_serial.lst: term/i386/pc/serial.c $(term/i386/pc/serial.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(serial_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh serial > $@ || (rm -f $@; exit 1)
+
+partmap-serial_mod-term_i386_pc_serial.lst: term/i386/pc/serial.c $(term/i386/pc/serial.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(serial_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh serial > $@ || (rm -f $@; exit 1)
+
+
+serial_mod_CFLAGS = $(COMMON_CFLAGS)
+serial_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _multiboot.mod.
+_multiboot_mod_SOURCES = loader/i386/pc/multiboot.c \
+                         loader/i386/pc/multiboot2.c \
+                         loader/multiboot2.c \
+                         loader/multiboot_loader.c
+CLEANFILES += _multiboot.mod mod-_multiboot.o mod-_multiboot.c pre-_multiboot.o _multiboot_mod-loader_i386_pc_multiboot.o _multiboot_mod-loader_i386_pc_multiboot2.o _multiboot_mod-loader_multiboot2.o _multiboot_mod-loader_multiboot_loader.o und-_multiboot.lst
+ifneq ($(_multiboot_mod_EXPORTS),no)
+CLEANFILES += def-_multiboot.lst
+DEFSYMFILES += def-_multiboot.lst
+endif
+MOSTLYCLEANFILES += _multiboot_mod-loader_i386_pc_multiboot.d _multiboot_mod-loader_i386_pc_multiboot2.d _multiboot_mod-loader_multiboot2.d _multiboot_mod-loader_multiboot_loader.d
+UNDSYMFILES += und-_multiboot.lst
+
+_multiboot.mod: pre-_multiboot.o mod-_multiboot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(_multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-_multiboot.o mod-_multiboot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-_multiboot.o: $(_multiboot_mod_DEPENDENCIES) _multiboot_mod-loader_i386_pc_multiboot.o _multiboot_mod-loader_i386_pc_multiboot2.o _multiboot_mod-loader_multiboot2.o _multiboot_mod-loader_multiboot_loader.o
+       -rm -f $@
+       $(TARGET_CC) $(_multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ _multiboot_mod-loader_i386_pc_multiboot.o _multiboot_mod-loader_i386_pc_multiboot2.o _multiboot_mod-loader_multiboot2.o _multiboot_mod-loader_multiboot_loader.o
+
+mod-_multiboot.o: mod-_multiboot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -c -o $@ $<
+
+mod-_multiboot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '_multiboot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(_multiboot_mod_EXPORTS),no)
+def-_multiboot.lst: pre-_multiboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _multiboot/' > $@
+endif
+
+und-_multiboot.lst: pre-_multiboot.o
+       echo '_multiboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+_multiboot_mod-loader_i386_pc_multiboot.o: loader/i386/pc/multiboot.c $(loader/i386/pc/multiboot.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include _multiboot_mod-loader_i386_pc_multiboot.d
+
+CLEANFILES += cmd-_multiboot_mod-loader_i386_pc_multiboot.lst fs-_multiboot_mod-loader_i386_pc_multiboot.lst partmap-_multiboot_mod-loader_i386_pc_multiboot.lst
+COMMANDFILES += cmd-_multiboot_mod-loader_i386_pc_multiboot.lst
+FSFILES += fs-_multiboot_mod-loader_i386_pc_multiboot.lst
+PARTMAPFILES += partmap-_multiboot_mod-loader_i386_pc_multiboot.lst
+
+cmd-_multiboot_mod-loader_i386_pc_multiboot.lst: loader/i386/pc/multiboot.c $(loader/i386/pc/multiboot.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+fs-_multiboot_mod-loader_i386_pc_multiboot.lst: loader/i386/pc/multiboot.c $(loader/i386/pc/multiboot.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-_multiboot_mod-loader_i386_pc_multiboot.lst: loader/i386/pc/multiboot.c $(loader/i386/pc/multiboot.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+
+_multiboot_mod-loader_i386_pc_multiboot2.o: loader/i386/pc/multiboot2.c $(loader/i386/pc/multiboot2.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include _multiboot_mod-loader_i386_pc_multiboot2.d
+
+CLEANFILES += cmd-_multiboot_mod-loader_i386_pc_multiboot2.lst fs-_multiboot_mod-loader_i386_pc_multiboot2.lst partmap-_multiboot_mod-loader_i386_pc_multiboot2.lst
+COMMANDFILES += cmd-_multiboot_mod-loader_i386_pc_multiboot2.lst
+FSFILES += fs-_multiboot_mod-loader_i386_pc_multiboot2.lst
+PARTMAPFILES += partmap-_multiboot_mod-loader_i386_pc_multiboot2.lst
+
+cmd-_multiboot_mod-loader_i386_pc_multiboot2.lst: loader/i386/pc/multiboot2.c $(loader/i386/pc/multiboot2.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+fs-_multiboot_mod-loader_i386_pc_multiboot2.lst: loader/i386/pc/multiboot2.c $(loader/i386/pc/multiboot2.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-_multiboot_mod-loader_i386_pc_multiboot2.lst: loader/i386/pc/multiboot2.c $(loader/i386/pc/multiboot2.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+
+_multiboot_mod-loader_multiboot2.o: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include _multiboot_mod-loader_multiboot2.d
+
+CLEANFILES += cmd-_multiboot_mod-loader_multiboot2.lst fs-_multiboot_mod-loader_multiboot2.lst partmap-_multiboot_mod-loader_multiboot2.lst
+COMMANDFILES += cmd-_multiboot_mod-loader_multiboot2.lst
+FSFILES += fs-_multiboot_mod-loader_multiboot2.lst
+PARTMAPFILES += partmap-_multiboot_mod-loader_multiboot2.lst
+
+cmd-_multiboot_mod-loader_multiboot2.lst: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+fs-_multiboot_mod-loader_multiboot2.lst: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-_multiboot_mod-loader_multiboot2.lst: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+
+_multiboot_mod-loader_multiboot_loader.o: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include _multiboot_mod-loader_multiboot_loader.d
+
+CLEANFILES += cmd-_multiboot_mod-loader_multiboot_loader.lst fs-_multiboot_mod-loader_multiboot_loader.lst partmap-_multiboot_mod-loader_multiboot_loader.lst
+COMMANDFILES += cmd-_multiboot_mod-loader_multiboot_loader.lst
+FSFILES += fs-_multiboot_mod-loader_multiboot_loader.lst
+PARTMAPFILES += partmap-_multiboot_mod-loader_multiboot_loader.lst
+
+cmd-_multiboot_mod-loader_multiboot_loader.lst: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+fs-_multiboot_mod-loader_multiboot_loader.lst: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-_multiboot_mod-loader_multiboot_loader.lst: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+
+_multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+_multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For multiboot.mod.
+multiboot_mod_SOURCES = loader/multiboot_loader_normal.c 
+CLEANFILES += multiboot.mod mod-multiboot.o mod-multiboot.c pre-multiboot.o multiboot_mod-loader_multiboot_loader_normal.o und-multiboot.lst
+ifneq ($(multiboot_mod_EXPORTS),no)
+CLEANFILES += def-multiboot.lst
+DEFSYMFILES += def-multiboot.lst
+endif
+MOSTLYCLEANFILES += multiboot_mod-loader_multiboot_loader_normal.d
+UNDSYMFILES += und-multiboot.lst
+
+multiboot.mod: pre-multiboot.o mod-multiboot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-multiboot.o mod-multiboot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-multiboot.o: $(multiboot_mod_DEPENDENCIES) multiboot_mod-loader_multiboot_loader_normal.o
+       -rm -f $@
+       $(TARGET_CC) $(multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ multiboot_mod-loader_multiboot_loader_normal.o
+
+mod-multiboot.o: mod-multiboot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -c -o $@ $<
+
+mod-multiboot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'multiboot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(multiboot_mod_EXPORTS),no)
+def-multiboot.lst: pre-multiboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 multiboot/' > $@
+endif
+
+und-multiboot.lst: pre-multiboot.o
+       echo 'multiboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+multiboot_mod-loader_multiboot_loader_normal.o: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include multiboot_mod-loader_multiboot_loader_normal.d
+
+CLEANFILES += cmd-multiboot_mod-loader_multiboot_loader_normal.lst fs-multiboot_mod-loader_multiboot_loader_normal.lst partmap-multiboot_mod-loader_multiboot_loader_normal.lst
+COMMANDFILES += cmd-multiboot_mod-loader_multiboot_loader_normal.lst
+FSFILES += fs-multiboot_mod-loader_multiboot_loader_normal.lst
+PARTMAPFILES += partmap-multiboot_mod-loader_multiboot_loader_normal.lst
+
+cmd-multiboot_mod-loader_multiboot_loader_normal.lst: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh multiboot > $@ || (rm -f $@; exit 1)
+
+fs-multiboot_mod-loader_multiboot_loader_normal.lst: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-multiboot_mod-loader_multiboot_loader_normal.lst: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh multiboot > $@ || (rm -f $@; exit 1)
+
+
+multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For aout.mod.
+aout_mod_SOURCES = loader/aout.c
+CLEANFILES += aout.mod mod-aout.o mod-aout.c pre-aout.o aout_mod-loader_aout.o und-aout.lst
+ifneq ($(aout_mod_EXPORTS),no)
+CLEANFILES += def-aout.lst
+DEFSYMFILES += def-aout.lst
+endif
+MOSTLYCLEANFILES += aout_mod-loader_aout.d
+UNDSYMFILES += und-aout.lst
+
+aout.mod: pre-aout.o mod-aout.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(aout_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-aout.o mod-aout.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-aout.o: $(aout_mod_DEPENDENCIES) aout_mod-loader_aout.o
+       -rm -f $@
+       $(TARGET_CC) $(aout_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ aout_mod-loader_aout.o
+
+mod-aout.o: mod-aout.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(aout_mod_CFLAGS) -c -o $@ $<
+
+mod-aout.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'aout' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(aout_mod_EXPORTS),no)
+def-aout.lst: pre-aout.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 aout/' > $@
+endif
+
+und-aout.lst: pre-aout.o
+       echo 'aout' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+aout_mod-loader_aout.o: loader/aout.c $(loader/aout.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(aout_mod_CFLAGS) -MD -c -o $@ $<
+-include aout_mod-loader_aout.d
+
+CLEANFILES += cmd-aout_mod-loader_aout.lst fs-aout_mod-loader_aout.lst partmap-aout_mod-loader_aout.lst
+COMMANDFILES += cmd-aout_mod-loader_aout.lst
+FSFILES += fs-aout_mod-loader_aout.lst
+PARTMAPFILES += partmap-aout_mod-loader_aout.lst
+
+cmd-aout_mod-loader_aout.lst: loader/aout.c $(loader/aout.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(aout_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh aout > $@ || (rm -f $@; exit 1)
+
+fs-aout_mod-loader_aout.lst: loader/aout.c $(loader/aout.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(aout_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh aout > $@ || (rm -f $@; exit 1)
+
+partmap-aout_mod-loader_aout.lst: loader/aout.c $(loader/aout.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(aout_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh aout > $@ || (rm -f $@; exit 1)
+
+
+aout_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For play.mod.
+play_mod_SOURCES = commands/i386/pc/play.c
+CLEANFILES += play.mod mod-play.o mod-play.c pre-play.o play_mod-commands_i386_pc_play.o und-play.lst
+ifneq ($(play_mod_EXPORTS),no)
+CLEANFILES += def-play.lst
+DEFSYMFILES += def-play.lst
+endif
+MOSTLYCLEANFILES += play_mod-commands_i386_pc_play.d
+UNDSYMFILES += und-play.lst
+
+play.mod: pre-play.o mod-play.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(play_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-play.o mod-play.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-play.o: $(play_mod_DEPENDENCIES) play_mod-commands_i386_pc_play.o
+       -rm -f $@
+       $(TARGET_CC) $(play_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ play_mod-commands_i386_pc_play.o
+
+mod-play.o: mod-play.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(play_mod_CFLAGS) -c -o $@ $<
+
+mod-play.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'play' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(play_mod_EXPORTS),no)
+def-play.lst: pre-play.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 play/' > $@
+endif
+
+und-play.lst: pre-play.o
+       echo 'play' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+play_mod-commands_i386_pc_play.o: commands/i386/pc/play.c $(commands/i386/pc/play.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(play_mod_CFLAGS) -MD -c -o $@ $<
+-include play_mod-commands_i386_pc_play.d
+
+CLEANFILES += cmd-play_mod-commands_i386_pc_play.lst fs-play_mod-commands_i386_pc_play.lst partmap-play_mod-commands_i386_pc_play.lst
+COMMANDFILES += cmd-play_mod-commands_i386_pc_play.lst
+FSFILES += fs-play_mod-commands_i386_pc_play.lst
+PARTMAPFILES += partmap-play_mod-commands_i386_pc_play.lst
+
+cmd-play_mod-commands_i386_pc_play.lst: commands/i386/pc/play.c $(commands/i386/pc/play.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(play_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh play > $@ || (rm -f $@; exit 1)
+
+fs-play_mod-commands_i386_pc_play.lst: commands/i386/pc/play.c $(commands/i386/pc/play.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(play_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh play > $@ || (rm -f $@; exit 1)
+
+partmap-play_mod-commands_i386_pc_play.lst: commands/i386/pc/play.c $(commands/i386/pc/play.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(play_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh play > $@ || (rm -f $@; exit 1)
+
+
+play_mod_CFLAGS = $(COMMON_CFLAGS)
+play_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ata.mod.
+ata_mod_SOURCES = disk/ata.c
+CLEANFILES += ata.mod mod-ata.o mod-ata.c pre-ata.o ata_mod-disk_ata.o und-ata.lst
+ifneq ($(ata_mod_EXPORTS),no)
+CLEANFILES += def-ata.lst
+DEFSYMFILES += def-ata.lst
+endif
+MOSTLYCLEANFILES += ata_mod-disk_ata.d
+UNDSYMFILES += und-ata.lst
+
+ata.mod: pre-ata.o mod-ata.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(ata_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-ata.o mod-ata.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-ata.o: $(ata_mod_DEPENDENCIES) ata_mod-disk_ata.o
+       -rm -f $@
+       $(TARGET_CC) $(ata_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ ata_mod-disk_ata.o
+
+mod-ata.o: mod-ata.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_mod_CFLAGS) -c -o $@ $<
+
+mod-ata.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'ata' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(ata_mod_EXPORTS),no)
+def-ata.lst: pre-ata.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 ata/' > $@
+endif
+
+und-ata.lst: pre-ata.o
+       echo 'ata' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+ata_mod-disk_ata.o: disk/ata.c $(disk/ata.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(ata_mod_CFLAGS) -MD -c -o $@ $<
+-include ata_mod-disk_ata.d
+
+CLEANFILES += cmd-ata_mod-disk_ata.lst fs-ata_mod-disk_ata.lst partmap-ata_mod-disk_ata.lst
+COMMANDFILES += cmd-ata_mod-disk_ata.lst
+FSFILES += fs-ata_mod-disk_ata.lst
+PARTMAPFILES += partmap-ata_mod-disk_ata.lst
+
+cmd-ata_mod-disk_ata.lst: disk/ata.c $(disk/ata.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh ata > $@ || (rm -f $@; exit 1)
+
+fs-ata_mod-disk_ata.lst: disk/ata.c $(disk/ata.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh ata > $@ || (rm -f $@; exit 1)
+
+partmap-ata_mod-disk_ata.lst: disk/ata.c $(disk/ata.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh ata > $@ || (rm -f $@; exit 1)
+
+
+ata_mod_CFLAGS = $(COMMON_CFLAGS)
+ata_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For memdisk.mod.
+memdisk_mod_SOURCES = disk/memdisk.c
+CLEANFILES += memdisk.mod mod-memdisk.o mod-memdisk.c pre-memdisk.o memdisk_mod-disk_memdisk.o und-memdisk.lst
+ifneq ($(memdisk_mod_EXPORTS),no)
+CLEANFILES += def-memdisk.lst
+DEFSYMFILES += def-memdisk.lst
+endif
+MOSTLYCLEANFILES += memdisk_mod-disk_memdisk.d
+UNDSYMFILES += und-memdisk.lst
+
+memdisk.mod: pre-memdisk.o mod-memdisk.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(memdisk_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-memdisk.o mod-memdisk.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-memdisk.o: $(memdisk_mod_DEPENDENCIES) memdisk_mod-disk_memdisk.o
+       -rm -f $@
+       $(TARGET_CC) $(memdisk_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ memdisk_mod-disk_memdisk.o
+
+mod-memdisk.o: mod-memdisk.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -c -o $@ $<
+
+mod-memdisk.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'memdisk' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(memdisk_mod_EXPORTS),no)
+def-memdisk.lst: pre-memdisk.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 memdisk/' > $@
+endif
+
+und-memdisk.lst: pre-memdisk.o
+       echo 'memdisk' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+memdisk_mod-disk_memdisk.o: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -MD -c -o $@ $<
+-include memdisk_mod-disk_memdisk.d
+
+CLEANFILES += cmd-memdisk_mod-disk_memdisk.lst fs-memdisk_mod-disk_memdisk.lst partmap-memdisk_mod-disk_memdisk.lst
+COMMANDFILES += cmd-memdisk_mod-disk_memdisk.lst
+FSFILES += fs-memdisk_mod-disk_memdisk.lst
+PARTMAPFILES += partmap-memdisk_mod-disk_memdisk.lst
+
+cmd-memdisk_mod-disk_memdisk.lst: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh memdisk > $@ || (rm -f $@; exit 1)
+
+fs-memdisk_mod-disk_memdisk.lst: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh memdisk > $@ || (rm -f $@; exit 1)
+
+partmap-memdisk_mod-disk_memdisk.lst: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh memdisk > $@ || (rm -f $@; exit 1)
+
+
+memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+CLEANFILES += pci.mod mod-pci.o mod-pci.c pre-pci.o pci_mod-bus_pci.o und-pci.lst
+ifneq ($(pci_mod_EXPORTS),no)
+CLEANFILES += def-pci.lst
+DEFSYMFILES += def-pci.lst
+endif
+MOSTLYCLEANFILES += pci_mod-bus_pci.d
+UNDSYMFILES += und-pci.lst
+
+pci.mod: pre-pci.o mod-pci.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(pci_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-pci.o mod-pci.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-pci.o: $(pci_mod_DEPENDENCIES) pci_mod-bus_pci.o
+       -rm -f $@
+       $(TARGET_CC) $(pci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pci_mod-bus_pci.o
+
+mod-pci.o: mod-pci.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -c -o $@ $<
+
+mod-pci.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'pci' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(pci_mod_EXPORTS),no)
+def-pci.lst: pre-pci.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 pci/' > $@
+endif
+
+und-pci.lst: pre-pci.o
+       echo 'pci' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+pci_mod-bus_pci.o: bus/pci.c $(bus/pci.c_DEPENDENCIES)
+       $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -MD -c -o $@ $<
+-include pci_mod-bus_pci.d
+
+CLEANFILES += cmd-pci_mod-bus_pci.lst fs-pci_mod-bus_pci.lst partmap-pci_mod-bus_pci.lst
+COMMANDFILES += cmd-pci_mod-bus_pci.lst
+FSFILES += fs-pci_mod-bus_pci.lst
+PARTMAPFILES += partmap-pci_mod-bus_pci.lst
+
+cmd-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh pci > $@ || (rm -f $@; exit 1)
+
+fs-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh pci > $@ || (rm -f $@; exit 1)
+
+partmap-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh pci > $@ || (rm -f $@; exit 1)
+
+
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+CLEANFILES += lspci.mod mod-lspci.o mod-lspci.c pre-lspci.o lspci_mod-commands_lspci.o und-lspci.lst
+ifneq ($(lspci_mod_EXPORTS),no)
+CLEANFILES += def-lspci.lst
+DEFSYMFILES += def-lspci.lst
+endif
+MOSTLYCLEANFILES += lspci_mod-commands_lspci.d
+UNDSYMFILES += und-lspci.lst
+
+lspci.mod: pre-lspci.o mod-lspci.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(lspci_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-lspci.o mod-lspci.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-lspci.o: $(lspci_mod_DEPENDENCIES) lspci_mod-commands_lspci.o
+       -rm -f $@
+       $(TARGET_CC) $(lspci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ lspci_mod-commands_lspci.o
+
+mod-lspci.o: mod-lspci.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -c -o $@ $<
+
+mod-lspci.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'lspci' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(lspci_mod_EXPORTS),no)
+def-lspci.lst: pre-lspci.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 lspci/' > $@
+endif
+
+und-lspci.lst: pre-lspci.o
+       echo 'lspci' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+lspci_mod-commands_lspci.o: commands/lspci.c $(commands/lspci.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -MD -c -o $@ $<
+-include lspci_mod-commands_lspci.d
+
+CLEANFILES += cmd-lspci_mod-commands_lspci.lst fs-lspci_mod-commands_lspci.lst partmap-lspci_mod-commands_lspci.lst
+COMMANDFILES += cmd-lspci_mod-commands_lspci.lst
+FSFILES += fs-lspci_mod-commands_lspci.lst
+PARTMAPFILES += partmap-lspci_mod-commands_lspci.lst
+
+cmd-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh lspci > $@ || (rm -f $@; exit 1)
+
+fs-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh lspci > $@ || (rm -f $@; exit 1)
+
+partmap-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh lspci > $@ || (rm -f $@; exit 1)
+
+
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datetime.mod
+datetime_mod_SOURCES = lib/datetime.c lib/i386/datetime.c
+CLEANFILES += datetime.mod mod-datetime.o mod-datetime.c pre-datetime.o datetime_mod-lib_datetime.o datetime_mod-lib_i386_datetime.o und-datetime.lst
+ifneq ($(datetime_mod_EXPORTS),no)
+CLEANFILES += def-datetime.lst
+DEFSYMFILES += def-datetime.lst
+endif
+MOSTLYCLEANFILES += datetime_mod-lib_datetime.d datetime_mod-lib_i386_datetime.d
+UNDSYMFILES += und-datetime.lst
+
+datetime.mod: pre-datetime.o mod-datetime.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(datetime_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-datetime.o mod-datetime.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-datetime.o: $(datetime_mod_DEPENDENCIES) datetime_mod-lib_datetime.o datetime_mod-lib_i386_datetime.o
+       -rm -f $@
+       $(TARGET_CC) $(datetime_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ datetime_mod-lib_datetime.o datetime_mod-lib_i386_datetime.o
+
+mod-datetime.o: mod-datetime.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -c -o $@ $<
+
+mod-datetime.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'datetime' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(datetime_mod_EXPORTS),no)
+def-datetime.lst: pre-datetime.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 datetime/' > $@
+endif
+
+und-datetime.lst: pre-datetime.o
+       echo 'datetime' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+datetime_mod-lib_datetime.o: lib/datetime.c $(lib/datetime.c_DEPENDENCIES)
+       $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -MD -c -o $@ $<
+-include datetime_mod-lib_datetime.d
+
+CLEANFILES += cmd-datetime_mod-lib_datetime.lst fs-datetime_mod-lib_datetime.lst partmap-datetime_mod-lib_datetime.lst
+COMMANDFILES += cmd-datetime_mod-lib_datetime.lst
+FSFILES += fs-datetime_mod-lib_datetime.lst
+PARTMAPFILES += partmap-datetime_mod-lib_datetime.lst
+
+cmd-datetime_mod-lib_datetime.lst: lib/datetime.c $(lib/datetime.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh datetime > $@ || (rm -f $@; exit 1)
+
+fs-datetime_mod-lib_datetime.lst: lib/datetime.c $(lib/datetime.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh datetime > $@ || (rm -f $@; exit 1)
+
+partmap-datetime_mod-lib_datetime.lst: lib/datetime.c $(lib/datetime.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh datetime > $@ || (rm -f $@; exit 1)
+
+
+datetime_mod-lib_i386_datetime.o: lib/i386/datetime.c $(lib/i386/datetime.c_DEPENDENCIES)
+       $(TARGET_CC) -Ilib/i386 -I$(srcdir)/lib/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -MD -c -o $@ $<
+-include datetime_mod-lib_i386_datetime.d
+
+CLEANFILES += cmd-datetime_mod-lib_i386_datetime.lst fs-datetime_mod-lib_i386_datetime.lst partmap-datetime_mod-lib_i386_datetime.lst
+COMMANDFILES += cmd-datetime_mod-lib_i386_datetime.lst
+FSFILES += fs-datetime_mod-lib_i386_datetime.lst
+PARTMAPFILES += partmap-datetime_mod-lib_i386_datetime.lst
+
+cmd-datetime_mod-lib_i386_datetime.lst: lib/i386/datetime.c $(lib/i386/datetime.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ilib/i386 -I$(srcdir)/lib/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh datetime > $@ || (rm -f $@; exit 1)
+
+fs-datetime_mod-lib_i386_datetime.lst: lib/i386/datetime.c $(lib/i386/datetime.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ilib/i386 -I$(srcdir)/lib/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh datetime > $@ || (rm -f $@; exit 1)
+
+partmap-datetime_mod-lib_i386_datetime.lst: lib/i386/datetime.c $(lib/i386/datetime.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ilib/i386 -I$(srcdir)/lib/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh datetime > $@ || (rm -f $@; exit 1)
+
+
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+CLEANFILES += date.mod mod-date.o mod-date.c pre-date.o date_mod-commands_date.o und-date.lst
+ifneq ($(date_mod_EXPORTS),no)
+CLEANFILES += def-date.lst
+DEFSYMFILES += def-date.lst
+endif
+MOSTLYCLEANFILES += date_mod-commands_date.d
+UNDSYMFILES += und-date.lst
+
+date.mod: pre-date.o mod-date.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(date_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-date.o mod-date.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-date.o: $(date_mod_DEPENDENCIES) date_mod-commands_date.o
+       -rm -f $@
+       $(TARGET_CC) $(date_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ date_mod-commands_date.o
+
+mod-date.o: mod-date.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -c -o $@ $<
+
+mod-date.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'date' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(date_mod_EXPORTS),no)
+def-date.lst: pre-date.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 date/' > $@
+endif
+
+und-date.lst: pre-date.o
+       echo 'date' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+date_mod-commands_date.o: commands/date.c $(commands/date.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(date_mod_CFLAGS) -MD -c -o $@ $<
+-include date_mod-commands_date.d
+
+CLEANFILES += cmd-date_mod-commands_date.lst fs-date_mod-commands_date.lst partmap-date_mod-commands_date.lst
+COMMANDFILES += cmd-date_mod-commands_date.lst
+FSFILES += fs-date_mod-commands_date.lst
+PARTMAPFILES += partmap-date_mod-commands_date.lst
+
+cmd-date_mod-commands_date.lst: commands/date.c $(commands/date.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh date > $@ || (rm -f $@; exit 1)
+
+fs-date_mod-commands_date.lst: commands/date.c $(commands/date.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh date > $@ || (rm -f $@; exit 1)
+
+partmap-date_mod-commands_date.lst: commands/date.c $(commands/date.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh date > $@ || (rm -f $@; exit 1)
+
+
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datehook.mod
+datehook_mod_SOURCES = hook/datehook.c
+CLEANFILES += datehook.mod mod-datehook.o mod-datehook.c pre-datehook.o datehook_mod-hook_datehook.o und-datehook.lst
+ifneq ($(datehook_mod_EXPORTS),no)
+CLEANFILES += def-datehook.lst
+DEFSYMFILES += def-datehook.lst
+endif
+MOSTLYCLEANFILES += datehook_mod-hook_datehook.d
+UNDSYMFILES += und-datehook.lst
+
+datehook.mod: pre-datehook.o mod-datehook.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(datehook_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-datehook.o mod-datehook.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-datehook.o: $(datehook_mod_DEPENDENCIES) datehook_mod-hook_datehook.o
+       -rm -f $@
+       $(TARGET_CC) $(datehook_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ datehook_mod-hook_datehook.o
+
+mod-datehook.o: mod-datehook.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -c -o $@ $<
+
+mod-datehook.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'datehook' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(datehook_mod_EXPORTS),no)
+def-datehook.lst: pre-datehook.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 datehook/' > $@
+endif
+
+und-datehook.lst: pre-datehook.o
+       echo 'datehook' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+datehook_mod-hook_datehook.o: hook/datehook.c $(hook/datehook.c_DEPENDENCIES)
+       $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -MD -c -o $@ $<
+-include datehook_mod-hook_datehook.d
+
+CLEANFILES += cmd-datehook_mod-hook_datehook.lst fs-datehook_mod-hook_datehook.lst partmap-datehook_mod-hook_datehook.lst
+COMMANDFILES += cmd-datehook_mod-hook_datehook.lst
+FSFILES += fs-datehook_mod-hook_datehook.lst
+PARTMAPFILES += partmap-datehook_mod-hook_datehook.lst
+
+cmd-datehook_mod-hook_datehook.lst: hook/datehook.c $(hook/datehook.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh datehook > $@ || (rm -f $@; exit 1)
+
+fs-datehook_mod-hook_datehook.lst: hook/datehook.c $(hook/datehook.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh datehook > $@ || (rm -f $@; exit 1)
+
+partmap-datehook_mod-hook_datehook.lst: hook/datehook.c $(hook/datehook.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh datehook > $@ || (rm -f $@; exit 1)
+
+
+datehook_mod_CFLAGS = $(COMMON_CFLAGS)
+datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lsmmap.mod
+lsmmap_mod_SOURCES = commands/lsmmap.c
+CLEANFILES += lsmmap.mod mod-lsmmap.o mod-lsmmap.c pre-lsmmap.o lsmmap_mod-commands_lsmmap.o und-lsmmap.lst
+ifneq ($(lsmmap_mod_EXPORTS),no)
+CLEANFILES += def-lsmmap.lst
+DEFSYMFILES += def-lsmmap.lst
+endif
+MOSTLYCLEANFILES += lsmmap_mod-commands_lsmmap.d
+UNDSYMFILES += und-lsmmap.lst
+
+lsmmap.mod: pre-lsmmap.o mod-lsmmap.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(lsmmap_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-lsmmap.o mod-lsmmap.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-lsmmap.o: $(lsmmap_mod_DEPENDENCIES) lsmmap_mod-commands_lsmmap.o
+       -rm -f $@
+       $(TARGET_CC) $(lsmmap_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ lsmmap_mod-commands_lsmmap.o
+
+mod-lsmmap.o: mod-lsmmap.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -c -o $@ $<
+
+mod-lsmmap.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'lsmmap' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(lsmmap_mod_EXPORTS),no)
+def-lsmmap.lst: pre-lsmmap.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 lsmmap/' > $@
+endif
+
+und-lsmmap.lst: pre-lsmmap.o
+       echo 'lsmmap' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+lsmmap_mod-commands_lsmmap.o: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -MD -c -o $@ $<
+-include lsmmap_mod-commands_lsmmap.d
+
+CLEANFILES += cmd-lsmmap_mod-commands_lsmmap.lst fs-lsmmap_mod-commands_lsmmap.lst partmap-lsmmap_mod-commands_lsmmap.lst
+COMMANDFILES += cmd-lsmmap_mod-commands_lsmmap.lst
+FSFILES += fs-lsmmap_mod-commands_lsmmap.lst
+PARTMAPFILES += partmap-lsmmap_mod-commands_lsmmap.lst
+
+cmd-lsmmap_mod-commands_lsmmap.lst: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh lsmmap > $@ || (rm -f $@; exit 1)
+
+fs-lsmmap_mod-commands_lsmmap.lst: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh lsmmap > $@ || (rm -f $@; exit 1)
+
+partmap-lsmmap_mod-commands_lsmmap.lst: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh lsmmap > $@ || (rm -f $@; exit 1)
+
+
+lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
+lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+include $(srcdir)/conf/i386.mk
+include $(srcdir)/conf/common.mk
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
new file mode 100644 (file)
index 0000000..b97483b
--- /dev/null
@@ -0,0 +1,215 @@
+# -*- makefile -*-
+
+COMMON_ASFLAGS = -nostdinc -fno-builtin -m32
+COMMON_CFLAGS = -fno-builtin -mrtd -mregparm=3 -m32
+COMMON_LDFLAGS = -m32 -nostdlib
+
+# Used by various components.  These rules need to precede them.
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Images.
+pkglib_PROGRAMS = kernel.elf
+
+# For kernel.elf.
+kernel_elf_SOURCES = kern/i386/coreboot/startup.S \
+       kern/i386/coreboot/init.c \
+       kern/i386/multiboot_mmap.c \
+       kern/main.c kern/device.c \
+       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
+       kern/time.c \
+       kern/i386/dl.c kern/parser.c kern/partition.c \
+       kern/i386/tsc.c kern/i386/pit.c \
+       kern/generic/rtc_get_time_ms.c \
+       kern/generic/millisleep.c \
+       kern/env.c \
+       term/i386/pc/vga_text.c term/i386/vga_common.c \
+       term/i386/pc/at_keyboard.c \
+       symlist.c
+kernel_elf_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
+       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
+       partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
+       machine/boot.h machine/console.h machine/init.h \
+       machine/memory.h machine/loader.h
+kernel_elf_CFLAGS = $(COMMON_CFLAGS)
+kernel_elf_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_elf_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x8200,-Bstatic
+
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+symlist.c: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h gensymlist.sh
+       /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h genkernsyms.sh
+       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+# Utilities.
+sbin_UTILITIES = grub-mkdevicemap
+ifeq ($(enable_grub_emu), yes)
+sbin_UTILITIES += grub-emu
+endif
+
+# For grub-mkdevicemap.
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+
+# For grub-emu.
+util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
+grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c       \
+       commands/configfile.c commands/echo.c commands/help.c           \
+       commands/terminal.c commands/ls.c commands/test.c               \
+       commands/search.c commands/blocklist.c commands/hexdump.c       \
+       lib/hexdump.c commands/i386/cpuid.c                             \
+       disk/host.c disk/loopback.c                                     \
+       \
+       fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c  fs/hfs.c                \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c          \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c                  \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                             \
+       \
+       fs/fshelp.c                                                     \
+       io/gzio.c                                                       \
+       kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c       \
+       kern/err.c                                                      \
+       normal/execute.c kern/file.c kern/fs.c normal/lexer.c           \
+       kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
+       grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
+       normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
+       normal/completion.c normal/main.c normal/menu_text.c            \
+       normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
+       normal/misc.c normal/script.c                                   \
+       normal/color.c                                                  \
+       partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
+       partmap/acorn.c partmap/gpt.c                                   \
+       util/console.c util/hostfs.c util/grub-emu.c util/misc.c        \
+       util/hostdisk.c util/getroot.c                                  \
+       util/i386/pc/misc.c                                             \
+       \
+       disk/raid.c disk/raid5_recover.c disk/raid6_recover.c           \
+       disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c             \
+       grub_emu_init.c
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+sbin_SCRIPTS += grub-install
+grub_install_SOURCES = util/i386/pc/grub-install.in
+
+# Modules.
+pkglib_MODULES = _linux.mod linux.mod normal.mod       \
+       _multiboot.mod multiboot.mod aout.mod           \
+       play.mod serial.mod ata.mod                     \
+       memdisk.mod pci.mod lspci.mod reboot.mod        \
+       halt.mod datetime.mod date.mod datehook.mod     \
+       lsmmap.mod
+
+# For _linux.mod.
+_linux_mod_SOURCES = loader/i386/linux.c
+_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/linux_normal.c
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+#
+# Only arch dependant part of normal.mod will be here. Common part for
+# all architecures of normal.mod is at start and should be kept at sync
+# with other makefiles.
+# 
+# Please put arch dependant part of normal.mod at the end of list to
+# keep it simpler to update to different architectures.
+#
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/color.c                                                  \
+       normal/menu_viewer.c normal/menu_entry.c                        \
+       normal/misc.c grub_script.tab.c                                 \
+       normal/script.c                                                 \
+       normal/i386/setjmp.S
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reboot.mod.
+reboot_mod_SOURCES = commands/reboot.c kern/i386/reboot.c
+reboot_mod_CFLAGS = $(COMMON_CFLAGS)
+reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For halt.mod.
+halt_mod_SOURCES = commands/halt.c kern/i386/halt.c
+halt_mod_CFLAGS = $(COMMON_CFLAGS)
+halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For serial.mod.
+serial_mod_SOURCES = term/i386/pc/serial.c
+serial_mod_CFLAGS = $(COMMON_CFLAGS)
+serial_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _multiboot.mod.
+_multiboot_mod_SOURCES = loader/i386/pc/multiboot.c \
+                         loader/i386/pc/multiboot2.c \
+                         loader/multiboot2.c \
+                         loader/multiboot_loader.c
+_multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+_multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For multiboot.mod.
+multiboot_mod_SOURCES = loader/multiboot_loader_normal.c 
+multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For aout.mod.
+aout_mod_SOURCES = loader/aout.c
+aout_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For play.mod.
+play_mod_SOURCES = commands/i386/pc/play.c
+play_mod_CFLAGS = $(COMMON_CFLAGS)
+play_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ata.mod.
+ata_mod_SOURCES = disk/ata.c
+ata_mod_CFLAGS = $(COMMON_CFLAGS)
+ata_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For memdisk.mod.
+memdisk_mod_SOURCES = disk/memdisk.c
+memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datetime.mod
+datetime_mod_SOURCES = lib/datetime.c lib/i386/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datehook.mod
+datehook_mod_SOURCES = hook/datehook.c
+datehook_mod_CFLAGS = $(COMMON_CFLAGS)
+datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lsmmap.mod
+lsmmap_mod_SOURCES = commands/lsmmap.c
+lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
+lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+include $(srcdir)/conf/i386.mk
+include $(srcdir)/conf/common.mk
diff --git a/conf/i386-efi.mk b/conf/i386-efi.mk
new file mode 100644 (file)
index 0000000..9e98098
--- /dev/null
@@ -0,0 +1,1817 @@
+# -*- makefile -*-
+# Generated by genmk.rb, please don't edit!
+
+COMMON_ASFLAGS = -nostdinc -fno-builtin -m32
+COMMON_CFLAGS = -fno-builtin -m32
+COMMON_LDFLAGS = -melf_i386 -nostdlib
+
+# Used by various components.  These rules need to precede them.
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Utilities.
+bin_UTILITIES = grub-mkimage
+sbin_UTILITIES = grub-mkdevicemap
+#ifeq ($(enable_grub_emu), yes)
+#sbin_UTILITIES += grub-emu
+#endif
+
+# For grub-mkimage.
+grub_mkimage_SOURCES = util/i386/efi/grub-mkimage.c util/misc.c \
+       util/resolve.c
+CLEANFILES += grub-mkimage$(EXEEXT) grub_mkimage-util_i386_efi_grub_mkimage.o grub_mkimage-util_misc.o grub_mkimage-util_resolve.o
+MOSTLYCLEANFILES += grub_mkimage-util_i386_efi_grub_mkimage.d grub_mkimage-util_misc.d grub_mkimage-util_resolve.d
+
+grub-mkimage: $(grub_mkimage_DEPENDENCIES) grub_mkimage-util_i386_efi_grub_mkimage.o grub_mkimage-util_misc.o grub_mkimage-util_resolve.o
+       $(CC) -o $@ grub_mkimage-util_i386_efi_grub_mkimage.o grub_mkimage-util_misc.o grub_mkimage-util_resolve.o $(LDFLAGS) $(grub_mkimage_LDFLAGS)
+
+grub_mkimage-util_i386_efi_grub_mkimage.o: util/i386/efi/grub-mkimage.c $(util/i386/efi/grub-mkimage.c_DEPENDENCIES)
+       $(CC) -Iutil/i386/efi -I$(srcdir)/util/i386/efi $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkimage-util_i386_efi_grub_mkimage.d
+
+grub_mkimage-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkimage-util_misc.d
+
+grub_mkimage-util_resolve.o: util/resolve.c $(util/resolve.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkimage-util_resolve.d
+
+util/i386/efi/grub-mkimage.c_DEPENDENCIES = Makefile
+
+# For grub-setup.
+#grub_setup_SOURCES = util/i386/pc/grub-setup.c util/hostdisk.c        \
+#      util/misc.c util/getroot.c kern/device.c kern/disk.c    \
+#      kern/err.c kern/misc.c fs/fat.c fs/ext2.c fs/xfs.c fs/affs.c    \
+#      fs/sfs.c kern/parser.c kern/partition.c partmap/pc.c            \
+#      fs/ufs.c fs/minix.c fs/hfs.c fs/jfs.c fs/hfsplus.c kern/file.c  \
+#      kern/fs.c kern/env.c fs/fshelp.c
+
+# For grub-mkdevicemap.
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+CLEANFILES += grub-mkdevicemap$(EXEEXT) grub_mkdevicemap-util_grub_mkdevicemap.o grub_mkdevicemap-util_misc.o
+MOSTLYCLEANFILES += grub_mkdevicemap-util_grub_mkdevicemap.d grub_mkdevicemap-util_misc.d
+
+grub-mkdevicemap: $(grub_mkdevicemap_DEPENDENCIES) grub_mkdevicemap-util_grub_mkdevicemap.o grub_mkdevicemap-util_misc.o
+       $(CC) -o $@ grub_mkdevicemap-util_grub_mkdevicemap.o grub_mkdevicemap-util_misc.o $(LDFLAGS) $(grub_mkdevicemap_LDFLAGS)
+
+grub_mkdevicemap-util_grub_mkdevicemap.o: util/grub-mkdevicemap.c $(util/grub-mkdevicemap.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkdevicemap_CFLAGS) -MD -c -o $@ $<
+-include grub_mkdevicemap-util_grub_mkdevicemap.d
+
+grub_mkdevicemap-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkdevicemap_CFLAGS) -MD -c -o $@ $<
+-include grub_mkdevicemap-util_misc.d
+
+
+# For grub-emu.
+util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
+grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c       \
+       commands/configfile.c commands/help.c                           \
+       commands/terminal.c commands/ls.c commands/test.c               \
+       commands/search.c commands/hexdump.c lib/hexdump.c              \
+       commands/halt.c commands/reboot.c                               \
+       commands/i386/cpuid.c                                           \
+       disk/loopback.c                                                 \
+       \
+       fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c                 \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c          \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c                  \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                             \
+       \
+       io/gzio.c                                                       \
+       kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c       \
+       kern/err.c                                                      \
+       normal/execute.c kern/file.c kern/fs.c normal/lexer.c           \
+       kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
+       grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
+       normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
+       normal/completion.c normal/context.c normal/main.c              \
+       normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
+       normal/menu_text.c                                              \
+       normal/misc.c normal/script.c                                   \
+       normal/color.c                                                  \
+       partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
+       partmap/acorn.c partmap/gpt.c                                   \
+       util/console.c util/hostfs.c util/grub-emu.c util/misc.c        \
+       util/hostdisk.c util/getroot.c                                  \
+       util/i386/pc/misc.c                                             \
+       \
+       disk/raid.c disk/raid5_recover.c disk/raid6_recover.c           \
+       disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c             \
+       grub_emu_init.c
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+# Scripts.
+sbin_SCRIPTS = grub-install
+
+# For grub-install.
+grub_install_SOURCES = util/i386/efi/grub-install.in
+CLEANFILES += grub-install
+
+grub-install: util/i386/efi/grub-install.in $(util/i386/efi/grub-install.in_DEPENDENCIES) config.status
+       ./config.status --file=grub-install:util/i386/efi/grub-install.in
+       chmod +x $@
+
+
+# Modules.
+pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
+       _linux.mod linux.mod halt.mod reboot.mod pci.mod lspci.mod \
+       datetime.mod date.mod datehook.mod
+
+# For kernel.mod.
+kernel_mod_EXPORTS = no
+kernel_mod_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.c \
+       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
+       kern/i386/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \
+       kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \
+       term/efi/console.c disk/efi/efidisk.c \
+       kern/time.c \
+       kern/i386/tsc.c kern/i386/pit.c \
+       kern/generic/rtc_get_time_ms.c \
+       kern/generic/millisleep.c
+CLEANFILES += kernel.mod mod-kernel.o mod-kernel.c pre-kernel.o kernel_mod-kern_i386_efi_startup.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_i386_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o kernel_mod-kern_efi_init.o kernel_mod-kern_efi_mm.o kernel_mod-term_efi_console.o kernel_mod-disk_efi_efidisk.o kernel_mod-kern_time.o kernel_mod-kern_i386_tsc.o kernel_mod-kern_i386_pit.o kernel_mod-kern_generic_rtc_get_time_ms.o kernel_mod-kern_generic_millisleep.o und-kernel.lst
+ifneq ($(kernel_mod_EXPORTS),no)
+CLEANFILES += def-kernel.lst
+DEFSYMFILES += def-kernel.lst
+endif
+MOSTLYCLEANFILES += kernel_mod-kern_i386_efi_startup.d kernel_mod-kern_main.d kernel_mod-kern_device.d kernel_mod-kern_disk.d kernel_mod-kern_dl.d kernel_mod-kern_file.d kernel_mod-kern_fs.d kernel_mod-kern_err.d kernel_mod-kern_misc.d kernel_mod-kern_mm.d kernel_mod-kern_loader.d kernel_mod-kern_rescue.d kernel_mod-kern_term.d kernel_mod-kern_i386_dl.d kernel_mod-kern_i386_efi_init.d kernel_mod-kern_parser.d kernel_mod-kern_partition.d kernel_mod-kern_env.d kernel_mod-symlist.d kernel_mod-kern_efi_efi.d kernel_mod-kern_efi_init.d kernel_mod-kern_efi_mm.d kernel_mod-term_efi_console.d kernel_mod-disk_efi_efidisk.d kernel_mod-kern_time.d kernel_mod-kern_i386_tsc.d kernel_mod-kern_i386_pit.d kernel_mod-kern_generic_rtc_get_time_ms.d kernel_mod-kern_generic_millisleep.d
+UNDSYMFILES += und-kernel.lst
+
+kernel.mod: pre-kernel.o mod-kernel.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(kernel_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-kernel.o mod-kernel.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-kernel.o: $(kernel_mod_DEPENDENCIES) kernel_mod-kern_i386_efi_startup.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_i386_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o kernel_mod-kern_efi_init.o kernel_mod-kern_efi_mm.o kernel_mod-term_efi_console.o kernel_mod-disk_efi_efidisk.o kernel_mod-kern_time.o kernel_mod-kern_i386_tsc.o kernel_mod-kern_i386_pit.o kernel_mod-kern_generic_rtc_get_time_ms.o kernel_mod-kern_generic_millisleep.o
+       -rm -f $@
+       $(TARGET_CC) $(kernel_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ kernel_mod-kern_i386_efi_startup.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_i386_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o kernel_mod-kern_efi_init.o kernel_mod-kern_efi_mm.o kernel_mod-term_efi_console.o kernel_mod-disk_efi_efidisk.o kernel_mod-kern_time.o kernel_mod-kern_i386_tsc.o kernel_mod-kern_i386_pit.o kernel_mod-kern_generic_rtc_get_time_ms.o kernel_mod-kern_generic_millisleep.o
+
+mod-kernel.o: mod-kernel.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -c -o $@ $<
+
+mod-kernel.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'kernel' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(kernel_mod_EXPORTS),no)
+def-kernel.lst: pre-kernel.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 kernel/' > $@
+endif
+
+und-kernel.lst: pre-kernel.o
+       echo 'kernel' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+kernel_mod-kern_i386_efi_startup.o: kern/i386/efi/startup.S $(kern/i386/efi/startup.S_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386/efi -I$(srcdir)/kern/i386/efi $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(kernel_mod_ASFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_i386_efi_startup.d
+
+CLEANFILES += cmd-kernel_mod-kern_i386_efi_startup.lst fs-kernel_mod-kern_i386_efi_startup.lst partmap-kernel_mod-kern_i386_efi_startup.lst
+COMMANDFILES += cmd-kernel_mod-kern_i386_efi_startup.lst
+FSFILES += fs-kernel_mod-kern_i386_efi_startup.lst
+PARTMAPFILES += partmap-kernel_mod-kern_i386_efi_startup.lst
+
+cmd-kernel_mod-kern_i386_efi_startup.lst: kern/i386/efi/startup.S $(kern/i386/efi/startup.S_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386/efi -I$(srcdir)/kern/i386/efi $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(kernel_mod_ASFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_i386_efi_startup.lst: kern/i386/efi/startup.S $(kern/i386/efi/startup.S_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386/efi -I$(srcdir)/kern/i386/efi $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(kernel_mod_ASFLAGS) -E $<         | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_i386_efi_startup.lst: kern/i386/efi/startup.S $(kern/i386/efi/startup.S_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386/efi -I$(srcdir)/kern/i386/efi $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(kernel_mod_ASFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_main.o: kern/main.c $(kern/main.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_main.d
+
+CLEANFILES += cmd-kernel_mod-kern_main.lst fs-kernel_mod-kern_main.lst partmap-kernel_mod-kern_main.lst
+COMMANDFILES += cmd-kernel_mod-kern_main.lst
+FSFILES += fs-kernel_mod-kern_main.lst
+PARTMAPFILES += partmap-kernel_mod-kern_main.lst
+
+cmd-kernel_mod-kern_main.lst: kern/main.c $(kern/main.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_main.lst: kern/main.c $(kern/main.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_main.lst: kern/main.c $(kern/main.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_device.o: kern/device.c $(kern/device.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_device.d
+
+CLEANFILES += cmd-kernel_mod-kern_device.lst fs-kernel_mod-kern_device.lst partmap-kernel_mod-kern_device.lst
+COMMANDFILES += cmd-kernel_mod-kern_device.lst
+FSFILES += fs-kernel_mod-kern_device.lst
+PARTMAPFILES += partmap-kernel_mod-kern_device.lst
+
+cmd-kernel_mod-kern_device.lst: kern/device.c $(kern/device.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_device.lst: kern/device.c $(kern/device.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_device.lst: kern/device.c $(kern/device.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_disk.o: kern/disk.c $(kern/disk.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_disk.d
+
+CLEANFILES += cmd-kernel_mod-kern_disk.lst fs-kernel_mod-kern_disk.lst partmap-kernel_mod-kern_disk.lst
+COMMANDFILES += cmd-kernel_mod-kern_disk.lst
+FSFILES += fs-kernel_mod-kern_disk.lst
+PARTMAPFILES += partmap-kernel_mod-kern_disk.lst
+
+cmd-kernel_mod-kern_disk.lst: kern/disk.c $(kern/disk.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_disk.lst: kern/disk.c $(kern/disk.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_disk.lst: kern/disk.c $(kern/disk.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_dl.o: kern/dl.c $(kern/dl.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_dl.d
+
+CLEANFILES += cmd-kernel_mod-kern_dl.lst fs-kernel_mod-kern_dl.lst partmap-kernel_mod-kern_dl.lst
+COMMANDFILES += cmd-kernel_mod-kern_dl.lst
+FSFILES += fs-kernel_mod-kern_dl.lst
+PARTMAPFILES += partmap-kernel_mod-kern_dl.lst
+
+cmd-kernel_mod-kern_dl.lst: kern/dl.c $(kern/dl.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_dl.lst: kern/dl.c $(kern/dl.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_dl.lst: kern/dl.c $(kern/dl.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_file.o: kern/file.c $(kern/file.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_file.d
+
+CLEANFILES += cmd-kernel_mod-kern_file.lst fs-kernel_mod-kern_file.lst partmap-kernel_mod-kern_file.lst
+COMMANDFILES += cmd-kernel_mod-kern_file.lst
+FSFILES += fs-kernel_mod-kern_file.lst
+PARTMAPFILES += partmap-kernel_mod-kern_file.lst
+
+cmd-kernel_mod-kern_file.lst: kern/file.c $(kern/file.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_file.lst: kern/file.c $(kern/file.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_file.lst: kern/file.c $(kern/file.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_fs.o: kern/fs.c $(kern/fs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_fs.d
+
+CLEANFILES += cmd-kernel_mod-kern_fs.lst fs-kernel_mod-kern_fs.lst partmap-kernel_mod-kern_fs.lst
+COMMANDFILES += cmd-kernel_mod-kern_fs.lst
+FSFILES += fs-kernel_mod-kern_fs.lst
+PARTMAPFILES += partmap-kernel_mod-kern_fs.lst
+
+cmd-kernel_mod-kern_fs.lst: kern/fs.c $(kern/fs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_fs.lst: kern/fs.c $(kern/fs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_fs.lst: kern/fs.c $(kern/fs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_err.d
+
+CLEANFILES += cmd-kernel_mod-kern_err.lst fs-kernel_mod-kern_err.lst partmap-kernel_mod-kern_err.lst
+COMMANDFILES += cmd-kernel_mod-kern_err.lst
+FSFILES += fs-kernel_mod-kern_err.lst
+PARTMAPFILES += partmap-kernel_mod-kern_err.lst
+
+cmd-kernel_mod-kern_err.lst: kern/err.c $(kern/err.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_err.lst: kern/err.c $(kern/err.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_err.lst: kern/err.c $(kern/err.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_misc.d
+
+CLEANFILES += cmd-kernel_mod-kern_misc.lst fs-kernel_mod-kern_misc.lst partmap-kernel_mod-kern_misc.lst
+COMMANDFILES += cmd-kernel_mod-kern_misc.lst
+FSFILES += fs-kernel_mod-kern_misc.lst
+PARTMAPFILES += partmap-kernel_mod-kern_misc.lst
+
+cmd-kernel_mod-kern_misc.lst: kern/misc.c $(kern/misc.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_misc.lst: kern/misc.c $(kern/misc.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_misc.lst: kern/misc.c $(kern/misc.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_mm.o: kern/mm.c $(kern/mm.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_mm.d
+
+CLEANFILES += cmd-kernel_mod-kern_mm.lst fs-kernel_mod-kern_mm.lst partmap-kernel_mod-kern_mm.lst
+COMMANDFILES += cmd-kernel_mod-kern_mm.lst
+FSFILES += fs-kernel_mod-kern_mm.lst
+PARTMAPFILES += partmap-kernel_mod-kern_mm.lst
+
+cmd-kernel_mod-kern_mm.lst: kern/mm.c $(kern/mm.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_mm.lst: kern/mm.c $(kern/mm.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_mm.lst: kern/mm.c $(kern/mm.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_loader.o: kern/loader.c $(kern/loader.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_loader.d
+
+CLEANFILES += cmd-kernel_mod-kern_loader.lst fs-kernel_mod-kern_loader.lst partmap-kernel_mod-kern_loader.lst
+COMMANDFILES += cmd-kernel_mod-kern_loader.lst
+FSFILES += fs-kernel_mod-kern_loader.lst
+PARTMAPFILES += partmap-kernel_mod-kern_loader.lst
+
+cmd-kernel_mod-kern_loader.lst: kern/loader.c $(kern/loader.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_loader.lst: kern/loader.c $(kern/loader.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_loader.lst: kern/loader.c $(kern/loader.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_rescue.o: kern/rescue.c $(kern/rescue.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_rescue.d
+
+CLEANFILES += cmd-kernel_mod-kern_rescue.lst fs-kernel_mod-kern_rescue.lst partmap-kernel_mod-kern_rescue.lst
+COMMANDFILES += cmd-kernel_mod-kern_rescue.lst
+FSFILES += fs-kernel_mod-kern_rescue.lst
+PARTMAPFILES += partmap-kernel_mod-kern_rescue.lst
+
+cmd-kernel_mod-kern_rescue.lst: kern/rescue.c $(kern/rescue.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_rescue.lst: kern/rescue.c $(kern/rescue.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_rescue.lst: kern/rescue.c $(kern/rescue.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_term.o: kern/term.c $(kern/term.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_term.d
+
+CLEANFILES += cmd-kernel_mod-kern_term.lst fs-kernel_mod-kern_term.lst partmap-kernel_mod-kern_term.lst
+COMMANDFILES += cmd-kernel_mod-kern_term.lst
+FSFILES += fs-kernel_mod-kern_term.lst
+PARTMAPFILES += partmap-kernel_mod-kern_term.lst
+
+cmd-kernel_mod-kern_term.lst: kern/term.c $(kern/term.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_term.lst: kern/term.c $(kern/term.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_term.lst: kern/term.c $(kern/term.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_i386_dl.o: kern/i386/dl.c $(kern/i386/dl.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_i386_dl.d
+
+CLEANFILES += cmd-kernel_mod-kern_i386_dl.lst fs-kernel_mod-kern_i386_dl.lst partmap-kernel_mod-kern_i386_dl.lst
+COMMANDFILES += cmd-kernel_mod-kern_i386_dl.lst
+FSFILES += fs-kernel_mod-kern_i386_dl.lst
+PARTMAPFILES += partmap-kernel_mod-kern_i386_dl.lst
+
+cmd-kernel_mod-kern_i386_dl.lst: kern/i386/dl.c $(kern/i386/dl.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_i386_dl.lst: kern/i386/dl.c $(kern/i386/dl.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_i386_dl.lst: kern/i386/dl.c $(kern/i386/dl.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_i386_efi_init.o: kern/i386/efi/init.c $(kern/i386/efi/init.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386/efi -I$(srcdir)/kern/i386/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_i386_efi_init.d
+
+CLEANFILES += cmd-kernel_mod-kern_i386_efi_init.lst fs-kernel_mod-kern_i386_efi_init.lst partmap-kernel_mod-kern_i386_efi_init.lst
+COMMANDFILES += cmd-kernel_mod-kern_i386_efi_init.lst
+FSFILES += fs-kernel_mod-kern_i386_efi_init.lst
+PARTMAPFILES += partmap-kernel_mod-kern_i386_efi_init.lst
+
+cmd-kernel_mod-kern_i386_efi_init.lst: kern/i386/efi/init.c $(kern/i386/efi/init.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386/efi -I$(srcdir)/kern/i386/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_i386_efi_init.lst: kern/i386/efi/init.c $(kern/i386/efi/init.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386/efi -I$(srcdir)/kern/i386/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_i386_efi_init.lst: kern/i386/efi/init.c $(kern/i386/efi/init.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386/efi -I$(srcdir)/kern/i386/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_parser.o: kern/parser.c $(kern/parser.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_parser.d
+
+CLEANFILES += cmd-kernel_mod-kern_parser.lst fs-kernel_mod-kern_parser.lst partmap-kernel_mod-kern_parser.lst
+COMMANDFILES += cmd-kernel_mod-kern_parser.lst
+FSFILES += fs-kernel_mod-kern_parser.lst
+PARTMAPFILES += partmap-kernel_mod-kern_parser.lst
+
+cmd-kernel_mod-kern_parser.lst: kern/parser.c $(kern/parser.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_parser.lst: kern/parser.c $(kern/parser.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_parser.lst: kern/parser.c $(kern/parser.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_partition.o: kern/partition.c $(kern/partition.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_partition.d
+
+CLEANFILES += cmd-kernel_mod-kern_partition.lst fs-kernel_mod-kern_partition.lst partmap-kernel_mod-kern_partition.lst
+COMMANDFILES += cmd-kernel_mod-kern_partition.lst
+FSFILES += fs-kernel_mod-kern_partition.lst
+PARTMAPFILES += partmap-kernel_mod-kern_partition.lst
+
+cmd-kernel_mod-kern_partition.lst: kern/partition.c $(kern/partition.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_partition.lst: kern/partition.c $(kern/partition.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_partition.lst: kern/partition.c $(kern/partition.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_env.o: kern/env.c $(kern/env.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_env.d
+
+CLEANFILES += cmd-kernel_mod-kern_env.lst fs-kernel_mod-kern_env.lst partmap-kernel_mod-kern_env.lst
+COMMANDFILES += cmd-kernel_mod-kern_env.lst
+FSFILES += fs-kernel_mod-kern_env.lst
+PARTMAPFILES += partmap-kernel_mod-kern_env.lst
+
+cmd-kernel_mod-kern_env.lst: kern/env.c $(kern/env.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_env.lst: kern/env.c $(kern/env.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_env.lst: kern/env.c $(kern/env.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-symlist.o: symlist.c $(symlist.c_DEPENDENCIES)
+       $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-symlist.d
+
+CLEANFILES += cmd-kernel_mod-symlist.lst fs-kernel_mod-symlist.lst partmap-kernel_mod-symlist.lst
+COMMANDFILES += cmd-kernel_mod-symlist.lst
+FSFILES += fs-kernel_mod-symlist.lst
+PARTMAPFILES += partmap-kernel_mod-symlist.lst
+
+cmd-kernel_mod-symlist.lst: symlist.c $(symlist.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-symlist.lst: symlist.c $(symlist.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-symlist.lst: symlist.c $(symlist.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_efi_efi.o: kern/efi/efi.c $(kern/efi/efi.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_efi_efi.d
+
+CLEANFILES += cmd-kernel_mod-kern_efi_efi.lst fs-kernel_mod-kern_efi_efi.lst partmap-kernel_mod-kern_efi_efi.lst
+COMMANDFILES += cmd-kernel_mod-kern_efi_efi.lst
+FSFILES += fs-kernel_mod-kern_efi_efi.lst
+PARTMAPFILES += partmap-kernel_mod-kern_efi_efi.lst
+
+cmd-kernel_mod-kern_efi_efi.lst: kern/efi/efi.c $(kern/efi/efi.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_efi_efi.lst: kern/efi/efi.c $(kern/efi/efi.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_efi_efi.lst: kern/efi/efi.c $(kern/efi/efi.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_efi_init.o: kern/efi/init.c $(kern/efi/init.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_efi_init.d
+
+CLEANFILES += cmd-kernel_mod-kern_efi_init.lst fs-kernel_mod-kern_efi_init.lst partmap-kernel_mod-kern_efi_init.lst
+COMMANDFILES += cmd-kernel_mod-kern_efi_init.lst
+FSFILES += fs-kernel_mod-kern_efi_init.lst
+PARTMAPFILES += partmap-kernel_mod-kern_efi_init.lst
+
+cmd-kernel_mod-kern_efi_init.lst: kern/efi/init.c $(kern/efi/init.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_efi_init.lst: kern/efi/init.c $(kern/efi/init.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_efi_init.lst: kern/efi/init.c $(kern/efi/init.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_efi_mm.o: kern/efi/mm.c $(kern/efi/mm.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_efi_mm.d
+
+CLEANFILES += cmd-kernel_mod-kern_efi_mm.lst fs-kernel_mod-kern_efi_mm.lst partmap-kernel_mod-kern_efi_mm.lst
+COMMANDFILES += cmd-kernel_mod-kern_efi_mm.lst
+FSFILES += fs-kernel_mod-kern_efi_mm.lst
+PARTMAPFILES += partmap-kernel_mod-kern_efi_mm.lst
+
+cmd-kernel_mod-kern_efi_mm.lst: kern/efi/mm.c $(kern/efi/mm.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_efi_mm.lst: kern/efi/mm.c $(kern/efi/mm.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_efi_mm.lst: kern/efi/mm.c $(kern/efi/mm.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-term_efi_console.o: term/efi/console.c $(term/efi/console.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/efi -I$(srcdir)/term/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-term_efi_console.d
+
+CLEANFILES += cmd-kernel_mod-term_efi_console.lst fs-kernel_mod-term_efi_console.lst partmap-kernel_mod-term_efi_console.lst
+COMMANDFILES += cmd-kernel_mod-term_efi_console.lst
+FSFILES += fs-kernel_mod-term_efi_console.lst
+PARTMAPFILES += partmap-kernel_mod-term_efi_console.lst
+
+cmd-kernel_mod-term_efi_console.lst: term/efi/console.c $(term/efi/console.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iterm/efi -I$(srcdir)/term/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-term_efi_console.lst: term/efi/console.c $(term/efi/console.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iterm/efi -I$(srcdir)/term/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-term_efi_console.lst: term/efi/console.c $(term/efi/console.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iterm/efi -I$(srcdir)/term/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-disk_efi_efidisk.o: disk/efi/efidisk.c $(disk/efi/efidisk.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk/efi -I$(srcdir)/disk/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-disk_efi_efidisk.d
+
+CLEANFILES += cmd-kernel_mod-disk_efi_efidisk.lst fs-kernel_mod-disk_efi_efidisk.lst partmap-kernel_mod-disk_efi_efidisk.lst
+COMMANDFILES += cmd-kernel_mod-disk_efi_efidisk.lst
+FSFILES += fs-kernel_mod-disk_efi_efidisk.lst
+PARTMAPFILES += partmap-kernel_mod-disk_efi_efidisk.lst
+
+cmd-kernel_mod-disk_efi_efidisk.lst: disk/efi/efidisk.c $(disk/efi/efidisk.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk/efi -I$(srcdir)/disk/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-disk_efi_efidisk.lst: disk/efi/efidisk.c $(disk/efi/efidisk.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk/efi -I$(srcdir)/disk/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-disk_efi_efidisk.lst: disk/efi/efidisk.c $(disk/efi/efidisk.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk/efi -I$(srcdir)/disk/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_time.o: kern/time.c $(kern/time.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_time.d
+
+CLEANFILES += cmd-kernel_mod-kern_time.lst fs-kernel_mod-kern_time.lst partmap-kernel_mod-kern_time.lst
+COMMANDFILES += cmd-kernel_mod-kern_time.lst
+FSFILES += fs-kernel_mod-kern_time.lst
+PARTMAPFILES += partmap-kernel_mod-kern_time.lst
+
+cmd-kernel_mod-kern_time.lst: kern/time.c $(kern/time.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_time.lst: kern/time.c $(kern/time.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_time.lst: kern/time.c $(kern/time.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_i386_tsc.o: kern/i386/tsc.c $(kern/i386/tsc.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_i386_tsc.d
+
+CLEANFILES += cmd-kernel_mod-kern_i386_tsc.lst fs-kernel_mod-kern_i386_tsc.lst partmap-kernel_mod-kern_i386_tsc.lst
+COMMANDFILES += cmd-kernel_mod-kern_i386_tsc.lst
+FSFILES += fs-kernel_mod-kern_i386_tsc.lst
+PARTMAPFILES += partmap-kernel_mod-kern_i386_tsc.lst
+
+cmd-kernel_mod-kern_i386_tsc.lst: kern/i386/tsc.c $(kern/i386/tsc.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_i386_tsc.lst: kern/i386/tsc.c $(kern/i386/tsc.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_i386_tsc.lst: kern/i386/tsc.c $(kern/i386/tsc.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_i386_pit.o: kern/i386/pit.c $(kern/i386/pit.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_i386_pit.d
+
+CLEANFILES += cmd-kernel_mod-kern_i386_pit.lst fs-kernel_mod-kern_i386_pit.lst partmap-kernel_mod-kern_i386_pit.lst
+COMMANDFILES += cmd-kernel_mod-kern_i386_pit.lst
+FSFILES += fs-kernel_mod-kern_i386_pit.lst
+PARTMAPFILES += partmap-kernel_mod-kern_i386_pit.lst
+
+cmd-kernel_mod-kern_i386_pit.lst: kern/i386/pit.c $(kern/i386/pit.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_i386_pit.lst: kern/i386/pit.c $(kern/i386/pit.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_i386_pit.lst: kern/i386/pit.c $(kern/i386/pit.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_generic_rtc_get_time_ms.o: kern/generic/rtc_get_time_ms.c $(kern/generic/rtc_get_time_ms.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_generic_rtc_get_time_ms.d
+
+CLEANFILES += cmd-kernel_mod-kern_generic_rtc_get_time_ms.lst fs-kernel_mod-kern_generic_rtc_get_time_ms.lst partmap-kernel_mod-kern_generic_rtc_get_time_ms.lst
+COMMANDFILES += cmd-kernel_mod-kern_generic_rtc_get_time_ms.lst
+FSFILES += fs-kernel_mod-kern_generic_rtc_get_time_ms.lst
+PARTMAPFILES += partmap-kernel_mod-kern_generic_rtc_get_time_ms.lst
+
+cmd-kernel_mod-kern_generic_rtc_get_time_ms.lst: kern/generic/rtc_get_time_ms.c $(kern/generic/rtc_get_time_ms.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_generic_rtc_get_time_ms.lst: kern/generic/rtc_get_time_ms.c $(kern/generic/rtc_get_time_ms.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_generic_rtc_get_time_ms.lst: kern/generic/rtc_get_time_ms.c $(kern/generic/rtc_get_time_ms.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_generic_millisleep.o: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_generic_millisleep.d
+
+CLEANFILES += cmd-kernel_mod-kern_generic_millisleep.lst fs-kernel_mod-kern_generic_millisleep.lst partmap-kernel_mod-kern_generic_millisleep.lst
+COMMANDFILES += cmd-kernel_mod-kern_generic_millisleep.lst
+FSFILES += fs-kernel_mod-kern_generic_millisleep.lst
+PARTMAPFILES += partmap-kernel_mod-kern_generic_millisleep.lst
+
+cmd-kernel_mod-kern_generic_millisleep.lst: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_generic_millisleep.lst: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_generic_millisleep.lst: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
+       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
+       partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
+       efi/efi.h efi/time.h efi/disk.h
+kernel_mod_CFLAGS = $(COMMON_CFLAGS)
+kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+MOSTLYCLEANFILES += symlist.c
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+symlist.c: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h gensymlist.sh
+       /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h genkernsyms.sh
+       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+#
+# Only arch dependant part of normal.mod will be here. Common part for
+# all architecures of normal.mod is at start and should be kept at sync
+# with other makefiles.
+# 
+# Please put arch dependant part of normal.mod at the end of list to
+# keep it simpler to update to different architectures.
+#
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/color.c                                                  \
+       normal/menu_viewer.c normal/menu_entry.c                        \
+       normal/misc.c grub_script.tab.c                                 \
+       normal/script.c                                                 \
+       normal/i386/setjmp.S
+CLEANFILES += normal.mod mod-normal.o mod-normal.c pre-normal.o normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_i386_setjmp.o und-normal.lst
+ifneq ($(normal_mod_EXPORTS),no)
+CLEANFILES += def-normal.lst
+DEFSYMFILES += def-normal.lst
+endif
+MOSTLYCLEANFILES += normal_mod-normal_arg.d normal_mod-normal_cmdline.d normal_mod-normal_command.d normal_mod-normal_completion.d normal_mod-normal_execute.d normal_mod-normal_function.d normal_mod-normal_lexer.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_menu_text.d normal_mod-normal_color.d normal_mod-normal_menu_viewer.d normal_mod-normal_menu_entry.d normal_mod-normal_misc.d normal_mod-grub_script_tab.d normal_mod-normal_script.d normal_mod-normal_i386_setjmp.d
+UNDSYMFILES += und-normal.lst
+
+normal.mod: pre-normal.o mod-normal.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(normal_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-normal.o mod-normal.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-normal.o: $(normal_mod_DEPENDENCIES) normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_i386_setjmp.o
+       -rm -f $@
+       $(TARGET_CC) $(normal_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_i386_setjmp.o
+
+mod-normal.o: mod-normal.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
+
+mod-normal.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'normal' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(normal_mod_EXPORTS),no)
+def-normal.lst: pre-normal.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 normal/' > $@
+endif
+
+und-normal.lst: pre-normal.o
+       echo 'normal' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+normal_mod-normal_arg.o: normal/arg.c $(normal/arg.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_arg.d
+
+CLEANFILES += cmd-normal_mod-normal_arg.lst fs-normal_mod-normal_arg.lst partmap-normal_mod-normal_arg.lst
+COMMANDFILES += cmd-normal_mod-normal_arg.lst
+FSFILES += fs-normal_mod-normal_arg.lst
+PARTMAPFILES += partmap-normal_mod-normal_arg.lst
+
+cmd-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_cmdline.o: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_cmdline.d
+
+CLEANFILES += cmd-normal_mod-normal_cmdline.lst fs-normal_mod-normal_cmdline.lst partmap-normal_mod-normal_cmdline.lst
+COMMANDFILES += cmd-normal_mod-normal_cmdline.lst
+FSFILES += fs-normal_mod-normal_cmdline.lst
+PARTMAPFILES += partmap-normal_mod-normal_cmdline.lst
+
+cmd-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_command.o: normal/command.c $(normal/command.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_command.d
+
+CLEANFILES += cmd-normal_mod-normal_command.lst fs-normal_mod-normal_command.lst partmap-normal_mod-normal_command.lst
+COMMANDFILES += cmd-normal_mod-normal_command.lst
+FSFILES += fs-normal_mod-normal_command.lst
+PARTMAPFILES += partmap-normal_mod-normal_command.lst
+
+cmd-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_completion.o: normal/completion.c $(normal/completion.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_completion.d
+
+CLEANFILES += cmd-normal_mod-normal_completion.lst fs-normal_mod-normal_completion.lst partmap-normal_mod-normal_completion.lst
+COMMANDFILES += cmd-normal_mod-normal_completion.lst
+FSFILES += fs-normal_mod-normal_completion.lst
+PARTMAPFILES += partmap-normal_mod-normal_completion.lst
+
+cmd-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_execute.o: normal/execute.c $(normal/execute.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_execute.d
+
+CLEANFILES += cmd-normal_mod-normal_execute.lst fs-normal_mod-normal_execute.lst partmap-normal_mod-normal_execute.lst
+COMMANDFILES += cmd-normal_mod-normal_execute.lst
+FSFILES += fs-normal_mod-normal_execute.lst
+PARTMAPFILES += partmap-normal_mod-normal_execute.lst
+
+cmd-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_function.o: normal/function.c $(normal/function.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_function.d
+
+CLEANFILES += cmd-normal_mod-normal_function.lst fs-normal_mod-normal_function.lst partmap-normal_mod-normal_function.lst
+COMMANDFILES += cmd-normal_mod-normal_function.lst
+FSFILES += fs-normal_mod-normal_function.lst
+PARTMAPFILES += partmap-normal_mod-normal_function.lst
+
+cmd-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_lexer.o: normal/lexer.c $(normal/lexer.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_lexer.d
+
+CLEANFILES += cmd-normal_mod-normal_lexer.lst fs-normal_mod-normal_lexer.lst partmap-normal_mod-normal_lexer.lst
+COMMANDFILES += cmd-normal_mod-normal_lexer.lst
+FSFILES += fs-normal_mod-normal_lexer.lst
+PARTMAPFILES += partmap-normal_mod-normal_lexer.lst
+
+cmd-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_main.o: normal/main.c $(normal/main.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_main.d
+
+CLEANFILES += cmd-normal_mod-normal_main.lst fs-normal_mod-normal_main.lst partmap-normal_mod-normal_main.lst
+COMMANDFILES += cmd-normal_mod-normal_main.lst
+FSFILES += fs-normal_mod-normal_main.lst
+PARTMAPFILES += partmap-normal_mod-normal_main.lst
+
+cmd-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu.o: normal/menu.c $(normal/menu.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu.d
+
+CLEANFILES += cmd-normal_mod-normal_menu.lst fs-normal_mod-normal_menu.lst partmap-normal_mod-normal_menu.lst
+COMMANDFILES += cmd-normal_mod-normal_menu.lst
+FSFILES += fs-normal_mod-normal_menu.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu.lst
+
+cmd-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_text.o: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_text.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_text.lst fs-normal_mod-normal_menu_text.lst partmap-normal_mod-normal_menu_text.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_text.lst
+FSFILES += fs-normal_mod-normal_menu_text.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_text.lst
+
+cmd-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_color.o: normal/color.c $(normal/color.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_color.d
+
+CLEANFILES += cmd-normal_mod-normal_color.lst fs-normal_mod-normal_color.lst partmap-normal_mod-normal_color.lst
+COMMANDFILES += cmd-normal_mod-normal_color.lst
+FSFILES += fs-normal_mod-normal_color.lst
+PARTMAPFILES += partmap-normal_mod-normal_color.lst
+
+cmd-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_viewer.o: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_viewer.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_viewer.lst fs-normal_mod-normal_menu_viewer.lst partmap-normal_mod-normal_menu_viewer.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_viewer.lst
+FSFILES += fs-normal_mod-normal_menu_viewer.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_viewer.lst
+
+cmd-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_entry.o: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_entry.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_entry.lst fs-normal_mod-normal_menu_entry.lst partmap-normal_mod-normal_menu_entry.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_entry.lst
+FSFILES += fs-normal_mod-normal_menu_entry.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_entry.lst
+
+cmd-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_misc.o: normal/misc.c $(normal/misc.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_misc.d
+
+CLEANFILES += cmd-normal_mod-normal_misc.lst fs-normal_mod-normal_misc.lst partmap-normal_mod-normal_misc.lst
+COMMANDFILES += cmd-normal_mod-normal_misc.lst
+FSFILES += fs-normal_mod-normal_misc.lst
+PARTMAPFILES += partmap-normal_mod-normal_misc.lst
+
+cmd-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-grub_script_tab.o: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES)
+       $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-grub_script_tab.d
+
+CLEANFILES += cmd-normal_mod-grub_script_tab.lst fs-normal_mod-grub_script_tab.lst partmap-normal_mod-grub_script_tab.lst
+COMMANDFILES += cmd-normal_mod-grub_script_tab.lst
+FSFILES += fs-normal_mod-grub_script_tab.lst
+PARTMAPFILES += partmap-normal_mod-grub_script_tab.lst
+
+cmd-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_script.o: normal/script.c $(normal/script.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_script.d
+
+CLEANFILES += cmd-normal_mod-normal_script.lst fs-normal_mod-normal_script.lst partmap-normal_mod-normal_script.lst
+COMMANDFILES += cmd-normal_mod-normal_script.lst
+FSFILES += fs-normal_mod-normal_script.lst
+PARTMAPFILES += partmap-normal_mod-normal_script.lst
+
+cmd-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_i386_setjmp.o: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES)
+       $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_i386_setjmp.d
+
+CLEANFILES += cmd-normal_mod-normal_i386_setjmp.lst fs-normal_mod-normal_i386_setjmp.lst partmap-normal_mod-normal_i386_setjmp.lst
+COMMANDFILES += cmd-normal_mod-normal_i386_setjmp.lst
+FSFILES += fs-normal_mod-normal_i386_setjmp.lst
+PARTMAPFILES += partmap-normal_mod-normal_i386_setjmp.lst
+
+cmd-normal_mod-normal_i386_setjmp.lst: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_i386_setjmp.lst: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<     | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_i386_setjmp.lst: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _chain.mod.
+_chain_mod_SOURCES = loader/efi/chainloader.c
+CLEANFILES += _chain.mod mod-_chain.o mod-_chain.c pre-_chain.o _chain_mod-loader_efi_chainloader.o und-_chain.lst
+ifneq ($(_chain_mod_EXPORTS),no)
+CLEANFILES += def-_chain.lst
+DEFSYMFILES += def-_chain.lst
+endif
+MOSTLYCLEANFILES += _chain_mod-loader_efi_chainloader.d
+UNDSYMFILES += und-_chain.lst
+
+_chain.mod: pre-_chain.o mod-_chain.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(_chain_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-_chain.o mod-_chain.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-_chain.o: $(_chain_mod_DEPENDENCIES) _chain_mod-loader_efi_chainloader.o
+       -rm -f $@
+       $(TARGET_CC) $(_chain_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ _chain_mod-loader_efi_chainloader.o
+
+mod-_chain.o: mod-_chain.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_chain_mod_CFLAGS) -c -o $@ $<
+
+mod-_chain.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '_chain' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(_chain_mod_EXPORTS),no)
+def-_chain.lst: pre-_chain.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _chain/' > $@
+endif
+
+und-_chain.lst: pre-_chain.o
+       echo '_chain' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+_chain_mod-loader_efi_chainloader.o: loader/efi/chainloader.c $(loader/efi/chainloader.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_chain_mod_CFLAGS) -MD -c -o $@ $<
+-include _chain_mod-loader_efi_chainloader.d
+
+CLEANFILES += cmd-_chain_mod-loader_efi_chainloader.lst fs-_chain_mod-loader_efi_chainloader.lst partmap-_chain_mod-loader_efi_chainloader.lst
+COMMANDFILES += cmd-_chain_mod-loader_efi_chainloader.lst
+FSFILES += fs-_chain_mod-loader_efi_chainloader.lst
+PARTMAPFILES += partmap-_chain_mod-loader_efi_chainloader.lst
+
+cmd-_chain_mod-loader_efi_chainloader.lst: loader/efi/chainloader.c $(loader/efi/chainloader.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_chain_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh _chain > $@ || (rm -f $@; exit 1)
+
+fs-_chain_mod-loader_efi_chainloader.lst: loader/efi/chainloader.c $(loader/efi/chainloader.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_chain_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh _chain > $@ || (rm -f $@; exit 1)
+
+partmap-_chain_mod-loader_efi_chainloader.lst: loader/efi/chainloader.c $(loader/efi/chainloader.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_chain_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh _chain > $@ || (rm -f $@; exit 1)
+
+
+_chain_mod_CFLAGS = $(COMMON_CFLAGS)
+_chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For chain.mod.
+chain_mod_SOURCES = loader/efi/chainloader_normal.c
+CLEANFILES += chain.mod mod-chain.o mod-chain.c pre-chain.o chain_mod-loader_efi_chainloader_normal.o und-chain.lst
+ifneq ($(chain_mod_EXPORTS),no)
+CLEANFILES += def-chain.lst
+DEFSYMFILES += def-chain.lst
+endif
+MOSTLYCLEANFILES += chain_mod-loader_efi_chainloader_normal.d
+UNDSYMFILES += und-chain.lst
+
+chain.mod: pre-chain.o mod-chain.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(chain_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-chain.o mod-chain.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-chain.o: $(chain_mod_DEPENDENCIES) chain_mod-loader_efi_chainloader_normal.o
+       -rm -f $@
+       $(TARGET_CC) $(chain_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ chain_mod-loader_efi_chainloader_normal.o
+
+mod-chain.o: mod-chain.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(chain_mod_CFLAGS) -c -o $@ $<
+
+mod-chain.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'chain' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(chain_mod_EXPORTS),no)
+def-chain.lst: pre-chain.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 chain/' > $@
+endif
+
+und-chain.lst: pre-chain.o
+       echo 'chain' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+chain_mod-loader_efi_chainloader_normal.o: loader/efi/chainloader_normal.c $(loader/efi/chainloader_normal.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(chain_mod_CFLAGS) -MD -c -o $@ $<
+-include chain_mod-loader_efi_chainloader_normal.d
+
+CLEANFILES += cmd-chain_mod-loader_efi_chainloader_normal.lst fs-chain_mod-loader_efi_chainloader_normal.lst partmap-chain_mod-loader_efi_chainloader_normal.lst
+COMMANDFILES += cmd-chain_mod-loader_efi_chainloader_normal.lst
+FSFILES += fs-chain_mod-loader_efi_chainloader_normal.lst
+PARTMAPFILES += partmap-chain_mod-loader_efi_chainloader_normal.lst
+
+cmd-chain_mod-loader_efi_chainloader_normal.lst: loader/efi/chainloader_normal.c $(loader/efi/chainloader_normal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(chain_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh chain > $@ || (rm -f $@; exit 1)
+
+fs-chain_mod-loader_efi_chainloader_normal.lst: loader/efi/chainloader_normal.c $(loader/efi/chainloader_normal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(chain_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh chain > $@ || (rm -f $@; exit 1)
+
+partmap-chain_mod-loader_efi_chainloader_normal.lst: loader/efi/chainloader_normal.c $(loader/efi/chainloader_normal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(chain_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh chain > $@ || (rm -f $@; exit 1)
+
+
+chain_mod_CFLAGS = $(COMMON_CFLAGS)
+chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For appleldr.mod.
+appleldr_mod_SOURCES = loader/efi/appleloader.c
+CLEANFILES += appleldr.mod mod-appleldr.o mod-appleldr.c pre-appleldr.o appleldr_mod-loader_efi_appleloader.o und-appleldr.lst
+ifneq ($(appleldr_mod_EXPORTS),no)
+CLEANFILES += def-appleldr.lst
+DEFSYMFILES += def-appleldr.lst
+endif
+MOSTLYCLEANFILES += appleldr_mod-loader_efi_appleloader.d
+UNDSYMFILES += und-appleldr.lst
+
+appleldr.mod: pre-appleldr.o mod-appleldr.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(appleldr_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-appleldr.o mod-appleldr.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-appleldr.o: $(appleldr_mod_DEPENDENCIES) appleldr_mod-loader_efi_appleloader.o
+       -rm -f $@
+       $(TARGET_CC) $(appleldr_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ appleldr_mod-loader_efi_appleloader.o
+
+mod-appleldr.o: mod-appleldr.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(appleldr_mod_CFLAGS) -c -o $@ $<
+
+mod-appleldr.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'appleldr' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(appleldr_mod_EXPORTS),no)
+def-appleldr.lst: pre-appleldr.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 appleldr/' > $@
+endif
+
+und-appleldr.lst: pre-appleldr.o
+       echo 'appleldr' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+appleldr_mod-loader_efi_appleloader.o: loader/efi/appleloader.c $(loader/efi/appleloader.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(appleldr_mod_CFLAGS) -MD -c -o $@ $<
+-include appleldr_mod-loader_efi_appleloader.d
+
+CLEANFILES += cmd-appleldr_mod-loader_efi_appleloader.lst fs-appleldr_mod-loader_efi_appleloader.lst partmap-appleldr_mod-loader_efi_appleloader.lst
+COMMANDFILES += cmd-appleldr_mod-loader_efi_appleloader.lst
+FSFILES += fs-appleldr_mod-loader_efi_appleloader.lst
+PARTMAPFILES += partmap-appleldr_mod-loader_efi_appleloader.lst
+
+cmd-appleldr_mod-loader_efi_appleloader.lst: loader/efi/appleloader.c $(loader/efi/appleloader.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(appleldr_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh appleldr > $@ || (rm -f $@; exit 1)
+
+fs-appleldr_mod-loader_efi_appleloader.lst: loader/efi/appleloader.c $(loader/efi/appleloader.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(appleldr_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh appleldr > $@ || (rm -f $@; exit 1)
+
+partmap-appleldr_mod-loader_efi_appleloader.lst: loader/efi/appleloader.c $(loader/efi/appleloader.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(appleldr_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh appleldr > $@ || (rm -f $@; exit 1)
+
+
+appleldr_mod_CFLAGS = $(COMMON_CFLAGS)
+appleldr_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _linux.mod.
+_linux_mod_SOURCES = loader/i386/efi/linux.c
+CLEANFILES += _linux.mod mod-_linux.o mod-_linux.c pre-_linux.o _linux_mod-loader_i386_efi_linux.o und-_linux.lst
+ifneq ($(_linux_mod_EXPORTS),no)
+CLEANFILES += def-_linux.lst
+DEFSYMFILES += def-_linux.lst
+endif
+MOSTLYCLEANFILES += _linux_mod-loader_i386_efi_linux.d
+UNDSYMFILES += und-_linux.lst
+
+_linux.mod: pre-_linux.o mod-_linux.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(_linux_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-_linux.o mod-_linux.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-_linux.o: $(_linux_mod_DEPENDENCIES) _linux_mod-loader_i386_efi_linux.o
+       -rm -f $@
+       $(TARGET_CC) $(_linux_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ _linux_mod-loader_i386_efi_linux.o
+
+mod-_linux.o: mod-_linux.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -c -o $@ $<
+
+mod-_linux.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '_linux' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(_linux_mod_EXPORTS),no)
+def-_linux.lst: pre-_linux.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _linux/' > $@
+endif
+
+und-_linux.lst: pre-_linux.o
+       echo '_linux' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+_linux_mod-loader_i386_efi_linux.o: loader/i386/efi/linux.c $(loader/i386/efi/linux.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/i386/efi -I$(srcdir)/loader/i386/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -MD -c -o $@ $<
+-include _linux_mod-loader_i386_efi_linux.d
+
+CLEANFILES += cmd-_linux_mod-loader_i386_efi_linux.lst fs-_linux_mod-loader_i386_efi_linux.lst partmap-_linux_mod-loader_i386_efi_linux.lst
+COMMANDFILES += cmd-_linux_mod-loader_i386_efi_linux.lst
+FSFILES += fs-_linux_mod-loader_i386_efi_linux.lst
+PARTMAPFILES += partmap-_linux_mod-loader_i386_efi_linux.lst
+
+cmd-_linux_mod-loader_i386_efi_linux.lst: loader/i386/efi/linux.c $(loader/i386/efi/linux.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/efi -I$(srcdir)/loader/i386/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh _linux > $@ || (rm -f $@; exit 1)
+
+fs-_linux_mod-loader_i386_efi_linux.lst: loader/i386/efi/linux.c $(loader/i386/efi/linux.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/efi -I$(srcdir)/loader/i386/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh _linux > $@ || (rm -f $@; exit 1)
+
+partmap-_linux_mod-loader_i386_efi_linux.lst: loader/i386/efi/linux.c $(loader/i386/efi/linux.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/efi -I$(srcdir)/loader/i386/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh _linux > $@ || (rm -f $@; exit 1)
+
+
+_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/linux_normal.c
+CLEANFILES += linux.mod mod-linux.o mod-linux.c pre-linux.o linux_mod-loader_linux_normal.o und-linux.lst
+ifneq ($(linux_mod_EXPORTS),no)
+CLEANFILES += def-linux.lst
+DEFSYMFILES += def-linux.lst
+endif
+MOSTLYCLEANFILES += linux_mod-loader_linux_normal.d
+UNDSYMFILES += und-linux.lst
+
+linux.mod: pre-linux.o mod-linux.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(linux_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-linux.o mod-linux.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-linux.o: $(linux_mod_DEPENDENCIES) linux_mod-loader_linux_normal.o
+       -rm -f $@
+       $(TARGET_CC) $(linux_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ linux_mod-loader_linux_normal.o
+
+mod-linux.o: mod-linux.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -c -o $@ $<
+
+mod-linux.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'linux' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(linux_mod_EXPORTS),no)
+def-linux.lst: pre-linux.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 linux/' > $@
+endif
+
+und-linux.lst: pre-linux.o
+       echo 'linux' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+linux_mod-loader_linux_normal.o: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -MD -c -o $@ $<
+-include linux_mod-loader_linux_normal.d
+
+CLEANFILES += cmd-linux_mod-loader_linux_normal.lst fs-linux_mod-loader_linux_normal.lst partmap-linux_mod-loader_linux_normal.lst
+COMMANDFILES += cmd-linux_mod-loader_linux_normal.lst
+FSFILES += fs-linux_mod-loader_linux_normal.lst
+PARTMAPFILES += partmap-linux_mod-loader_linux_normal.lst
+
+cmd-linux_mod-loader_linux_normal.lst: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh linux > $@ || (rm -f $@; exit 1)
+
+fs-linux_mod-loader_linux_normal.lst: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh linux > $@ || (rm -f $@; exit 1)
+
+partmap-linux_mod-loader_linux_normal.lst: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh linux > $@ || (rm -f $@; exit 1)
+
+
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For halt.mod.
+halt_mod_SOURCES = commands/halt.c
+CLEANFILES += halt.mod mod-halt.o mod-halt.c pre-halt.o halt_mod-commands_halt.o und-halt.lst
+ifneq ($(halt_mod_EXPORTS),no)
+CLEANFILES += def-halt.lst
+DEFSYMFILES += def-halt.lst
+endif
+MOSTLYCLEANFILES += halt_mod-commands_halt.d
+UNDSYMFILES += und-halt.lst
+
+halt.mod: pre-halt.o mod-halt.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(halt_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-halt.o mod-halt.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-halt.o: $(halt_mod_DEPENDENCIES) halt_mod-commands_halt.o
+       -rm -f $@
+       $(TARGET_CC) $(halt_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ halt_mod-commands_halt.o
+
+mod-halt.o: mod-halt.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -c -o $@ $<
+
+mod-halt.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'halt' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(halt_mod_EXPORTS),no)
+def-halt.lst: pre-halt.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 halt/' > $@
+endif
+
+und-halt.lst: pre-halt.o
+       echo 'halt' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+halt_mod-commands_halt.o: commands/halt.c $(commands/halt.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -MD -c -o $@ $<
+-include halt_mod-commands_halt.d
+
+CLEANFILES += cmd-halt_mod-commands_halt.lst fs-halt_mod-commands_halt.lst partmap-halt_mod-commands_halt.lst
+COMMANDFILES += cmd-halt_mod-commands_halt.lst
+FSFILES += fs-halt_mod-commands_halt.lst
+PARTMAPFILES += partmap-halt_mod-commands_halt.lst
+
+cmd-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh halt > $@ || (rm -f $@; exit 1)
+
+fs-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh halt > $@ || (rm -f $@; exit 1)
+
+partmap-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh halt > $@ || (rm -f $@; exit 1)
+
+
+halt_mod_CFLAGS = $(COMMON_CFLAGS)
+halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reboot.mod.
+reboot_mod_SOURCES = commands/reboot.c
+CLEANFILES += reboot.mod mod-reboot.o mod-reboot.c pre-reboot.o reboot_mod-commands_reboot.o und-reboot.lst
+ifneq ($(reboot_mod_EXPORTS),no)
+CLEANFILES += def-reboot.lst
+DEFSYMFILES += def-reboot.lst
+endif
+MOSTLYCLEANFILES += reboot_mod-commands_reboot.d
+UNDSYMFILES += und-reboot.lst
+
+reboot.mod: pre-reboot.o mod-reboot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(reboot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-reboot.o mod-reboot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-reboot.o: $(reboot_mod_DEPENDENCIES) reboot_mod-commands_reboot.o
+       -rm -f $@
+       $(TARGET_CC) $(reboot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ reboot_mod-commands_reboot.o
+
+mod-reboot.o: mod-reboot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -c -o $@ $<
+
+mod-reboot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'reboot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(reboot_mod_EXPORTS),no)
+def-reboot.lst: pre-reboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 reboot/' > $@
+endif
+
+und-reboot.lst: pre-reboot.o
+       echo 'reboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+reboot_mod-commands_reboot.o: commands/reboot.c $(commands/reboot.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -MD -c -o $@ $<
+-include reboot_mod-commands_reboot.d
+
+CLEANFILES += cmd-reboot_mod-commands_reboot.lst fs-reboot_mod-commands_reboot.lst partmap-reboot_mod-commands_reboot.lst
+COMMANDFILES += cmd-reboot_mod-commands_reboot.lst
+FSFILES += fs-reboot_mod-commands_reboot.lst
+PARTMAPFILES += partmap-reboot_mod-commands_reboot.lst
+
+cmd-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh reboot > $@ || (rm -f $@; exit 1)
+
+fs-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh reboot > $@ || (rm -f $@; exit 1)
+
+partmap-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh reboot > $@ || (rm -f $@; exit 1)
+
+
+reboot_mod_CFLAGS = $(COMMON_CFLAGS)
+reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+CLEANFILES += pci.mod mod-pci.o mod-pci.c pre-pci.o pci_mod-bus_pci.o und-pci.lst
+ifneq ($(pci_mod_EXPORTS),no)
+CLEANFILES += def-pci.lst
+DEFSYMFILES += def-pci.lst
+endif
+MOSTLYCLEANFILES += pci_mod-bus_pci.d
+UNDSYMFILES += und-pci.lst
+
+pci.mod: pre-pci.o mod-pci.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(pci_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-pci.o mod-pci.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-pci.o: $(pci_mod_DEPENDENCIES) pci_mod-bus_pci.o
+       -rm -f $@
+       $(TARGET_CC) $(pci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pci_mod-bus_pci.o
+
+mod-pci.o: mod-pci.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -c -o $@ $<
+
+mod-pci.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'pci' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(pci_mod_EXPORTS),no)
+def-pci.lst: pre-pci.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 pci/' > $@
+endif
+
+und-pci.lst: pre-pci.o
+       echo 'pci' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+pci_mod-bus_pci.o: bus/pci.c $(bus/pci.c_DEPENDENCIES)
+       $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -MD -c -o $@ $<
+-include pci_mod-bus_pci.d
+
+CLEANFILES += cmd-pci_mod-bus_pci.lst fs-pci_mod-bus_pci.lst partmap-pci_mod-bus_pci.lst
+COMMANDFILES += cmd-pci_mod-bus_pci.lst
+FSFILES += fs-pci_mod-bus_pci.lst
+PARTMAPFILES += partmap-pci_mod-bus_pci.lst
+
+cmd-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh pci > $@ || (rm -f $@; exit 1)
+
+fs-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh pci > $@ || (rm -f $@; exit 1)
+
+partmap-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh pci > $@ || (rm -f $@; exit 1)
+
+
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+CLEANFILES += lspci.mod mod-lspci.o mod-lspci.c pre-lspci.o lspci_mod-commands_lspci.o und-lspci.lst
+ifneq ($(lspci_mod_EXPORTS),no)
+CLEANFILES += def-lspci.lst
+DEFSYMFILES += def-lspci.lst
+endif
+MOSTLYCLEANFILES += lspci_mod-commands_lspci.d
+UNDSYMFILES += und-lspci.lst
+
+lspci.mod: pre-lspci.o mod-lspci.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(lspci_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-lspci.o mod-lspci.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-lspci.o: $(lspci_mod_DEPENDENCIES) lspci_mod-commands_lspci.o
+       -rm -f $@
+       $(TARGET_CC) $(lspci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ lspci_mod-commands_lspci.o
+
+mod-lspci.o: mod-lspci.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -c -o $@ $<
+
+mod-lspci.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'lspci' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(lspci_mod_EXPORTS),no)
+def-lspci.lst: pre-lspci.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 lspci/' > $@
+endif
+
+und-lspci.lst: pre-lspci.o
+       echo 'lspci' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+lspci_mod-commands_lspci.o: commands/lspci.c $(commands/lspci.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -MD -c -o $@ $<
+-include lspci_mod-commands_lspci.d
+
+CLEANFILES += cmd-lspci_mod-commands_lspci.lst fs-lspci_mod-commands_lspci.lst partmap-lspci_mod-commands_lspci.lst
+COMMANDFILES += cmd-lspci_mod-commands_lspci.lst
+FSFILES += fs-lspci_mod-commands_lspci.lst
+PARTMAPFILES += partmap-lspci_mod-commands_lspci.lst
+
+cmd-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh lspci > $@ || (rm -f $@; exit 1)
+
+fs-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh lspci > $@ || (rm -f $@; exit 1)
+
+partmap-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh lspci > $@ || (rm -f $@; exit 1)
+
+
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datetime.mod
+datetime_mod_SOURCES = lib/datetime.c lib/efi/datetime.c
+CLEANFILES += datetime.mod mod-datetime.o mod-datetime.c pre-datetime.o datetime_mod-lib_datetime.o datetime_mod-lib_efi_datetime.o und-datetime.lst
+ifneq ($(datetime_mod_EXPORTS),no)
+CLEANFILES += def-datetime.lst
+DEFSYMFILES += def-datetime.lst
+endif
+MOSTLYCLEANFILES += datetime_mod-lib_datetime.d datetime_mod-lib_efi_datetime.d
+UNDSYMFILES += und-datetime.lst
+
+datetime.mod: pre-datetime.o mod-datetime.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(datetime_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-datetime.o mod-datetime.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-datetime.o: $(datetime_mod_DEPENDENCIES) datetime_mod-lib_datetime.o datetime_mod-lib_efi_datetime.o
+       -rm -f $@
+       $(TARGET_CC) $(datetime_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ datetime_mod-lib_datetime.o datetime_mod-lib_efi_datetime.o
+
+mod-datetime.o: mod-datetime.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -c -o $@ $<
+
+mod-datetime.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'datetime' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(datetime_mod_EXPORTS),no)
+def-datetime.lst: pre-datetime.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 datetime/' > $@
+endif
+
+und-datetime.lst: pre-datetime.o
+       echo 'datetime' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+datetime_mod-lib_datetime.o: lib/datetime.c $(lib/datetime.c_DEPENDENCIES)
+       $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -MD -c -o $@ $<
+-include datetime_mod-lib_datetime.d
+
+CLEANFILES += cmd-datetime_mod-lib_datetime.lst fs-datetime_mod-lib_datetime.lst partmap-datetime_mod-lib_datetime.lst
+COMMANDFILES += cmd-datetime_mod-lib_datetime.lst
+FSFILES += fs-datetime_mod-lib_datetime.lst
+PARTMAPFILES += partmap-datetime_mod-lib_datetime.lst
+
+cmd-datetime_mod-lib_datetime.lst: lib/datetime.c $(lib/datetime.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh datetime > $@ || (rm -f $@; exit 1)
+
+fs-datetime_mod-lib_datetime.lst: lib/datetime.c $(lib/datetime.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh datetime > $@ || (rm -f $@; exit 1)
+
+partmap-datetime_mod-lib_datetime.lst: lib/datetime.c $(lib/datetime.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh datetime > $@ || (rm -f $@; exit 1)
+
+
+datetime_mod-lib_efi_datetime.o: lib/efi/datetime.c $(lib/efi/datetime.c_DEPENDENCIES)
+       $(TARGET_CC) -Ilib/efi -I$(srcdir)/lib/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -MD -c -o $@ $<
+-include datetime_mod-lib_efi_datetime.d
+
+CLEANFILES += cmd-datetime_mod-lib_efi_datetime.lst fs-datetime_mod-lib_efi_datetime.lst partmap-datetime_mod-lib_efi_datetime.lst
+COMMANDFILES += cmd-datetime_mod-lib_efi_datetime.lst
+FSFILES += fs-datetime_mod-lib_efi_datetime.lst
+PARTMAPFILES += partmap-datetime_mod-lib_efi_datetime.lst
+
+cmd-datetime_mod-lib_efi_datetime.lst: lib/efi/datetime.c $(lib/efi/datetime.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ilib/efi -I$(srcdir)/lib/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh datetime > $@ || (rm -f $@; exit 1)
+
+fs-datetime_mod-lib_efi_datetime.lst: lib/efi/datetime.c $(lib/efi/datetime.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ilib/efi -I$(srcdir)/lib/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh datetime > $@ || (rm -f $@; exit 1)
+
+partmap-datetime_mod-lib_efi_datetime.lst: lib/efi/datetime.c $(lib/efi/datetime.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ilib/efi -I$(srcdir)/lib/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh datetime > $@ || (rm -f $@; exit 1)
+
+
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+CLEANFILES += date.mod mod-date.o mod-date.c pre-date.o date_mod-commands_date.o und-date.lst
+ifneq ($(date_mod_EXPORTS),no)
+CLEANFILES += def-date.lst
+DEFSYMFILES += def-date.lst
+endif
+MOSTLYCLEANFILES += date_mod-commands_date.d
+UNDSYMFILES += und-date.lst
+
+date.mod: pre-date.o mod-date.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(date_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-date.o mod-date.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-date.o: $(date_mod_DEPENDENCIES) date_mod-commands_date.o
+       -rm -f $@
+       $(TARGET_CC) $(date_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ date_mod-commands_date.o
+
+mod-date.o: mod-date.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -c -o $@ $<
+
+mod-date.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'date' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(date_mod_EXPORTS),no)
+def-date.lst: pre-date.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 date/' > $@
+endif
+
+und-date.lst: pre-date.o
+       echo 'date' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+date_mod-commands_date.o: commands/date.c $(commands/date.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(date_mod_CFLAGS) -MD -c -o $@ $<
+-include date_mod-commands_date.d
+
+CLEANFILES += cmd-date_mod-commands_date.lst fs-date_mod-commands_date.lst partmap-date_mod-commands_date.lst
+COMMANDFILES += cmd-date_mod-commands_date.lst
+FSFILES += fs-date_mod-commands_date.lst
+PARTMAPFILES += partmap-date_mod-commands_date.lst
+
+cmd-date_mod-commands_date.lst: commands/date.c $(commands/date.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh date > $@ || (rm -f $@; exit 1)
+
+fs-date_mod-commands_date.lst: commands/date.c $(commands/date.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh date > $@ || (rm -f $@; exit 1)
+
+partmap-date_mod-commands_date.lst: commands/date.c $(commands/date.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh date > $@ || (rm -f $@; exit 1)
+
+
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datehook.mod
+datehook_mod_SOURCES = hook/datehook.c
+CLEANFILES += datehook.mod mod-datehook.o mod-datehook.c pre-datehook.o datehook_mod-hook_datehook.o und-datehook.lst
+ifneq ($(datehook_mod_EXPORTS),no)
+CLEANFILES += def-datehook.lst
+DEFSYMFILES += def-datehook.lst
+endif
+MOSTLYCLEANFILES += datehook_mod-hook_datehook.d
+UNDSYMFILES += und-datehook.lst
+
+datehook.mod: pre-datehook.o mod-datehook.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(datehook_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-datehook.o mod-datehook.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-datehook.o: $(datehook_mod_DEPENDENCIES) datehook_mod-hook_datehook.o
+       -rm -f $@
+       $(TARGET_CC) $(datehook_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ datehook_mod-hook_datehook.o
+
+mod-datehook.o: mod-datehook.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -c -o $@ $<
+
+mod-datehook.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'datehook' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(datehook_mod_EXPORTS),no)
+def-datehook.lst: pre-datehook.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 datehook/' > $@
+endif
+
+und-datehook.lst: pre-datehook.o
+       echo 'datehook' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+datehook_mod-hook_datehook.o: hook/datehook.c $(hook/datehook.c_DEPENDENCIES)
+       $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -MD -c -o $@ $<
+-include datehook_mod-hook_datehook.d
+
+CLEANFILES += cmd-datehook_mod-hook_datehook.lst fs-datehook_mod-hook_datehook.lst partmap-datehook_mod-hook_datehook.lst
+COMMANDFILES += cmd-datehook_mod-hook_datehook.lst
+FSFILES += fs-datehook_mod-hook_datehook.lst
+PARTMAPFILES += partmap-datehook_mod-hook_datehook.lst
+
+cmd-datehook_mod-hook_datehook.lst: hook/datehook.c $(hook/datehook.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh datehook > $@ || (rm -f $@; exit 1)
+
+fs-datehook_mod-hook_datehook.lst: hook/datehook.c $(hook/datehook.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh datehook > $@ || (rm -f $@; exit 1)
+
+partmap-datehook_mod-hook_datehook.lst: hook/datehook.c $(hook/datehook.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh datehook > $@ || (rm -f $@; exit 1)
+
+
+datehook_mod_CFLAGS = $(COMMON_CFLAGS)
+datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+include $(srcdir)/conf/i386.mk
+include $(srcdir)/conf/common.mk
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
new file mode 100644 (file)
index 0000000..3814abb
--- /dev/null
@@ -0,0 +1,195 @@
+# -*- makefile -*-
+
+COMMON_ASFLAGS = -nostdinc -fno-builtin -m32
+COMMON_CFLAGS = -fno-builtin -m32
+COMMON_LDFLAGS = -melf_i386 -nostdlib
+
+# Used by various components.  These rules need to precede them.
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Utilities.
+bin_UTILITIES = grub-mkimage
+sbin_UTILITIES = grub-mkdevicemap
+#ifeq ($(enable_grub_emu), yes)
+#sbin_UTILITIES += grub-emu
+#endif
+
+# For grub-mkimage.
+grub_mkimage_SOURCES = util/i386/efi/grub-mkimage.c util/misc.c \
+       util/resolve.c
+util/i386/efi/grub-mkimage.c_DEPENDENCIES = Makefile
+
+# For grub-setup.
+#grub_setup_SOURCES = util/i386/pc/grub-setup.c util/hostdisk.c        \
+#      util/misc.c util/getroot.c kern/device.c kern/disk.c    \
+#      kern/err.c kern/misc.c fs/fat.c fs/ext2.c fs/xfs.c fs/affs.c    \
+#      fs/sfs.c kern/parser.c kern/partition.c partmap/pc.c            \
+#      fs/ufs.c fs/minix.c fs/hfs.c fs/jfs.c fs/hfsplus.c kern/file.c  \
+#      kern/fs.c kern/env.c fs/fshelp.c
+
+# For grub-mkdevicemap.
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+
+# For grub-emu.
+util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
+grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c       \
+       commands/configfile.c commands/help.c                           \
+       commands/terminal.c commands/ls.c commands/test.c               \
+       commands/search.c commands/hexdump.c lib/hexdump.c              \
+       commands/halt.c commands/reboot.c                               \
+       commands/i386/cpuid.c                                           \
+       disk/loopback.c                                                 \
+       \
+       fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c                 \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c          \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c                  \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                             \
+       \
+       io/gzio.c                                                       \
+       kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c       \
+       kern/err.c                                                      \
+       normal/execute.c kern/file.c kern/fs.c normal/lexer.c           \
+       kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
+       grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
+       normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
+       normal/completion.c normal/context.c normal/main.c              \
+       normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
+       normal/menu_text.c                                              \
+       normal/misc.c normal/script.c                                   \
+       normal/color.c                                                  \
+       partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
+       partmap/acorn.c partmap/gpt.c                                   \
+       util/console.c util/hostfs.c util/grub-emu.c util/misc.c        \
+       util/hostdisk.c util/getroot.c                                  \
+       util/i386/pc/misc.c                                             \
+       \
+       disk/raid.c disk/raid5_recover.c disk/raid6_recover.c           \
+       disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c             \
+       grub_emu_init.c
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+# Scripts.
+sbin_SCRIPTS = grub-install
+
+# For grub-install.
+grub_install_SOURCES = util/i386/efi/grub-install.in
+
+# Modules.
+pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
+       _linux.mod linux.mod halt.mod reboot.mod pci.mod lspci.mod \
+       datetime.mod date.mod datehook.mod
+
+# For kernel.mod.
+kernel_mod_EXPORTS = no
+kernel_mod_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.c \
+       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
+       kern/i386/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \
+       kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \
+       term/efi/console.c disk/efi/efidisk.c \
+       kern/time.c \
+       kern/i386/tsc.c kern/i386/pit.c \
+       kern/generic/rtc_get_time_ms.c \
+       kern/generic/millisleep.c
+kernel_mod_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
+       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
+       partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
+       efi/efi.h efi/time.h efi/disk.h
+kernel_mod_CFLAGS = $(COMMON_CFLAGS)
+kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+MOSTLYCLEANFILES += symlist.c
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+symlist.c: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h gensymlist.sh
+       /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h genkernsyms.sh
+       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+#
+# Only arch dependant part of normal.mod will be here. Common part for
+# all architecures of normal.mod is at start and should be kept at sync
+# with other makefiles.
+# 
+# Please put arch dependant part of normal.mod at the end of list to
+# keep it simpler to update to different architectures.
+#
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/color.c                                                  \
+       normal/menu_viewer.c normal/menu_entry.c                        \
+       normal/misc.c grub_script.tab.c                                 \
+       normal/script.c                                                 \
+       normal/i386/setjmp.S
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _chain.mod.
+_chain_mod_SOURCES = loader/efi/chainloader.c
+_chain_mod_CFLAGS = $(COMMON_CFLAGS)
+_chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For chain.mod.
+chain_mod_SOURCES = loader/efi/chainloader_normal.c
+chain_mod_CFLAGS = $(COMMON_CFLAGS)
+chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For appleldr.mod.
+appleldr_mod_SOURCES = loader/efi/appleloader.c
+appleldr_mod_CFLAGS = $(COMMON_CFLAGS)
+appleldr_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _linux.mod.
+_linux_mod_SOURCES = loader/i386/efi/linux.c
+_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/linux_normal.c
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For halt.mod.
+halt_mod_SOURCES = commands/halt.c
+halt_mod_CFLAGS = $(COMMON_CFLAGS)
+halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reboot.mod.
+reboot_mod_SOURCES = commands/reboot.c
+reboot_mod_CFLAGS = $(COMMON_CFLAGS)
+reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datetime.mod
+datetime_mod_SOURCES = lib/datetime.c lib/efi/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datehook.mod
+datehook_mod_SOURCES = hook/datehook.c
+datehook_mod_CFLAGS = $(COMMON_CFLAGS)
+datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+include $(srcdir)/conf/i386.mk
+include $(srcdir)/conf/common.mk
diff --git a/conf/i386-ieee1275.mk b/conf/i386-ieee1275.mk
new file mode 100644 (file)
index 0000000..504a185
--- /dev/null
@@ -0,0 +1,2012 @@
+# -*- makefile -*-
+# Generated by genmk.rb, please don't edit!
+
+COMMON_ASFLAGS = -m32 -nostdinc -fno-builtin
+COMMON_CFLAGS  = -ffreestanding -mrtd -mregparm=3
+COMMON_LDFLAGS = -nostdlib -static -lgcc
+
+# Used by various components.  These rules need to precede them.
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Images.
+pkglib_PROGRAMS = kernel.elf
+
+# For kernel.elf.
+kernel_elf_SOURCES = kern/i386/ieee1275/startup.S kern/i386/ieee1275/init.c \
+       kern/ieee1275/init.c \
+       kern/ieee1275/mmap.c \
+       kern/ieee1275/cmain.c kern/ieee1275/openfw.c \
+       kern/main.c kern/device.c \
+       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
+       kern/i386/dl.c kern/parser.c kern/partition.c \
+       kern/env.c \
+       kern/time.c \
+       kern/generic/millisleep.c \
+       kern/ieee1275/ieee1275.c \
+       term/ieee1275/ofconsole.c \
+       disk/ieee1275/ofdisk.c \
+       symlist.c
+CLEANFILES += kernel.elf kernel_elf-kern_i386_ieee1275_startup.o kernel_elf-kern_i386_ieee1275_init.o kernel_elf-kern_ieee1275_init.o kernel_elf-kern_ieee1275_mmap.o kernel_elf-kern_ieee1275_cmain.o kernel_elf-kern_ieee1275_openfw.o kernel_elf-kern_main.o kernel_elf-kern_device.o kernel_elf-kern_disk.o kernel_elf-kern_dl.o kernel_elf-kern_file.o kernel_elf-kern_fs.o kernel_elf-kern_err.o kernel_elf-kern_misc.o kernel_elf-kern_mm.o kernel_elf-kern_loader.o kernel_elf-kern_rescue.o kernel_elf-kern_term.o kernel_elf-kern_i386_dl.o kernel_elf-kern_parser.o kernel_elf-kern_partition.o kernel_elf-kern_env.o kernel_elf-kern_time.o kernel_elf-kern_generic_millisleep.o kernel_elf-kern_ieee1275_ieee1275.o kernel_elf-term_ieee1275_ofconsole.o kernel_elf-disk_ieee1275_ofdisk.o kernel_elf-symlist.o
+MOSTLYCLEANFILES += kernel_elf-kern_i386_ieee1275_startup.d kernel_elf-kern_i386_ieee1275_init.d kernel_elf-kern_ieee1275_init.d kernel_elf-kern_ieee1275_mmap.d kernel_elf-kern_ieee1275_cmain.d kernel_elf-kern_ieee1275_openfw.d kernel_elf-kern_main.d kernel_elf-kern_device.d kernel_elf-kern_disk.d kernel_elf-kern_dl.d kernel_elf-kern_file.d kernel_elf-kern_fs.d kernel_elf-kern_err.d kernel_elf-kern_misc.d kernel_elf-kern_mm.d kernel_elf-kern_loader.d kernel_elf-kern_rescue.d kernel_elf-kern_term.d kernel_elf-kern_i386_dl.d kernel_elf-kern_parser.d kernel_elf-kern_partition.d kernel_elf-kern_env.d kernel_elf-kern_time.d kernel_elf-kern_generic_millisleep.d kernel_elf-kern_ieee1275_ieee1275.d kernel_elf-term_ieee1275_ofconsole.d kernel_elf-disk_ieee1275_ofdisk.d kernel_elf-symlist.d
+
+kernel.elf: $(kernel_elf_DEPENDENCIES) kernel_elf-kern_i386_ieee1275_startup.o kernel_elf-kern_i386_ieee1275_init.o kernel_elf-kern_ieee1275_init.o kernel_elf-kern_ieee1275_mmap.o kernel_elf-kern_ieee1275_cmain.o kernel_elf-kern_ieee1275_openfw.o kernel_elf-kern_main.o kernel_elf-kern_device.o kernel_elf-kern_disk.o kernel_elf-kern_dl.o kernel_elf-kern_file.o kernel_elf-kern_fs.o kernel_elf-kern_err.o kernel_elf-kern_misc.o kernel_elf-kern_mm.o kernel_elf-kern_loader.o kernel_elf-kern_rescue.o kernel_elf-kern_term.o kernel_elf-kern_i386_dl.o kernel_elf-kern_parser.o kernel_elf-kern_partition.o kernel_elf-kern_env.o kernel_elf-kern_time.o kernel_elf-kern_generic_millisleep.o kernel_elf-kern_ieee1275_ieee1275.o kernel_elf-term_ieee1275_ofconsole.o kernel_elf-disk_ieee1275_ofdisk.o kernel_elf-symlist.o
+       $(TARGET_CC) -o $@ kernel_elf-kern_i386_ieee1275_startup.o kernel_elf-kern_i386_ieee1275_init.o kernel_elf-kern_ieee1275_init.o kernel_elf-kern_ieee1275_mmap.o kernel_elf-kern_ieee1275_cmain.o kernel_elf-kern_ieee1275_openfw.o kernel_elf-kern_main.o kernel_elf-kern_device.o kernel_elf-kern_disk.o kernel_elf-kern_dl.o kernel_elf-kern_file.o kernel_elf-kern_fs.o kernel_elf-kern_err.o kernel_elf-kern_misc.o kernel_elf-kern_mm.o kernel_elf-kern_loader.o kernel_elf-kern_rescue.o kernel_elf-kern_term.o kernel_elf-kern_i386_dl.o kernel_elf-kern_parser.o kernel_elf-kern_partition.o kernel_elf-kern_env.o kernel_elf-kern_time.o kernel_elf-kern_generic_millisleep.o kernel_elf-kern_ieee1275_ieee1275.o kernel_elf-term_ieee1275_ofconsole.o kernel_elf-disk_ieee1275_ofdisk.o kernel_elf-symlist.o $(TARGET_LDFLAGS) $(kernel_elf_LDFLAGS)
+
+kernel_elf-kern_i386_ieee1275_startup.o: kern/i386/ieee1275/startup.S $(kern/i386/ieee1275/startup.S_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386/ieee1275 -I$(srcdir)/kern/i386/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_i386_ieee1275_startup.d
+
+kernel_elf-kern_i386_ieee1275_init.o: kern/i386/ieee1275/init.c $(kern/i386/ieee1275/init.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386/ieee1275 -I$(srcdir)/kern/i386/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_i386_ieee1275_init.d
+
+kernel_elf-kern_ieee1275_init.o: kern/ieee1275/init.c $(kern/ieee1275/init.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/ieee1275 -I$(srcdir)/kern/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_ieee1275_init.d
+
+kernel_elf-kern_ieee1275_mmap.o: kern/ieee1275/mmap.c $(kern/ieee1275/mmap.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/ieee1275 -I$(srcdir)/kern/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_ieee1275_mmap.d
+
+kernel_elf-kern_ieee1275_cmain.o: kern/ieee1275/cmain.c $(kern/ieee1275/cmain.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/ieee1275 -I$(srcdir)/kern/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_ieee1275_cmain.d
+
+kernel_elf-kern_ieee1275_openfw.o: kern/ieee1275/openfw.c $(kern/ieee1275/openfw.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/ieee1275 -I$(srcdir)/kern/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_ieee1275_openfw.d
+
+kernel_elf-kern_main.o: kern/main.c $(kern/main.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_main.d
+
+kernel_elf-kern_device.o: kern/device.c $(kern/device.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_device.d
+
+kernel_elf-kern_disk.o: kern/disk.c $(kern/disk.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_disk.d
+
+kernel_elf-kern_dl.o: kern/dl.c $(kern/dl.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_dl.d
+
+kernel_elf-kern_file.o: kern/file.c $(kern/file.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_file.d
+
+kernel_elf-kern_fs.o: kern/fs.c $(kern/fs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_fs.d
+
+kernel_elf-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_err.d
+
+kernel_elf-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_misc.d
+
+kernel_elf-kern_mm.o: kern/mm.c $(kern/mm.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_mm.d
+
+kernel_elf-kern_loader.o: kern/loader.c $(kern/loader.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_loader.d
+
+kernel_elf-kern_rescue.o: kern/rescue.c $(kern/rescue.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_rescue.d
+
+kernel_elf-kern_term.o: kern/term.c $(kern/term.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_term.d
+
+kernel_elf-kern_i386_dl.o: kern/i386/dl.c $(kern/i386/dl.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_i386_dl.d
+
+kernel_elf-kern_parser.o: kern/parser.c $(kern/parser.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_parser.d
+
+kernel_elf-kern_partition.o: kern/partition.c $(kern/partition.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_partition.d
+
+kernel_elf-kern_env.o: kern/env.c $(kern/env.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_env.d
+
+kernel_elf-kern_time.o: kern/time.c $(kern/time.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_time.d
+
+kernel_elf-kern_generic_millisleep.o: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_generic_millisleep.d
+
+kernel_elf-kern_ieee1275_ieee1275.o: kern/ieee1275/ieee1275.c $(kern/ieee1275/ieee1275.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/ieee1275 -I$(srcdir)/kern/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_ieee1275_ieee1275.d
+
+kernel_elf-term_ieee1275_ofconsole.o: term/ieee1275/ofconsole.c $(term/ieee1275/ofconsole.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/ieee1275 -I$(srcdir)/term/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-term_ieee1275_ofconsole.d
+
+kernel_elf-disk_ieee1275_ofdisk.o: disk/ieee1275/ofdisk.c $(disk/ieee1275/ofdisk.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk/ieee1275 -I$(srcdir)/disk/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-disk_ieee1275_ofdisk.d
+
+kernel_elf-symlist.o: symlist.c $(symlist.c_DEPENDENCIES)
+       $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-symlist.d
+
+kernel_elf_HEADERS = arg.h cache.h device.h disk.h dl.h elf.h elfload.h \
+       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
+       partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
+       ieee1275/ieee1275.h machine/kernel.h machine/loader.h machine/memory.h
+kernel_elf_CFLAGS = $(COMMON_CFLAGS)
+kernel_elf_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x10000,-Bstatic
+
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+symlist.c: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h gensymlist.sh
+       /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h genkernsyms.sh
+       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+# Utilities.
+sbin_UTILITIES = grub-mkdevicemap
+ifeq ($(enable_grub_emu), yes)
+sbin_UTILITIES += grub-emu
+endif
+
+# For grub-mkdevicemap.
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+CLEANFILES += grub-mkdevicemap$(EXEEXT) grub_mkdevicemap-util_grub_mkdevicemap.o grub_mkdevicemap-util_misc.o
+MOSTLYCLEANFILES += grub_mkdevicemap-util_grub_mkdevicemap.d grub_mkdevicemap-util_misc.d
+
+grub-mkdevicemap: $(grub_mkdevicemap_DEPENDENCIES) grub_mkdevicemap-util_grub_mkdevicemap.o grub_mkdevicemap-util_misc.o
+       $(CC) -o $@ grub_mkdevicemap-util_grub_mkdevicemap.o grub_mkdevicemap-util_misc.o $(LDFLAGS) $(grub_mkdevicemap_LDFLAGS)
+
+grub_mkdevicemap-util_grub_mkdevicemap.o: util/grub-mkdevicemap.c $(util/grub-mkdevicemap.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkdevicemap_CFLAGS) -MD -c -o $@ $<
+-include grub_mkdevicemap-util_grub_mkdevicemap.d
+
+grub_mkdevicemap-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkdevicemap_CFLAGS) -MD -c -o $@ $<
+-include grub_mkdevicemap-util_misc.d
+
+
+# For grub-emu.
+util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
+grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c       \
+       commands/configfile.c commands/echo.c commands/help.c           \
+       commands/terminal.c commands/ls.c commands/test.c               \
+       commands/search.c commands/blocklist.c commands/hexdump.c       \
+       lib/hexdump.c commands/halt.c commands/reboot.c                 \
+       commands/i386/cpuid.c                                           \
+       disk/host.c disk/loopback.c                                     \
+       \
+       fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c                 \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c          \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c                  \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                             \
+       \
+       fs/fshelp.c                                                     \
+       io/gzio.c                                                       \
+       kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c       \
+       kern/err.c                                                      \
+       normal/execute.c kern/file.c kern/fs.c normal/lexer.c           \
+       kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
+       grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
+       normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
+       normal/completion.c normal/main.c normal/menu_text.c            \
+       normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
+       normal/misc.c normal/script.c                                   \
+       normal/color.c                                                  \
+       partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
+       partmap/acorn.c partmap/gpt.c                                   \
+       util/console.c util/hostfs.c util/grub-emu.c util/misc.c        \
+       util/hostdisk.c util/getroot.c                                  \
+       util/i386/pc/misc.c                                             \
+       \
+       disk/raid.c disk/raid5_recover.c disk/raid6_recover.c           \
+       disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c             \
+       grub_emu_init.c
+CLEANFILES += grub-emu$(EXEEXT) grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_echo.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_halt.o grub_emu-commands_reboot.o grub_emu-commands_i386_cpuid.o grub_emu-disk_host.o grub_emu-disk_loopback.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_fat.o grub_emu-fs_ext2.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-fs_fshelp.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_main.o grub_emu-normal_menu_text.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-normal_color.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-partmap_gpt.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_i386_pc_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_emu_init.o
+MOSTLYCLEANFILES += grub_emu-commands_boot.d grub_emu-commands_cat.d grub_emu-commands_cmp.d grub_emu-commands_configfile.d grub_emu-commands_echo.d grub_emu-commands_help.d grub_emu-commands_terminal.d grub_emu-commands_ls.d grub_emu-commands_test.d grub_emu-commands_search.d grub_emu-commands_blocklist.d grub_emu-commands_hexdump.d grub_emu-lib_hexdump.d grub_emu-commands_halt.d grub_emu-commands_reboot.d grub_emu-commands_i386_cpuid.d grub_emu-disk_host.d grub_emu-disk_loopback.d grub_emu-fs_affs.d grub_emu-fs_cpio.d grub_emu-fs_fat.d grub_emu-fs_ext2.d grub_emu-fs_hfs.d grub_emu-fs_hfsplus.d grub_emu-fs_iso9660.d grub_emu-fs_udf.d grub_emu-fs_jfs.d grub_emu-fs_minix.d grub_emu-fs_ntfs.d grub_emu-fs_ntfscomp.d grub_emu-fs_reiserfs.d grub_emu-fs_sfs.d grub_emu-fs_ufs.d grub_emu-fs_xfs.d grub_emu-fs_afs.d grub_emu-fs_tar.d grub_emu-fs_fshelp.d grub_emu-io_gzio.d grub_emu-kern_device.d grub_emu-kern_disk.d grub_emu-kern_dl.d grub_emu-kern_elf.d grub_emu-kern_env.d grub_emu-kern_err.d grub_emu-normal_execute.d grub_emu-kern_file.d grub_emu-kern_fs.d grub_emu-normal_lexer.d grub_emu-kern_loader.d grub_emu-kern_main.d grub_emu-kern_misc.d grub_emu-kern_parser.d grub_emu-grub_script_tab.d grub_emu-kern_partition.d grub_emu-kern_rescue.d grub_emu-kern_term.d grub_emu-normal_arg.d grub_emu-normal_cmdline.d grub_emu-normal_command.d grub_emu-normal_function.d grub_emu-normal_completion.d grub_emu-normal_main.d grub_emu-normal_menu_text.d grub_emu-normal_menu.d grub_emu-normal_menu_entry.d grub_emu-normal_menu_viewer.d grub_emu-normal_misc.d grub_emu-normal_script.d grub_emu-normal_color.d grub_emu-partmap_amiga.d grub_emu-partmap_apple.d grub_emu-partmap_pc.d grub_emu-partmap_sun.d grub_emu-partmap_acorn.d grub_emu-partmap_gpt.d grub_emu-util_console.d grub_emu-util_hostfs.d grub_emu-util_grub_emu.d grub_emu-util_misc.d grub_emu-util_hostdisk.d grub_emu-util_getroot.d grub_emu-util_i386_pc_misc.d grub_emu-disk_raid.d grub_emu-disk_raid5_recover.d grub_emu-disk_raid6_recover.d grub_emu-disk_mdraid_linux.d grub_emu-disk_dmraid_nvidia.d grub_emu-disk_lvm.d grub_emu-grub_emu_init.d
+
+grub-emu: $(grub_emu_DEPENDENCIES) grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_echo.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_halt.o grub_emu-commands_reboot.o grub_emu-commands_i386_cpuid.o grub_emu-disk_host.o grub_emu-disk_loopback.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_fat.o grub_emu-fs_ext2.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-fs_fshelp.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_main.o grub_emu-normal_menu_text.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-normal_color.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-partmap_gpt.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_i386_pc_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_emu_init.o
+       $(CC) -o $@ grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_echo.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_halt.o grub_emu-commands_reboot.o grub_emu-commands_i386_cpuid.o grub_emu-disk_host.o grub_emu-disk_loopback.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_fat.o grub_emu-fs_ext2.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-fs_fshelp.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_main.o grub_emu-normal_menu_text.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-normal_color.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-partmap_gpt.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_i386_pc_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_emu_init.o $(LDFLAGS) $(grub_emu_LDFLAGS)
+
+grub_emu-commands_boot.o: commands/boot.c $(commands/boot.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_boot.d
+
+grub_emu-commands_cat.o: commands/cat.c $(commands/cat.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_cat.d
+
+grub_emu-commands_cmp.o: commands/cmp.c $(commands/cmp.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_cmp.d
+
+grub_emu-commands_configfile.o: commands/configfile.c $(commands/configfile.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_configfile.d
+
+grub_emu-commands_echo.o: commands/echo.c $(commands/echo.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_echo.d
+
+grub_emu-commands_help.o: commands/help.c $(commands/help.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_help.d
+
+grub_emu-commands_terminal.o: commands/terminal.c $(commands/terminal.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_terminal.d
+
+grub_emu-commands_ls.o: commands/ls.c $(commands/ls.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_ls.d
+
+grub_emu-commands_test.o: commands/test.c $(commands/test.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_test.d
+
+grub_emu-commands_search.o: commands/search.c $(commands/search.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_search.d
+
+grub_emu-commands_blocklist.o: commands/blocklist.c $(commands/blocklist.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_blocklist.d
+
+grub_emu-commands_hexdump.o: commands/hexdump.c $(commands/hexdump.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_hexdump.d
+
+grub_emu-lib_hexdump.o: lib/hexdump.c $(lib/hexdump.c_DEPENDENCIES)
+       $(CC) -Ilib -I$(srcdir)/lib $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-lib_hexdump.d
+
+grub_emu-commands_halt.o: commands/halt.c $(commands/halt.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_halt.d
+
+grub_emu-commands_reboot.o: commands/reboot.c $(commands/reboot.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_reboot.d
+
+grub_emu-commands_i386_cpuid.o: commands/i386/cpuid.c $(commands/i386/cpuid.c_DEPENDENCIES)
+       $(CC) -Icommands/i386 -I$(srcdir)/commands/i386 $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_i386_cpuid.d
+
+grub_emu-disk_host.o: disk/host.c $(disk/host.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_host.d
+
+grub_emu-disk_loopback.o: disk/loopback.c $(disk/loopback.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_loopback.d
+
+grub_emu-fs_affs.o: fs/affs.c $(fs/affs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_affs.d
+
+grub_emu-fs_cpio.o: fs/cpio.c $(fs/cpio.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_cpio.d
+
+grub_emu-fs_fat.o: fs/fat.c $(fs/fat.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_fat.d
+
+grub_emu-fs_ext2.o: fs/ext2.c $(fs/ext2.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ext2.d
+
+grub_emu-fs_hfs.o: fs/hfs.c $(fs/hfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_hfs.d
+
+grub_emu-fs_hfsplus.o: fs/hfsplus.c $(fs/hfsplus.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_hfsplus.d
+
+grub_emu-fs_iso9660.o: fs/iso9660.c $(fs/iso9660.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_iso9660.d
+
+grub_emu-fs_udf.o: fs/udf.c $(fs/udf.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_udf.d
+
+grub_emu-fs_jfs.o: fs/jfs.c $(fs/jfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_jfs.d
+
+grub_emu-fs_minix.o: fs/minix.c $(fs/minix.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_minix.d
+
+grub_emu-fs_ntfs.o: fs/ntfs.c $(fs/ntfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ntfs.d
+
+grub_emu-fs_ntfscomp.o: fs/ntfscomp.c $(fs/ntfscomp.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ntfscomp.d
+
+grub_emu-fs_reiserfs.o: fs/reiserfs.c $(fs/reiserfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_reiserfs.d
+
+grub_emu-fs_sfs.o: fs/sfs.c $(fs/sfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_sfs.d
+
+grub_emu-fs_ufs.o: fs/ufs.c $(fs/ufs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ufs.d
+
+grub_emu-fs_xfs.o: fs/xfs.c $(fs/xfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_xfs.d
+
+grub_emu-fs_afs.o: fs/afs.c $(fs/afs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_afs.d
+
+grub_emu-fs_tar.o: fs/tar.c $(fs/tar.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_tar.d
+
+grub_emu-fs_fshelp.o: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_fshelp.d
+
+grub_emu-io_gzio.o: io/gzio.c $(io/gzio.c_DEPENDENCIES)
+       $(CC) -Iio -I$(srcdir)/io $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-io_gzio.d
+
+grub_emu-kern_device.o: kern/device.c $(kern/device.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_device.d
+
+grub_emu-kern_disk.o: kern/disk.c $(kern/disk.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_disk.d
+
+grub_emu-kern_dl.o: kern/dl.c $(kern/dl.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_dl.d
+
+grub_emu-kern_elf.o: kern/elf.c $(kern/elf.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_elf.d
+
+grub_emu-kern_env.o: kern/env.c $(kern/env.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_env.d
+
+grub_emu-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_err.d
+
+grub_emu-normal_execute.o: normal/execute.c $(normal/execute.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_execute.d
+
+grub_emu-kern_file.o: kern/file.c $(kern/file.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_file.d
+
+grub_emu-kern_fs.o: kern/fs.c $(kern/fs.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_fs.d
+
+grub_emu-normal_lexer.o: normal/lexer.c $(normal/lexer.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_lexer.d
+
+grub_emu-kern_loader.o: kern/loader.c $(kern/loader.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_loader.d
+
+grub_emu-kern_main.o: kern/main.c $(kern/main.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_main.d
+
+grub_emu-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_misc.d
+
+grub_emu-kern_parser.o: kern/parser.c $(kern/parser.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_parser.d
+
+grub_emu-grub_script_tab.o: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES)
+       $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-grub_script_tab.d
+
+grub_emu-kern_partition.o: kern/partition.c $(kern/partition.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_partition.d
+
+grub_emu-kern_rescue.o: kern/rescue.c $(kern/rescue.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_rescue.d
+
+grub_emu-kern_term.o: kern/term.c $(kern/term.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_term.d
+
+grub_emu-normal_arg.o: normal/arg.c $(normal/arg.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_arg.d
+
+grub_emu-normal_cmdline.o: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_cmdline.d
+
+grub_emu-normal_command.o: normal/command.c $(normal/command.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_command.d
+
+grub_emu-normal_function.o: normal/function.c $(normal/function.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_function.d
+
+grub_emu-normal_completion.o: normal/completion.c $(normal/completion.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_completion.d
+
+grub_emu-normal_main.o: normal/main.c $(normal/main.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_main.d
+
+grub_emu-normal_menu_text.o: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu_text.d
+
+grub_emu-normal_menu.o: normal/menu.c $(normal/menu.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu.d
+
+grub_emu-normal_menu_entry.o: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu_entry.d
+
+grub_emu-normal_menu_viewer.o: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu_viewer.d
+
+grub_emu-normal_misc.o: normal/misc.c $(normal/misc.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_misc.d
+
+grub_emu-normal_script.o: normal/script.c $(normal/script.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_script.d
+
+grub_emu-normal_color.o: normal/color.c $(normal/color.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_color.d
+
+grub_emu-partmap_amiga.o: partmap/amiga.c $(partmap/amiga.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_amiga.d
+
+grub_emu-partmap_apple.o: partmap/apple.c $(partmap/apple.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_apple.d
+
+grub_emu-partmap_pc.o: partmap/pc.c $(partmap/pc.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_pc.d
+
+grub_emu-partmap_sun.o: partmap/sun.c $(partmap/sun.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_sun.d
+
+grub_emu-partmap_acorn.o: partmap/acorn.c $(partmap/acorn.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_acorn.d
+
+grub_emu-partmap_gpt.o: partmap/gpt.c $(partmap/gpt.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_gpt.d
+
+grub_emu-util_console.o: util/console.c $(util/console.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_console.d
+
+grub_emu-util_hostfs.o: util/hostfs.c $(util/hostfs.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_hostfs.d
+
+grub_emu-util_grub_emu.o: util/grub-emu.c $(util/grub-emu.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_grub_emu.d
+
+grub_emu-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_misc.d
+
+grub_emu-util_hostdisk.o: util/hostdisk.c $(util/hostdisk.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_hostdisk.d
+
+grub_emu-util_getroot.o: util/getroot.c $(util/getroot.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_getroot.d
+
+grub_emu-util_i386_pc_misc.o: util/i386/pc/misc.c $(util/i386/pc/misc.c_DEPENDENCIES)
+       $(CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_i386_pc_misc.d
+
+grub_emu-disk_raid.o: disk/raid.c $(disk/raid.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_raid.d
+
+grub_emu-disk_raid5_recover.o: disk/raid5_recover.c $(disk/raid5_recover.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_raid5_recover.d
+
+grub_emu-disk_raid6_recover.o: disk/raid6_recover.c $(disk/raid6_recover.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_raid6_recover.d
+
+grub_emu-disk_mdraid_linux.o: disk/mdraid_linux.c $(disk/mdraid_linux.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_mdraid_linux.d
+
+grub_emu-disk_dmraid_nvidia.o: disk/dmraid_nvidia.c $(disk/dmraid_nvidia.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_dmraid_nvidia.d
+
+grub_emu-disk_lvm.o: disk/lvm.c $(disk/lvm.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_lvm.d
+
+grub_emu-grub_emu_init.o: grub_emu_init.c $(grub_emu_init.c_DEPENDENCIES)
+       $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-grub_emu_init.d
+
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+# Scripts.
+sbin_SCRIPTS = grub-install
+
+# For grub-install.
+grub_install_SOURCES = util/ieee1275/grub-install.in
+CLEANFILES += grub-install
+
+grub-install: util/ieee1275/grub-install.in $(util/ieee1275/grub-install.in_DEPENDENCIES) config.status
+       ./config.status --file=grub-install:util/ieee1275/grub-install.in
+       chmod +x $@
+
+
+# Modules.
+pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod            \
+       multiboot.mod _multiboot.mod aout.mod serial.mod linux.mod      \
+       _linux.mod nand.mod memdisk.mod pci.mod lspci.mod datetime.mod  \
+       date.mod datehook.mod lsmmap.mod
+
+#
+# Only arch dependant part of normal.mod will be here. Common part for
+# all architecures of normal.mod is at start and should be kept at sync
+# with other makefiles.
+# 
+# Please put arch dependant part of normal.mod at the end of list to
+# keep it simpler to update to different architectures.
+#
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/color.c                                                  \
+       normal/menu_viewer.c normal/menu_entry.c                        \
+       normal/misc.c grub_script.tab.c                                 \
+       normal/script.c                                                 \
+       normal/i386/setjmp.S
+CLEANFILES += normal.mod mod-normal.o mod-normal.c pre-normal.o normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_i386_setjmp.o und-normal.lst
+ifneq ($(normal_mod_EXPORTS),no)
+CLEANFILES += def-normal.lst
+DEFSYMFILES += def-normal.lst
+endif
+MOSTLYCLEANFILES += normal_mod-normal_arg.d normal_mod-normal_cmdline.d normal_mod-normal_command.d normal_mod-normal_completion.d normal_mod-normal_execute.d normal_mod-normal_function.d normal_mod-normal_lexer.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_menu_text.d normal_mod-normal_color.d normal_mod-normal_menu_viewer.d normal_mod-normal_menu_entry.d normal_mod-normal_misc.d normal_mod-grub_script_tab.d normal_mod-normal_script.d normal_mod-normal_i386_setjmp.d
+UNDSYMFILES += und-normal.lst
+
+normal.mod: pre-normal.o mod-normal.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(normal_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-normal.o mod-normal.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-normal.o: $(normal_mod_DEPENDENCIES) normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_i386_setjmp.o
+       -rm -f $@
+       $(TARGET_CC) $(normal_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_i386_setjmp.o
+
+mod-normal.o: mod-normal.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
+
+mod-normal.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'normal' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(normal_mod_EXPORTS),no)
+def-normal.lst: pre-normal.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 normal/' > $@
+endif
+
+und-normal.lst: pre-normal.o
+       echo 'normal' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+normal_mod-normal_arg.o: normal/arg.c $(normal/arg.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_arg.d
+
+CLEANFILES += cmd-normal_mod-normal_arg.lst fs-normal_mod-normal_arg.lst partmap-normal_mod-normal_arg.lst
+COMMANDFILES += cmd-normal_mod-normal_arg.lst
+FSFILES += fs-normal_mod-normal_arg.lst
+PARTMAPFILES += partmap-normal_mod-normal_arg.lst
+
+cmd-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_cmdline.o: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_cmdline.d
+
+CLEANFILES += cmd-normal_mod-normal_cmdline.lst fs-normal_mod-normal_cmdline.lst partmap-normal_mod-normal_cmdline.lst
+COMMANDFILES += cmd-normal_mod-normal_cmdline.lst
+FSFILES += fs-normal_mod-normal_cmdline.lst
+PARTMAPFILES += partmap-normal_mod-normal_cmdline.lst
+
+cmd-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_command.o: normal/command.c $(normal/command.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_command.d
+
+CLEANFILES += cmd-normal_mod-normal_command.lst fs-normal_mod-normal_command.lst partmap-normal_mod-normal_command.lst
+COMMANDFILES += cmd-normal_mod-normal_command.lst
+FSFILES += fs-normal_mod-normal_command.lst
+PARTMAPFILES += partmap-normal_mod-normal_command.lst
+
+cmd-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_completion.o: normal/completion.c $(normal/completion.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_completion.d
+
+CLEANFILES += cmd-normal_mod-normal_completion.lst fs-normal_mod-normal_completion.lst partmap-normal_mod-normal_completion.lst
+COMMANDFILES += cmd-normal_mod-normal_completion.lst
+FSFILES += fs-normal_mod-normal_completion.lst
+PARTMAPFILES += partmap-normal_mod-normal_completion.lst
+
+cmd-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_execute.o: normal/execute.c $(normal/execute.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_execute.d
+
+CLEANFILES += cmd-normal_mod-normal_execute.lst fs-normal_mod-normal_execute.lst partmap-normal_mod-normal_execute.lst
+COMMANDFILES += cmd-normal_mod-normal_execute.lst
+FSFILES += fs-normal_mod-normal_execute.lst
+PARTMAPFILES += partmap-normal_mod-normal_execute.lst
+
+cmd-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_function.o: normal/function.c $(normal/function.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_function.d
+
+CLEANFILES += cmd-normal_mod-normal_function.lst fs-normal_mod-normal_function.lst partmap-normal_mod-normal_function.lst
+COMMANDFILES += cmd-normal_mod-normal_function.lst
+FSFILES += fs-normal_mod-normal_function.lst
+PARTMAPFILES += partmap-normal_mod-normal_function.lst
+
+cmd-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_lexer.o: normal/lexer.c $(normal/lexer.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_lexer.d
+
+CLEANFILES += cmd-normal_mod-normal_lexer.lst fs-normal_mod-normal_lexer.lst partmap-normal_mod-normal_lexer.lst
+COMMANDFILES += cmd-normal_mod-normal_lexer.lst
+FSFILES += fs-normal_mod-normal_lexer.lst
+PARTMAPFILES += partmap-normal_mod-normal_lexer.lst
+
+cmd-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_main.o: normal/main.c $(normal/main.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_main.d
+
+CLEANFILES += cmd-normal_mod-normal_main.lst fs-normal_mod-normal_main.lst partmap-normal_mod-normal_main.lst
+COMMANDFILES += cmd-normal_mod-normal_main.lst
+FSFILES += fs-normal_mod-normal_main.lst
+PARTMAPFILES += partmap-normal_mod-normal_main.lst
+
+cmd-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu.o: normal/menu.c $(normal/menu.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu.d
+
+CLEANFILES += cmd-normal_mod-normal_menu.lst fs-normal_mod-normal_menu.lst partmap-normal_mod-normal_menu.lst
+COMMANDFILES += cmd-normal_mod-normal_menu.lst
+FSFILES += fs-normal_mod-normal_menu.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu.lst
+
+cmd-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_text.o: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_text.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_text.lst fs-normal_mod-normal_menu_text.lst partmap-normal_mod-normal_menu_text.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_text.lst
+FSFILES += fs-normal_mod-normal_menu_text.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_text.lst
+
+cmd-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_color.o: normal/color.c $(normal/color.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_color.d
+
+CLEANFILES += cmd-normal_mod-normal_color.lst fs-normal_mod-normal_color.lst partmap-normal_mod-normal_color.lst
+COMMANDFILES += cmd-normal_mod-normal_color.lst
+FSFILES += fs-normal_mod-normal_color.lst
+PARTMAPFILES += partmap-normal_mod-normal_color.lst
+
+cmd-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_viewer.o: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_viewer.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_viewer.lst fs-normal_mod-normal_menu_viewer.lst partmap-normal_mod-normal_menu_viewer.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_viewer.lst
+FSFILES += fs-normal_mod-normal_menu_viewer.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_viewer.lst
+
+cmd-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_entry.o: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_entry.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_entry.lst fs-normal_mod-normal_menu_entry.lst partmap-normal_mod-normal_menu_entry.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_entry.lst
+FSFILES += fs-normal_mod-normal_menu_entry.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_entry.lst
+
+cmd-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_misc.o: normal/misc.c $(normal/misc.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_misc.d
+
+CLEANFILES += cmd-normal_mod-normal_misc.lst fs-normal_mod-normal_misc.lst partmap-normal_mod-normal_misc.lst
+COMMANDFILES += cmd-normal_mod-normal_misc.lst
+FSFILES += fs-normal_mod-normal_misc.lst
+PARTMAPFILES += partmap-normal_mod-normal_misc.lst
+
+cmd-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-grub_script_tab.o: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES)
+       $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-grub_script_tab.d
+
+CLEANFILES += cmd-normal_mod-grub_script_tab.lst fs-normal_mod-grub_script_tab.lst partmap-normal_mod-grub_script_tab.lst
+COMMANDFILES += cmd-normal_mod-grub_script_tab.lst
+FSFILES += fs-normal_mod-grub_script_tab.lst
+PARTMAPFILES += partmap-normal_mod-grub_script_tab.lst
+
+cmd-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_script.o: normal/script.c $(normal/script.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_script.d
+
+CLEANFILES += cmd-normal_mod-normal_script.lst fs-normal_mod-normal_script.lst partmap-normal_mod-normal_script.lst
+COMMANDFILES += cmd-normal_mod-normal_script.lst
+FSFILES += fs-normal_mod-normal_script.lst
+PARTMAPFILES += partmap-normal_mod-normal_script.lst
+
+cmd-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_i386_setjmp.o: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES)
+       $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_i386_setjmp.d
+
+CLEANFILES += cmd-normal_mod-normal_i386_setjmp.lst fs-normal_mod-normal_i386_setjmp.lst partmap-normal_mod-normal_i386_setjmp.lst
+COMMANDFILES += cmd-normal_mod-normal_i386_setjmp.lst
+FSFILES += fs-normal_mod-normal_i386_setjmp.lst
+PARTMAPFILES += partmap-normal_mod-normal_i386_setjmp.lst
+
+cmd-normal_mod-normal_i386_setjmp.lst: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_i386_setjmp.lst: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<     | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_i386_setjmp.lst: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _multiboot.mod.
+_multiboot_mod_SOURCES = loader/ieee1275/multiboot2.c \
+                        loader/multiboot2.c \
+                        loader/multiboot_loader.c
+CLEANFILES += _multiboot.mod mod-_multiboot.o mod-_multiboot.c pre-_multiboot.o _multiboot_mod-loader_ieee1275_multiboot2.o _multiboot_mod-loader_multiboot2.o _multiboot_mod-loader_multiboot_loader.o und-_multiboot.lst
+ifneq ($(_multiboot_mod_EXPORTS),no)
+CLEANFILES += def-_multiboot.lst
+DEFSYMFILES += def-_multiboot.lst
+endif
+MOSTLYCLEANFILES += _multiboot_mod-loader_ieee1275_multiboot2.d _multiboot_mod-loader_multiboot2.d _multiboot_mod-loader_multiboot_loader.d
+UNDSYMFILES += und-_multiboot.lst
+
+_multiboot.mod: pre-_multiboot.o mod-_multiboot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(_multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-_multiboot.o mod-_multiboot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-_multiboot.o: $(_multiboot_mod_DEPENDENCIES) _multiboot_mod-loader_ieee1275_multiboot2.o _multiboot_mod-loader_multiboot2.o _multiboot_mod-loader_multiboot_loader.o
+       -rm -f $@
+       $(TARGET_CC) $(_multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ _multiboot_mod-loader_ieee1275_multiboot2.o _multiboot_mod-loader_multiboot2.o _multiboot_mod-loader_multiboot_loader.o
+
+mod-_multiboot.o: mod-_multiboot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -c -o $@ $<
+
+mod-_multiboot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '_multiboot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(_multiboot_mod_EXPORTS),no)
+def-_multiboot.lst: pre-_multiboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _multiboot/' > $@
+endif
+
+und-_multiboot.lst: pre-_multiboot.o
+       echo '_multiboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+_multiboot_mod-loader_ieee1275_multiboot2.o: loader/ieee1275/multiboot2.c $(loader/ieee1275/multiboot2.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/ieee1275 -I$(srcdir)/loader/ieee1275 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include _multiboot_mod-loader_ieee1275_multiboot2.d
+
+CLEANFILES += cmd-_multiboot_mod-loader_ieee1275_multiboot2.lst fs-_multiboot_mod-loader_ieee1275_multiboot2.lst partmap-_multiboot_mod-loader_ieee1275_multiboot2.lst
+COMMANDFILES += cmd-_multiboot_mod-loader_ieee1275_multiboot2.lst
+FSFILES += fs-_multiboot_mod-loader_ieee1275_multiboot2.lst
+PARTMAPFILES += partmap-_multiboot_mod-loader_ieee1275_multiboot2.lst
+
+cmd-_multiboot_mod-loader_ieee1275_multiboot2.lst: loader/ieee1275/multiboot2.c $(loader/ieee1275/multiboot2.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/ieee1275 -I$(srcdir)/loader/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+fs-_multiboot_mod-loader_ieee1275_multiboot2.lst: loader/ieee1275/multiboot2.c $(loader/ieee1275/multiboot2.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/ieee1275 -I$(srcdir)/loader/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-_multiboot_mod-loader_ieee1275_multiboot2.lst: loader/ieee1275/multiboot2.c $(loader/ieee1275/multiboot2.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/ieee1275 -I$(srcdir)/loader/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+
+_multiboot_mod-loader_multiboot2.o: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include _multiboot_mod-loader_multiboot2.d
+
+CLEANFILES += cmd-_multiboot_mod-loader_multiboot2.lst fs-_multiboot_mod-loader_multiboot2.lst partmap-_multiboot_mod-loader_multiboot2.lst
+COMMANDFILES += cmd-_multiboot_mod-loader_multiboot2.lst
+FSFILES += fs-_multiboot_mod-loader_multiboot2.lst
+PARTMAPFILES += partmap-_multiboot_mod-loader_multiboot2.lst
+
+cmd-_multiboot_mod-loader_multiboot2.lst: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+fs-_multiboot_mod-loader_multiboot2.lst: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-_multiboot_mod-loader_multiboot2.lst: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+
+_multiboot_mod-loader_multiboot_loader.o: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include _multiboot_mod-loader_multiboot_loader.d
+
+CLEANFILES += cmd-_multiboot_mod-loader_multiboot_loader.lst fs-_multiboot_mod-loader_multiboot_loader.lst partmap-_multiboot_mod-loader_multiboot_loader.lst
+COMMANDFILES += cmd-_multiboot_mod-loader_multiboot_loader.lst
+FSFILES += fs-_multiboot_mod-loader_multiboot_loader.lst
+PARTMAPFILES += partmap-_multiboot_mod-loader_multiboot_loader.lst
+
+cmd-_multiboot_mod-loader_multiboot_loader.lst: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+fs-_multiboot_mod-loader_multiboot_loader.lst: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-_multiboot_mod-loader_multiboot_loader.lst: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+
+_multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+_multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For multiboot.mod.
+multiboot_mod_SOURCES = loader/multiboot_loader_normal.c 
+CLEANFILES += multiboot.mod mod-multiboot.o mod-multiboot.c pre-multiboot.o multiboot_mod-loader_multiboot_loader_normal.o und-multiboot.lst
+ifneq ($(multiboot_mod_EXPORTS),no)
+CLEANFILES += def-multiboot.lst
+DEFSYMFILES += def-multiboot.lst
+endif
+MOSTLYCLEANFILES += multiboot_mod-loader_multiboot_loader_normal.d
+UNDSYMFILES += und-multiboot.lst
+
+multiboot.mod: pre-multiboot.o mod-multiboot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-multiboot.o mod-multiboot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-multiboot.o: $(multiboot_mod_DEPENDENCIES) multiboot_mod-loader_multiboot_loader_normal.o
+       -rm -f $@
+       $(TARGET_CC) $(multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ multiboot_mod-loader_multiboot_loader_normal.o
+
+mod-multiboot.o: mod-multiboot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -c -o $@ $<
+
+mod-multiboot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'multiboot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(multiboot_mod_EXPORTS),no)
+def-multiboot.lst: pre-multiboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 multiboot/' > $@
+endif
+
+und-multiboot.lst: pre-multiboot.o
+       echo 'multiboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+multiboot_mod-loader_multiboot_loader_normal.o: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include multiboot_mod-loader_multiboot_loader_normal.d
+
+CLEANFILES += cmd-multiboot_mod-loader_multiboot_loader_normal.lst fs-multiboot_mod-loader_multiboot_loader_normal.lst partmap-multiboot_mod-loader_multiboot_loader_normal.lst
+COMMANDFILES += cmd-multiboot_mod-loader_multiboot_loader_normal.lst
+FSFILES += fs-multiboot_mod-loader_multiboot_loader_normal.lst
+PARTMAPFILES += partmap-multiboot_mod-loader_multiboot_loader_normal.lst
+
+cmd-multiboot_mod-loader_multiboot_loader_normal.lst: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh multiboot > $@ || (rm -f $@; exit 1)
+
+fs-multiboot_mod-loader_multiboot_loader_normal.lst: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-multiboot_mod-loader_multiboot_loader_normal.lst: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh multiboot > $@ || (rm -f $@; exit 1)
+
+
+multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For aout.mod.
+aout_mod_SOURCES = loader/aout.c
+CLEANFILES += aout.mod mod-aout.o mod-aout.c pre-aout.o aout_mod-loader_aout.o und-aout.lst
+ifneq ($(aout_mod_EXPORTS),no)
+CLEANFILES += def-aout.lst
+DEFSYMFILES += def-aout.lst
+endif
+MOSTLYCLEANFILES += aout_mod-loader_aout.d
+UNDSYMFILES += und-aout.lst
+
+aout.mod: pre-aout.o mod-aout.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(aout_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-aout.o mod-aout.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-aout.o: $(aout_mod_DEPENDENCIES) aout_mod-loader_aout.o
+       -rm -f $@
+       $(TARGET_CC) $(aout_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ aout_mod-loader_aout.o
+
+mod-aout.o: mod-aout.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(aout_mod_CFLAGS) -c -o $@ $<
+
+mod-aout.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'aout' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(aout_mod_EXPORTS),no)
+def-aout.lst: pre-aout.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 aout/' > $@
+endif
+
+und-aout.lst: pre-aout.o
+       echo 'aout' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+aout_mod-loader_aout.o: loader/aout.c $(loader/aout.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(aout_mod_CFLAGS) -MD -c -o $@ $<
+-include aout_mod-loader_aout.d
+
+CLEANFILES += cmd-aout_mod-loader_aout.lst fs-aout_mod-loader_aout.lst partmap-aout_mod-loader_aout.lst
+COMMANDFILES += cmd-aout_mod-loader_aout.lst
+FSFILES += fs-aout_mod-loader_aout.lst
+PARTMAPFILES += partmap-aout_mod-loader_aout.lst
+
+cmd-aout_mod-loader_aout.lst: loader/aout.c $(loader/aout.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(aout_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh aout > $@ || (rm -f $@; exit 1)
+
+fs-aout_mod-loader_aout.lst: loader/aout.c $(loader/aout.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(aout_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh aout > $@ || (rm -f $@; exit 1)
+
+partmap-aout_mod-loader_aout.lst: loader/aout.c $(loader/aout.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(aout_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh aout > $@ || (rm -f $@; exit 1)
+
+
+aout_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For suspend.mod
+suspend_mod_SOURCES = commands/ieee1275/suspend.c
+CLEANFILES += suspend.mod mod-suspend.o mod-suspend.c pre-suspend.o suspend_mod-commands_ieee1275_suspend.o und-suspend.lst
+ifneq ($(suspend_mod_EXPORTS),no)
+CLEANFILES += def-suspend.lst
+DEFSYMFILES += def-suspend.lst
+endif
+MOSTLYCLEANFILES += suspend_mod-commands_ieee1275_suspend.d
+UNDSYMFILES += und-suspend.lst
+
+suspend.mod: pre-suspend.o mod-suspend.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(suspend_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-suspend.o mod-suspend.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-suspend.o: $(suspend_mod_DEPENDENCIES) suspend_mod-commands_ieee1275_suspend.o
+       -rm -f $@
+       $(TARGET_CC) $(suspend_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ suspend_mod-commands_ieee1275_suspend.o
+
+mod-suspend.o: mod-suspend.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(suspend_mod_CFLAGS) -c -o $@ $<
+
+mod-suspend.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'suspend' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(suspend_mod_EXPORTS),no)
+def-suspend.lst: pre-suspend.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 suspend/' > $@
+endif
+
+und-suspend.lst: pre-suspend.o
+       echo 'suspend' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+suspend_mod-commands_ieee1275_suspend.o: commands/ieee1275/suspend.c $(commands/ieee1275/suspend.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands/ieee1275 -I$(srcdir)/commands/ieee1275 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(suspend_mod_CFLAGS) -MD -c -o $@ $<
+-include suspend_mod-commands_ieee1275_suspend.d
+
+CLEANFILES += cmd-suspend_mod-commands_ieee1275_suspend.lst fs-suspend_mod-commands_ieee1275_suspend.lst partmap-suspend_mod-commands_ieee1275_suspend.lst
+COMMANDFILES += cmd-suspend_mod-commands_ieee1275_suspend.lst
+FSFILES += fs-suspend_mod-commands_ieee1275_suspend.lst
+PARTMAPFILES += partmap-suspend_mod-commands_ieee1275_suspend.lst
+
+cmd-suspend_mod-commands_ieee1275_suspend.lst: commands/ieee1275/suspend.c $(commands/ieee1275/suspend.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands/ieee1275 -I$(srcdir)/commands/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(suspend_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh suspend > $@ || (rm -f $@; exit 1)
+
+fs-suspend_mod-commands_ieee1275_suspend.lst: commands/ieee1275/suspend.c $(commands/ieee1275/suspend.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands/ieee1275 -I$(srcdir)/commands/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(suspend_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh suspend > $@ || (rm -f $@; exit 1)
+
+partmap-suspend_mod-commands_ieee1275_suspend.lst: commands/ieee1275/suspend.c $(commands/ieee1275/suspend.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands/ieee1275 -I$(srcdir)/commands/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(suspend_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh suspend > $@ || (rm -f $@; exit 1)
+
+
+suspend_mod_CFLAGS = $(COMMON_CFLAGS)
+suspend_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reboot.mod
+reboot_mod_SOURCES = commands/reboot.c
+CLEANFILES += reboot.mod mod-reboot.o mod-reboot.c pre-reboot.o reboot_mod-commands_reboot.o und-reboot.lst
+ifneq ($(reboot_mod_EXPORTS),no)
+CLEANFILES += def-reboot.lst
+DEFSYMFILES += def-reboot.lst
+endif
+MOSTLYCLEANFILES += reboot_mod-commands_reboot.d
+UNDSYMFILES += und-reboot.lst
+
+reboot.mod: pre-reboot.o mod-reboot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(reboot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-reboot.o mod-reboot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-reboot.o: $(reboot_mod_DEPENDENCIES) reboot_mod-commands_reboot.o
+       -rm -f $@
+       $(TARGET_CC) $(reboot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ reboot_mod-commands_reboot.o
+
+mod-reboot.o: mod-reboot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -c -o $@ $<
+
+mod-reboot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'reboot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(reboot_mod_EXPORTS),no)
+def-reboot.lst: pre-reboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 reboot/' > $@
+endif
+
+und-reboot.lst: pre-reboot.o
+       echo 'reboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+reboot_mod-commands_reboot.o: commands/reboot.c $(commands/reboot.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -MD -c -o $@ $<
+-include reboot_mod-commands_reboot.d
+
+CLEANFILES += cmd-reboot_mod-commands_reboot.lst fs-reboot_mod-commands_reboot.lst partmap-reboot_mod-commands_reboot.lst
+COMMANDFILES += cmd-reboot_mod-commands_reboot.lst
+FSFILES += fs-reboot_mod-commands_reboot.lst
+PARTMAPFILES += partmap-reboot_mod-commands_reboot.lst
+
+cmd-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh reboot > $@ || (rm -f $@; exit 1)
+
+fs-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh reboot > $@ || (rm -f $@; exit 1)
+
+partmap-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh reboot > $@ || (rm -f $@; exit 1)
+
+
+reboot_mod_CFLAGS = $(COMMON_CFLAGS)
+reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For halt.mod
+halt_mod_SOURCES = commands/halt.c
+CLEANFILES += halt.mod mod-halt.o mod-halt.c pre-halt.o halt_mod-commands_halt.o und-halt.lst
+ifneq ($(halt_mod_EXPORTS),no)
+CLEANFILES += def-halt.lst
+DEFSYMFILES += def-halt.lst
+endif
+MOSTLYCLEANFILES += halt_mod-commands_halt.d
+UNDSYMFILES += und-halt.lst
+
+halt.mod: pre-halt.o mod-halt.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(halt_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-halt.o mod-halt.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-halt.o: $(halt_mod_DEPENDENCIES) halt_mod-commands_halt.o
+       -rm -f $@
+       $(TARGET_CC) $(halt_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ halt_mod-commands_halt.o
+
+mod-halt.o: mod-halt.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -c -o $@ $<
+
+mod-halt.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'halt' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(halt_mod_EXPORTS),no)
+def-halt.lst: pre-halt.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 halt/' > $@
+endif
+
+und-halt.lst: pre-halt.o
+       echo 'halt' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+halt_mod-commands_halt.o: commands/halt.c $(commands/halt.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -MD -c -o $@ $<
+-include halt_mod-commands_halt.d
+
+CLEANFILES += cmd-halt_mod-commands_halt.lst fs-halt_mod-commands_halt.lst partmap-halt_mod-commands_halt.lst
+COMMANDFILES += cmd-halt_mod-commands_halt.lst
+FSFILES += fs-halt_mod-commands_halt.lst
+PARTMAPFILES += partmap-halt_mod-commands_halt.lst
+
+cmd-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh halt > $@ || (rm -f $@; exit 1)
+
+fs-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh halt > $@ || (rm -f $@; exit 1)
+
+partmap-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh halt > $@ || (rm -f $@; exit 1)
+
+
+halt_mod_CFLAGS = $(COMMON_CFLAGS)
+halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For serial.mod.
+serial_mod_SOURCES = term/i386/pc/serial.c
+CLEANFILES += serial.mod mod-serial.o mod-serial.c pre-serial.o serial_mod-term_i386_pc_serial.o und-serial.lst
+ifneq ($(serial_mod_EXPORTS),no)
+CLEANFILES += def-serial.lst
+DEFSYMFILES += def-serial.lst
+endif
+MOSTLYCLEANFILES += serial_mod-term_i386_pc_serial.d
+UNDSYMFILES += und-serial.lst
+
+serial.mod: pre-serial.o mod-serial.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(serial_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-serial.o mod-serial.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-serial.o: $(serial_mod_DEPENDENCIES) serial_mod-term_i386_pc_serial.o
+       -rm -f $@
+       $(TARGET_CC) $(serial_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ serial_mod-term_i386_pc_serial.o
+
+mod-serial.o: mod-serial.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(serial_mod_CFLAGS) -c -o $@ $<
+
+mod-serial.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'serial' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(serial_mod_EXPORTS),no)
+def-serial.lst: pre-serial.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 serial/' > $@
+endif
+
+und-serial.lst: pre-serial.o
+       echo 'serial' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+serial_mod-term_i386_pc_serial.o: term/i386/pc/serial.c $(term/i386/pc/serial.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(serial_mod_CFLAGS) -MD -c -o $@ $<
+-include serial_mod-term_i386_pc_serial.d
+
+CLEANFILES += cmd-serial_mod-term_i386_pc_serial.lst fs-serial_mod-term_i386_pc_serial.lst partmap-serial_mod-term_i386_pc_serial.lst
+COMMANDFILES += cmd-serial_mod-term_i386_pc_serial.lst
+FSFILES += fs-serial_mod-term_i386_pc_serial.lst
+PARTMAPFILES += partmap-serial_mod-term_i386_pc_serial.lst
+
+cmd-serial_mod-term_i386_pc_serial.lst: term/i386/pc/serial.c $(term/i386/pc/serial.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(serial_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh serial > $@ || (rm -f $@; exit 1)
+
+fs-serial_mod-term_i386_pc_serial.lst: term/i386/pc/serial.c $(term/i386/pc/serial.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(serial_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh serial > $@ || (rm -f $@; exit 1)
+
+partmap-serial_mod-term_i386_pc_serial.lst: term/i386/pc/serial.c $(term/i386/pc/serial.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(serial_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh serial > $@ || (rm -f $@; exit 1)
+
+
+serial_mod_CFLAGS = $(COMMON_CFLAGS)
+serial_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _linux.mod.
+_linux_mod_SOURCES = loader/i386/ieee1275/linux.c
+CLEANFILES += _linux.mod mod-_linux.o mod-_linux.c pre-_linux.o _linux_mod-loader_i386_ieee1275_linux.o und-_linux.lst
+ifneq ($(_linux_mod_EXPORTS),no)
+CLEANFILES += def-_linux.lst
+DEFSYMFILES += def-_linux.lst
+endif
+MOSTLYCLEANFILES += _linux_mod-loader_i386_ieee1275_linux.d
+UNDSYMFILES += und-_linux.lst
+
+_linux.mod: pre-_linux.o mod-_linux.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(_linux_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-_linux.o mod-_linux.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-_linux.o: $(_linux_mod_DEPENDENCIES) _linux_mod-loader_i386_ieee1275_linux.o
+       -rm -f $@
+       $(TARGET_CC) $(_linux_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ _linux_mod-loader_i386_ieee1275_linux.o
+
+mod-_linux.o: mod-_linux.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -c -o $@ $<
+
+mod-_linux.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '_linux' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(_linux_mod_EXPORTS),no)
+def-_linux.lst: pre-_linux.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _linux/' > $@
+endif
+
+und-_linux.lst: pre-_linux.o
+       echo '_linux' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+_linux_mod-loader_i386_ieee1275_linux.o: loader/i386/ieee1275/linux.c $(loader/i386/ieee1275/linux.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/i386/ieee1275 -I$(srcdir)/loader/i386/ieee1275 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -MD -c -o $@ $<
+-include _linux_mod-loader_i386_ieee1275_linux.d
+
+CLEANFILES += cmd-_linux_mod-loader_i386_ieee1275_linux.lst fs-_linux_mod-loader_i386_ieee1275_linux.lst partmap-_linux_mod-loader_i386_ieee1275_linux.lst
+COMMANDFILES += cmd-_linux_mod-loader_i386_ieee1275_linux.lst
+FSFILES += fs-_linux_mod-loader_i386_ieee1275_linux.lst
+PARTMAPFILES += partmap-_linux_mod-loader_i386_ieee1275_linux.lst
+
+cmd-_linux_mod-loader_i386_ieee1275_linux.lst: loader/i386/ieee1275/linux.c $(loader/i386/ieee1275/linux.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/ieee1275 -I$(srcdir)/loader/i386/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh _linux > $@ || (rm -f $@; exit 1)
+
+fs-_linux_mod-loader_i386_ieee1275_linux.lst: loader/i386/ieee1275/linux.c $(loader/i386/ieee1275/linux.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/ieee1275 -I$(srcdir)/loader/i386/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh _linux > $@ || (rm -f $@; exit 1)
+
+partmap-_linux_mod-loader_i386_ieee1275_linux.lst: loader/i386/ieee1275/linux.c $(loader/i386/ieee1275/linux.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/ieee1275 -I$(srcdir)/loader/i386/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh _linux > $@ || (rm -f $@; exit 1)
+
+
+_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/linux_normal.c
+CLEANFILES += linux.mod mod-linux.o mod-linux.c pre-linux.o linux_mod-loader_linux_normal.o und-linux.lst
+ifneq ($(linux_mod_EXPORTS),no)
+CLEANFILES += def-linux.lst
+DEFSYMFILES += def-linux.lst
+endif
+MOSTLYCLEANFILES += linux_mod-loader_linux_normal.d
+UNDSYMFILES += und-linux.lst
+
+linux.mod: pre-linux.o mod-linux.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(linux_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-linux.o mod-linux.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-linux.o: $(linux_mod_DEPENDENCIES) linux_mod-loader_linux_normal.o
+       -rm -f $@
+       $(TARGET_CC) $(linux_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ linux_mod-loader_linux_normal.o
+
+mod-linux.o: mod-linux.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -c -o $@ $<
+
+mod-linux.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'linux' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(linux_mod_EXPORTS),no)
+def-linux.lst: pre-linux.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 linux/' > $@
+endif
+
+und-linux.lst: pre-linux.o
+       echo 'linux' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+linux_mod-loader_linux_normal.o: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -MD -c -o $@ $<
+-include linux_mod-loader_linux_normal.d
+
+CLEANFILES += cmd-linux_mod-loader_linux_normal.lst fs-linux_mod-loader_linux_normal.lst partmap-linux_mod-loader_linux_normal.lst
+COMMANDFILES += cmd-linux_mod-loader_linux_normal.lst
+FSFILES += fs-linux_mod-loader_linux_normal.lst
+PARTMAPFILES += partmap-linux_mod-loader_linux_normal.lst
+
+cmd-linux_mod-loader_linux_normal.lst: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh linux > $@ || (rm -f $@; exit 1)
+
+fs-linux_mod-loader_linux_normal.lst: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh linux > $@ || (rm -f $@; exit 1)
+
+partmap-linux_mod-loader_linux_normal.lst: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh linux > $@ || (rm -f $@; exit 1)
+
+
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For nand.mod.
+nand_mod_SOURCES = disk/ieee1275/nand.c
+CLEANFILES += nand.mod mod-nand.o mod-nand.c pre-nand.o nand_mod-disk_ieee1275_nand.o und-nand.lst
+ifneq ($(nand_mod_EXPORTS),no)
+CLEANFILES += def-nand.lst
+DEFSYMFILES += def-nand.lst
+endif
+MOSTLYCLEANFILES += nand_mod-disk_ieee1275_nand.d
+UNDSYMFILES += und-nand.lst
+
+nand.mod: pre-nand.o mod-nand.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(nand_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-nand.o mod-nand.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-nand.o: $(nand_mod_DEPENDENCIES) nand_mod-disk_ieee1275_nand.o
+       -rm -f $@
+       $(TARGET_CC) $(nand_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ nand_mod-disk_ieee1275_nand.o
+
+mod-nand.o: mod-nand.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(nand_mod_CFLAGS) -c -o $@ $<
+
+mod-nand.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'nand' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(nand_mod_EXPORTS),no)
+def-nand.lst: pre-nand.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 nand/' > $@
+endif
+
+und-nand.lst: pre-nand.o
+       echo 'nand' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+nand_mod-disk_ieee1275_nand.o: disk/ieee1275/nand.c $(disk/ieee1275/nand.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk/ieee1275 -I$(srcdir)/disk/ieee1275 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(nand_mod_CFLAGS) -MD -c -o $@ $<
+-include nand_mod-disk_ieee1275_nand.d
+
+CLEANFILES += cmd-nand_mod-disk_ieee1275_nand.lst fs-nand_mod-disk_ieee1275_nand.lst partmap-nand_mod-disk_ieee1275_nand.lst
+COMMANDFILES += cmd-nand_mod-disk_ieee1275_nand.lst
+FSFILES += fs-nand_mod-disk_ieee1275_nand.lst
+PARTMAPFILES += partmap-nand_mod-disk_ieee1275_nand.lst
+
+cmd-nand_mod-disk_ieee1275_nand.lst: disk/ieee1275/nand.c $(disk/ieee1275/nand.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk/ieee1275 -I$(srcdir)/disk/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(nand_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh nand > $@ || (rm -f $@; exit 1)
+
+fs-nand_mod-disk_ieee1275_nand.lst: disk/ieee1275/nand.c $(disk/ieee1275/nand.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk/ieee1275 -I$(srcdir)/disk/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(nand_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh nand > $@ || (rm -f $@; exit 1)
+
+partmap-nand_mod-disk_ieee1275_nand.lst: disk/ieee1275/nand.c $(disk/ieee1275/nand.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk/ieee1275 -I$(srcdir)/disk/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(nand_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh nand > $@ || (rm -f $@; exit 1)
+
+
+nand_mod_CFLAGS = $(COMMON_CFLAGS)
+nand_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For memdisk.mod.
+memdisk_mod_SOURCES = disk/memdisk.c
+CLEANFILES += memdisk.mod mod-memdisk.o mod-memdisk.c pre-memdisk.o memdisk_mod-disk_memdisk.o und-memdisk.lst
+ifneq ($(memdisk_mod_EXPORTS),no)
+CLEANFILES += def-memdisk.lst
+DEFSYMFILES += def-memdisk.lst
+endif
+MOSTLYCLEANFILES += memdisk_mod-disk_memdisk.d
+UNDSYMFILES += und-memdisk.lst
+
+memdisk.mod: pre-memdisk.o mod-memdisk.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(memdisk_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-memdisk.o mod-memdisk.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-memdisk.o: $(memdisk_mod_DEPENDENCIES) memdisk_mod-disk_memdisk.o
+       -rm -f $@
+       $(TARGET_CC) $(memdisk_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ memdisk_mod-disk_memdisk.o
+
+mod-memdisk.o: mod-memdisk.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -c -o $@ $<
+
+mod-memdisk.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'memdisk' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(memdisk_mod_EXPORTS),no)
+def-memdisk.lst: pre-memdisk.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 memdisk/' > $@
+endif
+
+und-memdisk.lst: pre-memdisk.o
+       echo 'memdisk' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+memdisk_mod-disk_memdisk.o: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -MD -c -o $@ $<
+-include memdisk_mod-disk_memdisk.d
+
+CLEANFILES += cmd-memdisk_mod-disk_memdisk.lst fs-memdisk_mod-disk_memdisk.lst partmap-memdisk_mod-disk_memdisk.lst
+COMMANDFILES += cmd-memdisk_mod-disk_memdisk.lst
+FSFILES += fs-memdisk_mod-disk_memdisk.lst
+PARTMAPFILES += partmap-memdisk_mod-disk_memdisk.lst
+
+cmd-memdisk_mod-disk_memdisk.lst: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh memdisk > $@ || (rm -f $@; exit 1)
+
+fs-memdisk_mod-disk_memdisk.lst: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh memdisk > $@ || (rm -f $@; exit 1)
+
+partmap-memdisk_mod-disk_memdisk.lst: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh memdisk > $@ || (rm -f $@; exit 1)
+
+
+memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+CLEANFILES += pci.mod mod-pci.o mod-pci.c pre-pci.o pci_mod-bus_pci.o und-pci.lst
+ifneq ($(pci_mod_EXPORTS),no)
+CLEANFILES += def-pci.lst
+DEFSYMFILES += def-pci.lst
+endif
+MOSTLYCLEANFILES += pci_mod-bus_pci.d
+UNDSYMFILES += und-pci.lst
+
+pci.mod: pre-pci.o mod-pci.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(pci_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-pci.o mod-pci.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-pci.o: $(pci_mod_DEPENDENCIES) pci_mod-bus_pci.o
+       -rm -f $@
+       $(TARGET_CC) $(pci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pci_mod-bus_pci.o
+
+mod-pci.o: mod-pci.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -c -o $@ $<
+
+mod-pci.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'pci' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(pci_mod_EXPORTS),no)
+def-pci.lst: pre-pci.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 pci/' > $@
+endif
+
+und-pci.lst: pre-pci.o
+       echo 'pci' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+pci_mod-bus_pci.o: bus/pci.c $(bus/pci.c_DEPENDENCIES)
+       $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -MD -c -o $@ $<
+-include pci_mod-bus_pci.d
+
+CLEANFILES += cmd-pci_mod-bus_pci.lst fs-pci_mod-bus_pci.lst partmap-pci_mod-bus_pci.lst
+COMMANDFILES += cmd-pci_mod-bus_pci.lst
+FSFILES += fs-pci_mod-bus_pci.lst
+PARTMAPFILES += partmap-pci_mod-bus_pci.lst
+
+cmd-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh pci > $@ || (rm -f $@; exit 1)
+
+fs-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh pci > $@ || (rm -f $@; exit 1)
+
+partmap-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh pci > $@ || (rm -f $@; exit 1)
+
+
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+CLEANFILES += lspci.mod mod-lspci.o mod-lspci.c pre-lspci.o lspci_mod-commands_lspci.o und-lspci.lst
+ifneq ($(lspci_mod_EXPORTS),no)
+CLEANFILES += def-lspci.lst
+DEFSYMFILES += def-lspci.lst
+endif
+MOSTLYCLEANFILES += lspci_mod-commands_lspci.d
+UNDSYMFILES += und-lspci.lst
+
+lspci.mod: pre-lspci.o mod-lspci.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(lspci_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-lspci.o mod-lspci.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-lspci.o: $(lspci_mod_DEPENDENCIES) lspci_mod-commands_lspci.o
+       -rm -f $@
+       $(TARGET_CC) $(lspci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ lspci_mod-commands_lspci.o
+
+mod-lspci.o: mod-lspci.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -c -o $@ $<
+
+mod-lspci.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'lspci' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(lspci_mod_EXPORTS),no)
+def-lspci.lst: pre-lspci.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 lspci/' > $@
+endif
+
+und-lspci.lst: pre-lspci.o
+       echo 'lspci' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+lspci_mod-commands_lspci.o: commands/lspci.c $(commands/lspci.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -MD -c -o $@ $<
+-include lspci_mod-commands_lspci.d
+
+CLEANFILES += cmd-lspci_mod-commands_lspci.lst fs-lspci_mod-commands_lspci.lst partmap-lspci_mod-commands_lspci.lst
+COMMANDFILES += cmd-lspci_mod-commands_lspci.lst
+FSFILES += fs-lspci_mod-commands_lspci.lst
+PARTMAPFILES += partmap-lspci_mod-commands_lspci.lst
+
+cmd-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh lspci > $@ || (rm -f $@; exit 1)
+
+fs-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh lspci > $@ || (rm -f $@; exit 1)
+
+partmap-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh lspci > $@ || (rm -f $@; exit 1)
+
+
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datetime.mod
+datetime_mod_SOURCES = lib/datetime.c lib/i386/datetime.c
+CLEANFILES += datetime.mod mod-datetime.o mod-datetime.c pre-datetime.o datetime_mod-lib_datetime.o datetime_mod-lib_i386_datetime.o und-datetime.lst
+ifneq ($(datetime_mod_EXPORTS),no)
+CLEANFILES += def-datetime.lst
+DEFSYMFILES += def-datetime.lst
+endif
+MOSTLYCLEANFILES += datetime_mod-lib_datetime.d datetime_mod-lib_i386_datetime.d
+UNDSYMFILES += und-datetime.lst
+
+datetime.mod: pre-datetime.o mod-datetime.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(datetime_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-datetime.o mod-datetime.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-datetime.o: $(datetime_mod_DEPENDENCIES) datetime_mod-lib_datetime.o datetime_mod-lib_i386_datetime.o
+       -rm -f $@
+       $(TARGET_CC) $(datetime_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ datetime_mod-lib_datetime.o datetime_mod-lib_i386_datetime.o
+
+mod-datetime.o: mod-datetime.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -c -o $@ $<
+
+mod-datetime.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'datetime' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(datetime_mod_EXPORTS),no)
+def-datetime.lst: pre-datetime.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 datetime/' > $@
+endif
+
+und-datetime.lst: pre-datetime.o
+       echo 'datetime' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+datetime_mod-lib_datetime.o: lib/datetime.c $(lib/datetime.c_DEPENDENCIES)
+       $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -MD -c -o $@ $<
+-include datetime_mod-lib_datetime.d
+
+CLEANFILES += cmd-datetime_mod-lib_datetime.lst fs-datetime_mod-lib_datetime.lst partmap-datetime_mod-lib_datetime.lst
+COMMANDFILES += cmd-datetime_mod-lib_datetime.lst
+FSFILES += fs-datetime_mod-lib_datetime.lst
+PARTMAPFILES += partmap-datetime_mod-lib_datetime.lst
+
+cmd-datetime_mod-lib_datetime.lst: lib/datetime.c $(lib/datetime.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh datetime > $@ || (rm -f $@; exit 1)
+
+fs-datetime_mod-lib_datetime.lst: lib/datetime.c $(lib/datetime.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh datetime > $@ || (rm -f $@; exit 1)
+
+partmap-datetime_mod-lib_datetime.lst: lib/datetime.c $(lib/datetime.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh datetime > $@ || (rm -f $@; exit 1)
+
+
+datetime_mod-lib_i386_datetime.o: lib/i386/datetime.c $(lib/i386/datetime.c_DEPENDENCIES)
+       $(TARGET_CC) -Ilib/i386 -I$(srcdir)/lib/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -MD -c -o $@ $<
+-include datetime_mod-lib_i386_datetime.d
+
+CLEANFILES += cmd-datetime_mod-lib_i386_datetime.lst fs-datetime_mod-lib_i386_datetime.lst partmap-datetime_mod-lib_i386_datetime.lst
+COMMANDFILES += cmd-datetime_mod-lib_i386_datetime.lst
+FSFILES += fs-datetime_mod-lib_i386_datetime.lst
+PARTMAPFILES += partmap-datetime_mod-lib_i386_datetime.lst
+
+cmd-datetime_mod-lib_i386_datetime.lst: lib/i386/datetime.c $(lib/i386/datetime.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ilib/i386 -I$(srcdir)/lib/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh datetime > $@ || (rm -f $@; exit 1)
+
+fs-datetime_mod-lib_i386_datetime.lst: lib/i386/datetime.c $(lib/i386/datetime.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ilib/i386 -I$(srcdir)/lib/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh datetime > $@ || (rm -f $@; exit 1)
+
+partmap-datetime_mod-lib_i386_datetime.lst: lib/i386/datetime.c $(lib/i386/datetime.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ilib/i386 -I$(srcdir)/lib/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh datetime > $@ || (rm -f $@; exit 1)
+
+
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+CLEANFILES += date.mod mod-date.o mod-date.c pre-date.o date_mod-commands_date.o und-date.lst
+ifneq ($(date_mod_EXPORTS),no)
+CLEANFILES += def-date.lst
+DEFSYMFILES += def-date.lst
+endif
+MOSTLYCLEANFILES += date_mod-commands_date.d
+UNDSYMFILES += und-date.lst
+
+date.mod: pre-date.o mod-date.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(date_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-date.o mod-date.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-date.o: $(date_mod_DEPENDENCIES) date_mod-commands_date.o
+       -rm -f $@
+       $(TARGET_CC) $(date_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ date_mod-commands_date.o
+
+mod-date.o: mod-date.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -c -o $@ $<
+
+mod-date.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'date' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(date_mod_EXPORTS),no)
+def-date.lst: pre-date.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 date/' > $@
+endif
+
+und-date.lst: pre-date.o
+       echo 'date' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+date_mod-commands_date.o: commands/date.c $(commands/date.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(date_mod_CFLAGS) -MD -c -o $@ $<
+-include date_mod-commands_date.d
+
+CLEANFILES += cmd-date_mod-commands_date.lst fs-date_mod-commands_date.lst partmap-date_mod-commands_date.lst
+COMMANDFILES += cmd-date_mod-commands_date.lst
+FSFILES += fs-date_mod-commands_date.lst
+PARTMAPFILES += partmap-date_mod-commands_date.lst
+
+cmd-date_mod-commands_date.lst: commands/date.c $(commands/date.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh date > $@ || (rm -f $@; exit 1)
+
+fs-date_mod-commands_date.lst: commands/date.c $(commands/date.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh date > $@ || (rm -f $@; exit 1)
+
+partmap-date_mod-commands_date.lst: commands/date.c $(commands/date.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh date > $@ || (rm -f $@; exit 1)
+
+
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datehook.mod
+datehook_mod_SOURCES = hook/datehook.c
+CLEANFILES += datehook.mod mod-datehook.o mod-datehook.c pre-datehook.o datehook_mod-hook_datehook.o und-datehook.lst
+ifneq ($(datehook_mod_EXPORTS),no)
+CLEANFILES += def-datehook.lst
+DEFSYMFILES += def-datehook.lst
+endif
+MOSTLYCLEANFILES += datehook_mod-hook_datehook.d
+UNDSYMFILES += und-datehook.lst
+
+datehook.mod: pre-datehook.o mod-datehook.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(datehook_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-datehook.o mod-datehook.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-datehook.o: $(datehook_mod_DEPENDENCIES) datehook_mod-hook_datehook.o
+       -rm -f $@
+       $(TARGET_CC) $(datehook_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ datehook_mod-hook_datehook.o
+
+mod-datehook.o: mod-datehook.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -c -o $@ $<
+
+mod-datehook.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'datehook' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(datehook_mod_EXPORTS),no)
+def-datehook.lst: pre-datehook.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 datehook/' > $@
+endif
+
+und-datehook.lst: pre-datehook.o
+       echo 'datehook' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+datehook_mod-hook_datehook.o: hook/datehook.c $(hook/datehook.c_DEPENDENCIES)
+       $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -MD -c -o $@ $<
+-include datehook_mod-hook_datehook.d
+
+CLEANFILES += cmd-datehook_mod-hook_datehook.lst fs-datehook_mod-hook_datehook.lst partmap-datehook_mod-hook_datehook.lst
+COMMANDFILES += cmd-datehook_mod-hook_datehook.lst
+FSFILES += fs-datehook_mod-hook_datehook.lst
+PARTMAPFILES += partmap-datehook_mod-hook_datehook.lst
+
+cmd-datehook_mod-hook_datehook.lst: hook/datehook.c $(hook/datehook.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh datehook > $@ || (rm -f $@; exit 1)
+
+fs-datehook_mod-hook_datehook.lst: hook/datehook.c $(hook/datehook.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh datehook > $@ || (rm -f $@; exit 1)
+
+partmap-datehook_mod-hook_datehook.lst: hook/datehook.c $(hook/datehook.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh datehook > $@ || (rm -f $@; exit 1)
+
+
+datehook_mod_CFLAGS = $(COMMON_CFLAGS)
+datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lsmmap.mod
+lsmmap_mod_SOURCES = commands/lsmmap.c
+CLEANFILES += lsmmap.mod mod-lsmmap.o mod-lsmmap.c pre-lsmmap.o lsmmap_mod-commands_lsmmap.o und-lsmmap.lst
+ifneq ($(lsmmap_mod_EXPORTS),no)
+CLEANFILES += def-lsmmap.lst
+DEFSYMFILES += def-lsmmap.lst
+endif
+MOSTLYCLEANFILES += lsmmap_mod-commands_lsmmap.d
+UNDSYMFILES += und-lsmmap.lst
+
+lsmmap.mod: pre-lsmmap.o mod-lsmmap.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(lsmmap_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-lsmmap.o mod-lsmmap.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-lsmmap.o: $(lsmmap_mod_DEPENDENCIES) lsmmap_mod-commands_lsmmap.o
+       -rm -f $@
+       $(TARGET_CC) $(lsmmap_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ lsmmap_mod-commands_lsmmap.o
+
+mod-lsmmap.o: mod-lsmmap.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -c -o $@ $<
+
+mod-lsmmap.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'lsmmap' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(lsmmap_mod_EXPORTS),no)
+def-lsmmap.lst: pre-lsmmap.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 lsmmap/' > $@
+endif
+
+und-lsmmap.lst: pre-lsmmap.o
+       echo 'lsmmap' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+lsmmap_mod-commands_lsmmap.o: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -MD -c -o $@ $<
+-include lsmmap_mod-commands_lsmmap.d
+
+CLEANFILES += cmd-lsmmap_mod-commands_lsmmap.lst fs-lsmmap_mod-commands_lsmmap.lst partmap-lsmmap_mod-commands_lsmmap.lst
+COMMANDFILES += cmd-lsmmap_mod-commands_lsmmap.lst
+FSFILES += fs-lsmmap_mod-commands_lsmmap.lst
+PARTMAPFILES += partmap-lsmmap_mod-commands_lsmmap.lst
+
+cmd-lsmmap_mod-commands_lsmmap.lst: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh lsmmap > $@ || (rm -f $@; exit 1)
+
+fs-lsmmap_mod-commands_lsmmap.lst: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh lsmmap > $@ || (rm -f $@; exit 1)
+
+partmap-lsmmap_mod-commands_lsmmap.lst: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh lsmmap > $@ || (rm -f $@; exit 1)
+
+
+lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
+lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+include $(srcdir)/conf/i386.mk
+include $(srcdir)/conf/common.mk
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
new file mode 100644 (file)
index 0000000..903113e
--- /dev/null
@@ -0,0 +1,214 @@
+# -*- makefile -*-
+
+COMMON_ASFLAGS = -m32 -nostdinc -fno-builtin
+COMMON_CFLAGS  = -ffreestanding -mrtd -mregparm=3
+COMMON_LDFLAGS = -nostdlib -static -lgcc
+
+# Used by various components.  These rules need to precede them.
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Images.
+pkglib_PROGRAMS = kernel.elf
+
+# For kernel.elf.
+kernel_elf_SOURCES = kern/i386/ieee1275/startup.S kern/i386/ieee1275/init.c \
+       kern/ieee1275/init.c \
+       kern/ieee1275/mmap.c \
+       kern/ieee1275/cmain.c kern/ieee1275/openfw.c \
+       kern/main.c kern/device.c \
+       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
+       kern/i386/dl.c kern/parser.c kern/partition.c \
+       kern/env.c \
+       kern/time.c \
+       kern/generic/millisleep.c \
+       kern/ieee1275/ieee1275.c \
+       term/ieee1275/ofconsole.c \
+       disk/ieee1275/ofdisk.c \
+       symlist.c
+kernel_elf_HEADERS = arg.h cache.h device.h disk.h dl.h elf.h elfload.h \
+       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
+       partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
+       ieee1275/ieee1275.h machine/kernel.h machine/loader.h machine/memory.h
+kernel_elf_CFLAGS = $(COMMON_CFLAGS)
+kernel_elf_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x10000,-Bstatic
+
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+symlist.c: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h gensymlist.sh
+       /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h genkernsyms.sh
+       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+# Utilities.
+sbin_UTILITIES = grub-mkdevicemap
+ifeq ($(enable_grub_emu), yes)
+sbin_UTILITIES += grub-emu
+endif
+
+# For grub-mkdevicemap.
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+
+# For grub-emu.
+util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
+grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c       \
+       commands/configfile.c commands/echo.c commands/help.c           \
+       commands/terminal.c commands/ls.c commands/test.c               \
+       commands/search.c commands/blocklist.c commands/hexdump.c       \
+       lib/hexdump.c commands/halt.c commands/reboot.c                 \
+       commands/i386/cpuid.c                                           \
+       disk/host.c disk/loopback.c                                     \
+       \
+       fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c                 \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c          \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c                  \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                             \
+       \
+       fs/fshelp.c                                                     \
+       io/gzio.c                                                       \
+       kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c       \
+       kern/err.c                                                      \
+       normal/execute.c kern/file.c kern/fs.c normal/lexer.c           \
+       kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
+       grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
+       normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
+       normal/completion.c normal/main.c normal/menu_text.c            \
+       normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
+       normal/misc.c normal/script.c                                   \
+       normal/color.c                                                  \
+       partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
+       partmap/acorn.c partmap/gpt.c                                   \
+       util/console.c util/hostfs.c util/grub-emu.c util/misc.c        \
+       util/hostdisk.c util/getroot.c                                  \
+       util/i386/pc/misc.c                                             \
+       \
+       disk/raid.c disk/raid5_recover.c disk/raid6_recover.c           \
+       disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c             \
+       grub_emu_init.c
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+# Scripts.
+sbin_SCRIPTS = grub-install
+
+# For grub-install.
+grub_install_SOURCES = util/ieee1275/grub-install.in
+
+# Modules.
+pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod            \
+       multiboot.mod _multiboot.mod aout.mod serial.mod linux.mod      \
+       _linux.mod nand.mod memdisk.mod pci.mod lspci.mod datetime.mod  \
+       date.mod datehook.mod lsmmap.mod
+
+#
+# Only arch dependant part of normal.mod will be here. Common part for
+# all architecures of normal.mod is at start and should be kept at sync
+# with other makefiles.
+# 
+# Please put arch dependant part of normal.mod at the end of list to
+# keep it simpler to update to different architectures.
+#
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/color.c                                                  \
+       normal/menu_viewer.c normal/menu_entry.c                        \
+       normal/misc.c grub_script.tab.c                                 \
+       normal/script.c                                                 \
+       normal/i386/setjmp.S
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _multiboot.mod.
+_multiboot_mod_SOURCES = loader/ieee1275/multiboot2.c \
+                        loader/multiboot2.c \
+                        loader/multiboot_loader.c
+_multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+_multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For multiboot.mod.
+multiboot_mod_SOURCES = loader/multiboot_loader_normal.c 
+multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For aout.mod.
+aout_mod_SOURCES = loader/aout.c
+aout_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For suspend.mod
+suspend_mod_SOURCES = commands/ieee1275/suspend.c
+suspend_mod_CFLAGS = $(COMMON_CFLAGS)
+suspend_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reboot.mod
+reboot_mod_SOURCES = commands/reboot.c
+reboot_mod_CFLAGS = $(COMMON_CFLAGS)
+reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For halt.mod
+halt_mod_SOURCES = commands/halt.c
+halt_mod_CFLAGS = $(COMMON_CFLAGS)
+halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For serial.mod.
+serial_mod_SOURCES = term/i386/pc/serial.c
+serial_mod_CFLAGS = $(COMMON_CFLAGS)
+serial_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _linux.mod.
+_linux_mod_SOURCES = loader/i386/ieee1275/linux.c
+_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/linux_normal.c
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For nand.mod.
+nand_mod_SOURCES = disk/ieee1275/nand.c
+nand_mod_CFLAGS = $(COMMON_CFLAGS)
+nand_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For memdisk.mod.
+memdisk_mod_SOURCES = disk/memdisk.c
+memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datetime.mod
+datetime_mod_SOURCES = lib/datetime.c lib/i386/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datehook.mod
+datehook_mod_SOURCES = hook/datehook.c
+datehook_mod_CFLAGS = $(COMMON_CFLAGS)
+datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lsmmap.mod
+lsmmap_mod_SOURCES = commands/lsmmap.c
+lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
+lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+include $(srcdir)/conf/i386.mk
+include $(srcdir)/conf/common.mk
diff --git a/conf/i386-pc-cygwin-img-ld.sc b/conf/i386-pc-cygwin-img-ld.sc
new file mode 100644 (file)
index 0000000..a41cac7
--- /dev/null
@@ -0,0 +1,53 @@
+/* Linker script to create grub .img files on Cygwin.  */
+
+SECTIONS
+{
+  .text :
+  {
+    start = . ;
+    *(.text)
+    etext = . ;
+  }
+  .data :
+  {
+    __data_start__ = . ;
+    *(.data)
+    __data_end__ = . ;
+  }
+  .rdata :
+  {
+    __rdata_start__ = . ;
+    *(.rdata)
+    __rdata_end__ = . ;
+  }
+  .pdata :
+  {
+    *(.pdata)
+    edata = . ;
+  }
+  .bss :
+  {
+    __bss_start__ = . ;
+    *(.bss)
+    __common_start__ = . ;
+    *(COMMON)
+    __bss_end__ = . ;
+  }
+  .edata :
+  {
+    *(.edata)
+    end = . ;
+  }
+  .stab :
+  {
+    *(.stab)
+  }
+  .stabstr :
+  {
+    *(.stabstr)
+  }
+}
+
+ASSERT("__rdata_end__"=="edata", ".pdata not empty")
+ASSERT("__bss_end__"  =="end"  , ".edata not empty")
+
diff --git a/conf/i386-pc.mk b/conf/i386-pc.mk
new file mode 100644 (file)
index 0000000..72e0957
--- /dev/null
@@ -0,0 +1,3609 @@
+# -*- makefile -*-
+# Generated by genmk.rb, please don't edit!
+
+GRUB_MEMORY_MACHINE_LINK_ADDR = 0x8200
+
+COMMON_ASFLAGS = -nostdinc -fno-builtin -m32
+COMMON_CFLAGS = -fno-builtin -mrtd -mregparm=3 -m32
+COMMON_LDFLAGS = -m32 -nostdlib
+
+# Used by various components.  These rules need to precede them.
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Images.
+pkglib_IMAGES = boot.img diskboot.img kernel.img pxeboot.img lnxboot.img \
+               cdboot.img
+
+# For boot.img.
+boot_img_SOURCES = boot/i386/pc/boot.S
+CLEANFILES += boot.img boot.exec boot_img-boot_i386_pc_boot.o
+MOSTLYCLEANFILES += boot_img-boot_i386_pc_boot.d
+
+boot.img: boot.exec
+       $(OBJCOPY) -O binary -R .note -R .comment -R .note.gnu.build-id $< $@
+
+boot.exec: boot_img-boot_i386_pc_boot.o
+       $(TARGET_CC) -o $@ $^ $(TARGET_LDFLAGS) $(boot_img_LDFLAGS)
+
+boot_img-boot_i386_pc_boot.o: boot/i386/pc/boot.S $(boot/i386/pc/boot.S_DEPENDENCIES)
+       $(TARGET_CC) -Iboot/i386/pc -I$(srcdir)/boot/i386/pc $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(boot_img_ASFLAGS) -MD -c -o $@ $<
+-include boot_img-boot_i386_pc_boot.d
+
+boot_img_ASFLAGS = $(COMMON_ASFLAGS)
+boot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,7C00
+
+# For pxeboot.img
+pxeboot_img_SOURCES = boot/i386/pc/pxeboot.S
+CLEANFILES += pxeboot.img pxeboot.exec pxeboot_img-boot_i386_pc_pxeboot.o
+MOSTLYCLEANFILES += pxeboot_img-boot_i386_pc_pxeboot.d
+
+pxeboot.img: pxeboot.exec
+       $(OBJCOPY) -O binary -R .note -R .comment -R .note.gnu.build-id $< $@
+
+pxeboot.exec: pxeboot_img-boot_i386_pc_pxeboot.o
+       $(TARGET_CC) -o $@ $^ $(TARGET_LDFLAGS) $(pxeboot_img_LDFLAGS)
+
+pxeboot_img-boot_i386_pc_pxeboot.o: boot/i386/pc/pxeboot.S $(boot/i386/pc/pxeboot.S_DEPENDENCIES)
+       $(TARGET_CC) -Iboot/i386/pc -I$(srcdir)/boot/i386/pc $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(pxeboot_img_ASFLAGS) -MD -c -o $@ $<
+-include pxeboot_img-boot_i386_pc_pxeboot.d
+
+pxeboot_img_ASFLAGS = $(COMMON_ASFLAGS)
+pxeboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,7C00
+
+# For diskboot.img.
+diskboot_img_SOURCES = boot/i386/pc/diskboot.S
+CLEANFILES += diskboot.img diskboot.exec diskboot_img-boot_i386_pc_diskboot.o
+MOSTLYCLEANFILES += diskboot_img-boot_i386_pc_diskboot.d
+
+diskboot.img: diskboot.exec
+       $(OBJCOPY) -O binary -R .note -R .comment -R .note.gnu.build-id $< $@
+
+diskboot.exec: diskboot_img-boot_i386_pc_diskboot.o
+       $(TARGET_CC) -o $@ $^ $(TARGET_LDFLAGS) $(diskboot_img_LDFLAGS)
+
+diskboot_img-boot_i386_pc_diskboot.o: boot/i386/pc/diskboot.S $(boot/i386/pc/diskboot.S_DEPENDENCIES)
+       $(TARGET_CC) -Iboot/i386/pc -I$(srcdir)/boot/i386/pc $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(diskboot_img_ASFLAGS) -MD -c -o $@ $<
+-include diskboot_img-boot_i386_pc_diskboot.d
+
+diskboot_img_ASFLAGS = $(COMMON_ASFLAGS)
+diskboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,8000
+
+# For lnxboot.img.
+lnxboot_img_SOURCES = boot/i386/pc/lnxboot.S
+CLEANFILES += lnxboot.img lnxboot.exec lnxboot_img-boot_i386_pc_lnxboot.o
+MOSTLYCLEANFILES += lnxboot_img-boot_i386_pc_lnxboot.d
+
+lnxboot.img: lnxboot.exec
+       $(OBJCOPY) -O binary -R .note -R .comment -R .note.gnu.build-id $< $@
+
+lnxboot.exec: lnxboot_img-boot_i386_pc_lnxboot.o
+       $(TARGET_CC) -o $@ $^ $(TARGET_LDFLAGS) $(lnxboot_img_LDFLAGS)
+
+lnxboot_img-boot_i386_pc_lnxboot.o: boot/i386/pc/lnxboot.S $(boot/i386/pc/lnxboot.S_DEPENDENCIES)
+       $(TARGET_CC) -Iboot/i386/pc -I$(srcdir)/boot/i386/pc $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(lnxboot_img_ASFLAGS) -MD -c -o $@ $<
+-include lnxboot_img-boot_i386_pc_lnxboot.d
+
+lnxboot_img_ASFLAGS = $(COMMON_ASFLAGS)
+lnxboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,6000
+
+# For cdboot.img.
+cdboot_img_SOURCES = boot/i386/pc/cdboot.S
+CLEANFILES += cdboot.img cdboot.exec cdboot_img-boot_i386_pc_cdboot.o
+MOSTLYCLEANFILES += cdboot_img-boot_i386_pc_cdboot.d
+
+cdboot.img: cdboot.exec
+       $(OBJCOPY) -O binary -R .note -R .comment -R .note.gnu.build-id $< $@
+
+cdboot.exec: cdboot_img-boot_i386_pc_cdboot.o
+       $(TARGET_CC) -o $@ $^ $(TARGET_LDFLAGS) $(cdboot_img_LDFLAGS)
+
+cdboot_img-boot_i386_pc_cdboot.o: boot/i386/pc/cdboot.S $(boot/i386/pc/cdboot.S_DEPENDENCIES)
+       $(TARGET_CC) -Iboot/i386/pc -I$(srcdir)/boot/i386/pc $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(cdboot_img_ASFLAGS) -MD -c -o $@ $<
+-include cdboot_img-boot_i386_pc_cdboot.d
+
+cdboot_img_ASFLAGS = $(COMMON_ASFLAGS)
+cdboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,7C00
+
+# For kernel.img.
+kernel_img_SOURCES = kern/i386/pc/startup.S kern/main.c kern/device.c \
+       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
+       kern/time.c \
+       kern/i386/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \
+       kern/parser.c kern/partition.c \
+       kern/i386/tsc.c kern/i386/pit.c \
+       kern/generic/rtc_get_time_ms.c \
+       kern/generic/millisleep.c \
+       kern/env.c \
+       term/i386/pc/console.c term/i386/vga_common.c \
+       symlist.c
+CLEANFILES += kernel.img kernel.exec kernel_img-kern_i386_pc_startup.o kernel_img-kern_main.o kernel_img-kern_device.o kernel_img-kern_disk.o kernel_img-kern_dl.o kernel_img-kern_file.o kernel_img-kern_fs.o kernel_img-kern_err.o kernel_img-kern_misc.o kernel_img-kern_mm.o kernel_img-kern_loader.o kernel_img-kern_rescue.o kernel_img-kern_term.o kernel_img-kern_time.o kernel_img-kern_i386_dl.o kernel_img-kern_i386_pc_init.o kernel_img-kern_i386_pc_mmap.o kernel_img-kern_parser.o kernel_img-kern_partition.o kernel_img-kern_i386_tsc.o kernel_img-kern_i386_pit.o kernel_img-kern_generic_rtc_get_time_ms.o kernel_img-kern_generic_millisleep.o kernel_img-kern_env.o kernel_img-term_i386_pc_console.o kernel_img-term_i386_vga_common.o kernel_img-symlist.o
+MOSTLYCLEANFILES += kernel_img-kern_i386_pc_startup.d kernel_img-kern_main.d kernel_img-kern_device.d kernel_img-kern_disk.d kernel_img-kern_dl.d kernel_img-kern_file.d kernel_img-kern_fs.d kernel_img-kern_err.d kernel_img-kern_misc.d kernel_img-kern_mm.d kernel_img-kern_loader.d kernel_img-kern_rescue.d kernel_img-kern_term.d kernel_img-kern_time.d kernel_img-kern_i386_dl.d kernel_img-kern_i386_pc_init.d kernel_img-kern_i386_pc_mmap.d kernel_img-kern_parser.d kernel_img-kern_partition.d kernel_img-kern_i386_tsc.d kernel_img-kern_i386_pit.d kernel_img-kern_generic_rtc_get_time_ms.d kernel_img-kern_generic_millisleep.d kernel_img-kern_env.d kernel_img-term_i386_pc_console.d kernel_img-term_i386_vga_common.d kernel_img-symlist.d
+
+kernel.img: kernel.exec
+       $(OBJCOPY) -O binary -R .note -R .comment -R .note.gnu.build-id $< $@
+
+kernel.exec: kernel_img-kern_i386_pc_startup.o kernel_img-kern_main.o kernel_img-kern_device.o kernel_img-kern_disk.o kernel_img-kern_dl.o kernel_img-kern_file.o kernel_img-kern_fs.o kernel_img-kern_err.o kernel_img-kern_misc.o kernel_img-kern_mm.o kernel_img-kern_loader.o kernel_img-kern_rescue.o kernel_img-kern_term.o kernel_img-kern_time.o kernel_img-kern_i386_dl.o kernel_img-kern_i386_pc_init.o kernel_img-kern_i386_pc_mmap.o kernel_img-kern_parser.o kernel_img-kern_partition.o kernel_img-kern_i386_tsc.o kernel_img-kern_i386_pit.o kernel_img-kern_generic_rtc_get_time_ms.o kernel_img-kern_generic_millisleep.o kernel_img-kern_env.o kernel_img-term_i386_pc_console.o kernel_img-term_i386_vga_common.o kernel_img-symlist.o
+       $(TARGET_CC) -o $@ $^ $(TARGET_LDFLAGS) $(kernel_img_LDFLAGS)
+
+kernel_img-kern_i386_pc_startup.o: kern/i386/pc/startup.S $(kern/i386/pc/startup.S_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386/pc -I$(srcdir)/kern/i386/pc $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(kernel_img_ASFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_i386_pc_startup.d
+
+kernel_img-kern_main.o: kern/main.c $(kern/main.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_main.d
+
+kernel_img-kern_device.o: kern/device.c $(kern/device.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_device.d
+
+kernel_img-kern_disk.o: kern/disk.c $(kern/disk.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_disk.d
+
+kernel_img-kern_dl.o: kern/dl.c $(kern/dl.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_dl.d
+
+kernel_img-kern_file.o: kern/file.c $(kern/file.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_file.d
+
+kernel_img-kern_fs.o: kern/fs.c $(kern/fs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_fs.d
+
+kernel_img-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_err.d
+
+kernel_img-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_misc.d
+
+kernel_img-kern_mm.o: kern/mm.c $(kern/mm.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_mm.d
+
+kernel_img-kern_loader.o: kern/loader.c $(kern/loader.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_loader.d
+
+kernel_img-kern_rescue.o: kern/rescue.c $(kern/rescue.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_rescue.d
+
+kernel_img-kern_term.o: kern/term.c $(kern/term.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_term.d
+
+kernel_img-kern_time.o: kern/time.c $(kern/time.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_time.d
+
+kernel_img-kern_i386_dl.o: kern/i386/dl.c $(kern/i386/dl.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_i386_dl.d
+
+kernel_img-kern_i386_pc_init.o: kern/i386/pc/init.c $(kern/i386/pc/init.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386/pc -I$(srcdir)/kern/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_i386_pc_init.d
+
+kernel_img-kern_i386_pc_mmap.o: kern/i386/pc/mmap.c $(kern/i386/pc/mmap.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386/pc -I$(srcdir)/kern/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_i386_pc_mmap.d
+
+kernel_img-kern_parser.o: kern/parser.c $(kern/parser.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_parser.d
+
+kernel_img-kern_partition.o: kern/partition.c $(kern/partition.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_partition.d
+
+kernel_img-kern_i386_tsc.o: kern/i386/tsc.c $(kern/i386/tsc.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_i386_tsc.d
+
+kernel_img-kern_i386_pit.o: kern/i386/pit.c $(kern/i386/pit.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_i386_pit.d
+
+kernel_img-kern_generic_rtc_get_time_ms.o: kern/generic/rtc_get_time_ms.c $(kern/generic/rtc_get_time_ms.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_generic_rtc_get_time_ms.d
+
+kernel_img-kern_generic_millisleep.o: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_generic_millisleep.d
+
+kernel_img-kern_env.o: kern/env.c $(kern/env.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-kern_env.d
+
+kernel_img-term_i386_pc_console.o: term/i386/pc/console.c $(term/i386/pc/console.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-term_i386_pc_console.d
+
+kernel_img-term_i386_vga_common.o: term/i386/vga_common.c $(term/i386/vga_common.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/i386 -I$(srcdir)/term/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-term_i386_vga_common.d
+
+kernel_img-symlist.o: symlist.c $(symlist.c_DEPENDENCIES)
+       $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_img_CFLAGS) -MD -c -o $@ $<
+-include kernel_img-symlist.d
+
+kernel_img_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
+       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
+       partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
+       machine/biosdisk.h machine/boot.h machine/console.h machine/init.h \
+       machine/memory.h machine/loader.h machine/vga.h machine/vbe.h \
+       machine/kernel.h machine/pxe.h
+kernel_img_CFLAGS = $(COMMON_CFLAGS)
+kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,$(GRUB_MEMORY_MACHINE_LINK_ADDR) $(COMMON_CFLAGS)
+
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+symlist.c: $(addprefix include/grub/,$(kernel_img_HEADERS)) config.h gensymlist.sh
+       /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_img_HEADERS)) config.h genkernsyms.sh
+       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+# Utilities.
+bin_UTILITIES = grub-mkimage
+sbin_UTILITIES = grub-setup grub-mkdevicemap
+ifeq ($(enable_grub_emu), yes)
+sbin_UTILITIES += grub-emu
+endif
+
+# For grub-mkimage.
+ifeq ($(enable_lzo), yes)
+grub_mkimage_SOURCES = util/i386/pc/grub-mkimage.c util/misc.c \
+       util/resolve.c
+CLEANFILES += grub-mkimage$(EXEEXT) grub_mkimage-util_i386_pc_grub_mkimage.o grub_mkimage-util_misc.o grub_mkimage-util_resolve.o
+MOSTLYCLEANFILES += grub_mkimage-util_i386_pc_grub_mkimage.d grub_mkimage-util_misc.d grub_mkimage-util_resolve.d
+
+grub-mkimage: $(grub_mkimage_DEPENDENCIES) grub_mkimage-util_i386_pc_grub_mkimage.o grub_mkimage-util_misc.o grub_mkimage-util_resolve.o
+       $(CC) -o $@ grub_mkimage-util_i386_pc_grub_mkimage.o grub_mkimage-util_misc.o grub_mkimage-util_resolve.o $(LDFLAGS) $(grub_mkimage_LDFLAGS)
+
+grub_mkimage-util_i386_pc_grub_mkimage.o: util/i386/pc/grub-mkimage.c $(util/i386/pc/grub-mkimage.c_DEPENDENCIES)
+       $(CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkimage-util_i386_pc_grub_mkimage.d
+
+grub_mkimage-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkimage-util_misc.d
+
+grub_mkimage-util_resolve.o: util/resolve.c $(util/resolve.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkimage-util_resolve.d
+
+grub_mkimage_LDFLAGS = $(LIBLZO)
+else
+grub_mkimage_SOURCES = util/i386/pc/grub-mkimage.c util/misc.c \
+       util/resolve.c lib/LzmaEnc.c lib/LzFind.c
+CLEANFILES += grub-mkimage$(EXEEXT) grub_mkimage-util_i386_pc_grub_mkimage.o grub_mkimage-util_misc.o grub_mkimage-util_resolve.o grub_mkimage-lib_LzmaEnc.o grub_mkimage-lib_LzFind.o
+MOSTLYCLEANFILES += grub_mkimage-util_i386_pc_grub_mkimage.d grub_mkimage-util_misc.d grub_mkimage-util_resolve.d grub_mkimage-lib_LzmaEnc.d grub_mkimage-lib_LzFind.d
+
+grub-mkimage: $(grub_mkimage_DEPENDENCIES) grub_mkimage-util_i386_pc_grub_mkimage.o grub_mkimage-util_misc.o grub_mkimage-util_resolve.o grub_mkimage-lib_LzmaEnc.o grub_mkimage-lib_LzFind.o
+       $(CC) -o $@ grub_mkimage-util_i386_pc_grub_mkimage.o grub_mkimage-util_misc.o grub_mkimage-util_resolve.o grub_mkimage-lib_LzmaEnc.o grub_mkimage-lib_LzFind.o $(LDFLAGS) $(grub_mkimage_LDFLAGS)
+
+grub_mkimage-util_i386_pc_grub_mkimage.o: util/i386/pc/grub-mkimage.c $(util/i386/pc/grub-mkimage.c_DEPENDENCIES)
+       $(CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkimage-util_i386_pc_grub_mkimage.d
+
+grub_mkimage-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkimage-util_misc.d
+
+grub_mkimage-util_resolve.o: util/resolve.c $(util/resolve.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkimage-util_resolve.d
+
+grub_mkimage-lib_LzmaEnc.o: lib/LzmaEnc.c $(lib/LzmaEnc.c_DEPENDENCIES)
+       $(CC) -Ilib -I$(srcdir)/lib $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkimage-lib_LzmaEnc.d
+
+grub_mkimage-lib_LzFind.o: lib/LzFind.c $(lib/LzFind.c_DEPENDENCIES)
+       $(CC) -Ilib -I$(srcdir)/lib $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkimage-lib_LzFind.d
+
+endif
+grub_mkimage_CFLAGS = -DGRUB_MEMORY_MACHINE_LINK_ADDR=$(GRUB_MEMORY_MACHINE_LINK_ADDR)
+util/i386/pc/grub-mkimage.c_DEPENDENCIES = Makefile
+
+# For grub-setup.
+util/i386/pc/grub-setup.c_DEPENDENCIES = grub_setup_init.h
+grub_setup_SOURCES = util/i386/pc/grub-setup.c util/hostdisk.c \
+       util/misc.c util/getroot.c kern/device.c kern/disk.c    \
+       kern/err.c kern/misc.c kern/parser.c kern/partition.c   \
+       kern/file.c kern/fs.c kern/env.c fs/fshelp.c            \
+       \
+       fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c         \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c  \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c          \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                     \
+       \
+       partmap/pc.c partmap/gpt.c                              \
+       \
+       disk/raid.c disk/mdraid_linux.c disk/lvm.c              \
+       util/raid.c util/lvm.c                                  \
+       grub_setup_init.c
+CLEANFILES += grub-setup$(EXEEXT) grub_setup-util_i386_pc_grub_setup.o grub_setup-util_hostdisk.o grub_setup-util_misc.o grub_setup-util_getroot.o grub_setup-kern_device.o grub_setup-kern_disk.o grub_setup-kern_err.o grub_setup-kern_misc.o grub_setup-kern_parser.o grub_setup-kern_partition.o grub_setup-kern_file.o grub_setup-kern_fs.o grub_setup-kern_env.o grub_setup-fs_fshelp.o grub_setup-fs_affs.o grub_setup-fs_cpio.o grub_setup-fs_ext2.o grub_setup-fs_fat.o grub_setup-fs_hfs.o grub_setup-fs_hfsplus.o grub_setup-fs_iso9660.o grub_setup-fs_udf.o grub_setup-fs_jfs.o grub_setup-fs_minix.o grub_setup-fs_ntfs.o grub_setup-fs_ntfscomp.o grub_setup-fs_reiserfs.o grub_setup-fs_sfs.o grub_setup-fs_ufs.o grub_setup-fs_xfs.o grub_setup-fs_afs.o grub_setup-fs_tar.o grub_setup-partmap_pc.o grub_setup-partmap_gpt.o grub_setup-disk_raid.o grub_setup-disk_mdraid_linux.o grub_setup-disk_lvm.o grub_setup-util_raid.o grub_setup-util_lvm.o grub_setup-grub_setup_init.o
+MOSTLYCLEANFILES += grub_setup-util_i386_pc_grub_setup.d grub_setup-util_hostdisk.d grub_setup-util_misc.d grub_setup-util_getroot.d grub_setup-kern_device.d grub_setup-kern_disk.d grub_setup-kern_err.d grub_setup-kern_misc.d grub_setup-kern_parser.d grub_setup-kern_partition.d grub_setup-kern_file.d grub_setup-kern_fs.d grub_setup-kern_env.d grub_setup-fs_fshelp.d grub_setup-fs_affs.d grub_setup-fs_cpio.d grub_setup-fs_ext2.d grub_setup-fs_fat.d grub_setup-fs_hfs.d grub_setup-fs_hfsplus.d grub_setup-fs_iso9660.d grub_setup-fs_udf.d grub_setup-fs_jfs.d grub_setup-fs_minix.d grub_setup-fs_ntfs.d grub_setup-fs_ntfscomp.d grub_setup-fs_reiserfs.d grub_setup-fs_sfs.d grub_setup-fs_ufs.d grub_setup-fs_xfs.d grub_setup-fs_afs.d grub_setup-fs_tar.d grub_setup-partmap_pc.d grub_setup-partmap_gpt.d grub_setup-disk_raid.d grub_setup-disk_mdraid_linux.d grub_setup-disk_lvm.d grub_setup-util_raid.d grub_setup-util_lvm.d grub_setup-grub_setup_init.d
+
+grub-setup: $(grub_setup_DEPENDENCIES) grub_setup-util_i386_pc_grub_setup.o grub_setup-util_hostdisk.o grub_setup-util_misc.o grub_setup-util_getroot.o grub_setup-kern_device.o grub_setup-kern_disk.o grub_setup-kern_err.o grub_setup-kern_misc.o grub_setup-kern_parser.o grub_setup-kern_partition.o grub_setup-kern_file.o grub_setup-kern_fs.o grub_setup-kern_env.o grub_setup-fs_fshelp.o grub_setup-fs_affs.o grub_setup-fs_cpio.o grub_setup-fs_ext2.o grub_setup-fs_fat.o grub_setup-fs_hfs.o grub_setup-fs_hfsplus.o grub_setup-fs_iso9660.o grub_setup-fs_udf.o grub_setup-fs_jfs.o grub_setup-fs_minix.o grub_setup-fs_ntfs.o grub_setup-fs_ntfscomp.o grub_setup-fs_reiserfs.o grub_setup-fs_sfs.o grub_setup-fs_ufs.o grub_setup-fs_xfs.o grub_setup-fs_afs.o grub_setup-fs_tar.o grub_setup-partmap_pc.o grub_setup-partmap_gpt.o grub_setup-disk_raid.o grub_setup-disk_mdraid_linux.o grub_setup-disk_lvm.o grub_setup-util_raid.o grub_setup-util_lvm.o grub_setup-grub_setup_init.o
+       $(CC) -o $@ grub_setup-util_i386_pc_grub_setup.o grub_setup-util_hostdisk.o grub_setup-util_misc.o grub_setup-util_getroot.o grub_setup-kern_device.o grub_setup-kern_disk.o grub_setup-kern_err.o grub_setup-kern_misc.o grub_setup-kern_parser.o grub_setup-kern_partition.o grub_setup-kern_file.o grub_setup-kern_fs.o grub_setup-kern_env.o grub_setup-fs_fshelp.o grub_setup-fs_affs.o grub_setup-fs_cpio.o grub_setup-fs_ext2.o grub_setup-fs_fat.o grub_setup-fs_hfs.o grub_setup-fs_hfsplus.o grub_setup-fs_iso9660.o grub_setup-fs_udf.o grub_setup-fs_jfs.o grub_setup-fs_minix.o grub_setup-fs_ntfs.o grub_setup-fs_ntfscomp.o grub_setup-fs_reiserfs.o grub_setup-fs_sfs.o grub_setup-fs_ufs.o grub_setup-fs_xfs.o grub_setup-fs_afs.o grub_setup-fs_tar.o grub_setup-partmap_pc.o grub_setup-partmap_gpt.o grub_setup-disk_raid.o grub_setup-disk_mdraid_linux.o grub_setup-disk_lvm.o grub_setup-util_raid.o grub_setup-util_lvm.o grub_setup-grub_setup_init.o $(LDFLAGS) $(grub_setup_LDFLAGS)
+
+grub_setup-util_i386_pc_grub_setup.o: util/i386/pc/grub-setup.c $(util/i386/pc/grub-setup.c_DEPENDENCIES)
+       $(CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-util_i386_pc_grub_setup.d
+
+grub_setup-util_hostdisk.o: util/hostdisk.c $(util/hostdisk.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-util_hostdisk.d
+
+grub_setup-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-util_misc.d
+
+grub_setup-util_getroot.o: util/getroot.c $(util/getroot.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-util_getroot.d
+
+grub_setup-kern_device.o: kern/device.c $(kern/device.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-kern_device.d
+
+grub_setup-kern_disk.o: kern/disk.c $(kern/disk.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-kern_disk.d
+
+grub_setup-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-kern_err.d
+
+grub_setup-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-kern_misc.d
+
+grub_setup-kern_parser.o: kern/parser.c $(kern/parser.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-kern_parser.d
+
+grub_setup-kern_partition.o: kern/partition.c $(kern/partition.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-kern_partition.d
+
+grub_setup-kern_file.o: kern/file.c $(kern/file.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-kern_file.d
+
+grub_setup-kern_fs.o: kern/fs.c $(kern/fs.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-kern_fs.d
+
+grub_setup-kern_env.o: kern/env.c $(kern/env.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-kern_env.d
+
+grub_setup-fs_fshelp.o: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_fshelp.d
+
+grub_setup-fs_affs.o: fs/affs.c $(fs/affs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_affs.d
+
+grub_setup-fs_cpio.o: fs/cpio.c $(fs/cpio.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_cpio.d
+
+grub_setup-fs_ext2.o: fs/ext2.c $(fs/ext2.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_ext2.d
+
+grub_setup-fs_fat.o: fs/fat.c $(fs/fat.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_fat.d
+
+grub_setup-fs_hfs.o: fs/hfs.c $(fs/hfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_hfs.d
+
+grub_setup-fs_hfsplus.o: fs/hfsplus.c $(fs/hfsplus.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_hfsplus.d
+
+grub_setup-fs_iso9660.o: fs/iso9660.c $(fs/iso9660.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_iso9660.d
+
+grub_setup-fs_udf.o: fs/udf.c $(fs/udf.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_udf.d
+
+grub_setup-fs_jfs.o: fs/jfs.c $(fs/jfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_jfs.d
+
+grub_setup-fs_minix.o: fs/minix.c $(fs/minix.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_minix.d
+
+grub_setup-fs_ntfs.o: fs/ntfs.c $(fs/ntfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_ntfs.d
+
+grub_setup-fs_ntfscomp.o: fs/ntfscomp.c $(fs/ntfscomp.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_ntfscomp.d
+
+grub_setup-fs_reiserfs.o: fs/reiserfs.c $(fs/reiserfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_reiserfs.d
+
+grub_setup-fs_sfs.o: fs/sfs.c $(fs/sfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_sfs.d
+
+grub_setup-fs_ufs.o: fs/ufs.c $(fs/ufs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_ufs.d
+
+grub_setup-fs_xfs.o: fs/xfs.c $(fs/xfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_xfs.d
+
+grub_setup-fs_afs.o: fs/afs.c $(fs/afs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_afs.d
+
+grub_setup-fs_tar.o: fs/tar.c $(fs/tar.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-fs_tar.d
+
+grub_setup-partmap_pc.o: partmap/pc.c $(partmap/pc.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-partmap_pc.d
+
+grub_setup-partmap_gpt.o: partmap/gpt.c $(partmap/gpt.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-partmap_gpt.d
+
+grub_setup-disk_raid.o: disk/raid.c $(disk/raid.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-disk_raid.d
+
+grub_setup-disk_mdraid_linux.o: disk/mdraid_linux.c $(disk/mdraid_linux.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-disk_mdraid_linux.d
+
+grub_setup-disk_lvm.o: disk/lvm.c $(disk/lvm.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-disk_lvm.d
+
+grub_setup-util_raid.o: util/raid.c $(util/raid.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-util_raid.d
+
+grub_setup-util_lvm.o: util/lvm.c $(util/lvm.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-util_lvm.d
+
+grub_setup-grub_setup_init.o: grub_setup_init.c $(grub_setup_init.c_DEPENDENCIES)
+       $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_setup_CFLAGS) -MD -c -o $@ $<
+-include grub_setup-grub_setup_init.d
+
+
+# For grub-mkdevicemap.
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+CLEANFILES += grub-mkdevicemap$(EXEEXT) grub_mkdevicemap-util_grub_mkdevicemap.o grub_mkdevicemap-util_misc.o
+MOSTLYCLEANFILES += grub_mkdevicemap-util_grub_mkdevicemap.d grub_mkdevicemap-util_misc.d
+
+grub-mkdevicemap: $(grub_mkdevicemap_DEPENDENCIES) grub_mkdevicemap-util_grub_mkdevicemap.o grub_mkdevicemap-util_misc.o
+       $(CC) -o $@ grub_mkdevicemap-util_grub_mkdevicemap.o grub_mkdevicemap-util_misc.o $(LDFLAGS) $(grub_mkdevicemap_LDFLAGS)
+
+grub_mkdevicemap-util_grub_mkdevicemap.o: util/grub-mkdevicemap.c $(util/grub-mkdevicemap.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkdevicemap_CFLAGS) -MD -c -o $@ $<
+-include grub_mkdevicemap-util_grub_mkdevicemap.d
+
+grub_mkdevicemap-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkdevicemap_CFLAGS) -MD -c -o $@ $<
+-include grub_mkdevicemap-util_misc.d
+
+
+# For grub-emu.
+util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
+grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c       \
+       commands/configfile.c commands/echo.c commands/help.c           \
+       commands/terminal.c commands/ls.c commands/test.c               \
+       commands/search.c commands/blocklist.c commands/hexdump.c       \
+       lib/hexdump.c commands/i386/pc/halt.c commands/reboot.c         \
+       commands/i386/cpuid.c                                           \
+       disk/host.c disk/loopback.c disk/scsi.c                         \
+       fs/fshelp.c     \
+       \
+       io/gzio.c                                                       \
+       kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c       \
+       kern/err.c                                                      \
+       normal/execute.c kern/file.c kern/fs.c normal/lexer.c           \
+       kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
+       grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
+       normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
+       normal/completion.c normal/main.c normal/color.c                \
+       normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
+       normal/menu_text.c                                              \
+       normal/misc.c normal/script.c                                   \
+       partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
+       partmap/acorn.c partmap/gpt.c                                   \
+       \
+       fs/affs.c fs/cpio.c  fs/fat.c fs/ext2.c fs/hfs.c                \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c          \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c                  \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                             \
+       \
+       util/console.c util/hostfs.c util/grub-emu.c util/misc.c        \
+       util/hostdisk.c util/getroot.c                                  \
+       util/i386/pc/misc.c                                             \
+       \
+       disk/raid.c disk/raid5_recover.c disk/raid6_recover.c           \
+       disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c             \
+       grub_emu_init.c
+CLEANFILES += grub-emu$(EXEEXT) grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_echo.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_reboot.o grub_emu-commands_i386_cpuid.o grub_emu-disk_host.o grub_emu-disk_loopback.o grub_emu-disk_scsi.o grub_emu-fs_fshelp.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_main.o grub_emu-normal_color.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_menu_text.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-partmap_gpt.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_fat.o grub_emu-fs_ext2.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_i386_pc_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_emu_init.o
+MOSTLYCLEANFILES += grub_emu-commands_boot.d grub_emu-commands_cat.d grub_emu-commands_cmp.d grub_emu-commands_configfile.d grub_emu-commands_echo.d grub_emu-commands_help.d grub_emu-commands_terminal.d grub_emu-commands_ls.d grub_emu-commands_test.d grub_emu-commands_search.d grub_emu-commands_blocklist.d grub_emu-commands_hexdump.d grub_emu-lib_hexdump.d grub_emu-commands_i386_pc_halt.d grub_emu-commands_reboot.d grub_emu-commands_i386_cpuid.d grub_emu-disk_host.d grub_emu-disk_loopback.d grub_emu-disk_scsi.d grub_emu-fs_fshelp.d grub_emu-io_gzio.d grub_emu-kern_device.d grub_emu-kern_disk.d grub_emu-kern_dl.d grub_emu-kern_elf.d grub_emu-kern_env.d grub_emu-kern_err.d grub_emu-normal_execute.d grub_emu-kern_file.d grub_emu-kern_fs.d grub_emu-normal_lexer.d grub_emu-kern_loader.d grub_emu-kern_main.d grub_emu-kern_misc.d grub_emu-kern_parser.d grub_emu-grub_script_tab.d grub_emu-kern_partition.d grub_emu-kern_rescue.d grub_emu-kern_term.d grub_emu-normal_arg.d grub_emu-normal_cmdline.d grub_emu-normal_command.d grub_emu-normal_function.d grub_emu-normal_completion.d grub_emu-normal_main.d grub_emu-normal_color.d grub_emu-normal_menu.d grub_emu-normal_menu_entry.d grub_emu-normal_menu_viewer.d grub_emu-normal_menu_text.d grub_emu-normal_misc.d grub_emu-normal_script.d grub_emu-partmap_amiga.d grub_emu-partmap_apple.d grub_emu-partmap_pc.d grub_emu-partmap_sun.d grub_emu-partmap_acorn.d grub_emu-partmap_gpt.d grub_emu-fs_affs.d grub_emu-fs_cpio.d grub_emu-fs_fat.d grub_emu-fs_ext2.d grub_emu-fs_hfs.d grub_emu-fs_hfsplus.d grub_emu-fs_iso9660.d grub_emu-fs_udf.d grub_emu-fs_jfs.d grub_emu-fs_minix.d grub_emu-fs_ntfs.d grub_emu-fs_ntfscomp.d grub_emu-fs_reiserfs.d grub_emu-fs_sfs.d grub_emu-fs_ufs.d grub_emu-fs_xfs.d grub_emu-fs_afs.d grub_emu-fs_tar.d grub_emu-util_console.d grub_emu-util_hostfs.d grub_emu-util_grub_emu.d grub_emu-util_misc.d grub_emu-util_hostdisk.d grub_emu-util_getroot.d grub_emu-util_i386_pc_misc.d grub_emu-disk_raid.d grub_emu-disk_raid5_recover.d grub_emu-disk_raid6_recover.d grub_emu-disk_mdraid_linux.d grub_emu-disk_dmraid_nvidia.d grub_emu-disk_lvm.d grub_emu-grub_emu_init.d
+
+grub-emu: $(grub_emu_DEPENDENCIES) grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_echo.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_reboot.o grub_emu-commands_i386_cpuid.o grub_emu-disk_host.o grub_emu-disk_loopback.o grub_emu-disk_scsi.o grub_emu-fs_fshelp.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_main.o grub_emu-normal_color.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_menu_text.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-partmap_gpt.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_fat.o grub_emu-fs_ext2.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_i386_pc_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_emu_init.o
+       $(CC) -o $@ grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_echo.o grub_emu-commands_help.o grub_emu-commands_terminal.o grub_emu-commands_ls.o grub_emu-commands_test.o grub_emu-commands_search.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_i386_pc_halt.o grub_emu-commands_reboot.o grub_emu-commands_i386_cpuid.o grub_emu-disk_host.o grub_emu-disk_loopback.o grub_emu-disk_scsi.o grub_emu-fs_fshelp.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-normal_execute.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-normal_lexer.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-grub_script_tab.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_function.o grub_emu-normal_completion.o grub_emu-normal_main.o grub_emu-normal_color.o grub_emu-normal_menu.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_menu_text.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-partmap_gpt.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_fat.o grub_emu-fs_ext2.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_i386_pc_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_emu_init.o $(LDFLAGS) $(grub_emu_LDFLAGS)
+
+grub_emu-commands_boot.o: commands/boot.c $(commands/boot.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_boot.d
+
+grub_emu-commands_cat.o: commands/cat.c $(commands/cat.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_cat.d
+
+grub_emu-commands_cmp.o: commands/cmp.c $(commands/cmp.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_cmp.d
+
+grub_emu-commands_configfile.o: commands/configfile.c $(commands/configfile.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_configfile.d
+
+grub_emu-commands_echo.o: commands/echo.c $(commands/echo.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_echo.d
+
+grub_emu-commands_help.o: commands/help.c $(commands/help.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_help.d
+
+grub_emu-commands_terminal.o: commands/terminal.c $(commands/terminal.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_terminal.d
+
+grub_emu-commands_ls.o: commands/ls.c $(commands/ls.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_ls.d
+
+grub_emu-commands_test.o: commands/test.c $(commands/test.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_test.d
+
+grub_emu-commands_search.o: commands/search.c $(commands/search.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_search.d
+
+grub_emu-commands_blocklist.o: commands/blocklist.c $(commands/blocklist.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_blocklist.d
+
+grub_emu-commands_hexdump.o: commands/hexdump.c $(commands/hexdump.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_hexdump.d
+
+grub_emu-lib_hexdump.o: lib/hexdump.c $(lib/hexdump.c_DEPENDENCIES)
+       $(CC) -Ilib -I$(srcdir)/lib $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-lib_hexdump.d
+
+grub_emu-commands_i386_pc_halt.o: commands/i386/pc/halt.c $(commands/i386/pc/halt.c_DEPENDENCIES)
+       $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_i386_pc_halt.d
+
+grub_emu-commands_reboot.o: commands/reboot.c $(commands/reboot.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_reboot.d
+
+grub_emu-commands_i386_cpuid.o: commands/i386/cpuid.c $(commands/i386/cpuid.c_DEPENDENCIES)
+       $(CC) -Icommands/i386 -I$(srcdir)/commands/i386 $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_i386_cpuid.d
+
+grub_emu-disk_host.o: disk/host.c $(disk/host.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_host.d
+
+grub_emu-disk_loopback.o: disk/loopback.c $(disk/loopback.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_loopback.d
+
+grub_emu-disk_scsi.o: disk/scsi.c $(disk/scsi.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_scsi.d
+
+grub_emu-fs_fshelp.o: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_fshelp.d
+
+grub_emu-io_gzio.o: io/gzio.c $(io/gzio.c_DEPENDENCIES)
+       $(CC) -Iio -I$(srcdir)/io $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-io_gzio.d
+
+grub_emu-kern_device.o: kern/device.c $(kern/device.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_device.d
+
+grub_emu-kern_disk.o: kern/disk.c $(kern/disk.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_disk.d
+
+grub_emu-kern_dl.o: kern/dl.c $(kern/dl.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_dl.d
+
+grub_emu-kern_elf.o: kern/elf.c $(kern/elf.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_elf.d
+
+grub_emu-kern_env.o: kern/env.c $(kern/env.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_env.d
+
+grub_emu-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_err.d
+
+grub_emu-normal_execute.o: normal/execute.c $(normal/execute.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_execute.d
+
+grub_emu-kern_file.o: kern/file.c $(kern/file.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_file.d
+
+grub_emu-kern_fs.o: kern/fs.c $(kern/fs.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_fs.d
+
+grub_emu-normal_lexer.o: normal/lexer.c $(normal/lexer.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_lexer.d
+
+grub_emu-kern_loader.o: kern/loader.c $(kern/loader.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_loader.d
+
+grub_emu-kern_main.o: kern/main.c $(kern/main.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_main.d
+
+grub_emu-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_misc.d
+
+grub_emu-kern_parser.o: kern/parser.c $(kern/parser.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_parser.d
+
+grub_emu-grub_script_tab.o: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES)
+       $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-grub_script_tab.d
+
+grub_emu-kern_partition.o: kern/partition.c $(kern/partition.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_partition.d
+
+grub_emu-kern_rescue.o: kern/rescue.c $(kern/rescue.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_rescue.d
+
+grub_emu-kern_term.o: kern/term.c $(kern/term.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_term.d
+
+grub_emu-normal_arg.o: normal/arg.c $(normal/arg.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_arg.d
+
+grub_emu-normal_cmdline.o: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_cmdline.d
+
+grub_emu-normal_command.o: normal/command.c $(normal/command.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_command.d
+
+grub_emu-normal_function.o: normal/function.c $(normal/function.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_function.d
+
+grub_emu-normal_completion.o: normal/completion.c $(normal/completion.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_completion.d
+
+grub_emu-normal_main.o: normal/main.c $(normal/main.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_main.d
+
+grub_emu-normal_color.o: normal/color.c $(normal/color.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_color.d
+
+grub_emu-normal_menu.o: normal/menu.c $(normal/menu.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu.d
+
+grub_emu-normal_menu_entry.o: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu_entry.d
+
+grub_emu-normal_menu_viewer.o: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu_viewer.d
+
+grub_emu-normal_menu_text.o: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu_text.d
+
+grub_emu-normal_misc.o: normal/misc.c $(normal/misc.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_misc.d
+
+grub_emu-normal_script.o: normal/script.c $(normal/script.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_script.d
+
+grub_emu-partmap_amiga.o: partmap/amiga.c $(partmap/amiga.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_amiga.d
+
+grub_emu-partmap_apple.o: partmap/apple.c $(partmap/apple.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_apple.d
+
+grub_emu-partmap_pc.o: partmap/pc.c $(partmap/pc.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_pc.d
+
+grub_emu-partmap_sun.o: partmap/sun.c $(partmap/sun.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_sun.d
+
+grub_emu-partmap_acorn.o: partmap/acorn.c $(partmap/acorn.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_acorn.d
+
+grub_emu-partmap_gpt.o: partmap/gpt.c $(partmap/gpt.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_gpt.d
+
+grub_emu-fs_affs.o: fs/affs.c $(fs/affs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_affs.d
+
+grub_emu-fs_cpio.o: fs/cpio.c $(fs/cpio.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_cpio.d
+
+grub_emu-fs_fat.o: fs/fat.c $(fs/fat.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_fat.d
+
+grub_emu-fs_ext2.o: fs/ext2.c $(fs/ext2.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ext2.d
+
+grub_emu-fs_hfs.o: fs/hfs.c $(fs/hfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_hfs.d
+
+grub_emu-fs_hfsplus.o: fs/hfsplus.c $(fs/hfsplus.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_hfsplus.d
+
+grub_emu-fs_iso9660.o: fs/iso9660.c $(fs/iso9660.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_iso9660.d
+
+grub_emu-fs_udf.o: fs/udf.c $(fs/udf.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_udf.d
+
+grub_emu-fs_jfs.o: fs/jfs.c $(fs/jfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_jfs.d
+
+grub_emu-fs_minix.o: fs/minix.c $(fs/minix.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_minix.d
+
+grub_emu-fs_ntfs.o: fs/ntfs.c $(fs/ntfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ntfs.d
+
+grub_emu-fs_ntfscomp.o: fs/ntfscomp.c $(fs/ntfscomp.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ntfscomp.d
+
+grub_emu-fs_reiserfs.o: fs/reiserfs.c $(fs/reiserfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_reiserfs.d
+
+grub_emu-fs_sfs.o: fs/sfs.c $(fs/sfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_sfs.d
+
+grub_emu-fs_ufs.o: fs/ufs.c $(fs/ufs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ufs.d
+
+grub_emu-fs_xfs.o: fs/xfs.c $(fs/xfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_xfs.d
+
+grub_emu-fs_afs.o: fs/afs.c $(fs/afs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_afs.d
+
+grub_emu-fs_tar.o: fs/tar.c $(fs/tar.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_tar.d
+
+grub_emu-util_console.o: util/console.c $(util/console.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_console.d
+
+grub_emu-util_hostfs.o: util/hostfs.c $(util/hostfs.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_hostfs.d
+
+grub_emu-util_grub_emu.o: util/grub-emu.c $(util/grub-emu.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_grub_emu.d
+
+grub_emu-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_misc.d
+
+grub_emu-util_hostdisk.o: util/hostdisk.c $(util/hostdisk.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_hostdisk.d
+
+grub_emu-util_getroot.o: util/getroot.c $(util/getroot.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_getroot.d
+
+grub_emu-util_i386_pc_misc.o: util/i386/pc/misc.c $(util/i386/pc/misc.c_DEPENDENCIES)
+       $(CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_i386_pc_misc.d
+
+grub_emu-disk_raid.o: disk/raid.c $(disk/raid.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_raid.d
+
+grub_emu-disk_raid5_recover.o: disk/raid5_recover.c $(disk/raid5_recover.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_raid5_recover.d
+
+grub_emu-disk_raid6_recover.o: disk/raid6_recover.c $(disk/raid6_recover.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_raid6_recover.d
+
+grub_emu-disk_mdraid_linux.o: disk/mdraid_linux.c $(disk/mdraid_linux.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_mdraid_linux.d
+
+grub_emu-disk_dmraid_nvidia.o: disk/dmraid_nvidia.c $(disk/dmraid_nvidia.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_dmraid_nvidia.d
+
+grub_emu-disk_lvm.o: disk/lvm.c $(disk/lvm.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_lvm.d
+
+grub_emu-grub_emu_init.o: grub_emu_init.c $(grub_emu_init.c_DEPENDENCIES)
+       $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-grub_emu_init.d
+
+
+grub_emu_LDFLAGS = $(LIBCURSES) 
+
+ifeq ($(enable_grub_emu_usb), yes)
+grub_emu_SOURCES += disk/usbms.c util/usb.c bus/usb/usb.c      \
+               commands/usbtest.c
+CLEANFILES += grub-emu$(EXEEXT) grub_emu-disk_usbms.o grub_emu-util_usb.o grub_emu-bus_usb_usb.o grub_emu-commands_usbtest.o
+MOSTLYCLEANFILES += grub_emu-disk_usbms.d grub_emu-util_usb.d grub_emu-bus_usb_usb.d grub_emu-commands_usbtest.d
+
+grub-emu: $(grub_emu_DEPENDENCIES) grub_emu-disk_usbms.o grub_emu-util_usb.o grub_emu-bus_usb_usb.o grub_emu-commands_usbtest.o
+       $(CC) -o $@ grub_emu-disk_usbms.o grub_emu-util_usb.o grub_emu-bus_usb_usb.o grub_emu-commands_usbtest.o $(LDFLAGS) $(grub_emu_LDFLAGS)
+
+grub_emu-disk_usbms.o: disk/usbms.c $(disk/usbms.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_usbms.d
+
+grub_emu-util_usb.o: util/usb.c $(util/usb.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_usb.d
+
+grub_emu-bus_usb_usb.o: bus/usb/usb.c $(bus/usb/usb.c_DEPENDENCIES)
+       $(CC) -Ibus/usb -I$(srcdir)/bus/usb $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-bus_usb_usb.d
+
+grub_emu-commands_usbtest.o: commands/usbtest.c $(commands/usbtest.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_usbtest.d
+
+grub_emu_LDFLAGS += $(LIBCURSES) $(LIBUSB)
+endif
+
+# Scripts.
+sbin_SCRIPTS = grub-install
+bin_SCRIPTS = grub-mkrescue
+
+# For grub-install.
+grub_install_SOURCES = util/i386/pc/grub-install.in
+CLEANFILES += grub-install
+
+grub-install: util/i386/pc/grub-install.in $(util/i386/pc/grub-install.in_DEPENDENCIES) config.status
+       ./config.status --file=grub-install:util/i386/pc/grub-install.in
+       chmod +x $@
+
+
+# For grub-mkrescue.
+grub_mkrescue_SOURCES = util/i386/pc/grub-mkrescue.in
+CLEANFILES += grub-mkrescue
+
+grub-mkrescue: util/i386/pc/grub-mkrescue.in $(util/i386/pc/grub-mkrescue.in_DEPENDENCIES) config.status
+       ./config.status --file=grub-mkrescue:util/i386/pc/grub-mkrescue.in
+       chmod +x $@
+
+
+# Modules.
+pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \
+       _multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod      \
+       vbe.mod vbetest.mod vbeinfo.mod play.mod serial.mod     \
+       ata.mod vga.mod memdisk.mod pci.mod lspci.mod \
+       aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod datetime.mod date.mod \
+       datehook.mod lsmmap.mod ata_pthru.mod hdparm.mod \
+       usb.mod uhci.mod ohci.mod usbtest.mod usbms.mod usb_keyboard.mod
+
+# For biosdisk.mod.
+biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
+CLEANFILES += biosdisk.mod mod-biosdisk.o mod-biosdisk.c pre-biosdisk.o biosdisk_mod-disk_i386_pc_biosdisk.o und-biosdisk.lst
+ifneq ($(biosdisk_mod_EXPORTS),no)
+CLEANFILES += def-biosdisk.lst
+DEFSYMFILES += def-biosdisk.lst
+endif
+MOSTLYCLEANFILES += biosdisk_mod-disk_i386_pc_biosdisk.d
+UNDSYMFILES += und-biosdisk.lst
+
+biosdisk.mod: pre-biosdisk.o mod-biosdisk.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(biosdisk_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-biosdisk.o mod-biosdisk.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-biosdisk.o: $(biosdisk_mod_DEPENDENCIES) biosdisk_mod-disk_i386_pc_biosdisk.o
+       -rm -f $@
+       $(TARGET_CC) $(biosdisk_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ biosdisk_mod-disk_i386_pc_biosdisk.o
+
+mod-biosdisk.o: mod-biosdisk.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(biosdisk_mod_CFLAGS) -c -o $@ $<
+
+mod-biosdisk.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'biosdisk' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(biosdisk_mod_EXPORTS),no)
+def-biosdisk.lst: pre-biosdisk.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 biosdisk/' > $@
+endif
+
+und-biosdisk.lst: pre-biosdisk.o
+       echo 'biosdisk' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+biosdisk_mod-disk_i386_pc_biosdisk.o: disk/i386/pc/biosdisk.c $(disk/i386/pc/biosdisk.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk/i386/pc -I$(srcdir)/disk/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(biosdisk_mod_CFLAGS) -MD -c -o $@ $<
+-include biosdisk_mod-disk_i386_pc_biosdisk.d
+
+CLEANFILES += cmd-biosdisk_mod-disk_i386_pc_biosdisk.lst fs-biosdisk_mod-disk_i386_pc_biosdisk.lst partmap-biosdisk_mod-disk_i386_pc_biosdisk.lst
+COMMANDFILES += cmd-biosdisk_mod-disk_i386_pc_biosdisk.lst
+FSFILES += fs-biosdisk_mod-disk_i386_pc_biosdisk.lst
+PARTMAPFILES += partmap-biosdisk_mod-disk_i386_pc_biosdisk.lst
+
+cmd-biosdisk_mod-disk_i386_pc_biosdisk.lst: disk/i386/pc/biosdisk.c $(disk/i386/pc/biosdisk.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk/i386/pc -I$(srcdir)/disk/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(biosdisk_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh biosdisk > $@ || (rm -f $@; exit 1)
+
+fs-biosdisk_mod-disk_i386_pc_biosdisk.lst: disk/i386/pc/biosdisk.c $(disk/i386/pc/biosdisk.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk/i386/pc -I$(srcdir)/disk/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(biosdisk_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh biosdisk > $@ || (rm -f $@; exit 1)
+
+partmap-biosdisk_mod-disk_i386_pc_biosdisk.lst: disk/i386/pc/biosdisk.c $(disk/i386/pc/biosdisk.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk/i386/pc -I$(srcdir)/disk/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(biosdisk_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh biosdisk > $@ || (rm -f $@; exit 1)
+
+
+biosdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+biosdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _chain.mod.
+_chain_mod_SOURCES = loader/i386/pc/chainloader.c
+CLEANFILES += _chain.mod mod-_chain.o mod-_chain.c pre-_chain.o _chain_mod-loader_i386_pc_chainloader.o und-_chain.lst
+ifneq ($(_chain_mod_EXPORTS),no)
+CLEANFILES += def-_chain.lst
+DEFSYMFILES += def-_chain.lst
+endif
+MOSTLYCLEANFILES += _chain_mod-loader_i386_pc_chainloader.d
+UNDSYMFILES += und-_chain.lst
+
+_chain.mod: pre-_chain.o mod-_chain.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(_chain_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-_chain.o mod-_chain.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-_chain.o: $(_chain_mod_DEPENDENCIES) _chain_mod-loader_i386_pc_chainloader.o
+       -rm -f $@
+       $(TARGET_CC) $(_chain_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ _chain_mod-loader_i386_pc_chainloader.o
+
+mod-_chain.o: mod-_chain.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_chain_mod_CFLAGS) -c -o $@ $<
+
+mod-_chain.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '_chain' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(_chain_mod_EXPORTS),no)
+def-_chain.lst: pre-_chain.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _chain/' > $@
+endif
+
+und-_chain.lst: pre-_chain.o
+       echo '_chain' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+_chain_mod-loader_i386_pc_chainloader.o: loader/i386/pc/chainloader.c $(loader/i386/pc/chainloader.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_chain_mod_CFLAGS) -MD -c -o $@ $<
+-include _chain_mod-loader_i386_pc_chainloader.d
+
+CLEANFILES += cmd-_chain_mod-loader_i386_pc_chainloader.lst fs-_chain_mod-loader_i386_pc_chainloader.lst partmap-_chain_mod-loader_i386_pc_chainloader.lst
+COMMANDFILES += cmd-_chain_mod-loader_i386_pc_chainloader.lst
+FSFILES += fs-_chain_mod-loader_i386_pc_chainloader.lst
+PARTMAPFILES += partmap-_chain_mod-loader_i386_pc_chainloader.lst
+
+cmd-_chain_mod-loader_i386_pc_chainloader.lst: loader/i386/pc/chainloader.c $(loader/i386/pc/chainloader.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_chain_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh _chain > $@ || (rm -f $@; exit 1)
+
+fs-_chain_mod-loader_i386_pc_chainloader.lst: loader/i386/pc/chainloader.c $(loader/i386/pc/chainloader.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_chain_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh _chain > $@ || (rm -f $@; exit 1)
+
+partmap-_chain_mod-loader_i386_pc_chainloader.lst: loader/i386/pc/chainloader.c $(loader/i386/pc/chainloader.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_chain_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh _chain > $@ || (rm -f $@; exit 1)
+
+
+_chain_mod_CFLAGS = $(COMMON_CFLAGS)
+_chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For chain.mod.
+chain_mod_SOURCES = loader/i386/pc/chainloader_normal.c
+CLEANFILES += chain.mod mod-chain.o mod-chain.c pre-chain.o chain_mod-loader_i386_pc_chainloader_normal.o und-chain.lst
+ifneq ($(chain_mod_EXPORTS),no)
+CLEANFILES += def-chain.lst
+DEFSYMFILES += def-chain.lst
+endif
+MOSTLYCLEANFILES += chain_mod-loader_i386_pc_chainloader_normal.d
+UNDSYMFILES += und-chain.lst
+
+chain.mod: pre-chain.o mod-chain.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(chain_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-chain.o mod-chain.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-chain.o: $(chain_mod_DEPENDENCIES) chain_mod-loader_i386_pc_chainloader_normal.o
+       -rm -f $@
+       $(TARGET_CC) $(chain_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ chain_mod-loader_i386_pc_chainloader_normal.o
+
+mod-chain.o: mod-chain.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(chain_mod_CFLAGS) -c -o $@ $<
+
+mod-chain.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'chain' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(chain_mod_EXPORTS),no)
+def-chain.lst: pre-chain.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 chain/' > $@
+endif
+
+und-chain.lst: pre-chain.o
+       echo 'chain' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+chain_mod-loader_i386_pc_chainloader_normal.o: loader/i386/pc/chainloader_normal.c $(loader/i386/pc/chainloader_normal.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(chain_mod_CFLAGS) -MD -c -o $@ $<
+-include chain_mod-loader_i386_pc_chainloader_normal.d
+
+CLEANFILES += cmd-chain_mod-loader_i386_pc_chainloader_normal.lst fs-chain_mod-loader_i386_pc_chainloader_normal.lst partmap-chain_mod-loader_i386_pc_chainloader_normal.lst
+COMMANDFILES += cmd-chain_mod-loader_i386_pc_chainloader_normal.lst
+FSFILES += fs-chain_mod-loader_i386_pc_chainloader_normal.lst
+PARTMAPFILES += partmap-chain_mod-loader_i386_pc_chainloader_normal.lst
+
+cmd-chain_mod-loader_i386_pc_chainloader_normal.lst: loader/i386/pc/chainloader_normal.c $(loader/i386/pc/chainloader_normal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(chain_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh chain > $@ || (rm -f $@; exit 1)
+
+fs-chain_mod-loader_i386_pc_chainloader_normal.lst: loader/i386/pc/chainloader_normal.c $(loader/i386/pc/chainloader_normal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(chain_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh chain > $@ || (rm -f $@; exit 1)
+
+partmap-chain_mod-loader_i386_pc_chainloader_normal.lst: loader/i386/pc/chainloader_normal.c $(loader/i386/pc/chainloader_normal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(chain_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh chain > $@ || (rm -f $@; exit 1)
+
+
+chain_mod_CFLAGS = $(COMMON_CFLAGS)
+chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _linux.mod.
+_linux_mod_SOURCES = loader/i386/pc/linux.c
+CLEANFILES += _linux.mod mod-_linux.o mod-_linux.c pre-_linux.o _linux_mod-loader_i386_pc_linux.o und-_linux.lst
+ifneq ($(_linux_mod_EXPORTS),no)
+CLEANFILES += def-_linux.lst
+DEFSYMFILES += def-_linux.lst
+endif
+MOSTLYCLEANFILES += _linux_mod-loader_i386_pc_linux.d
+UNDSYMFILES += und-_linux.lst
+
+_linux.mod: pre-_linux.o mod-_linux.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(_linux_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-_linux.o mod-_linux.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-_linux.o: $(_linux_mod_DEPENDENCIES) _linux_mod-loader_i386_pc_linux.o
+       -rm -f $@
+       $(TARGET_CC) $(_linux_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ _linux_mod-loader_i386_pc_linux.o
+
+mod-_linux.o: mod-_linux.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -c -o $@ $<
+
+mod-_linux.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '_linux' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(_linux_mod_EXPORTS),no)
+def-_linux.lst: pre-_linux.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _linux/' > $@
+endif
+
+und-_linux.lst: pre-_linux.o
+       echo '_linux' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+_linux_mod-loader_i386_pc_linux.o: loader/i386/pc/linux.c $(loader/i386/pc/linux.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -MD -c -o $@ $<
+-include _linux_mod-loader_i386_pc_linux.d
+
+CLEANFILES += cmd-_linux_mod-loader_i386_pc_linux.lst fs-_linux_mod-loader_i386_pc_linux.lst partmap-_linux_mod-loader_i386_pc_linux.lst
+COMMANDFILES += cmd-_linux_mod-loader_i386_pc_linux.lst
+FSFILES += fs-_linux_mod-loader_i386_pc_linux.lst
+PARTMAPFILES += partmap-_linux_mod-loader_i386_pc_linux.lst
+
+cmd-_linux_mod-loader_i386_pc_linux.lst: loader/i386/pc/linux.c $(loader/i386/pc/linux.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh _linux > $@ || (rm -f $@; exit 1)
+
+fs-_linux_mod-loader_i386_pc_linux.lst: loader/i386/pc/linux.c $(loader/i386/pc/linux.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh _linux > $@ || (rm -f $@; exit 1)
+
+partmap-_linux_mod-loader_i386_pc_linux.lst: loader/i386/pc/linux.c $(loader/i386/pc/linux.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh _linux > $@ || (rm -f $@; exit 1)
+
+
+_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/linux_normal.c
+CLEANFILES += linux.mod mod-linux.o mod-linux.c pre-linux.o linux_mod-loader_linux_normal.o und-linux.lst
+ifneq ($(linux_mod_EXPORTS),no)
+CLEANFILES += def-linux.lst
+DEFSYMFILES += def-linux.lst
+endif
+MOSTLYCLEANFILES += linux_mod-loader_linux_normal.d
+UNDSYMFILES += und-linux.lst
+
+linux.mod: pre-linux.o mod-linux.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(linux_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-linux.o mod-linux.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-linux.o: $(linux_mod_DEPENDENCIES) linux_mod-loader_linux_normal.o
+       -rm -f $@
+       $(TARGET_CC) $(linux_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ linux_mod-loader_linux_normal.o
+
+mod-linux.o: mod-linux.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -c -o $@ $<
+
+mod-linux.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'linux' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(linux_mod_EXPORTS),no)
+def-linux.lst: pre-linux.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 linux/' > $@
+endif
+
+und-linux.lst: pre-linux.o
+       echo 'linux' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+linux_mod-loader_linux_normal.o: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -MD -c -o $@ $<
+-include linux_mod-loader_linux_normal.d
+
+CLEANFILES += cmd-linux_mod-loader_linux_normal.lst fs-linux_mod-loader_linux_normal.lst partmap-linux_mod-loader_linux_normal.lst
+COMMANDFILES += cmd-linux_mod-loader_linux_normal.lst
+FSFILES += fs-linux_mod-loader_linux_normal.lst
+PARTMAPFILES += partmap-linux_mod-loader_linux_normal.lst
+
+cmd-linux_mod-loader_linux_normal.lst: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh linux > $@ || (rm -f $@; exit 1)
+
+fs-linux_mod-loader_linux_normal.lst: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh linux > $@ || (rm -f $@; exit 1)
+
+partmap-linux_mod-loader_linux_normal.lst: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh linux > $@ || (rm -f $@; exit 1)
+
+
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+#
+# Only arch dependant part of normal.mod will be here. Common part for
+# all architecures of normal.mod is at start and should be kept at sync
+# with other makefiles.
+# 
+# Please put arch dependant part of normal.mod at the end of list to
+# keep it simpler to update to different architectures.
+#
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/color.c                                                  \
+       normal/menu_viewer.c normal/menu_entry.c                        \
+       normal/misc.c grub_script.tab.c                                 \
+       normal/script.c                                                 \
+       normal/i386/setjmp.S
+CLEANFILES += normal.mod mod-normal.o mod-normal.c pre-normal.o normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_i386_setjmp.o und-normal.lst
+ifneq ($(normal_mod_EXPORTS),no)
+CLEANFILES += def-normal.lst
+DEFSYMFILES += def-normal.lst
+endif
+MOSTLYCLEANFILES += normal_mod-normal_arg.d normal_mod-normal_cmdline.d normal_mod-normal_command.d normal_mod-normal_completion.d normal_mod-normal_execute.d normal_mod-normal_function.d normal_mod-normal_lexer.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_menu_text.d normal_mod-normal_color.d normal_mod-normal_menu_viewer.d normal_mod-normal_menu_entry.d normal_mod-normal_misc.d normal_mod-grub_script_tab.d normal_mod-normal_script.d normal_mod-normal_i386_setjmp.d
+UNDSYMFILES += und-normal.lst
+
+normal.mod: pre-normal.o mod-normal.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(normal_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-normal.o mod-normal.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-normal.o: $(normal_mod_DEPENDENCIES) normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_i386_setjmp.o
+       -rm -f $@
+       $(TARGET_CC) $(normal_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_i386_setjmp.o
+
+mod-normal.o: mod-normal.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
+
+mod-normal.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'normal' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(normal_mod_EXPORTS),no)
+def-normal.lst: pre-normal.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 normal/' > $@
+endif
+
+und-normal.lst: pre-normal.o
+       echo 'normal' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+normal_mod-normal_arg.o: normal/arg.c $(normal/arg.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_arg.d
+
+CLEANFILES += cmd-normal_mod-normal_arg.lst fs-normal_mod-normal_arg.lst partmap-normal_mod-normal_arg.lst
+COMMANDFILES += cmd-normal_mod-normal_arg.lst
+FSFILES += fs-normal_mod-normal_arg.lst
+PARTMAPFILES += partmap-normal_mod-normal_arg.lst
+
+cmd-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_cmdline.o: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_cmdline.d
+
+CLEANFILES += cmd-normal_mod-normal_cmdline.lst fs-normal_mod-normal_cmdline.lst partmap-normal_mod-normal_cmdline.lst
+COMMANDFILES += cmd-normal_mod-normal_cmdline.lst
+FSFILES += fs-normal_mod-normal_cmdline.lst
+PARTMAPFILES += partmap-normal_mod-normal_cmdline.lst
+
+cmd-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_command.o: normal/command.c $(normal/command.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_command.d
+
+CLEANFILES += cmd-normal_mod-normal_command.lst fs-normal_mod-normal_command.lst partmap-normal_mod-normal_command.lst
+COMMANDFILES += cmd-normal_mod-normal_command.lst
+FSFILES += fs-normal_mod-normal_command.lst
+PARTMAPFILES += partmap-normal_mod-normal_command.lst
+
+cmd-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_completion.o: normal/completion.c $(normal/completion.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_completion.d
+
+CLEANFILES += cmd-normal_mod-normal_completion.lst fs-normal_mod-normal_completion.lst partmap-normal_mod-normal_completion.lst
+COMMANDFILES += cmd-normal_mod-normal_completion.lst
+FSFILES += fs-normal_mod-normal_completion.lst
+PARTMAPFILES += partmap-normal_mod-normal_completion.lst
+
+cmd-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_execute.o: normal/execute.c $(normal/execute.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_execute.d
+
+CLEANFILES += cmd-normal_mod-normal_execute.lst fs-normal_mod-normal_execute.lst partmap-normal_mod-normal_execute.lst
+COMMANDFILES += cmd-normal_mod-normal_execute.lst
+FSFILES += fs-normal_mod-normal_execute.lst
+PARTMAPFILES += partmap-normal_mod-normal_execute.lst
+
+cmd-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_function.o: normal/function.c $(normal/function.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_function.d
+
+CLEANFILES += cmd-normal_mod-normal_function.lst fs-normal_mod-normal_function.lst partmap-normal_mod-normal_function.lst
+COMMANDFILES += cmd-normal_mod-normal_function.lst
+FSFILES += fs-normal_mod-normal_function.lst
+PARTMAPFILES += partmap-normal_mod-normal_function.lst
+
+cmd-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_lexer.o: normal/lexer.c $(normal/lexer.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_lexer.d
+
+CLEANFILES += cmd-normal_mod-normal_lexer.lst fs-normal_mod-normal_lexer.lst partmap-normal_mod-normal_lexer.lst
+COMMANDFILES += cmd-normal_mod-normal_lexer.lst
+FSFILES += fs-normal_mod-normal_lexer.lst
+PARTMAPFILES += partmap-normal_mod-normal_lexer.lst
+
+cmd-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_main.o: normal/main.c $(normal/main.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_main.d
+
+CLEANFILES += cmd-normal_mod-normal_main.lst fs-normal_mod-normal_main.lst partmap-normal_mod-normal_main.lst
+COMMANDFILES += cmd-normal_mod-normal_main.lst
+FSFILES += fs-normal_mod-normal_main.lst
+PARTMAPFILES += partmap-normal_mod-normal_main.lst
+
+cmd-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu.o: normal/menu.c $(normal/menu.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu.d
+
+CLEANFILES += cmd-normal_mod-normal_menu.lst fs-normal_mod-normal_menu.lst partmap-normal_mod-normal_menu.lst
+COMMANDFILES += cmd-normal_mod-normal_menu.lst
+FSFILES += fs-normal_mod-normal_menu.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu.lst
+
+cmd-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_text.o: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_text.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_text.lst fs-normal_mod-normal_menu_text.lst partmap-normal_mod-normal_menu_text.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_text.lst
+FSFILES += fs-normal_mod-normal_menu_text.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_text.lst
+
+cmd-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_color.o: normal/color.c $(normal/color.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_color.d
+
+CLEANFILES += cmd-normal_mod-normal_color.lst fs-normal_mod-normal_color.lst partmap-normal_mod-normal_color.lst
+COMMANDFILES += cmd-normal_mod-normal_color.lst
+FSFILES += fs-normal_mod-normal_color.lst
+PARTMAPFILES += partmap-normal_mod-normal_color.lst
+
+cmd-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_viewer.o: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_viewer.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_viewer.lst fs-normal_mod-normal_menu_viewer.lst partmap-normal_mod-normal_menu_viewer.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_viewer.lst
+FSFILES += fs-normal_mod-normal_menu_viewer.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_viewer.lst
+
+cmd-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_entry.o: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_entry.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_entry.lst fs-normal_mod-normal_menu_entry.lst partmap-normal_mod-normal_menu_entry.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_entry.lst
+FSFILES += fs-normal_mod-normal_menu_entry.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_entry.lst
+
+cmd-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_misc.o: normal/misc.c $(normal/misc.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_misc.d
+
+CLEANFILES += cmd-normal_mod-normal_misc.lst fs-normal_mod-normal_misc.lst partmap-normal_mod-normal_misc.lst
+COMMANDFILES += cmd-normal_mod-normal_misc.lst
+FSFILES += fs-normal_mod-normal_misc.lst
+PARTMAPFILES += partmap-normal_mod-normal_misc.lst
+
+cmd-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-grub_script_tab.o: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES)
+       $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-grub_script_tab.d
+
+CLEANFILES += cmd-normal_mod-grub_script_tab.lst fs-normal_mod-grub_script_tab.lst partmap-normal_mod-grub_script_tab.lst
+COMMANDFILES += cmd-normal_mod-grub_script_tab.lst
+FSFILES += fs-normal_mod-grub_script_tab.lst
+PARTMAPFILES += partmap-normal_mod-grub_script_tab.lst
+
+cmd-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_script.o: normal/script.c $(normal/script.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_script.d
+
+CLEANFILES += cmd-normal_mod-normal_script.lst fs-normal_mod-normal_script.lst partmap-normal_mod-normal_script.lst
+COMMANDFILES += cmd-normal_mod-normal_script.lst
+FSFILES += fs-normal_mod-normal_script.lst
+PARTMAPFILES += partmap-normal_mod-normal_script.lst
+
+cmd-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_i386_setjmp.o: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES)
+       $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_i386_setjmp.d
+
+CLEANFILES += cmd-normal_mod-normal_i386_setjmp.lst fs-normal_mod-normal_i386_setjmp.lst partmap-normal_mod-normal_i386_setjmp.lst
+COMMANDFILES += cmd-normal_mod-normal_i386_setjmp.lst
+FSFILES += fs-normal_mod-normal_i386_setjmp.lst
+PARTMAPFILES += partmap-normal_mod-normal_i386_setjmp.lst
+
+cmd-normal_mod-normal_i386_setjmp.lst: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_i386_setjmp.lst: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<     | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_i386_setjmp.lst: normal/i386/setjmp.S $(normal/i386/setjmp.S_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal/i386 -I$(srcdir)/normal/i386 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reboot.mod.
+reboot_mod_SOURCES = commands/reboot.c
+CLEANFILES += reboot.mod mod-reboot.o mod-reboot.c pre-reboot.o reboot_mod-commands_reboot.o und-reboot.lst
+ifneq ($(reboot_mod_EXPORTS),no)
+CLEANFILES += def-reboot.lst
+DEFSYMFILES += def-reboot.lst
+endif
+MOSTLYCLEANFILES += reboot_mod-commands_reboot.d
+UNDSYMFILES += und-reboot.lst
+
+reboot.mod: pre-reboot.o mod-reboot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(reboot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-reboot.o mod-reboot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-reboot.o: $(reboot_mod_DEPENDENCIES) reboot_mod-commands_reboot.o
+       -rm -f $@
+       $(TARGET_CC) $(reboot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ reboot_mod-commands_reboot.o
+
+mod-reboot.o: mod-reboot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -c -o $@ $<
+
+mod-reboot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'reboot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(reboot_mod_EXPORTS),no)
+def-reboot.lst: pre-reboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 reboot/' > $@
+endif
+
+und-reboot.lst: pre-reboot.o
+       echo 'reboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+reboot_mod-commands_reboot.o: commands/reboot.c $(commands/reboot.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -MD -c -o $@ $<
+-include reboot_mod-commands_reboot.d
+
+CLEANFILES += cmd-reboot_mod-commands_reboot.lst fs-reboot_mod-commands_reboot.lst partmap-reboot_mod-commands_reboot.lst
+COMMANDFILES += cmd-reboot_mod-commands_reboot.lst
+FSFILES += fs-reboot_mod-commands_reboot.lst
+PARTMAPFILES += partmap-reboot_mod-commands_reboot.lst
+
+cmd-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh reboot > $@ || (rm -f $@; exit 1)
+
+fs-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh reboot > $@ || (rm -f $@; exit 1)
+
+partmap-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh reboot > $@ || (rm -f $@; exit 1)
+
+
+reboot_mod_CFLAGS = $(COMMON_CFLAGS)
+reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For halt.mod.
+halt_mod_SOURCES = commands/i386/pc/halt.c
+CLEANFILES += halt.mod mod-halt.o mod-halt.c pre-halt.o halt_mod-commands_i386_pc_halt.o und-halt.lst
+ifneq ($(halt_mod_EXPORTS),no)
+CLEANFILES += def-halt.lst
+DEFSYMFILES += def-halt.lst
+endif
+MOSTLYCLEANFILES += halt_mod-commands_i386_pc_halt.d
+UNDSYMFILES += und-halt.lst
+
+halt.mod: pre-halt.o mod-halt.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(halt_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-halt.o mod-halt.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-halt.o: $(halt_mod_DEPENDENCIES) halt_mod-commands_i386_pc_halt.o
+       -rm -f $@
+       $(TARGET_CC) $(halt_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ halt_mod-commands_i386_pc_halt.o
+
+mod-halt.o: mod-halt.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -c -o $@ $<
+
+mod-halt.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'halt' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(halt_mod_EXPORTS),no)
+def-halt.lst: pre-halt.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 halt/' > $@
+endif
+
+und-halt.lst: pre-halt.o
+       echo 'halt' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+halt_mod-commands_i386_pc_halt.o: commands/i386/pc/halt.c $(commands/i386/pc/halt.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -MD -c -o $@ $<
+-include halt_mod-commands_i386_pc_halt.d
+
+CLEANFILES += cmd-halt_mod-commands_i386_pc_halt.lst fs-halt_mod-commands_i386_pc_halt.lst partmap-halt_mod-commands_i386_pc_halt.lst
+COMMANDFILES += cmd-halt_mod-commands_i386_pc_halt.lst
+FSFILES += fs-halt_mod-commands_i386_pc_halt.lst
+PARTMAPFILES += partmap-halt_mod-commands_i386_pc_halt.lst
+
+cmd-halt_mod-commands_i386_pc_halt.lst: commands/i386/pc/halt.c $(commands/i386/pc/halt.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh halt > $@ || (rm -f $@; exit 1)
+
+fs-halt_mod-commands_i386_pc_halt.lst: commands/i386/pc/halt.c $(commands/i386/pc/halt.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh halt > $@ || (rm -f $@; exit 1)
+
+partmap-halt_mod-commands_i386_pc_halt.lst: commands/i386/pc/halt.c $(commands/i386/pc/halt.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh halt > $@ || (rm -f $@; exit 1)
+
+
+halt_mod_CFLAGS = $(COMMON_CFLAGS)
+halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For serial.mod.
+serial_mod_SOURCES = term/i386/pc/serial.c
+CLEANFILES += serial.mod mod-serial.o mod-serial.c pre-serial.o serial_mod-term_i386_pc_serial.o und-serial.lst
+ifneq ($(serial_mod_EXPORTS),no)
+CLEANFILES += def-serial.lst
+DEFSYMFILES += def-serial.lst
+endif
+MOSTLYCLEANFILES += serial_mod-term_i386_pc_serial.d
+UNDSYMFILES += und-serial.lst
+
+serial.mod: pre-serial.o mod-serial.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(serial_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-serial.o mod-serial.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-serial.o: $(serial_mod_DEPENDENCIES) serial_mod-term_i386_pc_serial.o
+       -rm -f $@
+       $(TARGET_CC) $(serial_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ serial_mod-term_i386_pc_serial.o
+
+mod-serial.o: mod-serial.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(serial_mod_CFLAGS) -c -o $@ $<
+
+mod-serial.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'serial' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(serial_mod_EXPORTS),no)
+def-serial.lst: pre-serial.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 serial/' > $@
+endif
+
+und-serial.lst: pre-serial.o
+       echo 'serial' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+serial_mod-term_i386_pc_serial.o: term/i386/pc/serial.c $(term/i386/pc/serial.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(serial_mod_CFLAGS) -MD -c -o $@ $<
+-include serial_mod-term_i386_pc_serial.d
+
+CLEANFILES += cmd-serial_mod-term_i386_pc_serial.lst fs-serial_mod-term_i386_pc_serial.lst partmap-serial_mod-term_i386_pc_serial.lst
+COMMANDFILES += cmd-serial_mod-term_i386_pc_serial.lst
+FSFILES += fs-serial_mod-term_i386_pc_serial.lst
+PARTMAPFILES += partmap-serial_mod-term_i386_pc_serial.lst
+
+cmd-serial_mod-term_i386_pc_serial.lst: term/i386/pc/serial.c $(term/i386/pc/serial.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(serial_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh serial > $@ || (rm -f $@; exit 1)
+
+fs-serial_mod-term_i386_pc_serial.lst: term/i386/pc/serial.c $(term/i386/pc/serial.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(serial_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh serial > $@ || (rm -f $@; exit 1)
+
+partmap-serial_mod-term_i386_pc_serial.lst: term/i386/pc/serial.c $(term/i386/pc/serial.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(serial_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh serial > $@ || (rm -f $@; exit 1)
+
+
+serial_mod_CFLAGS = $(COMMON_CFLAGS)
+serial_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _multiboot.mod.
+_multiboot_mod_SOURCES = loader/i386/pc/multiboot.c \
+                         loader/i386/pc/multiboot2.c \
+                         loader/multiboot2.c \
+                         loader/multiboot_loader.c
+CLEANFILES += _multiboot.mod mod-_multiboot.o mod-_multiboot.c pre-_multiboot.o _multiboot_mod-loader_i386_pc_multiboot.o _multiboot_mod-loader_i386_pc_multiboot2.o _multiboot_mod-loader_multiboot2.o _multiboot_mod-loader_multiboot_loader.o und-_multiboot.lst
+ifneq ($(_multiboot_mod_EXPORTS),no)
+CLEANFILES += def-_multiboot.lst
+DEFSYMFILES += def-_multiboot.lst
+endif
+MOSTLYCLEANFILES += _multiboot_mod-loader_i386_pc_multiboot.d _multiboot_mod-loader_i386_pc_multiboot2.d _multiboot_mod-loader_multiboot2.d _multiboot_mod-loader_multiboot_loader.d
+UNDSYMFILES += und-_multiboot.lst
+
+_multiboot.mod: pre-_multiboot.o mod-_multiboot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(_multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-_multiboot.o mod-_multiboot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-_multiboot.o: $(_multiboot_mod_DEPENDENCIES) _multiboot_mod-loader_i386_pc_multiboot.o _multiboot_mod-loader_i386_pc_multiboot2.o _multiboot_mod-loader_multiboot2.o _multiboot_mod-loader_multiboot_loader.o
+       -rm -f $@
+       $(TARGET_CC) $(_multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ _multiboot_mod-loader_i386_pc_multiboot.o _multiboot_mod-loader_i386_pc_multiboot2.o _multiboot_mod-loader_multiboot2.o _multiboot_mod-loader_multiboot_loader.o
+
+mod-_multiboot.o: mod-_multiboot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -c -o $@ $<
+
+mod-_multiboot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '_multiboot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(_multiboot_mod_EXPORTS),no)
+def-_multiboot.lst: pre-_multiboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _multiboot/' > $@
+endif
+
+und-_multiboot.lst: pre-_multiboot.o
+       echo '_multiboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+_multiboot_mod-loader_i386_pc_multiboot.o: loader/i386/pc/multiboot.c $(loader/i386/pc/multiboot.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include _multiboot_mod-loader_i386_pc_multiboot.d
+
+CLEANFILES += cmd-_multiboot_mod-loader_i386_pc_multiboot.lst fs-_multiboot_mod-loader_i386_pc_multiboot.lst partmap-_multiboot_mod-loader_i386_pc_multiboot.lst
+COMMANDFILES += cmd-_multiboot_mod-loader_i386_pc_multiboot.lst
+FSFILES += fs-_multiboot_mod-loader_i386_pc_multiboot.lst
+PARTMAPFILES += partmap-_multiboot_mod-loader_i386_pc_multiboot.lst
+
+cmd-_multiboot_mod-loader_i386_pc_multiboot.lst: loader/i386/pc/multiboot.c $(loader/i386/pc/multiboot.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+fs-_multiboot_mod-loader_i386_pc_multiboot.lst: loader/i386/pc/multiboot.c $(loader/i386/pc/multiboot.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-_multiboot_mod-loader_i386_pc_multiboot.lst: loader/i386/pc/multiboot.c $(loader/i386/pc/multiboot.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+
+_multiboot_mod-loader_i386_pc_multiboot2.o: loader/i386/pc/multiboot2.c $(loader/i386/pc/multiboot2.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include _multiboot_mod-loader_i386_pc_multiboot2.d
+
+CLEANFILES += cmd-_multiboot_mod-loader_i386_pc_multiboot2.lst fs-_multiboot_mod-loader_i386_pc_multiboot2.lst partmap-_multiboot_mod-loader_i386_pc_multiboot2.lst
+COMMANDFILES += cmd-_multiboot_mod-loader_i386_pc_multiboot2.lst
+FSFILES += fs-_multiboot_mod-loader_i386_pc_multiboot2.lst
+PARTMAPFILES += partmap-_multiboot_mod-loader_i386_pc_multiboot2.lst
+
+cmd-_multiboot_mod-loader_i386_pc_multiboot2.lst: loader/i386/pc/multiboot2.c $(loader/i386/pc/multiboot2.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+fs-_multiboot_mod-loader_i386_pc_multiboot2.lst: loader/i386/pc/multiboot2.c $(loader/i386/pc/multiboot2.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-_multiboot_mod-loader_i386_pc_multiboot2.lst: loader/i386/pc/multiboot2.c $(loader/i386/pc/multiboot2.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+
+_multiboot_mod-loader_multiboot2.o: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include _multiboot_mod-loader_multiboot2.d
+
+CLEANFILES += cmd-_multiboot_mod-loader_multiboot2.lst fs-_multiboot_mod-loader_multiboot2.lst partmap-_multiboot_mod-loader_multiboot2.lst
+COMMANDFILES += cmd-_multiboot_mod-loader_multiboot2.lst
+FSFILES += fs-_multiboot_mod-loader_multiboot2.lst
+PARTMAPFILES += partmap-_multiboot_mod-loader_multiboot2.lst
+
+cmd-_multiboot_mod-loader_multiboot2.lst: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+fs-_multiboot_mod-loader_multiboot2.lst: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-_multiboot_mod-loader_multiboot2.lst: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+
+_multiboot_mod-loader_multiboot_loader.o: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include _multiboot_mod-loader_multiboot_loader.d
+
+CLEANFILES += cmd-_multiboot_mod-loader_multiboot_loader.lst fs-_multiboot_mod-loader_multiboot_loader.lst partmap-_multiboot_mod-loader_multiboot_loader.lst
+COMMANDFILES += cmd-_multiboot_mod-loader_multiboot_loader.lst
+FSFILES += fs-_multiboot_mod-loader_multiboot_loader.lst
+PARTMAPFILES += partmap-_multiboot_mod-loader_multiboot_loader.lst
+
+cmd-_multiboot_mod-loader_multiboot_loader.lst: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+fs-_multiboot_mod-loader_multiboot_loader.lst: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-_multiboot_mod-loader_multiboot_loader.lst: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+
+_multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+_multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For multiboot.mod.
+multiboot_mod_SOURCES = loader/multiboot_loader_normal.c 
+CLEANFILES += multiboot.mod mod-multiboot.o mod-multiboot.c pre-multiboot.o multiboot_mod-loader_multiboot_loader_normal.o und-multiboot.lst
+ifneq ($(multiboot_mod_EXPORTS),no)
+CLEANFILES += def-multiboot.lst
+DEFSYMFILES += def-multiboot.lst
+endif
+MOSTLYCLEANFILES += multiboot_mod-loader_multiboot_loader_normal.d
+UNDSYMFILES += und-multiboot.lst
+
+multiboot.mod: pre-multiboot.o mod-multiboot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-multiboot.o mod-multiboot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-multiboot.o: $(multiboot_mod_DEPENDENCIES) multiboot_mod-loader_multiboot_loader_normal.o
+       -rm -f $@
+       $(TARGET_CC) $(multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ multiboot_mod-loader_multiboot_loader_normal.o
+
+mod-multiboot.o: mod-multiboot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -c -o $@ $<
+
+mod-multiboot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'multiboot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(multiboot_mod_EXPORTS),no)
+def-multiboot.lst: pre-multiboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 multiboot/' > $@
+endif
+
+und-multiboot.lst: pre-multiboot.o
+       echo 'multiboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+multiboot_mod-loader_multiboot_loader_normal.o: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include multiboot_mod-loader_multiboot_loader_normal.d
+
+CLEANFILES += cmd-multiboot_mod-loader_multiboot_loader_normal.lst fs-multiboot_mod-loader_multiboot_loader_normal.lst partmap-multiboot_mod-loader_multiboot_loader_normal.lst
+COMMANDFILES += cmd-multiboot_mod-loader_multiboot_loader_normal.lst
+FSFILES += fs-multiboot_mod-loader_multiboot_loader_normal.lst
+PARTMAPFILES += partmap-multiboot_mod-loader_multiboot_loader_normal.lst
+
+cmd-multiboot_mod-loader_multiboot_loader_normal.lst: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh multiboot > $@ || (rm -f $@; exit 1)
+
+fs-multiboot_mod-loader_multiboot_loader_normal.lst: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-multiboot_mod-loader_multiboot_loader_normal.lst: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh multiboot > $@ || (rm -f $@; exit 1)
+
+
+multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For vbe.mod.
+vbe_mod_SOURCES = video/i386/pc/vbe.c video/i386/pc/vbeblit.c \
+                 video/i386/pc/vbefill.c video/i386/pc/vbeutil.c
+CLEANFILES += vbe.mod mod-vbe.o mod-vbe.c pre-vbe.o vbe_mod-video_i386_pc_vbe.o vbe_mod-video_i386_pc_vbeblit.o vbe_mod-video_i386_pc_vbefill.o vbe_mod-video_i386_pc_vbeutil.o und-vbe.lst
+ifneq ($(vbe_mod_EXPORTS),no)
+CLEANFILES += def-vbe.lst
+DEFSYMFILES += def-vbe.lst
+endif
+MOSTLYCLEANFILES += vbe_mod-video_i386_pc_vbe.d vbe_mod-video_i386_pc_vbeblit.d vbe_mod-video_i386_pc_vbefill.d vbe_mod-video_i386_pc_vbeutil.d
+UNDSYMFILES += und-vbe.lst
+
+vbe.mod: pre-vbe.o mod-vbe.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(vbe_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-vbe.o mod-vbe.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-vbe.o: $(vbe_mod_DEPENDENCIES) vbe_mod-video_i386_pc_vbe.o vbe_mod-video_i386_pc_vbeblit.o vbe_mod-video_i386_pc_vbefill.o vbe_mod-video_i386_pc_vbeutil.o
+       -rm -f $@
+       $(TARGET_CC) $(vbe_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ vbe_mod-video_i386_pc_vbe.o vbe_mod-video_i386_pc_vbeblit.o vbe_mod-video_i386_pc_vbefill.o vbe_mod-video_i386_pc_vbeutil.o
+
+mod-vbe.o: mod-vbe.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -c -o $@ $<
+
+mod-vbe.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'vbe' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(vbe_mod_EXPORTS),no)
+def-vbe.lst: pre-vbe.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 vbe/' > $@
+endif
+
+und-vbe.lst: pre-vbe.o
+       echo 'vbe' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+vbe_mod-video_i386_pc_vbe.o: video/i386/pc/vbe.c $(video/i386/pc/vbe.c_DEPENDENCIES)
+       $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -MD -c -o $@ $<
+-include vbe_mod-video_i386_pc_vbe.d
+
+CLEANFILES += cmd-vbe_mod-video_i386_pc_vbe.lst fs-vbe_mod-video_i386_pc_vbe.lst partmap-vbe_mod-video_i386_pc_vbe.lst
+COMMANDFILES += cmd-vbe_mod-video_i386_pc_vbe.lst
+FSFILES += fs-vbe_mod-video_i386_pc_vbe.lst
+PARTMAPFILES += partmap-vbe_mod-video_i386_pc_vbe.lst
+
+cmd-vbe_mod-video_i386_pc_vbe.lst: video/i386/pc/vbe.c $(video/i386/pc/vbe.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh vbe > $@ || (rm -f $@; exit 1)
+
+fs-vbe_mod-video_i386_pc_vbe.lst: video/i386/pc/vbe.c $(video/i386/pc/vbe.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh vbe > $@ || (rm -f $@; exit 1)
+
+partmap-vbe_mod-video_i386_pc_vbe.lst: video/i386/pc/vbe.c $(video/i386/pc/vbe.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh vbe > $@ || (rm -f $@; exit 1)
+
+
+vbe_mod-video_i386_pc_vbeblit.o: video/i386/pc/vbeblit.c $(video/i386/pc/vbeblit.c_DEPENDENCIES)
+       $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -MD -c -o $@ $<
+-include vbe_mod-video_i386_pc_vbeblit.d
+
+CLEANFILES += cmd-vbe_mod-video_i386_pc_vbeblit.lst fs-vbe_mod-video_i386_pc_vbeblit.lst partmap-vbe_mod-video_i386_pc_vbeblit.lst
+COMMANDFILES += cmd-vbe_mod-video_i386_pc_vbeblit.lst
+FSFILES += fs-vbe_mod-video_i386_pc_vbeblit.lst
+PARTMAPFILES += partmap-vbe_mod-video_i386_pc_vbeblit.lst
+
+cmd-vbe_mod-video_i386_pc_vbeblit.lst: video/i386/pc/vbeblit.c $(video/i386/pc/vbeblit.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh vbe > $@ || (rm -f $@; exit 1)
+
+fs-vbe_mod-video_i386_pc_vbeblit.lst: video/i386/pc/vbeblit.c $(video/i386/pc/vbeblit.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh vbe > $@ || (rm -f $@; exit 1)
+
+partmap-vbe_mod-video_i386_pc_vbeblit.lst: video/i386/pc/vbeblit.c $(video/i386/pc/vbeblit.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh vbe > $@ || (rm -f $@; exit 1)
+
+
+vbe_mod-video_i386_pc_vbefill.o: video/i386/pc/vbefill.c $(video/i386/pc/vbefill.c_DEPENDENCIES)
+       $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -MD -c -o $@ $<
+-include vbe_mod-video_i386_pc_vbefill.d
+
+CLEANFILES += cmd-vbe_mod-video_i386_pc_vbefill.lst fs-vbe_mod-video_i386_pc_vbefill.lst partmap-vbe_mod-video_i386_pc_vbefill.lst
+COMMANDFILES += cmd-vbe_mod-video_i386_pc_vbefill.lst
+FSFILES += fs-vbe_mod-video_i386_pc_vbefill.lst
+PARTMAPFILES += partmap-vbe_mod-video_i386_pc_vbefill.lst
+
+cmd-vbe_mod-video_i386_pc_vbefill.lst: video/i386/pc/vbefill.c $(video/i386/pc/vbefill.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh vbe > $@ || (rm -f $@; exit 1)
+
+fs-vbe_mod-video_i386_pc_vbefill.lst: video/i386/pc/vbefill.c $(video/i386/pc/vbefill.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh vbe > $@ || (rm -f $@; exit 1)
+
+partmap-vbe_mod-video_i386_pc_vbefill.lst: video/i386/pc/vbefill.c $(video/i386/pc/vbefill.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh vbe > $@ || (rm -f $@; exit 1)
+
+
+vbe_mod-video_i386_pc_vbeutil.o: video/i386/pc/vbeutil.c $(video/i386/pc/vbeutil.c_DEPENDENCIES)
+       $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -MD -c -o $@ $<
+-include vbe_mod-video_i386_pc_vbeutil.d
+
+CLEANFILES += cmd-vbe_mod-video_i386_pc_vbeutil.lst fs-vbe_mod-video_i386_pc_vbeutil.lst partmap-vbe_mod-video_i386_pc_vbeutil.lst
+COMMANDFILES += cmd-vbe_mod-video_i386_pc_vbeutil.lst
+FSFILES += fs-vbe_mod-video_i386_pc_vbeutil.lst
+PARTMAPFILES += partmap-vbe_mod-video_i386_pc_vbeutil.lst
+
+cmd-vbe_mod-video_i386_pc_vbeutil.lst: video/i386/pc/vbeutil.c $(video/i386/pc/vbeutil.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh vbe > $@ || (rm -f $@; exit 1)
+
+fs-vbe_mod-video_i386_pc_vbeutil.lst: video/i386/pc/vbeutil.c $(video/i386/pc/vbeutil.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh vbe > $@ || (rm -f $@; exit 1)
+
+partmap-vbe_mod-video_i386_pc_vbeutil.lst: video/i386/pc/vbeutil.c $(video/i386/pc/vbeutil.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ivideo/i386/pc -I$(srcdir)/video/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbe_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh vbe > $@ || (rm -f $@; exit 1)
+
+
+vbe_mod_CFLAGS = $(COMMON_CFLAGS)
+vbe_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For vbeinfo.mod.
+vbeinfo_mod_SOURCES = commands/i386/pc/vbeinfo.c
+CLEANFILES += vbeinfo.mod mod-vbeinfo.o mod-vbeinfo.c pre-vbeinfo.o vbeinfo_mod-commands_i386_pc_vbeinfo.o und-vbeinfo.lst
+ifneq ($(vbeinfo_mod_EXPORTS),no)
+CLEANFILES += def-vbeinfo.lst
+DEFSYMFILES += def-vbeinfo.lst
+endif
+MOSTLYCLEANFILES += vbeinfo_mod-commands_i386_pc_vbeinfo.d
+UNDSYMFILES += und-vbeinfo.lst
+
+vbeinfo.mod: pre-vbeinfo.o mod-vbeinfo.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(vbeinfo_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-vbeinfo.o mod-vbeinfo.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-vbeinfo.o: $(vbeinfo_mod_DEPENDENCIES) vbeinfo_mod-commands_i386_pc_vbeinfo.o
+       -rm -f $@
+       $(TARGET_CC) $(vbeinfo_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ vbeinfo_mod-commands_i386_pc_vbeinfo.o
+
+mod-vbeinfo.o: mod-vbeinfo.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbeinfo_mod_CFLAGS) -c -o $@ $<
+
+mod-vbeinfo.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'vbeinfo' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(vbeinfo_mod_EXPORTS),no)
+def-vbeinfo.lst: pre-vbeinfo.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 vbeinfo/' > $@
+endif
+
+und-vbeinfo.lst: pre-vbeinfo.o
+       echo 'vbeinfo' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+vbeinfo_mod-commands_i386_pc_vbeinfo.o: commands/i386/pc/vbeinfo.c $(commands/i386/pc/vbeinfo.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(vbeinfo_mod_CFLAGS) -MD -c -o $@ $<
+-include vbeinfo_mod-commands_i386_pc_vbeinfo.d
+
+CLEANFILES += cmd-vbeinfo_mod-commands_i386_pc_vbeinfo.lst fs-vbeinfo_mod-commands_i386_pc_vbeinfo.lst partmap-vbeinfo_mod-commands_i386_pc_vbeinfo.lst
+COMMANDFILES += cmd-vbeinfo_mod-commands_i386_pc_vbeinfo.lst
+FSFILES += fs-vbeinfo_mod-commands_i386_pc_vbeinfo.lst
+PARTMAPFILES += partmap-vbeinfo_mod-commands_i386_pc_vbeinfo.lst
+
+cmd-vbeinfo_mod-commands_i386_pc_vbeinfo.lst: commands/i386/pc/vbeinfo.c $(commands/i386/pc/vbeinfo.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbeinfo_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh vbeinfo > $@ || (rm -f $@; exit 1)
+
+fs-vbeinfo_mod-commands_i386_pc_vbeinfo.lst: commands/i386/pc/vbeinfo.c $(commands/i386/pc/vbeinfo.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbeinfo_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh vbeinfo > $@ || (rm -f $@; exit 1)
+
+partmap-vbeinfo_mod-commands_i386_pc_vbeinfo.lst: commands/i386/pc/vbeinfo.c $(commands/i386/pc/vbeinfo.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbeinfo_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh vbeinfo > $@ || (rm -f $@; exit 1)
+
+
+vbeinfo_mod_CFLAGS = $(COMMON_CFLAGS)
+vbeinfo_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For vbetest.mod.
+vbetest_mod_SOURCES = commands/i386/pc/vbetest.c
+CLEANFILES += vbetest.mod mod-vbetest.o mod-vbetest.c pre-vbetest.o vbetest_mod-commands_i386_pc_vbetest.o und-vbetest.lst
+ifneq ($(vbetest_mod_EXPORTS),no)
+CLEANFILES += def-vbetest.lst
+DEFSYMFILES += def-vbetest.lst
+endif
+MOSTLYCLEANFILES += vbetest_mod-commands_i386_pc_vbetest.d
+UNDSYMFILES += und-vbetest.lst
+
+vbetest.mod: pre-vbetest.o mod-vbetest.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(vbetest_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-vbetest.o mod-vbetest.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-vbetest.o: $(vbetest_mod_DEPENDENCIES) vbetest_mod-commands_i386_pc_vbetest.o
+       -rm -f $@
+       $(TARGET_CC) $(vbetest_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ vbetest_mod-commands_i386_pc_vbetest.o
+
+mod-vbetest.o: mod-vbetest.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbetest_mod_CFLAGS) -c -o $@ $<
+
+mod-vbetest.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'vbetest' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(vbetest_mod_EXPORTS),no)
+def-vbetest.lst: pre-vbetest.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 vbetest/' > $@
+endif
+
+und-vbetest.lst: pre-vbetest.o
+       echo 'vbetest' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+vbetest_mod-commands_i386_pc_vbetest.o: commands/i386/pc/vbetest.c $(commands/i386/pc/vbetest.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(vbetest_mod_CFLAGS) -MD -c -o $@ $<
+-include vbetest_mod-commands_i386_pc_vbetest.d
+
+CLEANFILES += cmd-vbetest_mod-commands_i386_pc_vbetest.lst fs-vbetest_mod-commands_i386_pc_vbetest.lst partmap-vbetest_mod-commands_i386_pc_vbetest.lst
+COMMANDFILES += cmd-vbetest_mod-commands_i386_pc_vbetest.lst
+FSFILES += fs-vbetest_mod-commands_i386_pc_vbetest.lst
+PARTMAPFILES += partmap-vbetest_mod-commands_i386_pc_vbetest.lst
+
+cmd-vbetest_mod-commands_i386_pc_vbetest.lst: commands/i386/pc/vbetest.c $(commands/i386/pc/vbetest.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbetest_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh vbetest > $@ || (rm -f $@; exit 1)
+
+fs-vbetest_mod-commands_i386_pc_vbetest.lst: commands/i386/pc/vbetest.c $(commands/i386/pc/vbetest.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbetest_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh vbetest > $@ || (rm -f $@; exit 1)
+
+partmap-vbetest_mod-commands_i386_pc_vbetest.lst: commands/i386/pc/vbetest.c $(commands/i386/pc/vbetest.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vbetest_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh vbetest > $@ || (rm -f $@; exit 1)
+
+
+vbetest_mod_CFLAGS = $(COMMON_CFLAGS)
+vbetest_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For play.mod.
+play_mod_SOURCES = commands/i386/pc/play.c
+CLEANFILES += play.mod mod-play.o mod-play.c pre-play.o play_mod-commands_i386_pc_play.o und-play.lst
+ifneq ($(play_mod_EXPORTS),no)
+CLEANFILES += def-play.lst
+DEFSYMFILES += def-play.lst
+endif
+MOSTLYCLEANFILES += play_mod-commands_i386_pc_play.d
+UNDSYMFILES += und-play.lst
+
+play.mod: pre-play.o mod-play.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(play_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-play.o mod-play.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-play.o: $(play_mod_DEPENDENCIES) play_mod-commands_i386_pc_play.o
+       -rm -f $@
+       $(TARGET_CC) $(play_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ play_mod-commands_i386_pc_play.o
+
+mod-play.o: mod-play.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(play_mod_CFLAGS) -c -o $@ $<
+
+mod-play.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'play' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(play_mod_EXPORTS),no)
+def-play.lst: pre-play.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 play/' > $@
+endif
+
+und-play.lst: pre-play.o
+       echo 'play' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+play_mod-commands_i386_pc_play.o: commands/i386/pc/play.c $(commands/i386/pc/play.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(play_mod_CFLAGS) -MD -c -o $@ $<
+-include play_mod-commands_i386_pc_play.d
+
+CLEANFILES += cmd-play_mod-commands_i386_pc_play.lst fs-play_mod-commands_i386_pc_play.lst partmap-play_mod-commands_i386_pc_play.lst
+COMMANDFILES += cmd-play_mod-commands_i386_pc_play.lst
+FSFILES += fs-play_mod-commands_i386_pc_play.lst
+PARTMAPFILES += partmap-play_mod-commands_i386_pc_play.lst
+
+cmd-play_mod-commands_i386_pc_play.lst: commands/i386/pc/play.c $(commands/i386/pc/play.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(play_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh play > $@ || (rm -f $@; exit 1)
+
+fs-play_mod-commands_i386_pc_play.lst: commands/i386/pc/play.c $(commands/i386/pc/play.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(play_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh play > $@ || (rm -f $@; exit 1)
+
+partmap-play_mod-commands_i386_pc_play.lst: commands/i386/pc/play.c $(commands/i386/pc/play.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(play_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh play > $@ || (rm -f $@; exit 1)
+
+
+play_mod_CFLAGS = $(COMMON_CFLAGS)
+play_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ata.mod.
+ata_mod_SOURCES = disk/ata.c
+CLEANFILES += ata.mod mod-ata.o mod-ata.c pre-ata.o ata_mod-disk_ata.o und-ata.lst
+ifneq ($(ata_mod_EXPORTS),no)
+CLEANFILES += def-ata.lst
+DEFSYMFILES += def-ata.lst
+endif
+MOSTLYCLEANFILES += ata_mod-disk_ata.d
+UNDSYMFILES += und-ata.lst
+
+ata.mod: pre-ata.o mod-ata.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(ata_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-ata.o mod-ata.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-ata.o: $(ata_mod_DEPENDENCIES) ata_mod-disk_ata.o
+       -rm -f $@
+       $(TARGET_CC) $(ata_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ ata_mod-disk_ata.o
+
+mod-ata.o: mod-ata.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_mod_CFLAGS) -c -o $@ $<
+
+mod-ata.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'ata' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(ata_mod_EXPORTS),no)
+def-ata.lst: pre-ata.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 ata/' > $@
+endif
+
+und-ata.lst: pre-ata.o
+       echo 'ata' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+ata_mod-disk_ata.o: disk/ata.c $(disk/ata.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(ata_mod_CFLAGS) -MD -c -o $@ $<
+-include ata_mod-disk_ata.d
+
+CLEANFILES += cmd-ata_mod-disk_ata.lst fs-ata_mod-disk_ata.lst partmap-ata_mod-disk_ata.lst
+COMMANDFILES += cmd-ata_mod-disk_ata.lst
+FSFILES += fs-ata_mod-disk_ata.lst
+PARTMAPFILES += partmap-ata_mod-disk_ata.lst
+
+cmd-ata_mod-disk_ata.lst: disk/ata.c $(disk/ata.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh ata > $@ || (rm -f $@; exit 1)
+
+fs-ata_mod-disk_ata.lst: disk/ata.c $(disk/ata.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh ata > $@ || (rm -f $@; exit 1)
+
+partmap-ata_mod-disk_ata.lst: disk/ata.c $(disk/ata.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh ata > $@ || (rm -f $@; exit 1)
+
+
+ata_mod_CFLAGS = $(COMMON_CFLAGS)
+ata_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For vga.mod.
+vga_mod_SOURCES = term/i386/pc/vga.c
+CLEANFILES += vga.mod mod-vga.o mod-vga.c pre-vga.o vga_mod-term_i386_pc_vga.o und-vga.lst
+ifneq ($(vga_mod_EXPORTS),no)
+CLEANFILES += def-vga.lst
+DEFSYMFILES += def-vga.lst
+endif
+MOSTLYCLEANFILES += vga_mod-term_i386_pc_vga.d
+UNDSYMFILES += und-vga.lst
+
+vga.mod: pre-vga.o mod-vga.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(vga_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-vga.o mod-vga.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-vga.o: $(vga_mod_DEPENDENCIES) vga_mod-term_i386_pc_vga.o
+       -rm -f $@
+       $(TARGET_CC) $(vga_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ vga_mod-term_i386_pc_vga.o
+
+mod-vga.o: mod-vga.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vga_mod_CFLAGS) -c -o $@ $<
+
+mod-vga.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'vga' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(vga_mod_EXPORTS),no)
+def-vga.lst: pre-vga.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 vga/' > $@
+endif
+
+und-vga.lst: pre-vga.o
+       echo 'vga' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+vga_mod-term_i386_pc_vga.o: term/i386/pc/vga.c $(term/i386/pc/vga.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(vga_mod_CFLAGS) -MD -c -o $@ $<
+-include vga_mod-term_i386_pc_vga.d
+
+CLEANFILES += cmd-vga_mod-term_i386_pc_vga.lst fs-vga_mod-term_i386_pc_vga.lst partmap-vga_mod-term_i386_pc_vga.lst
+COMMANDFILES += cmd-vga_mod-term_i386_pc_vga.lst
+FSFILES += fs-vga_mod-term_i386_pc_vga.lst
+PARTMAPFILES += partmap-vga_mod-term_i386_pc_vga.lst
+
+cmd-vga_mod-term_i386_pc_vga.lst: term/i386/pc/vga.c $(term/i386/pc/vga.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vga_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh vga > $@ || (rm -f $@; exit 1)
+
+fs-vga_mod-term_i386_pc_vga.lst: term/i386/pc/vga.c $(term/i386/pc/vga.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vga_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh vga > $@ || (rm -f $@; exit 1)
+
+partmap-vga_mod-term_i386_pc_vga.lst: term/i386/pc/vga.c $(term/i386/pc/vga.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vga_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh vga > $@ || (rm -f $@; exit 1)
+
+
+vga_mod_CFLAGS = $(COMMON_CFLAGS)
+vga_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For memdisk.mod.
+memdisk_mod_SOURCES = disk/memdisk.c
+CLEANFILES += memdisk.mod mod-memdisk.o mod-memdisk.c pre-memdisk.o memdisk_mod-disk_memdisk.o und-memdisk.lst
+ifneq ($(memdisk_mod_EXPORTS),no)
+CLEANFILES += def-memdisk.lst
+DEFSYMFILES += def-memdisk.lst
+endif
+MOSTLYCLEANFILES += memdisk_mod-disk_memdisk.d
+UNDSYMFILES += und-memdisk.lst
+
+memdisk.mod: pre-memdisk.o mod-memdisk.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(memdisk_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-memdisk.o mod-memdisk.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-memdisk.o: $(memdisk_mod_DEPENDENCIES) memdisk_mod-disk_memdisk.o
+       -rm -f $@
+       $(TARGET_CC) $(memdisk_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ memdisk_mod-disk_memdisk.o
+
+mod-memdisk.o: mod-memdisk.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -c -o $@ $<
+
+mod-memdisk.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'memdisk' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(memdisk_mod_EXPORTS),no)
+def-memdisk.lst: pre-memdisk.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 memdisk/' > $@
+endif
+
+und-memdisk.lst: pre-memdisk.o
+       echo 'memdisk' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+memdisk_mod-disk_memdisk.o: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -MD -c -o $@ $<
+-include memdisk_mod-disk_memdisk.d
+
+CLEANFILES += cmd-memdisk_mod-disk_memdisk.lst fs-memdisk_mod-disk_memdisk.lst partmap-memdisk_mod-disk_memdisk.lst
+COMMANDFILES += cmd-memdisk_mod-disk_memdisk.lst
+FSFILES += fs-memdisk_mod-disk_memdisk.lst
+PARTMAPFILES += partmap-memdisk_mod-disk_memdisk.lst
+
+cmd-memdisk_mod-disk_memdisk.lst: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh memdisk > $@ || (rm -f $@; exit 1)
+
+fs-memdisk_mod-disk_memdisk.lst: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh memdisk > $@ || (rm -f $@; exit 1)
+
+partmap-memdisk_mod-disk_memdisk.lst: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh memdisk > $@ || (rm -f $@; exit 1)
+
+
+memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+CLEANFILES += pci.mod mod-pci.o mod-pci.c pre-pci.o pci_mod-bus_pci.o und-pci.lst
+ifneq ($(pci_mod_EXPORTS),no)
+CLEANFILES += def-pci.lst
+DEFSYMFILES += def-pci.lst
+endif
+MOSTLYCLEANFILES += pci_mod-bus_pci.d
+UNDSYMFILES += und-pci.lst
+
+pci.mod: pre-pci.o mod-pci.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(pci_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-pci.o mod-pci.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-pci.o: $(pci_mod_DEPENDENCIES) pci_mod-bus_pci.o
+       -rm -f $@
+       $(TARGET_CC) $(pci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pci_mod-bus_pci.o
+
+mod-pci.o: mod-pci.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -c -o $@ $<
+
+mod-pci.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'pci' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(pci_mod_EXPORTS),no)
+def-pci.lst: pre-pci.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 pci/' > $@
+endif
+
+und-pci.lst: pre-pci.o
+       echo 'pci' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+pci_mod-bus_pci.o: bus/pci.c $(bus/pci.c_DEPENDENCIES)
+       $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -MD -c -o $@ $<
+-include pci_mod-bus_pci.d
+
+CLEANFILES += cmd-pci_mod-bus_pci.lst fs-pci_mod-bus_pci.lst partmap-pci_mod-bus_pci.lst
+COMMANDFILES += cmd-pci_mod-bus_pci.lst
+FSFILES += fs-pci_mod-bus_pci.lst
+PARTMAPFILES += partmap-pci_mod-bus_pci.lst
+
+cmd-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh pci > $@ || (rm -f $@; exit 1)
+
+fs-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh pci > $@ || (rm -f $@; exit 1)
+
+partmap-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh pci > $@ || (rm -f $@; exit 1)
+
+
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+CLEANFILES += lspci.mod mod-lspci.o mod-lspci.c pre-lspci.o lspci_mod-commands_lspci.o und-lspci.lst
+ifneq ($(lspci_mod_EXPORTS),no)
+CLEANFILES += def-lspci.lst
+DEFSYMFILES += def-lspci.lst
+endif
+MOSTLYCLEANFILES += lspci_mod-commands_lspci.d
+UNDSYMFILES += und-lspci.lst
+
+lspci.mod: pre-lspci.o mod-lspci.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(lspci_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-lspci.o mod-lspci.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-lspci.o: $(lspci_mod_DEPENDENCIES) lspci_mod-commands_lspci.o
+       -rm -f $@
+       $(TARGET_CC) $(lspci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ lspci_mod-commands_lspci.o
+
+mod-lspci.o: mod-lspci.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -c -o $@ $<
+
+mod-lspci.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'lspci' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(lspci_mod_EXPORTS),no)
+def-lspci.lst: pre-lspci.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 lspci/' > $@
+endif
+
+und-lspci.lst: pre-lspci.o
+       echo 'lspci' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+lspci_mod-commands_lspci.o: commands/lspci.c $(commands/lspci.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -MD -c -o $@ $<
+-include lspci_mod-commands_lspci.d
+
+CLEANFILES += cmd-lspci_mod-commands_lspci.lst fs-lspci_mod-commands_lspci.lst partmap-lspci_mod-commands_lspci.lst
+COMMANDFILES += cmd-lspci_mod-commands_lspci.lst
+FSFILES += fs-lspci_mod-commands_lspci.lst
+PARTMAPFILES += partmap-lspci_mod-commands_lspci.lst
+
+cmd-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh lspci > $@ || (rm -f $@; exit 1)
+
+fs-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh lspci > $@ || (rm -f $@; exit 1)
+
+partmap-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh lspci > $@ || (rm -f $@; exit 1)
+
+
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For aout.mod
+aout_mod_SOURCES = loader/aout.c
+CLEANFILES += aout.mod mod-aout.o mod-aout.c pre-aout.o aout_mod-loader_aout.o und-aout.lst
+ifneq ($(aout_mod_EXPORTS),no)
+CLEANFILES += def-aout.lst
+DEFSYMFILES += def-aout.lst
+endif
+MOSTLYCLEANFILES += aout_mod-loader_aout.d
+UNDSYMFILES += und-aout.lst
+
+aout.mod: pre-aout.o mod-aout.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(aout_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-aout.o mod-aout.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-aout.o: $(aout_mod_DEPENDENCIES) aout_mod-loader_aout.o
+       -rm -f $@
+       $(TARGET_CC) $(aout_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ aout_mod-loader_aout.o
+
+mod-aout.o: mod-aout.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(aout_mod_CFLAGS) -c -o $@ $<
+
+mod-aout.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'aout' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(aout_mod_EXPORTS),no)
+def-aout.lst: pre-aout.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 aout/' > $@
+endif
+
+und-aout.lst: pre-aout.o
+       echo 'aout' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+aout_mod-loader_aout.o: loader/aout.c $(loader/aout.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(aout_mod_CFLAGS) -MD -c -o $@ $<
+-include aout_mod-loader_aout.d
+
+CLEANFILES += cmd-aout_mod-loader_aout.lst fs-aout_mod-loader_aout.lst partmap-aout_mod-loader_aout.lst
+COMMANDFILES += cmd-aout_mod-loader_aout.lst
+FSFILES += fs-aout_mod-loader_aout.lst
+PARTMAPFILES += partmap-aout_mod-loader_aout.lst
+
+cmd-aout_mod-loader_aout.lst: loader/aout.c $(loader/aout.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(aout_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh aout > $@ || (rm -f $@; exit 1)
+
+fs-aout_mod-loader_aout.lst: loader/aout.c $(loader/aout.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(aout_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh aout > $@ || (rm -f $@; exit 1)
+
+partmap-aout_mod-loader_aout.lst: loader/aout.c $(loader/aout.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(aout_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh aout > $@ || (rm -f $@; exit 1)
+
+
+aout_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _bsd.mod
+_bsd_mod_SOURCES = loader/i386/bsd.c
+CLEANFILES += _bsd.mod mod-_bsd.o mod-_bsd.c pre-_bsd.o _bsd_mod-loader_i386_bsd.o und-_bsd.lst
+ifneq ($(_bsd_mod_EXPORTS),no)
+CLEANFILES += def-_bsd.lst
+DEFSYMFILES += def-_bsd.lst
+endif
+MOSTLYCLEANFILES += _bsd_mod-loader_i386_bsd.d
+UNDSYMFILES += und-_bsd.lst
+
+_bsd.mod: pre-_bsd.o mod-_bsd.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(_bsd_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-_bsd.o mod-_bsd.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-_bsd.o: $(_bsd_mod_DEPENDENCIES) _bsd_mod-loader_i386_bsd.o
+       -rm -f $@
+       $(TARGET_CC) $(_bsd_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ _bsd_mod-loader_i386_bsd.o
+
+mod-_bsd.o: mod-_bsd.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_bsd_mod_CFLAGS) -c -o $@ $<
+
+mod-_bsd.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '_bsd' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(_bsd_mod_EXPORTS),no)
+def-_bsd.lst: pre-_bsd.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _bsd/' > $@
+endif
+
+und-_bsd.lst: pre-_bsd.o
+       echo '_bsd' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+_bsd_mod-loader_i386_bsd.o: loader/i386/bsd.c $(loader/i386/bsd.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/i386 -I$(srcdir)/loader/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_bsd_mod_CFLAGS) -MD -c -o $@ $<
+-include _bsd_mod-loader_i386_bsd.d
+
+CLEANFILES += cmd-_bsd_mod-loader_i386_bsd.lst fs-_bsd_mod-loader_i386_bsd.lst partmap-_bsd_mod-loader_i386_bsd.lst
+COMMANDFILES += cmd-_bsd_mod-loader_i386_bsd.lst
+FSFILES += fs-_bsd_mod-loader_i386_bsd.lst
+PARTMAPFILES += partmap-_bsd_mod-loader_i386_bsd.lst
+
+cmd-_bsd_mod-loader_i386_bsd.lst: loader/i386/bsd.c $(loader/i386/bsd.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386 -I$(srcdir)/loader/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_bsd_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh _bsd > $@ || (rm -f $@; exit 1)
+
+fs-_bsd_mod-loader_i386_bsd.lst: loader/i386/bsd.c $(loader/i386/bsd.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386 -I$(srcdir)/loader/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_bsd_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh _bsd > $@ || (rm -f $@; exit 1)
+
+partmap-_bsd_mod-loader_i386_bsd.lst: loader/i386/bsd.c $(loader/i386/bsd.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386 -I$(srcdir)/loader/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_bsd_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh _bsd > $@ || (rm -f $@; exit 1)
+
+
+_bsd_mod_CFLAGS = $(COMMON_CFLAGS)
+_bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For bsd.mod
+bsd_mod_SOURCES = loader/i386/bsd_normal.c
+CLEANFILES += bsd.mod mod-bsd.o mod-bsd.c pre-bsd.o bsd_mod-loader_i386_bsd_normal.o und-bsd.lst
+ifneq ($(bsd_mod_EXPORTS),no)
+CLEANFILES += def-bsd.lst
+DEFSYMFILES += def-bsd.lst
+endif
+MOSTLYCLEANFILES += bsd_mod-loader_i386_bsd_normal.d
+UNDSYMFILES += und-bsd.lst
+
+bsd.mod: pre-bsd.o mod-bsd.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(bsd_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-bsd.o mod-bsd.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-bsd.o: $(bsd_mod_DEPENDENCIES) bsd_mod-loader_i386_bsd_normal.o
+       -rm -f $@
+       $(TARGET_CC) $(bsd_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ bsd_mod-loader_i386_bsd_normal.o
+
+mod-bsd.o: mod-bsd.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bsd_mod_CFLAGS) -c -o $@ $<
+
+mod-bsd.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'bsd' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(bsd_mod_EXPORTS),no)
+def-bsd.lst: pre-bsd.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 bsd/' > $@
+endif
+
+und-bsd.lst: pre-bsd.o
+       echo 'bsd' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+bsd_mod-loader_i386_bsd_normal.o: loader/i386/bsd_normal.c $(loader/i386/bsd_normal.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/i386 -I$(srcdir)/loader/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(bsd_mod_CFLAGS) -MD -c -o $@ $<
+-include bsd_mod-loader_i386_bsd_normal.d
+
+CLEANFILES += cmd-bsd_mod-loader_i386_bsd_normal.lst fs-bsd_mod-loader_i386_bsd_normal.lst partmap-bsd_mod-loader_i386_bsd_normal.lst
+COMMANDFILES += cmd-bsd_mod-loader_i386_bsd_normal.lst
+FSFILES += fs-bsd_mod-loader_i386_bsd_normal.lst
+PARTMAPFILES += partmap-bsd_mod-loader_i386_bsd_normal.lst
+
+cmd-bsd_mod-loader_i386_bsd_normal.lst: loader/i386/bsd_normal.c $(loader/i386/bsd_normal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386 -I$(srcdir)/loader/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bsd_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh bsd > $@ || (rm -f $@; exit 1)
+
+fs-bsd_mod-loader_i386_bsd_normal.lst: loader/i386/bsd_normal.c $(loader/i386/bsd_normal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386 -I$(srcdir)/loader/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bsd_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh bsd > $@ || (rm -f $@; exit 1)
+
+partmap-bsd_mod-loader_i386_bsd_normal.lst: loader/i386/bsd_normal.c $(loader/i386/bsd_normal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386 -I$(srcdir)/loader/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(bsd_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh bsd > $@ || (rm -f $@; exit 1)
+
+
+bsd_mod_CFLAGS = $(COMMON_CFLAGS)
+bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For usb.mod
+usb_mod_SOURCES = bus/usb/usb.c bus/usb/usbtrans.c bus/usb/usbhub.c
+CLEANFILES += usb.mod mod-usb.o mod-usb.c pre-usb.o usb_mod-bus_usb_usb.o usb_mod-bus_usb_usbtrans.o usb_mod-bus_usb_usbhub.o und-usb.lst
+ifneq ($(usb_mod_EXPORTS),no)
+CLEANFILES += def-usb.lst
+DEFSYMFILES += def-usb.lst
+endif
+MOSTLYCLEANFILES += usb_mod-bus_usb_usb.d usb_mod-bus_usb_usbtrans.d usb_mod-bus_usb_usbhub.d
+UNDSYMFILES += und-usb.lst
+
+usb.mod: pre-usb.o mod-usb.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(usb_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-usb.o mod-usb.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-usb.o: $(usb_mod_DEPENDENCIES) usb_mod-bus_usb_usb.o usb_mod-bus_usb_usbtrans.o usb_mod-bus_usb_usbhub.o
+       -rm -f $@
+       $(TARGET_CC) $(usb_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ usb_mod-bus_usb_usb.o usb_mod-bus_usb_usbtrans.o usb_mod-bus_usb_usbhub.o
+
+mod-usb.o: mod-usb.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -c -o $@ $<
+
+mod-usb.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'usb' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(usb_mod_EXPORTS),no)
+def-usb.lst: pre-usb.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 usb/' > $@
+endif
+
+und-usb.lst: pre-usb.o
+       echo 'usb' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+usb_mod-bus_usb_usb.o: bus/usb/usb.c $(bus/usb/usb.c_DEPENDENCIES)
+       $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -MD -c -o $@ $<
+-include usb_mod-bus_usb_usb.d
+
+CLEANFILES += cmd-usb_mod-bus_usb_usb.lst fs-usb_mod-bus_usb_usb.lst partmap-usb_mod-bus_usb_usb.lst
+COMMANDFILES += cmd-usb_mod-bus_usb_usb.lst
+FSFILES += fs-usb_mod-bus_usb_usb.lst
+PARTMAPFILES += partmap-usb_mod-bus_usb_usb.lst
+
+cmd-usb_mod-bus_usb_usb.lst: bus/usb/usb.c $(bus/usb/usb.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh usb > $@ || (rm -f $@; exit 1)
+
+fs-usb_mod-bus_usb_usb.lst: bus/usb/usb.c $(bus/usb/usb.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh usb > $@ || (rm -f $@; exit 1)
+
+partmap-usb_mod-bus_usb_usb.lst: bus/usb/usb.c $(bus/usb/usb.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh usb > $@ || (rm -f $@; exit 1)
+
+
+usb_mod-bus_usb_usbtrans.o: bus/usb/usbtrans.c $(bus/usb/usbtrans.c_DEPENDENCIES)
+       $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -MD -c -o $@ $<
+-include usb_mod-bus_usb_usbtrans.d
+
+CLEANFILES += cmd-usb_mod-bus_usb_usbtrans.lst fs-usb_mod-bus_usb_usbtrans.lst partmap-usb_mod-bus_usb_usbtrans.lst
+COMMANDFILES += cmd-usb_mod-bus_usb_usbtrans.lst
+FSFILES += fs-usb_mod-bus_usb_usbtrans.lst
+PARTMAPFILES += partmap-usb_mod-bus_usb_usbtrans.lst
+
+cmd-usb_mod-bus_usb_usbtrans.lst: bus/usb/usbtrans.c $(bus/usb/usbtrans.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh usb > $@ || (rm -f $@; exit 1)
+
+fs-usb_mod-bus_usb_usbtrans.lst: bus/usb/usbtrans.c $(bus/usb/usbtrans.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh usb > $@ || (rm -f $@; exit 1)
+
+partmap-usb_mod-bus_usb_usbtrans.lst: bus/usb/usbtrans.c $(bus/usb/usbtrans.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh usb > $@ || (rm -f $@; exit 1)
+
+
+usb_mod-bus_usb_usbhub.o: bus/usb/usbhub.c $(bus/usb/usbhub.c_DEPENDENCIES)
+       $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -MD -c -o $@ $<
+-include usb_mod-bus_usb_usbhub.d
+
+CLEANFILES += cmd-usb_mod-bus_usb_usbhub.lst fs-usb_mod-bus_usb_usbhub.lst partmap-usb_mod-bus_usb_usbhub.lst
+COMMANDFILES += cmd-usb_mod-bus_usb_usbhub.lst
+FSFILES += fs-usb_mod-bus_usb_usbhub.lst
+PARTMAPFILES += partmap-usb_mod-bus_usb_usbhub.lst
+
+cmd-usb_mod-bus_usb_usbhub.lst: bus/usb/usbhub.c $(bus/usb/usbhub.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh usb > $@ || (rm -f $@; exit 1)
+
+fs-usb_mod-bus_usb_usbhub.lst: bus/usb/usbhub.c $(bus/usb/usbhub.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh usb > $@ || (rm -f $@; exit 1)
+
+partmap-usb_mod-bus_usb_usbhub.lst: bus/usb/usbhub.c $(bus/usb/usbhub.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh usb > $@ || (rm -f $@; exit 1)
+
+
+usb_mod_CFLAGS = $(COMMON_CFLAGS)
+usb_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For usbtest.mod
+usbtest_mod_SOURCES = commands/usbtest.c
+CLEANFILES += usbtest.mod mod-usbtest.o mod-usbtest.c pre-usbtest.o usbtest_mod-commands_usbtest.o und-usbtest.lst
+ifneq ($(usbtest_mod_EXPORTS),no)
+CLEANFILES += def-usbtest.lst
+DEFSYMFILES += def-usbtest.lst
+endif
+MOSTLYCLEANFILES += usbtest_mod-commands_usbtest.d
+UNDSYMFILES += und-usbtest.lst
+
+usbtest.mod: pre-usbtest.o mod-usbtest.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(usbtest_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-usbtest.o mod-usbtest.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-usbtest.o: $(usbtest_mod_DEPENDENCIES) usbtest_mod-commands_usbtest.o
+       -rm -f $@
+       $(TARGET_CC) $(usbtest_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ usbtest_mod-commands_usbtest.o
+
+mod-usbtest.o: mod-usbtest.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbtest_mod_CFLAGS) -c -o $@ $<
+
+mod-usbtest.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'usbtest' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(usbtest_mod_EXPORTS),no)
+def-usbtest.lst: pre-usbtest.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 usbtest/' > $@
+endif
+
+und-usbtest.lst: pre-usbtest.o
+       echo 'usbtest' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+usbtest_mod-commands_usbtest.o: commands/usbtest.c $(commands/usbtest.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(usbtest_mod_CFLAGS) -MD -c -o $@ $<
+-include usbtest_mod-commands_usbtest.d
+
+CLEANFILES += cmd-usbtest_mod-commands_usbtest.lst fs-usbtest_mod-commands_usbtest.lst partmap-usbtest_mod-commands_usbtest.lst
+COMMANDFILES += cmd-usbtest_mod-commands_usbtest.lst
+FSFILES += fs-usbtest_mod-commands_usbtest.lst
+PARTMAPFILES += partmap-usbtest_mod-commands_usbtest.lst
+
+cmd-usbtest_mod-commands_usbtest.lst: commands/usbtest.c $(commands/usbtest.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbtest_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh usbtest > $@ || (rm -f $@; exit 1)
+
+fs-usbtest_mod-commands_usbtest.lst: commands/usbtest.c $(commands/usbtest.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbtest_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh usbtest > $@ || (rm -f $@; exit 1)
+
+partmap-usbtest_mod-commands_usbtest.lst: commands/usbtest.c $(commands/usbtest.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbtest_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh usbtest > $@ || (rm -f $@; exit 1)
+
+
+usbtest_mod_CFLAGS = $(COMMON_CFLAGS)
+usbtest_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For uhci.mod
+uhci_mod_SOURCES = bus/usb/uhci.c
+CLEANFILES += uhci.mod mod-uhci.o mod-uhci.c pre-uhci.o uhci_mod-bus_usb_uhci.o und-uhci.lst
+ifneq ($(uhci_mod_EXPORTS),no)
+CLEANFILES += def-uhci.lst
+DEFSYMFILES += def-uhci.lst
+endif
+MOSTLYCLEANFILES += uhci_mod-bus_usb_uhci.d
+UNDSYMFILES += und-uhci.lst
+
+uhci.mod: pre-uhci.o mod-uhci.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(uhci_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-uhci.o mod-uhci.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-uhci.o: $(uhci_mod_DEPENDENCIES) uhci_mod-bus_usb_uhci.o
+       -rm -f $@
+       $(TARGET_CC) $(uhci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ uhci_mod-bus_usb_uhci.o
+
+mod-uhci.o: mod-uhci.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(uhci_mod_CFLAGS) -c -o $@ $<
+
+mod-uhci.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'uhci' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(uhci_mod_EXPORTS),no)
+def-uhci.lst: pre-uhci.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 uhci/' > $@
+endif
+
+und-uhci.lst: pre-uhci.o
+       echo 'uhci' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+uhci_mod-bus_usb_uhci.o: bus/usb/uhci.c $(bus/usb/uhci.c_DEPENDENCIES)
+       $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(uhci_mod_CFLAGS) -MD -c -o $@ $<
+-include uhci_mod-bus_usb_uhci.d
+
+CLEANFILES += cmd-uhci_mod-bus_usb_uhci.lst fs-uhci_mod-bus_usb_uhci.lst partmap-uhci_mod-bus_usb_uhci.lst
+COMMANDFILES += cmd-uhci_mod-bus_usb_uhci.lst
+FSFILES += fs-uhci_mod-bus_usb_uhci.lst
+PARTMAPFILES += partmap-uhci_mod-bus_usb_uhci.lst
+
+cmd-uhci_mod-bus_usb_uhci.lst: bus/usb/uhci.c $(bus/usb/uhci.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(uhci_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh uhci > $@ || (rm -f $@; exit 1)
+
+fs-uhci_mod-bus_usb_uhci.lst: bus/usb/uhci.c $(bus/usb/uhci.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(uhci_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh uhci > $@ || (rm -f $@; exit 1)
+
+partmap-uhci_mod-bus_usb_uhci.lst: bus/usb/uhci.c $(bus/usb/uhci.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(uhci_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh uhci > $@ || (rm -f $@; exit 1)
+
+
+uhci_mod_CFLAGS = $(COMMON_CFLAGS)
+uhci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ohci.mod
+ohci_mod_SOURCES = bus/usb/ohci.c
+CLEANFILES += ohci.mod mod-ohci.o mod-ohci.c pre-ohci.o ohci_mod-bus_usb_ohci.o und-ohci.lst
+ifneq ($(ohci_mod_EXPORTS),no)
+CLEANFILES += def-ohci.lst
+DEFSYMFILES += def-ohci.lst
+endif
+MOSTLYCLEANFILES += ohci_mod-bus_usb_ohci.d
+UNDSYMFILES += und-ohci.lst
+
+ohci.mod: pre-ohci.o mod-ohci.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(ohci_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-ohci.o mod-ohci.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-ohci.o: $(ohci_mod_DEPENDENCIES) ohci_mod-bus_usb_ohci.o
+       -rm -f $@
+       $(TARGET_CC) $(ohci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ ohci_mod-bus_usb_ohci.o
+
+mod-ohci.o: mod-ohci.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ohci_mod_CFLAGS) -c -o $@ $<
+
+mod-ohci.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'ohci' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(ohci_mod_EXPORTS),no)
+def-ohci.lst: pre-ohci.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 ohci/' > $@
+endif
+
+und-ohci.lst: pre-ohci.o
+       echo 'ohci' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+ohci_mod-bus_usb_ohci.o: bus/usb/ohci.c $(bus/usb/ohci.c_DEPENDENCIES)
+       $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(ohci_mod_CFLAGS) -MD -c -o $@ $<
+-include ohci_mod-bus_usb_ohci.d
+
+CLEANFILES += cmd-ohci_mod-bus_usb_ohci.lst fs-ohci_mod-bus_usb_ohci.lst partmap-ohci_mod-bus_usb_ohci.lst
+COMMANDFILES += cmd-ohci_mod-bus_usb_ohci.lst
+FSFILES += fs-ohci_mod-bus_usb_ohci.lst
+PARTMAPFILES += partmap-ohci_mod-bus_usb_ohci.lst
+
+cmd-ohci_mod-bus_usb_ohci.lst: bus/usb/ohci.c $(bus/usb/ohci.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ohci_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh ohci > $@ || (rm -f $@; exit 1)
+
+fs-ohci_mod-bus_usb_ohci.lst: bus/usb/ohci.c $(bus/usb/ohci.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ohci_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh ohci > $@ || (rm -f $@; exit 1)
+
+partmap-ohci_mod-bus_usb_ohci.lst: bus/usb/ohci.c $(bus/usb/ohci.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ibus/usb -I$(srcdir)/bus/usb $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ohci_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh ohci > $@ || (rm -f $@; exit 1)
+
+
+ohci_mod_CFLAGS = $(COMMON_CFLAGS)
+ohci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For usbms.mod
+usbms_mod_SOURCES = disk/usbms.c
+CLEANFILES += usbms.mod mod-usbms.o mod-usbms.c pre-usbms.o usbms_mod-disk_usbms.o und-usbms.lst
+ifneq ($(usbms_mod_EXPORTS),no)
+CLEANFILES += def-usbms.lst
+DEFSYMFILES += def-usbms.lst
+endif
+MOSTLYCLEANFILES += usbms_mod-disk_usbms.d
+UNDSYMFILES += und-usbms.lst
+
+usbms.mod: pre-usbms.o mod-usbms.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(usbms_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-usbms.o mod-usbms.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-usbms.o: $(usbms_mod_DEPENDENCIES) usbms_mod-disk_usbms.o
+       -rm -f $@
+       $(TARGET_CC) $(usbms_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ usbms_mod-disk_usbms.o
+
+mod-usbms.o: mod-usbms.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbms_mod_CFLAGS) -c -o $@ $<
+
+mod-usbms.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'usbms' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(usbms_mod_EXPORTS),no)
+def-usbms.lst: pre-usbms.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 usbms/' > $@
+endif
+
+und-usbms.lst: pre-usbms.o
+       echo 'usbms' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+usbms_mod-disk_usbms.o: disk/usbms.c $(disk/usbms.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(usbms_mod_CFLAGS) -MD -c -o $@ $<
+-include usbms_mod-disk_usbms.d
+
+CLEANFILES += cmd-usbms_mod-disk_usbms.lst fs-usbms_mod-disk_usbms.lst partmap-usbms_mod-disk_usbms.lst
+COMMANDFILES += cmd-usbms_mod-disk_usbms.lst
+FSFILES += fs-usbms_mod-disk_usbms.lst
+PARTMAPFILES += partmap-usbms_mod-disk_usbms.lst
+
+cmd-usbms_mod-disk_usbms.lst: disk/usbms.c $(disk/usbms.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbms_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh usbms > $@ || (rm -f $@; exit 1)
+
+fs-usbms_mod-disk_usbms.lst: disk/usbms.c $(disk/usbms.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbms_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh usbms > $@ || (rm -f $@; exit 1)
+
+partmap-usbms_mod-disk_usbms.lst: disk/usbms.c $(disk/usbms.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usbms_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh usbms > $@ || (rm -f $@; exit 1)
+
+
+usbms_mod_CFLAGS = $(COMMON_CFLAGS)
+usbms_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For usb_keyboard.mod
+usb_keyboard_mod_SOURCES = term/usb_keyboard.c
+CLEANFILES += usb_keyboard.mod mod-usb_keyboard.o mod-usb_keyboard.c pre-usb_keyboard.o usb_keyboard_mod-term_usb_keyboard.o und-usb_keyboard.lst
+ifneq ($(usb_keyboard_mod_EXPORTS),no)
+CLEANFILES += def-usb_keyboard.lst
+DEFSYMFILES += def-usb_keyboard.lst
+endif
+MOSTLYCLEANFILES += usb_keyboard_mod-term_usb_keyboard.d
+UNDSYMFILES += und-usb_keyboard.lst
+
+usb_keyboard.mod: pre-usb_keyboard.o mod-usb_keyboard.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(usb_keyboard_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-usb_keyboard.o mod-usb_keyboard.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-usb_keyboard.o: $(usb_keyboard_mod_DEPENDENCIES) usb_keyboard_mod-term_usb_keyboard.o
+       -rm -f $@
+       $(TARGET_CC) $(usb_keyboard_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ usb_keyboard_mod-term_usb_keyboard.o
+
+mod-usb_keyboard.o: mod-usb_keyboard.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_keyboard_mod_CFLAGS) -c -o $@ $<
+
+mod-usb_keyboard.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'usb_keyboard' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(usb_keyboard_mod_EXPORTS),no)
+def-usb_keyboard.lst: pre-usb_keyboard.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 usb_keyboard/' > $@
+endif
+
+und-usb_keyboard.lst: pre-usb_keyboard.o
+       echo 'usb_keyboard' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+usb_keyboard_mod-term_usb_keyboard.o: term/usb_keyboard.c $(term/usb_keyboard.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(usb_keyboard_mod_CFLAGS) -MD -c -o $@ $<
+-include usb_keyboard_mod-term_usb_keyboard.d
+
+CLEANFILES += cmd-usb_keyboard_mod-term_usb_keyboard.lst fs-usb_keyboard_mod-term_usb_keyboard.lst partmap-usb_keyboard_mod-term_usb_keyboard.lst
+COMMANDFILES += cmd-usb_keyboard_mod-term_usb_keyboard.lst
+FSFILES += fs-usb_keyboard_mod-term_usb_keyboard.lst
+PARTMAPFILES += partmap-usb_keyboard_mod-term_usb_keyboard.lst
+
+cmd-usb_keyboard_mod-term_usb_keyboard.lst: term/usb_keyboard.c $(term/usb_keyboard.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_keyboard_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh usb_keyboard > $@ || (rm -f $@; exit 1)
+
+fs-usb_keyboard_mod-term_usb_keyboard.lst: term/usb_keyboard.c $(term/usb_keyboard.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_keyboard_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh usb_keyboard > $@ || (rm -f $@; exit 1)
+
+partmap-usb_keyboard_mod-term_usb_keyboard.lst: term/usb_keyboard.c $(term/usb_keyboard.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_keyboard_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh usb_keyboard > $@ || (rm -f $@; exit 1)
+
+
+usb_keyboard_mod_CFLAGS = $(COMMON_CFLAGS)
+usb_keyboard_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pxe.mod
+pxe_mod_SOURCES = fs/i386/pc/pxe.c
+CLEANFILES += pxe.mod mod-pxe.o mod-pxe.c pre-pxe.o pxe_mod-fs_i386_pc_pxe.o und-pxe.lst
+ifneq ($(pxe_mod_EXPORTS),no)
+CLEANFILES += def-pxe.lst
+DEFSYMFILES += def-pxe.lst
+endif
+MOSTLYCLEANFILES += pxe_mod-fs_i386_pc_pxe.d
+UNDSYMFILES += und-pxe.lst
+
+pxe.mod: pre-pxe.o mod-pxe.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(pxe_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-pxe.o mod-pxe.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-pxe.o: $(pxe_mod_DEPENDENCIES) pxe_mod-fs_i386_pc_pxe.o
+       -rm -f $@
+       $(TARGET_CC) $(pxe_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pxe_mod-fs_i386_pc_pxe.o
+
+mod-pxe.o: mod-pxe.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxe_mod_CFLAGS) -c -o $@ $<
+
+mod-pxe.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'pxe' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(pxe_mod_EXPORTS),no)
+def-pxe.lst: pre-pxe.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 pxe/' > $@
+endif
+
+und-pxe.lst: pre-pxe.o
+       echo 'pxe' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+pxe_mod-fs_i386_pc_pxe.o: fs/i386/pc/pxe.c $(fs/i386/pc/pxe.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs/i386/pc -I$(srcdir)/fs/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(pxe_mod_CFLAGS) -MD -c -o $@ $<
+-include pxe_mod-fs_i386_pc_pxe.d
+
+CLEANFILES += cmd-pxe_mod-fs_i386_pc_pxe.lst fs-pxe_mod-fs_i386_pc_pxe.lst partmap-pxe_mod-fs_i386_pc_pxe.lst
+COMMANDFILES += cmd-pxe_mod-fs_i386_pc_pxe.lst
+FSFILES += fs-pxe_mod-fs_i386_pc_pxe.lst
+PARTMAPFILES += partmap-pxe_mod-fs_i386_pc_pxe.lst
+
+cmd-pxe_mod-fs_i386_pc_pxe.lst: fs/i386/pc/pxe.c $(fs/i386/pc/pxe.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs/i386/pc -I$(srcdir)/fs/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxe_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh pxe > $@ || (rm -f $@; exit 1)
+
+fs-pxe_mod-fs_i386_pc_pxe.lst: fs/i386/pc/pxe.c $(fs/i386/pc/pxe.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs/i386/pc -I$(srcdir)/fs/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxe_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh pxe > $@ || (rm -f $@; exit 1)
+
+partmap-pxe_mod-fs_i386_pc_pxe.lst: fs/i386/pc/pxe.c $(fs/i386/pc/pxe.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs/i386/pc -I$(srcdir)/fs/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxe_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh pxe > $@ || (rm -f $@; exit 1)
+
+
+pxe_mod_CFLAGS = $(COMMON_CFLAGS)
+pxe_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pxecmd.mod
+pxecmd_mod_SOURCES = commands/i386/pc/pxecmd.c
+CLEANFILES += pxecmd.mod mod-pxecmd.o mod-pxecmd.c pre-pxecmd.o pxecmd_mod-commands_i386_pc_pxecmd.o und-pxecmd.lst
+ifneq ($(pxecmd_mod_EXPORTS),no)
+CLEANFILES += def-pxecmd.lst
+DEFSYMFILES += def-pxecmd.lst
+endif
+MOSTLYCLEANFILES += pxecmd_mod-commands_i386_pc_pxecmd.d
+UNDSYMFILES += und-pxecmd.lst
+
+pxecmd.mod: pre-pxecmd.o mod-pxecmd.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(pxecmd_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-pxecmd.o mod-pxecmd.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-pxecmd.o: $(pxecmd_mod_DEPENDENCIES) pxecmd_mod-commands_i386_pc_pxecmd.o
+       -rm -f $@
+       $(TARGET_CC) $(pxecmd_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pxecmd_mod-commands_i386_pc_pxecmd.o
+
+mod-pxecmd.o: mod-pxecmd.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxecmd_mod_CFLAGS) -c -o $@ $<
+
+mod-pxecmd.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'pxecmd' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(pxecmd_mod_EXPORTS),no)
+def-pxecmd.lst: pre-pxecmd.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 pxecmd/' > $@
+endif
+
+und-pxecmd.lst: pre-pxecmd.o
+       echo 'pxecmd' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+pxecmd_mod-commands_i386_pc_pxecmd.o: commands/i386/pc/pxecmd.c $(commands/i386/pc/pxecmd.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(pxecmd_mod_CFLAGS) -MD -c -o $@ $<
+-include pxecmd_mod-commands_i386_pc_pxecmd.d
+
+CLEANFILES += cmd-pxecmd_mod-commands_i386_pc_pxecmd.lst fs-pxecmd_mod-commands_i386_pc_pxecmd.lst partmap-pxecmd_mod-commands_i386_pc_pxecmd.lst
+COMMANDFILES += cmd-pxecmd_mod-commands_i386_pc_pxecmd.lst
+FSFILES += fs-pxecmd_mod-commands_i386_pc_pxecmd.lst
+PARTMAPFILES += partmap-pxecmd_mod-commands_i386_pc_pxecmd.lst
+
+cmd-pxecmd_mod-commands_i386_pc_pxecmd.lst: commands/i386/pc/pxecmd.c $(commands/i386/pc/pxecmd.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxecmd_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh pxecmd > $@ || (rm -f $@; exit 1)
+
+fs-pxecmd_mod-commands_i386_pc_pxecmd.lst: commands/i386/pc/pxecmd.c $(commands/i386/pc/pxecmd.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxecmd_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh pxecmd > $@ || (rm -f $@; exit 1)
+
+partmap-pxecmd_mod-commands_i386_pc_pxecmd.lst: commands/i386/pc/pxecmd.c $(commands/i386/pc/pxecmd.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pxecmd_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh pxecmd > $@ || (rm -f $@; exit 1)
+
+
+pxecmd_mod_CFLAGS = $(COMMON_CFLAGS)
+pxecmd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datetime.mod
+datetime_mod_SOURCES = lib/datetime.c lib/i386/datetime.c
+CLEANFILES += datetime.mod mod-datetime.o mod-datetime.c pre-datetime.o datetime_mod-lib_datetime.o datetime_mod-lib_i386_datetime.o und-datetime.lst
+ifneq ($(datetime_mod_EXPORTS),no)
+CLEANFILES += def-datetime.lst
+DEFSYMFILES += def-datetime.lst
+endif
+MOSTLYCLEANFILES += datetime_mod-lib_datetime.d datetime_mod-lib_i386_datetime.d
+UNDSYMFILES += und-datetime.lst
+
+datetime.mod: pre-datetime.o mod-datetime.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(datetime_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-datetime.o mod-datetime.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-datetime.o: $(datetime_mod_DEPENDENCIES) datetime_mod-lib_datetime.o datetime_mod-lib_i386_datetime.o
+       -rm -f $@
+       $(TARGET_CC) $(datetime_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ datetime_mod-lib_datetime.o datetime_mod-lib_i386_datetime.o
+
+mod-datetime.o: mod-datetime.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -c -o $@ $<
+
+mod-datetime.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'datetime' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(datetime_mod_EXPORTS),no)
+def-datetime.lst: pre-datetime.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 datetime/' > $@
+endif
+
+und-datetime.lst: pre-datetime.o
+       echo 'datetime' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+datetime_mod-lib_datetime.o: lib/datetime.c $(lib/datetime.c_DEPENDENCIES)
+       $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -MD -c -o $@ $<
+-include datetime_mod-lib_datetime.d
+
+CLEANFILES += cmd-datetime_mod-lib_datetime.lst fs-datetime_mod-lib_datetime.lst partmap-datetime_mod-lib_datetime.lst
+COMMANDFILES += cmd-datetime_mod-lib_datetime.lst
+FSFILES += fs-datetime_mod-lib_datetime.lst
+PARTMAPFILES += partmap-datetime_mod-lib_datetime.lst
+
+cmd-datetime_mod-lib_datetime.lst: lib/datetime.c $(lib/datetime.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh datetime > $@ || (rm -f $@; exit 1)
+
+fs-datetime_mod-lib_datetime.lst: lib/datetime.c $(lib/datetime.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh datetime > $@ || (rm -f $@; exit 1)
+
+partmap-datetime_mod-lib_datetime.lst: lib/datetime.c $(lib/datetime.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh datetime > $@ || (rm -f $@; exit 1)
+
+
+datetime_mod-lib_i386_datetime.o: lib/i386/datetime.c $(lib/i386/datetime.c_DEPENDENCIES)
+       $(TARGET_CC) -Ilib/i386 -I$(srcdir)/lib/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -MD -c -o $@ $<
+-include datetime_mod-lib_i386_datetime.d
+
+CLEANFILES += cmd-datetime_mod-lib_i386_datetime.lst fs-datetime_mod-lib_i386_datetime.lst partmap-datetime_mod-lib_i386_datetime.lst
+COMMANDFILES += cmd-datetime_mod-lib_i386_datetime.lst
+FSFILES += fs-datetime_mod-lib_i386_datetime.lst
+PARTMAPFILES += partmap-datetime_mod-lib_i386_datetime.lst
+
+cmd-datetime_mod-lib_i386_datetime.lst: lib/i386/datetime.c $(lib/i386/datetime.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ilib/i386 -I$(srcdir)/lib/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh datetime > $@ || (rm -f $@; exit 1)
+
+fs-datetime_mod-lib_i386_datetime.lst: lib/i386/datetime.c $(lib/i386/datetime.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ilib/i386 -I$(srcdir)/lib/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh datetime > $@ || (rm -f $@; exit 1)
+
+partmap-datetime_mod-lib_i386_datetime.lst: lib/i386/datetime.c $(lib/i386/datetime.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ilib/i386 -I$(srcdir)/lib/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh datetime > $@ || (rm -f $@; exit 1)
+
+
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+CLEANFILES += date.mod mod-date.o mod-date.c pre-date.o date_mod-commands_date.o und-date.lst
+ifneq ($(date_mod_EXPORTS),no)
+CLEANFILES += def-date.lst
+DEFSYMFILES += def-date.lst
+endif
+MOSTLYCLEANFILES += date_mod-commands_date.d
+UNDSYMFILES += und-date.lst
+
+date.mod: pre-date.o mod-date.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(date_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-date.o mod-date.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-date.o: $(date_mod_DEPENDENCIES) date_mod-commands_date.o
+       -rm -f $@
+       $(TARGET_CC) $(date_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ date_mod-commands_date.o
+
+mod-date.o: mod-date.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -c -o $@ $<
+
+mod-date.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'date' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(date_mod_EXPORTS),no)
+def-date.lst: pre-date.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 date/' > $@
+endif
+
+und-date.lst: pre-date.o
+       echo 'date' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+date_mod-commands_date.o: commands/date.c $(commands/date.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(date_mod_CFLAGS) -MD -c -o $@ $<
+-include date_mod-commands_date.d
+
+CLEANFILES += cmd-date_mod-commands_date.lst fs-date_mod-commands_date.lst partmap-date_mod-commands_date.lst
+COMMANDFILES += cmd-date_mod-commands_date.lst
+FSFILES += fs-date_mod-commands_date.lst
+PARTMAPFILES += partmap-date_mod-commands_date.lst
+
+cmd-date_mod-commands_date.lst: commands/date.c $(commands/date.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh date > $@ || (rm -f $@; exit 1)
+
+fs-date_mod-commands_date.lst: commands/date.c $(commands/date.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh date > $@ || (rm -f $@; exit 1)
+
+partmap-date_mod-commands_date.lst: commands/date.c $(commands/date.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh date > $@ || (rm -f $@; exit 1)
+
+
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datehook.mod
+datehook_mod_SOURCES = hook/datehook.c
+CLEANFILES += datehook.mod mod-datehook.o mod-datehook.c pre-datehook.o datehook_mod-hook_datehook.o und-datehook.lst
+ifneq ($(datehook_mod_EXPORTS),no)
+CLEANFILES += def-datehook.lst
+DEFSYMFILES += def-datehook.lst
+endif
+MOSTLYCLEANFILES += datehook_mod-hook_datehook.d
+UNDSYMFILES += und-datehook.lst
+
+datehook.mod: pre-datehook.o mod-datehook.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(datehook_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-datehook.o mod-datehook.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-datehook.o: $(datehook_mod_DEPENDENCIES) datehook_mod-hook_datehook.o
+       -rm -f $@
+       $(TARGET_CC) $(datehook_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ datehook_mod-hook_datehook.o
+
+mod-datehook.o: mod-datehook.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -c -o $@ $<
+
+mod-datehook.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'datehook' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(datehook_mod_EXPORTS),no)
+def-datehook.lst: pre-datehook.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 datehook/' > $@
+endif
+
+und-datehook.lst: pre-datehook.o
+       echo 'datehook' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+datehook_mod-hook_datehook.o: hook/datehook.c $(hook/datehook.c_DEPENDENCIES)
+       $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -MD -c -o $@ $<
+-include datehook_mod-hook_datehook.d
+
+CLEANFILES += cmd-datehook_mod-hook_datehook.lst fs-datehook_mod-hook_datehook.lst partmap-datehook_mod-hook_datehook.lst
+COMMANDFILES += cmd-datehook_mod-hook_datehook.lst
+FSFILES += fs-datehook_mod-hook_datehook.lst
+PARTMAPFILES += partmap-datehook_mod-hook_datehook.lst
+
+cmd-datehook_mod-hook_datehook.lst: hook/datehook.c $(hook/datehook.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh datehook > $@ || (rm -f $@; exit 1)
+
+fs-datehook_mod-hook_datehook.lst: hook/datehook.c $(hook/datehook.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh datehook > $@ || (rm -f $@; exit 1)
+
+partmap-datehook_mod-hook_datehook.lst: hook/datehook.c $(hook/datehook.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh datehook > $@ || (rm -f $@; exit 1)
+
+
+datehook_mod_CFLAGS = $(COMMON_CFLAGS)
+datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lsmmap.mod
+lsmmap_mod_SOURCES = commands/lsmmap.c
+CLEANFILES += lsmmap.mod mod-lsmmap.o mod-lsmmap.c pre-lsmmap.o lsmmap_mod-commands_lsmmap.o und-lsmmap.lst
+ifneq ($(lsmmap_mod_EXPORTS),no)
+CLEANFILES += def-lsmmap.lst
+DEFSYMFILES += def-lsmmap.lst
+endif
+MOSTLYCLEANFILES += lsmmap_mod-commands_lsmmap.d
+UNDSYMFILES += und-lsmmap.lst
+
+lsmmap.mod: pre-lsmmap.o mod-lsmmap.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(lsmmap_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-lsmmap.o mod-lsmmap.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-lsmmap.o: $(lsmmap_mod_DEPENDENCIES) lsmmap_mod-commands_lsmmap.o
+       -rm -f $@
+       $(TARGET_CC) $(lsmmap_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ lsmmap_mod-commands_lsmmap.o
+
+mod-lsmmap.o: mod-lsmmap.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -c -o $@ $<
+
+mod-lsmmap.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'lsmmap' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(lsmmap_mod_EXPORTS),no)
+def-lsmmap.lst: pre-lsmmap.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 lsmmap/' > $@
+endif
+
+und-lsmmap.lst: pre-lsmmap.o
+       echo 'lsmmap' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+lsmmap_mod-commands_lsmmap.o: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -MD -c -o $@ $<
+-include lsmmap_mod-commands_lsmmap.d
+
+CLEANFILES += cmd-lsmmap_mod-commands_lsmmap.lst fs-lsmmap_mod-commands_lsmmap.lst partmap-lsmmap_mod-commands_lsmmap.lst
+COMMANDFILES += cmd-lsmmap_mod-commands_lsmmap.lst
+FSFILES += fs-lsmmap_mod-commands_lsmmap.lst
+PARTMAPFILES += partmap-lsmmap_mod-commands_lsmmap.lst
+
+cmd-lsmmap_mod-commands_lsmmap.lst: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh lsmmap > $@ || (rm -f $@; exit 1)
+
+fs-lsmmap_mod-commands_lsmmap.lst: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh lsmmap > $@ || (rm -f $@; exit 1)
+
+partmap-lsmmap_mod-commands_lsmmap.lst: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh lsmmap > $@ || (rm -f $@; exit 1)
+
+
+lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
+lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ata_pthru.mod.
+ata_pthru_mod_SOURCES = disk/ata_pthru.c
+CLEANFILES += ata_pthru.mod mod-ata_pthru.o mod-ata_pthru.c pre-ata_pthru.o ata_pthru_mod-disk_ata_pthru.o und-ata_pthru.lst
+ifneq ($(ata_pthru_mod_EXPORTS),no)
+CLEANFILES += def-ata_pthru.lst
+DEFSYMFILES += def-ata_pthru.lst
+endif
+MOSTLYCLEANFILES += ata_pthru_mod-disk_ata_pthru.d
+UNDSYMFILES += und-ata_pthru.lst
+
+ata_pthru.mod: pre-ata_pthru.o mod-ata_pthru.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(ata_pthru_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-ata_pthru.o mod-ata_pthru.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-ata_pthru.o: $(ata_pthru_mod_DEPENDENCIES) ata_pthru_mod-disk_ata_pthru.o
+       -rm -f $@
+       $(TARGET_CC) $(ata_pthru_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ ata_pthru_mod-disk_ata_pthru.o
+
+mod-ata_pthru.o: mod-ata_pthru.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_pthru_mod_CFLAGS) -c -o $@ $<
+
+mod-ata_pthru.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'ata_pthru' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(ata_pthru_mod_EXPORTS),no)
+def-ata_pthru.lst: pre-ata_pthru.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 ata_pthru/' > $@
+endif
+
+und-ata_pthru.lst: pre-ata_pthru.o
+       echo 'ata_pthru' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+ata_pthru_mod-disk_ata_pthru.o: disk/ata_pthru.c $(disk/ata_pthru.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(ata_pthru_mod_CFLAGS) -MD -c -o $@ $<
+-include ata_pthru_mod-disk_ata_pthru.d
+
+CLEANFILES += cmd-ata_pthru_mod-disk_ata_pthru.lst fs-ata_pthru_mod-disk_ata_pthru.lst partmap-ata_pthru_mod-disk_ata_pthru.lst
+COMMANDFILES += cmd-ata_pthru_mod-disk_ata_pthru.lst
+FSFILES += fs-ata_pthru_mod-disk_ata_pthru.lst
+PARTMAPFILES += partmap-ata_pthru_mod-disk_ata_pthru.lst
+
+cmd-ata_pthru_mod-disk_ata_pthru.lst: disk/ata_pthru.c $(disk/ata_pthru.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_pthru_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh ata_pthru > $@ || (rm -f $@; exit 1)
+
+fs-ata_pthru_mod-disk_ata_pthru.lst: disk/ata_pthru.c $(disk/ata_pthru.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_pthru_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh ata_pthru > $@ || (rm -f $@; exit 1)
+
+partmap-ata_pthru_mod-disk_ata_pthru.lst: disk/ata_pthru.c $(disk/ata_pthru.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_pthru_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh ata_pthru > $@ || (rm -f $@; exit 1)
+
+
+ata_pthru_mod_CFLAGS = $(COMMON_CFLAGS)
+ata_pthru_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For hdparm.mod.
+hdparm_mod_SOURCES = commands/hdparm.c lib/hexdump.c
+CLEANFILES += hdparm.mod mod-hdparm.o mod-hdparm.c pre-hdparm.o hdparm_mod-commands_hdparm.o hdparm_mod-lib_hexdump.o und-hdparm.lst
+ifneq ($(hdparm_mod_EXPORTS),no)
+CLEANFILES += def-hdparm.lst
+DEFSYMFILES += def-hdparm.lst
+endif
+MOSTLYCLEANFILES += hdparm_mod-commands_hdparm.d hdparm_mod-lib_hexdump.d
+UNDSYMFILES += und-hdparm.lst
+
+hdparm.mod: pre-hdparm.o mod-hdparm.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(hdparm_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-hdparm.o mod-hdparm.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-hdparm.o: $(hdparm_mod_DEPENDENCIES) hdparm_mod-commands_hdparm.o hdparm_mod-lib_hexdump.o
+       -rm -f $@
+       $(TARGET_CC) $(hdparm_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ hdparm_mod-commands_hdparm.o hdparm_mod-lib_hexdump.o
+
+mod-hdparm.o: mod-hdparm.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hdparm_mod_CFLAGS) -c -o $@ $<
+
+mod-hdparm.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'hdparm' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(hdparm_mod_EXPORTS),no)
+def-hdparm.lst: pre-hdparm.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 hdparm/' > $@
+endif
+
+und-hdparm.lst: pre-hdparm.o
+       echo 'hdparm' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+hdparm_mod-commands_hdparm.o: commands/hdparm.c $(commands/hdparm.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(hdparm_mod_CFLAGS) -MD -c -o $@ $<
+-include hdparm_mod-commands_hdparm.d
+
+CLEANFILES += cmd-hdparm_mod-commands_hdparm.lst fs-hdparm_mod-commands_hdparm.lst partmap-hdparm_mod-commands_hdparm.lst
+COMMANDFILES += cmd-hdparm_mod-commands_hdparm.lst
+FSFILES += fs-hdparm_mod-commands_hdparm.lst
+PARTMAPFILES += partmap-hdparm_mod-commands_hdparm.lst
+
+cmd-hdparm_mod-commands_hdparm.lst: commands/hdparm.c $(commands/hdparm.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hdparm_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh hdparm > $@ || (rm -f $@; exit 1)
+
+fs-hdparm_mod-commands_hdparm.lst: commands/hdparm.c $(commands/hdparm.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hdparm_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh hdparm > $@ || (rm -f $@; exit 1)
+
+partmap-hdparm_mod-commands_hdparm.lst: commands/hdparm.c $(commands/hdparm.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hdparm_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh hdparm > $@ || (rm -f $@; exit 1)
+
+
+hdparm_mod-lib_hexdump.o: lib/hexdump.c $(lib/hexdump.c_DEPENDENCIES)
+       $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(hdparm_mod_CFLAGS) -MD -c -o $@ $<
+-include hdparm_mod-lib_hexdump.d
+
+CLEANFILES += cmd-hdparm_mod-lib_hexdump.lst fs-hdparm_mod-lib_hexdump.lst partmap-hdparm_mod-lib_hexdump.lst
+COMMANDFILES += cmd-hdparm_mod-lib_hexdump.lst
+FSFILES += fs-hdparm_mod-lib_hexdump.lst
+PARTMAPFILES += partmap-hdparm_mod-lib_hexdump.lst
+
+cmd-hdparm_mod-lib_hexdump.lst: lib/hexdump.c $(lib/hexdump.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hdparm_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh hdparm > $@ || (rm -f $@; exit 1)
+
+fs-hdparm_mod-lib_hexdump.lst: lib/hexdump.c $(lib/hexdump.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hdparm_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh hdparm > $@ || (rm -f $@; exit 1)
+
+partmap-hdparm_mod-lib_hexdump.lst: lib/hexdump.c $(lib/hexdump.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hdparm_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh hdparm > $@ || (rm -f $@; exit 1)
+
+
+hdparm_mod_CFLAGS = $(COMMON_CFLAGS)
+hdparm_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+include $(srcdir)/conf/i386.mk
+include $(srcdir)/conf/common.mk
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
new file mode 100644 (file)
index 0000000..fd66ce9
--- /dev/null
@@ -0,0 +1,384 @@
+# -*- makefile -*-
+
+GRUB_MEMORY_MACHINE_LINK_ADDR = 0x8200
+
+COMMON_ASFLAGS = -nostdinc -fno-builtin -m32
+COMMON_CFLAGS = -fno-builtin -mrtd -mregparm=3 -m32
+COMMON_LDFLAGS = -m32 -nostdlib
+
+# Used by various components.  These rules need to precede them.
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Images.
+pkglib_IMAGES = boot.img diskboot.img kernel.img pxeboot.img lnxboot.img \
+               cdboot.img
+
+# For boot.img.
+boot_img_SOURCES = boot/i386/pc/boot.S
+boot_img_ASFLAGS = $(COMMON_ASFLAGS)
+boot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,7C00
+
+# For pxeboot.img
+pxeboot_img_SOURCES = boot/i386/pc/pxeboot.S
+pxeboot_img_ASFLAGS = $(COMMON_ASFLAGS)
+pxeboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,7C00
+
+# For diskboot.img.
+diskboot_img_SOURCES = boot/i386/pc/diskboot.S
+diskboot_img_ASFLAGS = $(COMMON_ASFLAGS)
+diskboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,8000
+
+# For lnxboot.img.
+lnxboot_img_SOURCES = boot/i386/pc/lnxboot.S
+lnxboot_img_ASFLAGS = $(COMMON_ASFLAGS)
+lnxboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,6000
+
+# For cdboot.img.
+cdboot_img_SOURCES = boot/i386/pc/cdboot.S
+cdboot_img_ASFLAGS = $(COMMON_ASFLAGS)
+cdboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,7C00
+
+# For kernel.img.
+kernel_img_SOURCES = kern/i386/pc/startup.S kern/main.c kern/device.c \
+       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
+       kern/time.c \
+       kern/i386/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \
+       kern/parser.c kern/partition.c \
+       kern/i386/tsc.c kern/i386/pit.c \
+       kern/generic/rtc_get_time_ms.c \
+       kern/generic/millisleep.c \
+       kern/env.c \
+       term/i386/pc/console.c term/i386/vga_common.c \
+       symlist.c
+kernel_img_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
+       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
+       partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
+       machine/biosdisk.h machine/boot.h machine/console.h machine/init.h \
+       machine/memory.h machine/loader.h machine/vga.h machine/vbe.h \
+       machine/kernel.h machine/pxe.h
+kernel_img_CFLAGS = $(COMMON_CFLAGS)
+kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,$(GRUB_MEMORY_MACHINE_LINK_ADDR) $(COMMON_CFLAGS)
+
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+symlist.c: $(addprefix include/grub/,$(kernel_img_HEADERS)) config.h gensymlist.sh
+       /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_img_HEADERS)) config.h genkernsyms.sh
+       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+# Utilities.
+bin_UTILITIES = grub-mkimage
+sbin_UTILITIES = grub-setup grub-mkdevicemap
+ifeq ($(enable_grub_emu), yes)
+sbin_UTILITIES += grub-emu
+endif
+
+# For grub-mkimage.
+ifeq ($(enable_lzo), yes)
+grub_mkimage_SOURCES = util/i386/pc/grub-mkimage.c util/misc.c \
+       util/resolve.c
+grub_mkimage_LDFLAGS = $(LIBLZO)
+else
+grub_mkimage_SOURCES = util/i386/pc/grub-mkimage.c util/misc.c \
+       util/resolve.c lib/LzmaEnc.c lib/LzFind.c
+endif
+grub_mkimage_CFLAGS = -DGRUB_MEMORY_MACHINE_LINK_ADDR=$(GRUB_MEMORY_MACHINE_LINK_ADDR)
+util/i386/pc/grub-mkimage.c_DEPENDENCIES = Makefile
+
+# For grub-setup.
+util/i386/pc/grub-setup.c_DEPENDENCIES = grub_setup_init.h
+grub_setup_SOURCES = util/i386/pc/grub-setup.c util/hostdisk.c \
+       util/misc.c util/getroot.c kern/device.c kern/disk.c    \
+       kern/err.c kern/misc.c kern/parser.c kern/partition.c   \
+       kern/file.c kern/fs.c kern/env.c fs/fshelp.c            \
+       \
+       fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c         \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c  \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c          \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                     \
+       \
+       partmap/pc.c partmap/gpt.c                              \
+       \
+       disk/raid.c disk/mdraid_linux.c disk/lvm.c              \
+       util/raid.c util/lvm.c                                  \
+       grub_setup_init.c
+
+# For grub-mkdevicemap.
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+
+# For grub-emu.
+util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
+grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c       \
+       commands/configfile.c commands/echo.c commands/help.c           \
+       commands/terminal.c commands/ls.c commands/test.c               \
+       commands/search.c commands/blocklist.c commands/hexdump.c       \
+       lib/hexdump.c commands/i386/pc/halt.c commands/reboot.c         \
+       commands/i386/cpuid.c                                           \
+       disk/host.c disk/loopback.c disk/scsi.c                         \
+       fs/fshelp.c     \
+       \
+       io/gzio.c                                                       \
+       kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c       \
+       kern/err.c                                                      \
+       normal/execute.c kern/file.c kern/fs.c normal/lexer.c           \
+       kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
+       grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
+       normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
+       normal/completion.c normal/main.c normal/color.c                \
+       normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
+       normal/menu_text.c                                              \
+       normal/misc.c normal/script.c                                   \
+       partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
+       partmap/acorn.c partmap/gpt.c                                   \
+       \
+       fs/affs.c fs/cpio.c  fs/fat.c fs/ext2.c fs/hfs.c                \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c          \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c                  \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                             \
+       \
+       util/console.c util/hostfs.c util/grub-emu.c util/misc.c        \
+       util/hostdisk.c util/getroot.c                                  \
+       util/i386/pc/misc.c                                             \
+       \
+       disk/raid.c disk/raid5_recover.c disk/raid6_recover.c           \
+       disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c             \
+       grub_emu_init.c
+
+grub_emu_LDFLAGS = $(LIBCURSES) 
+
+ifeq ($(enable_grub_emu_usb), yes)
+grub_emu_SOURCES += disk/usbms.c util/usb.c bus/usb/usb.c      \
+               commands/usbtest.c
+grub_emu_LDFLAGS += $(LIBCURSES) $(LIBUSB)
+endif
+
+# Scripts.
+sbin_SCRIPTS = grub-install
+bin_SCRIPTS = grub-mkrescue
+
+# For grub-install.
+grub_install_SOURCES = util/i386/pc/grub-install.in
+
+# For grub-mkrescue.
+grub_mkrescue_SOURCES = util/i386/pc/grub-mkrescue.in
+
+# Modules.
+pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \
+       _multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod      \
+       vbe.mod vbetest.mod vbeinfo.mod play.mod serial.mod     \
+       ata.mod vga.mod memdisk.mod pci.mod lspci.mod \
+       aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod datetime.mod date.mod \
+       datehook.mod lsmmap.mod ata_pthru.mod hdparm.mod \
+       usb.mod uhci.mod ohci.mod usbtest.mod usbms.mod usb_keyboard.mod
+
+# For biosdisk.mod.
+biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
+biosdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+biosdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _chain.mod.
+_chain_mod_SOURCES = loader/i386/pc/chainloader.c
+_chain_mod_CFLAGS = $(COMMON_CFLAGS)
+_chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For chain.mod.
+chain_mod_SOURCES = loader/i386/pc/chainloader_normal.c
+chain_mod_CFLAGS = $(COMMON_CFLAGS)
+chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _linux.mod.
+_linux_mod_SOURCES = loader/i386/pc/linux.c
+_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/linux_normal.c
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+#
+# Only arch dependant part of normal.mod will be here. Common part for
+# all architecures of normal.mod is at start and should be kept at sync
+# with other makefiles.
+# 
+# Please put arch dependant part of normal.mod at the end of list to
+# keep it simpler to update to different architectures.
+#
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/color.c                                                  \
+       normal/menu_viewer.c normal/menu_entry.c                        \
+       normal/misc.c grub_script.tab.c                                 \
+       normal/script.c                                                 \
+       normal/i386/setjmp.S
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reboot.mod.
+reboot_mod_SOURCES = commands/reboot.c
+reboot_mod_CFLAGS = $(COMMON_CFLAGS)
+reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For halt.mod.
+halt_mod_SOURCES = commands/i386/pc/halt.c
+halt_mod_CFLAGS = $(COMMON_CFLAGS)
+halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For serial.mod.
+serial_mod_SOURCES = term/i386/pc/serial.c
+serial_mod_CFLAGS = $(COMMON_CFLAGS)
+serial_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _multiboot.mod.
+_multiboot_mod_SOURCES = loader/i386/pc/multiboot.c \
+                         loader/i386/pc/multiboot2.c \
+                         loader/multiboot2.c \
+                         loader/multiboot_loader.c
+_multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+_multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For multiboot.mod.
+multiboot_mod_SOURCES = loader/multiboot_loader_normal.c 
+multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For vbe.mod.
+vbe_mod_SOURCES = video/i386/pc/vbe.c video/i386/pc/vbeblit.c \
+                 video/i386/pc/vbefill.c video/i386/pc/vbeutil.c
+vbe_mod_CFLAGS = $(COMMON_CFLAGS)
+vbe_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For vbeinfo.mod.
+vbeinfo_mod_SOURCES = commands/i386/pc/vbeinfo.c
+vbeinfo_mod_CFLAGS = $(COMMON_CFLAGS)
+vbeinfo_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For vbetest.mod.
+vbetest_mod_SOURCES = commands/i386/pc/vbetest.c
+vbetest_mod_CFLAGS = $(COMMON_CFLAGS)
+vbetest_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For play.mod.
+play_mod_SOURCES = commands/i386/pc/play.c
+play_mod_CFLAGS = $(COMMON_CFLAGS)
+play_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ata.mod.
+ata_mod_SOURCES = disk/ata.c
+ata_mod_CFLAGS = $(COMMON_CFLAGS)
+ata_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For vga.mod.
+vga_mod_SOURCES = term/i386/pc/vga.c
+vga_mod_CFLAGS = $(COMMON_CFLAGS)
+vga_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For memdisk.mod.
+memdisk_mod_SOURCES = disk/memdisk.c
+memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For aout.mod
+aout_mod_SOURCES = loader/aout.c
+aout_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _bsd.mod
+_bsd_mod_SOURCES = loader/i386/bsd.c
+_bsd_mod_CFLAGS = $(COMMON_CFLAGS)
+_bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For bsd.mod
+bsd_mod_SOURCES = loader/i386/bsd_normal.c
+bsd_mod_CFLAGS = $(COMMON_CFLAGS)
+bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For usb.mod
+usb_mod_SOURCES = bus/usb/usb.c bus/usb/usbtrans.c bus/usb/usbhub.c
+usb_mod_CFLAGS = $(COMMON_CFLAGS)
+usb_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For usbtest.mod
+usbtest_mod_SOURCES = commands/usbtest.c
+usbtest_mod_CFLAGS = $(COMMON_CFLAGS)
+usbtest_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For uhci.mod
+uhci_mod_SOURCES = bus/usb/uhci.c
+uhci_mod_CFLAGS = $(COMMON_CFLAGS)
+uhci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ohci.mod
+ohci_mod_SOURCES = bus/usb/ohci.c
+ohci_mod_CFLAGS = $(COMMON_CFLAGS)
+ohci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For usbms.mod
+usbms_mod_SOURCES = disk/usbms.c
+usbms_mod_CFLAGS = $(COMMON_CFLAGS)
+usbms_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For usb_keyboard.mod
+usb_keyboard_mod_SOURCES = term/usb_keyboard.c
+usb_keyboard_mod_CFLAGS = $(COMMON_CFLAGS)
+usb_keyboard_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pxe.mod
+pxe_mod_SOURCES = fs/i386/pc/pxe.c
+pxe_mod_CFLAGS = $(COMMON_CFLAGS)
+pxe_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pxecmd.mod
+pxecmd_mod_SOURCES = commands/i386/pc/pxecmd.c
+pxecmd_mod_CFLAGS = $(COMMON_CFLAGS)
+pxecmd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datetime.mod
+datetime_mod_SOURCES = lib/datetime.c lib/i386/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datehook.mod
+datehook_mod_SOURCES = hook/datehook.c
+datehook_mod_CFLAGS = $(COMMON_CFLAGS)
+datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lsmmap.mod
+lsmmap_mod_SOURCES = commands/lsmmap.c
+lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
+lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ata_pthru.mod.
+ata_pthru_mod_SOURCES = disk/ata_pthru.c
+ata_pthru_mod_CFLAGS = $(COMMON_CFLAGS)
+ata_pthru_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For hdparm.mod.
+hdparm_mod_SOURCES = commands/hdparm.c lib/hexdump.c
+hdparm_mod_CFLAGS = $(COMMON_CFLAGS)
+hdparm_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+include $(srcdir)/conf/i386.mk
+include $(srcdir)/conf/common.mk
diff --git a/conf/i386.mk b/conf/i386.mk
new file mode 100644 (file)
index 0000000..5cd7b42
--- /dev/null
@@ -0,0 +1,192 @@
+# -*- makefile -*-
+# Generated by genmk.rb, please don't edit!
+
+pkglib_MODULES += cpuid.mod
+cpuid_mod_SOURCES = commands/i386/cpuid.c
+CLEANFILES += cpuid.mod mod-cpuid.o mod-cpuid.c pre-cpuid.o cpuid_mod-commands_i386_cpuid.o und-cpuid.lst
+ifneq ($(cpuid_mod_EXPORTS),no)
+CLEANFILES += def-cpuid.lst
+DEFSYMFILES += def-cpuid.lst
+endif
+MOSTLYCLEANFILES += cpuid_mod-commands_i386_cpuid.d
+UNDSYMFILES += und-cpuid.lst
+
+cpuid.mod: pre-cpuid.o mod-cpuid.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(cpuid_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-cpuid.o mod-cpuid.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-cpuid.o: $(cpuid_mod_DEPENDENCIES) cpuid_mod-commands_i386_cpuid.o
+       -rm -f $@
+       $(TARGET_CC) $(cpuid_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ cpuid_mod-commands_i386_cpuid.o
+
+mod-cpuid.o: mod-cpuid.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cpuid_mod_CFLAGS) -c -o $@ $<
+
+mod-cpuid.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'cpuid' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(cpuid_mod_EXPORTS),no)
+def-cpuid.lst: pre-cpuid.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 cpuid/' > $@
+endif
+
+und-cpuid.lst: pre-cpuid.o
+       echo 'cpuid' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+cpuid_mod-commands_i386_cpuid.o: commands/i386/cpuid.c $(commands/i386/cpuid.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands/i386 -I$(srcdir)/commands/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(cpuid_mod_CFLAGS) -MD -c -o $@ $<
+-include cpuid_mod-commands_i386_cpuid.d
+
+CLEANFILES += cmd-cpuid_mod-commands_i386_cpuid.lst fs-cpuid_mod-commands_i386_cpuid.lst partmap-cpuid_mod-commands_i386_cpuid.lst
+COMMANDFILES += cmd-cpuid_mod-commands_i386_cpuid.lst
+FSFILES += fs-cpuid_mod-commands_i386_cpuid.lst
+PARTMAPFILES += partmap-cpuid_mod-commands_i386_cpuid.lst
+
+cmd-cpuid_mod-commands_i386_cpuid.lst: commands/i386/cpuid.c $(commands/i386/cpuid.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386 -I$(srcdir)/commands/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cpuid_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh cpuid > $@ || (rm -f $@; exit 1)
+
+fs-cpuid_mod-commands_i386_cpuid.lst: commands/i386/cpuid.c $(commands/i386/cpuid.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386 -I$(srcdir)/commands/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cpuid_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh cpuid > $@ || (rm -f $@; exit 1)
+
+partmap-cpuid_mod-commands_i386_cpuid.lst: commands/i386/cpuid.c $(commands/i386/cpuid.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands/i386 -I$(srcdir)/commands/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cpuid_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh cpuid > $@ || (rm -f $@; exit 1)
+
+
+cpuid_mod_CFLAGS = $(COMMON_CFLAGS)
+cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+pkglib_MODULES += at_keyboard.mod
+at_keyboard_mod_SOURCES = term/i386/pc/at_keyboard.c
+CLEANFILES += at_keyboard.mod mod-at_keyboard.o mod-at_keyboard.c pre-at_keyboard.o at_keyboard_mod-term_i386_pc_at_keyboard.o und-at_keyboard.lst
+ifneq ($(at_keyboard_mod_EXPORTS),no)
+CLEANFILES += def-at_keyboard.lst
+DEFSYMFILES += def-at_keyboard.lst
+endif
+MOSTLYCLEANFILES += at_keyboard_mod-term_i386_pc_at_keyboard.d
+UNDSYMFILES += und-at_keyboard.lst
+
+at_keyboard.mod: pre-at_keyboard.o mod-at_keyboard.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(at_keyboard_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-at_keyboard.o mod-at_keyboard.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-at_keyboard.o: $(at_keyboard_mod_DEPENDENCIES) at_keyboard_mod-term_i386_pc_at_keyboard.o
+       -rm -f $@
+       $(TARGET_CC) $(at_keyboard_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ at_keyboard_mod-term_i386_pc_at_keyboard.o
+
+mod-at_keyboard.o: mod-at_keyboard.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(at_keyboard_mod_CFLAGS) -c -o $@ $<
+
+mod-at_keyboard.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'at_keyboard' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(at_keyboard_mod_EXPORTS),no)
+def-at_keyboard.lst: pre-at_keyboard.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 at_keyboard/' > $@
+endif
+
+und-at_keyboard.lst: pre-at_keyboard.o
+       echo 'at_keyboard' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+at_keyboard_mod-term_i386_pc_at_keyboard.o: term/i386/pc/at_keyboard.c $(term/i386/pc/at_keyboard.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(at_keyboard_mod_CFLAGS) -MD -c -o $@ $<
+-include at_keyboard_mod-term_i386_pc_at_keyboard.d
+
+CLEANFILES += cmd-at_keyboard_mod-term_i386_pc_at_keyboard.lst fs-at_keyboard_mod-term_i386_pc_at_keyboard.lst partmap-at_keyboard_mod-term_i386_pc_at_keyboard.lst
+COMMANDFILES += cmd-at_keyboard_mod-term_i386_pc_at_keyboard.lst
+FSFILES += fs-at_keyboard_mod-term_i386_pc_at_keyboard.lst
+PARTMAPFILES += partmap-at_keyboard_mod-term_i386_pc_at_keyboard.lst
+
+cmd-at_keyboard_mod-term_i386_pc_at_keyboard.lst: term/i386/pc/at_keyboard.c $(term/i386/pc/at_keyboard.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(at_keyboard_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh at_keyboard > $@ || (rm -f $@; exit 1)
+
+fs-at_keyboard_mod-term_i386_pc_at_keyboard.lst: term/i386/pc/at_keyboard.c $(term/i386/pc/at_keyboard.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(at_keyboard_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh at_keyboard > $@ || (rm -f $@; exit 1)
+
+partmap-at_keyboard_mod-term_i386_pc_at_keyboard.lst: term/i386/pc/at_keyboard.c $(term/i386/pc/at_keyboard.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(at_keyboard_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh at_keyboard > $@ || (rm -f $@; exit 1)
+
+
+at_keyboard_mod_CFLAGS = $(COMMON_CFLAGS)
+at_keyboard_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+pkglib_MODULES += vga_text.mod
+vga_text_mod_SOURCES = term/i386/pc/vga_text.c term/i386/vga_common.c
+CLEANFILES += vga_text.mod mod-vga_text.o mod-vga_text.c pre-vga_text.o vga_text_mod-term_i386_pc_vga_text.o vga_text_mod-term_i386_vga_common.o und-vga_text.lst
+ifneq ($(vga_text_mod_EXPORTS),no)
+CLEANFILES += def-vga_text.lst
+DEFSYMFILES += def-vga_text.lst
+endif
+MOSTLYCLEANFILES += vga_text_mod-term_i386_pc_vga_text.d vga_text_mod-term_i386_vga_common.d
+UNDSYMFILES += und-vga_text.lst
+
+vga_text.mod: pre-vga_text.o mod-vga_text.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(vga_text_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-vga_text.o mod-vga_text.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-vga_text.o: $(vga_text_mod_DEPENDENCIES) vga_text_mod-term_i386_pc_vga_text.o vga_text_mod-term_i386_vga_common.o
+       -rm -f $@
+       $(TARGET_CC) $(vga_text_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ vga_text_mod-term_i386_pc_vga_text.o vga_text_mod-term_i386_vga_common.o
+
+mod-vga_text.o: mod-vga_text.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vga_text_mod_CFLAGS) -c -o $@ $<
+
+mod-vga_text.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'vga_text' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(vga_text_mod_EXPORTS),no)
+def-vga_text.lst: pre-vga_text.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 vga_text/' > $@
+endif
+
+und-vga_text.lst: pre-vga_text.o
+       echo 'vga_text' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+vga_text_mod-term_i386_pc_vga_text.o: term/i386/pc/vga_text.c $(term/i386/pc/vga_text.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(vga_text_mod_CFLAGS) -MD -c -o $@ $<
+-include vga_text_mod-term_i386_pc_vga_text.d
+
+CLEANFILES += cmd-vga_text_mod-term_i386_pc_vga_text.lst fs-vga_text_mod-term_i386_pc_vga_text.lst partmap-vga_text_mod-term_i386_pc_vga_text.lst
+COMMANDFILES += cmd-vga_text_mod-term_i386_pc_vga_text.lst
+FSFILES += fs-vga_text_mod-term_i386_pc_vga_text.lst
+PARTMAPFILES += partmap-vga_text_mod-term_i386_pc_vga_text.lst
+
+cmd-vga_text_mod-term_i386_pc_vga_text.lst: term/i386/pc/vga_text.c $(term/i386/pc/vga_text.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vga_text_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh vga_text > $@ || (rm -f $@; exit 1)
+
+fs-vga_text_mod-term_i386_pc_vga_text.lst: term/i386/pc/vga_text.c $(term/i386/pc/vga_text.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vga_text_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh vga_text > $@ || (rm -f $@; exit 1)
+
+partmap-vga_text_mod-term_i386_pc_vga_text.lst: term/i386/pc/vga_text.c $(term/i386/pc/vga_text.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vga_text_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh vga_text > $@ || (rm -f $@; exit 1)
+
+
+vga_text_mod-term_i386_vga_common.o: term/i386/vga_common.c $(term/i386/vga_common.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/i386 -I$(srcdir)/term/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(vga_text_mod_CFLAGS) -MD -c -o $@ $<
+-include vga_text_mod-term_i386_vga_common.d
+
+CLEANFILES += cmd-vga_text_mod-term_i386_vga_common.lst fs-vga_text_mod-term_i386_vga_common.lst partmap-vga_text_mod-term_i386_vga_common.lst
+COMMANDFILES += cmd-vga_text_mod-term_i386_vga_common.lst
+FSFILES += fs-vga_text_mod-term_i386_vga_common.lst
+PARTMAPFILES += partmap-vga_text_mod-term_i386_vga_common.lst
+
+cmd-vga_text_mod-term_i386_vga_common.lst: term/i386/vga_common.c $(term/i386/vga_common.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386 -I$(srcdir)/term/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vga_text_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh vga_text > $@ || (rm -f $@; exit 1)
+
+fs-vga_text_mod-term_i386_vga_common.lst: term/i386/vga_common.c $(term/i386/vga_common.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386 -I$(srcdir)/term/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vga_text_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh vga_text > $@ || (rm -f $@; exit 1)
+
+partmap-vga_text_mod-term_i386_vga_common.lst: term/i386/vga_common.c $(term/i386/vga_common.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iterm/i386 -I$(srcdir)/term/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(vga_text_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh vga_text > $@ || (rm -f $@; exit 1)
+
+
+vga_text_mod_CFLAGS = $(COMMON_CFLAGS)
+vga_text_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/conf/i386.rmk b/conf/i386.rmk
new file mode 100644 (file)
index 0000000..93f84ce
--- /dev/null
@@ -0,0 +1,16 @@
+# -*- makefile -*-
+
+pkglib_MODULES += cpuid.mod
+cpuid_mod_SOURCES = commands/i386/cpuid.c
+cpuid_mod_CFLAGS = $(COMMON_CFLAGS)
+cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+pkglib_MODULES += at_keyboard.mod
+at_keyboard_mod_SOURCES = term/i386/pc/at_keyboard.c
+at_keyboard_mod_CFLAGS = $(COMMON_CFLAGS)
+at_keyboard_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+pkglib_MODULES += vga_text.mod
+vga_text_mod_SOURCES = term/i386/pc/vga_text.c term/i386/vga_common.c
+vga_text_mod_CFLAGS = $(COMMON_CFLAGS)
+vga_text_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/conf/powerpc-ieee1275.mk b/conf/powerpc-ieee1275.mk
new file mode 100644 (file)
index 0000000..18edeaf
--- /dev/null
@@ -0,0 +1,1542 @@
+
+# Generated by genmk.rb, please don't edit!
+# -*- makefile -*-
+
+COMMON_ASFLAGS = -nostdinc -D__ASSEMBLY__
+COMMON_CFLAGS = -ffreestanding
+COMMON_LDFLAGS += -nostdlib
+
+# Used by various components.  These rules need to precede them.
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Images.
+
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+kernel_elf_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
+       env.h err.h file.h fs.h kernel.h misc.h mm.h net.h parser.h rescue.h \
+       symbol.h term.h time.h types.h powerpc/libgcc.h loader.h partition.h \
+       pc_partition.h ieee1275/ieee1275.h machine/kernel.h
+
+symlist.c: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h gensymlist.sh
+       /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h genkernsyms.sh
+       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+# Programs
+pkglib_PROGRAMS = kernel.elf
+
+# Utilities.
+sbin_UTILITIES = grub-mkdevicemap
+ifeq ($(enable_grub_emu), yes)
+sbin_UTILITIES += grub-emu
+endif
+# For grub-mkdevicemap.
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+CLEANFILES += grub-mkdevicemap$(EXEEXT) grub_mkdevicemap-util_grub_mkdevicemap.o grub_mkdevicemap-util_misc.o
+MOSTLYCLEANFILES += grub_mkdevicemap-util_grub_mkdevicemap.d grub_mkdevicemap-util_misc.d
+
+grub-mkdevicemap: $(grub_mkdevicemap_DEPENDENCIES) grub_mkdevicemap-util_grub_mkdevicemap.o grub_mkdevicemap-util_misc.o
+       $(CC) -o $@ grub_mkdevicemap-util_grub_mkdevicemap.o grub_mkdevicemap-util_misc.o $(LDFLAGS) $(grub_mkdevicemap_LDFLAGS)
+
+grub_mkdevicemap-util_grub_mkdevicemap.o: util/grub-mkdevicemap.c $(util/grub-mkdevicemap.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkdevicemap_CFLAGS) -MD -c -o $@ $<
+-include grub_mkdevicemap-util_grub_mkdevicemap.d
+
+grub_mkdevicemap-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkdevicemap_CFLAGS) -MD -c -o $@ $<
+-include grub_mkdevicemap-util_misc.d
+
+
+# For grub-emu
+util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
+grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c       \
+       commands/configfile.c commands/help.c                           \
+       commands/search.c commands/terminal.c commands/test.c           \
+       commands/ls.c commands/blocklist.c commands/hexdump.c           \
+       lib/hexdump.c commands/halt.c commands/reboot.c                 \
+       disk/loopback.c                                                 \
+       \
+       fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/ext2.c fs/hfs.c       \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c          \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c                  \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                             \
+       \
+       io/gzio.c                                                       \
+       kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c       \
+       kern/err.c kern/file.c kern/fs.c kern/loader.c kern/main.c      \
+       kern/misc.c kern/parser.c kern/partition.c kern/rescue.c        \
+       kern/term.c fs/fshelp.c                                         \
+       normal/arg.c normal/cmdline.c normal/command.c                  \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/menu_entry.c normal/menu_viewer.c normal/misc.c          \
+       normal/script.c                                                 \
+       normal/color.c                                                  \
+       partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
+       partmap/acorn.c                                                 \
+       util/console.c util/hostfs.c util/grub-emu.c util/misc.c        \
+       util/hostdisk.c util/getroot.c                                  \
+       util/powerpc/ieee1275/misc.c                                    \
+       \
+       disk/raid.c disk/raid5_recover.c disk/raid6_recover.c           \
+       disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c             \
+       grub_script.tab.c grub_emu_init.c
+CLEANFILES += grub-emu$(EXEEXT) grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_help.o grub_emu-commands_search.o grub_emu-commands_terminal.o grub_emu-commands_test.o grub_emu-commands_ls.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_halt.o grub_emu-commands_reboot.o grub_emu-disk_loopback.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_ext2.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-fs_fshelp.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_completion.o grub_emu-normal_execute.o grub_emu-normal_function.o grub_emu-normal_lexer.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_text.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-normal_color.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_powerpc_ieee1275_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_script_tab.o grub_emu-grub_emu_init.o
+MOSTLYCLEANFILES += grub_emu-commands_boot.d grub_emu-commands_cat.d grub_emu-commands_cmp.d grub_emu-commands_configfile.d grub_emu-commands_help.d grub_emu-commands_search.d grub_emu-commands_terminal.d grub_emu-commands_test.d grub_emu-commands_ls.d grub_emu-commands_blocklist.d grub_emu-commands_hexdump.d grub_emu-lib_hexdump.d grub_emu-commands_halt.d grub_emu-commands_reboot.d grub_emu-disk_loopback.d grub_emu-fs_affs.d grub_emu-fs_cpio.d grub_emu-fs_ext2.d grub_emu-fs_fat.d grub_emu-fs_ext2.d grub_emu-fs_hfs.d grub_emu-fs_hfsplus.d grub_emu-fs_iso9660.d grub_emu-fs_udf.d grub_emu-fs_jfs.d grub_emu-fs_minix.d grub_emu-fs_ntfs.d grub_emu-fs_ntfscomp.d grub_emu-fs_reiserfs.d grub_emu-fs_sfs.d grub_emu-fs_ufs.d grub_emu-fs_xfs.d grub_emu-fs_afs.d grub_emu-fs_tar.d grub_emu-io_gzio.d grub_emu-kern_device.d grub_emu-kern_disk.d grub_emu-kern_dl.d grub_emu-kern_elf.d grub_emu-kern_env.d grub_emu-kern_err.d grub_emu-kern_file.d grub_emu-kern_fs.d grub_emu-kern_loader.d grub_emu-kern_main.d grub_emu-kern_misc.d grub_emu-kern_parser.d grub_emu-kern_partition.d grub_emu-kern_rescue.d grub_emu-kern_term.d grub_emu-fs_fshelp.d grub_emu-normal_arg.d grub_emu-normal_cmdline.d grub_emu-normal_command.d grub_emu-normal_completion.d grub_emu-normal_execute.d grub_emu-normal_function.d grub_emu-normal_lexer.d grub_emu-normal_main.d grub_emu-normal_menu.d grub_emu-normal_menu_text.d grub_emu-normal_menu_entry.d grub_emu-normal_menu_viewer.d grub_emu-normal_misc.d grub_emu-normal_script.d grub_emu-normal_color.d grub_emu-partmap_amiga.d grub_emu-partmap_apple.d grub_emu-partmap_pc.d grub_emu-partmap_sun.d grub_emu-partmap_acorn.d grub_emu-util_console.d grub_emu-util_hostfs.d grub_emu-util_grub_emu.d grub_emu-util_misc.d grub_emu-util_hostdisk.d grub_emu-util_getroot.d grub_emu-util_powerpc_ieee1275_misc.d grub_emu-disk_raid.d grub_emu-disk_raid5_recover.d grub_emu-disk_raid6_recover.d grub_emu-disk_mdraid_linux.d grub_emu-disk_dmraid_nvidia.d grub_emu-disk_lvm.d grub_emu-grub_script_tab.d grub_emu-grub_emu_init.d
+
+grub-emu: $(grub_emu_DEPENDENCIES) grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_help.o grub_emu-commands_search.o grub_emu-commands_terminal.o grub_emu-commands_test.o grub_emu-commands_ls.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_halt.o grub_emu-commands_reboot.o grub_emu-disk_loopback.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_ext2.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-fs_fshelp.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_completion.o grub_emu-normal_execute.o grub_emu-normal_function.o grub_emu-normal_lexer.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_text.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-normal_color.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_powerpc_ieee1275_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_script_tab.o grub_emu-grub_emu_init.o
+       $(CC) -o $@ grub_emu-commands_boot.o grub_emu-commands_cat.o grub_emu-commands_cmp.o grub_emu-commands_configfile.o grub_emu-commands_help.o grub_emu-commands_search.o grub_emu-commands_terminal.o grub_emu-commands_test.o grub_emu-commands_ls.o grub_emu-commands_blocklist.o grub_emu-commands_hexdump.o grub_emu-lib_hexdump.o grub_emu-commands_halt.o grub_emu-commands_reboot.o grub_emu-disk_loopback.o grub_emu-fs_affs.o grub_emu-fs_cpio.o grub_emu-fs_ext2.o grub_emu-fs_fat.o grub_emu-fs_ext2.o grub_emu-fs_hfs.o grub_emu-fs_hfsplus.o grub_emu-fs_iso9660.o grub_emu-fs_udf.o grub_emu-fs_jfs.o grub_emu-fs_minix.o grub_emu-fs_ntfs.o grub_emu-fs_ntfscomp.o grub_emu-fs_reiserfs.o grub_emu-fs_sfs.o grub_emu-fs_ufs.o grub_emu-fs_xfs.o grub_emu-fs_afs.o grub_emu-fs_tar.o grub_emu-io_gzio.o grub_emu-kern_device.o grub_emu-kern_disk.o grub_emu-kern_dl.o grub_emu-kern_elf.o grub_emu-kern_env.o grub_emu-kern_err.o grub_emu-kern_file.o grub_emu-kern_fs.o grub_emu-kern_loader.o grub_emu-kern_main.o grub_emu-kern_misc.o grub_emu-kern_parser.o grub_emu-kern_partition.o grub_emu-kern_rescue.o grub_emu-kern_term.o grub_emu-fs_fshelp.o grub_emu-normal_arg.o grub_emu-normal_cmdline.o grub_emu-normal_command.o grub_emu-normal_completion.o grub_emu-normal_execute.o grub_emu-normal_function.o grub_emu-normal_lexer.o grub_emu-normal_main.o grub_emu-normal_menu.o grub_emu-normal_menu_text.o grub_emu-normal_menu_entry.o grub_emu-normal_menu_viewer.o grub_emu-normal_misc.o grub_emu-normal_script.o grub_emu-normal_color.o grub_emu-partmap_amiga.o grub_emu-partmap_apple.o grub_emu-partmap_pc.o grub_emu-partmap_sun.o grub_emu-partmap_acorn.o grub_emu-util_console.o grub_emu-util_hostfs.o grub_emu-util_grub_emu.o grub_emu-util_misc.o grub_emu-util_hostdisk.o grub_emu-util_getroot.o grub_emu-util_powerpc_ieee1275_misc.o grub_emu-disk_raid.o grub_emu-disk_raid5_recover.o grub_emu-disk_raid6_recover.o grub_emu-disk_mdraid_linux.o grub_emu-disk_dmraid_nvidia.o grub_emu-disk_lvm.o grub_emu-grub_script_tab.o grub_emu-grub_emu_init.o $(LDFLAGS) $(grub_emu_LDFLAGS)
+
+grub_emu-commands_boot.o: commands/boot.c $(commands/boot.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_boot.d
+
+grub_emu-commands_cat.o: commands/cat.c $(commands/cat.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_cat.d
+
+grub_emu-commands_cmp.o: commands/cmp.c $(commands/cmp.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_cmp.d
+
+grub_emu-commands_configfile.o: commands/configfile.c $(commands/configfile.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_configfile.d
+
+grub_emu-commands_help.o: commands/help.c $(commands/help.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_help.d
+
+grub_emu-commands_search.o: commands/search.c $(commands/search.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_search.d
+
+grub_emu-commands_terminal.o: commands/terminal.c $(commands/terminal.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_terminal.d
+
+grub_emu-commands_test.o: commands/test.c $(commands/test.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_test.d
+
+grub_emu-commands_ls.o: commands/ls.c $(commands/ls.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_ls.d
+
+grub_emu-commands_blocklist.o: commands/blocklist.c $(commands/blocklist.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_blocklist.d
+
+grub_emu-commands_hexdump.o: commands/hexdump.c $(commands/hexdump.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_hexdump.d
+
+grub_emu-lib_hexdump.o: lib/hexdump.c $(lib/hexdump.c_DEPENDENCIES)
+       $(CC) -Ilib -I$(srcdir)/lib $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-lib_hexdump.d
+
+grub_emu-commands_halt.o: commands/halt.c $(commands/halt.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_halt.d
+
+grub_emu-commands_reboot.o: commands/reboot.c $(commands/reboot.c_DEPENDENCIES)
+       $(CC) -Icommands -I$(srcdir)/commands $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-commands_reboot.d
+
+grub_emu-disk_loopback.o: disk/loopback.c $(disk/loopback.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_loopback.d
+
+grub_emu-fs_affs.o: fs/affs.c $(fs/affs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_affs.d
+
+grub_emu-fs_cpio.o: fs/cpio.c $(fs/cpio.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_cpio.d
+
+grub_emu-fs_ext2.o: fs/ext2.c $(fs/ext2.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ext2.d
+
+grub_emu-fs_fat.o: fs/fat.c $(fs/fat.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_fat.d
+
+grub_emu-fs_ext2.o: fs/ext2.c $(fs/ext2.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ext2.d
+
+grub_emu-fs_hfs.o: fs/hfs.c $(fs/hfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_hfs.d
+
+grub_emu-fs_hfsplus.o: fs/hfsplus.c $(fs/hfsplus.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_hfsplus.d
+
+grub_emu-fs_iso9660.o: fs/iso9660.c $(fs/iso9660.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_iso9660.d
+
+grub_emu-fs_udf.o: fs/udf.c $(fs/udf.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_udf.d
+
+grub_emu-fs_jfs.o: fs/jfs.c $(fs/jfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_jfs.d
+
+grub_emu-fs_minix.o: fs/minix.c $(fs/minix.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_minix.d
+
+grub_emu-fs_ntfs.o: fs/ntfs.c $(fs/ntfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ntfs.d
+
+grub_emu-fs_ntfscomp.o: fs/ntfscomp.c $(fs/ntfscomp.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ntfscomp.d
+
+grub_emu-fs_reiserfs.o: fs/reiserfs.c $(fs/reiserfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_reiserfs.d
+
+grub_emu-fs_sfs.o: fs/sfs.c $(fs/sfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_sfs.d
+
+grub_emu-fs_ufs.o: fs/ufs.c $(fs/ufs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_ufs.d
+
+grub_emu-fs_xfs.o: fs/xfs.c $(fs/xfs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_xfs.d
+
+grub_emu-fs_afs.o: fs/afs.c $(fs/afs.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_afs.d
+
+grub_emu-fs_tar.o: fs/tar.c $(fs/tar.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_tar.d
+
+grub_emu-io_gzio.o: io/gzio.c $(io/gzio.c_DEPENDENCIES)
+       $(CC) -Iio -I$(srcdir)/io $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-io_gzio.d
+
+grub_emu-kern_device.o: kern/device.c $(kern/device.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_device.d
+
+grub_emu-kern_disk.o: kern/disk.c $(kern/disk.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_disk.d
+
+grub_emu-kern_dl.o: kern/dl.c $(kern/dl.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_dl.d
+
+grub_emu-kern_elf.o: kern/elf.c $(kern/elf.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_elf.d
+
+grub_emu-kern_env.o: kern/env.c $(kern/env.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_env.d
+
+grub_emu-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_err.d
+
+grub_emu-kern_file.o: kern/file.c $(kern/file.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_file.d
+
+grub_emu-kern_fs.o: kern/fs.c $(kern/fs.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_fs.d
+
+grub_emu-kern_loader.o: kern/loader.c $(kern/loader.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_loader.d
+
+grub_emu-kern_main.o: kern/main.c $(kern/main.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_main.d
+
+grub_emu-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_misc.d
+
+grub_emu-kern_parser.o: kern/parser.c $(kern/parser.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_parser.d
+
+grub_emu-kern_partition.o: kern/partition.c $(kern/partition.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_partition.d
+
+grub_emu-kern_rescue.o: kern/rescue.c $(kern/rescue.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_rescue.d
+
+grub_emu-kern_term.o: kern/term.c $(kern/term.c_DEPENDENCIES)
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-kern_term.d
+
+grub_emu-fs_fshelp.o: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES)
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-fs_fshelp.d
+
+grub_emu-normal_arg.o: normal/arg.c $(normal/arg.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_arg.d
+
+grub_emu-normal_cmdline.o: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_cmdline.d
+
+grub_emu-normal_command.o: normal/command.c $(normal/command.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_command.d
+
+grub_emu-normal_completion.o: normal/completion.c $(normal/completion.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_completion.d
+
+grub_emu-normal_execute.o: normal/execute.c $(normal/execute.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_execute.d
+
+grub_emu-normal_function.o: normal/function.c $(normal/function.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_function.d
+
+grub_emu-normal_lexer.o: normal/lexer.c $(normal/lexer.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_lexer.d
+
+grub_emu-normal_main.o: normal/main.c $(normal/main.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_main.d
+
+grub_emu-normal_menu.o: normal/menu.c $(normal/menu.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu.d
+
+grub_emu-normal_menu_text.o: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu_text.d
+
+grub_emu-normal_menu_entry.o: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu_entry.d
+
+grub_emu-normal_menu_viewer.o: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_menu_viewer.d
+
+grub_emu-normal_misc.o: normal/misc.c $(normal/misc.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_misc.d
+
+grub_emu-normal_script.o: normal/script.c $(normal/script.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_script.d
+
+grub_emu-normal_color.o: normal/color.c $(normal/color.c_DEPENDENCIES)
+       $(CC) -Inormal -I$(srcdir)/normal $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-normal_color.d
+
+grub_emu-partmap_amiga.o: partmap/amiga.c $(partmap/amiga.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_amiga.d
+
+grub_emu-partmap_apple.o: partmap/apple.c $(partmap/apple.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_apple.d
+
+grub_emu-partmap_pc.o: partmap/pc.c $(partmap/pc.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_pc.d
+
+grub_emu-partmap_sun.o: partmap/sun.c $(partmap/sun.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_sun.d
+
+grub_emu-partmap_acorn.o: partmap/acorn.c $(partmap/acorn.c_DEPENDENCIES)
+       $(CC) -Ipartmap -I$(srcdir)/partmap $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-partmap_acorn.d
+
+grub_emu-util_console.o: util/console.c $(util/console.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_console.d
+
+grub_emu-util_hostfs.o: util/hostfs.c $(util/hostfs.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_hostfs.d
+
+grub_emu-util_grub_emu.o: util/grub-emu.c $(util/grub-emu.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_grub_emu.d
+
+grub_emu-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_misc.d
+
+grub_emu-util_hostdisk.o: util/hostdisk.c $(util/hostdisk.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_hostdisk.d
+
+grub_emu-util_getroot.o: util/getroot.c $(util/getroot.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_getroot.d
+
+grub_emu-util_powerpc_ieee1275_misc.o: util/powerpc/ieee1275/misc.c $(util/powerpc/ieee1275/misc.c_DEPENDENCIES)
+       $(CC) -Iutil/powerpc/ieee1275 -I$(srcdir)/util/powerpc/ieee1275 $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-util_powerpc_ieee1275_misc.d
+
+grub_emu-disk_raid.o: disk/raid.c $(disk/raid.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_raid.d
+
+grub_emu-disk_raid5_recover.o: disk/raid5_recover.c $(disk/raid5_recover.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_raid5_recover.d
+
+grub_emu-disk_raid6_recover.o: disk/raid6_recover.c $(disk/raid6_recover.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_raid6_recover.d
+
+grub_emu-disk_mdraid_linux.o: disk/mdraid_linux.c $(disk/mdraid_linux.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_mdraid_linux.d
+
+grub_emu-disk_dmraid_nvidia.o: disk/dmraid_nvidia.c $(disk/dmraid_nvidia.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_dmraid_nvidia.d
+
+grub_emu-disk_lvm.o: disk/lvm.c $(disk/lvm.c_DEPENDENCIES)
+       $(CC) -Idisk -I$(srcdir)/disk $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-disk_lvm.d
+
+grub_emu-grub_script_tab.o: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES)
+       $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-grub_script_tab.d
+
+grub_emu-grub_emu_init.o: grub_emu_init.c $(grub_emu_init.c_DEPENDENCIES)
+       $(CC) -I. -I$(srcdir)/. $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
+-include grub_emu-grub_emu_init.d
+
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+kernel_elf_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \
+       kern/ieee1275/ieee1275.c kern/main.c kern/device.c              \
+       kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c          \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c   \
+       kern/ieee1275/init.c                                            \
+       kern/ieee1275/mmap.c                                            \
+       term/ieee1275/ofconsole.c               \
+       kern/ieee1275/openfw.c disk/ieee1275/ofdisk.c           \
+       kern/parser.c kern/partition.c kern/env.c kern/powerpc/dl.c     \
+       kern/generic/millisleep.c kern/time.c                            \
+       symlist.c kern/powerpc/cache.S
+CLEANFILES += kernel.elf kernel_elf-kern_powerpc_ieee1275_startup.o kernel_elf-kern_ieee1275_cmain.o kernel_elf-kern_ieee1275_ieee1275.o kernel_elf-kern_main.o kernel_elf-kern_device.o kernel_elf-kern_disk.o kernel_elf-kern_dl.o kernel_elf-kern_err.o kernel_elf-kern_file.o kernel_elf-kern_fs.o kernel_elf-kern_misc.o kernel_elf-kern_mm.o kernel_elf-kern_loader.o kernel_elf-kern_rescue.o kernel_elf-kern_term.o kernel_elf-kern_ieee1275_init.o kernel_elf-kern_ieee1275_mmap.o kernel_elf-term_ieee1275_ofconsole.o kernel_elf-kern_ieee1275_openfw.o kernel_elf-disk_ieee1275_ofdisk.o kernel_elf-kern_parser.o kernel_elf-kern_partition.o kernel_elf-kern_env.o kernel_elf-kern_powerpc_dl.o kernel_elf-kern_generic_millisleep.o kernel_elf-kern_time.o kernel_elf-symlist.o kernel_elf-kern_powerpc_cache.o
+MOSTLYCLEANFILES += kernel_elf-kern_powerpc_ieee1275_startup.d kernel_elf-kern_ieee1275_cmain.d kernel_elf-kern_ieee1275_ieee1275.d kernel_elf-kern_main.d kernel_elf-kern_device.d kernel_elf-kern_disk.d kernel_elf-kern_dl.d kernel_elf-kern_err.d kernel_elf-kern_file.d kernel_elf-kern_fs.d kernel_elf-kern_misc.d kernel_elf-kern_mm.d kernel_elf-kern_loader.d kernel_elf-kern_rescue.d kernel_elf-kern_term.d kernel_elf-kern_ieee1275_init.d kernel_elf-kern_ieee1275_mmap.d kernel_elf-term_ieee1275_ofconsole.d kernel_elf-kern_ieee1275_openfw.d kernel_elf-disk_ieee1275_ofdisk.d kernel_elf-kern_parser.d kernel_elf-kern_partition.d kernel_elf-kern_env.d kernel_elf-kern_powerpc_dl.d kernel_elf-kern_generic_millisleep.d kernel_elf-kern_time.d kernel_elf-symlist.d kernel_elf-kern_powerpc_cache.d
+
+kernel.elf: $(kernel_elf_DEPENDENCIES) kernel_elf-kern_powerpc_ieee1275_startup.o kernel_elf-kern_ieee1275_cmain.o kernel_elf-kern_ieee1275_ieee1275.o kernel_elf-kern_main.o kernel_elf-kern_device.o kernel_elf-kern_disk.o kernel_elf-kern_dl.o kernel_elf-kern_err.o kernel_elf-kern_file.o kernel_elf-kern_fs.o kernel_elf-kern_misc.o kernel_elf-kern_mm.o kernel_elf-kern_loader.o kernel_elf-kern_rescue.o kernel_elf-kern_term.o kernel_elf-kern_ieee1275_init.o kernel_elf-kern_ieee1275_mmap.o kernel_elf-term_ieee1275_ofconsole.o kernel_elf-kern_ieee1275_openfw.o kernel_elf-disk_ieee1275_ofdisk.o kernel_elf-kern_parser.o kernel_elf-kern_partition.o kernel_elf-kern_env.o kernel_elf-kern_powerpc_dl.o kernel_elf-kern_generic_millisleep.o kernel_elf-kern_time.o kernel_elf-symlist.o kernel_elf-kern_powerpc_cache.o
+       $(TARGET_CC) -o $@ kernel_elf-kern_powerpc_ieee1275_startup.o kernel_elf-kern_ieee1275_cmain.o kernel_elf-kern_ieee1275_ieee1275.o kernel_elf-kern_main.o kernel_elf-kern_device.o kernel_elf-kern_disk.o kernel_elf-kern_dl.o kernel_elf-kern_err.o kernel_elf-kern_file.o kernel_elf-kern_fs.o kernel_elf-kern_misc.o kernel_elf-kern_mm.o kernel_elf-kern_loader.o kernel_elf-kern_rescue.o kernel_elf-kern_term.o kernel_elf-kern_ieee1275_init.o kernel_elf-kern_ieee1275_mmap.o kernel_elf-term_ieee1275_ofconsole.o kernel_elf-kern_ieee1275_openfw.o kernel_elf-disk_ieee1275_ofdisk.o kernel_elf-kern_parser.o kernel_elf-kern_partition.o kernel_elf-kern_env.o kernel_elf-kern_powerpc_dl.o kernel_elf-kern_generic_millisleep.o kernel_elf-kern_time.o kernel_elf-symlist.o kernel_elf-kern_powerpc_cache.o $(TARGET_LDFLAGS) $(kernel_elf_LDFLAGS)
+
+kernel_elf-kern_powerpc_ieee1275_startup.o: kern/powerpc/ieee1275/startup.S $(kern/powerpc/ieee1275/startup.S_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/powerpc/ieee1275 -I$(srcdir)/kern/powerpc/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_powerpc_ieee1275_startup.d
+
+kernel_elf-kern_ieee1275_cmain.o: kern/ieee1275/cmain.c $(kern/ieee1275/cmain.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/ieee1275 -I$(srcdir)/kern/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_ieee1275_cmain.d
+
+kernel_elf-kern_ieee1275_ieee1275.o: kern/ieee1275/ieee1275.c $(kern/ieee1275/ieee1275.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/ieee1275 -I$(srcdir)/kern/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_ieee1275_ieee1275.d
+
+kernel_elf-kern_main.o: kern/main.c $(kern/main.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_main.d
+
+kernel_elf-kern_device.o: kern/device.c $(kern/device.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_device.d
+
+kernel_elf-kern_disk.o: kern/disk.c $(kern/disk.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_disk.d
+
+kernel_elf-kern_dl.o: kern/dl.c $(kern/dl.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_dl.d
+
+kernel_elf-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_err.d
+
+kernel_elf-kern_file.o: kern/file.c $(kern/file.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_file.d
+
+kernel_elf-kern_fs.o: kern/fs.c $(kern/fs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_fs.d
+
+kernel_elf-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_misc.d
+
+kernel_elf-kern_mm.o: kern/mm.c $(kern/mm.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_mm.d
+
+kernel_elf-kern_loader.o: kern/loader.c $(kern/loader.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_loader.d
+
+kernel_elf-kern_rescue.o: kern/rescue.c $(kern/rescue.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_rescue.d
+
+kernel_elf-kern_term.o: kern/term.c $(kern/term.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_term.d
+
+kernel_elf-kern_ieee1275_init.o: kern/ieee1275/init.c $(kern/ieee1275/init.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/ieee1275 -I$(srcdir)/kern/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_ieee1275_init.d
+
+kernel_elf-kern_ieee1275_mmap.o: kern/ieee1275/mmap.c $(kern/ieee1275/mmap.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/ieee1275 -I$(srcdir)/kern/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_ieee1275_mmap.d
+
+kernel_elf-term_ieee1275_ofconsole.o: term/ieee1275/ofconsole.c $(term/ieee1275/ofconsole.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/ieee1275 -I$(srcdir)/term/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-term_ieee1275_ofconsole.d
+
+kernel_elf-kern_ieee1275_openfw.o: kern/ieee1275/openfw.c $(kern/ieee1275/openfw.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/ieee1275 -I$(srcdir)/kern/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_ieee1275_openfw.d
+
+kernel_elf-disk_ieee1275_ofdisk.o: disk/ieee1275/ofdisk.c $(disk/ieee1275/ofdisk.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk/ieee1275 -I$(srcdir)/disk/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-disk_ieee1275_ofdisk.d
+
+kernel_elf-kern_parser.o: kern/parser.c $(kern/parser.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_parser.d
+
+kernel_elf-kern_partition.o: kern/partition.c $(kern/partition.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_partition.d
+
+kernel_elf-kern_env.o: kern/env.c $(kern/env.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_env.d
+
+kernel_elf-kern_powerpc_dl.o: kern/powerpc/dl.c $(kern/powerpc/dl.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/powerpc -I$(srcdir)/kern/powerpc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_powerpc_dl.d
+
+kernel_elf-kern_generic_millisleep.o: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_generic_millisleep.d
+
+kernel_elf-kern_time.o: kern/time.c $(kern/time.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_time.d
+
+kernel_elf-symlist.o: symlist.c $(symlist.c_DEPENDENCIES)
+       $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-symlist.d
+
+kernel_elf-kern_powerpc_cache.o: kern/powerpc/cache.S $(kern/powerpc/cache.S_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/powerpc -I$(srcdir)/kern/powerpc $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_powerpc_cache.d
+
+kernel_elf_HEADERS = grub/powerpc/ieee1275/ieee1275.h
+kernel_elf_CFLAGS = $(COMMON_CFLAGS)
+kernel_elf_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_elf_LDFLAGS = $(COMMON_LDFLAGS) -static-libgcc -lgcc \
+       -Wl,-N,-S,-Ttext,0x200000,-Bstatic
+
+# Scripts.
+sbin_SCRIPTS = grub-install
+bin_SCRIPTS = grub-mkrescue
+
+# For grub-install.
+grub_install_SOURCES = util/ieee1275/grub-install.in
+CLEANFILES += grub-install
+
+grub-install: util/ieee1275/grub-install.in $(util/ieee1275/grub-install.in_DEPENDENCIES) config.status
+       ./config.status --file=grub-install:util/ieee1275/grub-install.in
+       chmod +x $@
+
+
+# For grub-mkrescue.
+grub_mkrescue_SOURCES = util/powerpc/ieee1275/grub-mkrescue.in
+CLEANFILES += grub-mkrescue
+
+grub-mkrescue: util/powerpc/ieee1275/grub-mkrescue.in $(util/powerpc/ieee1275/grub-mkrescue.in_DEPENDENCIES) config.status
+       ./config.status --file=grub-mkrescue:util/powerpc/ieee1275/grub-mkrescue.in
+       chmod +x $@
+
+
+# Modules.
+pkglib_MODULES = halt.mod \
+       _linux.mod \
+       linux.mod \
+       normal.mod \
+       reboot.mod \
+       suspend.mod \
+        _multiboot.mod \
+        multiboot.mod \
+       memdisk.mod \
+       lsmmap.mod
+
+# For _linux.mod.
+_linux_mod_SOURCES = loader/powerpc/ieee1275/linux.c
+CLEANFILES += _linux.mod mod-_linux.o mod-_linux.c pre-_linux.o _linux_mod-loader_powerpc_ieee1275_linux.o und-_linux.lst
+ifneq ($(_linux_mod_EXPORTS),no)
+CLEANFILES += def-_linux.lst
+DEFSYMFILES += def-_linux.lst
+endif
+MOSTLYCLEANFILES += _linux_mod-loader_powerpc_ieee1275_linux.d
+UNDSYMFILES += und-_linux.lst
+
+_linux.mod: pre-_linux.o mod-_linux.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(_linux_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-_linux.o mod-_linux.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-_linux.o: $(_linux_mod_DEPENDENCIES) _linux_mod-loader_powerpc_ieee1275_linux.o
+       -rm -f $@
+       $(TARGET_CC) $(_linux_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ _linux_mod-loader_powerpc_ieee1275_linux.o
+
+mod-_linux.o: mod-_linux.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -c -o $@ $<
+
+mod-_linux.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '_linux' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(_linux_mod_EXPORTS),no)
+def-_linux.lst: pre-_linux.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _linux/' > $@
+endif
+
+und-_linux.lst: pre-_linux.o
+       echo '_linux' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+_linux_mod-loader_powerpc_ieee1275_linux.o: loader/powerpc/ieee1275/linux.c $(loader/powerpc/ieee1275/linux.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/powerpc/ieee1275 -I$(srcdir)/loader/powerpc/ieee1275 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -MD -c -o $@ $<
+-include _linux_mod-loader_powerpc_ieee1275_linux.d
+
+CLEANFILES += cmd-_linux_mod-loader_powerpc_ieee1275_linux.lst fs-_linux_mod-loader_powerpc_ieee1275_linux.lst partmap-_linux_mod-loader_powerpc_ieee1275_linux.lst
+COMMANDFILES += cmd-_linux_mod-loader_powerpc_ieee1275_linux.lst
+FSFILES += fs-_linux_mod-loader_powerpc_ieee1275_linux.lst
+PARTMAPFILES += partmap-_linux_mod-loader_powerpc_ieee1275_linux.lst
+
+cmd-_linux_mod-loader_powerpc_ieee1275_linux.lst: loader/powerpc/ieee1275/linux.c $(loader/powerpc/ieee1275/linux.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/powerpc/ieee1275 -I$(srcdir)/loader/powerpc/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh _linux > $@ || (rm -f $@; exit 1)
+
+fs-_linux_mod-loader_powerpc_ieee1275_linux.lst: loader/powerpc/ieee1275/linux.c $(loader/powerpc/ieee1275/linux.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/powerpc/ieee1275 -I$(srcdir)/loader/powerpc/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh _linux > $@ || (rm -f $@; exit 1)
+
+partmap-_linux_mod-loader_powerpc_ieee1275_linux.lst: loader/powerpc/ieee1275/linux.c $(loader/powerpc/ieee1275/linux.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/powerpc/ieee1275 -I$(srcdir)/loader/powerpc/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh _linux > $@ || (rm -f $@; exit 1)
+
+
+_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/powerpc/ieee1275/linux_normal.c
+CLEANFILES += linux.mod mod-linux.o mod-linux.c pre-linux.o linux_mod-loader_powerpc_ieee1275_linux_normal.o und-linux.lst
+ifneq ($(linux_mod_EXPORTS),no)
+CLEANFILES += def-linux.lst
+DEFSYMFILES += def-linux.lst
+endif
+MOSTLYCLEANFILES += linux_mod-loader_powerpc_ieee1275_linux_normal.d
+UNDSYMFILES += und-linux.lst
+
+linux.mod: pre-linux.o mod-linux.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(linux_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-linux.o mod-linux.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-linux.o: $(linux_mod_DEPENDENCIES) linux_mod-loader_powerpc_ieee1275_linux_normal.o
+       -rm -f $@
+       $(TARGET_CC) $(linux_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ linux_mod-loader_powerpc_ieee1275_linux_normal.o
+
+mod-linux.o: mod-linux.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -c -o $@ $<
+
+mod-linux.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'linux' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(linux_mod_EXPORTS),no)
+def-linux.lst: pre-linux.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 linux/' > $@
+endif
+
+und-linux.lst: pre-linux.o
+       echo 'linux' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+linux_mod-loader_powerpc_ieee1275_linux_normal.o: loader/powerpc/ieee1275/linux_normal.c $(loader/powerpc/ieee1275/linux_normal.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/powerpc/ieee1275 -I$(srcdir)/loader/powerpc/ieee1275 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -MD -c -o $@ $<
+-include linux_mod-loader_powerpc_ieee1275_linux_normal.d
+
+CLEANFILES += cmd-linux_mod-loader_powerpc_ieee1275_linux_normal.lst fs-linux_mod-loader_powerpc_ieee1275_linux_normal.lst partmap-linux_mod-loader_powerpc_ieee1275_linux_normal.lst
+COMMANDFILES += cmd-linux_mod-loader_powerpc_ieee1275_linux_normal.lst
+FSFILES += fs-linux_mod-loader_powerpc_ieee1275_linux_normal.lst
+PARTMAPFILES += partmap-linux_mod-loader_powerpc_ieee1275_linux_normal.lst
+
+cmd-linux_mod-loader_powerpc_ieee1275_linux_normal.lst: loader/powerpc/ieee1275/linux_normal.c $(loader/powerpc/ieee1275/linux_normal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/powerpc/ieee1275 -I$(srcdir)/loader/powerpc/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh linux > $@ || (rm -f $@; exit 1)
+
+fs-linux_mod-loader_powerpc_ieee1275_linux_normal.lst: loader/powerpc/ieee1275/linux_normal.c $(loader/powerpc/ieee1275/linux_normal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/powerpc/ieee1275 -I$(srcdir)/loader/powerpc/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh linux > $@ || (rm -f $@; exit 1)
+
+partmap-linux_mod-loader_powerpc_ieee1275_linux_normal.lst: loader/powerpc/ieee1275/linux_normal.c $(loader/powerpc/ieee1275/linux_normal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/powerpc/ieee1275 -I$(srcdir)/loader/powerpc/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh linux > $@ || (rm -f $@; exit 1)
+
+
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+#
+# Only arch dependant part of normal.mod will be here. Common part for
+# all architecures of normal.mod is at start and should be kept at sync
+# with other makefiles.
+# 
+# Please put arch dependant part of normal.mod at the end of list to
+# keep it simpler to update to different architectures.
+#
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/color.c                                                  \
+       normal/menu_viewer.c normal/menu_entry.c                        \
+       normal/misc.c grub_script.tab.c                                 \
+       normal/script.c                                                 \
+       normal/powerpc/setjmp.S
+CLEANFILES += normal.mod mod-normal.o mod-normal.c pre-normal.o normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_powerpc_setjmp.o und-normal.lst
+ifneq ($(normal_mod_EXPORTS),no)
+CLEANFILES += def-normal.lst
+DEFSYMFILES += def-normal.lst
+endif
+MOSTLYCLEANFILES += normal_mod-normal_arg.d normal_mod-normal_cmdline.d normal_mod-normal_command.d normal_mod-normal_completion.d normal_mod-normal_execute.d normal_mod-normal_function.d normal_mod-normal_lexer.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_menu_text.d normal_mod-normal_color.d normal_mod-normal_menu_viewer.d normal_mod-normal_menu_entry.d normal_mod-normal_misc.d normal_mod-grub_script_tab.d normal_mod-normal_script.d normal_mod-normal_powerpc_setjmp.d
+UNDSYMFILES += und-normal.lst
+
+normal.mod: pre-normal.o mod-normal.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(normal_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-normal.o mod-normal.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-normal.o: $(normal_mod_DEPENDENCIES) normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_powerpc_setjmp.o
+       -rm -f $@
+       $(TARGET_CC) $(normal_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_powerpc_setjmp.o
+
+mod-normal.o: mod-normal.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
+
+mod-normal.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'normal' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(normal_mod_EXPORTS),no)
+def-normal.lst: pre-normal.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 normal/' > $@
+endif
+
+und-normal.lst: pre-normal.o
+       echo 'normal' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+normal_mod-normal_arg.o: normal/arg.c $(normal/arg.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_arg.d
+
+CLEANFILES += cmd-normal_mod-normal_arg.lst fs-normal_mod-normal_arg.lst partmap-normal_mod-normal_arg.lst
+COMMANDFILES += cmd-normal_mod-normal_arg.lst
+FSFILES += fs-normal_mod-normal_arg.lst
+PARTMAPFILES += partmap-normal_mod-normal_arg.lst
+
+cmd-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_cmdline.o: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_cmdline.d
+
+CLEANFILES += cmd-normal_mod-normal_cmdline.lst fs-normal_mod-normal_cmdline.lst partmap-normal_mod-normal_cmdline.lst
+COMMANDFILES += cmd-normal_mod-normal_cmdline.lst
+FSFILES += fs-normal_mod-normal_cmdline.lst
+PARTMAPFILES += partmap-normal_mod-normal_cmdline.lst
+
+cmd-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_command.o: normal/command.c $(normal/command.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_command.d
+
+CLEANFILES += cmd-normal_mod-normal_command.lst fs-normal_mod-normal_command.lst partmap-normal_mod-normal_command.lst
+COMMANDFILES += cmd-normal_mod-normal_command.lst
+FSFILES += fs-normal_mod-normal_command.lst
+PARTMAPFILES += partmap-normal_mod-normal_command.lst
+
+cmd-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_completion.o: normal/completion.c $(normal/completion.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_completion.d
+
+CLEANFILES += cmd-normal_mod-normal_completion.lst fs-normal_mod-normal_completion.lst partmap-normal_mod-normal_completion.lst
+COMMANDFILES += cmd-normal_mod-normal_completion.lst
+FSFILES += fs-normal_mod-normal_completion.lst
+PARTMAPFILES += partmap-normal_mod-normal_completion.lst
+
+cmd-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_execute.o: normal/execute.c $(normal/execute.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_execute.d
+
+CLEANFILES += cmd-normal_mod-normal_execute.lst fs-normal_mod-normal_execute.lst partmap-normal_mod-normal_execute.lst
+COMMANDFILES += cmd-normal_mod-normal_execute.lst
+FSFILES += fs-normal_mod-normal_execute.lst
+PARTMAPFILES += partmap-normal_mod-normal_execute.lst
+
+cmd-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_function.o: normal/function.c $(normal/function.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_function.d
+
+CLEANFILES += cmd-normal_mod-normal_function.lst fs-normal_mod-normal_function.lst partmap-normal_mod-normal_function.lst
+COMMANDFILES += cmd-normal_mod-normal_function.lst
+FSFILES += fs-normal_mod-normal_function.lst
+PARTMAPFILES += partmap-normal_mod-normal_function.lst
+
+cmd-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_lexer.o: normal/lexer.c $(normal/lexer.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_lexer.d
+
+CLEANFILES += cmd-normal_mod-normal_lexer.lst fs-normal_mod-normal_lexer.lst partmap-normal_mod-normal_lexer.lst
+COMMANDFILES += cmd-normal_mod-normal_lexer.lst
+FSFILES += fs-normal_mod-normal_lexer.lst
+PARTMAPFILES += partmap-normal_mod-normal_lexer.lst
+
+cmd-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_main.o: normal/main.c $(normal/main.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_main.d
+
+CLEANFILES += cmd-normal_mod-normal_main.lst fs-normal_mod-normal_main.lst partmap-normal_mod-normal_main.lst
+COMMANDFILES += cmd-normal_mod-normal_main.lst
+FSFILES += fs-normal_mod-normal_main.lst
+PARTMAPFILES += partmap-normal_mod-normal_main.lst
+
+cmd-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu.o: normal/menu.c $(normal/menu.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu.d
+
+CLEANFILES += cmd-normal_mod-normal_menu.lst fs-normal_mod-normal_menu.lst partmap-normal_mod-normal_menu.lst
+COMMANDFILES += cmd-normal_mod-normal_menu.lst
+FSFILES += fs-normal_mod-normal_menu.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu.lst
+
+cmd-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_text.o: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_text.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_text.lst fs-normal_mod-normal_menu_text.lst partmap-normal_mod-normal_menu_text.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_text.lst
+FSFILES += fs-normal_mod-normal_menu_text.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_text.lst
+
+cmd-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_color.o: normal/color.c $(normal/color.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_color.d
+
+CLEANFILES += cmd-normal_mod-normal_color.lst fs-normal_mod-normal_color.lst partmap-normal_mod-normal_color.lst
+COMMANDFILES += cmd-normal_mod-normal_color.lst
+FSFILES += fs-normal_mod-normal_color.lst
+PARTMAPFILES += partmap-normal_mod-normal_color.lst
+
+cmd-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_viewer.o: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_viewer.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_viewer.lst fs-normal_mod-normal_menu_viewer.lst partmap-normal_mod-normal_menu_viewer.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_viewer.lst
+FSFILES += fs-normal_mod-normal_menu_viewer.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_viewer.lst
+
+cmd-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_entry.o: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_entry.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_entry.lst fs-normal_mod-normal_menu_entry.lst partmap-normal_mod-normal_menu_entry.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_entry.lst
+FSFILES += fs-normal_mod-normal_menu_entry.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_entry.lst
+
+cmd-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_misc.o: normal/misc.c $(normal/misc.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_misc.d
+
+CLEANFILES += cmd-normal_mod-normal_misc.lst fs-normal_mod-normal_misc.lst partmap-normal_mod-normal_misc.lst
+COMMANDFILES += cmd-normal_mod-normal_misc.lst
+FSFILES += fs-normal_mod-normal_misc.lst
+PARTMAPFILES += partmap-normal_mod-normal_misc.lst
+
+cmd-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-grub_script_tab.o: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES)
+       $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-grub_script_tab.d
+
+CLEANFILES += cmd-normal_mod-grub_script_tab.lst fs-normal_mod-grub_script_tab.lst partmap-normal_mod-grub_script_tab.lst
+COMMANDFILES += cmd-normal_mod-grub_script_tab.lst
+FSFILES += fs-normal_mod-grub_script_tab.lst
+PARTMAPFILES += partmap-normal_mod-grub_script_tab.lst
+
+cmd-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_script.o: normal/script.c $(normal/script.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_script.d
+
+CLEANFILES += cmd-normal_mod-normal_script.lst fs-normal_mod-normal_script.lst partmap-normal_mod-normal_script.lst
+COMMANDFILES += cmd-normal_mod-normal_script.lst
+FSFILES += fs-normal_mod-normal_script.lst
+PARTMAPFILES += partmap-normal_mod-normal_script.lst
+
+cmd-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_powerpc_setjmp.o: normal/powerpc/setjmp.S $(normal/powerpc/setjmp.S_DEPENDENCIES)
+       $(TARGET_CC) -Inormal/powerpc -I$(srcdir)/normal/powerpc $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_powerpc_setjmp.d
+
+CLEANFILES += cmd-normal_mod-normal_powerpc_setjmp.lst fs-normal_mod-normal_powerpc_setjmp.lst partmap-normal_mod-normal_powerpc_setjmp.lst
+COMMANDFILES += cmd-normal_mod-normal_powerpc_setjmp.lst
+FSFILES += fs-normal_mod-normal_powerpc_setjmp.lst
+PARTMAPFILES += partmap-normal_mod-normal_powerpc_setjmp.lst
+
+cmd-normal_mod-normal_powerpc_setjmp.lst: normal/powerpc/setjmp.S $(normal/powerpc/setjmp.S_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal/powerpc -I$(srcdir)/normal/powerpc $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_powerpc_setjmp.lst: normal/powerpc/setjmp.S $(normal/powerpc/setjmp.S_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal/powerpc -I$(srcdir)/normal/powerpc $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<       | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_powerpc_setjmp.lst: normal/powerpc/setjmp.S $(normal/powerpc/setjmp.S_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal/powerpc -I$(srcdir)/normal/powerpc $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For suspend.mod
+suspend_mod_SOURCES = commands/ieee1275/suspend.c
+CLEANFILES += suspend.mod mod-suspend.o mod-suspend.c pre-suspend.o suspend_mod-commands_ieee1275_suspend.o und-suspend.lst
+ifneq ($(suspend_mod_EXPORTS),no)
+CLEANFILES += def-suspend.lst
+DEFSYMFILES += def-suspend.lst
+endif
+MOSTLYCLEANFILES += suspend_mod-commands_ieee1275_suspend.d
+UNDSYMFILES += und-suspend.lst
+
+suspend.mod: pre-suspend.o mod-suspend.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(suspend_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-suspend.o mod-suspend.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-suspend.o: $(suspend_mod_DEPENDENCIES) suspend_mod-commands_ieee1275_suspend.o
+       -rm -f $@
+       $(TARGET_CC) $(suspend_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ suspend_mod-commands_ieee1275_suspend.o
+
+mod-suspend.o: mod-suspend.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(suspend_mod_CFLAGS) -c -o $@ $<
+
+mod-suspend.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'suspend' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(suspend_mod_EXPORTS),no)
+def-suspend.lst: pre-suspend.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 suspend/' > $@
+endif
+
+und-suspend.lst: pre-suspend.o
+       echo 'suspend' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+suspend_mod-commands_ieee1275_suspend.o: commands/ieee1275/suspend.c $(commands/ieee1275/suspend.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands/ieee1275 -I$(srcdir)/commands/ieee1275 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(suspend_mod_CFLAGS) -MD -c -o $@ $<
+-include suspend_mod-commands_ieee1275_suspend.d
+
+CLEANFILES += cmd-suspend_mod-commands_ieee1275_suspend.lst fs-suspend_mod-commands_ieee1275_suspend.lst partmap-suspend_mod-commands_ieee1275_suspend.lst
+COMMANDFILES += cmd-suspend_mod-commands_ieee1275_suspend.lst
+FSFILES += fs-suspend_mod-commands_ieee1275_suspend.lst
+PARTMAPFILES += partmap-suspend_mod-commands_ieee1275_suspend.lst
+
+cmd-suspend_mod-commands_ieee1275_suspend.lst: commands/ieee1275/suspend.c $(commands/ieee1275/suspend.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands/ieee1275 -I$(srcdir)/commands/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(suspend_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh suspend > $@ || (rm -f $@; exit 1)
+
+fs-suspend_mod-commands_ieee1275_suspend.lst: commands/ieee1275/suspend.c $(commands/ieee1275/suspend.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands/ieee1275 -I$(srcdir)/commands/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(suspend_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh suspend > $@ || (rm -f $@; exit 1)
+
+partmap-suspend_mod-commands_ieee1275_suspend.lst: commands/ieee1275/suspend.c $(commands/ieee1275/suspend.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands/ieee1275 -I$(srcdir)/commands/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(suspend_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh suspend > $@ || (rm -f $@; exit 1)
+
+
+suspend_mod_CFLAGS = $(COMMON_CFLAGS)
+suspend_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reboot.mod
+reboot_mod_SOURCES = commands/reboot.c
+CLEANFILES += reboot.mod mod-reboot.o mod-reboot.c pre-reboot.o reboot_mod-commands_reboot.o und-reboot.lst
+ifneq ($(reboot_mod_EXPORTS),no)
+CLEANFILES += def-reboot.lst
+DEFSYMFILES += def-reboot.lst
+endif
+MOSTLYCLEANFILES += reboot_mod-commands_reboot.d
+UNDSYMFILES += und-reboot.lst
+
+reboot.mod: pre-reboot.o mod-reboot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(reboot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-reboot.o mod-reboot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-reboot.o: $(reboot_mod_DEPENDENCIES) reboot_mod-commands_reboot.o
+       -rm -f $@
+       $(TARGET_CC) $(reboot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ reboot_mod-commands_reboot.o
+
+mod-reboot.o: mod-reboot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -c -o $@ $<
+
+mod-reboot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'reboot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(reboot_mod_EXPORTS),no)
+def-reboot.lst: pre-reboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 reboot/' > $@
+endif
+
+und-reboot.lst: pre-reboot.o
+       echo 'reboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+reboot_mod-commands_reboot.o: commands/reboot.c $(commands/reboot.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -MD -c -o $@ $<
+-include reboot_mod-commands_reboot.d
+
+CLEANFILES += cmd-reboot_mod-commands_reboot.lst fs-reboot_mod-commands_reboot.lst partmap-reboot_mod-commands_reboot.lst
+COMMANDFILES += cmd-reboot_mod-commands_reboot.lst
+FSFILES += fs-reboot_mod-commands_reboot.lst
+PARTMAPFILES += partmap-reboot_mod-commands_reboot.lst
+
+cmd-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh reboot > $@ || (rm -f $@; exit 1)
+
+fs-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh reboot > $@ || (rm -f $@; exit 1)
+
+partmap-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh reboot > $@ || (rm -f $@; exit 1)
+
+
+reboot_mod_CFLAGS = $(COMMON_CFLAGS)
+reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For halt.mod
+halt_mod_SOURCES = commands/halt.c
+CLEANFILES += halt.mod mod-halt.o mod-halt.c pre-halt.o halt_mod-commands_halt.o und-halt.lst
+ifneq ($(halt_mod_EXPORTS),no)
+CLEANFILES += def-halt.lst
+DEFSYMFILES += def-halt.lst
+endif
+MOSTLYCLEANFILES += halt_mod-commands_halt.d
+UNDSYMFILES += und-halt.lst
+
+halt.mod: pre-halt.o mod-halt.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(halt_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-halt.o mod-halt.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-halt.o: $(halt_mod_DEPENDENCIES) halt_mod-commands_halt.o
+       -rm -f $@
+       $(TARGET_CC) $(halt_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ halt_mod-commands_halt.o
+
+mod-halt.o: mod-halt.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -c -o $@ $<
+
+mod-halt.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'halt' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(halt_mod_EXPORTS),no)
+def-halt.lst: pre-halt.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 halt/' > $@
+endif
+
+und-halt.lst: pre-halt.o
+       echo 'halt' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+halt_mod-commands_halt.o: commands/halt.c $(commands/halt.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -MD -c -o $@ $<
+-include halt_mod-commands_halt.d
+
+CLEANFILES += cmd-halt_mod-commands_halt.lst fs-halt_mod-commands_halt.lst partmap-halt_mod-commands_halt.lst
+COMMANDFILES += cmd-halt_mod-commands_halt.lst
+FSFILES += fs-halt_mod-commands_halt.lst
+PARTMAPFILES += partmap-halt_mod-commands_halt.lst
+
+cmd-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh halt > $@ || (rm -f $@; exit 1)
+
+fs-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh halt > $@ || (rm -f $@; exit 1)
+
+partmap-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh halt > $@ || (rm -f $@; exit 1)
+
+
+halt_mod_CFLAGS = $(COMMON_CFLAGS)
+halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _multiboot.mod
+_multiboot_mod_SOURCES = loader/ieee1275/multiboot2.c \
+                         loader/multiboot2.c \
+                         loader/multiboot_loader.c
+CLEANFILES += _multiboot.mod mod-_multiboot.o mod-_multiboot.c pre-_multiboot.o _multiboot_mod-loader_ieee1275_multiboot2.o _multiboot_mod-loader_multiboot2.o _multiboot_mod-loader_multiboot_loader.o und-_multiboot.lst
+ifneq ($(_multiboot_mod_EXPORTS),no)
+CLEANFILES += def-_multiboot.lst
+DEFSYMFILES += def-_multiboot.lst
+endif
+MOSTLYCLEANFILES += _multiboot_mod-loader_ieee1275_multiboot2.d _multiboot_mod-loader_multiboot2.d _multiboot_mod-loader_multiboot_loader.d
+UNDSYMFILES += und-_multiboot.lst
+
+_multiboot.mod: pre-_multiboot.o mod-_multiboot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(_multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-_multiboot.o mod-_multiboot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-_multiboot.o: $(_multiboot_mod_DEPENDENCIES) _multiboot_mod-loader_ieee1275_multiboot2.o _multiboot_mod-loader_multiboot2.o _multiboot_mod-loader_multiboot_loader.o
+       -rm -f $@
+       $(TARGET_CC) $(_multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ _multiboot_mod-loader_ieee1275_multiboot2.o _multiboot_mod-loader_multiboot2.o _multiboot_mod-loader_multiboot_loader.o
+
+mod-_multiboot.o: mod-_multiboot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -c -o $@ $<
+
+mod-_multiboot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '_multiboot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(_multiboot_mod_EXPORTS),no)
+def-_multiboot.lst: pre-_multiboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _multiboot/' > $@
+endif
+
+und-_multiboot.lst: pre-_multiboot.o
+       echo '_multiboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+_multiboot_mod-loader_ieee1275_multiboot2.o: loader/ieee1275/multiboot2.c $(loader/ieee1275/multiboot2.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/ieee1275 -I$(srcdir)/loader/ieee1275 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include _multiboot_mod-loader_ieee1275_multiboot2.d
+
+CLEANFILES += cmd-_multiboot_mod-loader_ieee1275_multiboot2.lst fs-_multiboot_mod-loader_ieee1275_multiboot2.lst partmap-_multiboot_mod-loader_ieee1275_multiboot2.lst
+COMMANDFILES += cmd-_multiboot_mod-loader_ieee1275_multiboot2.lst
+FSFILES += fs-_multiboot_mod-loader_ieee1275_multiboot2.lst
+PARTMAPFILES += partmap-_multiboot_mod-loader_ieee1275_multiboot2.lst
+
+cmd-_multiboot_mod-loader_ieee1275_multiboot2.lst: loader/ieee1275/multiboot2.c $(loader/ieee1275/multiboot2.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/ieee1275 -I$(srcdir)/loader/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+fs-_multiboot_mod-loader_ieee1275_multiboot2.lst: loader/ieee1275/multiboot2.c $(loader/ieee1275/multiboot2.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/ieee1275 -I$(srcdir)/loader/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-_multiboot_mod-loader_ieee1275_multiboot2.lst: loader/ieee1275/multiboot2.c $(loader/ieee1275/multiboot2.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/ieee1275 -I$(srcdir)/loader/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+
+_multiboot_mod-loader_multiboot2.o: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include _multiboot_mod-loader_multiboot2.d
+
+CLEANFILES += cmd-_multiboot_mod-loader_multiboot2.lst fs-_multiboot_mod-loader_multiboot2.lst partmap-_multiboot_mod-loader_multiboot2.lst
+COMMANDFILES += cmd-_multiboot_mod-loader_multiboot2.lst
+FSFILES += fs-_multiboot_mod-loader_multiboot2.lst
+PARTMAPFILES += partmap-_multiboot_mod-loader_multiboot2.lst
+
+cmd-_multiboot_mod-loader_multiboot2.lst: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+fs-_multiboot_mod-loader_multiboot2.lst: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-_multiboot_mod-loader_multiboot2.lst: loader/multiboot2.c $(loader/multiboot2.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+
+_multiboot_mod-loader_multiboot_loader.o: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include _multiboot_mod-loader_multiboot_loader.d
+
+CLEANFILES += cmd-_multiboot_mod-loader_multiboot_loader.lst fs-_multiboot_mod-loader_multiboot_loader.lst partmap-_multiboot_mod-loader_multiboot_loader.lst
+COMMANDFILES += cmd-_multiboot_mod-loader_multiboot_loader.lst
+FSFILES += fs-_multiboot_mod-loader_multiboot_loader.lst
+PARTMAPFILES += partmap-_multiboot_mod-loader_multiboot_loader.lst
+
+cmd-_multiboot_mod-loader_multiboot_loader.lst: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+fs-_multiboot_mod-loader_multiboot_loader.lst: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-_multiboot_mod-loader_multiboot_loader.lst: loader/multiboot_loader.c $(loader/multiboot_loader.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_multiboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh _multiboot > $@ || (rm -f $@; exit 1)
+
+
+_multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+_multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For multiboot.mod
+multiboot_mod_SOURCES = loader/multiboot_loader_normal.c
+CLEANFILES += multiboot.mod mod-multiboot.o mod-multiboot.c pre-multiboot.o multiboot_mod-loader_multiboot_loader_normal.o und-multiboot.lst
+ifneq ($(multiboot_mod_EXPORTS),no)
+CLEANFILES += def-multiboot.lst
+DEFSYMFILES += def-multiboot.lst
+endif
+MOSTLYCLEANFILES += multiboot_mod-loader_multiboot_loader_normal.d
+UNDSYMFILES += und-multiboot.lst
+
+multiboot.mod: pre-multiboot.o mod-multiboot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-multiboot.o mod-multiboot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-multiboot.o: $(multiboot_mod_DEPENDENCIES) multiboot_mod-loader_multiboot_loader_normal.o
+       -rm -f $@
+       $(TARGET_CC) $(multiboot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ multiboot_mod-loader_multiboot_loader_normal.o
+
+mod-multiboot.o: mod-multiboot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -c -o $@ $<
+
+mod-multiboot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'multiboot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(multiboot_mod_EXPORTS),no)
+def-multiboot.lst: pre-multiboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 multiboot/' > $@
+endif
+
+und-multiboot.lst: pre-multiboot.o
+       echo 'multiboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+multiboot_mod-loader_multiboot_loader_normal.o: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -MD -c -o $@ $<
+-include multiboot_mod-loader_multiboot_loader_normal.d
+
+CLEANFILES += cmd-multiboot_mod-loader_multiboot_loader_normal.lst fs-multiboot_mod-loader_multiboot_loader_normal.lst partmap-multiboot_mod-loader_multiboot_loader_normal.lst
+COMMANDFILES += cmd-multiboot_mod-loader_multiboot_loader_normal.lst
+FSFILES += fs-multiboot_mod-loader_multiboot_loader_normal.lst
+PARTMAPFILES += partmap-multiboot_mod-loader_multiboot_loader_normal.lst
+
+cmd-multiboot_mod-loader_multiboot_loader_normal.lst: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh multiboot > $@ || (rm -f $@; exit 1)
+
+fs-multiboot_mod-loader_multiboot_loader_normal.lst: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh multiboot > $@ || (rm -f $@; exit 1)
+
+partmap-multiboot_mod-loader_multiboot_loader_normal.lst: loader/multiboot_loader_normal.c $(loader/multiboot_loader_normal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(multiboot_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh multiboot > $@ || (rm -f $@; exit 1)
+
+
+multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) 
+
+# For memdisk.mod.
+memdisk_mod_SOURCES = disk/memdisk.c
+CLEANFILES += memdisk.mod mod-memdisk.o mod-memdisk.c pre-memdisk.o memdisk_mod-disk_memdisk.o und-memdisk.lst
+ifneq ($(memdisk_mod_EXPORTS),no)
+CLEANFILES += def-memdisk.lst
+DEFSYMFILES += def-memdisk.lst
+endif
+MOSTLYCLEANFILES += memdisk_mod-disk_memdisk.d
+UNDSYMFILES += und-memdisk.lst
+
+memdisk.mod: pre-memdisk.o mod-memdisk.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(memdisk_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-memdisk.o mod-memdisk.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-memdisk.o: $(memdisk_mod_DEPENDENCIES) memdisk_mod-disk_memdisk.o
+       -rm -f $@
+       $(TARGET_CC) $(memdisk_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ memdisk_mod-disk_memdisk.o
+
+mod-memdisk.o: mod-memdisk.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -c -o $@ $<
+
+mod-memdisk.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'memdisk' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(memdisk_mod_EXPORTS),no)
+def-memdisk.lst: pre-memdisk.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 memdisk/' > $@
+endif
+
+und-memdisk.lst: pre-memdisk.o
+       echo 'memdisk' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+memdisk_mod-disk_memdisk.o: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -MD -c -o $@ $<
+-include memdisk_mod-disk_memdisk.d
+
+CLEANFILES += cmd-memdisk_mod-disk_memdisk.lst fs-memdisk_mod-disk_memdisk.lst partmap-memdisk_mod-disk_memdisk.lst
+COMMANDFILES += cmd-memdisk_mod-disk_memdisk.lst
+FSFILES += fs-memdisk_mod-disk_memdisk.lst
+PARTMAPFILES += partmap-memdisk_mod-disk_memdisk.lst
+
+cmd-memdisk_mod-disk_memdisk.lst: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh memdisk > $@ || (rm -f $@; exit 1)
+
+fs-memdisk_mod-disk_memdisk.lst: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh memdisk > $@ || (rm -f $@; exit 1)
+
+partmap-memdisk_mod-disk_memdisk.lst: disk/memdisk.c $(disk/memdisk.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(memdisk_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh memdisk > $@ || (rm -f $@; exit 1)
+
+
+memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lsmmap.mod
+lsmmap_mod_SOURCES = commands/lsmmap.c
+CLEANFILES += lsmmap.mod mod-lsmmap.o mod-lsmmap.c pre-lsmmap.o lsmmap_mod-commands_lsmmap.o und-lsmmap.lst
+ifneq ($(lsmmap_mod_EXPORTS),no)
+CLEANFILES += def-lsmmap.lst
+DEFSYMFILES += def-lsmmap.lst
+endif
+MOSTLYCLEANFILES += lsmmap_mod-commands_lsmmap.d
+UNDSYMFILES += und-lsmmap.lst
+
+lsmmap.mod: pre-lsmmap.o mod-lsmmap.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(lsmmap_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-lsmmap.o mod-lsmmap.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-lsmmap.o: $(lsmmap_mod_DEPENDENCIES) lsmmap_mod-commands_lsmmap.o
+       -rm -f $@
+       $(TARGET_CC) $(lsmmap_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ lsmmap_mod-commands_lsmmap.o
+
+mod-lsmmap.o: mod-lsmmap.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -c -o $@ $<
+
+mod-lsmmap.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'lsmmap' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(lsmmap_mod_EXPORTS),no)
+def-lsmmap.lst: pre-lsmmap.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 lsmmap/' > $@
+endif
+
+und-lsmmap.lst: pre-lsmmap.o
+       echo 'lsmmap' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+lsmmap_mod-commands_lsmmap.o: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -MD -c -o $@ $<
+-include lsmmap_mod-commands_lsmmap.d
+
+CLEANFILES += cmd-lsmmap_mod-commands_lsmmap.lst fs-lsmmap_mod-commands_lsmmap.lst partmap-lsmmap_mod-commands_lsmmap.lst
+COMMANDFILES += cmd-lsmmap_mod-commands_lsmmap.lst
+FSFILES += fs-lsmmap_mod-commands_lsmmap.lst
+PARTMAPFILES += partmap-lsmmap_mod-commands_lsmmap.lst
+
+cmd-lsmmap_mod-commands_lsmmap.lst: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh lsmmap > $@ || (rm -f $@; exit 1)
+
+fs-lsmmap_mod-commands_lsmmap.lst: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh lsmmap > $@ || (rm -f $@; exit 1)
+
+partmap-lsmmap_mod-commands_lsmmap.lst: commands/lsmmap.c $(commands/lsmmap.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lsmmap_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh lsmmap > $@ || (rm -f $@; exit 1)
+
+
+lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
+lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+include $(srcdir)/conf/common.mk
+
diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk
new file mode 100644 (file)
index 0000000..51e7c07
--- /dev/null
@@ -0,0 +1,185 @@
+
+# -*- makefile -*-
+
+COMMON_ASFLAGS = -nostdinc -D__ASSEMBLY__
+COMMON_CFLAGS = -ffreestanding
+COMMON_LDFLAGS += -nostdlib
+
+# Used by various components.  These rules need to precede them.
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Images.
+
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+kernel_elf_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
+       env.h err.h file.h fs.h kernel.h misc.h mm.h net.h parser.h rescue.h \
+       symbol.h term.h time.h types.h powerpc/libgcc.h loader.h partition.h \
+       pc_partition.h ieee1275/ieee1275.h machine/kernel.h
+
+symlist.c: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h gensymlist.sh
+       /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h genkernsyms.sh
+       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+# Programs
+pkglib_PROGRAMS = kernel.elf
+
+# Utilities.
+sbin_UTILITIES = grub-mkdevicemap
+ifeq ($(enable_grub_emu), yes)
+sbin_UTILITIES += grub-emu
+endif
+# For grub-mkdevicemap.
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+
+# For grub-emu
+util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
+grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c       \
+       commands/configfile.c commands/help.c                           \
+       commands/search.c commands/terminal.c commands/test.c           \
+       commands/ls.c commands/blocklist.c commands/hexdump.c           \
+       lib/hexdump.c commands/halt.c commands/reboot.c                 \
+       disk/loopback.c                                                 \
+       \
+       fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/ext2.c fs/hfs.c       \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c          \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c                  \
+       fs/ufs.c fs/xfs.c fs/afs.c fs/tar.c                             \
+       \
+       io/gzio.c                                                       \
+       kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c       \
+       kern/err.c kern/file.c kern/fs.c kern/loader.c kern/main.c      \
+       kern/misc.c kern/parser.c kern/partition.c kern/rescue.c        \
+       kern/term.c fs/fshelp.c                                         \
+       normal/arg.c normal/cmdline.c normal/command.c                  \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/menu_entry.c normal/menu_viewer.c normal/misc.c          \
+       normal/script.c                                                 \
+       normal/color.c                                                  \
+       partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
+       partmap/acorn.c                                                 \
+       util/console.c util/hostfs.c util/grub-emu.c util/misc.c        \
+       util/hostdisk.c util/getroot.c                                  \
+       util/powerpc/ieee1275/misc.c                                    \
+       \
+       disk/raid.c disk/raid5_recover.c disk/raid6_recover.c           \
+       disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c             \
+       grub_script.tab.c grub_emu_init.c
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+kernel_elf_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \
+       kern/ieee1275/ieee1275.c kern/main.c kern/device.c              \
+       kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c          \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c   \
+       kern/ieee1275/init.c                                            \
+       kern/ieee1275/mmap.c                                            \
+       term/ieee1275/ofconsole.c               \
+       kern/ieee1275/openfw.c disk/ieee1275/ofdisk.c           \
+       kern/parser.c kern/partition.c kern/env.c kern/powerpc/dl.c     \
+       kern/generic/millisleep.c kern/time.c                            \
+       symlist.c kern/powerpc/cache.S
+kernel_elf_HEADERS = grub/powerpc/ieee1275/ieee1275.h
+kernel_elf_CFLAGS = $(COMMON_CFLAGS)
+kernel_elf_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_elf_LDFLAGS = $(COMMON_LDFLAGS) -static-libgcc -lgcc \
+       -Wl,-N,-S,-Ttext,0x200000,-Bstatic
+
+# Scripts.
+sbin_SCRIPTS = grub-install
+bin_SCRIPTS = grub-mkrescue
+
+# For grub-install.
+grub_install_SOURCES = util/ieee1275/grub-install.in
+
+# For grub-mkrescue.
+grub_mkrescue_SOURCES = util/powerpc/ieee1275/grub-mkrescue.in
+
+# Modules.
+pkglib_MODULES = halt.mod \
+       _linux.mod \
+       linux.mod \
+       normal.mod \
+       reboot.mod \
+       suspend.mod \
+        _multiboot.mod \
+        multiboot.mod \
+       memdisk.mod \
+       lsmmap.mod
+
+# For _linux.mod.
+_linux_mod_SOURCES = loader/powerpc/ieee1275/linux.c
+_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/powerpc/ieee1275/linux_normal.c
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+#
+# Only arch dependant part of normal.mod will be here. Common part for
+# all architecures of normal.mod is at start and should be kept at sync
+# with other makefiles.
+# 
+# Please put arch dependant part of normal.mod at the end of list to
+# keep it simpler to update to different architectures.
+#
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/color.c                                                  \
+       normal/menu_viewer.c normal/menu_entry.c                        \
+       normal/misc.c grub_script.tab.c                                 \
+       normal/script.c                                                 \
+       normal/powerpc/setjmp.S
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For suspend.mod
+suspend_mod_SOURCES = commands/ieee1275/suspend.c
+suspend_mod_CFLAGS = $(COMMON_CFLAGS)
+suspend_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reboot.mod
+reboot_mod_SOURCES = commands/reboot.c
+reboot_mod_CFLAGS = $(COMMON_CFLAGS)
+reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For halt.mod
+halt_mod_SOURCES = commands/halt.c
+halt_mod_CFLAGS = $(COMMON_CFLAGS)
+halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _multiboot.mod
+_multiboot_mod_SOURCES = loader/ieee1275/multiboot2.c \
+                         loader/multiboot2.c \
+                         loader/multiboot_loader.c
+_multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+_multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For multiboot.mod
+multiboot_mod_SOURCES = loader/multiboot_loader_normal.c
+multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) 
+
+# For memdisk.mod.
+memdisk_mod_SOURCES = disk/memdisk.c
+memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lsmmap.mod
+lsmmap_mod_SOURCES = commands/lsmmap.c
+lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
+lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+include $(srcdir)/conf/common.mk
+
diff --git a/conf/sparc64-ieee1275.mk b/conf/sparc64-ieee1275.mk
new file mode 100644 (file)
index 0000000..ce49690
--- /dev/null
@@ -0,0 +1,2315 @@
+
+# Generated by genmk.rb, please don't edit!
+# -*- makefile -*-
+
+COMMON_ASFLAGS = -nostdinc
+COMMON_CFLAGS = -ggdb -ffreestanding -m64 -mno-app-regs
+COMMON_LDFLAGS = -melf64_sparc -nostdlib
+
+# Used by various components.  These rules need to precede them.
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Images.
+
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+kernel_elf_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
+       env.h err.h file.h fs.h kernel.h misc.h mm.h net.h parser.h rescue.h \
+       symbol.h term.h time.h types.h sparc64/libgcc.h loader.h partition.h \
+       pc_partition.h ieee1275/ieee1275.h machine/kernel.h
+
+symlist.c: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h gensymlist.sh
+       /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+# For the parser.
+grub_script.tab.c grub_script.tab.h: normal/parser.y
+       $(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/normal/parser.y
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h genkernsyms.sh
+       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+# Programs
+pkglib_PROGRAMS = kernel.elf
+
+# Utilities.
+#bin_UTILITIES = grub-mkimage
+#ifeq ($(enable_grub_emu), yes)
+#bin_UTILITIES += grub-emu
+#endif
+
+# For grub-mkimage.
+grub_mkimage_SOURCES = util/sparc64/ieee1275/grub-mkimage.c util/misc.c \
+        util/resolve.c 
+
+# For grub-emu
+#grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c      \
+#      commands/configfile.c commands/default.c commands/help.c        \
+#      commands/search.c commands/terminal.c commands/ls.c             \
+#      commands/timeout.c commands/test.c                              \
+#      commands/halt.c commands/reboot.c               \
+#      disk/loopback.c                                                 \
+#      fs/affs.c fs/fat.c fs/ext2.c fs/fshelp.c fs/hfs.c fs/iso9660.c  \
+#      fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c                  \
+#      grub_script.tab.c                                               \
+#      io/gzio.c                                                       \
+#      kern/device.c kern/disk.c kern/dl.c kern/env.c kern/err.c       \
+#      kern/file.c kern/fs.c kern/loader.c kern/main.c kern/misc.c     \
+#      kern/parser.c kern/partition.c kern/rescue.c kern/term.c        \
+#      normal/arg.c normal/cmdline.c normal/command.c                  \
+#      normal/completion.c normal/context.c normal/execute.c           \
+#      normal/function.c normal/lexer.c                                \
+#      normal/main.c normal/menu.c normal/menu_entry.c                 \
+#      normal/menu_text.c                                              \
+#      normal/menu_viewer.c normal/misc.c                              \
+#      partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
+#      partmap/acorn.c                                                 \
+#      util/console.c util/grub-emu.c util/misc.c                      \
+#      util/hostdisk.c util/getroot.c                                  \
+#      util/sparc64/ieee1275/misc.c
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+kernel_elf_SOURCES = kern/sparc64/ieee1275/init.c kern/ieee1275/ieee1275.c \
+       kern/main.c kern/device.c kern/disk.c kern/dl.c kern/file.c \
+       kern/fs.c kern/err.c kern/misc.c kern/mm.c kern/loader.c \
+       kern/rescue.c kern/term.c term/ieee1275/ofconsole.c \
+       kern/sparc64/ieee1275/openfw.c disk/ieee1275/ofdisk.c \
+       kern/partition.c kern/env.c kern/sparc64/dl.c symlist.c \
+       kern/generic/millisleep.c kern/generic/get_time_ms.c \
+       kern/sparc64/cache.S kern/parser.c
+CLEANFILES += kernel.elf kernel_elf-kern_sparc64_ieee1275_init.o kernel_elf-kern_ieee1275_ieee1275.o kernel_elf-kern_main.o kernel_elf-kern_device.o kernel_elf-kern_disk.o kernel_elf-kern_dl.o kernel_elf-kern_file.o kernel_elf-kern_fs.o kernel_elf-kern_err.o kernel_elf-kern_misc.o kernel_elf-kern_mm.o kernel_elf-kern_loader.o kernel_elf-kern_rescue.o kernel_elf-kern_term.o kernel_elf-term_ieee1275_ofconsole.o kernel_elf-kern_sparc64_ieee1275_openfw.o kernel_elf-disk_ieee1275_ofdisk.o kernel_elf-kern_partition.o kernel_elf-kern_env.o kernel_elf-kern_sparc64_dl.o kernel_elf-symlist.o kernel_elf-kern_generic_millisleep.o kernel_elf-kern_generic_get_time_ms.o kernel_elf-kern_sparc64_cache.o kernel_elf-kern_parser.o
+MOSTLYCLEANFILES += kernel_elf-kern_sparc64_ieee1275_init.d kernel_elf-kern_ieee1275_ieee1275.d kernel_elf-kern_main.d kernel_elf-kern_device.d kernel_elf-kern_disk.d kernel_elf-kern_dl.d kernel_elf-kern_file.d kernel_elf-kern_fs.d kernel_elf-kern_err.d kernel_elf-kern_misc.d kernel_elf-kern_mm.d kernel_elf-kern_loader.d kernel_elf-kern_rescue.d kernel_elf-kern_term.d kernel_elf-term_ieee1275_ofconsole.d kernel_elf-kern_sparc64_ieee1275_openfw.d kernel_elf-disk_ieee1275_ofdisk.d kernel_elf-kern_partition.d kernel_elf-kern_env.d kernel_elf-kern_sparc64_dl.d kernel_elf-symlist.d kernel_elf-kern_generic_millisleep.d kernel_elf-kern_generic_get_time_ms.d kernel_elf-kern_sparc64_cache.d kernel_elf-kern_parser.d
+
+kernel.elf: $(kernel_elf_DEPENDENCIES) kernel_elf-kern_sparc64_ieee1275_init.o kernel_elf-kern_ieee1275_ieee1275.o kernel_elf-kern_main.o kernel_elf-kern_device.o kernel_elf-kern_disk.o kernel_elf-kern_dl.o kernel_elf-kern_file.o kernel_elf-kern_fs.o kernel_elf-kern_err.o kernel_elf-kern_misc.o kernel_elf-kern_mm.o kernel_elf-kern_loader.o kernel_elf-kern_rescue.o kernel_elf-kern_term.o kernel_elf-term_ieee1275_ofconsole.o kernel_elf-kern_sparc64_ieee1275_openfw.o kernel_elf-disk_ieee1275_ofdisk.o kernel_elf-kern_partition.o kernel_elf-kern_env.o kernel_elf-kern_sparc64_dl.o kernel_elf-symlist.o kernel_elf-kern_generic_millisleep.o kernel_elf-kern_generic_get_time_ms.o kernel_elf-kern_sparc64_cache.o kernel_elf-kern_parser.o
+       $(TARGET_CC) -o $@ kernel_elf-kern_sparc64_ieee1275_init.o kernel_elf-kern_ieee1275_ieee1275.o kernel_elf-kern_main.o kernel_elf-kern_device.o kernel_elf-kern_disk.o kernel_elf-kern_dl.o kernel_elf-kern_file.o kernel_elf-kern_fs.o kernel_elf-kern_err.o kernel_elf-kern_misc.o kernel_elf-kern_mm.o kernel_elf-kern_loader.o kernel_elf-kern_rescue.o kernel_elf-kern_term.o kernel_elf-term_ieee1275_ofconsole.o kernel_elf-kern_sparc64_ieee1275_openfw.o kernel_elf-disk_ieee1275_ofdisk.o kernel_elf-kern_partition.o kernel_elf-kern_env.o kernel_elf-kern_sparc64_dl.o kernel_elf-symlist.o kernel_elf-kern_generic_millisleep.o kernel_elf-kern_generic_get_time_ms.o kernel_elf-kern_sparc64_cache.o kernel_elf-kern_parser.o $(TARGET_LDFLAGS) $(kernel_elf_LDFLAGS)
+
+kernel_elf-kern_sparc64_ieee1275_init.o: kern/sparc64/ieee1275/init.c $(kern/sparc64/ieee1275/init.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/sparc64/ieee1275 -I$(srcdir)/kern/sparc64/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_sparc64_ieee1275_init.d
+
+kernel_elf-kern_ieee1275_ieee1275.o: kern/ieee1275/ieee1275.c $(kern/ieee1275/ieee1275.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/ieee1275 -I$(srcdir)/kern/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_ieee1275_ieee1275.d
+
+kernel_elf-kern_main.o: kern/main.c $(kern/main.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_main.d
+
+kernel_elf-kern_device.o: kern/device.c $(kern/device.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_device.d
+
+kernel_elf-kern_disk.o: kern/disk.c $(kern/disk.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_disk.d
+
+kernel_elf-kern_dl.o: kern/dl.c $(kern/dl.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_dl.d
+
+kernel_elf-kern_file.o: kern/file.c $(kern/file.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_file.d
+
+kernel_elf-kern_fs.o: kern/fs.c $(kern/fs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_fs.d
+
+kernel_elf-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_err.d
+
+kernel_elf-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_misc.d
+
+kernel_elf-kern_mm.o: kern/mm.c $(kern/mm.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_mm.d
+
+kernel_elf-kern_loader.o: kern/loader.c $(kern/loader.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_loader.d
+
+kernel_elf-kern_rescue.o: kern/rescue.c $(kern/rescue.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_rescue.d
+
+kernel_elf-kern_term.o: kern/term.c $(kern/term.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_term.d
+
+kernel_elf-term_ieee1275_ofconsole.o: term/ieee1275/ofconsole.c $(term/ieee1275/ofconsole.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/ieee1275 -I$(srcdir)/term/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-term_ieee1275_ofconsole.d
+
+kernel_elf-kern_sparc64_ieee1275_openfw.o: kern/sparc64/ieee1275/openfw.c $(kern/sparc64/ieee1275/openfw.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/sparc64/ieee1275 -I$(srcdir)/kern/sparc64/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_sparc64_ieee1275_openfw.d
+
+kernel_elf-disk_ieee1275_ofdisk.o: disk/ieee1275/ofdisk.c $(disk/ieee1275/ofdisk.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk/ieee1275 -I$(srcdir)/disk/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-disk_ieee1275_ofdisk.d
+
+kernel_elf-kern_partition.o: kern/partition.c $(kern/partition.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_partition.d
+
+kernel_elf-kern_env.o: kern/env.c $(kern/env.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_env.d
+
+kernel_elf-kern_sparc64_dl.o: kern/sparc64/dl.c $(kern/sparc64/dl.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/sparc64 -I$(srcdir)/kern/sparc64 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_sparc64_dl.d
+
+kernel_elf-symlist.o: symlist.c $(symlist.c_DEPENDENCIES)
+       $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-symlist.d
+
+kernel_elf-kern_generic_millisleep.o: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_generic_millisleep.d
+
+kernel_elf-kern_generic_get_time_ms.o: kern/generic/get_time_ms.c $(kern/generic/get_time_ms.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_generic_get_time_ms.d
+
+kernel_elf-kern_sparc64_cache.o: kern/sparc64/cache.S $(kern/sparc64/cache.S_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/sparc64 -I$(srcdir)/kern/sparc64 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_sparc64_cache.d
+
+kernel_elf-kern_parser.o: kern/parser.c $(kern/parser.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_elf_CFLAGS) -MD -c -o $@ $<
+-include kernel_elf-kern_parser.d
+
+kernel_elf_HEADERS = grub/sparc64/ieee1275/ieee1275.h
+kernel_elf_CFLAGS = $(COMMON_CFLAGS)
+kernel_elf_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_elf_LDFLAGS = -mno-app-regs -nostdlib -Wl,-N,-Ttext,0x200000,-Bstatic,-melf64_sparc
+
+# Modules.
+#_linux.mod linux.mod
+pkglib_MODULES = fat.mod ufs.mod ext2.mod minix.mod \
+       hfs.mod jfs.mod normal.mod hello.mod font.mod ls.mod \
+       boot.mod cmp.mod cat.mod terminal.mod fshelp.mod amiga.mod apple.mod \
+       pc.mod suspend.mod loopback.mod help.mod reboot.mod halt.mod sun.mod \
+       configfile.mod search.mod gzio.mod xfs.mod \
+       affs.mod sfs.mod acorn.mod
+
+# For fshelp.mod.
+fshelp_mod_SOURCES = fs/fshelp.c
+CLEANFILES += fshelp.mod mod-fshelp.o mod-fshelp.c pre-fshelp.o fshelp_mod-fs_fshelp.o und-fshelp.lst
+ifneq ($(fshelp_mod_EXPORTS),no)
+CLEANFILES += def-fshelp.lst
+DEFSYMFILES += def-fshelp.lst
+endif
+MOSTLYCLEANFILES += fshelp_mod-fs_fshelp.d
+UNDSYMFILES += und-fshelp.lst
+
+fshelp.mod: pre-fshelp.o mod-fshelp.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(fshelp_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-fshelp.o mod-fshelp.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-fshelp.o: $(fshelp_mod_DEPENDENCIES) fshelp_mod-fs_fshelp.o
+       -rm -f $@
+       $(TARGET_CC) $(fshelp_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ fshelp_mod-fs_fshelp.o
+
+mod-fshelp.o: mod-fshelp.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fshelp_mod_CFLAGS) -c -o $@ $<
+
+mod-fshelp.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'fshelp' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(fshelp_mod_EXPORTS),no)
+def-fshelp.lst: pre-fshelp.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 fshelp/' > $@
+endif
+
+und-fshelp.lst: pre-fshelp.o
+       echo 'fshelp' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+fshelp_mod-fs_fshelp.o: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(fshelp_mod_CFLAGS) -MD -c -o $@ $<
+-include fshelp_mod-fs_fshelp.d
+
+CLEANFILES += cmd-fshelp_mod-fs_fshelp.lst fs-fshelp_mod-fs_fshelp.lst partmap-fshelp_mod-fs_fshelp.lst
+COMMANDFILES += cmd-fshelp_mod-fs_fshelp.lst
+FSFILES += fs-fshelp_mod-fs_fshelp.lst
+PARTMAPFILES += partmap-fshelp_mod-fs_fshelp.lst
+
+cmd-fshelp_mod-fs_fshelp.lst: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fshelp_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh fshelp > $@ || (rm -f $@; exit 1)
+
+fs-fshelp_mod-fs_fshelp.lst: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fshelp_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh fshelp > $@ || (rm -f $@; exit 1)
+
+partmap-fshelp_mod-fs_fshelp.lst: fs/fshelp.c $(fs/fshelp.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fshelp_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh fshelp > $@ || (rm -f $@; exit 1)
+
+
+fshelp_mod_CFLAGS = $(COMMON_CFLAGS)
+fshelp_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For fat.mod.
+fat_mod_SOURCES = fs/fat.c
+CLEANFILES += fat.mod mod-fat.o mod-fat.c pre-fat.o fat_mod-fs_fat.o und-fat.lst
+ifneq ($(fat_mod_EXPORTS),no)
+CLEANFILES += def-fat.lst
+DEFSYMFILES += def-fat.lst
+endif
+MOSTLYCLEANFILES += fat_mod-fs_fat.d
+UNDSYMFILES += und-fat.lst
+
+fat.mod: pre-fat.o mod-fat.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(fat_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-fat.o mod-fat.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-fat.o: $(fat_mod_DEPENDENCIES) fat_mod-fs_fat.o
+       -rm -f $@
+       $(TARGET_CC) $(fat_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ fat_mod-fs_fat.o
+
+mod-fat.o: mod-fat.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fat_mod_CFLAGS) -c -o $@ $<
+
+mod-fat.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'fat' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(fat_mod_EXPORTS),no)
+def-fat.lst: pre-fat.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 fat/' > $@
+endif
+
+und-fat.lst: pre-fat.o
+       echo 'fat' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+fat_mod-fs_fat.o: fs/fat.c $(fs/fat.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(fat_mod_CFLAGS) -MD -c -o $@ $<
+-include fat_mod-fs_fat.d
+
+CLEANFILES += cmd-fat_mod-fs_fat.lst fs-fat_mod-fs_fat.lst partmap-fat_mod-fs_fat.lst
+COMMANDFILES += cmd-fat_mod-fs_fat.lst
+FSFILES += fs-fat_mod-fs_fat.lst
+PARTMAPFILES += partmap-fat_mod-fs_fat.lst
+
+cmd-fat_mod-fs_fat.lst: fs/fat.c $(fs/fat.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fat_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh fat > $@ || (rm -f $@; exit 1)
+
+fs-fat_mod-fs_fat.lst: fs/fat.c $(fs/fat.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fat_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh fat > $@ || (rm -f $@; exit 1)
+
+partmap-fat_mod-fs_fat.lst: fs/fat.c $(fs/fat.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(fat_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh fat > $@ || (rm -f $@; exit 1)
+
+
+fat_mod_CFLAGS = $(COMMON_CFLAGS)
+fat_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ext2.mod.
+ext2_mod_SOURCES = fs/ext2.c
+CLEANFILES += ext2.mod mod-ext2.o mod-ext2.c pre-ext2.o ext2_mod-fs_ext2.o und-ext2.lst
+ifneq ($(ext2_mod_EXPORTS),no)
+CLEANFILES += def-ext2.lst
+DEFSYMFILES += def-ext2.lst
+endif
+MOSTLYCLEANFILES += ext2_mod-fs_ext2.d
+UNDSYMFILES += und-ext2.lst
+
+ext2.mod: pre-ext2.o mod-ext2.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(ext2_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-ext2.o mod-ext2.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-ext2.o: $(ext2_mod_DEPENDENCIES) ext2_mod-fs_ext2.o
+       -rm -f $@
+       $(TARGET_CC) $(ext2_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ ext2_mod-fs_ext2.o
+
+mod-ext2.o: mod-ext2.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ext2_mod_CFLAGS) -c -o $@ $<
+
+mod-ext2.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'ext2' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(ext2_mod_EXPORTS),no)
+def-ext2.lst: pre-ext2.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 ext2/' > $@
+endif
+
+und-ext2.lst: pre-ext2.o
+       echo 'ext2' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+ext2_mod-fs_ext2.o: fs/ext2.c $(fs/ext2.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(ext2_mod_CFLAGS) -MD -c -o $@ $<
+-include ext2_mod-fs_ext2.d
+
+CLEANFILES += cmd-ext2_mod-fs_ext2.lst fs-ext2_mod-fs_ext2.lst partmap-ext2_mod-fs_ext2.lst
+COMMANDFILES += cmd-ext2_mod-fs_ext2.lst
+FSFILES += fs-ext2_mod-fs_ext2.lst
+PARTMAPFILES += partmap-ext2_mod-fs_ext2.lst
+
+cmd-ext2_mod-fs_ext2.lst: fs/ext2.c $(fs/ext2.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ext2_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh ext2 > $@ || (rm -f $@; exit 1)
+
+fs-ext2_mod-fs_ext2.lst: fs/ext2.c $(fs/ext2.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ext2_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh ext2 > $@ || (rm -f $@; exit 1)
+
+partmap-ext2_mod-fs_ext2.lst: fs/ext2.c $(fs/ext2.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ext2_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh ext2 > $@ || (rm -f $@; exit 1)
+
+
+ext2_mod_CFLAGS = $(COMMON_CFLAGS)
+ext2_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ufs.mod.
+ufs_mod_SOURCES = fs/ufs.c
+CLEANFILES += ufs.mod mod-ufs.o mod-ufs.c pre-ufs.o ufs_mod-fs_ufs.o und-ufs.lst
+ifneq ($(ufs_mod_EXPORTS),no)
+CLEANFILES += def-ufs.lst
+DEFSYMFILES += def-ufs.lst
+endif
+MOSTLYCLEANFILES += ufs_mod-fs_ufs.d
+UNDSYMFILES += und-ufs.lst
+
+ufs.mod: pre-ufs.o mod-ufs.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(ufs_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-ufs.o mod-ufs.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-ufs.o: $(ufs_mod_DEPENDENCIES) ufs_mod-fs_ufs.o
+       -rm -f $@
+       $(TARGET_CC) $(ufs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ ufs_mod-fs_ufs.o
+
+mod-ufs.o: mod-ufs.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ufs_mod_CFLAGS) -c -o $@ $<
+
+mod-ufs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'ufs' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(ufs_mod_EXPORTS),no)
+def-ufs.lst: pre-ufs.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 ufs/' > $@
+endif
+
+und-ufs.lst: pre-ufs.o
+       echo 'ufs' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+ufs_mod-fs_ufs.o: fs/ufs.c $(fs/ufs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(ufs_mod_CFLAGS) -MD -c -o $@ $<
+-include ufs_mod-fs_ufs.d
+
+CLEANFILES += cmd-ufs_mod-fs_ufs.lst fs-ufs_mod-fs_ufs.lst partmap-ufs_mod-fs_ufs.lst
+COMMANDFILES += cmd-ufs_mod-fs_ufs.lst
+FSFILES += fs-ufs_mod-fs_ufs.lst
+PARTMAPFILES += partmap-ufs_mod-fs_ufs.lst
+
+cmd-ufs_mod-fs_ufs.lst: fs/ufs.c $(fs/ufs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ufs_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh ufs > $@ || (rm -f $@; exit 1)
+
+fs-ufs_mod-fs_ufs.lst: fs/ufs.c $(fs/ufs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ufs_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh ufs > $@ || (rm -f $@; exit 1)
+
+partmap-ufs_mod-fs_ufs.lst: fs/ufs.c $(fs/ufs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ufs_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh ufs > $@ || (rm -f $@; exit 1)
+
+
+ufs_mod_CFLAGS = $(COMMON_CFLAGS)
+ufs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For minix.mod.
+minix_mod_SOURCES = fs/minix.c
+CLEANFILES += minix.mod mod-minix.o mod-minix.c pre-minix.o minix_mod-fs_minix.o und-minix.lst
+ifneq ($(minix_mod_EXPORTS),no)
+CLEANFILES += def-minix.lst
+DEFSYMFILES += def-minix.lst
+endif
+MOSTLYCLEANFILES += minix_mod-fs_minix.d
+UNDSYMFILES += und-minix.lst
+
+minix.mod: pre-minix.o mod-minix.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(minix_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-minix.o mod-minix.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-minix.o: $(minix_mod_DEPENDENCIES) minix_mod-fs_minix.o
+       -rm -f $@
+       $(TARGET_CC) $(minix_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ minix_mod-fs_minix.o
+
+mod-minix.o: mod-minix.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(minix_mod_CFLAGS) -c -o $@ $<
+
+mod-minix.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'minix' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(minix_mod_EXPORTS),no)
+def-minix.lst: pre-minix.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 minix/' > $@
+endif
+
+und-minix.lst: pre-minix.o
+       echo 'minix' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+minix_mod-fs_minix.o: fs/minix.c $(fs/minix.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(minix_mod_CFLAGS) -MD -c -o $@ $<
+-include minix_mod-fs_minix.d
+
+CLEANFILES += cmd-minix_mod-fs_minix.lst fs-minix_mod-fs_minix.lst partmap-minix_mod-fs_minix.lst
+COMMANDFILES += cmd-minix_mod-fs_minix.lst
+FSFILES += fs-minix_mod-fs_minix.lst
+PARTMAPFILES += partmap-minix_mod-fs_minix.lst
+
+cmd-minix_mod-fs_minix.lst: fs/minix.c $(fs/minix.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(minix_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh minix > $@ || (rm -f $@; exit 1)
+
+fs-minix_mod-fs_minix.lst: fs/minix.c $(fs/minix.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(minix_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh minix > $@ || (rm -f $@; exit 1)
+
+partmap-minix_mod-fs_minix.lst: fs/minix.c $(fs/minix.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(minix_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh minix > $@ || (rm -f $@; exit 1)
+
+
+minix_mod_CFLAGS = $(COMMON_CFLAGS)
+minix_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For hfs.mod.
+hfs_mod_SOURCES = fs/hfs.c
+CLEANFILES += hfs.mod mod-hfs.o mod-hfs.c pre-hfs.o hfs_mod-fs_hfs.o und-hfs.lst
+ifneq ($(hfs_mod_EXPORTS),no)
+CLEANFILES += def-hfs.lst
+DEFSYMFILES += def-hfs.lst
+endif
+MOSTLYCLEANFILES += hfs_mod-fs_hfs.d
+UNDSYMFILES += und-hfs.lst
+
+hfs.mod: pre-hfs.o mod-hfs.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(hfs_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-hfs.o mod-hfs.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-hfs.o: $(hfs_mod_DEPENDENCIES) hfs_mod-fs_hfs.o
+       -rm -f $@
+       $(TARGET_CC) $(hfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ hfs_mod-fs_hfs.o
+
+mod-hfs.o: mod-hfs.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hfs_mod_CFLAGS) -c -o $@ $<
+
+mod-hfs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'hfs' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(hfs_mod_EXPORTS),no)
+def-hfs.lst: pre-hfs.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 hfs/' > $@
+endif
+
+und-hfs.lst: pre-hfs.o
+       echo 'hfs' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+hfs_mod-fs_hfs.o: fs/hfs.c $(fs/hfs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(hfs_mod_CFLAGS) -MD -c -o $@ $<
+-include hfs_mod-fs_hfs.d
+
+CLEANFILES += cmd-hfs_mod-fs_hfs.lst fs-hfs_mod-fs_hfs.lst partmap-hfs_mod-fs_hfs.lst
+COMMANDFILES += cmd-hfs_mod-fs_hfs.lst
+FSFILES += fs-hfs_mod-fs_hfs.lst
+PARTMAPFILES += partmap-hfs_mod-fs_hfs.lst
+
+cmd-hfs_mod-fs_hfs.lst: fs/hfs.c $(fs/hfs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hfs_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh hfs > $@ || (rm -f $@; exit 1)
+
+fs-hfs_mod-fs_hfs.lst: fs/hfs.c $(fs/hfs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh hfs > $@ || (rm -f $@; exit 1)
+
+partmap-hfs_mod-fs_hfs.lst: fs/hfs.c $(fs/hfs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh hfs > $@ || (rm -f $@; exit 1)
+
+
+hfs_mod_CFLAGS = $(COMMON_CFLAGS)
+hfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For jfs.mod.
+jfs_mod_SOURCES = fs/jfs.c
+CLEANFILES += jfs.mod mod-jfs.o mod-jfs.c pre-jfs.o jfs_mod-fs_jfs.o und-jfs.lst
+ifneq ($(jfs_mod_EXPORTS),no)
+CLEANFILES += def-jfs.lst
+DEFSYMFILES += def-jfs.lst
+endif
+MOSTLYCLEANFILES += jfs_mod-fs_jfs.d
+UNDSYMFILES += und-jfs.lst
+
+jfs.mod: pre-jfs.o mod-jfs.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(jfs_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-jfs.o mod-jfs.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-jfs.o: $(jfs_mod_DEPENDENCIES) jfs_mod-fs_jfs.o
+       -rm -f $@
+       $(TARGET_CC) $(jfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ jfs_mod-fs_jfs.o
+
+mod-jfs.o: mod-jfs.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(jfs_mod_CFLAGS) -c -o $@ $<
+
+mod-jfs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'jfs' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(jfs_mod_EXPORTS),no)
+def-jfs.lst: pre-jfs.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 jfs/' > $@
+endif
+
+und-jfs.lst: pre-jfs.o
+       echo 'jfs' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+jfs_mod-fs_jfs.o: fs/jfs.c $(fs/jfs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(jfs_mod_CFLAGS) -MD -c -o $@ $<
+-include jfs_mod-fs_jfs.d
+
+CLEANFILES += cmd-jfs_mod-fs_jfs.lst fs-jfs_mod-fs_jfs.lst partmap-jfs_mod-fs_jfs.lst
+COMMANDFILES += cmd-jfs_mod-fs_jfs.lst
+FSFILES += fs-jfs_mod-fs_jfs.lst
+PARTMAPFILES += partmap-jfs_mod-fs_jfs.lst
+
+cmd-jfs_mod-fs_jfs.lst: fs/jfs.c $(fs/jfs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(jfs_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh jfs > $@ || (rm -f $@; exit 1)
+
+fs-jfs_mod-fs_jfs.lst: fs/jfs.c $(fs/jfs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(jfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh jfs > $@ || (rm -f $@; exit 1)
+
+partmap-jfs_mod-fs_jfs.lst: fs/jfs.c $(fs/jfs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(jfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh jfs > $@ || (rm -f $@; exit 1)
+
+
+jfs_mod_CFLAGS = $(COMMON_CFLAGS)
+jfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For iso9660.mod.
+iso9660_mod_SOURCES = fs/iso9660.c
+iso9660_mod_CFLAGS = $(COMMON_CFLAGS)
+iso9660_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For xfs.mod.
+xfs_mod_SOURCES = fs/xfs.c
+CLEANFILES += xfs.mod mod-xfs.o mod-xfs.c pre-xfs.o xfs_mod-fs_xfs.o und-xfs.lst
+ifneq ($(xfs_mod_EXPORTS),no)
+CLEANFILES += def-xfs.lst
+DEFSYMFILES += def-xfs.lst
+endif
+MOSTLYCLEANFILES += xfs_mod-fs_xfs.d
+UNDSYMFILES += und-xfs.lst
+
+xfs.mod: pre-xfs.o mod-xfs.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(xfs_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-xfs.o mod-xfs.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-xfs.o: $(xfs_mod_DEPENDENCIES) xfs_mod-fs_xfs.o
+       -rm -f $@
+       $(TARGET_CC) $(xfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ xfs_mod-fs_xfs.o
+
+mod-xfs.o: mod-xfs.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(xfs_mod_CFLAGS) -c -o $@ $<
+
+mod-xfs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'xfs' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(xfs_mod_EXPORTS),no)
+def-xfs.lst: pre-xfs.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 xfs/' > $@
+endif
+
+und-xfs.lst: pre-xfs.o
+       echo 'xfs' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+xfs_mod-fs_xfs.o: fs/xfs.c $(fs/xfs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(xfs_mod_CFLAGS) -MD -c -o $@ $<
+-include xfs_mod-fs_xfs.d
+
+CLEANFILES += cmd-xfs_mod-fs_xfs.lst fs-xfs_mod-fs_xfs.lst partmap-xfs_mod-fs_xfs.lst
+COMMANDFILES += cmd-xfs_mod-fs_xfs.lst
+FSFILES += fs-xfs_mod-fs_xfs.lst
+PARTMAPFILES += partmap-xfs_mod-fs_xfs.lst
+
+cmd-xfs_mod-fs_xfs.lst: fs/xfs.c $(fs/xfs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(xfs_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh xfs > $@ || (rm -f $@; exit 1)
+
+fs-xfs_mod-fs_xfs.lst: fs/xfs.c $(fs/xfs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(xfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh xfs > $@ || (rm -f $@; exit 1)
+
+partmap-xfs_mod-fs_xfs.lst: fs/xfs.c $(fs/xfs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(xfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh xfs > $@ || (rm -f $@; exit 1)
+
+
+xfs_mod_CFLAGS = $(COMMON_CFLAGS)
+xfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For affs.mod.
+affs_mod_SOURCES = fs/affs.c
+CLEANFILES += affs.mod mod-affs.o mod-affs.c pre-affs.o affs_mod-fs_affs.o und-affs.lst
+ifneq ($(affs_mod_EXPORTS),no)
+CLEANFILES += def-affs.lst
+DEFSYMFILES += def-affs.lst
+endif
+MOSTLYCLEANFILES += affs_mod-fs_affs.d
+UNDSYMFILES += und-affs.lst
+
+affs.mod: pre-affs.o mod-affs.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(affs_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-affs.o mod-affs.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-affs.o: $(affs_mod_DEPENDENCIES) affs_mod-fs_affs.o
+       -rm -f $@
+       $(TARGET_CC) $(affs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ affs_mod-fs_affs.o
+
+mod-affs.o: mod-affs.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(affs_mod_CFLAGS) -c -o $@ $<
+
+mod-affs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'affs' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(affs_mod_EXPORTS),no)
+def-affs.lst: pre-affs.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 affs/' > $@
+endif
+
+und-affs.lst: pre-affs.o
+       echo 'affs' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+affs_mod-fs_affs.o: fs/affs.c $(fs/affs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(affs_mod_CFLAGS) -MD -c -o $@ $<
+-include affs_mod-fs_affs.d
+
+CLEANFILES += cmd-affs_mod-fs_affs.lst fs-affs_mod-fs_affs.lst partmap-affs_mod-fs_affs.lst
+COMMANDFILES += cmd-affs_mod-fs_affs.lst
+FSFILES += fs-affs_mod-fs_affs.lst
+PARTMAPFILES += partmap-affs_mod-fs_affs.lst
+
+cmd-affs_mod-fs_affs.lst: fs/affs.c $(fs/affs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(affs_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh affs > $@ || (rm -f $@; exit 1)
+
+fs-affs_mod-fs_affs.lst: fs/affs.c $(fs/affs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(affs_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh affs > $@ || (rm -f $@; exit 1)
+
+partmap-affs_mod-fs_affs.lst: fs/affs.c $(fs/affs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(affs_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh affs > $@ || (rm -f $@; exit 1)
+
+
+affs_mod_CFLAGS = $(COMMON_CFLAGS)
+affs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For sfs.mod.
+sfs_mod_SOURCES = fs/sfs.c
+CLEANFILES += sfs.mod mod-sfs.o mod-sfs.c pre-sfs.o sfs_mod-fs_sfs.o und-sfs.lst
+ifneq ($(sfs_mod_EXPORTS),no)
+CLEANFILES += def-sfs.lst
+DEFSYMFILES += def-sfs.lst
+endif
+MOSTLYCLEANFILES += sfs_mod-fs_sfs.d
+UNDSYMFILES += und-sfs.lst
+
+sfs.mod: pre-sfs.o mod-sfs.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(sfs_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-sfs.o mod-sfs.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-sfs.o: $(sfs_mod_DEPENDENCIES) sfs_mod-fs_sfs.o
+       -rm -f $@
+       $(TARGET_CC) $(sfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ sfs_mod-fs_sfs.o
+
+mod-sfs.o: mod-sfs.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sfs_mod_CFLAGS) -c -o $@ $<
+
+mod-sfs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'sfs' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(sfs_mod_EXPORTS),no)
+def-sfs.lst: pre-sfs.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 sfs/' > $@
+endif
+
+und-sfs.lst: pre-sfs.o
+       echo 'sfs' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+sfs_mod-fs_sfs.o: fs/sfs.c $(fs/sfs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(sfs_mod_CFLAGS) -MD -c -o $@ $<
+-include sfs_mod-fs_sfs.d
+
+CLEANFILES += cmd-sfs_mod-fs_sfs.lst fs-sfs_mod-fs_sfs.lst partmap-sfs_mod-fs_sfs.lst
+COMMANDFILES += cmd-sfs_mod-fs_sfs.lst
+FSFILES += fs-sfs_mod-fs_sfs.lst
+PARTMAPFILES += partmap-sfs_mod-fs_sfs.lst
+
+cmd-sfs_mod-fs_sfs.lst: fs/sfs.c $(fs/sfs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sfs_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh sfs > $@ || (rm -f $@; exit 1)
+
+fs-sfs_mod-fs_sfs.lst: fs/sfs.c $(fs/sfs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh sfs > $@ || (rm -f $@; exit 1)
+
+partmap-sfs_mod-fs_sfs.lst: fs/sfs.c $(fs/sfs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifs -I$(srcdir)/fs $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sfs_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh sfs > $@ || (rm -f $@; exit 1)
+
+
+sfs_mod_CFLAGS = $(COMMON_CFLAGS)
+sfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _linux.mod.
+#_linux_mod_SOURCES = loader/sparc64/ieee1275/linux.c
+#_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+#_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For linux.mod.
+#linux_mod_SOURCES = loader/sparc64/ieee1275/linux_normal.c
+#linux_mod_CFLAGS = $(COMMON_CFLAGS)
+#linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+#
+# Only arch dependant part of normal.mod will be here. Common part for
+# all architecures of normal.mod is at start and should be kept at sync
+# with other makefiles.
+# 
+# Please put arch dependant part of normal.mod at the end of list to
+# keep it simpler to update to different architectures.
+#
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/color.c                                                  \
+       normal/menu_viewer.c normal/menu_entry.c                        \
+       normal/misc.c grub_script.tab.c                                 \
+       normal/script.c                                                 \
+       normal/sparc64/setjmp.S
+CLEANFILES += normal.mod mod-normal.o mod-normal.c pre-normal.o normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_sparc64_setjmp.o und-normal.lst
+ifneq ($(normal_mod_EXPORTS),no)
+CLEANFILES += def-normal.lst
+DEFSYMFILES += def-normal.lst
+endif
+MOSTLYCLEANFILES += normal_mod-normal_arg.d normal_mod-normal_cmdline.d normal_mod-normal_command.d normal_mod-normal_completion.d normal_mod-normal_execute.d normal_mod-normal_function.d normal_mod-normal_lexer.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_menu_text.d normal_mod-normal_color.d normal_mod-normal_menu_viewer.d normal_mod-normal_menu_entry.d normal_mod-normal_misc.d normal_mod-grub_script_tab.d normal_mod-normal_script.d normal_mod-normal_sparc64_setjmp.d
+UNDSYMFILES += und-normal.lst
+
+normal.mod: pre-normal.o mod-normal.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(normal_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-normal.o mod-normal.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-normal.o: $(normal_mod_DEPENDENCIES) normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_sparc64_setjmp.o
+       -rm -f $@
+       $(TARGET_CC) $(normal_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_sparc64_setjmp.o
+
+mod-normal.o: mod-normal.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
+
+mod-normal.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'normal' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(normal_mod_EXPORTS),no)
+def-normal.lst: pre-normal.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 normal/' > $@
+endif
+
+und-normal.lst: pre-normal.o
+       echo 'normal' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+normal_mod-normal_arg.o: normal/arg.c $(normal/arg.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_arg.d
+
+CLEANFILES += cmd-normal_mod-normal_arg.lst fs-normal_mod-normal_arg.lst partmap-normal_mod-normal_arg.lst
+COMMANDFILES += cmd-normal_mod-normal_arg.lst
+FSFILES += fs-normal_mod-normal_arg.lst
+PARTMAPFILES += partmap-normal_mod-normal_arg.lst
+
+cmd-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_cmdline.o: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_cmdline.d
+
+CLEANFILES += cmd-normal_mod-normal_cmdline.lst fs-normal_mod-normal_cmdline.lst partmap-normal_mod-normal_cmdline.lst
+COMMANDFILES += cmd-normal_mod-normal_cmdline.lst
+FSFILES += fs-normal_mod-normal_cmdline.lst
+PARTMAPFILES += partmap-normal_mod-normal_cmdline.lst
+
+cmd-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_command.o: normal/command.c $(normal/command.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_command.d
+
+CLEANFILES += cmd-normal_mod-normal_command.lst fs-normal_mod-normal_command.lst partmap-normal_mod-normal_command.lst
+COMMANDFILES += cmd-normal_mod-normal_command.lst
+FSFILES += fs-normal_mod-normal_command.lst
+PARTMAPFILES += partmap-normal_mod-normal_command.lst
+
+cmd-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_completion.o: normal/completion.c $(normal/completion.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_completion.d
+
+CLEANFILES += cmd-normal_mod-normal_completion.lst fs-normal_mod-normal_completion.lst partmap-normal_mod-normal_completion.lst
+COMMANDFILES += cmd-normal_mod-normal_completion.lst
+FSFILES += fs-normal_mod-normal_completion.lst
+PARTMAPFILES += partmap-normal_mod-normal_completion.lst
+
+cmd-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_execute.o: normal/execute.c $(normal/execute.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_execute.d
+
+CLEANFILES += cmd-normal_mod-normal_execute.lst fs-normal_mod-normal_execute.lst partmap-normal_mod-normal_execute.lst
+COMMANDFILES += cmd-normal_mod-normal_execute.lst
+FSFILES += fs-normal_mod-normal_execute.lst
+PARTMAPFILES += partmap-normal_mod-normal_execute.lst
+
+cmd-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_function.o: normal/function.c $(normal/function.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_function.d
+
+CLEANFILES += cmd-normal_mod-normal_function.lst fs-normal_mod-normal_function.lst partmap-normal_mod-normal_function.lst
+COMMANDFILES += cmd-normal_mod-normal_function.lst
+FSFILES += fs-normal_mod-normal_function.lst
+PARTMAPFILES += partmap-normal_mod-normal_function.lst
+
+cmd-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_lexer.o: normal/lexer.c $(normal/lexer.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_lexer.d
+
+CLEANFILES += cmd-normal_mod-normal_lexer.lst fs-normal_mod-normal_lexer.lst partmap-normal_mod-normal_lexer.lst
+COMMANDFILES += cmd-normal_mod-normal_lexer.lst
+FSFILES += fs-normal_mod-normal_lexer.lst
+PARTMAPFILES += partmap-normal_mod-normal_lexer.lst
+
+cmd-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_main.o: normal/main.c $(normal/main.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_main.d
+
+CLEANFILES += cmd-normal_mod-normal_main.lst fs-normal_mod-normal_main.lst partmap-normal_mod-normal_main.lst
+COMMANDFILES += cmd-normal_mod-normal_main.lst
+FSFILES += fs-normal_mod-normal_main.lst
+PARTMAPFILES += partmap-normal_mod-normal_main.lst
+
+cmd-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu.o: normal/menu.c $(normal/menu.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu.d
+
+CLEANFILES += cmd-normal_mod-normal_menu.lst fs-normal_mod-normal_menu.lst partmap-normal_mod-normal_menu.lst
+COMMANDFILES += cmd-normal_mod-normal_menu.lst
+FSFILES += fs-normal_mod-normal_menu.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu.lst
+
+cmd-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_text.o: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_text.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_text.lst fs-normal_mod-normal_menu_text.lst partmap-normal_mod-normal_menu_text.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_text.lst
+FSFILES += fs-normal_mod-normal_menu_text.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_text.lst
+
+cmd-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_color.o: normal/color.c $(normal/color.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_color.d
+
+CLEANFILES += cmd-normal_mod-normal_color.lst fs-normal_mod-normal_color.lst partmap-normal_mod-normal_color.lst
+COMMANDFILES += cmd-normal_mod-normal_color.lst
+FSFILES += fs-normal_mod-normal_color.lst
+PARTMAPFILES += partmap-normal_mod-normal_color.lst
+
+cmd-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_viewer.o: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_viewer.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_viewer.lst fs-normal_mod-normal_menu_viewer.lst partmap-normal_mod-normal_menu_viewer.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_viewer.lst
+FSFILES += fs-normal_mod-normal_menu_viewer.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_viewer.lst
+
+cmd-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_entry.o: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_entry.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_entry.lst fs-normal_mod-normal_menu_entry.lst partmap-normal_mod-normal_menu_entry.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_entry.lst
+FSFILES += fs-normal_mod-normal_menu_entry.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_entry.lst
+
+cmd-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_misc.o: normal/misc.c $(normal/misc.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_misc.d
+
+CLEANFILES += cmd-normal_mod-normal_misc.lst fs-normal_mod-normal_misc.lst partmap-normal_mod-normal_misc.lst
+COMMANDFILES += cmd-normal_mod-normal_misc.lst
+FSFILES += fs-normal_mod-normal_misc.lst
+PARTMAPFILES += partmap-normal_mod-normal_misc.lst
+
+cmd-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-grub_script_tab.o: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES)
+       $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-grub_script_tab.d
+
+CLEANFILES += cmd-normal_mod-grub_script_tab.lst fs-normal_mod-grub_script_tab.lst partmap-normal_mod-grub_script_tab.lst
+COMMANDFILES += cmd-normal_mod-grub_script_tab.lst
+FSFILES += fs-normal_mod-grub_script_tab.lst
+PARTMAPFILES += partmap-normal_mod-grub_script_tab.lst
+
+cmd-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_script.o: normal/script.c $(normal/script.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_script.d
+
+CLEANFILES += cmd-normal_mod-normal_script.lst fs-normal_mod-normal_script.lst partmap-normal_mod-normal_script.lst
+COMMANDFILES += cmd-normal_mod-normal_script.lst
+FSFILES += fs-normal_mod-normal_script.lst
+PARTMAPFILES += partmap-normal_mod-normal_script.lst
+
+cmd-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_sparc64_setjmp.o: normal/sparc64/setjmp.S $(normal/sparc64/setjmp.S_DEPENDENCIES)
+       $(TARGET_CC) -Inormal/sparc64 -I$(srcdir)/normal/sparc64 $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_sparc64_setjmp.d
+
+CLEANFILES += cmd-normal_mod-normal_sparc64_setjmp.lst fs-normal_mod-normal_sparc64_setjmp.lst partmap-normal_mod-normal_sparc64_setjmp.lst
+COMMANDFILES += cmd-normal_mod-normal_sparc64_setjmp.lst
+FSFILES += fs-normal_mod-normal_sparc64_setjmp.lst
+PARTMAPFILES += partmap-normal_mod-normal_sparc64_setjmp.lst
+
+cmd-normal_mod-normal_sparc64_setjmp.lst: normal/sparc64/setjmp.S $(normal/sparc64/setjmp.S_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal/sparc64 -I$(srcdir)/normal/sparc64 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_sparc64_setjmp.lst: normal/sparc64/setjmp.S $(normal/sparc64/setjmp.S_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal/sparc64 -I$(srcdir)/normal/sparc64 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<       | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_sparc64_setjmp.lst: normal/sparc64/setjmp.S $(normal/sparc64/setjmp.S_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal/sparc64 -I$(srcdir)/normal/sparc64 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For hello.mod.
+hello_mod_SOURCES = hello/hello.c
+CLEANFILES += hello.mod mod-hello.o mod-hello.c pre-hello.o hello_mod-hello_hello.o und-hello.lst
+ifneq ($(hello_mod_EXPORTS),no)
+CLEANFILES += def-hello.lst
+DEFSYMFILES += def-hello.lst
+endif
+MOSTLYCLEANFILES += hello_mod-hello_hello.d
+UNDSYMFILES += und-hello.lst
+
+hello.mod: pre-hello.o mod-hello.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(hello_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-hello.o mod-hello.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-hello.o: $(hello_mod_DEPENDENCIES) hello_mod-hello_hello.o
+       -rm -f $@
+       $(TARGET_CC) $(hello_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ hello_mod-hello_hello.o
+
+mod-hello.o: mod-hello.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hello_mod_CFLAGS) -c -o $@ $<
+
+mod-hello.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'hello' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(hello_mod_EXPORTS),no)
+def-hello.lst: pre-hello.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 hello/' > $@
+endif
+
+und-hello.lst: pre-hello.o
+       echo 'hello' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+hello_mod-hello_hello.o: hello/hello.c $(hello/hello.c_DEPENDENCIES)
+       $(TARGET_CC) -Ihello -I$(srcdir)/hello $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(hello_mod_CFLAGS) -MD -c -o $@ $<
+-include hello_mod-hello_hello.d
+
+CLEANFILES += cmd-hello_mod-hello_hello.lst fs-hello_mod-hello_hello.lst partmap-hello_mod-hello_hello.lst
+COMMANDFILES += cmd-hello_mod-hello_hello.lst
+FSFILES += fs-hello_mod-hello_hello.lst
+PARTMAPFILES += partmap-hello_mod-hello_hello.lst
+
+cmd-hello_mod-hello_hello.lst: hello/hello.c $(hello/hello.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ihello -I$(srcdir)/hello $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hello_mod_CFLAGS) -E $<    | sh $(srcdir)/gencmdlist.sh hello > $@ || (rm -f $@; exit 1)
+
+fs-hello_mod-hello_hello.lst: hello/hello.c $(hello/hello.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ihello -I$(srcdir)/hello $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hello_mod_CFLAGS) -E $<    | sh $(srcdir)/genfslist.sh hello > $@ || (rm -f $@; exit 1)
+
+partmap-hello_mod-hello_hello.lst: hello/hello.c $(hello/hello.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ihello -I$(srcdir)/hello $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(hello_mod_CFLAGS) -E $<    | sh $(srcdir)/genpartmaplist.sh hello > $@ || (rm -f $@; exit 1)
+
+
+hello_mod_CFLAGS = $(COMMON_CFLAGS)
+hello_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For boot.mod.
+boot_mod_SOURCES = commands/boot.c
+CLEANFILES += boot.mod mod-boot.o mod-boot.c pre-boot.o boot_mod-commands_boot.o und-boot.lst
+ifneq ($(boot_mod_EXPORTS),no)
+CLEANFILES += def-boot.lst
+DEFSYMFILES += def-boot.lst
+endif
+MOSTLYCLEANFILES += boot_mod-commands_boot.d
+UNDSYMFILES += und-boot.lst
+
+boot.mod: pre-boot.o mod-boot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(boot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-boot.o mod-boot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-boot.o: $(boot_mod_DEPENDENCIES) boot_mod-commands_boot.o
+       -rm -f $@
+       $(TARGET_CC) $(boot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ boot_mod-commands_boot.o
+
+mod-boot.o: mod-boot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(boot_mod_CFLAGS) -c -o $@ $<
+
+mod-boot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'boot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(boot_mod_EXPORTS),no)
+def-boot.lst: pre-boot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 boot/' > $@
+endif
+
+und-boot.lst: pre-boot.o
+       echo 'boot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+boot_mod-commands_boot.o: commands/boot.c $(commands/boot.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(boot_mod_CFLAGS) -MD -c -o $@ $<
+-include boot_mod-commands_boot.d
+
+CLEANFILES += cmd-boot_mod-commands_boot.lst fs-boot_mod-commands_boot.lst partmap-boot_mod-commands_boot.lst
+COMMANDFILES += cmd-boot_mod-commands_boot.lst
+FSFILES += fs-boot_mod-commands_boot.lst
+PARTMAPFILES += partmap-boot_mod-commands_boot.lst
+
+cmd-boot_mod-commands_boot.lst: commands/boot.c $(commands/boot.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(boot_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh boot > $@ || (rm -f $@; exit 1)
+
+fs-boot_mod-commands_boot.lst: commands/boot.c $(commands/boot.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(boot_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh boot > $@ || (rm -f $@; exit 1)
+
+partmap-boot_mod-commands_boot.lst: commands/boot.c $(commands/boot.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(boot_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh boot > $@ || (rm -f $@; exit 1)
+
+
+boot_mod_CFLAGS = $(COMMON_CFLAGS)
+boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For terminal.mod.
+terminal_mod_SOURCES = commands/terminal.c
+CLEANFILES += terminal.mod mod-terminal.o mod-terminal.c pre-terminal.o terminal_mod-commands_terminal.o und-terminal.lst
+ifneq ($(terminal_mod_EXPORTS),no)
+CLEANFILES += def-terminal.lst
+DEFSYMFILES += def-terminal.lst
+endif
+MOSTLYCLEANFILES += terminal_mod-commands_terminal.d
+UNDSYMFILES += und-terminal.lst
+
+terminal.mod: pre-terminal.o mod-terminal.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(terminal_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-terminal.o mod-terminal.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-terminal.o: $(terminal_mod_DEPENDENCIES) terminal_mod-commands_terminal.o
+       -rm -f $@
+       $(TARGET_CC) $(terminal_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ terminal_mod-commands_terminal.o
+
+mod-terminal.o: mod-terminal.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(terminal_mod_CFLAGS) -c -o $@ $<
+
+mod-terminal.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'terminal' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(terminal_mod_EXPORTS),no)
+def-terminal.lst: pre-terminal.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 terminal/' > $@
+endif
+
+und-terminal.lst: pre-terminal.o
+       echo 'terminal' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+terminal_mod-commands_terminal.o: commands/terminal.c $(commands/terminal.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(terminal_mod_CFLAGS) -MD -c -o $@ $<
+-include terminal_mod-commands_terminal.d
+
+CLEANFILES += cmd-terminal_mod-commands_terminal.lst fs-terminal_mod-commands_terminal.lst partmap-terminal_mod-commands_terminal.lst
+COMMANDFILES += cmd-terminal_mod-commands_terminal.lst
+FSFILES += fs-terminal_mod-commands_terminal.lst
+PARTMAPFILES += partmap-terminal_mod-commands_terminal.lst
+
+cmd-terminal_mod-commands_terminal.lst: commands/terminal.c $(commands/terminal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(terminal_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh terminal > $@ || (rm -f $@; exit 1)
+
+fs-terminal_mod-commands_terminal.lst: commands/terminal.c $(commands/terminal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(terminal_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh terminal > $@ || (rm -f $@; exit 1)
+
+partmap-terminal_mod-commands_terminal.lst: commands/terminal.c $(commands/terminal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(terminal_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh terminal > $@ || (rm -f $@; exit 1)
+
+
+terminal_mod_CFLAGS = $(COMMON_CFLAGS)
+terminal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ls.mod.
+ls_mod_SOURCES = commands/ls.c
+CLEANFILES += ls.mod mod-ls.o mod-ls.c pre-ls.o ls_mod-commands_ls.o und-ls.lst
+ifneq ($(ls_mod_EXPORTS),no)
+CLEANFILES += def-ls.lst
+DEFSYMFILES += def-ls.lst
+endif
+MOSTLYCLEANFILES += ls_mod-commands_ls.d
+UNDSYMFILES += und-ls.lst
+
+ls.mod: pre-ls.o mod-ls.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(ls_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-ls.o mod-ls.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-ls.o: $(ls_mod_DEPENDENCIES) ls_mod-commands_ls.o
+       -rm -f $@
+       $(TARGET_CC) $(ls_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ ls_mod-commands_ls.o
+
+mod-ls.o: mod-ls.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ls_mod_CFLAGS) -c -o $@ $<
+
+mod-ls.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'ls' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(ls_mod_EXPORTS),no)
+def-ls.lst: pre-ls.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 ls/' > $@
+endif
+
+und-ls.lst: pre-ls.o
+       echo 'ls' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+ls_mod-commands_ls.o: commands/ls.c $(commands/ls.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(ls_mod_CFLAGS) -MD -c -o $@ $<
+-include ls_mod-commands_ls.d
+
+CLEANFILES += cmd-ls_mod-commands_ls.lst fs-ls_mod-commands_ls.lst partmap-ls_mod-commands_ls.lst
+COMMANDFILES += cmd-ls_mod-commands_ls.lst
+FSFILES += fs-ls_mod-commands_ls.lst
+PARTMAPFILES += partmap-ls_mod-commands_ls.lst
+
+cmd-ls_mod-commands_ls.lst: commands/ls.c $(commands/ls.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ls_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh ls > $@ || (rm -f $@; exit 1)
+
+fs-ls_mod-commands_ls.lst: commands/ls.c $(commands/ls.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ls_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh ls > $@ || (rm -f $@; exit 1)
+
+partmap-ls_mod-commands_ls.lst: commands/ls.c $(commands/ls.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ls_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh ls > $@ || (rm -f $@; exit 1)
+
+
+ls_mod_CFLAGS = $(COMMON_CFLAGS)
+ls_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For cmp.mod.
+cmp_mod_SOURCES = commands/cmp.c
+CLEANFILES += cmp.mod mod-cmp.o mod-cmp.c pre-cmp.o cmp_mod-commands_cmp.o und-cmp.lst
+ifneq ($(cmp_mod_EXPORTS),no)
+CLEANFILES += def-cmp.lst
+DEFSYMFILES += def-cmp.lst
+endif
+MOSTLYCLEANFILES += cmp_mod-commands_cmp.d
+UNDSYMFILES += und-cmp.lst
+
+cmp.mod: pre-cmp.o mod-cmp.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(cmp_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-cmp.o mod-cmp.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-cmp.o: $(cmp_mod_DEPENDENCIES) cmp_mod-commands_cmp.o
+       -rm -f $@
+       $(TARGET_CC) $(cmp_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ cmp_mod-commands_cmp.o
+
+mod-cmp.o: mod-cmp.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cmp_mod_CFLAGS) -c -o $@ $<
+
+mod-cmp.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'cmp' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(cmp_mod_EXPORTS),no)
+def-cmp.lst: pre-cmp.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 cmp/' > $@
+endif
+
+und-cmp.lst: pre-cmp.o
+       echo 'cmp' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+cmp_mod-commands_cmp.o: commands/cmp.c $(commands/cmp.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(cmp_mod_CFLAGS) -MD -c -o $@ $<
+-include cmp_mod-commands_cmp.d
+
+CLEANFILES += cmd-cmp_mod-commands_cmp.lst fs-cmp_mod-commands_cmp.lst partmap-cmp_mod-commands_cmp.lst
+COMMANDFILES += cmd-cmp_mod-commands_cmp.lst
+FSFILES += fs-cmp_mod-commands_cmp.lst
+PARTMAPFILES += partmap-cmp_mod-commands_cmp.lst
+
+cmd-cmp_mod-commands_cmp.lst: commands/cmp.c $(commands/cmp.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cmp_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh cmp > $@ || (rm -f $@; exit 1)
+
+fs-cmp_mod-commands_cmp.lst: commands/cmp.c $(commands/cmp.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cmp_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh cmp > $@ || (rm -f $@; exit 1)
+
+partmap-cmp_mod-commands_cmp.lst: commands/cmp.c $(commands/cmp.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cmp_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh cmp > $@ || (rm -f $@; exit 1)
+
+
+cmp_mod_CFLAGS = $(COMMON_CFLAGS)
+cmp_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For cat.mod.
+cat_mod_SOURCES = commands/cat.c
+CLEANFILES += cat.mod mod-cat.o mod-cat.c pre-cat.o cat_mod-commands_cat.o und-cat.lst
+ifneq ($(cat_mod_EXPORTS),no)
+CLEANFILES += def-cat.lst
+DEFSYMFILES += def-cat.lst
+endif
+MOSTLYCLEANFILES += cat_mod-commands_cat.d
+UNDSYMFILES += und-cat.lst
+
+cat.mod: pre-cat.o mod-cat.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(cat_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-cat.o mod-cat.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-cat.o: $(cat_mod_DEPENDENCIES) cat_mod-commands_cat.o
+       -rm -f $@
+       $(TARGET_CC) $(cat_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ cat_mod-commands_cat.o
+
+mod-cat.o: mod-cat.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cat_mod_CFLAGS) -c -o $@ $<
+
+mod-cat.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'cat' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(cat_mod_EXPORTS),no)
+def-cat.lst: pre-cat.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 cat/' > $@
+endif
+
+und-cat.lst: pre-cat.o
+       echo 'cat' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+cat_mod-commands_cat.o: commands/cat.c $(commands/cat.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(cat_mod_CFLAGS) -MD -c -o $@ $<
+-include cat_mod-commands_cat.d
+
+CLEANFILES += cmd-cat_mod-commands_cat.lst fs-cat_mod-commands_cat.lst partmap-cat_mod-commands_cat.lst
+COMMANDFILES += cmd-cat_mod-commands_cat.lst
+FSFILES += fs-cat_mod-commands_cat.lst
+PARTMAPFILES += partmap-cat_mod-commands_cat.lst
+
+cmd-cat_mod-commands_cat.lst: commands/cat.c $(commands/cat.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cat_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh cat > $@ || (rm -f $@; exit 1)
+
+fs-cat_mod-commands_cat.lst: commands/cat.c $(commands/cat.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cat_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh cat > $@ || (rm -f $@; exit 1)
+
+partmap-cat_mod-commands_cat.lst: commands/cat.c $(commands/cat.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(cat_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh cat > $@ || (rm -f $@; exit 1)
+
+
+cat_mod_CFLAGS = $(COMMON_CFLAGS)
+cat_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For font.mod.
+font_mod_SOURCES = font/manager.c
+CLEANFILES += font.mod mod-font.o mod-font.c pre-font.o font_mod-font_manager.o und-font.lst
+ifneq ($(font_mod_EXPORTS),no)
+CLEANFILES += def-font.lst
+DEFSYMFILES += def-font.lst
+endif
+MOSTLYCLEANFILES += font_mod-font_manager.d
+UNDSYMFILES += und-font.lst
+
+font.mod: pre-font.o mod-font.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(font_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-font.o mod-font.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-font.o: $(font_mod_DEPENDENCIES) font_mod-font_manager.o
+       -rm -f $@
+       $(TARGET_CC) $(font_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ font_mod-font_manager.o
+
+mod-font.o: mod-font.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(font_mod_CFLAGS) -c -o $@ $<
+
+mod-font.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'font' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(font_mod_EXPORTS),no)
+def-font.lst: pre-font.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 font/' > $@
+endif
+
+und-font.lst: pre-font.o
+       echo 'font' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+font_mod-font_manager.o: font/manager.c $(font/manager.c_DEPENDENCIES)
+       $(TARGET_CC) -Ifont -I$(srcdir)/font $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(font_mod_CFLAGS) -MD -c -o $@ $<
+-include font_mod-font_manager.d
+
+CLEANFILES += cmd-font_mod-font_manager.lst fs-font_mod-font_manager.lst partmap-font_mod-font_manager.lst
+COMMANDFILES += cmd-font_mod-font_manager.lst
+FSFILES += fs-font_mod-font_manager.lst
+PARTMAPFILES += partmap-font_mod-font_manager.lst
+
+cmd-font_mod-font_manager.lst: font/manager.c $(font/manager.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ifont -I$(srcdir)/font $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(font_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh font > $@ || (rm -f $@; exit 1)
+
+fs-font_mod-font_manager.lst: font/manager.c $(font/manager.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ifont -I$(srcdir)/font $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(font_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh font > $@ || (rm -f $@; exit 1)
+
+partmap-font_mod-font_manager.lst: font/manager.c $(font/manager.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ifont -I$(srcdir)/font $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(font_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh font > $@ || (rm -f $@; exit 1)
+
+
+font_mod_CFLAGS = $(COMMON_CFLAGS)
+font_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For amiga.mod
+amiga_mod_SOURCES = partmap/amiga.c
+CLEANFILES += amiga.mod mod-amiga.o mod-amiga.c pre-amiga.o amiga_mod-partmap_amiga.o und-amiga.lst
+ifneq ($(amiga_mod_EXPORTS),no)
+CLEANFILES += def-amiga.lst
+DEFSYMFILES += def-amiga.lst
+endif
+MOSTLYCLEANFILES += amiga_mod-partmap_amiga.d
+UNDSYMFILES += und-amiga.lst
+
+amiga.mod: pre-amiga.o mod-amiga.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(amiga_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-amiga.o mod-amiga.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-amiga.o: $(amiga_mod_DEPENDENCIES) amiga_mod-partmap_amiga.o
+       -rm -f $@
+       $(TARGET_CC) $(amiga_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ amiga_mod-partmap_amiga.o
+
+mod-amiga.o: mod-amiga.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(amiga_mod_CFLAGS) -c -o $@ $<
+
+mod-amiga.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'amiga' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(amiga_mod_EXPORTS),no)
+def-amiga.lst: pre-amiga.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 amiga/' > $@
+endif
+
+und-amiga.lst: pre-amiga.o
+       echo 'amiga' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+amiga_mod-partmap_amiga.o: partmap/amiga.c $(partmap/amiga.c_DEPENDENCIES)
+       $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(amiga_mod_CFLAGS) -MD -c -o $@ $<
+-include amiga_mod-partmap_amiga.d
+
+CLEANFILES += cmd-amiga_mod-partmap_amiga.lst fs-amiga_mod-partmap_amiga.lst partmap-amiga_mod-partmap_amiga.lst
+COMMANDFILES += cmd-amiga_mod-partmap_amiga.lst
+FSFILES += fs-amiga_mod-partmap_amiga.lst
+PARTMAPFILES += partmap-amiga_mod-partmap_amiga.lst
+
+cmd-amiga_mod-partmap_amiga.lst: partmap/amiga.c $(partmap/amiga.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(amiga_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh amiga > $@ || (rm -f $@; exit 1)
+
+fs-amiga_mod-partmap_amiga.lst: partmap/amiga.c $(partmap/amiga.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(amiga_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh amiga > $@ || (rm -f $@; exit 1)
+
+partmap-amiga_mod-partmap_amiga.lst: partmap/amiga.c $(partmap/amiga.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(amiga_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh amiga > $@ || (rm -f $@; exit 1)
+
+
+amiga_mod_CFLAGS = $(COMMON_CFLAGS)
+amiga_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For apple.mod
+apple_mod_SOURCES = partmap/apple.c
+CLEANFILES += apple.mod mod-apple.o mod-apple.c pre-apple.o apple_mod-partmap_apple.o und-apple.lst
+ifneq ($(apple_mod_EXPORTS),no)
+CLEANFILES += def-apple.lst
+DEFSYMFILES += def-apple.lst
+endif
+MOSTLYCLEANFILES += apple_mod-partmap_apple.d
+UNDSYMFILES += und-apple.lst
+
+apple.mod: pre-apple.o mod-apple.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(apple_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-apple.o mod-apple.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-apple.o: $(apple_mod_DEPENDENCIES) apple_mod-partmap_apple.o
+       -rm -f $@
+       $(TARGET_CC) $(apple_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ apple_mod-partmap_apple.o
+
+mod-apple.o: mod-apple.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(apple_mod_CFLAGS) -c -o $@ $<
+
+mod-apple.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'apple' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(apple_mod_EXPORTS),no)
+def-apple.lst: pre-apple.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 apple/' > $@
+endif
+
+und-apple.lst: pre-apple.o
+       echo 'apple' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+apple_mod-partmap_apple.o: partmap/apple.c $(partmap/apple.c_DEPENDENCIES)
+       $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(apple_mod_CFLAGS) -MD -c -o $@ $<
+-include apple_mod-partmap_apple.d
+
+CLEANFILES += cmd-apple_mod-partmap_apple.lst fs-apple_mod-partmap_apple.lst partmap-apple_mod-partmap_apple.lst
+COMMANDFILES += cmd-apple_mod-partmap_apple.lst
+FSFILES += fs-apple_mod-partmap_apple.lst
+PARTMAPFILES += partmap-apple_mod-partmap_apple.lst
+
+cmd-apple_mod-partmap_apple.lst: partmap/apple.c $(partmap/apple.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(apple_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh apple > $@ || (rm -f $@; exit 1)
+
+fs-apple_mod-partmap_apple.lst: partmap/apple.c $(partmap/apple.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(apple_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh apple > $@ || (rm -f $@; exit 1)
+
+partmap-apple_mod-partmap_apple.lst: partmap/apple.c $(partmap/apple.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(apple_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh apple > $@ || (rm -f $@; exit 1)
+
+
+apple_mod_CFLAGS = $(COMMON_CFLAGS)
+apple_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pc.mod
+pc_mod_SOURCES = partmap/pc.c
+CLEANFILES += pc.mod mod-pc.o mod-pc.c pre-pc.o pc_mod-partmap_pc.o und-pc.lst
+ifneq ($(pc_mod_EXPORTS),no)
+CLEANFILES += def-pc.lst
+DEFSYMFILES += def-pc.lst
+endif
+MOSTLYCLEANFILES += pc_mod-partmap_pc.d
+UNDSYMFILES += und-pc.lst
+
+pc.mod: pre-pc.o mod-pc.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(pc_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-pc.o mod-pc.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-pc.o: $(pc_mod_DEPENDENCIES) pc_mod-partmap_pc.o
+       -rm -f $@
+       $(TARGET_CC) $(pc_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pc_mod-partmap_pc.o
+
+mod-pc.o: mod-pc.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pc_mod_CFLAGS) -c -o $@ $<
+
+mod-pc.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'pc' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(pc_mod_EXPORTS),no)
+def-pc.lst: pre-pc.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 pc/' > $@
+endif
+
+und-pc.lst: pre-pc.o
+       echo 'pc' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+pc_mod-partmap_pc.o: partmap/pc.c $(partmap/pc.c_DEPENDENCIES)
+       $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(pc_mod_CFLAGS) -MD -c -o $@ $<
+-include pc_mod-partmap_pc.d
+
+CLEANFILES += cmd-pc_mod-partmap_pc.lst fs-pc_mod-partmap_pc.lst partmap-pc_mod-partmap_pc.lst
+COMMANDFILES += cmd-pc_mod-partmap_pc.lst
+FSFILES += fs-pc_mod-partmap_pc.lst
+PARTMAPFILES += partmap-pc_mod-partmap_pc.lst
+
+cmd-pc_mod-partmap_pc.lst: partmap/pc.c $(partmap/pc.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pc_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh pc > $@ || (rm -f $@; exit 1)
+
+fs-pc_mod-partmap_pc.lst: partmap/pc.c $(partmap/pc.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pc_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh pc > $@ || (rm -f $@; exit 1)
+
+partmap-pc_mod-partmap_pc.lst: partmap/pc.c $(partmap/pc.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pc_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh pc > $@ || (rm -f $@; exit 1)
+
+
+pc_mod_CFLAGS = $(COMMON_CFLAGS)
+pc_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For sun.mod
+sun_mod_SOURCES = partmap/sun.c
+CLEANFILES += sun.mod mod-sun.o mod-sun.c pre-sun.o sun_mod-partmap_sun.o und-sun.lst
+ifneq ($(sun_mod_EXPORTS),no)
+CLEANFILES += def-sun.lst
+DEFSYMFILES += def-sun.lst
+endif
+MOSTLYCLEANFILES += sun_mod-partmap_sun.d
+UNDSYMFILES += und-sun.lst
+
+sun.mod: pre-sun.o mod-sun.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(sun_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-sun.o mod-sun.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-sun.o: $(sun_mod_DEPENDENCIES) sun_mod-partmap_sun.o
+       -rm -f $@
+       $(TARGET_CC) $(sun_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ sun_mod-partmap_sun.o
+
+mod-sun.o: mod-sun.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sun_mod_CFLAGS) -c -o $@ $<
+
+mod-sun.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'sun' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(sun_mod_EXPORTS),no)
+def-sun.lst: pre-sun.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 sun/' > $@
+endif
+
+und-sun.lst: pre-sun.o
+       echo 'sun' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+sun_mod-partmap_sun.o: partmap/sun.c $(partmap/sun.c_DEPENDENCIES)
+       $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(sun_mod_CFLAGS) -MD -c -o $@ $<
+-include sun_mod-partmap_sun.d
+
+CLEANFILES += cmd-sun_mod-partmap_sun.lst fs-sun_mod-partmap_sun.lst partmap-sun_mod-partmap_sun.lst
+COMMANDFILES += cmd-sun_mod-partmap_sun.lst
+FSFILES += fs-sun_mod-partmap_sun.lst
+PARTMAPFILES += partmap-sun_mod-partmap_sun.lst
+
+cmd-sun_mod-partmap_sun.lst: partmap/sun.c $(partmap/sun.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sun_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh sun > $@ || (rm -f $@; exit 1)
+
+fs-sun_mod-partmap_sun.lst: partmap/sun.c $(partmap/sun.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sun_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh sun > $@ || (rm -f $@; exit 1)
+
+partmap-sun_mod-partmap_sun.lst: partmap/sun.c $(partmap/sun.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sun_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh sun > $@ || (rm -f $@; exit 1)
+
+
+sun_mod_CFLAGS = $(COMMON_CFLAGS)
+sun_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For acorn.mod
+acorn_mod_SOURCES = partmap/acorn.c
+CLEANFILES += acorn.mod mod-acorn.o mod-acorn.c pre-acorn.o acorn_mod-partmap_acorn.o und-acorn.lst
+ifneq ($(acorn_mod_EXPORTS),no)
+CLEANFILES += def-acorn.lst
+DEFSYMFILES += def-acorn.lst
+endif
+MOSTLYCLEANFILES += acorn_mod-partmap_acorn.d
+UNDSYMFILES += und-acorn.lst
+
+acorn.mod: pre-acorn.o mod-acorn.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(acorn_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-acorn.o mod-acorn.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-acorn.o: $(acorn_mod_DEPENDENCIES) acorn_mod-partmap_acorn.o
+       -rm -f $@
+       $(TARGET_CC) $(acorn_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ acorn_mod-partmap_acorn.o
+
+mod-acorn.o: mod-acorn.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(acorn_mod_CFLAGS) -c -o $@ $<
+
+mod-acorn.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'acorn' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(acorn_mod_EXPORTS),no)
+def-acorn.lst: pre-acorn.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 acorn/' > $@
+endif
+
+und-acorn.lst: pre-acorn.o
+       echo 'acorn' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+acorn_mod-partmap_acorn.o: partmap/acorn.c $(partmap/acorn.c_DEPENDENCIES)
+       $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(acorn_mod_CFLAGS) -MD -c -o $@ $<
+-include acorn_mod-partmap_acorn.d
+
+CLEANFILES += cmd-acorn_mod-partmap_acorn.lst fs-acorn_mod-partmap_acorn.lst partmap-acorn_mod-partmap_acorn.lst
+COMMANDFILES += cmd-acorn_mod-partmap_acorn.lst
+FSFILES += fs-acorn_mod-partmap_acorn.lst
+PARTMAPFILES += partmap-acorn_mod-partmap_acorn.lst
+
+cmd-acorn_mod-partmap_acorn.lst: partmap/acorn.c $(partmap/acorn.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(acorn_mod_CFLAGS) -E $<        | sh $(srcdir)/gencmdlist.sh acorn > $@ || (rm -f $@; exit 1)
+
+fs-acorn_mod-partmap_acorn.lst: partmap/acorn.c $(partmap/acorn.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(acorn_mod_CFLAGS) -E $<        | sh $(srcdir)/genfslist.sh acorn > $@ || (rm -f $@; exit 1)
+
+partmap-acorn_mod-partmap_acorn.lst: partmap/acorn.c $(partmap/acorn.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ipartmap -I$(srcdir)/partmap $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(acorn_mod_CFLAGS) -E $<        | sh $(srcdir)/genpartmaplist.sh acorn > $@ || (rm -f $@; exit 1)
+
+
+acorn_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For loopback.mod
+loopback_mod_SOURCES = disk/loopback.c
+CLEANFILES += loopback.mod mod-loopback.o mod-loopback.c pre-loopback.o loopback_mod-disk_loopback.o und-loopback.lst
+ifneq ($(loopback_mod_EXPORTS),no)
+CLEANFILES += def-loopback.lst
+DEFSYMFILES += def-loopback.lst
+endif
+MOSTLYCLEANFILES += loopback_mod-disk_loopback.d
+UNDSYMFILES += und-loopback.lst
+
+loopback.mod: pre-loopback.o mod-loopback.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(loopback_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-loopback.o mod-loopback.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-loopback.o: $(loopback_mod_DEPENDENCIES) loopback_mod-disk_loopback.o
+       -rm -f $@
+       $(TARGET_CC) $(loopback_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ loopback_mod-disk_loopback.o
+
+mod-loopback.o: mod-loopback.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loopback_mod_CFLAGS) -c -o $@ $<
+
+mod-loopback.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'loopback' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(loopback_mod_EXPORTS),no)
+def-loopback.lst: pre-loopback.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 loopback/' > $@
+endif
+
+und-loopback.lst: pre-loopback.o
+       echo 'loopback' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+loopback_mod-disk_loopback.o: disk/loopback.c $(disk/loopback.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(loopback_mod_CFLAGS) -MD -c -o $@ $<
+-include loopback_mod-disk_loopback.d
+
+CLEANFILES += cmd-loopback_mod-disk_loopback.lst fs-loopback_mod-disk_loopback.lst partmap-loopback_mod-disk_loopback.lst
+COMMANDFILES += cmd-loopback_mod-disk_loopback.lst
+FSFILES += fs-loopback_mod-disk_loopback.lst
+PARTMAPFILES += partmap-loopback_mod-disk_loopback.lst
+
+cmd-loopback_mod-disk_loopback.lst: disk/loopback.c $(disk/loopback.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loopback_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh loopback > $@ || (rm -f $@; exit 1)
+
+fs-loopback_mod-disk_loopback.lst: disk/loopback.c $(disk/loopback.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loopback_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh loopback > $@ || (rm -f $@; exit 1)
+
+partmap-loopback_mod-disk_loopback.lst: disk/loopback.c $(disk/loopback.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loopback_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh loopback > $@ || (rm -f $@; exit 1)
+
+
+loopback_mod_CFLAGS = $(COMMON_CFLAGS)
+loopback_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For suspend.mod
+suspend_mod_SOURCES = commands/ieee1275/suspend.c
+CLEANFILES += suspend.mod mod-suspend.o mod-suspend.c pre-suspend.o suspend_mod-commands_ieee1275_suspend.o und-suspend.lst
+ifneq ($(suspend_mod_EXPORTS),no)
+CLEANFILES += def-suspend.lst
+DEFSYMFILES += def-suspend.lst
+endif
+MOSTLYCLEANFILES += suspend_mod-commands_ieee1275_suspend.d
+UNDSYMFILES += und-suspend.lst
+
+suspend.mod: pre-suspend.o mod-suspend.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(suspend_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-suspend.o mod-suspend.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-suspend.o: $(suspend_mod_DEPENDENCIES) suspend_mod-commands_ieee1275_suspend.o
+       -rm -f $@
+       $(TARGET_CC) $(suspend_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ suspend_mod-commands_ieee1275_suspend.o
+
+mod-suspend.o: mod-suspend.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(suspend_mod_CFLAGS) -c -o $@ $<
+
+mod-suspend.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'suspend' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(suspend_mod_EXPORTS),no)
+def-suspend.lst: pre-suspend.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 suspend/' > $@
+endif
+
+und-suspend.lst: pre-suspend.o
+       echo 'suspend' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+suspend_mod-commands_ieee1275_suspend.o: commands/ieee1275/suspend.c $(commands/ieee1275/suspend.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands/ieee1275 -I$(srcdir)/commands/ieee1275 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(suspend_mod_CFLAGS) -MD -c -o $@ $<
+-include suspend_mod-commands_ieee1275_suspend.d
+
+CLEANFILES += cmd-suspend_mod-commands_ieee1275_suspend.lst fs-suspend_mod-commands_ieee1275_suspend.lst partmap-suspend_mod-commands_ieee1275_suspend.lst
+COMMANDFILES += cmd-suspend_mod-commands_ieee1275_suspend.lst
+FSFILES += fs-suspend_mod-commands_ieee1275_suspend.lst
+PARTMAPFILES += partmap-suspend_mod-commands_ieee1275_suspend.lst
+
+cmd-suspend_mod-commands_ieee1275_suspend.lst: commands/ieee1275/suspend.c $(commands/ieee1275/suspend.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands/ieee1275 -I$(srcdir)/commands/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(suspend_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh suspend > $@ || (rm -f $@; exit 1)
+
+fs-suspend_mod-commands_ieee1275_suspend.lst: commands/ieee1275/suspend.c $(commands/ieee1275/suspend.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands/ieee1275 -I$(srcdir)/commands/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(suspend_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh suspend > $@ || (rm -f $@; exit 1)
+
+partmap-suspend_mod-commands_ieee1275_suspend.lst: commands/ieee1275/suspend.c $(commands/ieee1275/suspend.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands/ieee1275 -I$(srcdir)/commands/ieee1275 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(suspend_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh suspend > $@ || (rm -f $@; exit 1)
+
+
+suspend_mod_CFLAGS = $(COMMON_CFLAGS)
+suspend_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reboot.mod
+reboot_mod_SOURCES = commands/reboot.c
+CLEANFILES += reboot.mod mod-reboot.o mod-reboot.c pre-reboot.o reboot_mod-commands_reboot.o und-reboot.lst
+ifneq ($(reboot_mod_EXPORTS),no)
+CLEANFILES += def-reboot.lst
+DEFSYMFILES += def-reboot.lst
+endif
+MOSTLYCLEANFILES += reboot_mod-commands_reboot.d
+UNDSYMFILES += und-reboot.lst
+
+reboot.mod: pre-reboot.o mod-reboot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(reboot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-reboot.o mod-reboot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-reboot.o: $(reboot_mod_DEPENDENCIES) reboot_mod-commands_reboot.o
+       -rm -f $@
+       $(TARGET_CC) $(reboot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ reboot_mod-commands_reboot.o
+
+mod-reboot.o: mod-reboot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -c -o $@ $<
+
+mod-reboot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'reboot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(reboot_mod_EXPORTS),no)
+def-reboot.lst: pre-reboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 reboot/' > $@
+endif
+
+und-reboot.lst: pre-reboot.o
+       echo 'reboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+reboot_mod-commands_reboot.o: commands/reboot.c $(commands/reboot.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -MD -c -o $@ $<
+-include reboot_mod-commands_reboot.d
+
+CLEANFILES += cmd-reboot_mod-commands_reboot.lst fs-reboot_mod-commands_reboot.lst partmap-reboot_mod-commands_reboot.lst
+COMMANDFILES += cmd-reboot_mod-commands_reboot.lst
+FSFILES += fs-reboot_mod-commands_reboot.lst
+PARTMAPFILES += partmap-reboot_mod-commands_reboot.lst
+
+cmd-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh reboot > $@ || (rm -f $@; exit 1)
+
+fs-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh reboot > $@ || (rm -f $@; exit 1)
+
+partmap-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh reboot > $@ || (rm -f $@; exit 1)
+
+
+reboot_mod_CFLAGS = $(COMMON_CFLAGS)
+reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For halt.mod
+halt_mod_SOURCES = commands/halt.c
+CLEANFILES += halt.mod mod-halt.o mod-halt.c pre-halt.o halt_mod-commands_halt.o und-halt.lst
+ifneq ($(halt_mod_EXPORTS),no)
+CLEANFILES += def-halt.lst
+DEFSYMFILES += def-halt.lst
+endif
+MOSTLYCLEANFILES += halt_mod-commands_halt.d
+UNDSYMFILES += und-halt.lst
+
+halt.mod: pre-halt.o mod-halt.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(halt_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-halt.o mod-halt.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-halt.o: $(halt_mod_DEPENDENCIES) halt_mod-commands_halt.o
+       -rm -f $@
+       $(TARGET_CC) $(halt_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ halt_mod-commands_halt.o
+
+mod-halt.o: mod-halt.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -c -o $@ $<
+
+mod-halt.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'halt' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(halt_mod_EXPORTS),no)
+def-halt.lst: pre-halt.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 halt/' > $@
+endif
+
+und-halt.lst: pre-halt.o
+       echo 'halt' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+halt_mod-commands_halt.o: commands/halt.c $(commands/halt.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -MD -c -o $@ $<
+-include halt_mod-commands_halt.d
+
+CLEANFILES += cmd-halt_mod-commands_halt.lst fs-halt_mod-commands_halt.lst partmap-halt_mod-commands_halt.lst
+COMMANDFILES += cmd-halt_mod-commands_halt.lst
+FSFILES += fs-halt_mod-commands_halt.lst
+PARTMAPFILES += partmap-halt_mod-commands_halt.lst
+
+cmd-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh halt > $@ || (rm -f $@; exit 1)
+
+fs-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh halt > $@ || (rm -f $@; exit 1)
+
+partmap-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh halt > $@ || (rm -f $@; exit 1)
+
+
+halt_mod_CFLAGS = $(COMMON_CFLAGS)
+halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For help.mod.
+help_mod_SOURCES = commands/help.c
+CLEANFILES += help.mod mod-help.o mod-help.c pre-help.o help_mod-commands_help.o und-help.lst
+ifneq ($(help_mod_EXPORTS),no)
+CLEANFILES += def-help.lst
+DEFSYMFILES += def-help.lst
+endif
+MOSTLYCLEANFILES += help_mod-commands_help.d
+UNDSYMFILES += und-help.lst
+
+help.mod: pre-help.o mod-help.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(help_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-help.o mod-help.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-help.o: $(help_mod_DEPENDENCIES) help_mod-commands_help.o
+       -rm -f $@
+       $(TARGET_CC) $(help_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ help_mod-commands_help.o
+
+mod-help.o: mod-help.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(help_mod_CFLAGS) -c -o $@ $<
+
+mod-help.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'help' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(help_mod_EXPORTS),no)
+def-help.lst: pre-help.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 help/' > $@
+endif
+
+und-help.lst: pre-help.o
+       echo 'help' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+help_mod-commands_help.o: commands/help.c $(commands/help.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(help_mod_CFLAGS) -MD -c -o $@ $<
+-include help_mod-commands_help.d
+
+CLEANFILES += cmd-help_mod-commands_help.lst fs-help_mod-commands_help.lst partmap-help_mod-commands_help.lst
+COMMANDFILES += cmd-help_mod-commands_help.lst
+FSFILES += fs-help_mod-commands_help.lst
+PARTMAPFILES += partmap-help_mod-commands_help.lst
+
+cmd-help_mod-commands_help.lst: commands/help.c $(commands/help.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(help_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh help > $@ || (rm -f $@; exit 1)
+
+fs-help_mod-commands_help.lst: commands/help.c $(commands/help.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(help_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh help > $@ || (rm -f $@; exit 1)
+
+partmap-help_mod-commands_help.lst: commands/help.c $(commands/help.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(help_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh help > $@ || (rm -f $@; exit 1)
+
+
+help_mod_CFLAGS = $(COMMON_CFLAGS)
+help_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For default.mod
+default_mod_SOURCES = commands/default.c
+default_mod_CFLAGS =  $(COMMON_CFLAGS)
+default_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For timeout.mod
+timeout_mod_SOURCES = commands/timeout.c
+timeout_mod_CFLAGS =  $(COMMON_CFLAGS)
+timeout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For configfile.mod
+configfile_mod_SOURCES = commands/configfile.c
+CLEANFILES += configfile.mod mod-configfile.o mod-configfile.c pre-configfile.o configfile_mod-commands_configfile.o und-configfile.lst
+ifneq ($(configfile_mod_EXPORTS),no)
+CLEANFILES += def-configfile.lst
+DEFSYMFILES += def-configfile.lst
+endif
+MOSTLYCLEANFILES += configfile_mod-commands_configfile.d
+UNDSYMFILES += und-configfile.lst
+
+configfile.mod: pre-configfile.o mod-configfile.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(configfile_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-configfile.o mod-configfile.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-configfile.o: $(configfile_mod_DEPENDENCIES) configfile_mod-commands_configfile.o
+       -rm -f $@
+       $(TARGET_CC) $(configfile_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ configfile_mod-commands_configfile.o
+
+mod-configfile.o: mod-configfile.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(configfile_mod_CFLAGS) -c -o $@ $<
+
+mod-configfile.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'configfile' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(configfile_mod_EXPORTS),no)
+def-configfile.lst: pre-configfile.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 configfile/' > $@
+endif
+
+und-configfile.lst: pre-configfile.o
+       echo 'configfile' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+configfile_mod-commands_configfile.o: commands/configfile.c $(commands/configfile.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(configfile_mod_CFLAGS) -MD -c -o $@ $<
+-include configfile_mod-commands_configfile.d
+
+CLEANFILES += cmd-configfile_mod-commands_configfile.lst fs-configfile_mod-commands_configfile.lst partmap-configfile_mod-commands_configfile.lst
+COMMANDFILES += cmd-configfile_mod-commands_configfile.lst
+FSFILES += fs-configfile_mod-commands_configfile.lst
+PARTMAPFILES += partmap-configfile_mod-commands_configfile.lst
+
+cmd-configfile_mod-commands_configfile.lst: commands/configfile.c $(commands/configfile.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(configfile_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh configfile > $@ || (rm -f $@; exit 1)
+
+fs-configfile_mod-commands_configfile.lst: commands/configfile.c $(commands/configfile.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(configfile_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh configfile > $@ || (rm -f $@; exit 1)
+
+partmap-configfile_mod-commands_configfile.lst: commands/configfile.c $(commands/configfile.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(configfile_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh configfile > $@ || (rm -f $@; exit 1)
+
+
+configfile_mod_CFLAGS = $(COMMON_CFLAGS)
+configfile_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For search.mod.
+search_mod_SOURCES = commands/search.c
+CLEANFILES += search.mod mod-search.o mod-search.c pre-search.o search_mod-commands_search.o und-search.lst
+ifneq ($(search_mod_EXPORTS),no)
+CLEANFILES += def-search.lst
+DEFSYMFILES += def-search.lst
+endif
+MOSTLYCLEANFILES += search_mod-commands_search.d
+UNDSYMFILES += und-search.lst
+
+search.mod: pre-search.o mod-search.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(search_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-search.o mod-search.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-search.o: $(search_mod_DEPENDENCIES) search_mod-commands_search.o
+       -rm -f $@
+       $(TARGET_CC) $(search_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ search_mod-commands_search.o
+
+mod-search.o: mod-search.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(search_mod_CFLAGS) -c -o $@ $<
+
+mod-search.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'search' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(search_mod_EXPORTS),no)
+def-search.lst: pre-search.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 search/' > $@
+endif
+
+und-search.lst: pre-search.o
+       echo 'search' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+search_mod-commands_search.o: commands/search.c $(commands/search.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(search_mod_CFLAGS) -MD -c -o $@ $<
+-include search_mod-commands_search.d
+
+CLEANFILES += cmd-search_mod-commands_search.lst fs-search_mod-commands_search.lst partmap-search_mod-commands_search.lst
+COMMANDFILES += cmd-search_mod-commands_search.lst
+FSFILES += fs-search_mod-commands_search.lst
+PARTMAPFILES += partmap-search_mod-commands_search.lst
+
+cmd-search_mod-commands_search.lst: commands/search.c $(commands/search.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(search_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh search > $@ || (rm -f $@; exit 1)
+
+fs-search_mod-commands_search.lst: commands/search.c $(commands/search.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(search_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh search > $@ || (rm -f $@; exit 1)
+
+partmap-search_mod-commands_search.lst: commands/search.c $(commands/search.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(search_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh search > $@ || (rm -f $@; exit 1)
+
+
+search_mod_CFLAGS = $(COMMON_CFLAGS)
+search_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For gzio.mod.
+gzio_mod_SOURCES = io/gzio.c
+CLEANFILES += gzio.mod mod-gzio.o mod-gzio.c pre-gzio.o gzio_mod-io_gzio.o und-gzio.lst
+ifneq ($(gzio_mod_EXPORTS),no)
+CLEANFILES += def-gzio.lst
+DEFSYMFILES += def-gzio.lst
+endif
+MOSTLYCLEANFILES += gzio_mod-io_gzio.d
+UNDSYMFILES += und-gzio.lst
+
+gzio.mod: pre-gzio.o mod-gzio.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(gzio_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-gzio.o mod-gzio.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-gzio.o: $(gzio_mod_DEPENDENCIES) gzio_mod-io_gzio.o
+       -rm -f $@
+       $(TARGET_CC) $(gzio_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ gzio_mod-io_gzio.o
+
+mod-gzio.o: mod-gzio.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gzio_mod_CFLAGS) -c -o $@ $<
+
+mod-gzio.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'gzio' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(gzio_mod_EXPORTS),no)
+def-gzio.lst: pre-gzio.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 gzio/' > $@
+endif
+
+und-gzio.lst: pre-gzio.o
+       echo 'gzio' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+gzio_mod-io_gzio.o: io/gzio.c $(io/gzio.c_DEPENDENCIES)
+       $(TARGET_CC) -Iio -I$(srcdir)/io $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(gzio_mod_CFLAGS) -MD -c -o $@ $<
+-include gzio_mod-io_gzio.d
+
+CLEANFILES += cmd-gzio_mod-io_gzio.lst fs-gzio_mod-io_gzio.lst partmap-gzio_mod-io_gzio.lst
+COMMANDFILES += cmd-gzio_mod-io_gzio.lst
+FSFILES += fs-gzio_mod-io_gzio.lst
+PARTMAPFILES += partmap-gzio_mod-io_gzio.lst
+
+cmd-gzio_mod-io_gzio.lst: io/gzio.c $(io/gzio.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iio -I$(srcdir)/io $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gzio_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh gzio > $@ || (rm -f $@; exit 1)
+
+fs-gzio_mod-io_gzio.lst: io/gzio.c $(io/gzio.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iio -I$(srcdir)/io $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gzio_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh gzio > $@ || (rm -f $@; exit 1)
+
+partmap-gzio_mod-io_gzio.lst: io/gzio.c $(io/gzio.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iio -I$(srcdir)/io $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gzio_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh gzio > $@ || (rm -f $@; exit 1)
+
+
+gzio_mod_CFLAGS = $(COMMON_CFLAGS)
+gzio_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For test.mod.
+test_mod_SOURCES = commands/test.c
+test_mod_CFLAGS = $(COMMON_CFLAGS)
+test_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk
new file mode 100644 (file)
index 0000000..640ceda
--- /dev/null
@@ -0,0 +1,292 @@
+
+# -*- makefile -*-
+
+COMMON_ASFLAGS = -nostdinc
+COMMON_CFLAGS = -ggdb -ffreestanding -m64 -mno-app-regs
+COMMON_LDFLAGS = -melf64_sparc -nostdlib
+
+# Used by various components.  These rules need to precede them.
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Images.
+
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+kernel_elf_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
+       env.h err.h file.h fs.h kernel.h misc.h mm.h net.h parser.h rescue.h \
+       symbol.h term.h time.h types.h sparc64/libgcc.h loader.h partition.h \
+       pc_partition.h ieee1275/ieee1275.h machine/kernel.h
+
+symlist.c: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h gensymlist.sh
+       /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+# For the parser.
+grub_script.tab.c grub_script.tab.h: normal/parser.y
+       $(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/normal/parser.y
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_elf_HEADERS)) config.h genkernsyms.sh
+       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+# Programs
+pkglib_PROGRAMS = kernel.elf
+
+# Utilities.
+#bin_UTILITIES = grub-mkimage
+#ifeq ($(enable_grub_emu), yes)
+#bin_UTILITIES += grub-emu
+#endif
+
+# For grub-mkimage.
+grub_mkimage_SOURCES = util/sparc64/ieee1275/grub-mkimage.c util/misc.c \
+        util/resolve.c 
+
+# For grub-emu
+#grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c      \
+#      commands/configfile.c commands/default.c commands/help.c        \
+#      commands/search.c commands/terminal.c commands/ls.c             \
+#      commands/timeout.c commands/test.c                              \
+#      commands/halt.c commands/reboot.c               \
+#      disk/loopback.c                                                 \
+#      fs/affs.c fs/fat.c fs/ext2.c fs/fshelp.c fs/hfs.c fs/iso9660.c  \
+#      fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c                  \
+#      grub_script.tab.c                                               \
+#      io/gzio.c                                                       \
+#      kern/device.c kern/disk.c kern/dl.c kern/env.c kern/err.c       \
+#      kern/file.c kern/fs.c kern/loader.c kern/main.c kern/misc.c     \
+#      kern/parser.c kern/partition.c kern/rescue.c kern/term.c        \
+#      normal/arg.c normal/cmdline.c normal/command.c                  \
+#      normal/completion.c normal/context.c normal/execute.c           \
+#      normal/function.c normal/lexer.c                                \
+#      normal/main.c normal/menu.c normal/menu_entry.c                 \
+#      normal/menu_text.c                                              \
+#      normal/menu_viewer.c normal/misc.c                              \
+#      partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
+#      partmap/acorn.c                                                 \
+#      util/console.c util/grub-emu.c util/misc.c                      \
+#      util/hostdisk.c util/getroot.c                                  \
+#      util/sparc64/ieee1275/misc.c
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+kernel_elf_SOURCES = kern/sparc64/ieee1275/init.c kern/ieee1275/ieee1275.c \
+       kern/main.c kern/device.c kern/disk.c kern/dl.c kern/file.c \
+       kern/fs.c kern/err.c kern/misc.c kern/mm.c kern/loader.c \
+       kern/rescue.c kern/term.c term/ieee1275/ofconsole.c \
+       kern/sparc64/ieee1275/openfw.c disk/ieee1275/ofdisk.c \
+       kern/partition.c kern/env.c kern/sparc64/dl.c symlist.c \
+       kern/generic/millisleep.c kern/generic/get_time_ms.c \
+       kern/sparc64/cache.S kern/parser.c
+kernel_elf_HEADERS = grub/sparc64/ieee1275/ieee1275.h
+kernel_elf_CFLAGS = $(COMMON_CFLAGS)
+kernel_elf_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_elf_LDFLAGS = -mno-app-regs -nostdlib -Wl,-N,-Ttext,0x200000,-Bstatic,-melf64_sparc
+
+# Modules.
+#_linux.mod linux.mod
+pkglib_MODULES = fat.mod ufs.mod ext2.mod minix.mod \
+       hfs.mod jfs.mod normal.mod hello.mod font.mod ls.mod \
+       boot.mod cmp.mod cat.mod terminal.mod fshelp.mod amiga.mod apple.mod \
+       pc.mod suspend.mod loopback.mod help.mod reboot.mod halt.mod sun.mod \
+       configfile.mod search.mod gzio.mod xfs.mod \
+       affs.mod sfs.mod acorn.mod
+
+# For fshelp.mod.
+fshelp_mod_SOURCES = fs/fshelp.c
+fshelp_mod_CFLAGS = $(COMMON_CFLAGS)
+fshelp_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For fat.mod.
+fat_mod_SOURCES = fs/fat.c
+fat_mod_CFLAGS = $(COMMON_CFLAGS)
+fat_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ext2.mod.
+ext2_mod_SOURCES = fs/ext2.c
+ext2_mod_CFLAGS = $(COMMON_CFLAGS)
+ext2_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ufs.mod.
+ufs_mod_SOURCES = fs/ufs.c
+ufs_mod_CFLAGS = $(COMMON_CFLAGS)
+ufs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For minix.mod.
+minix_mod_SOURCES = fs/minix.c
+minix_mod_CFLAGS = $(COMMON_CFLAGS)
+minix_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For hfs.mod.
+hfs_mod_SOURCES = fs/hfs.c
+hfs_mod_CFLAGS = $(COMMON_CFLAGS)
+hfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For jfs.mod.
+jfs_mod_SOURCES = fs/jfs.c
+jfs_mod_CFLAGS = $(COMMON_CFLAGS)
+jfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For iso9660.mod.
+iso9660_mod_SOURCES = fs/iso9660.c
+iso9660_mod_CFLAGS = $(COMMON_CFLAGS)
+iso9660_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For xfs.mod.
+xfs_mod_SOURCES = fs/xfs.c
+xfs_mod_CFLAGS = $(COMMON_CFLAGS)
+xfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For affs.mod.
+affs_mod_SOURCES = fs/affs.c
+affs_mod_CFLAGS = $(COMMON_CFLAGS)
+affs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For sfs.mod.
+sfs_mod_SOURCES = fs/sfs.c
+sfs_mod_CFLAGS = $(COMMON_CFLAGS)
+sfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _linux.mod.
+#_linux_mod_SOURCES = loader/sparc64/ieee1275/linux.c
+#_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+#_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For linux.mod.
+#linux_mod_SOURCES = loader/sparc64/ieee1275/linux_normal.c
+#linux_mod_CFLAGS = $(COMMON_CFLAGS)
+#linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+#
+# Only arch dependant part of normal.mod will be here. Common part for
+# all architecures of normal.mod is at start and should be kept at sync
+# with other makefiles.
+# 
+# Please put arch dependant part of normal.mod at the end of list to
+# keep it simpler to update to different architectures.
+#
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/color.c                                                  \
+       normal/menu_viewer.c normal/menu_entry.c                        \
+       normal/misc.c grub_script.tab.c                                 \
+       normal/script.c                                                 \
+       normal/sparc64/setjmp.S
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For hello.mod.
+hello_mod_SOURCES = hello/hello.c
+hello_mod_CFLAGS = $(COMMON_CFLAGS)
+hello_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For boot.mod.
+boot_mod_SOURCES = commands/boot.c
+boot_mod_CFLAGS = $(COMMON_CFLAGS)
+boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For terminal.mod.
+terminal_mod_SOURCES = commands/terminal.c
+terminal_mod_CFLAGS = $(COMMON_CFLAGS)
+terminal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For ls.mod.
+ls_mod_SOURCES = commands/ls.c
+ls_mod_CFLAGS = $(COMMON_CFLAGS)
+ls_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For cmp.mod.
+cmp_mod_SOURCES = commands/cmp.c
+cmp_mod_CFLAGS = $(COMMON_CFLAGS)
+cmp_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For cat.mod.
+cat_mod_SOURCES = commands/cat.c
+cat_mod_CFLAGS = $(COMMON_CFLAGS)
+cat_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For font.mod.
+font_mod_SOURCES = font/manager.c
+font_mod_CFLAGS = $(COMMON_CFLAGS)
+font_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For amiga.mod
+amiga_mod_SOURCES = partmap/amiga.c
+amiga_mod_CFLAGS = $(COMMON_CFLAGS)
+amiga_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For apple.mod
+apple_mod_SOURCES = partmap/apple.c
+apple_mod_CFLAGS = $(COMMON_CFLAGS)
+apple_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pc.mod
+pc_mod_SOURCES = partmap/pc.c
+pc_mod_CFLAGS = $(COMMON_CFLAGS)
+pc_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For sun.mod
+sun_mod_SOURCES = partmap/sun.c
+sun_mod_CFLAGS = $(COMMON_CFLAGS)
+sun_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For acorn.mod
+acorn_mod_SOURCES = partmap/acorn.c
+acorn_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For loopback.mod
+loopback_mod_SOURCES = disk/loopback.c
+loopback_mod_CFLAGS = $(COMMON_CFLAGS)
+loopback_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For suspend.mod
+suspend_mod_SOURCES = commands/ieee1275/suspend.c
+suspend_mod_CFLAGS = $(COMMON_CFLAGS)
+suspend_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reboot.mod
+reboot_mod_SOURCES = commands/reboot.c
+reboot_mod_CFLAGS = $(COMMON_CFLAGS)
+reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For halt.mod
+halt_mod_SOURCES = commands/halt.c
+halt_mod_CFLAGS = $(COMMON_CFLAGS)
+halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For help.mod.
+help_mod_SOURCES = commands/help.c
+help_mod_CFLAGS = $(COMMON_CFLAGS)
+help_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For default.mod
+default_mod_SOURCES = commands/default.c
+default_mod_CFLAGS =  $(COMMON_CFLAGS)
+default_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For timeout.mod
+timeout_mod_SOURCES = commands/timeout.c
+timeout_mod_CFLAGS =  $(COMMON_CFLAGS)
+timeout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For configfile.mod
+configfile_mod_SOURCES = commands/configfile.c
+configfile_mod_CFLAGS = $(COMMON_CFLAGS)
+configfile_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For search.mod.
+search_mod_SOURCES = commands/search.c
+search_mod_CFLAGS = $(COMMON_CFLAGS)
+search_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For gzio.mod.
+gzio_mod_SOURCES = io/gzio.c
+gzio_mod_CFLAGS = $(COMMON_CFLAGS)
+gzio_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For test.mod.
+test_mod_SOURCES = commands/test.c
+test_mod_CFLAGS = $(COMMON_CFLAGS)
+test_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/conf/x86_64-efi.mk b/conf/x86_64-efi.mk
new file mode 100644 (file)
index 0000000..b2095df
--- /dev/null
@@ -0,0 +1,1824 @@
+# -*- makefile -*-
+# Generated by genmk.rb, please don't edit!
+
+COMMON_ASFLAGS = -nostdinc -fno-builtin -m64
+COMMON_CFLAGS = -fno-builtin -m64
+COMMON_LDFLAGS = -melf_x86_64 -nostdlib
+
+# Used by various components.  These rules need to precede them.
+normal/execute.c_DEPENDENCIES = grub_script.tab.h
+normal/command.c_DEPENDENCIES = grub_script.tab.h
+normal/function.c_DEPENDENCIES = grub_script.tab.h
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Utilities.
+bin_UTILITIES = grub-mkimage
+#sbin_UTILITIES = grub-mkdevicemap
+#ifeq ($(enable_grub_emu), yes)
+#sbin_UTILITIES += grub-emu
+#endif
+
+# For grub-mkimage.
+grub_mkimage_SOURCES = util/i386/efi/grub-mkimage.c util/misc.c \
+       util/resolve.c
+CLEANFILES += grub-mkimage$(EXEEXT) grub_mkimage-util_i386_efi_grub_mkimage.o grub_mkimage-util_misc.o grub_mkimage-util_resolve.o
+MOSTLYCLEANFILES += grub_mkimage-util_i386_efi_grub_mkimage.d grub_mkimage-util_misc.d grub_mkimage-util_resolve.d
+
+grub-mkimage: $(grub_mkimage_DEPENDENCIES) grub_mkimage-util_i386_efi_grub_mkimage.o grub_mkimage-util_misc.o grub_mkimage-util_resolve.o
+       $(CC) -o $@ grub_mkimage-util_i386_efi_grub_mkimage.o grub_mkimage-util_misc.o grub_mkimage-util_resolve.o $(LDFLAGS) $(grub_mkimage_LDFLAGS)
+
+grub_mkimage-util_i386_efi_grub_mkimage.o: util/i386/efi/grub-mkimage.c $(util/i386/efi/grub-mkimage.c_DEPENDENCIES)
+       $(CC) -Iutil/i386/efi -I$(srcdir)/util/i386/efi $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkimage-util_i386_efi_grub_mkimage.d
+
+grub_mkimage-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkimage-util_misc.d
+
+grub_mkimage-util_resolve.o: util/resolve.c $(util/resolve.c_DEPENDENCIES)
+       $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_mkimage_CFLAGS) -MD -c -o $@ $<
+-include grub_mkimage-util_resolve.d
+
+
+# For grub-setup.
+#grub_setup_SOURCES = util/i386/pc/grub-setup.c util/hostdisk.c        \
+#      util/misc.c util/getroot.c kern/device.c kern/disk.c    \
+#      kern/err.c kern/misc.c fs/fat.c fs/ext2.c fs/xfs.c fs/affs.c    \
+#      fs/sfs.c kern/parser.c kern/partition.c partmap/pc.c            \
+#      fs/ufs.c fs/minix.c fs/hfs.c fs/jfs.c fs/hfsplus.c kern/file.c  \
+#      kern/fs.c kern/env.c fs/fshelp.c
+
+# For grub-mkdevicemap.
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+
+# For grub-emu.
+util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
+grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c       \
+       commands/configfile.c commands/help.c                           \
+       commands/terminal.c commands/ls.c commands/test.c               \
+       commands/search.c commands/hexdump.c lib/hexdump.c              \
+       commands/halt.c commands/reboot.c                               \
+       commands/i386/cpuid.c                                           \
+       disk/loopback.c                                                 \
+       \
+       fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c                 \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c          \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c                  \
+       fs/ufs.c fs/xfs.c fs/afs.c                                      \
+       \
+       io/gzio.c                                                       \
+       kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c       \
+       kern/err.c                                                      \
+       normal/execute.c kern/file.c kern/fs.c normal/lexer.c           \
+       kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
+       grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
+       normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
+       normal/completion.c normal/context.c normal/main.c              \
+       normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
+       normal/menu_text.c                                              \
+       normal/misc.c normal/script.c                                   \
+       normal/color.c                                                  \
+       partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
+       partmap/acorn.c partmap/gpt.c                                   \
+       util/console.c util/hostfs.c util/grub-emu.c util/misc.c        \
+       util/hostdisk.c util/getroot.c                                  \
+       util/i386/pc/misc.c                                             \
+       \
+       disk/raid.c disk/raid5_recover.c disk/raid6_recover.c           \
+       disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c             \
+       grub_emu_init.c
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+# Scripts.
+sbin_SCRIPTS = grub-install
+
+# For grub-install.
+grub_install_SOURCES = util/i386/efi/grub-install.in
+CLEANFILES += grub-install
+
+grub-install: util/i386/efi/grub-install.in $(util/i386/efi/grub-install.in_DEPENDENCIES) config.status
+       ./config.status --file=grub-install:util/i386/efi/grub-install.in
+       chmod +x $@
+
+
+# Modules.
+pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
+       halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod \
+       datetime.mod date.mod datehook.mod
+
+# For kernel.mod.
+kernel_mod_EXPORTS = no
+kernel_mod_SOURCES = kern/x86_64/efi/startup.S kern/x86_64/efi/callwrap.S \
+       kern/main.c kern/device.c \
+       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
+       kern/x86_64/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \
+       kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \
+       kern/time.c \
+       kern/i386/tsc.c kern/i386/pit.c \
+       kern/generic/millisleep.c kern/generic/rtc_get_time_ms.c \
+       term/efi/console.c disk/efi/efidisk.c
+CLEANFILES += kernel.mod mod-kernel.o mod-kernel.c pre-kernel.o kernel_mod-kern_x86_64_efi_startup.o kernel_mod-kern_x86_64_efi_callwrap.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_x86_64_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o kernel_mod-kern_efi_init.o kernel_mod-kern_efi_mm.o kernel_mod-kern_time.o kernel_mod-kern_i386_tsc.o kernel_mod-kern_i386_pit.o kernel_mod-kern_generic_millisleep.o kernel_mod-kern_generic_rtc_get_time_ms.o kernel_mod-term_efi_console.o kernel_mod-disk_efi_efidisk.o und-kernel.lst
+ifneq ($(kernel_mod_EXPORTS),no)
+CLEANFILES += def-kernel.lst
+DEFSYMFILES += def-kernel.lst
+endif
+MOSTLYCLEANFILES += kernel_mod-kern_x86_64_efi_startup.d kernel_mod-kern_x86_64_efi_callwrap.d kernel_mod-kern_main.d kernel_mod-kern_device.d kernel_mod-kern_disk.d kernel_mod-kern_dl.d kernel_mod-kern_file.d kernel_mod-kern_fs.d kernel_mod-kern_err.d kernel_mod-kern_misc.d kernel_mod-kern_mm.d kernel_mod-kern_loader.d kernel_mod-kern_rescue.d kernel_mod-kern_term.d kernel_mod-kern_x86_64_dl.d kernel_mod-kern_i386_efi_init.d kernel_mod-kern_parser.d kernel_mod-kern_partition.d kernel_mod-kern_env.d kernel_mod-symlist.d kernel_mod-kern_efi_efi.d kernel_mod-kern_efi_init.d kernel_mod-kern_efi_mm.d kernel_mod-kern_time.d kernel_mod-kern_i386_tsc.d kernel_mod-kern_i386_pit.d kernel_mod-kern_generic_millisleep.d kernel_mod-kern_generic_rtc_get_time_ms.d kernel_mod-term_efi_console.d kernel_mod-disk_efi_efidisk.d
+UNDSYMFILES += und-kernel.lst
+
+kernel.mod: pre-kernel.o mod-kernel.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(kernel_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-kernel.o mod-kernel.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-kernel.o: $(kernel_mod_DEPENDENCIES) kernel_mod-kern_x86_64_efi_startup.o kernel_mod-kern_x86_64_efi_callwrap.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_x86_64_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o kernel_mod-kern_efi_init.o kernel_mod-kern_efi_mm.o kernel_mod-kern_time.o kernel_mod-kern_i386_tsc.o kernel_mod-kern_i386_pit.o kernel_mod-kern_generic_millisleep.o kernel_mod-kern_generic_rtc_get_time_ms.o kernel_mod-term_efi_console.o kernel_mod-disk_efi_efidisk.o
+       -rm -f $@
+       $(TARGET_CC) $(kernel_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ kernel_mod-kern_x86_64_efi_startup.o kernel_mod-kern_x86_64_efi_callwrap.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_x86_64_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o kernel_mod-kern_efi_init.o kernel_mod-kern_efi_mm.o kernel_mod-kern_time.o kernel_mod-kern_i386_tsc.o kernel_mod-kern_i386_pit.o kernel_mod-kern_generic_millisleep.o kernel_mod-kern_generic_rtc_get_time_ms.o kernel_mod-term_efi_console.o kernel_mod-disk_efi_efidisk.o
+
+mod-kernel.o: mod-kernel.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -c -o $@ $<
+
+mod-kernel.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'kernel' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(kernel_mod_EXPORTS),no)
+def-kernel.lst: pre-kernel.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 kernel/' > $@
+endif
+
+und-kernel.lst: pre-kernel.o
+       echo 'kernel' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+kernel_mod-kern_x86_64_efi_startup.o: kern/x86_64/efi/startup.S $(kern/x86_64/efi/startup.S_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/x86_64/efi -I$(srcdir)/kern/x86_64/efi $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(kernel_mod_ASFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_x86_64_efi_startup.d
+
+CLEANFILES += cmd-kernel_mod-kern_x86_64_efi_startup.lst fs-kernel_mod-kern_x86_64_efi_startup.lst partmap-kernel_mod-kern_x86_64_efi_startup.lst
+COMMANDFILES += cmd-kernel_mod-kern_x86_64_efi_startup.lst
+FSFILES += fs-kernel_mod-kern_x86_64_efi_startup.lst
+PARTMAPFILES += partmap-kernel_mod-kern_x86_64_efi_startup.lst
+
+cmd-kernel_mod-kern_x86_64_efi_startup.lst: kern/x86_64/efi/startup.S $(kern/x86_64/efi/startup.S_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/x86_64/efi -I$(srcdir)/kern/x86_64/efi $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(kernel_mod_ASFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_x86_64_efi_startup.lst: kern/x86_64/efi/startup.S $(kern/x86_64/efi/startup.S_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/x86_64/efi -I$(srcdir)/kern/x86_64/efi $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(kernel_mod_ASFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_x86_64_efi_startup.lst: kern/x86_64/efi/startup.S $(kern/x86_64/efi/startup.S_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/x86_64/efi -I$(srcdir)/kern/x86_64/efi $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(kernel_mod_ASFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_x86_64_efi_callwrap.o: kern/x86_64/efi/callwrap.S $(kern/x86_64/efi/callwrap.S_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/x86_64/efi -I$(srcdir)/kern/x86_64/efi $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(kernel_mod_ASFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_x86_64_efi_callwrap.d
+
+CLEANFILES += cmd-kernel_mod-kern_x86_64_efi_callwrap.lst fs-kernel_mod-kern_x86_64_efi_callwrap.lst partmap-kernel_mod-kern_x86_64_efi_callwrap.lst
+COMMANDFILES += cmd-kernel_mod-kern_x86_64_efi_callwrap.lst
+FSFILES += fs-kernel_mod-kern_x86_64_efi_callwrap.lst
+PARTMAPFILES += partmap-kernel_mod-kern_x86_64_efi_callwrap.lst
+
+cmd-kernel_mod-kern_x86_64_efi_callwrap.lst: kern/x86_64/efi/callwrap.S $(kern/x86_64/efi/callwrap.S_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/x86_64/efi -I$(srcdir)/kern/x86_64/efi $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(kernel_mod_ASFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_x86_64_efi_callwrap.lst: kern/x86_64/efi/callwrap.S $(kern/x86_64/efi/callwrap.S_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/x86_64/efi -I$(srcdir)/kern/x86_64/efi $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(kernel_mod_ASFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_x86_64_efi_callwrap.lst: kern/x86_64/efi/callwrap.S $(kern/x86_64/efi/callwrap.S_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/x86_64/efi -I$(srcdir)/kern/x86_64/efi $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(kernel_mod_ASFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_main.o: kern/main.c $(kern/main.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_main.d
+
+CLEANFILES += cmd-kernel_mod-kern_main.lst fs-kernel_mod-kern_main.lst partmap-kernel_mod-kern_main.lst
+COMMANDFILES += cmd-kernel_mod-kern_main.lst
+FSFILES += fs-kernel_mod-kern_main.lst
+PARTMAPFILES += partmap-kernel_mod-kern_main.lst
+
+cmd-kernel_mod-kern_main.lst: kern/main.c $(kern/main.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_main.lst: kern/main.c $(kern/main.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_main.lst: kern/main.c $(kern/main.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_device.o: kern/device.c $(kern/device.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_device.d
+
+CLEANFILES += cmd-kernel_mod-kern_device.lst fs-kernel_mod-kern_device.lst partmap-kernel_mod-kern_device.lst
+COMMANDFILES += cmd-kernel_mod-kern_device.lst
+FSFILES += fs-kernel_mod-kern_device.lst
+PARTMAPFILES += partmap-kernel_mod-kern_device.lst
+
+cmd-kernel_mod-kern_device.lst: kern/device.c $(kern/device.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_device.lst: kern/device.c $(kern/device.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_device.lst: kern/device.c $(kern/device.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_disk.o: kern/disk.c $(kern/disk.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_disk.d
+
+CLEANFILES += cmd-kernel_mod-kern_disk.lst fs-kernel_mod-kern_disk.lst partmap-kernel_mod-kern_disk.lst
+COMMANDFILES += cmd-kernel_mod-kern_disk.lst
+FSFILES += fs-kernel_mod-kern_disk.lst
+PARTMAPFILES += partmap-kernel_mod-kern_disk.lst
+
+cmd-kernel_mod-kern_disk.lst: kern/disk.c $(kern/disk.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_disk.lst: kern/disk.c $(kern/disk.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_disk.lst: kern/disk.c $(kern/disk.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_dl.o: kern/dl.c $(kern/dl.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_dl.d
+
+CLEANFILES += cmd-kernel_mod-kern_dl.lst fs-kernel_mod-kern_dl.lst partmap-kernel_mod-kern_dl.lst
+COMMANDFILES += cmd-kernel_mod-kern_dl.lst
+FSFILES += fs-kernel_mod-kern_dl.lst
+PARTMAPFILES += partmap-kernel_mod-kern_dl.lst
+
+cmd-kernel_mod-kern_dl.lst: kern/dl.c $(kern/dl.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_dl.lst: kern/dl.c $(kern/dl.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_dl.lst: kern/dl.c $(kern/dl.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_file.o: kern/file.c $(kern/file.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_file.d
+
+CLEANFILES += cmd-kernel_mod-kern_file.lst fs-kernel_mod-kern_file.lst partmap-kernel_mod-kern_file.lst
+COMMANDFILES += cmd-kernel_mod-kern_file.lst
+FSFILES += fs-kernel_mod-kern_file.lst
+PARTMAPFILES += partmap-kernel_mod-kern_file.lst
+
+cmd-kernel_mod-kern_file.lst: kern/file.c $(kern/file.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_file.lst: kern/file.c $(kern/file.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_file.lst: kern/file.c $(kern/file.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_fs.o: kern/fs.c $(kern/fs.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_fs.d
+
+CLEANFILES += cmd-kernel_mod-kern_fs.lst fs-kernel_mod-kern_fs.lst partmap-kernel_mod-kern_fs.lst
+COMMANDFILES += cmd-kernel_mod-kern_fs.lst
+FSFILES += fs-kernel_mod-kern_fs.lst
+PARTMAPFILES += partmap-kernel_mod-kern_fs.lst
+
+cmd-kernel_mod-kern_fs.lst: kern/fs.c $(kern/fs.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_fs.lst: kern/fs.c $(kern/fs.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_fs.lst: kern/fs.c $(kern/fs.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_err.d
+
+CLEANFILES += cmd-kernel_mod-kern_err.lst fs-kernel_mod-kern_err.lst partmap-kernel_mod-kern_err.lst
+COMMANDFILES += cmd-kernel_mod-kern_err.lst
+FSFILES += fs-kernel_mod-kern_err.lst
+PARTMAPFILES += partmap-kernel_mod-kern_err.lst
+
+cmd-kernel_mod-kern_err.lst: kern/err.c $(kern/err.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_err.lst: kern/err.c $(kern/err.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_err.lst: kern/err.c $(kern/err.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_misc.d
+
+CLEANFILES += cmd-kernel_mod-kern_misc.lst fs-kernel_mod-kern_misc.lst partmap-kernel_mod-kern_misc.lst
+COMMANDFILES += cmd-kernel_mod-kern_misc.lst
+FSFILES += fs-kernel_mod-kern_misc.lst
+PARTMAPFILES += partmap-kernel_mod-kern_misc.lst
+
+cmd-kernel_mod-kern_misc.lst: kern/misc.c $(kern/misc.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_misc.lst: kern/misc.c $(kern/misc.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_misc.lst: kern/misc.c $(kern/misc.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_mm.o: kern/mm.c $(kern/mm.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_mm.d
+
+CLEANFILES += cmd-kernel_mod-kern_mm.lst fs-kernel_mod-kern_mm.lst partmap-kernel_mod-kern_mm.lst
+COMMANDFILES += cmd-kernel_mod-kern_mm.lst
+FSFILES += fs-kernel_mod-kern_mm.lst
+PARTMAPFILES += partmap-kernel_mod-kern_mm.lst
+
+cmd-kernel_mod-kern_mm.lst: kern/mm.c $(kern/mm.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_mm.lst: kern/mm.c $(kern/mm.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_mm.lst: kern/mm.c $(kern/mm.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_loader.o: kern/loader.c $(kern/loader.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_loader.d
+
+CLEANFILES += cmd-kernel_mod-kern_loader.lst fs-kernel_mod-kern_loader.lst partmap-kernel_mod-kern_loader.lst
+COMMANDFILES += cmd-kernel_mod-kern_loader.lst
+FSFILES += fs-kernel_mod-kern_loader.lst
+PARTMAPFILES += partmap-kernel_mod-kern_loader.lst
+
+cmd-kernel_mod-kern_loader.lst: kern/loader.c $(kern/loader.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_loader.lst: kern/loader.c $(kern/loader.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_loader.lst: kern/loader.c $(kern/loader.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_rescue.o: kern/rescue.c $(kern/rescue.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_rescue.d
+
+CLEANFILES += cmd-kernel_mod-kern_rescue.lst fs-kernel_mod-kern_rescue.lst partmap-kernel_mod-kern_rescue.lst
+COMMANDFILES += cmd-kernel_mod-kern_rescue.lst
+FSFILES += fs-kernel_mod-kern_rescue.lst
+PARTMAPFILES += partmap-kernel_mod-kern_rescue.lst
+
+cmd-kernel_mod-kern_rescue.lst: kern/rescue.c $(kern/rescue.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_rescue.lst: kern/rescue.c $(kern/rescue.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_rescue.lst: kern/rescue.c $(kern/rescue.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_term.o: kern/term.c $(kern/term.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_term.d
+
+CLEANFILES += cmd-kernel_mod-kern_term.lst fs-kernel_mod-kern_term.lst partmap-kernel_mod-kern_term.lst
+COMMANDFILES += cmd-kernel_mod-kern_term.lst
+FSFILES += fs-kernel_mod-kern_term.lst
+PARTMAPFILES += partmap-kernel_mod-kern_term.lst
+
+cmd-kernel_mod-kern_term.lst: kern/term.c $(kern/term.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_term.lst: kern/term.c $(kern/term.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_term.lst: kern/term.c $(kern/term.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_x86_64_dl.o: kern/x86_64/dl.c $(kern/x86_64/dl.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/x86_64 -I$(srcdir)/kern/x86_64 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_x86_64_dl.d
+
+CLEANFILES += cmd-kernel_mod-kern_x86_64_dl.lst fs-kernel_mod-kern_x86_64_dl.lst partmap-kernel_mod-kern_x86_64_dl.lst
+COMMANDFILES += cmd-kernel_mod-kern_x86_64_dl.lst
+FSFILES += fs-kernel_mod-kern_x86_64_dl.lst
+PARTMAPFILES += partmap-kernel_mod-kern_x86_64_dl.lst
+
+cmd-kernel_mod-kern_x86_64_dl.lst: kern/x86_64/dl.c $(kern/x86_64/dl.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/x86_64 -I$(srcdir)/kern/x86_64 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_x86_64_dl.lst: kern/x86_64/dl.c $(kern/x86_64/dl.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/x86_64 -I$(srcdir)/kern/x86_64 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_x86_64_dl.lst: kern/x86_64/dl.c $(kern/x86_64/dl.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/x86_64 -I$(srcdir)/kern/x86_64 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_i386_efi_init.o: kern/i386/efi/init.c $(kern/i386/efi/init.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386/efi -I$(srcdir)/kern/i386/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_i386_efi_init.d
+
+CLEANFILES += cmd-kernel_mod-kern_i386_efi_init.lst fs-kernel_mod-kern_i386_efi_init.lst partmap-kernel_mod-kern_i386_efi_init.lst
+COMMANDFILES += cmd-kernel_mod-kern_i386_efi_init.lst
+FSFILES += fs-kernel_mod-kern_i386_efi_init.lst
+PARTMAPFILES += partmap-kernel_mod-kern_i386_efi_init.lst
+
+cmd-kernel_mod-kern_i386_efi_init.lst: kern/i386/efi/init.c $(kern/i386/efi/init.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386/efi -I$(srcdir)/kern/i386/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_i386_efi_init.lst: kern/i386/efi/init.c $(kern/i386/efi/init.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386/efi -I$(srcdir)/kern/i386/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_i386_efi_init.lst: kern/i386/efi/init.c $(kern/i386/efi/init.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386/efi -I$(srcdir)/kern/i386/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_parser.o: kern/parser.c $(kern/parser.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_parser.d
+
+CLEANFILES += cmd-kernel_mod-kern_parser.lst fs-kernel_mod-kern_parser.lst partmap-kernel_mod-kern_parser.lst
+COMMANDFILES += cmd-kernel_mod-kern_parser.lst
+FSFILES += fs-kernel_mod-kern_parser.lst
+PARTMAPFILES += partmap-kernel_mod-kern_parser.lst
+
+cmd-kernel_mod-kern_parser.lst: kern/parser.c $(kern/parser.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_parser.lst: kern/parser.c $(kern/parser.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_parser.lst: kern/parser.c $(kern/parser.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_partition.o: kern/partition.c $(kern/partition.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_partition.d
+
+CLEANFILES += cmd-kernel_mod-kern_partition.lst fs-kernel_mod-kern_partition.lst partmap-kernel_mod-kern_partition.lst
+COMMANDFILES += cmd-kernel_mod-kern_partition.lst
+FSFILES += fs-kernel_mod-kern_partition.lst
+PARTMAPFILES += partmap-kernel_mod-kern_partition.lst
+
+cmd-kernel_mod-kern_partition.lst: kern/partition.c $(kern/partition.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_partition.lst: kern/partition.c $(kern/partition.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_partition.lst: kern/partition.c $(kern/partition.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_env.o: kern/env.c $(kern/env.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_env.d
+
+CLEANFILES += cmd-kernel_mod-kern_env.lst fs-kernel_mod-kern_env.lst partmap-kernel_mod-kern_env.lst
+COMMANDFILES += cmd-kernel_mod-kern_env.lst
+FSFILES += fs-kernel_mod-kern_env.lst
+PARTMAPFILES += partmap-kernel_mod-kern_env.lst
+
+cmd-kernel_mod-kern_env.lst: kern/env.c $(kern/env.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_env.lst: kern/env.c $(kern/env.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_env.lst: kern/env.c $(kern/env.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-symlist.o: symlist.c $(symlist.c_DEPENDENCIES)
+       $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-symlist.d
+
+CLEANFILES += cmd-kernel_mod-symlist.lst fs-kernel_mod-symlist.lst partmap-kernel_mod-symlist.lst
+COMMANDFILES += cmd-kernel_mod-symlist.lst
+FSFILES += fs-kernel_mod-symlist.lst
+PARTMAPFILES += partmap-kernel_mod-symlist.lst
+
+cmd-kernel_mod-symlist.lst: symlist.c $(symlist.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-symlist.lst: symlist.c $(symlist.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-symlist.lst: symlist.c $(symlist.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_efi_efi.o: kern/efi/efi.c $(kern/efi/efi.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_efi_efi.d
+
+CLEANFILES += cmd-kernel_mod-kern_efi_efi.lst fs-kernel_mod-kern_efi_efi.lst partmap-kernel_mod-kern_efi_efi.lst
+COMMANDFILES += cmd-kernel_mod-kern_efi_efi.lst
+FSFILES += fs-kernel_mod-kern_efi_efi.lst
+PARTMAPFILES += partmap-kernel_mod-kern_efi_efi.lst
+
+cmd-kernel_mod-kern_efi_efi.lst: kern/efi/efi.c $(kern/efi/efi.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_efi_efi.lst: kern/efi/efi.c $(kern/efi/efi.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_efi_efi.lst: kern/efi/efi.c $(kern/efi/efi.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_efi_init.o: kern/efi/init.c $(kern/efi/init.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_efi_init.d
+
+CLEANFILES += cmd-kernel_mod-kern_efi_init.lst fs-kernel_mod-kern_efi_init.lst partmap-kernel_mod-kern_efi_init.lst
+COMMANDFILES += cmd-kernel_mod-kern_efi_init.lst
+FSFILES += fs-kernel_mod-kern_efi_init.lst
+PARTMAPFILES += partmap-kernel_mod-kern_efi_init.lst
+
+cmd-kernel_mod-kern_efi_init.lst: kern/efi/init.c $(kern/efi/init.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_efi_init.lst: kern/efi/init.c $(kern/efi/init.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_efi_init.lst: kern/efi/init.c $(kern/efi/init.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_efi_mm.o: kern/efi/mm.c $(kern/efi/mm.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_efi_mm.d
+
+CLEANFILES += cmd-kernel_mod-kern_efi_mm.lst fs-kernel_mod-kern_efi_mm.lst partmap-kernel_mod-kern_efi_mm.lst
+COMMANDFILES += cmd-kernel_mod-kern_efi_mm.lst
+FSFILES += fs-kernel_mod-kern_efi_mm.lst
+PARTMAPFILES += partmap-kernel_mod-kern_efi_mm.lst
+
+cmd-kernel_mod-kern_efi_mm.lst: kern/efi/mm.c $(kern/efi/mm.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_efi_mm.lst: kern/efi/mm.c $(kern/efi/mm.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_efi_mm.lst: kern/efi/mm.c $(kern/efi/mm.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/efi -I$(srcdir)/kern/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_time.o: kern/time.c $(kern/time.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_time.d
+
+CLEANFILES += cmd-kernel_mod-kern_time.lst fs-kernel_mod-kern_time.lst partmap-kernel_mod-kern_time.lst
+COMMANDFILES += cmd-kernel_mod-kern_time.lst
+FSFILES += fs-kernel_mod-kern_time.lst
+PARTMAPFILES += partmap-kernel_mod-kern_time.lst
+
+cmd-kernel_mod-kern_time.lst: kern/time.c $(kern/time.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_time.lst: kern/time.c $(kern/time.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_time.lst: kern/time.c $(kern/time.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern -I$(srcdir)/kern $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_i386_tsc.o: kern/i386/tsc.c $(kern/i386/tsc.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_i386_tsc.d
+
+CLEANFILES += cmd-kernel_mod-kern_i386_tsc.lst fs-kernel_mod-kern_i386_tsc.lst partmap-kernel_mod-kern_i386_tsc.lst
+COMMANDFILES += cmd-kernel_mod-kern_i386_tsc.lst
+FSFILES += fs-kernel_mod-kern_i386_tsc.lst
+PARTMAPFILES += partmap-kernel_mod-kern_i386_tsc.lst
+
+cmd-kernel_mod-kern_i386_tsc.lst: kern/i386/tsc.c $(kern/i386/tsc.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_i386_tsc.lst: kern/i386/tsc.c $(kern/i386/tsc.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_i386_tsc.lst: kern/i386/tsc.c $(kern/i386/tsc.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_i386_pit.o: kern/i386/pit.c $(kern/i386/pit.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_i386_pit.d
+
+CLEANFILES += cmd-kernel_mod-kern_i386_pit.lst fs-kernel_mod-kern_i386_pit.lst partmap-kernel_mod-kern_i386_pit.lst
+COMMANDFILES += cmd-kernel_mod-kern_i386_pit.lst
+FSFILES += fs-kernel_mod-kern_i386_pit.lst
+PARTMAPFILES += partmap-kernel_mod-kern_i386_pit.lst
+
+cmd-kernel_mod-kern_i386_pit.lst: kern/i386/pit.c $(kern/i386/pit.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_i386_pit.lst: kern/i386/pit.c $(kern/i386/pit.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_i386_pit.lst: kern/i386/pit.c $(kern/i386/pit.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_generic_millisleep.o: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_generic_millisleep.d
+
+CLEANFILES += cmd-kernel_mod-kern_generic_millisleep.lst fs-kernel_mod-kern_generic_millisleep.lst partmap-kernel_mod-kern_generic_millisleep.lst
+COMMANDFILES += cmd-kernel_mod-kern_generic_millisleep.lst
+FSFILES += fs-kernel_mod-kern_generic_millisleep.lst
+PARTMAPFILES += partmap-kernel_mod-kern_generic_millisleep.lst
+
+cmd-kernel_mod-kern_generic_millisleep.lst: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_generic_millisleep.lst: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_generic_millisleep.lst: kern/generic/millisleep.c $(kern/generic/millisleep.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-kern_generic_rtc_get_time_ms.o: kern/generic/rtc_get_time_ms.c $(kern/generic/rtc_get_time_ms.c_DEPENDENCIES)
+       $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-kern_generic_rtc_get_time_ms.d
+
+CLEANFILES += cmd-kernel_mod-kern_generic_rtc_get_time_ms.lst fs-kernel_mod-kern_generic_rtc_get_time_ms.lst partmap-kernel_mod-kern_generic_rtc_get_time_ms.lst
+COMMANDFILES += cmd-kernel_mod-kern_generic_rtc_get_time_ms.lst
+FSFILES += fs-kernel_mod-kern_generic_rtc_get_time_ms.lst
+PARTMAPFILES += partmap-kernel_mod-kern_generic_rtc_get_time_ms.lst
+
+cmd-kernel_mod-kern_generic_rtc_get_time_ms.lst: kern/generic/rtc_get_time_ms.c $(kern/generic/rtc_get_time_ms.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-kern_generic_rtc_get_time_ms.lst: kern/generic/rtc_get_time_ms.c $(kern/generic/rtc_get_time_ms.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-kern_generic_rtc_get_time_ms.lst: kern/generic/rtc_get_time_ms.c $(kern/generic/rtc_get_time_ms.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ikern/generic -I$(srcdir)/kern/generic $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-term_efi_console.o: term/efi/console.c $(term/efi/console.c_DEPENDENCIES)
+       $(TARGET_CC) -Iterm/efi -I$(srcdir)/term/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-term_efi_console.d
+
+CLEANFILES += cmd-kernel_mod-term_efi_console.lst fs-kernel_mod-term_efi_console.lst partmap-kernel_mod-term_efi_console.lst
+COMMANDFILES += cmd-kernel_mod-term_efi_console.lst
+FSFILES += fs-kernel_mod-term_efi_console.lst
+PARTMAPFILES += partmap-kernel_mod-term_efi_console.lst
+
+cmd-kernel_mod-term_efi_console.lst: term/efi/console.c $(term/efi/console.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iterm/efi -I$(srcdir)/term/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-term_efi_console.lst: term/efi/console.c $(term/efi/console.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iterm/efi -I$(srcdir)/term/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-term_efi_console.lst: term/efi/console.c $(term/efi/console.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iterm/efi -I$(srcdir)/term/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod-disk_efi_efidisk.o: disk/efi/efidisk.c $(disk/efi/efidisk.c_DEPENDENCIES)
+       $(TARGET_CC) -Idisk/efi -I$(srcdir)/disk/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -MD -c -o $@ $<
+-include kernel_mod-disk_efi_efidisk.d
+
+CLEANFILES += cmd-kernel_mod-disk_efi_efidisk.lst fs-kernel_mod-disk_efi_efidisk.lst partmap-kernel_mod-disk_efi_efidisk.lst
+COMMANDFILES += cmd-kernel_mod-disk_efi_efidisk.lst
+FSFILES += fs-kernel_mod-disk_efi_efidisk.lst
+PARTMAPFILES += partmap-kernel_mod-disk_efi_efidisk.lst
+
+cmd-kernel_mod-disk_efi_efidisk.lst: disk/efi/efidisk.c $(disk/efi/efidisk.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Idisk/efi -I$(srcdir)/disk/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1)
+
+fs-kernel_mod-disk_efi_efidisk.lst: disk/efi/efidisk.c $(disk/efi/efidisk.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Idisk/efi -I$(srcdir)/disk/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1)
+
+partmap-kernel_mod-disk_efi_efidisk.lst: disk/efi/efidisk.c $(disk/efi/efidisk.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Idisk/efi -I$(srcdir)/disk/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(kernel_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh kernel > $@ || (rm -f $@; exit 1)
+
+
+kernel_mod_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
+       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
+       partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
+       efi/efi.h efi/time.h efi/disk.h machine/loader.h
+kernel_mod_CFLAGS = $(COMMON_CFLAGS)
+kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+MOSTLYCLEANFILES += symlist.c
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+symlist.c: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h gensymlist.sh
+       /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h genkernsyms.sh
+       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+#
+# Only arch dependant part of normal.mod will be here. Common part for
+# all architecures of normal.mod is at start and should be kept at sync
+# with other makefiles.
+# 
+# Please put arch dependant part of normal.mod at the end of list to
+# keep it simpler to update to different architectures.
+#
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/color.c                                                  \
+       normal/menu_viewer.c normal/menu_entry.c                        \
+       normal/misc.c grub_script.tab.c                                 \
+       normal/script.c                                                 \
+       normal/x86_64/setjmp.S
+CLEANFILES += normal.mod mod-normal.o mod-normal.c pre-normal.o normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_x86_64_setjmp.o und-normal.lst
+ifneq ($(normal_mod_EXPORTS),no)
+CLEANFILES += def-normal.lst
+DEFSYMFILES += def-normal.lst
+endif
+MOSTLYCLEANFILES += normal_mod-normal_arg.d normal_mod-normal_cmdline.d normal_mod-normal_command.d normal_mod-normal_completion.d normal_mod-normal_execute.d normal_mod-normal_function.d normal_mod-normal_lexer.d normal_mod-normal_main.d normal_mod-normal_menu.d normal_mod-normal_menu_text.d normal_mod-normal_color.d normal_mod-normal_menu_viewer.d normal_mod-normal_menu_entry.d normal_mod-normal_misc.d normal_mod-grub_script_tab.d normal_mod-normal_script.d normal_mod-normal_x86_64_setjmp.d
+UNDSYMFILES += und-normal.lst
+
+normal.mod: pre-normal.o mod-normal.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(normal_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-normal.o mod-normal.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-normal.o: $(normal_mod_DEPENDENCIES) normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_x86_64_setjmp.o
+       -rm -f $@
+       $(TARGET_CC) $(normal_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ normal_mod-normal_arg.o normal_mod-normal_cmdline.o normal_mod-normal_command.o normal_mod-normal_completion.o normal_mod-normal_execute.o normal_mod-normal_function.o normal_mod-normal_lexer.o normal_mod-normal_main.o normal_mod-normal_menu.o normal_mod-normal_menu_text.o normal_mod-normal_color.o normal_mod-normal_menu_viewer.o normal_mod-normal_menu_entry.o normal_mod-normal_misc.o normal_mod-grub_script_tab.o normal_mod-normal_script.o normal_mod-normal_x86_64_setjmp.o
+
+mod-normal.o: mod-normal.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -c -o $@ $<
+
+mod-normal.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'normal' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(normal_mod_EXPORTS),no)
+def-normal.lst: pre-normal.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 normal/' > $@
+endif
+
+und-normal.lst: pre-normal.o
+       echo 'normal' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+normal_mod-normal_arg.o: normal/arg.c $(normal/arg.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_arg.d
+
+CLEANFILES += cmd-normal_mod-normal_arg.lst fs-normal_mod-normal_arg.lst partmap-normal_mod-normal_arg.lst
+COMMANDFILES += cmd-normal_mod-normal_arg.lst
+FSFILES += fs-normal_mod-normal_arg.lst
+PARTMAPFILES += partmap-normal_mod-normal_arg.lst
+
+cmd-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_arg.lst: normal/arg.c $(normal/arg.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_cmdline.o: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_cmdline.d
+
+CLEANFILES += cmd-normal_mod-normal_cmdline.lst fs-normal_mod-normal_cmdline.lst partmap-normal_mod-normal_cmdline.lst
+COMMANDFILES += cmd-normal_mod-normal_cmdline.lst
+FSFILES += fs-normal_mod-normal_cmdline.lst
+PARTMAPFILES += partmap-normal_mod-normal_cmdline.lst
+
+cmd-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_cmdline.lst: normal/cmdline.c $(normal/cmdline.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_command.o: normal/command.c $(normal/command.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_command.d
+
+CLEANFILES += cmd-normal_mod-normal_command.lst fs-normal_mod-normal_command.lst partmap-normal_mod-normal_command.lst
+COMMANDFILES += cmd-normal_mod-normal_command.lst
+FSFILES += fs-normal_mod-normal_command.lst
+PARTMAPFILES += partmap-normal_mod-normal_command.lst
+
+cmd-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_command.lst: normal/command.c $(normal/command.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_completion.o: normal/completion.c $(normal/completion.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_completion.d
+
+CLEANFILES += cmd-normal_mod-normal_completion.lst fs-normal_mod-normal_completion.lst partmap-normal_mod-normal_completion.lst
+COMMANDFILES += cmd-normal_mod-normal_completion.lst
+FSFILES += fs-normal_mod-normal_completion.lst
+PARTMAPFILES += partmap-normal_mod-normal_completion.lst
+
+cmd-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_completion.lst: normal/completion.c $(normal/completion.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_execute.o: normal/execute.c $(normal/execute.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_execute.d
+
+CLEANFILES += cmd-normal_mod-normal_execute.lst fs-normal_mod-normal_execute.lst partmap-normal_mod-normal_execute.lst
+COMMANDFILES += cmd-normal_mod-normal_execute.lst
+FSFILES += fs-normal_mod-normal_execute.lst
+PARTMAPFILES += partmap-normal_mod-normal_execute.lst
+
+cmd-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_execute.lst: normal/execute.c $(normal/execute.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_function.o: normal/function.c $(normal/function.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_function.d
+
+CLEANFILES += cmd-normal_mod-normal_function.lst fs-normal_mod-normal_function.lst partmap-normal_mod-normal_function.lst
+COMMANDFILES += cmd-normal_mod-normal_function.lst
+FSFILES += fs-normal_mod-normal_function.lst
+PARTMAPFILES += partmap-normal_mod-normal_function.lst
+
+cmd-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_function.lst: normal/function.c $(normal/function.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_lexer.o: normal/lexer.c $(normal/lexer.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_lexer.d
+
+CLEANFILES += cmd-normal_mod-normal_lexer.lst fs-normal_mod-normal_lexer.lst partmap-normal_mod-normal_lexer.lst
+COMMANDFILES += cmd-normal_mod-normal_lexer.lst
+FSFILES += fs-normal_mod-normal_lexer.lst
+PARTMAPFILES += partmap-normal_mod-normal_lexer.lst
+
+cmd-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_lexer.lst: normal/lexer.c $(normal/lexer.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_main.o: normal/main.c $(normal/main.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_main.d
+
+CLEANFILES += cmd-normal_mod-normal_main.lst fs-normal_mod-normal_main.lst partmap-normal_mod-normal_main.lst
+COMMANDFILES += cmd-normal_mod-normal_main.lst
+FSFILES += fs-normal_mod-normal_main.lst
+PARTMAPFILES += partmap-normal_mod-normal_main.lst
+
+cmd-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_main.lst: normal/main.c $(normal/main.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu.o: normal/menu.c $(normal/menu.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu.d
+
+CLEANFILES += cmd-normal_mod-normal_menu.lst fs-normal_mod-normal_menu.lst partmap-normal_mod-normal_menu.lst
+COMMANDFILES += cmd-normal_mod-normal_menu.lst
+FSFILES += fs-normal_mod-normal_menu.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu.lst
+
+cmd-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu.lst: normal/menu.c $(normal/menu.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_text.o: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_text.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_text.lst fs-normal_mod-normal_menu_text.lst partmap-normal_mod-normal_menu_text.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_text.lst
+FSFILES += fs-normal_mod-normal_menu_text.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_text.lst
+
+cmd-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_text.lst: normal/menu_text.c $(normal/menu_text.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_color.o: normal/color.c $(normal/color.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_color.d
+
+CLEANFILES += cmd-normal_mod-normal_color.lst fs-normal_mod-normal_color.lst partmap-normal_mod-normal_color.lst
+COMMANDFILES += cmd-normal_mod-normal_color.lst
+FSFILES += fs-normal_mod-normal_color.lst
+PARTMAPFILES += partmap-normal_mod-normal_color.lst
+
+cmd-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_color.lst: normal/color.c $(normal/color.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_viewer.o: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_viewer.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_viewer.lst fs-normal_mod-normal_menu_viewer.lst partmap-normal_mod-normal_menu_viewer.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_viewer.lst
+FSFILES += fs-normal_mod-normal_menu_viewer.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_viewer.lst
+
+cmd-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_viewer.lst: normal/menu_viewer.c $(normal/menu_viewer.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_menu_entry.o: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_menu_entry.d
+
+CLEANFILES += cmd-normal_mod-normal_menu_entry.lst fs-normal_mod-normal_menu_entry.lst partmap-normal_mod-normal_menu_entry.lst
+COMMANDFILES += cmd-normal_mod-normal_menu_entry.lst
+FSFILES += fs-normal_mod-normal_menu_entry.lst
+PARTMAPFILES += partmap-normal_mod-normal_menu_entry.lst
+
+cmd-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_menu_entry.lst: normal/menu_entry.c $(normal/menu_entry.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_misc.o: normal/misc.c $(normal/misc.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_misc.d
+
+CLEANFILES += cmd-normal_mod-normal_misc.lst fs-normal_mod-normal_misc.lst partmap-normal_mod-normal_misc.lst
+COMMANDFILES += cmd-normal_mod-normal_misc.lst
+FSFILES += fs-normal_mod-normal_misc.lst
+PARTMAPFILES += partmap-normal_mod-normal_misc.lst
+
+cmd-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_misc.lst: normal/misc.c $(normal/misc.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-grub_script_tab.o: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES)
+       $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-grub_script_tab.d
+
+CLEANFILES += cmd-normal_mod-grub_script_tab.lst fs-normal_mod-grub_script_tab.lst partmap-normal_mod-grub_script_tab.lst
+COMMANDFILES += cmd-normal_mod-grub_script_tab.lst
+FSFILES += fs-normal_mod-grub_script_tab.lst
+PARTMAPFILES += partmap-normal_mod-grub_script_tab.lst
+
+cmd-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-grub_script_tab.lst: grub_script.tab.c $(grub_script.tab.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -I. -I$(srcdir)/. $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_script.o: normal/script.c $(normal/script.c_DEPENDENCIES)
+       $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_script.d
+
+CLEANFILES += cmd-normal_mod-normal_script.lst fs-normal_mod-normal_script.lst partmap-normal_mod-normal_script.lst
+COMMANDFILES += cmd-normal_mod-normal_script.lst
+FSFILES += fs-normal_mod-normal_script.lst
+PARTMAPFILES += partmap-normal_mod-normal_script.lst
+
+cmd-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_script.lst: normal/script.c $(normal/script.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal -I$(srcdir)/normal $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(normal_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod-normal_x86_64_setjmp.o: normal/x86_64/setjmp.S $(normal/x86_64/setjmp.S_DEPENDENCIES)
+       $(TARGET_CC) -Inormal/x86_64 -I$(srcdir)/normal/x86_64 $(TARGET_CPPFLAGS) -DASM_FILE=1 $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -MD -c -o $@ $<
+-include normal_mod-normal_x86_64_setjmp.d
+
+CLEANFILES += cmd-normal_mod-normal_x86_64_setjmp.lst fs-normal_mod-normal_x86_64_setjmp.lst partmap-normal_mod-normal_x86_64_setjmp.lst
+COMMANDFILES += cmd-normal_mod-normal_x86_64_setjmp.lst
+FSFILES += fs-normal_mod-normal_x86_64_setjmp.lst
+PARTMAPFILES += partmap-normal_mod-normal_x86_64_setjmp.lst
+
+cmd-normal_mod-normal_x86_64_setjmp.lst: normal/x86_64/setjmp.S $(normal/x86_64/setjmp.S_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Inormal/x86_64 -I$(srcdir)/normal/x86_64 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh normal > $@ || (rm -f $@; exit 1)
+
+fs-normal_mod-normal_x86_64_setjmp.lst: normal/x86_64/setjmp.S $(normal/x86_64/setjmp.S_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Inormal/x86_64 -I$(srcdir)/normal/x86_64 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<         | sh $(srcdir)/genfslist.sh normal > $@ || (rm -f $@; exit 1)
+
+partmap-normal_mod-normal_x86_64_setjmp.lst: normal/x86_64/setjmp.S $(normal/x86_64/setjmp.S_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Inormal/x86_64 -I$(srcdir)/normal/x86_64 $(TARGET_CPPFLAGS) $(TARGET_ASFLAGS) $(normal_mod_ASFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh normal > $@ || (rm -f $@; exit 1)
+
+
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _chain.mod.
+_chain_mod_SOURCES = loader/efi/chainloader.c
+CLEANFILES += _chain.mod mod-_chain.o mod-_chain.c pre-_chain.o _chain_mod-loader_efi_chainloader.o und-_chain.lst
+ifneq ($(_chain_mod_EXPORTS),no)
+CLEANFILES += def-_chain.lst
+DEFSYMFILES += def-_chain.lst
+endif
+MOSTLYCLEANFILES += _chain_mod-loader_efi_chainloader.d
+UNDSYMFILES += und-_chain.lst
+
+_chain.mod: pre-_chain.o mod-_chain.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(_chain_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-_chain.o mod-_chain.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-_chain.o: $(_chain_mod_DEPENDENCIES) _chain_mod-loader_efi_chainloader.o
+       -rm -f $@
+       $(TARGET_CC) $(_chain_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ _chain_mod-loader_efi_chainloader.o
+
+mod-_chain.o: mod-_chain.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_chain_mod_CFLAGS) -c -o $@ $<
+
+mod-_chain.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '_chain' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(_chain_mod_EXPORTS),no)
+def-_chain.lst: pre-_chain.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _chain/' > $@
+endif
+
+und-_chain.lst: pre-_chain.o
+       echo '_chain' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+_chain_mod-loader_efi_chainloader.o: loader/efi/chainloader.c $(loader/efi/chainloader.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_chain_mod_CFLAGS) -MD -c -o $@ $<
+-include _chain_mod-loader_efi_chainloader.d
+
+CLEANFILES += cmd-_chain_mod-loader_efi_chainloader.lst fs-_chain_mod-loader_efi_chainloader.lst partmap-_chain_mod-loader_efi_chainloader.lst
+COMMANDFILES += cmd-_chain_mod-loader_efi_chainloader.lst
+FSFILES += fs-_chain_mod-loader_efi_chainloader.lst
+PARTMAPFILES += partmap-_chain_mod-loader_efi_chainloader.lst
+
+cmd-_chain_mod-loader_efi_chainloader.lst: loader/efi/chainloader.c $(loader/efi/chainloader.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_chain_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh _chain > $@ || (rm -f $@; exit 1)
+
+fs-_chain_mod-loader_efi_chainloader.lst: loader/efi/chainloader.c $(loader/efi/chainloader.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_chain_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh _chain > $@ || (rm -f $@; exit 1)
+
+partmap-_chain_mod-loader_efi_chainloader.lst: loader/efi/chainloader.c $(loader/efi/chainloader.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_chain_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh _chain > $@ || (rm -f $@; exit 1)
+
+
+_chain_mod_CFLAGS = $(COMMON_CFLAGS)
+_chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For chain.mod.
+chain_mod_SOURCES = loader/efi/chainloader_normal.c
+CLEANFILES += chain.mod mod-chain.o mod-chain.c pre-chain.o chain_mod-loader_efi_chainloader_normal.o und-chain.lst
+ifneq ($(chain_mod_EXPORTS),no)
+CLEANFILES += def-chain.lst
+DEFSYMFILES += def-chain.lst
+endif
+MOSTLYCLEANFILES += chain_mod-loader_efi_chainloader_normal.d
+UNDSYMFILES += und-chain.lst
+
+chain.mod: pre-chain.o mod-chain.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(chain_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-chain.o mod-chain.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-chain.o: $(chain_mod_DEPENDENCIES) chain_mod-loader_efi_chainloader_normal.o
+       -rm -f $@
+       $(TARGET_CC) $(chain_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ chain_mod-loader_efi_chainloader_normal.o
+
+mod-chain.o: mod-chain.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(chain_mod_CFLAGS) -c -o $@ $<
+
+mod-chain.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'chain' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(chain_mod_EXPORTS),no)
+def-chain.lst: pre-chain.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 chain/' > $@
+endif
+
+und-chain.lst: pre-chain.o
+       echo 'chain' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+chain_mod-loader_efi_chainloader_normal.o: loader/efi/chainloader_normal.c $(loader/efi/chainloader_normal.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(chain_mod_CFLAGS) -MD -c -o $@ $<
+-include chain_mod-loader_efi_chainloader_normal.d
+
+CLEANFILES += cmd-chain_mod-loader_efi_chainloader_normal.lst fs-chain_mod-loader_efi_chainloader_normal.lst partmap-chain_mod-loader_efi_chainloader_normal.lst
+COMMANDFILES += cmd-chain_mod-loader_efi_chainloader_normal.lst
+FSFILES += fs-chain_mod-loader_efi_chainloader_normal.lst
+PARTMAPFILES += partmap-chain_mod-loader_efi_chainloader_normal.lst
+
+cmd-chain_mod-loader_efi_chainloader_normal.lst: loader/efi/chainloader_normal.c $(loader/efi/chainloader_normal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(chain_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh chain > $@ || (rm -f $@; exit 1)
+
+fs-chain_mod-loader_efi_chainloader_normal.lst: loader/efi/chainloader_normal.c $(loader/efi/chainloader_normal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(chain_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh chain > $@ || (rm -f $@; exit 1)
+
+partmap-chain_mod-loader_efi_chainloader_normal.lst: loader/efi/chainloader_normal.c $(loader/efi/chainloader_normal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(chain_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh chain > $@ || (rm -f $@; exit 1)
+
+
+chain_mod_CFLAGS = $(COMMON_CFLAGS)
+chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For appleldr.mod.
+appleldr_mod_SOURCES = loader/efi/appleloader.c
+CLEANFILES += appleldr.mod mod-appleldr.o mod-appleldr.c pre-appleldr.o appleldr_mod-loader_efi_appleloader.o und-appleldr.lst
+ifneq ($(appleldr_mod_EXPORTS),no)
+CLEANFILES += def-appleldr.lst
+DEFSYMFILES += def-appleldr.lst
+endif
+MOSTLYCLEANFILES += appleldr_mod-loader_efi_appleloader.d
+UNDSYMFILES += und-appleldr.lst
+
+appleldr.mod: pre-appleldr.o mod-appleldr.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(appleldr_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-appleldr.o mod-appleldr.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-appleldr.o: $(appleldr_mod_DEPENDENCIES) appleldr_mod-loader_efi_appleloader.o
+       -rm -f $@
+       $(TARGET_CC) $(appleldr_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ appleldr_mod-loader_efi_appleloader.o
+
+mod-appleldr.o: mod-appleldr.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(appleldr_mod_CFLAGS) -c -o $@ $<
+
+mod-appleldr.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'appleldr' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(appleldr_mod_EXPORTS),no)
+def-appleldr.lst: pre-appleldr.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 appleldr/' > $@
+endif
+
+und-appleldr.lst: pre-appleldr.o
+       echo 'appleldr' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+appleldr_mod-loader_efi_appleloader.o: loader/efi/appleloader.c $(loader/efi/appleloader.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(appleldr_mod_CFLAGS) -MD -c -o $@ $<
+-include appleldr_mod-loader_efi_appleloader.d
+
+CLEANFILES += cmd-appleldr_mod-loader_efi_appleloader.lst fs-appleldr_mod-loader_efi_appleloader.lst partmap-appleldr_mod-loader_efi_appleloader.lst
+COMMANDFILES += cmd-appleldr_mod-loader_efi_appleloader.lst
+FSFILES += fs-appleldr_mod-loader_efi_appleloader.lst
+PARTMAPFILES += partmap-appleldr_mod-loader_efi_appleloader.lst
+
+cmd-appleldr_mod-loader_efi_appleloader.lst: loader/efi/appleloader.c $(loader/efi/appleloader.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(appleldr_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh appleldr > $@ || (rm -f $@; exit 1)
+
+fs-appleldr_mod-loader_efi_appleloader.lst: loader/efi/appleloader.c $(loader/efi/appleloader.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(appleldr_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh appleldr > $@ || (rm -f $@; exit 1)
+
+partmap-appleldr_mod-loader_efi_appleloader.lst: loader/efi/appleloader.c $(loader/efi/appleloader.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(appleldr_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh appleldr > $@ || (rm -f $@; exit 1)
+
+
+appleldr_mod_CFLAGS = $(COMMON_CFLAGS)
+appleldr_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _linux.mod.
+_linux_mod_SOURCES = loader/i386/efi/linux.c
+CLEANFILES += _linux.mod mod-_linux.o mod-_linux.c pre-_linux.o _linux_mod-loader_i386_efi_linux.o und-_linux.lst
+ifneq ($(_linux_mod_EXPORTS),no)
+CLEANFILES += def-_linux.lst
+DEFSYMFILES += def-_linux.lst
+endif
+MOSTLYCLEANFILES += _linux_mod-loader_i386_efi_linux.d
+UNDSYMFILES += und-_linux.lst
+
+_linux.mod: pre-_linux.o mod-_linux.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(_linux_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-_linux.o mod-_linux.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-_linux.o: $(_linux_mod_DEPENDENCIES) _linux_mod-loader_i386_efi_linux.o
+       -rm -f $@
+       $(TARGET_CC) $(_linux_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ _linux_mod-loader_i386_efi_linux.o
+
+mod-_linux.o: mod-_linux.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -c -o $@ $<
+
+mod-_linux.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '_linux' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(_linux_mod_EXPORTS),no)
+def-_linux.lst: pre-_linux.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _linux/' > $@
+endif
+
+und-_linux.lst: pre-_linux.o
+       echo '_linux' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+_linux_mod-loader_i386_efi_linux.o: loader/i386/efi/linux.c $(loader/i386/efi/linux.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader/i386/efi -I$(srcdir)/loader/i386/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -MD -c -o $@ $<
+-include _linux_mod-loader_i386_efi_linux.d
+
+CLEANFILES += cmd-_linux_mod-loader_i386_efi_linux.lst fs-_linux_mod-loader_i386_efi_linux.lst partmap-_linux_mod-loader_i386_efi_linux.lst
+COMMANDFILES += cmd-_linux_mod-loader_i386_efi_linux.lst
+FSFILES += fs-_linux_mod-loader_i386_efi_linux.lst
+PARTMAPFILES += partmap-_linux_mod-loader_i386_efi_linux.lst
+
+cmd-_linux_mod-loader_i386_efi_linux.lst: loader/i386/efi/linux.c $(loader/i386/efi/linux.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/efi -I$(srcdir)/loader/i386/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh _linux > $@ || (rm -f $@; exit 1)
+
+fs-_linux_mod-loader_i386_efi_linux.lst: loader/i386/efi/linux.c $(loader/i386/efi/linux.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/efi -I$(srcdir)/loader/i386/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh _linux > $@ || (rm -f $@; exit 1)
+
+partmap-_linux_mod-loader_i386_efi_linux.lst: loader/i386/efi/linux.c $(loader/i386/efi/linux.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader/i386/efi -I$(srcdir)/loader/i386/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(_linux_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh _linux > $@ || (rm -f $@; exit 1)
+
+
+_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/linux_normal.c
+CLEANFILES += linux.mod mod-linux.o mod-linux.c pre-linux.o linux_mod-loader_linux_normal.o und-linux.lst
+ifneq ($(linux_mod_EXPORTS),no)
+CLEANFILES += def-linux.lst
+DEFSYMFILES += def-linux.lst
+endif
+MOSTLYCLEANFILES += linux_mod-loader_linux_normal.d
+UNDSYMFILES += und-linux.lst
+
+linux.mod: pre-linux.o mod-linux.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(linux_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-linux.o mod-linux.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-linux.o: $(linux_mod_DEPENDENCIES) linux_mod-loader_linux_normal.o
+       -rm -f $@
+       $(TARGET_CC) $(linux_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ linux_mod-loader_linux_normal.o
+
+mod-linux.o: mod-linux.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -c -o $@ $<
+
+mod-linux.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'linux' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(linux_mod_EXPORTS),no)
+def-linux.lst: pre-linux.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 linux/' > $@
+endif
+
+und-linux.lst: pre-linux.o
+       echo 'linux' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+linux_mod-loader_linux_normal.o: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES)
+       $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -MD -c -o $@ $<
+-include linux_mod-loader_linux_normal.d
+
+CLEANFILES += cmd-linux_mod-loader_linux_normal.lst fs-linux_mod-loader_linux_normal.lst partmap-linux_mod-loader_linux_normal.lst
+COMMANDFILES += cmd-linux_mod-loader_linux_normal.lst
+FSFILES += fs-linux_mod-loader_linux_normal.lst
+PARTMAPFILES += partmap-linux_mod-loader_linux_normal.lst
+
+cmd-linux_mod-loader_linux_normal.lst: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh linux > $@ || (rm -f $@; exit 1)
+
+fs-linux_mod-loader_linux_normal.lst: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh linux > $@ || (rm -f $@; exit 1)
+
+partmap-linux_mod-loader_linux_normal.lst: loader/linux_normal.c $(loader/linux_normal.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Iloader -I$(srcdir)/loader $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(linux_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh linux > $@ || (rm -f $@; exit 1)
+
+
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For halt.mod.
+halt_mod_SOURCES = commands/halt.c
+CLEANFILES += halt.mod mod-halt.o mod-halt.c pre-halt.o halt_mod-commands_halt.o und-halt.lst
+ifneq ($(halt_mod_EXPORTS),no)
+CLEANFILES += def-halt.lst
+DEFSYMFILES += def-halt.lst
+endif
+MOSTLYCLEANFILES += halt_mod-commands_halt.d
+UNDSYMFILES += und-halt.lst
+
+halt.mod: pre-halt.o mod-halt.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(halt_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-halt.o mod-halt.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-halt.o: $(halt_mod_DEPENDENCIES) halt_mod-commands_halt.o
+       -rm -f $@
+       $(TARGET_CC) $(halt_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ halt_mod-commands_halt.o
+
+mod-halt.o: mod-halt.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -c -o $@ $<
+
+mod-halt.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'halt' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(halt_mod_EXPORTS),no)
+def-halt.lst: pre-halt.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 halt/' > $@
+endif
+
+und-halt.lst: pre-halt.o
+       echo 'halt' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+halt_mod-commands_halt.o: commands/halt.c $(commands/halt.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -MD -c -o $@ $<
+-include halt_mod-commands_halt.d
+
+CLEANFILES += cmd-halt_mod-commands_halt.lst fs-halt_mod-commands_halt.lst partmap-halt_mod-commands_halt.lst
+COMMANDFILES += cmd-halt_mod-commands_halt.lst
+FSFILES += fs-halt_mod-commands_halt.lst
+PARTMAPFILES += partmap-halt_mod-commands_halt.lst
+
+cmd-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh halt > $@ || (rm -f $@; exit 1)
+
+fs-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh halt > $@ || (rm -f $@; exit 1)
+
+partmap-halt_mod-commands_halt.lst: commands/halt.c $(commands/halt.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(halt_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh halt > $@ || (rm -f $@; exit 1)
+
+
+halt_mod_CFLAGS = $(COMMON_CFLAGS)
+halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reboot.mod.
+reboot_mod_SOURCES = commands/reboot.c
+CLEANFILES += reboot.mod mod-reboot.o mod-reboot.c pre-reboot.o reboot_mod-commands_reboot.o und-reboot.lst
+ifneq ($(reboot_mod_EXPORTS),no)
+CLEANFILES += def-reboot.lst
+DEFSYMFILES += def-reboot.lst
+endif
+MOSTLYCLEANFILES += reboot_mod-commands_reboot.d
+UNDSYMFILES += und-reboot.lst
+
+reboot.mod: pre-reboot.o mod-reboot.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(reboot_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-reboot.o mod-reboot.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-reboot.o: $(reboot_mod_DEPENDENCIES) reboot_mod-commands_reboot.o
+       -rm -f $@
+       $(TARGET_CC) $(reboot_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ reboot_mod-commands_reboot.o
+
+mod-reboot.o: mod-reboot.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -c -o $@ $<
+
+mod-reboot.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'reboot' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(reboot_mod_EXPORTS),no)
+def-reboot.lst: pre-reboot.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 reboot/' > $@
+endif
+
+und-reboot.lst: pre-reboot.o
+       echo 'reboot' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+reboot_mod-commands_reboot.o: commands/reboot.c $(commands/reboot.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -MD -c -o $@ $<
+-include reboot_mod-commands_reboot.d
+
+CLEANFILES += cmd-reboot_mod-commands_reboot.lst fs-reboot_mod-commands_reboot.lst partmap-reboot_mod-commands_reboot.lst
+COMMANDFILES += cmd-reboot_mod-commands_reboot.lst
+FSFILES += fs-reboot_mod-commands_reboot.lst
+PARTMAPFILES += partmap-reboot_mod-commands_reboot.lst
+
+cmd-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh reboot > $@ || (rm -f $@; exit 1)
+
+fs-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh reboot > $@ || (rm -f $@; exit 1)
+
+partmap-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(reboot_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh reboot > $@ || (rm -f $@; exit 1)
+
+
+reboot_mod_CFLAGS = $(COMMON_CFLAGS)
+reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+CLEANFILES += pci.mod mod-pci.o mod-pci.c pre-pci.o pci_mod-bus_pci.o und-pci.lst
+ifneq ($(pci_mod_EXPORTS),no)
+CLEANFILES += def-pci.lst
+DEFSYMFILES += def-pci.lst
+endif
+MOSTLYCLEANFILES += pci_mod-bus_pci.d
+UNDSYMFILES += und-pci.lst
+
+pci.mod: pre-pci.o mod-pci.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(pci_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-pci.o mod-pci.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-pci.o: $(pci_mod_DEPENDENCIES) pci_mod-bus_pci.o
+       -rm -f $@
+       $(TARGET_CC) $(pci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pci_mod-bus_pci.o
+
+mod-pci.o: mod-pci.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -c -o $@ $<
+
+mod-pci.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'pci' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(pci_mod_EXPORTS),no)
+def-pci.lst: pre-pci.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 pci/' > $@
+endif
+
+und-pci.lst: pre-pci.o
+       echo 'pci' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+pci_mod-bus_pci.o: bus/pci.c $(bus/pci.c_DEPENDENCIES)
+       $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -MD -c -o $@ $<
+-include pci_mod-bus_pci.d
+
+CLEANFILES += cmd-pci_mod-bus_pci.lst fs-pci_mod-bus_pci.lst partmap-pci_mod-bus_pci.lst
+COMMANDFILES += cmd-pci_mod-bus_pci.lst
+FSFILES += fs-pci_mod-bus_pci.lst
+PARTMAPFILES += partmap-pci_mod-bus_pci.lst
+
+cmd-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $<          | sh $(srcdir)/gencmdlist.sh pci > $@ || (rm -f $@; exit 1)
+
+fs-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $<          | sh $(srcdir)/genfslist.sh pci > $@ || (rm -f $@; exit 1)
+
+partmap-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $<          | sh $(srcdir)/genpartmaplist.sh pci > $@ || (rm -f $@; exit 1)
+
+
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+CLEANFILES += lspci.mod mod-lspci.o mod-lspci.c pre-lspci.o lspci_mod-commands_lspci.o und-lspci.lst
+ifneq ($(lspci_mod_EXPORTS),no)
+CLEANFILES += def-lspci.lst
+DEFSYMFILES += def-lspci.lst
+endif
+MOSTLYCLEANFILES += lspci_mod-commands_lspci.d
+UNDSYMFILES += und-lspci.lst
+
+lspci.mod: pre-lspci.o mod-lspci.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(lspci_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-lspci.o mod-lspci.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-lspci.o: $(lspci_mod_DEPENDENCIES) lspci_mod-commands_lspci.o
+       -rm -f $@
+       $(TARGET_CC) $(lspci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ lspci_mod-commands_lspci.o
+
+mod-lspci.o: mod-lspci.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -c -o $@ $<
+
+mod-lspci.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'lspci' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(lspci_mod_EXPORTS),no)
+def-lspci.lst: pre-lspci.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 lspci/' > $@
+endif
+
+und-lspci.lst: pre-lspci.o
+       echo 'lspci' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+lspci_mod-commands_lspci.o: commands/lspci.c $(commands/lspci.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -MD -c -o $@ $<
+-include lspci_mod-commands_lspci.d
+
+CLEANFILES += cmd-lspci_mod-commands_lspci.lst fs-lspci_mod-commands_lspci.lst partmap-lspci_mod-commands_lspci.lst
+COMMANDFILES += cmd-lspci_mod-commands_lspci.lst
+FSFILES += fs-lspci_mod-commands_lspci.lst
+PARTMAPFILES += partmap-lspci_mod-commands_lspci.lst
+
+cmd-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $<      | sh $(srcdir)/gencmdlist.sh lspci > $@ || (rm -f $@; exit 1)
+
+fs-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $<      | sh $(srcdir)/genfslist.sh lspci > $@ || (rm -f $@; exit 1)
+
+partmap-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $<      | sh $(srcdir)/genpartmaplist.sh lspci > $@ || (rm -f $@; exit 1)
+
+
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datetime.mod
+datetime_mod_SOURCES = lib/datetime.c lib/efi/datetime.c
+CLEANFILES += datetime.mod mod-datetime.o mod-datetime.c pre-datetime.o datetime_mod-lib_datetime.o datetime_mod-lib_efi_datetime.o und-datetime.lst
+ifneq ($(datetime_mod_EXPORTS),no)
+CLEANFILES += def-datetime.lst
+DEFSYMFILES += def-datetime.lst
+endif
+MOSTLYCLEANFILES += datetime_mod-lib_datetime.d datetime_mod-lib_efi_datetime.d
+UNDSYMFILES += und-datetime.lst
+
+datetime.mod: pre-datetime.o mod-datetime.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(datetime_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-datetime.o mod-datetime.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-datetime.o: $(datetime_mod_DEPENDENCIES) datetime_mod-lib_datetime.o datetime_mod-lib_efi_datetime.o
+       -rm -f $@
+       $(TARGET_CC) $(datetime_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ datetime_mod-lib_datetime.o datetime_mod-lib_efi_datetime.o
+
+mod-datetime.o: mod-datetime.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -c -o $@ $<
+
+mod-datetime.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'datetime' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(datetime_mod_EXPORTS),no)
+def-datetime.lst: pre-datetime.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 datetime/' > $@
+endif
+
+und-datetime.lst: pre-datetime.o
+       echo 'datetime' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+datetime_mod-lib_datetime.o: lib/datetime.c $(lib/datetime.c_DEPENDENCIES)
+       $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -MD -c -o $@ $<
+-include datetime_mod-lib_datetime.d
+
+CLEANFILES += cmd-datetime_mod-lib_datetime.lst fs-datetime_mod-lib_datetime.lst partmap-datetime_mod-lib_datetime.lst
+COMMANDFILES += cmd-datetime_mod-lib_datetime.lst
+FSFILES += fs-datetime_mod-lib_datetime.lst
+PARTMAPFILES += partmap-datetime_mod-lib_datetime.lst
+
+cmd-datetime_mod-lib_datetime.lst: lib/datetime.c $(lib/datetime.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh datetime > $@ || (rm -f $@; exit 1)
+
+fs-datetime_mod-lib_datetime.lst: lib/datetime.c $(lib/datetime.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh datetime > $@ || (rm -f $@; exit 1)
+
+partmap-datetime_mod-lib_datetime.lst: lib/datetime.c $(lib/datetime.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ilib -I$(srcdir)/lib $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh datetime > $@ || (rm -f $@; exit 1)
+
+
+datetime_mod-lib_efi_datetime.o: lib/efi/datetime.c $(lib/efi/datetime.c_DEPENDENCIES)
+       $(TARGET_CC) -Ilib/efi -I$(srcdir)/lib/efi $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -MD -c -o $@ $<
+-include datetime_mod-lib_efi_datetime.d
+
+CLEANFILES += cmd-datetime_mod-lib_efi_datetime.lst fs-datetime_mod-lib_efi_datetime.lst partmap-datetime_mod-lib_efi_datetime.lst
+COMMANDFILES += cmd-datetime_mod-lib_efi_datetime.lst
+FSFILES += fs-datetime_mod-lib_efi_datetime.lst
+PARTMAPFILES += partmap-datetime_mod-lib_efi_datetime.lst
+
+cmd-datetime_mod-lib_efi_datetime.lst: lib/efi/datetime.c $(lib/efi/datetime.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ilib/efi -I$(srcdir)/lib/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/gencmdlist.sh datetime > $@ || (rm -f $@; exit 1)
+
+fs-datetime_mod-lib_efi_datetime.lst: lib/efi/datetime.c $(lib/efi/datetime.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ilib/efi -I$(srcdir)/lib/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/genfslist.sh datetime > $@ || (rm -f $@; exit 1)
+
+partmap-datetime_mod-lib_efi_datetime.lst: lib/efi/datetime.c $(lib/efi/datetime.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ilib/efi -I$(srcdir)/lib/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datetime_mod_CFLAGS) -E $<     | sh $(srcdir)/genpartmaplist.sh datetime > $@ || (rm -f $@; exit 1)
+
+
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+CLEANFILES += date.mod mod-date.o mod-date.c pre-date.o date_mod-commands_date.o und-date.lst
+ifneq ($(date_mod_EXPORTS),no)
+CLEANFILES += def-date.lst
+DEFSYMFILES += def-date.lst
+endif
+MOSTLYCLEANFILES += date_mod-commands_date.d
+UNDSYMFILES += und-date.lst
+
+date.mod: pre-date.o mod-date.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(date_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-date.o mod-date.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-date.o: $(date_mod_DEPENDENCIES) date_mod-commands_date.o
+       -rm -f $@
+       $(TARGET_CC) $(date_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ date_mod-commands_date.o
+
+mod-date.o: mod-date.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -c -o $@ $<
+
+mod-date.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'date' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(date_mod_EXPORTS),no)
+def-date.lst: pre-date.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 date/' > $@
+endif
+
+und-date.lst: pre-date.o
+       echo 'date' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+date_mod-commands_date.o: commands/date.c $(commands/date.c_DEPENDENCIES)
+       $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(date_mod_CFLAGS) -MD -c -o $@ $<
+-include date_mod-commands_date.d
+
+CLEANFILES += cmd-date_mod-commands_date.lst fs-date_mod-commands_date.lst partmap-date_mod-commands_date.lst
+COMMANDFILES += cmd-date_mod-commands_date.lst
+FSFILES += fs-date_mod-commands_date.lst
+PARTMAPFILES += partmap-date_mod-commands_date.lst
+
+cmd-date_mod-commands_date.lst: commands/date.c $(commands/date.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -E $<       | sh $(srcdir)/gencmdlist.sh date > $@ || (rm -f $@; exit 1)
+
+fs-date_mod-commands_date.lst: commands/date.c $(commands/date.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -E $<       | sh $(srcdir)/genfslist.sh date > $@ || (rm -f $@; exit 1)
+
+partmap-date_mod-commands_date.lst: commands/date.c $(commands/date.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(date_mod_CFLAGS) -E $<       | sh $(srcdir)/genpartmaplist.sh date > $@ || (rm -f $@; exit 1)
+
+
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datehook.mod
+datehook_mod_SOURCES = hook/datehook.c
+CLEANFILES += datehook.mod mod-datehook.o mod-datehook.c pre-datehook.o datehook_mod-hook_datehook.o und-datehook.lst
+ifneq ($(datehook_mod_EXPORTS),no)
+CLEANFILES += def-datehook.lst
+DEFSYMFILES += def-datehook.lst
+endif
+MOSTLYCLEANFILES += datehook_mod-hook_datehook.d
+UNDSYMFILES += und-datehook.lst
+
+datehook.mod: pre-datehook.o mod-datehook.o $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(datehook_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-datehook.o mod-datehook.o
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-datehook.o: $(datehook_mod_DEPENDENCIES) datehook_mod-hook_datehook.o
+       -rm -f $@
+       $(TARGET_CC) $(datehook_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ datehook_mod-hook_datehook.o
+
+mod-datehook.o: mod-datehook.c
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -c -o $@ $<
+
+mod-datehook.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'datehook' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(datehook_mod_EXPORTS),no)
+def-datehook.lst: pre-datehook.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 datehook/' > $@
+endif
+
+und-datehook.lst: pre-datehook.o
+       echo 'datehook' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+datehook_mod-hook_datehook.o: hook/datehook.c $(hook/datehook.c_DEPENDENCIES)
+       $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -MD -c -o $@ $<
+-include datehook_mod-hook_datehook.d
+
+CLEANFILES += cmd-datehook_mod-hook_datehook.lst fs-datehook_mod-hook_datehook.lst partmap-datehook_mod-hook_datehook.lst
+COMMANDFILES += cmd-datehook_mod-hook_datehook.lst
+FSFILES += fs-datehook_mod-hook_datehook.lst
+PARTMAPFILES += partmap-datehook_mod-hook_datehook.lst
+
+cmd-datehook_mod-hook_datehook.lst: hook/datehook.c $(hook/datehook.c_DEPENDENCIES) gencmdlist.sh
+       set -e;           $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -E $<           | sh $(srcdir)/gencmdlist.sh datehook > $@ || (rm -f $@; exit 1)
+
+fs-datehook_mod-hook_datehook.lst: hook/datehook.c $(hook/datehook.c_DEPENDENCIES) genfslist.sh
+       set -e;           $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -E $<           | sh $(srcdir)/genfslist.sh datehook > $@ || (rm -f $@; exit 1)
+
+partmap-datehook_mod-hook_datehook.lst: hook/datehook.c $(hook/datehook.c_DEPENDENCIES) genpartmaplist.sh
+       set -e;           $(TARGET_CC) -Ihook -I$(srcdir)/hook $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(datehook_mod_CFLAGS) -E $<           | sh $(srcdir)/genpartmaplist.sh datehook > $@ || (rm -f $@; exit 1)
+
+
+datehook_mod_CFLAGS = $(COMMON_CFLAGS)
+datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+include $(srcdir)/conf/i386.mk
+include $(srcdir)/conf/common.mk
diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
new file mode 100644 (file)
index 0000000..5b108d2
--- /dev/null
@@ -0,0 +1,197 @@
+# -*- makefile -*-
+
+COMMON_ASFLAGS = -nostdinc -fno-builtin -m64
+COMMON_CFLAGS = -fno-builtin -m64
+COMMON_LDFLAGS = -melf_x86_64 -nostdlib
+
+# Used by various components.  These rules need to precede them.
+normal/execute.c_DEPENDENCIES = grub_script.tab.h
+normal/command.c_DEPENDENCIES = grub_script.tab.h
+normal/function.c_DEPENDENCIES = grub_script.tab.h
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Utilities.
+bin_UTILITIES = grub-mkimage
+#sbin_UTILITIES = grub-mkdevicemap
+#ifeq ($(enable_grub_emu), yes)
+#sbin_UTILITIES += grub-emu
+#endif
+
+# For grub-mkimage.
+grub_mkimage_SOURCES = util/i386/efi/grub-mkimage.c util/misc.c \
+       util/resolve.c
+
+# For grub-setup.
+#grub_setup_SOURCES = util/i386/pc/grub-setup.c util/hostdisk.c        \
+#      util/misc.c util/getroot.c kern/device.c kern/disk.c    \
+#      kern/err.c kern/misc.c fs/fat.c fs/ext2.c fs/xfs.c fs/affs.c    \
+#      fs/sfs.c kern/parser.c kern/partition.c partmap/pc.c            \
+#      fs/ufs.c fs/minix.c fs/hfs.c fs/jfs.c fs/hfsplus.c kern/file.c  \
+#      kern/fs.c kern/env.c fs/fshelp.c
+
+# For grub-mkdevicemap.
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+
+# For grub-emu.
+util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
+grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c       \
+       commands/configfile.c commands/help.c                           \
+       commands/terminal.c commands/ls.c commands/test.c               \
+       commands/search.c commands/hexdump.c lib/hexdump.c              \
+       commands/halt.c commands/reboot.c                               \
+       commands/i386/cpuid.c                                           \
+       disk/loopback.c                                                 \
+       \
+       fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c                 \
+       fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c          \
+       fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c                  \
+       fs/ufs.c fs/xfs.c fs/afs.c                                      \
+       \
+       io/gzio.c                                                       \
+       kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c       \
+       kern/err.c                                                      \
+       normal/execute.c kern/file.c kern/fs.c normal/lexer.c           \
+       kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
+       grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
+       normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
+       normal/completion.c normal/context.c normal/main.c              \
+       normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
+       normal/menu_text.c                                              \
+       normal/misc.c normal/script.c                                   \
+       normal/color.c                                                  \
+       partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
+       partmap/acorn.c partmap/gpt.c                                   \
+       util/console.c util/hostfs.c util/grub-emu.c util/misc.c        \
+       util/hostdisk.c util/getroot.c                                  \
+       util/i386/pc/misc.c                                             \
+       \
+       disk/raid.c disk/raid5_recover.c disk/raid6_recover.c           \
+       disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c             \
+       grub_emu_init.c
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+# Scripts.
+sbin_SCRIPTS = grub-install
+
+# For grub-install.
+grub_install_SOURCES = util/i386/efi/grub-install.in
+
+# Modules.
+pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
+       halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod \
+       datetime.mod date.mod datehook.mod
+
+# For kernel.mod.
+kernel_mod_EXPORTS = no
+kernel_mod_SOURCES = kern/x86_64/efi/startup.S kern/x86_64/efi/callwrap.S \
+       kern/main.c kern/device.c \
+       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
+       kern/x86_64/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \
+       kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \
+       kern/time.c \
+       kern/i386/tsc.c kern/i386/pit.c \
+       kern/generic/millisleep.c kern/generic/rtc_get_time_ms.c \
+       term/efi/console.c disk/efi/efidisk.c
+kernel_mod_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
+       env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
+       partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
+       efi/efi.h efi/time.h efi/disk.h machine/loader.h
+kernel_mod_CFLAGS = $(COMMON_CFLAGS)
+kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+MOSTLYCLEANFILES += symlist.c
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+symlist.c: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h gensymlist.sh
+       /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h genkernsyms.sh
+       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+#
+# Only arch dependant part of normal.mod will be here. Common part for
+# all architecures of normal.mod is at start and should be kept at sync
+# with other makefiles.
+# 
+# Please put arch dependant part of normal.mod at the end of list to
+# keep it simpler to update to different architectures.
+#
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/completion.c normal/execute.c                            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_text.c                                              \
+       normal/color.c                                                  \
+       normal/menu_viewer.c normal/menu_entry.c                        \
+       normal/misc.c grub_script.tab.c                                 \
+       normal/script.c                                                 \
+       normal/x86_64/setjmp.S
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _chain.mod.
+_chain_mod_SOURCES = loader/efi/chainloader.c
+_chain_mod_CFLAGS = $(COMMON_CFLAGS)
+_chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For chain.mod.
+chain_mod_SOURCES = loader/efi/chainloader_normal.c
+chain_mod_CFLAGS = $(COMMON_CFLAGS)
+chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For appleldr.mod.
+appleldr_mod_SOURCES = loader/efi/appleloader.c
+appleldr_mod_CFLAGS = $(COMMON_CFLAGS)
+appleldr_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _linux.mod.
+_linux_mod_SOURCES = loader/i386/efi/linux.c
+_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/linux_normal.c
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For halt.mod.
+halt_mod_SOURCES = commands/halt.c
+halt_mod_CFLAGS = $(COMMON_CFLAGS)
+halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reboot.mod.
+reboot_mod_SOURCES = commands/reboot.c
+reboot_mod_CFLAGS = $(COMMON_CFLAGS)
+reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datetime.mod
+datetime_mod_SOURCES = lib/datetime.c lib/efi/datetime.c
+datetime_mod_CFLAGS = $(COMMON_CFLAGS)
+datetime_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For date.mod
+date_mod_SOURCES = commands/date.c
+date_mod_CFLAGS = $(COMMON_CFLAGS)
+date_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For datehook.mod
+datehook_mod_SOURCES = hook/datehook.c
+datehook_mod_CFLAGS = $(COMMON_CFLAGS)
+datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+include $(srcdir)/conf/i386.mk
+include $(srcdir)/conf/common.mk
diff --git a/config.guess b/config.guess
new file mode 100644 (file)
index 0000000..3f51f4e
--- /dev/null
@@ -0,0 +1,1552 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+#   Free Software Foundation, Inc.
+
+timestamp='2008-12-19'
+
+# This file 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.
+#
+# 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
+# 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 Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+       for c in cc gcc c89 c99 ; do
+         if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+            CC_FOR_BUILD="$c"; break ;
+         fi ;
+       done ;
+       if test x"$CC_FOR_BUILD" = x ; then
+         CC_FOR_BUILD=no_compiler_found ;
+       fi
+       ;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+       PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+       # NetBSD (nbsd) targets should (where applicable) match one or
+       # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+       # *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+       # switched to ELF, *-*-netbsd* would select the old
+       # object file format.  This provides both forward
+       # compatibility and a consistent mechanism for selecting the
+       # object file format.
+       #
+       # Note: NetBSD doesn't particularly care about the vendor
+       # portion of the name.  We always set it to "unknown".
+       sysctl="sysctl -n hw.machine_arch"
+       UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+           /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+       case "${UNAME_MACHINE_ARCH}" in
+           armeb) machine=armeb-unknown ;;
+           arm*) machine=arm-unknown ;;
+           sh3el) machine=shl-unknown ;;
+           sh3eb) machine=sh-unknown ;;
+           sh5el) machine=sh5le-unknown ;;
+           *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+       esac
+       # The Operating System including object format, if it has switched
+       # to ELF recently, or will in the future.
+       case "${UNAME_MACHINE_ARCH}" in
+           arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+               eval $set_cc_for_build
+               if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+                       | grep __ELF__ >/dev/null
+               then
+                   # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+                   # Return netbsd for either.  FIX?
+                   os=netbsd
+               else
+                   os=netbsdelf
+               fi
+               ;;
+           *)
+               os=netbsd
+               ;;
+       esac
+       # The OS release
+       # Debian GNU/NetBSD machines have a different userland, and
+       # thus, need a distinct triplet. However, they do not need
+       # kernel version information, so it can be replaced with a
+       # suitable tag, in the style of linux-gnu.
+       case "${UNAME_VERSION}" in
+           Debian*)
+               release='-gnu'
+               ;;
+           *)
+               release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+               ;;
+       esac
+       # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+       # contains redundant information, the shorter form:
+       # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+       echo "${machine}-${os}${release}"
+       exit ;;
+    *:OpenBSD:*:*)
+       UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+       echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+       exit ;;
+    *:ekkoBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+       exit ;;
+    *:SolidBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+       exit ;;
+    macppc:MirBSD:*:*)
+       echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    *:MirBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    alpha:OSF1:*:*)
+       case $UNAME_RELEASE in
+       *4.0)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+               ;;
+       *5.*)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+               ;;
+       esac
+       # According to Compaq, /usr/sbin/psrinfo has been available on
+       # OSF/1 and Tru64 systems produced since 1995.  I hope that
+       # covers most systems running today.  This code pipes the CPU
+       # types through head -n 1, so we only detect the type of CPU 0.
+       ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+       case "$ALPHA_CPU_TYPE" in
+           "EV4 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "EV4.5 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "LCA4 (21066/21068)")
+               UNAME_MACHINE="alpha" ;;
+           "EV5 (21164)")
+               UNAME_MACHINE="alphaev5" ;;
+           "EV5.6 (21164A)")
+               UNAME_MACHINE="alphaev56" ;;
+           "EV5.6 (21164PC)")
+               UNAME_MACHINE="alphapca56" ;;
+           "EV5.7 (21164PC)")
+               UNAME_MACHINE="alphapca57" ;;
+           "EV6 (21264)")
+               UNAME_MACHINE="alphaev6" ;;
+           "EV6.7 (21264A)")
+               UNAME_MACHINE="alphaev67" ;;
+           "EV6.8CB (21264C)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8AL (21264B)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8CX (21264D)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.9A (21264/EV69A)")
+               UNAME_MACHINE="alphaev69" ;;
+           "EV7 (21364)")
+               UNAME_MACHINE="alphaev7" ;;
+           "EV7.9 (21364A)")
+               UNAME_MACHINE="alphaev79" ;;
+       esac
+       # A Pn.n version is a patched version.
+       # A Vn.n version is a released version.
+       # A Tn.n version is a released field test version.
+       # A Xn.n version is an unreleased experimental baselevel.
+       # 1.2 uses "1.2" for uname -r.
+       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       exit ;;
+    Alpha\ *:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # Should we change UNAME_MACHINE based on the output of uname instead
+       # of the specific Alpha model?
+       echo alpha-pc-interix
+       exit ;;
+    21064:Windows_NT:50:3)
+       echo alpha-dec-winnt3.5
+       exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+       echo m68k-unknown-sysv4
+       exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-amigaos
+       exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-morphos
+       exit ;;
+    *:OS/390:*:*)
+       echo i370-ibm-openedition
+       exit ;;
+    *:z/VM:*:*)
+       echo s390-ibm-zvmoe
+       exit ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+       exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+       echo arm-unknown-riscos
+       exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+       echo hppa1.1-hitachi-hiuxmpp
+       exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+       # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+       if test "`(/bin/universe) 2>/dev/null`" = att ; then
+               echo pyramid-pyramid-sysv3
+       else
+               echo pyramid-pyramid-bsd
+       fi
+       exit ;;
+    NILE*:*:*:dcosx)
+       echo pyramid-pyramid-svr4
+       exit ;;
+    DRS?6000:unix:4.0:6*)
+       echo sparc-icl-nx6
+       exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+       case `/usr/bin/uname -p` in
+           sparc) echo sparc-icl-nx7; exit ;;
+       esac ;;
+    sun4H:SunOS:5.*:*)
+       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+       eval $set_cc_for_build
+       SUN_ARCH="i386"
+       # If there is a compiler, see if it is configured for 64-bit objects.
+       # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+       # This test works for both compilers.
+       if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+           if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+               (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+               grep IS_64BIT_ARCH >/dev/null
+           then
+               SUN_ARCH="x86_64"
+           fi
+       fi
+       echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:6*:*)
+       # According to config.sub, this is the proper way to canonicalize
+       # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+       # it's likely to be more like Solaris than SunOS4.
+       echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:*:*)
+       case "`/usr/bin/arch -k`" in
+           Series*|S4*)
+               UNAME_RELEASE=`uname -v`
+               ;;
+       esac
+       # Japanese Language versions have a version number like `4.1.3-JL'.
+       echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+       exit ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit ;;
+    sun*:*:4.2BSD:*)
+       UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+       test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+       case "`/bin/arch`" in
+           sun3)
+               echo m68k-sun-sunos${UNAME_RELEASE}
+               ;;
+           sun4)
+               echo sparc-sun-sunos${UNAME_RELEASE}
+               ;;
+       esac
+       exit ;;
+    aushp:SunOS:*:*)
+       echo sparc-auspex-sunos${UNAME_RELEASE}
+       exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+        exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit ;;
+    m68k:machten:*:*)
+       echo m68k-apple-machten${UNAME_RELEASE}
+       exit ;;
+    powerpc:machten:*:*)
+       echo powerpc-apple-machten${UNAME_RELEASE}
+       exit ;;
+    RISC*:Mach:*:*)
+       echo mips-dec-mach_bsd4.3
+       exit ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+       echo clipper-intergraph-clix${UNAME_RELEASE}
+       exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+       int main (int argc, char *argv[]) {
+#else
+       int main (argc, argv) int argc; char *argv[]; {
+#endif
+       #if defined (host_mips) && defined (MIPSEB)
+       #if defined (SYSTYPE_SYSV)
+         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_SVR4)
+         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+       #endif
+       #endif
+         exit (-1);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c &&
+         dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+         SYSTEM_NAME=`$dummy $dummyarg` &&
+           { echo "$SYSTEM_NAME"; exit; }
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit ;;
+    Motorola:PowerMAX_OS:*:*)
+       echo powerpc-motorola-powermax
+       exit ;;
+    Motorola:*:4.3:PL8-*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+       echo powerpc-harris-powerunix
+       exit ;;
+    m88k:CX/UX:7*:*)
+       echo m88k-harris-cxux7
+       exit ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+       if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+       then
+           if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+              [ ${TARGET_BINARY_INTERFACE}x = x ]
+           then
+               echo m88k-dg-dgux${UNAME_RELEASE}
+           else
+               echo m88k-dg-dguxbcs${UNAME_RELEASE}
+           fi
+       else
+           echo i586-dg-dgux${UNAME_RELEASE}
+       fi
+       exit ;;
+    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
+       echo m88k-dolphin-sysv3
+       exit ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+       echo m88k-tektronix-sysv3
+       exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+       echo m68k-tektronix-bsd
+       exit ;;
+    *:IRIX*:*:*)
+       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+       echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+       exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+       echo i386-ibm-aix
+       exit ;;
+    ia64:AIX:*:*)
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:2:3)
+       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+               eval $set_cc_for_build
+               sed 's/^                //' << EOF >$dummy.c
+               #include <sys/systemcfg.h>
+
+               main()
+                       {
+                       if (!__power_pc())
+                               exit(1);
+                       puts("powerpc-ibm-aix3.2.5");
+                       exit(0);
+                       }
+EOF
+               if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+               then
+                       echo "$SYSTEM_NAME"
+               else
+                       echo rs6000-ibm-aix3.2.5
+               fi
+       elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+               echo rs6000-ibm-aix3.2.4
+       else
+               echo rs6000-ibm-aix3.2
+       fi
+       exit ;;
+    *:AIX:*:[456])
+       IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+       if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+               IBM_ARCH=rs6000
+       else
+               IBM_ARCH=powerpc
+       fi
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+       echo romp-ibm-bsd4.4
+       exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit ;;
+    9000/[34678]??:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       case "${UNAME_MACHINE}" in
+           9000/31? )            HP_ARCH=m68000 ;;
+           9000/[34]?? )         HP_ARCH=m68k ;;
+           9000/[678][0-9][0-9])
+               if [ -x /usr/bin/getconf ]; then
+                   sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                         '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+               fi
+               if [ "${HP_ARCH}" = "" ]; then
+                   eval $set_cc_for_build
+                   sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+               {
+               case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+               case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+               case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+                   switch (bits)
+                       {
+                       case 64: puts ("hppa2.0w"); break;
+                       case 32: puts ("hppa2.0n"); break;
+                       default: puts ("hppa2.0"); break;
+                       } break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+                   puts ("hppa2.0"); break;
+              #endif
+               default: puts ("hppa1.0"); break;
+               }
+                  exit (0);
+              }
+EOF
+                   (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+                   test -z "$HP_ARCH" && HP_ARCH=hppa
+               fi ;;
+       esac
+       if [ ${HP_ARCH} = "hppa2.0w" ]
+       then
+           eval $set_cc_for_build
+
+           # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+           # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+           # generating 64-bit code.  GNU and HP use different nomenclature:
+           #
+           # $ CC_FOR_BUILD=cc ./config.guess
+           # => hppa2.0w-hp-hpux11.23
+           # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+           # => hppa64-hp-hpux11.23
+
+           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+               grep __LP64__ >/dev/null
+           then
+               HP_ARCH="hppa2.0w"
+           else
+               HP_ARCH="hppa64"
+           fi
+       fi
+       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       exit ;;
+    ia64:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ia64-hp-hpux${HPUX_REV}
+       exit ;;
+    3050*:HI-UX:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <unistd.h>
+       int
+       main ()
+       {
+         long cpu = sysconf (_SC_CPU_VERSION);
+         /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+            true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+            results, however.  */
+         if (CPU_IS_PA_RISC (cpu))
+           {
+             switch (cpu)
+               {
+                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+                 default: puts ("hppa-hitachi-hiuxwe2"); break;
+               }
+           }
+         else if (CPU_IS_HP_MC68K (cpu))
+           puts ("m68k-hitachi-hiuxwe2");
+         else puts ("unknown-hitachi-hiuxwe2");
+         exit (0);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+               { echo "$SYSTEM_NAME"; exit; }
+       echo unknown-hitachi-hiuxwe2
+       exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+       echo hppa1.0-hp-mpeix
+       exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+       echo hppa1.1-hp-osf
+       exit ;;
+    hp8??:OSF1:*:*)
+       echo hppa1.0-hp-osf
+       exit ;;
+    i*86:OSF1:*:*)
+       if [ -x /usr/sbin/sysversion ] ; then
+           echo ${UNAME_MACHINE}-unknown-osf1mk
+       else
+           echo ${UNAME_MACHINE}-unknown-osf1
+       fi
+       exit ;;
+    parisc*:Lites*:*:*)
+       echo hppa1.1-hp-lites
+       exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+       echo c1-convex-bsd
+        exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+        exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+       echo c34-convex-bsd
+        exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+       echo c38-convex-bsd
+        exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+       echo c4-convex-bsd
+        exit ;;
+    CRAY*Y-MP:*:*:*)
+       echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*[A-Z]90:*:*:*)
+       echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+       | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+             -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*TS:*:*:*)
+       echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*T3E:*:*:*)
+       echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*SV1:*:*:*)
+       echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    *:UNICOS/mp:*:*)
+       echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+       FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+       exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       exit ;;
+    sparc*:BSD/OS:*:*)
+       echo sparc-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:FreeBSD:*:*)
+       case ${UNAME_MACHINE} in
+           pc98)
+               echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           amd64)
+               echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           *)
+               echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+       esac
+       exit ;;
+    i*:CYGWIN*:*)
+       echo ${UNAME_MACHINE}-pc-cygwin
+       exit ;;
+    *:MINGW*:*)
+       echo ${UNAME_MACHINE}-pc-mingw32
+       exit ;;
+    i*:windows32*:*)
+       # uname -m includes "-pc" on this system.
+       echo ${UNAME_MACHINE}-mingw32
+       exit ;;
+    i*:PW*:*)
+       echo ${UNAME_MACHINE}-pc-pw32
+       exit ;;
+    *:Interix*:[3456]*)
+       case ${UNAME_MACHINE} in
+           x86)
+               echo i586-pc-interix${UNAME_RELEASE}
+               exit ;;
+           EM64T | authenticamd | genuineintel)
+               echo x86_64-unknown-interix${UNAME_RELEASE}
+               exit ;;
+           IA64)
+               echo ia64-unknown-interix${UNAME_RELEASE}
+               exit ;;
+       esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+       echo i${UNAME_MACHINE}-pc-mks
+       exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+       # UNAME_MACHINE based on the output of uname instead of i386?
+       echo i586-pc-interix
+       exit ;;
+    i*:UWIN*:*)
+       echo ${UNAME_MACHINE}-pc-uwin
+       exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+       echo x86_64-unknown-cygwin
+       exit ;;
+    p*:CYGWIN*:*)
+       echo powerpcle-unknown-cygwin
+       exit ;;
+    prep*:SunOS:5.*:*)
+       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    *:GNU:*:*)
+       # the GNU system
+       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       exit ;;
+    *:GNU/*:*:*)
+       # other systems with GNU libc and userland
+       echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+       exit ;;
+    i*86:Minix:*:*)
+       echo ${UNAME_MACHINE}-pc-minix
+       exit ;;
+    arm*:Linux:*:*)
+       eval $set_cc_for_build
+       if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+           | grep -q __ARM_EABI__
+       then
+           echo ${UNAME_MACHINE}-unknown-linux-gnu
+       else
+           echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+       fi
+       exit ;;
+    avr32*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    cris:Linux:*:*)
+       echo cris-axis-linux-gnu
+       exit ;;
+    crisv32:Linux:*:*)
+       echo crisv32-axis-linux-gnu
+       exit ;;
+    frv:Linux:*:*)
+       echo frv-unknown-linux-gnu
+       exit ;;
+    ia64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    m32r*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    m68*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    mips:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef mips
+       #undef mipsel
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=mipsel
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=mips
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+           /^CPU/{
+               s: ::g
+               p
+           }'`"
+       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+       ;;
+    mips64:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef mips64
+       #undef mips64el
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=mips64el
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=mips64
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+           /^CPU/{
+               s: ::g
+               p
+           }'`"
+       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+       ;;
+    or32:Linux:*:*)
+       echo or32-unknown-linux-gnu
+       exit ;;
+    ppc:Linux:*:*)
+       echo powerpc-unknown-linux-gnu
+       exit ;;
+    ppc64:Linux:*:*)
+       echo powerpc64-unknown-linux-gnu
+       exit ;;
+    alpha:Linux:*:*)
+       case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+         EV5)   UNAME_MACHINE=alphaev5 ;;
+         EV56)  UNAME_MACHINE=alphaev56 ;;
+         PCA56) UNAME_MACHINE=alphapca56 ;;
+         PCA57) UNAME_MACHINE=alphapca56 ;;
+         EV6)   UNAME_MACHINE=alphaev6 ;;
+         EV67)  UNAME_MACHINE=alphaev67 ;;
+         EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+       objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+       if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+       echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+       exit ;;
+    padre:Linux:*:*)
+       echo sparc-unknown-linux-gnu
+       exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+       # Look for CPU level
+       case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+         PA7*) echo hppa1.1-unknown-linux-gnu ;;
+         PA8*) echo hppa2.0-unknown-linux-gnu ;;
+         *)    echo hppa-unknown-linux-gnu ;;
+       esac
+       exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+       echo hppa64-unknown-linux-gnu
+       exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+       echo ${UNAME_MACHINE}-ibm-linux
+       exit ;;
+    sh64*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    sh*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    vax:Linux:*:*)
+       echo ${UNAME_MACHINE}-dec-linux-gnu
+       exit ;;
+    x86_64:Linux:*:*)
+       echo x86_64-unknown-linux-gnu
+       exit ;;
+    xtensa*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    i*86:Linux:*:*)
+       # The BFD linker knows what the default object file format is, so
+       # first see if it will tell us. cd to the root directory to prevent
+       # problems with other programs or directories called `ld' in the path.
+       # Set LC_ALL=C to ensure ld outputs messages in English.
+       ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+                        | sed -ne '/supported targets:/!d
+                                   s/[         ][      ]*/ /g
+                                   s/.*supported targets: *//
+                                   s/ .*//
+                                   p'`
+        case "$ld_supported_targets" in
+         elf32-i386)
+               TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+               ;;
+         a.out-i386-linux)
+               echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+               exit ;;
+         "")
+               # Either a pre-BFD a.out linker (linux-gnuoldld) or
+               # one that does not give us useful --help.
+               echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+               exit ;;
+       esac
+       # Determine whether the default compiler is a.out or elf
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <features.h>
+       #ifdef __ELF__
+       # ifdef __GLIBC__
+       #  if __GLIBC__ >= 2
+       LIBC=gnu
+       #  else
+       LIBC=gnulibc1
+       #  endif
+       # else
+       LIBC=gnulibc1
+       # endif
+       #else
+       #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+       LIBC=gnu
+       #else
+       LIBC=gnuaout
+       #endif
+       #endif
+       #ifdef __dietlibc__
+       LIBC=dietlibc
+       #endif
+EOF
+       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+           /^LIBC/{
+               s: ::g
+               p
+           }'`"
+       test x"${LIBC}" != x && {
+               echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+               exit
+       }
+       test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+       ;;
+    i*86:DYNIX/ptx:4*:*)
+       # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+       # earlier versions are messed up and put the nodename in both
+       # sysname and nodename.
+       echo i386-sequent-sysv4
+       exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+       # I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+       echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+       exit ;;
+    i*86:OS/2:*:*)
+       # If we were able to find `uname', then EMX Unix compatibility
+       # is probably installed.
+       echo ${UNAME_MACHINE}-pc-os2-emx
+       exit ;;
+    i*86:XTS-300:*:STOP)
+       echo ${UNAME_MACHINE}-unknown-stop
+       exit ;;
+    i*86:atheos:*:*)
+       echo ${UNAME_MACHINE}-unknown-atheos
+       exit ;;
+    i*86:syllable:*:*)
+       echo ${UNAME_MACHINE}-pc-syllable
+       exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    i*86:*DOS:*:*)
+       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+       UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+               echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+       else
+               echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+       fi
+       exit ;;
+    i*86:*:5:[678]*)
+       # UnixWare 7.x, OpenUNIX and OpenServer 6.
+       case `/bin/uname -X | grep "^Machine"` in
+           *486*)           UNAME_MACHINE=i486 ;;
+           *Pentium)        UNAME_MACHINE=i586 ;;
+           *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+       esac
+       echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+       exit ;;
+    i*86:*:3.2:*)
+       if test -f /usr/options/cb.name; then
+               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/dev/null >/dev/null ; then
+               UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+               (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+                       && UNAME_MACHINE=i586
+               (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-pc-sysv32
+       fi
+       exit ;;
+    pc:*:*:*)
+       # Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+       echo i386-pc-msdosdjgpp
+        exit ;;
+    Intel:Mach:3*:*)
+       echo i386-pc-mach3
+       exit ;;
+    paragon:*:*:*)
+       echo i860-intel-osf1
+       exit ;;
+    i860:*:4.*:*) # i860-SVR4
+       if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+         echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+       else # Add other i860-SVR4 vendors below as they are discovered.
+         echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+       fi
+       exit ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+       echo m68k-convergent-sysv
+       exit ;;
+    M680?0:D-NIX:5.3:*)
+       echo m68k-diab-dnix
+       exit ;;
+    M68*:*:R3V[5678]*:*)
+       test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+       OS_REL=''
+       test -r /etc/.relid \
+       && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+         && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+         && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+       OS_REL='.3'
+       test -r /etc/.relid \
+           && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+           && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+           && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+           && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+       echo m68k-atari-sysv4
+       exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    rs6000:LynxOS:2.*:*)
+       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+       echo powerpc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+       echo mips-dde-sysv${UNAME_RELEASE}
+       exit ;;
+    RM*:ReliantUNIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    RM*:SINIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    *:SINIX-*:*:*)
+       if uname -p 2>/dev/null >/dev/null ; then
+               UNAME_MACHINE=`(uname -p) 2>/dev/null`
+               echo ${UNAME_MACHINE}-sni-sysv4
+       else
+               echo ns32k-sni-sysv
+       fi
+       exit ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # How about differentiating between stratus architectures? -djm
+       echo hppa1.1-stratus-sysv4
+       exit ;;
+    *:*:*:FTX*)
+       # From seanf@swdc.stratus.com.
+       echo i860-stratus-sysv4
+       exit ;;
+    i*86:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo ${UNAME_MACHINE}-stratus-vos
+       exit ;;
+    *:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo hppa1.1-stratus-vos
+       exit ;;
+    mc68*:A/UX:*:*)
+       echo m68k-apple-aux${UNAME_RELEASE}
+       exit ;;
+    news*:NEWS-OS:6*:*)
+       echo mips-sony-newsos6
+       exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+       if [ -d /usr/nec ]; then
+               echo mips-nec-sysv${UNAME_RELEASE}
+       else
+               echo mips-unknown-sysv${UNAME_RELEASE}
+       fi
+        exit ;;
+    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
+       echo powerpc-be-beos
+       exit ;;
+    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
+       echo powerpc-apple-beos
+       exit ;;
+    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
+       echo i586-pc-beos
+       exit ;;
+    BePC:Haiku:*:*)    # Haiku running on Intel PC compatible.
+       echo i586-pc-haiku
+       exit ;;
+    SX-4:SUPER-UX:*:*)
+       echo sx4-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-5:SUPER-UX:*:*)
+       echo sx5-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-6:SUPER-UX:*:*)
+       echo sx6-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-7:SUPER-UX:*:*)
+       echo sx7-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8:SUPER-UX:*:*)
+       echo sx8-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8R:SUPER-UX:*:*)
+       echo sx8r-nec-superux${UNAME_RELEASE}
+       exit ;;
+    Power*:Rhapsody:*:*)
+       echo powerpc-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Rhapsody:*:*)
+       echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Darwin:*:*)
+       UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+       case $UNAME_PROCESSOR in
+           unknown) UNAME_PROCESSOR=powerpc ;;
+       esac
+       echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+       exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+       UNAME_PROCESSOR=`uname -p`
+       if test "$UNAME_PROCESSOR" = "x86"; then
+               UNAME_PROCESSOR=i386
+               UNAME_MACHINE=pc
+       fi
+       echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+       exit ;;
+    *:QNX:*:4*)
+       echo i386-pc-qnx
+       exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+       echo nse-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+       echo nsr-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    *:NonStop-UX:*:*)
+       echo mips-compaq-nonstopux
+       exit ;;
+    BS2000:POSIX*:*:*)
+       echo bs2000-siemens-sysv
+       exit ;;
+    DS/*:UNIX_System_V:*:*)
+       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+       exit ;;
+    *:Plan9:*:*)
+       # "uname -m" is not consistent, so use $cputype instead. 386
+       # is converted to i386 for consistency with other x86
+       # operating systems.
+       if test "$cputype" = "386"; then
+           UNAME_MACHINE=i386
+       else
+           UNAME_MACHINE="$cputype"
+       fi
+       echo ${UNAME_MACHINE}-unknown-plan9
+       exit ;;
+    *:TOPS-10:*:*)
+       echo pdp10-unknown-tops10
+       exit ;;
+    *:TENEX:*:*)
+       echo pdp10-unknown-tenex
+       exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+       echo pdp10-dec-tops20
+       exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+       echo pdp10-xkl-tops20
+       exit ;;
+    *:TOPS-20:*:*)
+       echo pdp10-unknown-tops20
+       exit ;;
+    *:ITS:*:*)
+       echo pdp10-unknown-its
+       exit ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+       exit ;;
+    *:DragonFly:*:*)
+       echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit ;;
+    *:*VMS:*:*)
+       UNAME_MACHINE=`(uname -p) 2>/dev/null`
+       case "${UNAME_MACHINE}" in
+           A*) echo alpha-dec-vms ; exit ;;
+           I*) echo ia64-dec-vms ; exit ;;
+           V*) echo vax-dec-vms ; exit ;;
+       esac ;;
+    *:XENIX:*:SysV)
+       echo i386-pc-xenix
+       exit ;;
+    i*86:skyos:*:*)
+       echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+       exit ;;
+    i*86:rdos:*:*)
+       echo ${UNAME_MACHINE}-pc-rdos
+       exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+         ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+       printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+       printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+       { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+       echo c1-convex-bsd
+       exit ;;
+    c2*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit ;;
+    c34*)
+       echo c34-convex-bsd
+       exit ;;
+    c38*)
+       echo c38-convex-bsd
+       exit ;;
+    c4*)
+       echo c4-convex-bsd
+       exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.h.in b/config.h.in
new file mode 100644 (file)
index 0000000..91e9615
--- /dev/null
@@ -0,0 +1,131 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define it if GAS requires that absolute indirect calls/jumps are not
+   prefixed with an asterisk */
+#undef ABSOLUTE_WITHOUT_ASTERISK
+
+/* Define it to \"addr32\" or \"addr32;\" to make GAS happy */
+#undef ADDR32
+
+/* Define it to one of __bss_start, edata and _edata */
+#undef BSS_START_SYMBOL
+
+/* Define it to \"data32\" or \"data32;\" to make GAS happy */
+#undef DATA32
+
+/* Use lzma compression */
+#undef ENABLE_LZMA
+
+/* Use lzo compression */
+#undef ENABLE_LZO
+
+/* Define it to either end or _end */
+#undef END_SYMBOL
+
+/* Define if C symbols get an underscore after compilation */
+#undef HAVE_ASM_USCORE
+
+/* Define to 1 if you have the `asprintf' function. */
+#undef HAVE_ASPRINTF
+
+/* Define to 1 if you have the <curses.h> header file. */
+#undef HAVE_CURSES_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <lzo1x.h> header file. */
+#undef HAVE_LZO1X_H
+
+/* Define to 1 if you have the <lzo/lzo1x.h> header file. */
+#undef HAVE_LZO_LZO1X_H
+
+/* Define to 1 if you have the `memalign' function. */
+#undef HAVE_MEMALIGN
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <ncurses/curses.h> header file. */
+#undef HAVE_NCURSES_CURSES_H
+
+/* Define to 1 if you have the <ncurses.h> header file. */
+#undef HAVE_NCURSES_H
+
+/* Define to 1 if you have the `posix_memalign' function. */
+#undef HAVE_POSIX_MEMALIGN
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <usb.h> header file. */
+#undef HAVE_USB_H
+
+/* Define to 1 if you enable memory manager debugging. */
+#undef MM_DEBUG
+
+/* Define to 1 if GCC generates calls to __enable_execute_stack() */
+#undef NEED_ENABLE_EXECUTE_STACK
+
+/* Catch gcc bug */
+#undef NESTED_FUNC_ATTR
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of `long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* The size of `void *', as computed by sizeof. */
+#undef SIZEOF_VOID_P
+
+/* Define it to either start or _start */
+#undef START_SYMBOL
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
diff --git a/config.sub b/config.sub
new file mode 100644 (file)
index 0000000..d8573e8
--- /dev/null
@@ -0,0 +1,1681 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+#   Free Software Foundation, Inc.
+
+timestamp='2009-01-19'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file 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.
+#
+# 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 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 Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#      CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  kopensolaris*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+       -sun*os*)
+               # Prevent following clause from handling this invalid input.
+               ;;
+       -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+       -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+       -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+       -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+       -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+       -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+       -apple | -axis | -knuth | -cray)
+               os=
+               basic_machine=$1
+               ;;
+       -sim | -cisco | -oki | -wec | -winbond)
+               os=
+               basic_machine=$1
+               ;;
+       -scout)
+               ;;
+       -wrs)
+               os=-vxworks
+               basic_machine=$1
+               ;;
+       -chorusos*)
+               os=-chorusos
+               basic_machine=$1
+               ;;
+       -chorusrdb)
+               os=-chorusrdb
+               basic_machine=$1
+               ;;
+       -hiux*)
+               os=-hiuxwe2
+               ;;
+       -sco6)
+               os=-sco5v6
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco5)
+               os=-sco3.2v5
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco4)
+               os=-sco3.2v4
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2.[4-9]*)
+               os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2v[4-9]*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco5v6*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco*)
+               os=-sco3.2v2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -udk*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -isc)
+               os=-isc2.2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -clix*)
+               basic_machine=clipper-intergraph
+               ;;
+       -isc*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -lynx*)
+               os=-lynxos
+               ;;
+       -ptx*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+               ;;
+       -windowsnt*)
+               os=`echo $os | sed -e 's/windowsnt/winnt/'`
+               ;;
+       -psos*)
+               os=-psos
+               ;;
+       -mint | -mint[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+       # Recognize the basic CPU types without company name.
+       # Some are omitted here because they have special meanings below.
+       1750a | 580 \
+       | a29k \
+       | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+       | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+       | am33_2.0 \
+       | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+       | bfin \
+       | c4x | clipper \
+       | d10v | d30v | dlx | dsp16xx \
+       | fido | fr30 | frv \
+       | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+       | i370 | i860 | i960 | ia64 \
+       | ip2k | iq2000 \
+       | lm32 \
+       | m32c | m32r | m32rle | m68000 | m68k | m88k \
+       | maxq | mb | microblaze | mcore | mep | metag \
+       | mips | mipsbe | mipseb | mipsel | mipsle \
+       | mips16 \
+       | mips64 | mips64el \
+       | mips64octeon | mips64octeonel \
+       | mips64orion | mips64orionel \
+       | mips64r5900 | mips64r5900el \
+       | mips64vr | mips64vrel \
+       | mips64vr4100 | mips64vr4100el \
+       | mips64vr4300 | mips64vr4300el \
+       | mips64vr5000 | mips64vr5000el \
+       | mips64vr5900 | mips64vr5900el \
+       | mipsisa32 | mipsisa32el \
+       | mipsisa32r2 | mipsisa32r2el \
+       | mipsisa64 | mipsisa64el \
+       | mipsisa64r2 | mipsisa64r2el \
+       | mipsisa64sb1 | mipsisa64sb1el \
+       | mipsisa64sr71k | mipsisa64sr71kel \
+       | mipstx39 | mipstx39el \
+       | mn10200 | mn10300 \
+       | mt \
+       | msp430 \
+       | nios | nios2 \
+       | ns16k | ns32k \
+       | or32 \
+       | pdp10 | pdp11 | pj | pjl \
+       | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+       | pyramid \
+       | score \
+       | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+       | sh64 | sh64le \
+       | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+       | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+       | spu | strongarm \
+       | tahoe | thumb | tic4x | tic80 | tron \
+       | v850 | v850e \
+       | we32k \
+       | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+       | z8k | z80)
+               basic_machine=$basic_machine-unknown
+               ;;
+       m6811 | m68hc11 | m6812 | m68hc12)
+               # Motorola 68HC11/12.
+               basic_machine=$basic_machine-unknown
+               os=-none
+               ;;
+       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+               ;;
+       ms1)
+               basic_machine=mt-unknown
+               ;;
+
+       # We use `pc' rather than `unknown'
+       # because (1) that's what they normally are, and
+       # (2) the word "unknown" tends to confuse beginning users.
+       i*86 | x86_64)
+         basic_machine=$basic_machine-pc
+         ;;
+       # Object if more than one company name word.
+       *-*-*)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+       # Recognize the basic CPU types with company name.
+       580-* \
+       | a29k-* \
+       | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+       | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+       | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+       | arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+       | avr-* | avr32-* \
+       | bfin-* | bs2000-* \
+       | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+       | clipper-* | craynv-* | cydra-* \
+       | d10v-* | d30v-* | dlx-* \
+       | elxsi-* \
+       | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+       | h8300-* | h8500-* \
+       | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+       | i*86-* | i860-* | i960-* | ia64-* \
+       | ip2k-* | iq2000-* \
+       | lm32-* \
+       | m32c-* | m32r-* | m32rle-* \
+       | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+       | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+       | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+       | mips16-* \
+       | mips64-* | mips64el-* \
+       | mips64octeon-* | mips64octeonel-* \
+       | mips64orion-* | mips64orionel-* \
+       | mips64r5900-* | mips64r5900el-* \
+       | mips64vr-* | mips64vrel-* \
+       | mips64vr4100-* | mips64vr4100el-* \
+       | mips64vr4300-* | mips64vr4300el-* \
+       | mips64vr5000-* | mips64vr5000el-* \
+       | mips64vr5900-* | mips64vr5900el-* \
+       | mipsisa32-* | mipsisa32el-* \
+       | mipsisa32r2-* | mipsisa32r2el-* \
+       | mipsisa64-* | mipsisa64el-* \
+       | mipsisa64r2-* | mipsisa64r2el-* \
+       | mipsisa64sb1-* | mipsisa64sb1el-* \
+       | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+       | mipstx39-* | mipstx39el-* \
+       | mmix-* \
+       | mt-* \
+       | msp430-* \
+       | nios-* | nios2-* \
+       | none-* | np1-* | ns16k-* | ns32k-* \
+       | orion-* \
+       | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+       | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+       | pyramid-* \
+       | romp-* | rs6000-* \
+       | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+       | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+       | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+       | sparclite-* \
+       | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+       | tahoe-* | thumb-* \
+       | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
+       | tron-* \
+       | v850-* | v850e-* | vax-* \
+       | we32k-* \
+       | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+       | xstormy16-* | xtensa*-* \
+       | ymp-* \
+       | z8k-* | z80-*)
+               ;;
+       # Recognize the basic CPU types without company name, with glob match.
+       xtensa*)
+               basic_machine=$basic_machine-unknown
+               ;;
+       # Recognize the various machine names and aliases which stand
+       # for a CPU type and a company and sometimes even an OS.
+       386bsd)
+               basic_machine=i386-unknown
+               os=-bsd
+               ;;
+       3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+               basic_machine=m68000-att
+               ;;
+       3b*)
+               basic_machine=we32k-att
+               ;;
+       a29khif)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       abacus)
+               basic_machine=abacus-unknown
+               ;;
+       adobe68k)
+               basic_machine=m68010-adobe
+               os=-scout
+               ;;
+       alliant | fx80)
+               basic_machine=fx80-alliant
+               ;;
+       altos | altos3068)
+               basic_machine=m68k-altos
+               ;;
+       am29k)
+               basic_machine=a29k-none
+               os=-bsd
+               ;;
+       amd64)
+               basic_machine=x86_64-pc
+               ;;
+       amd64-*)
+               basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       amdahl)
+               basic_machine=580-amdahl
+               os=-sysv
+               ;;
+       amiga | amiga-*)
+               basic_machine=m68k-unknown
+               ;;
+       amigaos | amigados)
+               basic_machine=m68k-unknown
+               os=-amigaos
+               ;;
+       amigaunix | amix)
+               basic_machine=m68k-unknown
+               os=-sysv4
+               ;;
+       apollo68)
+               basic_machine=m68k-apollo
+               os=-sysv
+               ;;
+       apollo68bsd)
+               basic_machine=m68k-apollo
+               os=-bsd
+               ;;
+       aux)
+               basic_machine=m68k-apple
+               os=-aux
+               ;;
+       balance)
+               basic_machine=ns32k-sequent
+               os=-dynix
+               ;;
+       blackfin)
+               basic_machine=bfin-unknown
+               os=-linux
+               ;;
+       blackfin-*)
+               basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       c90)
+               basic_machine=c90-cray
+               os=-unicos
+               ;;
+        cegcc)
+               basic_machine=arm-unknown
+               os=-cegcc
+               ;;
+       convex-c1)
+               basic_machine=c1-convex
+               os=-bsd
+               ;;
+       convex-c2)
+               basic_machine=c2-convex
+               os=-bsd
+               ;;
+       convex-c32)
+               basic_machine=c32-convex
+               os=-bsd
+               ;;
+       convex-c34)
+               basic_machine=c34-convex
+               os=-bsd
+               ;;
+       convex-c38)
+               basic_machine=c38-convex
+               os=-bsd
+               ;;
+       cray | j90)
+               basic_machine=j90-cray
+               os=-unicos
+               ;;
+       craynv)
+               basic_machine=craynv-cray
+               os=-unicosmp
+               ;;
+       cr16)
+               basic_machine=cr16-unknown
+               os=-elf
+               ;;
+       crds | unos)
+               basic_machine=m68k-crds
+               ;;
+       crisv32 | crisv32-* | etraxfs*)
+               basic_machine=crisv32-axis
+               ;;
+       cris | cris-* | etrax*)
+               basic_machine=cris-axis
+               ;;
+       crx)
+               basic_machine=crx-unknown
+               os=-elf
+               ;;
+       da30 | da30-*)
+               basic_machine=m68k-da30
+               ;;
+       decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+               basic_machine=mips-dec
+               ;;
+       decsystem10* | dec10*)
+               basic_machine=pdp10-dec
+               os=-tops10
+               ;;
+       decsystem20* | dec20*)
+               basic_machine=pdp10-dec
+               os=-tops20
+               ;;
+       delta | 3300 | motorola-3300 | motorola-delta \
+             | 3300-motorola | delta-motorola)
+               basic_machine=m68k-motorola
+               ;;
+       delta88)
+               basic_machine=m88k-motorola
+               os=-sysv3
+               ;;
+       dicos)
+               basic_machine=i686-pc
+               os=-dicos
+               ;;
+       djgpp)
+               basic_machine=i586-pc
+               os=-msdosdjgpp
+               ;;
+       dpx20 | dpx20-*)
+               basic_machine=rs6000-bull
+               os=-bosx
+               ;;
+       dpx2* | dpx2*-bull)
+               basic_machine=m68k-bull
+               os=-sysv3
+               ;;
+       ebmon29k)
+               basic_machine=a29k-amd
+               os=-ebmon
+               ;;
+       elxsi)
+               basic_machine=elxsi-elxsi
+               os=-bsd
+               ;;
+       encore | umax | mmax)
+               basic_machine=ns32k-encore
+               ;;
+       es1800 | OSE68k | ose68k | ose | OSE)
+               basic_machine=m68k-ericsson
+               os=-ose
+               ;;
+       fx2800)
+               basic_machine=i860-alliant
+               ;;
+       genix)
+               basic_machine=ns32k-ns
+               ;;
+       gmicro)
+               basic_machine=tron-gmicro
+               os=-sysv
+               ;;
+       go32)
+               basic_machine=i386-pc
+               os=-go32
+               ;;
+       h3050r* | hiux*)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       h8300hms)
+               basic_machine=h8300-hitachi
+               os=-hms
+               ;;
+       h8300xray)
+               basic_machine=h8300-hitachi
+               os=-xray
+               ;;
+       h8500hms)
+               basic_machine=h8500-hitachi
+               os=-hms
+               ;;
+       harris)
+               basic_machine=m88k-harris
+               os=-sysv3
+               ;;
+       hp300-*)
+               basic_machine=m68k-hp
+               ;;
+       hp300bsd)
+               basic_machine=m68k-hp
+               os=-bsd
+               ;;
+       hp300hpux)
+               basic_machine=m68k-hp
+               os=-hpux
+               ;;
+       hp3k9[0-9][0-9] | hp9[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k2[0-9][0-9] | hp9k31[0-9])
+               basic_machine=m68000-hp
+               ;;
+       hp9k3[2-9][0-9])
+               basic_machine=m68k-hp
+               ;;
+       hp9k6[0-9][0-9] | hp6[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k7[0-79][0-9] | hp7[0-79][0-9])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k78[0-9] | hp78[0-9])
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][13679] | hp8[0-9][13679])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][0-9] | hp8[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hppa-next)
+               os=-nextstep3
+               ;;
+       hppaosf)
+               basic_machine=hppa1.1-hp
+               os=-osf
+               ;;
+       hppro)
+               basic_machine=hppa1.1-hp
+               os=-proelf
+               ;;
+       i370-ibm* | ibm*)
+               basic_machine=i370-ibm
+               ;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+       i*86v32)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv32
+               ;;
+       i*86v4*)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv4
+               ;;
+       i*86v)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv
+               ;;
+       i*86sol2)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-solaris2
+               ;;
+       i386mach)
+               basic_machine=i386-mach
+               os=-mach
+               ;;
+       i386-vsta | vsta)
+               basic_machine=i386-unknown
+               os=-vsta
+               ;;
+       iris | iris4d)
+               basic_machine=mips-sgi
+               case $os in
+                   -irix*)
+                       ;;
+                   *)
+                       os=-irix4
+                       ;;
+               esac
+               ;;
+       isi68 | isi)
+               basic_machine=m68k-isi
+               os=-sysv
+               ;;
+       m68knommu)
+               basic_machine=m68k-unknown
+               os=-linux
+               ;;
+       m68knommu-*)
+               basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       m88k-omron*)
+               basic_machine=m88k-omron
+               ;;
+       magnum | m3230)
+               basic_machine=mips-mips
+               os=-sysv
+               ;;
+       merlin)
+               basic_machine=ns32k-utek
+               os=-sysv
+               ;;
+       mingw32)
+               basic_machine=i386-pc
+               os=-mingw32
+               ;;
+       mingw32ce)
+               basic_machine=arm-unknown
+               os=-mingw32ce
+               ;;
+       miniframe)
+               basic_machine=m68000-convergent
+               ;;
+       *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+       mips3*-*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+               ;;
+       mips3*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+               ;;
+       monitor)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       morphos)
+               basic_machine=powerpc-unknown
+               os=-morphos
+               ;;
+       msdos)
+               basic_machine=i386-pc
+               os=-msdos
+               ;;
+       ms1-*)
+               basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+               ;;
+       mvs)
+               basic_machine=i370-ibm
+               os=-mvs
+               ;;
+       ncr3000)
+               basic_machine=i486-ncr
+               os=-sysv4
+               ;;
+       netbsd386)
+               basic_machine=i386-unknown
+               os=-netbsd
+               ;;
+       netwinder)
+               basic_machine=armv4l-rebel
+               os=-linux
+               ;;
+       news | news700 | news800 | news900)
+               basic_machine=m68k-sony
+               os=-newsos
+               ;;
+       news1000)
+               basic_machine=m68030-sony
+               os=-newsos
+               ;;
+       news-3600 | risc-news)
+               basic_machine=mips-sony
+               os=-newsos
+               ;;
+       necv70)
+               basic_machine=v70-nec
+               os=-sysv
+               ;;
+       next | m*-next )
+               basic_machine=m68k-next
+               case $os in
+                   -nextstep* )
+                       ;;
+                   -ns2*)
+                     os=-nextstep2
+                       ;;
+                   *)
+                     os=-nextstep3
+                       ;;
+               esac
+               ;;
+       nh3000)
+               basic_machine=m68k-harris
+               os=-cxux
+               ;;
+       nh[45]000)
+               basic_machine=m88k-harris
+               os=-cxux
+               ;;
+       nindy960)
+               basic_machine=i960-intel
+               os=-nindy
+               ;;
+       mon960)
+               basic_machine=i960-intel
+               os=-mon960
+               ;;
+       nonstopux)
+               basic_machine=mips-compaq
+               os=-nonstopux
+               ;;
+       np1)
+               basic_machine=np1-gould
+               ;;
+       nsr-tandem)
+               basic_machine=nsr-tandem
+               ;;
+       op50n-* | op60c-*)
+               basic_machine=hppa1.1-oki
+               os=-proelf
+               ;;
+       openrisc | openrisc-*)
+               basic_machine=or32-unknown
+               ;;
+       os400)
+               basic_machine=powerpc-ibm
+               os=-os400
+               ;;
+       OSE68000 | ose68000)
+               basic_machine=m68000-ericsson
+               os=-ose
+               ;;
+       os68k)
+               basic_machine=m68k-none
+               os=-os68k
+               ;;
+       pa-hitachi)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       paragon)
+               basic_machine=i860-intel
+               os=-osf
+               ;;
+       parisc)
+               basic_machine=hppa-unknown
+               os=-linux
+               ;;
+       parisc-*)
+               basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       pbd)
+               basic_machine=sparc-tti
+               ;;
+       pbb)
+               basic_machine=m68k-tti
+               ;;
+       pc532 | pc532-*)
+               basic_machine=ns32k-pc532
+               ;;
+       pc98)
+               basic_machine=i386-pc
+               ;;
+       pc98-*)
+               basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium | p5 | k5 | k6 | nexgen | viac3)
+               basic_machine=i586-pc
+               ;;
+       pentiumpro | p6 | 6x86 | athlon | athlon_*)
+               basic_machine=i686-pc
+               ;;
+       pentiumii | pentium2 | pentiumiii | pentium3)
+               basic_machine=i686-pc
+               ;;
+       pentium4)
+               basic_machine=i786-pc
+               ;;
+       pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+               basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumpro-* | p6-* | 6x86-* | athlon-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium4-*)
+               basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pn)
+               basic_machine=pn-gould
+               ;;
+       power)  basic_machine=power-ibm
+               ;;
+       ppc)    basic_machine=powerpc-unknown
+               ;;
+       ppc-*)  basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppcle | powerpclittle | ppc-le | powerpc-little)
+               basic_machine=powerpcle-unknown
+               ;;
+       ppcle-* | powerpclittle-*)
+               basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64)  basic_machine=powerpc64-unknown
+               ;;
+       ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+               basic_machine=powerpc64le-unknown
+               ;;
+       ppc64le-* | powerpc64little-*)
+               basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ps2)
+               basic_machine=i386-ibm
+               ;;
+       pw32)
+               basic_machine=i586-unknown
+               os=-pw32
+               ;;
+       rdos)
+               basic_machine=i386-pc
+               os=-rdos
+               ;;
+       rom68k)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       rm[46]00)
+               basic_machine=mips-siemens
+               ;;
+       rtpc | rtpc-*)
+               basic_machine=romp-ibm
+               ;;
+       s390 | s390-*)
+               basic_machine=s390-ibm
+               ;;
+       s390x | s390x-*)
+               basic_machine=s390x-ibm
+               ;;
+       sa29200)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       sb1)
+               basic_machine=mipsisa64sb1-unknown
+               ;;
+       sb1el)
+               basic_machine=mipsisa64sb1el-unknown
+               ;;
+       sde)
+               basic_machine=mipsisa32-sde
+               os=-elf
+               ;;
+       sei)
+               basic_machine=mips-sei
+               os=-seiux
+               ;;
+       sequent)
+               basic_machine=i386-sequent
+               ;;
+       sh)
+               basic_machine=sh-hitachi
+               os=-hms
+               ;;
+       sh5el)
+               basic_machine=sh5le-unknown
+               ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
+       sparclite-wrs | simso-wrs)
+               basic_machine=sparclite-wrs
+               os=-vxworks
+               ;;
+       sps7)
+               basic_machine=m68k-bull
+               os=-sysv2
+               ;;
+       spur)
+               basic_machine=spur-unknown
+               ;;
+       st2000)
+               basic_machine=m68k-tandem
+               ;;
+       stratus)
+               basic_machine=i860-stratus
+               os=-sysv4
+               ;;
+       sun2)
+               basic_machine=m68000-sun
+               ;;
+       sun2os3)
+               basic_machine=m68000-sun
+               os=-sunos3
+               ;;
+       sun2os4)
+               basic_machine=m68000-sun
+               os=-sunos4
+               ;;
+       sun3os3)
+               basic_machine=m68k-sun
+               os=-sunos3
+               ;;
+       sun3os4)
+               basic_machine=m68k-sun
+               os=-sunos4
+               ;;
+       sun4os3)
+               basic_machine=sparc-sun
+               os=-sunos3
+               ;;
+       sun4os4)
+               basic_machine=sparc-sun
+               os=-sunos4
+               ;;
+       sun4sol2)
+               basic_machine=sparc-sun
+               os=-solaris2
+               ;;
+       sun3 | sun3-*)
+               basic_machine=m68k-sun
+               ;;
+       sun4)
+               basic_machine=sparc-sun
+               ;;
+       sun386 | sun386i | roadrunner)
+               basic_machine=i386-sun
+               ;;
+       sv1)
+               basic_machine=sv1-cray
+               os=-unicos
+               ;;
+       symmetry)
+               basic_machine=i386-sequent
+               os=-dynix
+               ;;
+       t3e)
+               basic_machine=alphaev5-cray
+               os=-unicos
+               ;;
+       t90)
+               basic_machine=t90-cray
+               os=-unicos
+               ;;
+       tic54x | c54x*)
+               basic_machine=tic54x-unknown
+               os=-coff
+               ;;
+       tic55x | c55x*)
+               basic_machine=tic55x-unknown
+               os=-coff
+               ;;
+       tic6x | c6x*)
+               basic_machine=tic6x-unknown
+               os=-coff
+               ;;
+       tile*)
+               basic_machine=tile-unknown
+               os=-linux-gnu
+               ;;
+       tx39)
+               basic_machine=mipstx39-unknown
+               ;;
+       tx39el)
+               basic_machine=mipstx39el-unknown
+               ;;
+       toad1)
+               basic_machine=pdp10-xkl
+               os=-tops20
+               ;;
+       tower | tower-32)
+               basic_machine=m68k-ncr
+               ;;
+       tpf)
+               basic_machine=s390x-ibm
+               os=-tpf
+               ;;
+       udi29k)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       ultra3)
+               basic_machine=a29k-nyu
+               os=-sym1
+               ;;
+       v810 | necv810)
+               basic_machine=v810-nec
+               os=-none
+               ;;
+       vaxv)
+               basic_machine=vax-dec
+               os=-sysv
+               ;;
+       vms)
+               basic_machine=vax-dec
+               os=-vms
+               ;;
+       vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+       vxworks960)
+               basic_machine=i960-wrs
+               os=-vxworks
+               ;;
+       vxworks68)
+               basic_machine=m68k-wrs
+               os=-vxworks
+               ;;
+       vxworks29k)
+               basic_machine=a29k-wrs
+               os=-vxworks
+               ;;
+       w65*)
+               basic_machine=w65-wdc
+               os=-none
+               ;;
+       w89k-*)
+               basic_machine=hppa1.1-winbond
+               os=-proelf
+               ;;
+       xbox)
+               basic_machine=i686-pc
+               os=-mingw32
+               ;;
+       xps | xps100)
+               basic_machine=xps100-honeywell
+               ;;
+       ymp)
+               basic_machine=ymp-cray
+               os=-unicos
+               ;;
+       z8k-*-coff)
+               basic_machine=z8k-unknown
+               os=-sim
+               ;;
+       z80-*-coff)
+               basic_machine=z80-unknown
+               os=-sim
+               ;;
+       none)
+               basic_machine=none-none
+               os=-none
+               ;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+       w89k)
+               basic_machine=hppa1.1-winbond
+               ;;
+       op50n)
+               basic_machine=hppa1.1-oki
+               ;;
+       op60c)
+               basic_machine=hppa1.1-oki
+               ;;
+       romp)
+               basic_machine=romp-ibm
+               ;;
+       mmix)
+               basic_machine=mmix-knuth
+               ;;
+       rs6000)
+               basic_machine=rs6000-ibm
+               ;;
+       vax)
+               basic_machine=vax-dec
+               ;;
+       pdp10)
+               # there are many clones, so DEC is not a safe bet
+               basic_machine=pdp10-unknown
+               ;;
+       pdp11)
+               basic_machine=pdp11-dec
+               ;;
+       we32k)
+               basic_machine=we32k-att
+               ;;
+       sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+               basic_machine=sh-unknown
+               ;;
+       sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+               basic_machine=sparc-sun
+               ;;
+       cydra)
+               basic_machine=cydra-cydrome
+               ;;
+       orion)
+               basic_machine=orion-highlevel
+               ;;
+       orion105)
+               basic_machine=clipper-highlevel
+               ;;
+       mac | mpw | mac-mpw)
+               basic_machine=m68k-apple
+               ;;
+       pmac | pmac-mpw)
+               basic_machine=powerpc-apple
+               ;;
+       *-unknown)
+               # Make sure to match an already-canonicalized machine name.
+               ;;
+       *)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+       *-digital*)
+               basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+               ;;
+       *-commodore*)
+               basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+               ;;
+       *)
+               ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+       # -solaris* is a basic system type, with this one exception.
+       -solaris1 | -solaris1.*)
+               os=`echo $os | sed -e 's|solaris1|sunos4|'`
+               ;;
+       -solaris)
+               os=-solaris2
+               ;;
+       -svr4*)
+               os=-sysv4
+               ;;
+       -unixware*)
+               os=-sysv4.2uw
+               ;;
+       -gnu/linux*)
+               os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+               ;;
+       # First accept the basic system types.
+       # The portable systems comes first.
+       # Each alternative MUST END IN A *, to match a version number.
+       # -sysv* is not here because it comes later, after sysvr4.
+       -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+             | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+             | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+             | -kopensolaris* \
+             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+             | -aos* \
+             | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+             | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+             | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+             | -openbsd* | -solidbsd* \
+             | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+             | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+             | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+             | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+             | -chorusos* | -chorusrdb* | -cegcc* \
+             | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+             | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+             | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+             | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+             | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+             | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+             | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+             | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+             | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+       # Remember, each alternative MUST END IN *, to match a version number.
+               ;;
+       -qnx*)
+               case $basic_machine in
+                   x86-* | i*86-*)
+                       ;;
+                   *)
+                       os=-nto$os
+                       ;;
+               esac
+               ;;
+       -nto-qnx*)
+               ;;
+       -nto*)
+               os=`echo $os | sed -e 's|nto|nto-qnx|'`
+               ;;
+       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+             | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+             | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+               ;;
+       -mac*)
+               os=`echo $os | sed -e 's|mac|macos|'`
+               ;;
+       -linux-dietlibc)
+               os=-linux-dietlibc
+               ;;
+       -linux*)
+               os=`echo $os | sed -e 's|linux|linux-gnu|'`
+               ;;
+       -sunos5*)
+               os=`echo $os | sed -e 's|sunos5|solaris2|'`
+               ;;
+       -sunos6*)
+               os=`echo $os | sed -e 's|sunos6|solaris3|'`
+               ;;
+       -opened*)
+               os=-openedition
+               ;;
+        -os400*)
+               os=-os400
+               ;;
+       -wince*)
+               os=-wince
+               ;;
+       -osfrose*)
+               os=-osfrose
+               ;;
+       -osf*)
+               os=-osf
+               ;;
+       -utek*)
+               os=-bsd
+               ;;
+       -dynix*)
+               os=-bsd
+               ;;
+       -acis*)
+               os=-aos
+               ;;
+       -atheos*)
+               os=-atheos
+               ;;
+       -syllable*)
+               os=-syllable
+               ;;
+       -386bsd)
+               os=-bsd
+               ;;
+       -ctix* | -uts*)
+               os=-sysv
+               ;;
+       -nova*)
+               os=-rtmk-nova
+               ;;
+       -ns2 )
+               os=-nextstep2
+               ;;
+       -nsk*)
+               os=-nsk
+               ;;
+       # Preserve the version number of sinix5.
+       -sinix5.*)
+               os=`echo $os | sed -e 's|sinix|sysv|'`
+               ;;
+       -sinix*)
+               os=-sysv4
+               ;;
+        -tpf*)
+               os=-tpf
+               ;;
+       -triton*)
+               os=-sysv3
+               ;;
+       -oss*)
+               os=-sysv3
+               ;;
+       -svr4)
+               os=-sysv4
+               ;;
+       -svr3)
+               os=-sysv3
+               ;;
+       -sysvr4)
+               os=-sysv4
+               ;;
+       # This must come after -sysvr4.
+       -sysv*)
+               ;;
+       -ose*)
+               os=-ose
+               ;;
+       -es1800*)
+               os=-ose
+               ;;
+       -xenix)
+               os=-xenix
+               ;;
+       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+               os=-mint
+               ;;
+       -aros*)
+               os=-aros
+               ;;
+       -kaos*)
+               os=-kaos
+               ;;
+       -zvmoe)
+               os=-zvmoe
+               ;;
+       -dicos*)
+               os=-dicos
+               ;;
+       -none)
+               ;;
+       *)
+               # Get rid of the `-' at the beginning of $os.
+               os=`echo $os | sed 's/[^-]*-//'`
+               echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+        score-*)
+               os=-elf
+               ;;
+        spu-*)
+               os=-elf
+               ;;
+       *-acorn)
+               os=-riscix1.2
+               ;;
+       arm*-rebel)
+               os=-linux
+               ;;
+       arm*-semi)
+               os=-aout
+               ;;
+        c4x-* | tic4x-*)
+               os=-coff
+               ;;
+       # This must come before the *-dec entry.
+       pdp10-*)
+               os=-tops20
+               ;;
+       pdp11-*)
+               os=-none
+               ;;
+       *-dec | vax-*)
+               os=-ultrix4.2
+               ;;
+       m68*-apollo)
+               os=-domain
+               ;;
+       i386-sun)
+               os=-sunos4.0.2
+               ;;
+       m68000-sun)
+               os=-sunos3
+               # This also exists in the configure program, but was not the
+               # default.
+               # os=-sunos4
+               ;;
+       m68*-cisco)
+               os=-aout
+               ;;
+        mep-*)
+               os=-elf
+               ;;
+       mips*-cisco)
+               os=-elf
+               ;;
+       mips*-*)
+               os=-elf
+               ;;
+       or32-*)
+               os=-coff
+               ;;
+       *-tti)  # must be before sparc entry or we get the wrong os.
+               os=-sysv3
+               ;;
+       sparc-* | *-sun)
+               os=-sunos4.1.1
+               ;;
+       *-be)
+               os=-beos
+               ;;
+       *-haiku)
+               os=-haiku
+               ;;
+       *-ibm)
+               os=-aix
+               ;;
+       *-knuth)
+               os=-mmixware
+               ;;
+       *-wec)
+               os=-proelf
+               ;;
+       *-winbond)
+               os=-proelf
+               ;;
+       *-oki)
+               os=-proelf
+               ;;
+       *-hp)
+               os=-hpux
+               ;;
+       *-hitachi)
+               os=-hiux
+               ;;
+       i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+               os=-sysv
+               ;;
+       *-cbm)
+               os=-amigaos
+               ;;
+       *-dg)
+               os=-dgux
+               ;;
+       *-dolphin)
+               os=-sysv3
+               ;;
+       m68k-ccur)
+               os=-rtu
+               ;;
+       m88k-omron*)
+               os=-luna
+               ;;
+       *-next )
+               os=-nextstep
+               ;;
+       *-sequent)
+               os=-ptx
+               ;;
+       *-crds)
+               os=-unos
+               ;;
+       *-ns)
+               os=-genix
+               ;;
+       i370-*)
+               os=-mvs
+               ;;
+       *-next)
+               os=-nextstep3
+               ;;
+       *-gould)
+               os=-sysv
+               ;;
+       *-highlevel)
+               os=-bsd
+               ;;
+       *-encore)
+               os=-bsd
+               ;;
+       *-sgi)
+               os=-irix
+               ;;
+       *-siemens)
+               os=-sysv4
+               ;;
+       *-masscomp)
+               os=-rtu
+               ;;
+       f30[01]-fujitsu | f700-fujitsu)
+               os=-uxpv
+               ;;
+       *-rom68k)
+               os=-coff
+               ;;
+       *-*bug)
+               os=-coff
+               ;;
+       *-apple)
+               os=-macos
+               ;;
+       *-atari*)
+               os=-mint
+               ;;
+       *)
+               os=-none
+               ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+       *-unknown)
+               case $os in
+                       -riscix*)
+                               vendor=acorn
+                               ;;
+                       -sunos*)
+                               vendor=sun
+                               ;;
+                       -aix*)
+                               vendor=ibm
+                               ;;
+                       -beos*)
+                               vendor=be
+                               ;;
+                       -hpux*)
+                               vendor=hp
+                               ;;
+                       -mpeix*)
+                               vendor=hp
+                               ;;
+                       -hiux*)
+                               vendor=hitachi
+                               ;;
+                       -unos*)
+                               vendor=crds
+                               ;;
+                       -dgux*)
+                               vendor=dg
+                               ;;
+                       -luna*)
+                               vendor=omron
+                               ;;
+                       -genix*)
+                               vendor=ns
+                               ;;
+                       -mvs* | -opened*)
+                               vendor=ibm
+                               ;;
+                       -os400*)
+                               vendor=ibm
+                               ;;
+                       -ptx*)
+                               vendor=sequent
+                               ;;
+                       -tpf*)
+                               vendor=ibm
+                               ;;
+                       -vxsim* | -vxworks* | -windiss*)
+                               vendor=wrs
+                               ;;
+                       -aux*)
+                               vendor=apple
+                               ;;
+                       -hms*)
+                               vendor=hitachi
+                               ;;
+                       -mpw* | -macos*)
+                               vendor=apple
+                               ;;
+                       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+                               vendor=atari
+                               ;;
+                       -vos*)
+                               vendor=stratus
+                               ;;
+               esac
+               basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+               ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..c82ee24
--- /dev/null
+++ b/configure
@@ -0,0 +1,9915 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61 for GRUB 1.96.
+#
+# Report bugs to <bug-grub@gnu.org>.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+  if (eval ":") 2>/dev/null; then
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+
+  if test $as_have_required = yes &&    (eval ":
+(as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=\$LINENO
+  as_lineno_2=\$LINENO
+  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+  :
+else
+  as_candidate_shells=
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  case $as_dir in
+        /*)
+          for as_base in sh bash ksh sh5; do
+            as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+          done;;
+       esac
+done
+IFS=$as_save_IFS
+
+
+      for as_shell in $as_candidate_shells $SHELL; do
+        # Try only shells that exist, to save several forks.
+        if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+               { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+  CONFIG_SHELL=$as_shell
+              as_have_required=yes
+              if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+  (exit $1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+  break
+fi
+
+fi
+
+      done
+
+      if test "x$CONFIG_SHELL" != x; then
+  for as_var in BASH_ENV ENV
+        do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+        done
+        export CONFIG_SHELL
+        exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+    if test $as_have_required = no; then
+  echo This script requires a shell more modern than all the
+      echo shells that I found on your system.  Please install a
+      echo modern shell, or manually run the script under such a
+      echo shell if you do have one.
+      { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+  echo No shell found that supports shell functions.
+  echo Please tell autoconf@gnu.org about your system,
+  echo including any error possibly output before this
+  echo message
+}
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s='ln -s'
+  # ... but there are two gotchas:
+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+  # In both cases, we have to default to `cp -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+    as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+        test -d "$1/.";
+      else
+       case $1 in
+        -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='GRUB'
+PACKAGE_TARNAME='grub'
+PACKAGE_VERSION='1.96'
+PACKAGE_STRING='GRUB 1.96'
+PACKAGE_BUGREPORT='bug-grub@gnu.org'
+
+ac_unique_file="include/grub/dl.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+build
+build_cpu
+build_vendor
+build_os
+host
+host_cpu
+host_vendor
+host_os
+target
+target_cpu
+target_vendor
+target_os
+platform
+CMP
+YACC
+UNIFONT_BDF
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+AWK
+SET_MAKE
+RUBY
+HELP2MAN
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+CPP
+GREP
+EGREP
+LIBLZO
+enable_lzo
+TARGET_IMG_LDSCRIPT
+TARGET_IMG_LDFLAGS
+TARGET_OBJ2ELF
+TARGET_CC
+ac_ct_TARGET_CC
+OBJCOPY
+STRIP
+NM
+TARGET_CFLAGS
+TARGET_CPPFLAGS
+TARGET_LDFLAGS
+MODULE_LDFLAGS
+LIBCURSES
+LIBUSB
+enable_grub_emu
+enable_grub_emu_usb
+enable_grub_fstest
+enable_grub_pe2elf
+FREETYPE
+enable_grub_mkfont
+freetype_cflags
+freetype_libs
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files=''
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)   ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+    eval enable_$ac_feature=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+    eval enable_$ac_feature=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+    eval with_$ac_package=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+    eval with_$ac_package=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
+               datadir sysconfdir sharedstatedir localstatedir includedir \
+               oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+               libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  { echo "$as_me: error: Working directory cannot be determined" >&2
+   { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  { echo "$as_me: error: pwd does not report name of working directory" >&2
+   { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$0" : 'X\(//\)[^/]' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+       cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+   { (exit 1); exit 1; }; }
+       pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures GRUB 1.96 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                         [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                         [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --datarootdir=DIR      read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR          read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR          info documentation [DATAROOTDIR/info]
+  --localedir=DIR        locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR           man documentation [DATAROOTDIR/man]
+  --docdir=DIR           documentation root [DATAROOTDIR/doc/grub]
+  --htmldir=DIR          html documentation [DOCDIR]
+  --dvidir=DIR           dvi documentation [DOCDIR]
+  --pdfdir=DIR           pdf documentation [DOCDIR]
+  --psdir=DIR            ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+  --target=TARGET   configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of GRUB 1.96:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-largefile     omit support for large files
+  --enable-lzo            use lzo to compress kernel (default is lzma)
+  --enable-mm-debug       include memory manager debugging
+  --enable-grub-emu       build and install the `grub-emu' debugging utility
+  --enable-grub-emu-usb   build and install the `grub-emu' debugging utility
+                          with USB support
+  --enable-grub-fstest    build and install the `grub-fstest' debugging
+                          utility
+  --enable-grub-pe2elf    build and install the `grub-pe2elf' conversion
+                          utility
+  --enable-grub-mkfont    build and install the `grub-mkfont' utility
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-platform=PLATFORM
+                          select the host platform [guessed]
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <bug-grub@gnu.org>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" || continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+GRUB configure 1.96
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by GRUB $as_me 1.96, which was
+generated by GNU Autoconf 2.61.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+       ac_must_keep_next=false # Got value, back to normal.
+      else
+       case $ac_arg in
+         *=* | --config-cache | -C | -disable-* | --disable-* \
+         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+         | -with-* | --with-* | -without-* | --without-* | --x)
+           case "$ac_configure_args0 " in
+             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+           esac
+           ;;
+         -* ) ac_must_keep_next=true ;;
+       esac
+      fi
+      ac_configure_args="$ac_configure_args '$ac_arg'"
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+       "s/'\''/'\''\\\\'\'''\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+       eval ac_val=\$$ac_var
+       case $ac_val in
+       *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+       esac
+       echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+  set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+  set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+  set x "$ac_default_prefix/share/config.site" \
+       "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+       { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+       { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+       { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+       ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+# Checks for host and target systems.
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+if test "${ac_cv_host+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+echo "$as_me: error: invalid value of canonical host" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking target system type" >&5
+echo $ECHO_N "checking target system type... $ECHO_C" >&6; }
+if test "${ac_cv_target+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "x$target_alias" = x; then
+  ac_cv_target=$ac_cv_host
+else
+  ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+    { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5
+echo "${ECHO_T}$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5
+echo "$as_me: error: invalid value of canonical target" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+# Program name transformations
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.  echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm -f conftest.sed
+
+
+case "$host_cpu" in
+  powerpc64) host_m32=1 ;;
+esac
+
+case "$target_cpu" in
+  i[3456]86) target_cpu=i386 ;;
+esac
+
+# Specify the platform (such as firmware).
+
+# Check whether --with-platform was given.
+if test "${with_platform+set}" = set; then
+  withval=$with_platform;
+fi
+
+
+# Guess the platform if not specified.
+if test "x$with_platform" = x; then
+  case "$target_cpu"-"$target_vendor" in
+    i386-apple) platform=efi ;;
+    i386-*) platform=pc ;;
+    x86_64-apple) platform=efi ;;
+    x86_64-*) platform=pc ;;
+    powerpc-*) platform=ieee1275 ;;
+    powerpc64-*) platform=ieee1275 ;;
+    sparc64-*) platform=ieee1275 ;;
+    *) { { echo "$as_me:$LINENO: error: unsupported CPU: \"$target_cpu\"" >&5
+echo "$as_me: error: unsupported CPU: \"$target_cpu\"" >&2;}
+   { (exit 1); exit 1; }; } ;;
+  esac
+else
+  platform="$with_platform"
+fi
+
+# Adjust CPU unless target was explicitly specified.
+if test -z "$target_alias"; then
+  case "$target_cpu"-"$platform" in
+    x86_64-efi) ;;
+    x86_64-*) target_cpu=i386 ;;
+    powerpc64-ieee1275) target_cpu=powerpc ;;
+  esac
+fi
+
+# Check if the platform is supported, make final adjustments.
+case "$target_cpu"-"$platform" in
+  i386-efi) ;;
+  x86_64-efi) ;;
+  i386-pc) ;;
+  i386-coreboot) ;;
+  i386-linuxbios) platform=coreboot ;;
+  i386-ieee1275) ;;
+  powerpc-ieee1275) ;;
+  sparc64-ieee1275) ;;
+  *) { { echo "$as_me:$LINENO: error: platform \"$platform\" is not supported for target CPU \"$target_cpu\"" >&5
+echo "$as_me: error: platform \"$platform\" is not supported for target CPU \"$target_cpu\"" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+
+case "$target_cpu" in
+  i386 | powerpc) target_m32=1 ;;
+  x86_64 | sparc64) target_m64=1 ;;
+esac
+
+case "$host_os" in
+  mingw32) host_os=cygwin ;;
+esac
+
+
+
+
+
+
+
+#
+# Checks for build programs.
+#
+
+# Although cmp is listed in the GNU Coding Standards as a command which
+# can used directly, OpenBSD lacks cmp in the default installation.
+for ac_prog in cmp
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CMP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CMP"; then
+  ac_cv_prog_CMP="$CMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CMP="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CMP=$ac_cv_prog_CMP
+if test -n "$CMP"; then
+  { echo "$as_me:$LINENO: result: $CMP" >&5
+echo "${ECHO_T}$CMP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$CMP" && break
+done
+
+if test "x$CMP" = x; then
+  { { echo "$as_me:$LINENO: error: cmp is not found" >&5
+echo "$as_me: error: cmp is not found" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+for ac_prog in bison
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_YACC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_YACC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+  { echo "$as_me:$LINENO: result: $YACC" >&5
+echo "${ECHO_T}$YACC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$YACC" && break
+done
+
+if test "x$YACC" = x; then
+  { { echo "$as_me:$LINENO: error: bison is not found" >&5
+echo "$as_me: error: bison is not found" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+for file in /usr/src/unifont.bdf ; do
+  if test -e $file ; then
+    UNIFONT_BDF=$file
+
+    break
+  fi
+done
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+       if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+         if test $ac_prog = install &&
+           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         elif test $ac_prog = install &&
+           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # program-specific install script used by HP pwplus--don't use.
+           :
+         else
+           ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+           break 3
+         fi
+       fi
+      done
+    done
+    ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; }
+set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+       @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+  SET_MAKE=
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+# These are not a "must".
+# Extract the first word of "ruby", so it can be a program name with args.
+set dummy ruby; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_RUBY+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $RUBY in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_RUBY="$RUBY" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_RUBY="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+RUBY=$ac_cv_path_RUBY
+if test -n "$RUBY"; then
+  { echo "$as_me:$LINENO: result: $RUBY" >&5
+echo "${ECHO_T}$RUBY" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+# Extract the first word of "help2man", so it can be a program name with args.
+set dummy help2man; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_HELP2MAN+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $HELP2MAN in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_HELP2MAN="$HELP2MAN" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_HELP2MAN="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+HELP2MAN=$ac_cv_path_HELP2MAN
+if test -n "$HELP2MAN"; then
+  { echo "$as_me:$LINENO: result: $HELP2MAN" >&5
+echo "${ECHO_T}$HELP2MAN" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+
+#
+# Checks for host programs.
+#
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort.  b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions.  Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+        if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+       then :; else
+          ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       fi
+       # We set ac_cv_exeext here because the later test for it is not
+       # safe: cross compilers may not add the suffix if given an `-o'
+       # argument, so we may need to know it at that point already.
+       # Even if this section looks crufty: it has the advantage of
+       # actually working.
+       break;;
+    * )
+       break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       CFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_c_werror_flag=$ac_save_c_werror_flag
+        CFLAGS="-g"
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_c89=$ac_arg
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+  xno)
+    { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+# Must be GCC.
+test "x$GCC" = xyes || { { echo "$as_me:$LINENO: error: GCC is required" >&5
+echo "$as_me: error: GCC is required" >&2;}
+   { (exit 1); exit 1; }; }
+
+
+cat >>confdefs.h <<\_ACEOF
+#define _GNU_SOURCE 1
+_ACEOF
+
+
+
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then
+  enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+  { echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5
+echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_largefile_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_sys_largefile_CC=no
+     if test "$GCC" != yes; then
+       ac_save_CC=$CC
+       while :; do
+        # IRIX 6.2 and later do not support large files by default,
+        # so use the C compiler's -n32 option if that helps.
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+        rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+        CC="$CC -n32"
+        rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_sys_largefile_CC=' -n32'; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+        break
+       done
+       CC=$ac_save_CC
+       rm -f conftest.$ac_ext
+    fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5
+echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6; }
+  if test "$ac_cv_sys_largefile_CC" != no; then
+    CC=$CC$ac_cv_sys_largefile_CC
+  fi
+
+  { echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_file_offset_bits+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  while :; do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_sys_file_offset_bits=no; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_sys_file_offset_bits=64; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_file_offset_bits=unknown
+  break
+done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5
+echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -f conftest*
+  if test $ac_cv_sys_file_offset_bits = unknown; then
+    { echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5
+echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_large_files+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  while :; do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_sys_large_files=no; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_sys_large_files=1; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_large_files=unknown
+  break
+done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5
+echo "${ECHO_T}$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -f conftest*
+  fi
+fi
+
+
+# Identify characteristics of the host architecture.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in grep ggrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+    # Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_GREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in egrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+    # Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_EGREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+
+   fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; }
+if test "${ac_cv_c_bigendian+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if  ! (defined BYTE_ORDER && defined BIG_ENDIAN && defined LITTLE_ENDIAN \
+       && BYTE_ORDER && BIG_ENDIAN && LITTLE_ENDIAN)
+ bogus endian macros
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_bigendian=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_c_bigendian=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       # It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+  # try to guess the endianness by grepping values into an object file
+  ac_cv_c_bigendian=unknown
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+  ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+  if test "$ac_cv_c_bigendian" = unknown; then
+    ac_cv_c_bigendian=no
+  else
+    # finding both strings is unlikely to happen, but who knows?
+    ac_cv_c_bigendian=unknown
+  fi
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+  /* Are we little or big endian?  From Harbison&Steele.  */
+  union
+  {
+    long int l;
+    char c[sizeof (long int)];
+  } u;
+  u.l = 1;
+  return u.c[sizeof (long int) - 1] == 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6; }
+case $ac_cv_c_bigendian in
+  yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define WORDS_BIGENDIAN 1
+_ACEOF
+ ;;
+  no)
+     ;;
+  *)
+    { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+
+{ echo "$as_me:$LINENO: checking for void *" >&5
+echo $ECHO_N "checking for void *... $ECHO_C" >&6; }
+if test "${ac_cv_type_void_p+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef void * ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_void_p=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_type_void_p=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_void_p" >&5
+echo "${ECHO_T}$ac_cv_type_void_p" >&6; }
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ echo "$as_me:$LINENO: checking size of void *" >&5
+echo $ECHO_N "checking size of void *... $ECHO_C" >&6; }
+if test "${ac_cv_sizeof_void_p+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef void * ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef void * ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_lo=`expr $ac_mid + 1`
+                       if test $ac_lo -le $ac_mid; then
+                         ac_lo= ac_hi=
+                         break
+                       fi
+                       ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef void * ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef void * ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_hi=`expr '(' $ac_mid ')' - 1`
+                       if test $ac_mid -le $ac_hi; then
+                         ac_lo= ac_hi=
+                         break
+                       fi
+                       ac_mid=`expr 2 '*' $ac_mid`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_lo= ac_hi=
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef void * ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_void_p=$ac_lo;;
+'') if test "$ac_cv_type_void_p" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (void *)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (void *)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_void_p=0
+   fi ;;
+esac
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef void * ac__type_sizeof_;
+static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
+static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (((long int) (sizeof (ac__type_sizeof_))) < 0)
+    {
+      long int i = longval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+       return 1;
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+       return 1;
+      fprintf (f, "%lu\n", i);
+    }
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_void_p=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+if test "$ac_cv_type_void_p" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (void *)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (void *)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_void_p=0
+   fi
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.val
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_void_p" >&5
+echo "${ECHO_T}$ac_cv_sizeof_void_p" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
+_ACEOF
+
+
+{ echo "$as_me:$LINENO: checking for long" >&5
+echo $ECHO_N "checking for long... $ECHO_C" >&6; }
+if test "${ac_cv_type_long+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+typedef long ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+  return 0;
+if (sizeof (ac__type_new_))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_type_long=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_type_long=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5
+echo "${ECHO_T}$ac_cv_type_long" >&6; }
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ echo "$as_me:$LINENO: checking size of long" >&5
+echo $ECHO_N "checking size of long... $ECHO_C" >&6; }
+if test "${ac_cv_sizeof_long+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_lo=`expr $ac_mid + 1`
+                       if test $ac_lo -le $ac_mid; then
+                         ac_lo= ac_hi=
+                         break
+                       fi
+                       ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_hi=`expr '(' $ac_mid ')' - 1`
+                       if test $ac_mid -le $ac_hi; then
+                         ac_lo= ac_hi=
+                         break
+                       fi
+                       ac_mid=`expr 2 '*' $ac_mid`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_lo= ac_hi=
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long ac__type_sizeof_;
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long=$ac_lo;;
+'') if test "$ac_cv_type_long" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (long)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_long=0
+   fi ;;
+esac
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+   typedef long ac__type_sizeof_;
+static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); }
+static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (((long int) (sizeof (ac__type_sizeof_))) < 0)
+    {
+      long int i = longval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+       return 1;
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ((long int) (sizeof (ac__type_sizeof_))))
+       return 1;
+      fprintf (f, "%lu\n", i);
+    }
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_long=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+if test "$ac_cv_type_long" = yes; then
+     { { echo "$as_me:$LINENO: error: cannot compute sizeof (long)
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long)
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+   else
+     ac_cv_sizeof_long=0
+   fi
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.val
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+_ACEOF
+
+
+
+if test "x$host_m32" = x1; then
+  # Force 32-bit mode.
+  CFLAGS="$CFLAGS -m32"
+  LDFLAGS="$LDFLAGS -m32"
+fi
+
+# Check LZO when compiling for the i386-pc.
+if test "$target_cpu"-"$platform" = i386-pc; then
+  # Check whether --enable-lzo was given.
+if test "${enable_lzo+set}" = set; then
+  enableval=$enable_lzo;
+fi
+
+  if [ x"$enable_lzo" = xyes ]; then
+    # There are three possibilities. LZO version 2 installed with the name
+    # liblzo2, with the name liblzo, and LZO version 1.
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_LZO 1
+_ACEOF
+
+    { echo "$as_me:$LINENO: checking for __lzo_init_v2 in -llzo2" >&5
+echo $ECHO_N "checking for __lzo_init_v2 in -llzo2... $ECHO_C" >&6; }
+if test "${ac_cv_lib_lzo2___lzo_init_v2+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-llzo2  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char __lzo_init_v2 ();
+int
+main ()
+{
+return __lzo_init_v2 ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_lzo2___lzo_init_v2=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_lzo2___lzo_init_v2=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_lzo2___lzo_init_v2" >&5
+echo "${ECHO_T}$ac_cv_lib_lzo2___lzo_init_v2" >&6; }
+if test $ac_cv_lib_lzo2___lzo_init_v2 = yes; then
+  LIBLZO="-llzo2"
+else
+  { echo "$as_me:$LINENO: checking for __lzo_init_v2 in -llzo" >&5
+echo $ECHO_N "checking for __lzo_init_v2 in -llzo... $ECHO_C" >&6; }
+if test "${ac_cv_lib_lzo___lzo_init_v2+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-llzo  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char __lzo_init_v2 ();
+int
+main ()
+{
+return __lzo_init_v2 ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_lzo___lzo_init_v2=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_lzo___lzo_init_v2=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_lzo___lzo_init_v2" >&5
+echo "${ECHO_T}$ac_cv_lib_lzo___lzo_init_v2" >&6; }
+if test $ac_cv_lib_lzo___lzo_init_v2 = yes; then
+  LIBLZO="-llzo"
+else
+  { echo "$as_me:$LINENO: checking for __lzo_init2 in -llzo" >&5
+echo $ECHO_N "checking for __lzo_init2 in -llzo... $ECHO_C" >&6; }
+if test "${ac_cv_lib_lzo___lzo_init2+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-llzo  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char __lzo_init2 ();
+int
+main ()
+{
+return __lzo_init2 ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_lzo___lzo_init2=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_lzo___lzo_init2=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_lzo___lzo_init2" >&5
+echo "${ECHO_T}$ac_cv_lib_lzo___lzo_init2" >&6; }
+if test $ac_cv_lib_lzo___lzo_init2 = yes; then
+  LIBLZO="-llzo"
+else
+  { { echo "$as_me:$LINENO: error: LZO library version 1.02 or later is required" >&5
+echo "$as_me: error: LZO library version 1.02 or later is required" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+fi
+
+fi
+
+
+    LIBS="$LIBS $LIBLZO"
+    { echo "$as_me:$LINENO: checking for lzo1x_999_compress" >&5
+echo $ECHO_N "checking for lzo1x_999_compress... $ECHO_C" >&6; }
+if test "${ac_cv_func_lzo1x_999_compress+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define lzo1x_999_compress to an innocuous variant, in case <limits.h> declares lzo1x_999_compress.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define lzo1x_999_compress innocuous_lzo1x_999_compress
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char lzo1x_999_compress (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef lzo1x_999_compress
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char lzo1x_999_compress ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_lzo1x_999_compress || defined __stub___lzo1x_999_compress
+choke me
+#endif
+
+int
+main ()
+{
+return lzo1x_999_compress ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_func_lzo1x_999_compress=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_func_lzo1x_999_compress=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_lzo1x_999_compress" >&5
+echo "${ECHO_T}$ac_cv_func_lzo1x_999_compress" >&6; }
+if test $ac_cv_func_lzo1x_999_compress = yes; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: LZO1X-999 must be enabled" >&5
+echo "$as_me: error: LZO1X-999 must be enabled" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+    # LZO version 2 uses lzo/lzo1x.h, while LZO version 1 uses lzo1x.h.
+
+
+for ac_header in lzo/lzo1x.h lzo1x.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ------------------------------- ##
+## Report this to bug-grub@gnu.org ##
+## ------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+  else
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_LZMA 1
+_ACEOF
+
+  fi
+
+fi
+
+# Check for functions.
+
+
+
+for ac_func in posix_memalign memalign asprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+#
+# Check for target programs.
+#
+
+
+# Use linker script if present, otherwise use builtin -N script.
+{ echo "$as_me:$LINENO: checking for option to link raw image" >&5
+echo $ECHO_N "checking for option to link raw image... $ECHO_C" >&6; }
+if test -f "${srcdir}/conf/${target_cpu}-${platform}-${host_os}-img-ld.sc"; then
+  TARGET_IMG_LDSCRIPT='$(top_srcdir)'"/conf/${target_cpu}-${platform}-${host_os}-img-ld.sc"
+  TARGET_IMG_LDFLAGS="-Wl,-T${TARGET_IMG_LDSCRIPT}"
+  TARGET_IMG_LDFLAGS_AC="-Wl,-T${srcdir}/conf/${target_cpu}-${platform}-${host_os}-img-ld.sc"
+else
+  TARGET_IMG_LDSCRIPT=
+  TARGET_IMG_LDFLAGS='-Wl,-N'
+  TARGET_IMG_LDFLAGS_AC='-Wl,-N'
+fi
+
+
+{ echo "$as_me:$LINENO: result: $TARGET_IMG_LDFLAGS_AC" >&5
+echo "${ECHO_T}$TARGET_IMG_LDFLAGS_AC" >&6; }
+
+# For platforms where ELF is not the default link format.
+{ echo "$as_me:$LINENO: checking for command to convert module to ELF format" >&5
+echo $ECHO_N "checking for command to convert module to ELF format... $ECHO_C" >&6; }
+case "${host_os}" in
+  cygwin) TARGET_OBJ2ELF='grub-pe2elf' ;;
+  *) ;;
+esac
+
+{ echo "$as_me:$LINENO: result: $TARGET_OBJ2ELF" >&5
+echo "${ECHO_T}$TARGET_OBJ2ELF" >&6; }
+
+# For cross-compiling.
+if test "x$build" != "x$host"; then
+  # XXX this depends on the implementation of autoconf!
+  tmp_ac_tool_prefix="$ac_tool_prefix"
+  ac_tool_prefix=$target_alias-
+
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in gcc egcs cc
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_TARGET_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$TARGET_CC"; then
+  ac_cv_prog_TARGET_CC="$TARGET_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_TARGET_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+TARGET_CC=$ac_cv_prog_TARGET_CC
+if test -n "$TARGET_CC"; then
+  { echo "$as_me:$LINENO: result: $TARGET_CC" >&5
+echo "${ECHO_T}$TARGET_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+    test -n "$TARGET_CC" && break
+  done
+fi
+if test -z "$TARGET_CC"; then
+  ac_ct_TARGET_CC=$TARGET_CC
+  for ac_prog in gcc egcs cc
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_TARGET_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_TARGET_CC"; then
+  ac_cv_prog_ac_ct_TARGET_CC="$ac_ct_TARGET_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_TARGET_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_TARGET_CC=$ac_cv_prog_ac_ct_TARGET_CC
+if test -n "$ac_ct_TARGET_CC"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_TARGET_CC" >&5
+echo "${ECHO_T}$ac_ct_TARGET_CC" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$ac_ct_TARGET_CC" && break
+done
+
+  if test "x$ac_ct_TARGET_CC" = x; then
+    TARGET_CC="{ { echo "$as_me:$LINENO: error: none of gcc, egcs and cc is found. set TARGET_CC manually." >&5
+echo "$as_me: error: none of gcc, egcs and cc is found. set TARGET_CC manually." >&2;}
+   { (exit 1); exit 1; }; }"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    TARGET_CC=$ac_ct_TARGET_CC
+  fi
+fi
+
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objcopy", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objcopy; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_OBJCOPY+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$OBJCOPY"; then
+  ac_cv_prog_OBJCOPY="$OBJCOPY" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OBJCOPY="${ac_tool_prefix}objcopy"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJCOPY=$ac_cv_prog_OBJCOPY
+if test -n "$OBJCOPY"; then
+  { echo "$as_me:$LINENO: result: $OBJCOPY" >&5
+echo "${ECHO_T}$OBJCOPY" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJCOPY"; then
+  ac_ct_OBJCOPY=$OBJCOPY
+  # Extract the first word of "objcopy", so it can be a program name with args.
+set dummy objcopy; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_OBJCOPY+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_OBJCOPY"; then
+  ac_cv_prog_ac_ct_OBJCOPY="$ac_ct_OBJCOPY" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OBJCOPY="objcopy"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJCOPY=$ac_cv_prog_ac_ct_OBJCOPY
+if test -n "$ac_ct_OBJCOPY"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_OBJCOPY" >&5
+echo "${ECHO_T}$ac_ct_OBJCOPY" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_OBJCOPY" = x; then
+    OBJCOPY=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJCOPY=$ac_ct_OBJCOPY
+  fi
+else
+  OBJCOPY="$ac_cv_prog_OBJCOPY"
+fi
+
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}nm", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nm; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_NM+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$NM"; then
+  ac_cv_prog_NM="$NM" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_NM="${ac_tool_prefix}nm"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+NM=$ac_cv_prog_NM
+if test -n "$NM"; then
+  { echo "$as_me:$LINENO: result: $NM" >&5
+echo "${ECHO_T}$NM" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NM"; then
+  ac_ct_NM=$NM
+  # Extract the first word of "nm", so it can be a program name with args.
+set dummy nm; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_NM+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_NM"; then
+  ac_cv_prog_ac_ct_NM="$ac_ct_NM" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_NM="nm"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_NM=$ac_cv_prog_ac_ct_NM
+if test -n "$ac_ct_NM"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_NM" >&5
+echo "${ECHO_T}$ac_ct_NM" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_NM" = x; then
+    NM=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    NM=$ac_ct_NM
+  fi
+else
+  NM="$ac_cv_prog_NM"
+fi
+
+
+  ac_tool_prefix="$tmp_ac_tool_prefix"
+else
+  if test "x$TARGET_CC" = x; then
+    TARGET_CC=$CC
+  fi
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objcopy", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objcopy; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_OBJCOPY+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$OBJCOPY"; then
+  ac_cv_prog_OBJCOPY="$OBJCOPY" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_OBJCOPY="${ac_tool_prefix}objcopy"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJCOPY=$ac_cv_prog_OBJCOPY
+if test -n "$OBJCOPY"; then
+  { echo "$as_me:$LINENO: result: $OBJCOPY" >&5
+echo "${ECHO_T}$OBJCOPY" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJCOPY"; then
+  ac_ct_OBJCOPY=$OBJCOPY
+  # Extract the first word of "objcopy", so it can be a program name with args.
+set dummy objcopy; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_OBJCOPY+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_OBJCOPY"; then
+  ac_cv_prog_ac_ct_OBJCOPY="$ac_ct_OBJCOPY" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_OBJCOPY="objcopy"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJCOPY=$ac_cv_prog_ac_ct_OBJCOPY
+if test -n "$ac_ct_OBJCOPY"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_OBJCOPY" >&5
+echo "${ECHO_T}$ac_ct_OBJCOPY" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_OBJCOPY" = x; then
+    OBJCOPY=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJCOPY=$ac_ct_OBJCOPY
+  fi
+else
+  OBJCOPY="$ac_cv_prog_OBJCOPY"
+fi
+
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}nm", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nm; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_NM+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$NM"; then
+  ac_cv_prog_NM="$NM" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_NM="${ac_tool_prefix}nm"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+NM=$ac_cv_prog_NM
+if test -n "$NM"; then
+  { echo "$as_me:$LINENO: result: $NM" >&5
+echo "${ECHO_T}$NM" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NM"; then
+  ac_ct_NM=$NM
+  # Extract the first word of "nm", so it can be a program name with args.
+set dummy nm; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_NM+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_NM"; then
+  ac_cv_prog_ac_ct_NM="$ac_ct_NM" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_NM="nm"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_NM=$ac_cv_prog_ac_ct_NM
+if test -n "$ac_ct_NM"; then
+  { echo "$as_me:$LINENO: result: $ac_ct_NM" >&5
+echo "${ECHO_T}$ac_ct_NM" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+  if test "x$ac_ct_NM" = x; then
+    NM=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    NM=$ac_ct_NM
+  fi
+else
+  NM="$ac_cv_prog_NM"
+fi
+
+fi
+
+
+
+# Test the C compiler for the target environment.
+tmp_CC="$CC"
+tmp_CFLAGS="$CFLAGS"
+tmp_LDFLAGS="$LDFLAGS"
+tmp_CPPFLAGS="$CPPFLAGS"
+tmp_LIBS="$LIBS"
+CC="$TARGET_CC"
+CFLAGS="$TARGET_CFLAGS"
+CPPFLAGS="$TARGET_CPPFLAGS"
+LDFLAGS="$TARGET_LDFLAGS"
+LIBS=""
+
+if test "x$TARGET_CFLAGS" = x; then
+  # debug flags.
+  TARGET_CFLAGS="-Wall -W -Wshadow -Wpointer-arith -Wmissing-prototypes \
+                 -Wundef -Wstrict-prototypes -g"
+
+  # optimization flags.
+  { echo "$as_me:$LINENO: checking whether optimization for size works" >&5
+echo $ECHO_N "checking whether optimization for size works... $ECHO_C" >&6; }
+if test "${grub_cv_cc_Os+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+    CFLAGS=-Os
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  grub_cv_cc_Os=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       grub_cv_cc_Os=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ echo "$as_me:$LINENO: result: $grub_cv_cc_Os" >&5
+echo "${ECHO_T}$grub_cv_cc_Os" >&6; }
+  if test "x$grub_cv_cc_Os" = xyes; then
+    TARGET_CFLAGS="$TARGET_CFLAGS -Os"
+  else
+    TARGET_CFLAGS="$TARGET_CFLAGS -O2 -fno-strength-reduce -fno-unroll-loops"
+  fi
+
+  # Force no alignment to save space on i386.
+  if test "x$target_cpu" = xi386; then
+    { echo "$as_me:$LINENO: checking whether -falign-loops works" >&5
+echo $ECHO_N "checking whether -falign-loops works... $ECHO_C" >&6; }
+if test "${grub_cv_cc_falign_loop+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+      CFLAGS="-falign-loops=1"
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  grub_cv_cc_falign_loop=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       grub_cv_cc_falign_loop=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ echo "$as_me:$LINENO: result: $grub_cv_cc_falign_loop" >&5
+echo "${ECHO_T}$grub_cv_cc_falign_loop" >&6; }
+
+    if test "x$grub_cv_cc_falign_loop" = xyes; then
+      TARGET_CFLAGS="$TARGET_CFLAGS -falign-jumps=1 -falign-loops=1 -falign-functions=1"
+    else
+      TARGET_CFLAGS="$TARGET_CFLAGS -malign-jumps=1 -malign-loops=1 -malign-functions=1"
+    fi
+  fi
+fi
+
+if test "x$target_m32" = x1; then
+  # Force 32-bit mode.
+  TARGET_CFLAGS="$TARGET_CFLAGS -m32"
+  TARGET_LDFLAGS="$TARGET_LDFLAGS -m32"
+fi
+
+if test "x$target_m64" = x1; then
+  # Force 64-bit mode.
+  TARGET_CFLAGS="$TARGET_CFLAGS -m64"
+  TARGET_LDFLAGS="$TARGET_LDFLAGS -m64"
+fi
+
+#
+# Compiler features.
+#
+
+# Need __enable_execute_stack() for nested function trampolines?
+
+{ echo "$as_me:$LINENO: checking whether \`$CC' generates calls to \`__enable_execute_stack()'" >&5
+echo $ECHO_N "checking whether \`$CC' generates calls to \`__enable_execute_stack()'... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+
+void f (int (*p) (void));
+void g (int i)
+{
+  int nestedfunc (void) { return i; }
+  f (nestedfunc);
+}
+
+_ACEOF
+if { ac_try='${CC-cc} ${CFLAGS} -S conftest.c'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } && test -s conftest.s; then
+  true
+else
+  { { echo "$as_me:$LINENO: error: ${CC-cc} failed to produce assembly code" >&5
+echo "$as_me: error: ${CC-cc} failed to produce assembly code" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if grep __enable_execute_stack conftest.s >/dev/null 2>&1; then
+
+cat >>confdefs.h <<\_ACEOF
+#define NEED_ENABLE_EXECUTE_STACK 1
+_ACEOF
+
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+rm -f conftest*
+
+
+# Smashing stack protector.
+
+# Smashing stack protector.
+ssp_possible=yes
+{ echo "$as_me:$LINENO: checking whether \`$CC' accepts \`-fstack-protector'" >&5
+echo $ECHO_N "checking whether \`$CC' accepts \`-fstack-protector'... $ECHO_C" >&6; }
+# Is this a reliable test case?
+cat >conftest.$ac_ext <<_ACEOF
+void foo (void) { volatile char a[8]; a[3]; }
+_ACEOF
+# `$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
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+  # Should we clear up other files as well, having called `AC_LANG_CONFTEST'?
+  rm -f conftest.s
+else
+  ssp_possible=no
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+# Need that, because some distributions ship compilers that include
+# `-fstack-protector' in the default specs.
+if test "x$ssp_possible" = xyes; then
+  TARGET_CFLAGS="$TARGET_CFLAGS -fno-stack-protector"
+fi
+
+# Smashing stack arg probe.
+sap_possible=yes
+{ echo "$as_me:$LINENO: checking whether \`$CC' accepts \`-mstack-arg-probe'" >&5
+echo $ECHO_N "checking whether \`$CC' accepts \`-mstack-arg-probe'... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+void foo (void) { volatile char a[8]; a[3]; }
+_ACEOF
+if eval "$ac_compile -S -mstack-arg-probe -o conftest.s" 2> /dev/null; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+  # Should we clear up other files as well, having called `AC_LANG_CONFTEST'?
+  rm -f conftest.s
+else
+  sap_possible=no
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+# Cygwin's GCC uses alloca() to probe the stackframe on static
+# stack allocations above some threshold.
+if test x"$sap_possible" = xyes; then
+  TARGET_CFLAGS="$TARGET_CFLAGS -mno-stack-arg-probe"
+fi
+
+
+
+
+
+
+# Set them to their new values for the tests below.
+CC="$TARGET_CC"
+CFLAGS="$TARGET_CFLAGS"
+CPPFLAGS="$TARGET_CPPFLAGS"
+LDFLAGS="$TARGET_LDFLAGS"
+
+# Defined in aclocal.m4.
+{ echo "$as_me:$LINENO: checking whether target compiler is working" >&5
+echo $ECHO_N "checking whether target compiler is working... $ECHO_C" >&6; }
+if test "${grub_cv_prog_target_cc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  grub_cv_prog_target_cc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       grub_cv_prog_target_cc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+
+fi
+
+{ echo "$as_me:$LINENO: result: $grub_cv_prog_target_cc" >&5
+echo "${ECHO_T}$grub_cv_prog_target_cc" >&6; }
+
+if test "x$grub_cv_prog_target_cc" = xno; then
+  { { echo "$as_me:$LINENO: error: cannot compile for the target" >&5
+echo "$as_me: error: cannot compile for the target" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+{ echo "$as_me:$LINENO: checking whether ${OBJCOPY} works for absolute addresses" >&5
+echo $ECHO_N "checking whether ${OBJCOPY} works for absolute addresses... $ECHO_C" >&6; }
+if test "${grub_cv_prog_objcopy_absolute+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat > conftest.c <<\EOF
+void
+cmain (void)
+{
+   *((int *) 0x1000) = 2;
+}
+EOF
+
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s conftest.o; then :
+else
+  { { echo "$as_me:$LINENO: error: ${CC-cc} cannot compile C source code" >&5
+echo "$as_me: error: ${CC-cc} cannot compile C source code" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+grub_cv_prog_objcopy_absolute=yes
+for link_addr in 2000 8000 7C00; do
+  if { ac_try='${CC-cc} ${CFLAGS} -nostdlib ${TARGET_IMG_LDFLAGS_AC} -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then :
+  else
+    { { echo "$as_me:$LINENO: error: ${CC-cc} cannot link at address $link_addr" >&5
+echo "$as_me: error: ${CC-cc} cannot link at address $link_addr" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  if { ac_try='${OBJCOPY-objcopy} --only-section=.text -O binary conftest.exec conftest'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then :
+  else
+    { { echo "$as_me:$LINENO: error: ${OBJCOPY-objcopy} cannot create binary files" >&5
+echo "$as_me: error: ${OBJCOPY-objcopy} cannot create binary files" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  if test ! -f conftest.old || { ac_try='cmp -s conftest.old conftest'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    mv -f conftest conftest.old
+  else
+    grub_cv_prog_objcopy_absolute=no
+    break
+  fi
+done
+rm -f conftest*
+fi
+
+{ echo "$as_me:$LINENO: result: $grub_cv_prog_objcopy_absolute" >&5
+echo "${ECHO_T}$grub_cv_prog_objcopy_absolute" >&6; }
+
+if test "x$grub_cv_prog_objcopy_absolute" = xno; then
+  { { echo "$as_me:$LINENO: error: GRUB requires a working absolute objcopy; upgrade your binutils" >&5
+echo "$as_me: error: GRUB requires a working absolute objcopy; upgrade your binutils" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+{ echo "$as_me:$LINENO: checking whether linker accepts --build-id=none" >&5
+echo $ECHO_N "checking whether linker accepts --build-id=none... $ECHO_C" >&6; }
+if test "${grub_cv_prog_ld_build_id_none+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  save_LDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS -Wl,--build-id=none"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  grub_cv_prog_ld_build_id_none=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       grub_cv_prog_ld_build_id_none=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LDFLAGS="$save_LDFLAGS"
+
+fi
+
+{ echo "$as_me:$LINENO: result: $grub_cv_prog_ld_build_id_none" >&5
+echo "${ECHO_T}$grub_cv_prog_ld_build_id_none" >&6; }
+
+if test "x$grub_cv_prog_ld_build_id_none" = xyes; then
+  MODULE_LDFLAGS="$MODULE_LDFLAGS -Wl,--build-id=none"
+fi
+
+
+{ echo "$as_me:$LINENO: checking if C symbols get an underscore after compilation" >&5
+echo $ECHO_N "checking if C symbols get an underscore after compilation... $ECHO_C" >&6; }
+if test "${grub_cv_asm_uscore+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat > conftest.c <<\EOF
+int
+func (int *list)
+{
+  *list = 0;
+  return *list;
+}
+EOF
+
+if { ac_try='${CC-cc} ${CFLAGS} -S conftest.c'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } && test -s conftest.s; then
+  true
+else
+  { { echo "$as_me:$LINENO: error: ${CC-cc} failed to produce assembly code" >&5
+echo "$as_me: error: ${CC-cc} failed to produce assembly code" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+if grep _func conftest.s >/dev/null 2>&1; then
+  grub_cv_asm_uscore=yes
+else
+  grub_cv_asm_uscore=no
+fi
+
+rm -f conftest*
+fi
+
+
+if test "x$grub_cv_asm_uscore" = xyes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ASM_USCORE $grub_cv_asm_uscore
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: result: $grub_cv_asm_uscore" >&5
+echo "${ECHO_T}$grub_cv_asm_uscore" >&6; }
+
+if test "x$target_cpu" = xi386; then
+  if test ! -z "$TARGET_IMG_LDSCRIPT"; then
+    # Check symbols provided by linker script.
+    CFLAGS="$TARGET_CFLAGS -nostdlib $TARGET_IMG_LDFLAGS_AC -Wl,-Ttext,8000,--defsym,___main=0x8100"
+  fi
+  if test "x$platform" = xpc; then
+
+{ echo "$as_me:$LINENO: checking if start is defined by the compiler" >&5
+echo $ECHO_N "checking if start is defined by the compiler... $ECHO_C" >&6; }
+if test "${grub_cv_check_start_symbol+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+asm ("incl start")
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  grub_cv_check_start_symbol=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       grub_cv_check_start_symbol=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+
+{ echo "$as_me:$LINENO: result: $grub_cv_check_start_symbol" >&5
+echo "${ECHO_T}$grub_cv_check_start_symbol" >&6; }
+
+{ echo "$as_me:$LINENO: checking if _start is defined by the compiler" >&5
+echo $ECHO_N "checking if _start is defined by the compiler... $ECHO_C" >&6; }
+if test "${grub_cv_check_uscore_start_symbol+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+asm ("incl _start")
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  grub_cv_check_uscore_start_symbol=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       grub_cv_check_uscore_start_symbol=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+
+{ echo "$as_me:$LINENO: result: $grub_cv_check_uscore_start_symbol" >&5
+echo "${ECHO_T}$grub_cv_check_uscore_start_symbol" >&6; }
+
+
+
+
+if test "x$grub_cv_check_start_symbol" = xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define START_SYMBOL start
+_ACEOF
+
+elif test "x$grub_cv_check_uscore_start_symbol" = xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define START_SYMBOL _start
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: neither start nor _start is defined" >&5
+echo "$as_me: error: neither start nor _start is defined" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+{ echo "$as_me:$LINENO: checking if __bss_start is defined by the compiler" >&5
+echo $ECHO_N "checking if __bss_start is defined by the compiler... $ECHO_C" >&6; }
+if test "${grub_cv_check_uscore_uscore_bss_start_symbol+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+asm ("incl __bss_start")
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  grub_cv_check_uscore_uscore_bss_start_symbol=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       grub_cv_check_uscore_uscore_bss_start_symbol=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+
+{ echo "$as_me:$LINENO: result: $grub_cv_check_uscore_uscore_bss_start_symbol" >&5
+echo "${ECHO_T}$grub_cv_check_uscore_uscore_bss_start_symbol" >&6; }
+
+{ echo "$as_me:$LINENO: checking if edata is defined by the compiler" >&5
+echo $ECHO_N "checking if edata is defined by the compiler... $ECHO_C" >&6; }
+if test "${grub_cv_check_edata_symbol+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+asm ("incl edata")
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  grub_cv_check_edata_symbol=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       grub_cv_check_edata_symbol=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+
+{ echo "$as_me:$LINENO: result: $grub_cv_check_edata_symbol" >&5
+echo "${ECHO_T}$grub_cv_check_edata_symbol" >&6; }
+
+{ echo "$as_me:$LINENO: checking if _edata is defined by the compiler" >&5
+echo $ECHO_N "checking if _edata is defined by the compiler... $ECHO_C" >&6; }
+if test "${grub_cv_check_uscore_edata_symbol+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+asm ("incl _edata")
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  grub_cv_check_uscore_edata_symbol=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       grub_cv_check_uscore_edata_symbol=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+
+{ echo "$as_me:$LINENO: result: $grub_cv_check_uscore_edata_symbol" >&5
+echo "${ECHO_T}$grub_cv_check_uscore_edata_symbol" >&6; }
+
+
+
+
+if test "x$grub_cv_check_uscore_uscore_bss_start_symbol" = xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define BSS_START_SYMBOL __bss_start
+_ACEOF
+
+elif test "x$grub_cv_check_edata_symbol" = xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define BSS_START_SYMBOL edata
+_ACEOF
+
+elif test "x$grub_cv_check_uscore_edata_symbol" = xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define BSS_START_SYMBOL _edata
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: none of __bss_start, edata or _edata is defined" >&5
+echo "$as_me: error: none of __bss_start, edata or _edata is defined" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+{ echo "$as_me:$LINENO: checking if end is defined by the compiler" >&5
+echo $ECHO_N "checking if end is defined by the compiler... $ECHO_C" >&6; }
+if test "${grub_cv_check_end_symbol+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+asm ("incl end")
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  grub_cv_check_end_symbol=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       grub_cv_check_end_symbol=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+
+{ echo "$as_me:$LINENO: result: $grub_cv_check_end_symbol" >&5
+echo "${ECHO_T}$grub_cv_check_end_symbol" >&6; }
+
+{ echo "$as_me:$LINENO: checking if _end is defined by the compiler" >&5
+echo $ECHO_N "checking if _end is defined by the compiler... $ECHO_C" >&6; }
+if test "${grub_cv_check_uscore_end_symbol+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+asm ("incl _end")
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  grub_cv_check_uscore_end_symbol=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       grub_cv_check_uscore_end_symbol=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+
+
+{ echo "$as_me:$LINENO: result: $grub_cv_check_uscore_end_symbol" >&5
+echo "${ECHO_T}$grub_cv_check_uscore_end_symbol" >&6; }
+
+
+
+
+if test "x$grub_cv_check_end_symbol" = xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define END_SYMBOL end
+_ACEOF
+
+elif test "x$grub_cv_check_uscore_end_symbol" = xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define END_SYMBOL _end
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: neither end nor _end is defined" >&5
+echo "$as_me: error: neither end nor _end is defined" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+  fi
+  CFLAGS="$TARGET_CFLAGS"
+
+{ echo "$as_me:$LINENO: checking whether addr32 must be in the same line as the instruction" >&5
+echo $ECHO_N "checking whether addr32 must be in the same line as the instruction... $ECHO_C" >&6; }
+if test "${grub_cv_i386_asm_prefix_requirement+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat > conftest.s <<\EOF
+       .code16
+l1:    addr32  movb    %al, l1
+EOF
+
+if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } && test -s conftest.o; then
+  grub_cv_i386_asm_prefix_requirement=yes
+else
+  grub_cv_i386_asm_prefix_requirement=no
+fi
+
+rm -f conftest*
+fi
+
+
+if test "x$grub_cv_i386_asm_prefix_requirement" = xyes; then
+  grub_tmp_addr32="addr32"
+  grub_tmp_data32="data32"
+else
+  grub_tmp_addr32="addr32;"
+  grub_tmp_data32="data32;"
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define ADDR32 $grub_tmp_addr32
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define DATA32 $grub_tmp_data32
+_ACEOF
+
+
+{ echo "$as_me:$LINENO: result: $grub_cv_i386_asm_prefix_requirement" >&5
+echo "${ECHO_T}$grub_cv_i386_asm_prefix_requirement" >&6; }
+
+
+{ echo "$as_me:$LINENO: checking for .code16 addr32 assembler support" >&5
+echo $ECHO_N "checking for .code16 addr32 assembler support... $ECHO_C" >&6; }
+if test "${grub_cv_i386_asm_addr32+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat > conftest.s.in <<\EOF
+       .code16
+l1:    @ADDR32@        movb    %al, l1
+EOF
+
+if test "x$grub_cv_i386_asm_prefix_requirement" = xyes; then
+  sed -e s/@ADDR32@/addr32/ < conftest.s.in > conftest.s
+else
+  sed -e s/@ADDR32@/addr32\;/ < conftest.s.in > conftest.s
+fi
+
+if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } && test -s conftest.o; then
+  grub_cv_i386_asm_addr32=yes
+else
+  grub_cv_i386_asm_addr32=no
+fi
+
+rm -f conftest*
+fi
+
+
+{ echo "$as_me:$LINENO: result: $grub_cv_i386_asm_addr32" >&5
+echo "${ECHO_T}$grub_cv_i386_asm_addr32" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether an absolute indirect call/jump must not be prefixed with an asterisk" >&5
+echo $ECHO_N "checking whether an absolute indirect call/jump must not be prefixed with an asterisk... $ECHO_C" >&6; }
+if test "${grub_cv_i386_asm_absolute_without_asterisk+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat > conftest.s <<\EOF
+       lcall   *(offset)
+offset:
+       .long   0
+       .word   0
+EOF
+
+if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } && test -s conftest.o; then
+  grub_cv_i386_asm_absolute_without_asterisk=no
+else
+  grub_cv_i386_asm_absolute_without_asterisk=yes
+fi
+
+rm -f conftest*
+fi
+
+
+if test "x$grub_cv_i386_asm_absolute_without_asterisk" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ABSOLUTE_WITHOUT_ASTERISK 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: result: $grub_cv_i386_asm_absolute_without_asterisk" >&5
+echo "${ECHO_T}$grub_cv_i386_asm_absolute_without_asterisk" >&6; }
+
+{ echo "$as_me:$LINENO: checking if GCC has the regparm=3 bug" >&5
+echo $ECHO_N "checking if GCC has the regparm=3 bug... $ECHO_C" >&6; }
+if test "${grub_cv_i386_check_nested_functions+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+static int
+test (int *n)
+{
+  return *n == -1;
+}
+
+static int
+testfunc (int __attribute__ ((__regparm__ (3))) (*hook) (int a, int b, int *c))
+{
+  int a = 0;
+  int b = 0;
+  int c = -1;
+  return hook (a, b, &c);
+}
+
+int
+main (void)
+{
+  int __attribute__ ((__regparm__ (3))) nestedfunc (int a, int b, int *c)
+    {
+      return a == b && test (c);
+    }
+  return testfunc (nestedfunc) ? 0 : 1;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  grub_cv_i386_check_nested_functions=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+grub_cv_i386_check_nested_functions=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+
+{ echo "$as_me:$LINENO: result: $grub_cv_i386_check_nested_functions" >&5
+echo "${ECHO_T}$grub_cv_i386_check_nested_functions" >&6; }
+
+if test "x$grub_cv_i386_check_nested_functions" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1)))
+_ACEOF
+
+else
+
+cat >>confdefs.h <<\_ACEOF
+#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1)))
+_ACEOF
+
+fi
+
+else
+
+cat >>confdefs.h <<\_ACEOF
+#define NESTED_FUNC_ATTR
+_ACEOF
+
+fi
+
+# Restore the flags.
+CC="$tmp_CC"
+CFLAGS="$tmp_CFLAGS"
+CPPFLAGS="$tmp_CPPFLAGS"
+LDFLAGS="$tmp_LDFLAGS"
+LIBS="$tmp_LIBS"
+
+#
+# Check for options.
+#
+
+# Memory manager debugging.
+# Check whether --enable-mm-debug was given.
+if test "${enable_mm_debug+set}" = set; then
+  enableval=$enable_mm_debug;
+cat >>confdefs.h <<\_ACEOF
+#define MM_DEBUG 1
+_ACEOF
+
+fi
+
+
+# Check whether --enable-grub-emu was given.
+if test "${enable_grub_emu+set}" = set; then
+  enableval=$enable_grub_emu;
+fi
+
+# Check whether --enable-grub-emu-usb was given.
+if test "${enable_grub_emu_usb+set}" = set; then
+  enableval=$enable_grub_emu_usb;
+fi
+
+if [ x"$enable_grub_emu" = xyes ]; then
+  # Check for curses libraries.
+  { echo "$as_me:$LINENO: checking for wgetch in -lncurses" >&5
+echo $ECHO_N "checking for wgetch in -lncurses... $ECHO_C" >&6; }
+if test "${ac_cv_lib_ncurses_wgetch+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lncurses  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char wgetch ();
+int
+main ()
+{
+return wgetch ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_ncurses_wgetch=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_ncurses_wgetch=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_ncurses_wgetch" >&5
+echo "${ECHO_T}$ac_cv_lib_ncurses_wgetch" >&6; }
+if test $ac_cv_lib_ncurses_wgetch = yes; then
+  LIBCURSES="-lncurses"
+else
+  { echo "$as_me:$LINENO: checking for wgetch in -lcurses" >&5
+echo $ECHO_N "checking for wgetch in -lcurses... $ECHO_C" >&6; }
+if test "${ac_cv_lib_curses_wgetch+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcurses  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char wgetch ();
+int
+main ()
+{
+return wgetch ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_curses_wgetch=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_curses_wgetch=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_curses_wgetch" >&5
+echo "${ECHO_T}$ac_cv_lib_curses_wgetch" >&6; }
+if test $ac_cv_lib_curses_wgetch = yes; then
+  LIBCURSES="-lcurses"
+else
+  { { echo "$as_me:$LINENO: error: (n)curses libraries are required to build \`grub-emu'" >&5
+echo "$as_me: error: (n)curses libraries are required to build \`grub-emu'" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+fi
+
+
+
+  # Check for headers.
+
+for ac_header in ncurses/curses.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ------------------------------- ##
+## Report this to bug-grub@gnu.org ##
+## ------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+
+for ac_header in ncurses.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ------------------------------- ##
+## Report this to bug-grub@gnu.org ##
+## ------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+
+for ac_header in curses.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ------------------------------- ##
+## Report this to bug-grub@gnu.org ##
+## ------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: (n)curses header files are required to build \`grub-emu'" >&5
+echo "$as_me: error: (n)curses header files are required to build \`grub-emu'" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+done
+
+fi
+
+done
+
+fi
+
+done
+
+
+  if [ x"$enable_grub_emu_usb" = xyes ]; then
+    # Check for libusb libraries.
+    { echo "$as_me:$LINENO: checking for usb_claim_interface in -lusb" >&5
+echo $ECHO_N "checking for usb_claim_interface in -lusb... $ECHO_C" >&6; }
+if test "${ac_cv_lib_usb_usb_claim_interface+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lusb  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char usb_claim_interface ();
+int
+main ()
+{
+return usb_claim_interface ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_usb_usb_claim_interface=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_usb_usb_claim_interface=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_usb_usb_claim_interface" >&5
+echo "${ECHO_T}$ac_cv_lib_usb_usb_claim_interface" >&6; }
+if test $ac_cv_lib_usb_usb_claim_interface = yes; then
+  LIBUSB="-lusb"
+else
+  { { echo "$as_me:$LINENO: error: libusb libraries are required to build \`grub-emu' with USB support" >&5
+echo "$as_me: error: libusb libraries are required to build \`grub-emu' with USB support" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+
+    # Check for headers.
+
+for ac_header in usb.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ------------------------------- ##
+## Report this to bug-grub@gnu.org ##
+## ------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: libusb header file is required to build \`grub-emu' with USB support" >&5
+echo "$as_me: error: libusb header file is required to build \`grub-emu' with USB support" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+done
+
+  fi
+fi
+
+
+
+# Check whether --enable-grub-fstest was given.
+if test "${enable_grub_fstest+set}" = set; then
+  enableval=$enable_grub_fstest;
+fi
+
+
+
+# Check whether --enable-grub-pe2elf was given.
+if test "${enable_grub_pe2elf+set}" = set; then
+  enableval=$enable_grub_pe2elf;
+fi
+
+
+
+# Check whether --enable-grub-mkfont was given.
+if test "${enable_grub_mkfont+set}" = set; then
+  enableval=$enable_grub_mkfont;
+fi
+
+if test x"$enable_grub_mkfont" = xyes ; then
+  # Check for freetype libraries.
+  for ac_prog in freetype-config
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_FREETYPE+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$FREETYPE"; then
+  ac_cv_prog_FREETYPE="$FREETYPE" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_FREETYPE="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+FREETYPE=$ac_cv_prog_FREETYPE
+if test -n "$FREETYPE"; then
+  { echo "$as_me:$LINENO: result: $FREETYPE" >&5
+echo "${ECHO_T}$FREETYPE" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+  test -n "$FREETYPE" && break
+done
+
+  if test "x$FREETYPE" = x ; then
+    { { echo "$as_me:$LINENO: error: freetype2 libraries are required to build \`grub-mkfont'" >&5
+echo "$as_me: error: freetype2 libraries are required to build \`grub-mkfont'" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  freetype_cflags=`freetype-config --cflags`
+  freetype_libs=`freetype-config --libs`
+fi
+
+
+
+
+# Output files.
+ac_config_links="$ac_config_links include/grub/cpu:include/grub/$target_cpu include/grub/machine:include/grub/$target_cpu/$platform"
+
+ac_config_files="$ac_config_files Makefile gensymlist.sh genkernsyms.sh"
+
+ac_config_files="$ac_config_files stamp-h"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s='ln -s'
+  # ... but there are two gotchas:
+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+  # In both cases, we have to default to `cp -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+    as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+        test -d "$1/.";
+      else
+       case $1 in
+        -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by GRUB $as_me 1.96, which was
+generated by GNU Autoconf 2.61.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_links="$ac_config_links"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+                  instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+                  instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration links:
+$config_links
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+GRUB config.status 1.96
+configured by $0, generated by GNU Autoconf 2.61,
+  with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  CONFIG_SHELL=$SHELL
+  export CONFIG_SHELL
+  exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "include/grub/cpu") CONFIG_LINKS="$CONFIG_LINKS include/grub/cpu:include/grub/$target_cpu" ;;
+    "include/grub/machine") CONFIG_LINKS="$CONFIG_LINKS include/grub/machine:include/grub/$target_cpu/$platform" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "gensymlist.sh") CONFIG_FILES="$CONFIG_FILES gensymlist.sh" ;;
+    "genkernsyms.sh") CONFIG_FILES="$CONFIG_FILES genkernsyms.sh" ;;
+    "stamp-h") CONFIG_FILES="$CONFIG_FILES stamp-h" ;;
+
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_LINKS+set}" = set || CONFIG_LINKS=$config_links
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+build!$build$ac_delim
+build_cpu!$build_cpu$ac_delim
+build_vendor!$build_vendor$ac_delim
+build_os!$build_os$ac_delim
+host!$host$ac_delim
+host_cpu!$host_cpu$ac_delim
+host_vendor!$host_vendor$ac_delim
+host_os!$host_os$ac_delim
+target!$target$ac_delim
+target_cpu!$target_cpu$ac_delim
+target_vendor!$target_vendor$ac_delim
+target_os!$target_os$ac_delim
+platform!$platform$ac_delim
+CMP!$CMP$ac_delim
+YACC!$YACC$ac_delim
+UNIFONT_BDF!$UNIFONT_BDF$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+AWK!$AWK$ac_delim
+SET_MAKE!$SET_MAKE$ac_delim
+RUBY!$RUBY$ac_delim
+HELP2MAN!$HELP2MAN$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+CPP!$CPP$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+LIBLZO!$LIBLZO$ac_delim
+enable_lzo!$enable_lzo$ac_delim
+TARGET_IMG_LDSCRIPT!$TARGET_IMG_LDSCRIPT$ac_delim
+TARGET_IMG_LDFLAGS!$TARGET_IMG_LDFLAGS$ac_delim
+TARGET_OBJ2ELF!$TARGET_OBJ2ELF$ac_delim
+TARGET_CC!$TARGET_CC$ac_delim
+ac_ct_TARGET_CC!$ac_ct_TARGET_CC$ac_delim
+OBJCOPY!$OBJCOPY$ac_delim
+STRIP!$STRIP$ac_delim
+NM!$NM$ac_delim
+TARGET_CFLAGS!$TARGET_CFLAGS$ac_delim
+TARGET_CPPFLAGS!$TARGET_CPPFLAGS$ac_delim
+TARGET_LDFLAGS!$TARGET_LDFLAGS$ac_delim
+MODULE_LDFLAGS!$MODULE_LDFLAGS$ac_delim
+LIBCURSES!$LIBCURSES$ac_delim
+LIBUSB!$LIBUSB$ac_delim
+enable_grub_emu!$enable_grub_emu$ac_delim
+enable_grub_emu_usb!$enable_grub_emu_usb$ac_delim
+enable_grub_fstest!$enable_grub_fstest$ac_delim
+enable_grub_pe2elf!$enable_grub_pe2elf$ac_delim
+FREETYPE!$FREETYPE$ac_delim
+enable_grub_mkfont!$enable_grub_mkfont$ac_delim
+freetype_cflags!$freetype_cflags$ac_delim
+freetype_libs!$freetype_libs$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 96; then
+    break
+  elif $ac_last_try; then
+    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+  ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[    ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[      ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in  :F $CONFIG_FILES  :H $CONFIG_HEADERS  :L $CONFIG_LINKS
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+   { (exit 1); exit 1; }; };;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+        # (if the path is not absolute).  The absolute path cannot be DOS-style,
+        # because $ac_f cannot contain `:'.
+        test -f "$ac_f" ||
+          case $ac_f in
+          [\\/$]*) false;;
+          *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+          esac ||
+          { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+   { (exit 1); exit 1; }; };;
+      esac
+      ac_file_inputs="$ac_file_inputs $ac_f"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input="Generated from "`IFS=:
+         echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    fi
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin";;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  { as_dir="$ac_dir"
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+    s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed 's/|#_!!_#|//g' >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[         ]*datarootdir[  ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out"; rm -f "$tmp/out";;
+  *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+  esac
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status.  If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless.  But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([  #]*\\)[^        ]*\\([  ]*'
+ac_dB='\\)[     (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+  sed -n '
+       t rset
+       :rset
+       s/^[     ]*#[    ]*define[       ][      ]*//
+       t ok
+       d
+       :ok
+       s/[\\&,]/\\&/g
+       s/^\('"$ac_word_re"'\)\(([^()]*)\)[      ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+       s/^\('"$ac_word_re"'\)[  ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+  ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[    #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is:         sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is:        sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be:    sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+  # Write a here document:
+    cat >>$CONFIG_STATUS <<_ACEOF
+    # First, check the format of the line:
+    cat >"\$tmp/defines.sed" <<\\CEOF
+/^[     ]*#[    ]*undef[        ][      ]*$ac_word_re[  ]*\$/b def
+/^[     ]*#[    ]*define[       ][      ]*$ac_word_re[(         ]/b def
+b
+:def
+_ACEOF
+  sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+    sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+  ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+  sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+  grep . conftest.tail >/dev/null || break
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+  if test x"$ac_file" != x-; then
+    echo "/* $configure_input  */" >"$tmp/config.h"
+    cat "$ac_result" >>"$tmp/config.h"
+    if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f $ac_file
+      mv "$tmp/config.h" $ac_file
+    fi
+  else
+    echo "/* $configure_input  */"
+    cat "$ac_result"
+  fi
+  rm -f "$tmp/out12"
+ ;;
+  :L)
+  #
+  # CONFIG_LINK
+  #
+
+  { echo "$as_me:$LINENO: linking $srcdir/$ac_source to $ac_file" >&5
+echo "$as_me: linking $srcdir/$ac_source to $ac_file" >&6;}
+
+  if test ! -r "$srcdir/$ac_source"; then
+    { { echo "$as_me:$LINENO: error: $srcdir/$ac_source: file not found" >&5
+echo "$as_me: error: $srcdir/$ac_source: file not found" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  rm -f "$ac_file"
+
+  # Try a relative symlink, then a hard link, then a copy.
+  case $srcdir in
+  [\\/$]* | ?:[\\/]* ) ac_rel_source=$srcdir/$ac_source ;;
+      *) ac_rel_source=$ac_top_build_prefix$srcdir/$ac_source ;;
+  esac
+  ln -s "$ac_rel_source" "$ac_file" 2>/dev/null ||
+    ln "$srcdir/$ac_source" "$ac_file" 2>/dev/null ||
+    cp -p "$srcdir/$ac_source" "$ac_file" ||
+    { { echo "$as_me:$LINENO: error: cannot link or copy $srcdir/$ac_source to $ac_file" >&5
+echo "$as_me: error: cannot link or copy $srcdir/$ac_source to $ac_file" >&2;}
+   { (exit 1); exit 1; }; }
+ ;;
+
+  esac
+
+
+  case $ac_file$ac_mode in
+    "stamp-h":F) echo timestamp > stamp-h ;;
+
+  esac
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..7658c7a
--- /dev/null
@@ -0,0 +1,444 @@
+# Process this file with autoconf to produce a configure script.
+
+# Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009  Free Software Foundation, Inc.
+#
+# This configure.ac is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+dnl This configure script is complicated, because GRUB needs to deal
+dnl with three potentially different types:
+dnl
+dnl   build  -- the environment for building GRUB
+dnl   host   -- the environment for running utilities
+dnl   target -- the environment for running GRUB
+dnl
+dnl In addition, GRUB needs to deal with a platform specification
+dnl which specifies the system running GRUB, such as firmware.
+dnl This is necessary because the target type in autoconf does not
+dnl describe such a system very well.
+dnl
+dnl The current strategy is to use variables with no prefix (such as
+dnl CC, CFLAGS, etc.) for the host type as well as the build type,
+dnl because GRUB does not need to use those variables for the build
+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.96],[bug-grub@gnu.org])
+AC_PREREQ(2.59)
+AC_CONFIG_SRCDIR([include/grub/dl.h])
+AC_CONFIG_HEADER([config.h])
+
+# Checks for host and target systems.
+AC_CANONICAL_HOST
+AC_CANONICAL_TARGET
+
+# Program name transformations
+AC_ARG_PROGRAM
+
+case "$host_cpu" in
+  powerpc64) host_m32=1 ;;
+esac
+
+case "$target_cpu" in
+  i[[3456]]86) target_cpu=i386 ;;
+esac
+
+# Specify the platform (such as firmware).
+AC_ARG_WITH([platform],
+            AS_HELP_STRING([--with-platform=PLATFORM],
+                           [select the host platform [[guessed]]]))
+
+# Guess the platform if not specified.
+if test "x$with_platform" = x; then
+  case "$target_cpu"-"$target_vendor" in
+    i386-apple) platform=efi ;;
+    i386-*) platform=pc ;;
+    x86_64-apple) platform=efi ;;
+    x86_64-*) platform=pc ;;
+    powerpc-*) platform=ieee1275 ;;
+    powerpc64-*) platform=ieee1275 ;;
+    sparc64-*) platform=ieee1275 ;;
+    *) AC_MSG_ERROR([unsupported CPU: "$target_cpu"]) ;;
+  esac
+else
+  platform="$with_platform"
+fi
+
+# Adjust CPU unless target was explicitly specified.
+if test -z "$target_alias"; then
+  case "$target_cpu"-"$platform" in
+    x86_64-efi) ;;
+    x86_64-*) target_cpu=i386 ;;
+    powerpc64-ieee1275) target_cpu=powerpc ;;
+  esac
+fi
+
+# Check if the platform is supported, make final adjustments.
+case "$target_cpu"-"$platform" in
+  i386-efi) ;;
+  x86_64-efi) ;;
+  i386-pc) ;;
+  i386-coreboot) ;;
+  i386-linuxbios) platform=coreboot ;;
+  i386-ieee1275) ;;
+  powerpc-ieee1275) ;;
+  sparc64-ieee1275) ;;
+  *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;;
+esac
+
+case "$target_cpu" in
+  i386 | powerpc) target_m32=1 ;;
+  x86_64 | sparc64) target_m64=1 ;;
+esac
+
+case "$host_os" in
+  mingw32) host_os=cygwin ;;
+esac
+
+AC_SUBST(host_cpu)
+AC_SUBST(host_os)
+
+AC_SUBST(target_cpu)
+AC_SUBST(platform)
+
+#
+# Checks for build programs.
+#
+
+# Although cmp is listed in the GNU Coding Standards as a command which
+# can used directly, OpenBSD lacks cmp in the default installation.
+AC_CHECK_PROGS([CMP], [cmp])
+if test "x$CMP" = x; then
+  AC_MSG_ERROR([cmp is not found])
+fi
+
+AC_CHECK_PROGS([YACC], [bison])
+if test "x$YACC" = x; then
+  AC_MSG_ERROR([bison is not found])
+fi
+
+for file in /usr/src/unifont.bdf ; do
+  if test -e $file ; then
+    AC_SUBST([UNIFONT_BDF], [$file])
+    break
+  fi
+done
+
+AC_PROG_INSTALL
+AC_PROG_AWK
+AC_PROG_MAKE_SET
+
+# These are not a "must".
+AC_PATH_PROG(RUBY, ruby)
+AC_PATH_PROG(HELP2MAN, help2man)
+
+#
+# Checks for host programs.
+#
+
+AC_PROG_CC
+# Must be GCC.
+test "x$GCC" = xyes || AC_MSG_ERROR([GCC is required])
+
+AC_GNU_SOURCE
+AC_SYS_LARGEFILE
+
+# Identify characteristics of the host architecture.
+AC_C_BIGENDIAN
+AC_CHECK_SIZEOF(void *)
+AC_CHECK_SIZEOF(long)
+
+if test "x$host_m32" = x1; then
+  # Force 32-bit mode.
+  CFLAGS="$CFLAGS -m32"
+  LDFLAGS="$LDFLAGS -m32"
+fi
+
+# Check LZO when compiling for the i386-pc.
+if test "$target_cpu"-"$platform" = i386-pc; then
+  AC_ARG_ENABLE([lzo],
+             [AS_HELP_STRING([--enable-lzo],
+                             [use lzo to compress kernel (default is lzma)])])
+  [if [ x"$enable_lzo" = xyes ]; then
+    # There are three possibilities. LZO version 2 installed with the name
+    # liblzo2, with the name liblzo, and LZO version 1.]
+    AC_DEFINE([ENABLE_LZO], [1], [Use lzo compression])
+    AC_CHECK_LIB([lzo2], [__lzo_init_v2], [LIBLZO="-llzo2"],
+      [AC_CHECK_LIB([lzo], [__lzo_init_v2], [LIBLZO="-llzo"],
+        [AC_CHECK_LIB([lzo], [__lzo_init2], [LIBLZO="-llzo"],
+              [AC_MSG_ERROR([LZO library version 1.02 or later is required])])])])
+    AC_SUBST([LIBLZO])
+    [LIBS="$LIBS $LIBLZO"]
+    AC_CHECK_FUNC([lzo1x_999_compress], ,
+               [AC_MSG_ERROR([LZO1X-999 must be enabled])])
+
+    [# LZO version 2 uses lzo/lzo1x.h, while LZO version 1 uses lzo1x.h.]
+    AC_CHECK_HEADERS([lzo/lzo1x.h lzo1x.h])
+  [else]
+    AC_DEFINE([ENABLE_LZMA], [1], [Use lzma compression])
+  [fi]
+  AC_SUBST([enable_lzo])
+fi
+
+# Check for functions.
+AC_CHECK_FUNCS(posix_memalign memalign asprintf)
+
+#
+# Check for target programs.
+#
+
+
+# Use linker script if present, otherwise use builtin -N script.
+AC_MSG_CHECKING([for option to link raw image])
+if test -f "${srcdir}/conf/${target_cpu}-${platform}-${host_os}-img-ld.sc"; then
+  TARGET_IMG_LDSCRIPT='$(top_srcdir)'"/conf/${target_cpu}-${platform}-${host_os}-img-ld.sc"
+  TARGET_IMG_LDFLAGS="-Wl,-T${TARGET_IMG_LDSCRIPT}"
+  TARGET_IMG_LDFLAGS_AC="-Wl,-T${srcdir}/conf/${target_cpu}-${platform}-${host_os}-img-ld.sc"
+else
+  TARGET_IMG_LDSCRIPT=
+  TARGET_IMG_LDFLAGS='-Wl,-N'
+  TARGET_IMG_LDFLAGS_AC='-Wl,-N'
+fi
+AC_SUBST(TARGET_IMG_LDSCRIPT)
+AC_SUBST(TARGET_IMG_LDFLAGS)
+AC_MSG_RESULT([$TARGET_IMG_LDFLAGS_AC])
+
+# For platforms where ELF is not the default link format.
+AC_MSG_CHECKING([for command to convert module to ELF format])
+case "${host_os}" in
+  cygwin) TARGET_OBJ2ELF='grub-pe2elf' ;;
+  *) ;;
+esac
+AC_SUBST(TARGET_OBJ2ELF)
+AC_MSG_RESULT([$TARGET_OBJ2ELF])
+
+# For cross-compiling.
+if test "x$build" != "x$host"; then
+  # XXX this depends on the implementation of autoconf!
+  tmp_ac_tool_prefix="$ac_tool_prefix"
+  ac_tool_prefix=$target_alias-
+
+  AC_CHECK_TOOLS(TARGET_CC, [gcc egcs cc],
+                 [AC_MSG_ERROR([none of gcc, egcs and cc is found. set TARGET_CC manually.])])
+  AC_CHECK_TOOL(OBJCOPY, objcopy)
+  AC_CHECK_TOOL(STRIP, strip)
+  AC_CHECK_TOOL(NM, nm)
+
+  ac_tool_prefix="$tmp_ac_tool_prefix"
+else
+  if test "x$TARGET_CC" = x; then
+    TARGET_CC=$CC
+  fi
+  AC_CHECK_TOOL(OBJCOPY, objcopy)
+  AC_CHECK_TOOL(STRIP, strip)
+  AC_CHECK_TOOL(NM, nm)
+fi
+AC_SUBST(TARGET_CC)
+
+
+# Test the C compiler for the target environment.
+tmp_CC="$CC"
+tmp_CFLAGS="$CFLAGS"
+tmp_LDFLAGS="$LDFLAGS"
+tmp_CPPFLAGS="$CPPFLAGS"
+tmp_LIBS="$LIBS"
+CC="$TARGET_CC"
+CFLAGS="$TARGET_CFLAGS"
+CPPFLAGS="$TARGET_CPPFLAGS"
+LDFLAGS="$TARGET_LDFLAGS"
+LIBS=""
+
+if test "x$TARGET_CFLAGS" = x; then
+  # debug flags.
+  TARGET_CFLAGS="-Wall -W -Wshadow -Wpointer-arith -Wmissing-prototypes \
+                 -Wundef -Wstrict-prototypes -g"
+
+  # optimization flags.
+  AC_CACHE_CHECK([whether optimization for size works], grub_cv_cc_Os, [
+    CFLAGS=-Os
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
+                     [grub_cv_cc_Os=yes],
+                     [grub_cv_cc_Os=no])
+  ])
+  if test "x$grub_cv_cc_Os" = xyes; then
+    TARGET_CFLAGS="$TARGET_CFLAGS -Os"
+  else
+    TARGET_CFLAGS="$TARGET_CFLAGS -O2 -fno-strength-reduce -fno-unroll-loops"
+  fi
+
+  # Force no alignment to save space on i386.
+  if test "x$target_cpu" = xi386; then
+    AC_CACHE_CHECK([whether -falign-loops works], [grub_cv_cc_falign_loop], [
+      CFLAGS="-falign-loops=1"
+      AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
+                       [grub_cv_cc_falign_loop=yes],
+                       [grub_cv_cc_falign_loop=no])
+    ])
+
+    if test "x$grub_cv_cc_falign_loop" = xyes; then
+      TARGET_CFLAGS="$TARGET_CFLAGS -falign-jumps=1 -falign-loops=1 -falign-functions=1"
+    else
+      TARGET_CFLAGS="$TARGET_CFLAGS -malign-jumps=1 -malign-loops=1 -malign-functions=1"
+    fi
+  fi
+fi
+
+if test "x$target_m32" = x1; then
+  # Force 32-bit mode.
+  TARGET_CFLAGS="$TARGET_CFLAGS -m32"
+  TARGET_LDFLAGS="$TARGET_LDFLAGS -m32"
+fi
+
+if test "x$target_m64" = x1; then
+  # Force 64-bit mode.
+  TARGET_CFLAGS="$TARGET_CFLAGS -m64"
+  TARGET_LDFLAGS="$TARGET_LDFLAGS -m64"
+fi
+
+#
+# Compiler features.
+#
+
+# Need __enable_execute_stack() for nested function trampolines?
+grub_CHECK_ENABLE_EXECUTE_STACK
+
+# Smashing stack protector.
+grub_CHECK_STACK_PROTECTOR
+# Need that, because some distributions ship compilers that include
+# `-fstack-protector' in the default specs.
+if test "x$ssp_possible" = xyes; then
+  TARGET_CFLAGS="$TARGET_CFLAGS -fno-stack-protector"
+fi
+grub_CHECK_STACK_ARG_PROBE
+# Cygwin's GCC uses alloca() to probe the stackframe on static
+# stack allocations above some threshold.
+if test x"$sap_possible" = xyes; then
+  TARGET_CFLAGS="$TARGET_CFLAGS -mno-stack-arg-probe"
+fi
+
+AC_SUBST(TARGET_CFLAGS)
+AC_SUBST(TARGET_CPPFLAGS)
+AC_SUBST(TARGET_LDFLAGS)
+AC_SUBST(MODULE_LDFLAGS)
+
+# Set them to their new values for the tests below.
+CC="$TARGET_CC"
+CFLAGS="$TARGET_CFLAGS"
+CPPFLAGS="$TARGET_CPPFLAGS"
+LDFLAGS="$TARGET_LDFLAGS"
+
+# Defined in aclocal.m4.
+grub_PROG_TARGET_CC
+grub_PROG_OBJCOPY_ABSOLUTE
+grub_PROG_LD_BUILD_ID_NONE
+grub_ASM_USCORE
+if test "x$target_cpu" = xi386; then
+  if test ! -z "$TARGET_IMG_LDSCRIPT"; then
+    # Check symbols provided by linker script.
+    CFLAGS="$TARGET_CFLAGS -nostdlib $TARGET_IMG_LDFLAGS_AC -Wl,-Ttext,8000,--defsym,___main=0x8100"
+  fi
+  if test "x$platform" = xpc; then
+    grub_CHECK_START_SYMBOL
+    grub_CHECK_BSS_START_SYMBOL
+    grub_CHECK_END_SYMBOL
+  fi
+  CFLAGS="$TARGET_CFLAGS"
+  grub_I386_ASM_PREFIX_REQUIREMENT
+  grub_I386_ASM_ADDR32
+  grub_I386_ASM_ABSOLUTE_WITHOUT_ASTERISK
+  grub_I386_CHECK_REGPARM_BUG
+else
+  AC_DEFINE([NESTED_FUNC_ATTR], [], [Catch gcc bug])
+fi
+
+# Restore the flags.
+CC="$tmp_CC"
+CFLAGS="$tmp_CFLAGS"
+CPPFLAGS="$tmp_CPPFLAGS"
+LDFLAGS="$tmp_LDFLAGS"
+LIBS="$tmp_LIBS"
+
+#
+# Check for options.
+#
+
+# Memory manager debugging.
+AC_ARG_ENABLE([mm-debug], 
+             AS_HELP_STRING([--enable-mm-debug],
+                             [include memory manager debugging]),
+              [AC_DEFINE([MM_DEBUG], [1],
+                         [Define to 1 if you enable memory manager debugging.])])
+
+AC_ARG_ENABLE([grub-emu],
+             [AS_HELP_STRING([--enable-grub-emu],
+                             [build and install the `grub-emu' debugging utility])])
+AC_ARG_ENABLE([grub-emu-usb],
+             [AS_HELP_STRING([--enable-grub-emu-usb],
+                             [build and install the `grub-emu' debugging utility with USB support])])
+[if [ x"$enable_grub_emu" = xyes ]; then
+  # Check for curses libraries.]
+  AC_CHECK_LIB([ncurses], [wgetch], [LIBCURSES="-lncurses"],
+    [AC_CHECK_LIB([curses], [wgetch], [LIBCURSES="-lcurses"],
+      [AC_MSG_ERROR([(n)curses libraries are required to build `grub-emu'])])])
+  AC_SUBST([LIBCURSES])
+
+  [# Check for headers.]
+  AC_CHECK_HEADERS([ncurses/curses.h], [],
+    [AC_CHECK_HEADERS([ncurses.h], [],
+      [AC_CHECK_HEADERS([curses.h], [],
+       [AC_MSG_ERROR([(n)curses header files are required to build `grub-emu'])])])])
+
+  [if [ x"$enable_grub_emu_usb" = xyes ]; then
+    # Check for libusb libraries.]
+    AC_CHECK_LIB([usb], [usb_claim_interface], [LIBUSB="-lusb"],
+      [AC_MSG_ERROR([libusb libraries are required to build `grub-emu' with USB support])])
+    AC_SUBST([LIBUSB])
+
+    [# Check for headers.]
+    AC_CHECK_HEADERS([usb.h], [],
+      [AC_MSG_ERROR([libusb header file is required to build `grub-emu' with USB support])])
+  [fi]
+[fi]
+AC_SUBST([enable_grub_emu])
+AC_SUBST([enable_grub_emu_usb])
+
+AC_ARG_ENABLE([grub-fstest],
+             [AS_HELP_STRING([--enable-grub-fstest],
+                             [build and install the `grub-fstest' debugging utility])])
+AC_SUBST([enable_grub_fstest])
+
+AC_ARG_ENABLE([grub-pe2elf],
+             [AS_HELP_STRING([--enable-grub-pe2elf],
+                             [build and install the `grub-pe2elf' conversion utility])])
+AC_SUBST([enable_grub_pe2elf])
+
+AC_ARG_ENABLE([grub-mkfont],
+             [AS_HELP_STRING([--enable-grub-mkfont],
+                             [build and install the `grub-mkfont' utility])])
+if test x"$enable_grub_mkfont" = xyes ; then
+  # Check for freetype libraries.
+  AC_CHECK_PROGS([FREETYPE], [freetype-config])
+  if test "x$FREETYPE" = x ; then
+    AC_MSG_ERROR([freetype2 libraries are required to build `grub-mkfont'])
+  fi
+  freetype_cflags=`freetype-config --cflags`
+  freetype_libs=`freetype-config --libs`
+fi
+AC_SUBST([enable_grub_mkfont])
+AC_SUBST([freetype_cflags])
+AC_SUBST([freetype_libs])
+
+# Output files.
+AC_CONFIG_LINKS([include/grub/cpu:include/grub/$target_cpu
+       include/grub/machine:include/grub/$target_cpu/$platform])
+AC_CONFIG_FILES([Makefile gensymlist.sh genkernsyms.sh])
+AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h])
+AC_OUTPUT
diff --git a/disk/ata.c b/disk/ata.c
new file mode 100644 (file)
index 0000000..ed98b0b
--- /dev/null
@@ -0,0 +1,861 @@
+/* ata.c - ATA disk access.  */
+/*
+ *  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/>.
+ */
+
+#include <grub/ata.h>
+#include <grub/dl.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+#include <grub/time.h>
+#include <grub/pci.h>
+#include <grub/scsi.h>
+
+/* At the moment, only two IDE ports are supported.  */
+static const int grub_ata_ioaddress[] = { 0x1f0, 0x170 };
+static const int grub_ata_ioaddress2[] = { 0x3f6, 0x376 };
+
+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;
+  while (grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY)
+    {
+      if (i >= milliseconds)
+        {
+         grub_dprintf ("ata", "timeout: %dms\n", milliseconds);
+         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;
+}
+
+/* Byteorder has to be changed before strings can be read.  */
+static void
+grub_ata_strncpy (char *dst, char *src, grub_size_t len)
+{
+  grub_uint16_t *src16 = (grub_uint16_t *) src;
+  grub_uint16_t *dst16 = (grub_uint16_t *) dst;
+  unsigned int i;
+
+  for (i = 0; i < len / 2; i++)
+    *(dst16++) = grub_be_to_cpu16 (*(src16++));
+  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)
+{
+  char text[41];
+
+  /* The device information was read, dump it for debugging.  */
+  grub_ata_strncpy (text, info + 20, 20);
+  grub_dprintf ("ata", "Serial: %s\n", text);
+  grub_ata_strncpy (text, info + 46, 8);
+  grub_dprintf ("ata", "Firmware: %s\n", text);
+  grub_ata_strncpy (text, info + 54, 40);
+  grub_dprintf ("ata", "Model: %s\n", text);
+
+  if (! dev->atapi)
+    {
+      grub_dprintf ("ata", "Addressing: %d\n", dev->addr);
+      grub_dprintf ("ata", "Sectors: %lld\n", dev->size);
+    }
+}
+
+static grub_err_t
+grub_atapi_identify (struct grub_ata_device *dev)
+{
+  char *info;
+
+  info = grub_malloc (GRUB_DISK_SECTOR_SIZE);
+  if (! info)
+    return grub_errno;
+
+  grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4);
+  if (grub_ata_check_ready (dev))
+    {
+      grub_free (info);
+      return grub_errno;
+    }
+
+  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))
+    {
+      grub_free (info);
+      return grub_errno;
+    }
+  grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE);
+
+  dev->atapi = 1;
+
+  grub_ata_dumpinfo (dev, info);
+
+  grub_free (info);
+
+  return GRUB_ERR_NONE;
+}
+
+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)
+{
+  char *info;
+  grub_uint16_t *info16;
+
+  info = grub_malloc (GRUB_DISK_SECTOR_SIZE);
+  if (! info)
+    return grub_errno;
+
+  info16 = (grub_uint16_t *) info;
+
+  grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4);
+  if (grub_ata_check_ready (dev))
+    {
+      grub_free (info);
+      return grub_errno;
+    }
+
+  grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_IDENTIFY_DEVICE);
+  grub_ata_wait ();
+
+  if (grub_ata_wait_drq (dev, 0, GRUB_ATA_TOUT_STD))
+    {
+      if (grub_ata_regget (dev, GRUB_ATA_REG_ERROR) & 0x04) /* ABRT */
+       {
+         /* Device without ATA IDENTIFY, try ATAPI.  */
+         grub_free(info);
+         grub_errno = GRUB_ERR_NONE;
+         return grub_atapi_identify (dev);
+       }
+      else
+       {
+         /* Error.  */
+         grub_free(info);
+         return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                            "device can not be identified");
+       }
+    }
+
+  grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE);
+
+  /* Now it is certain that this is not an ATAPI device.  */
+  dev->atapi = 0;
+
+  /* CHS is always supported.  */
+  dev->addr = GRUB_ATA_CHS;
+
+  /* Check if LBA is supported.  */
+  if (info16[49] & (1 << 9))
+    {
+      /* Check if LBA48 is supported.  */
+      if (info16[83] & (1 << 10))
+       dev->addr = GRUB_ATA_LBA48;
+      else
+       dev->addr = GRUB_ATA_LBA;
+    }
+
+  /* Determine the amount of sectors.  */
+  if (dev->addr != GRUB_ATA_LBA48)
+    dev->size = grub_le_to_cpu32(*((grub_uint32_t *) &info16[60]));
+  else
+    dev->size = grub_le_to_cpu64(*((grub_uint64_t *) &info16[100]));
+
+  /* Read CHS information.  */
+  dev->cylinders = info16[1];
+  dev->heads = info16[3];
+  dev->sectors_per_track = info16[6];
+
+  grub_ata_dumpinfo (dev, info);
+
+  grub_free(info);
+
+  return 0;
+}
+
+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_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;
+  dev->ioaddress2 = addr2;
+  dev->next = NULL;
+
+  grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4);
+  grub_ata_wait ();
+
+  /* If status is 0x00, it is safe to assume that there
+     is no device (or only a !READY) device connected.  */
+  grub_int8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS);
+  grub_dprintf ("ata", "status=0x%x\n", sts);
+  if (sts == 0x00)
+    {
+      grub_free(dev);
+      return 0;
+    }
+
+  /* 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.
+     But this tests often detects a second (slave) device
+     connected to a SATA controller which supports only one
+     (master) device.  In this case, the status register
+     check above usually works.  */
+  grub_ata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A);  
+  grub_ata_wait ();
+  grub_int8_t sec = grub_ata_regget (dev, GRUB_ATA_REG_SECTORS);
+  grub_dprintf ("ata", "sectors=0x%x\n", sec);
+  if (sec != 0x5A)
+    {
+      grub_free(dev);
+      return 0;
+    }
+
+  /* Use the IDENTIFY DEVICE command to query the device.  */
+  if (grub_ata_identify (dev))
+    {
+      grub_free (dev);
+      return 0;
+    }
+
+  /* Register the device.  */
+  for (devp = &grub_ata_devices; *devp; devp = &(*devp)->next);
+  *devp = dev;
+
+  return 0;
+}
+
+static int
+grub_ata_pciinit (int bus, int device, int func,
+                 grub_pci_id_t pciid __attribute__((unused)))
+{
+  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;
+
+  /* Read class.  */
+  addr = grub_pci_make_address (bus, device, func, 2);
+  class = grub_pci_read (addr);
+
+  /* Check if this class ID matches that of a PCI IDE Controller.  */
+  if (class >> 16 != 0x0101)
+    return 0;
+
+  for (i = 0; i < 2; i++)
+    {
+      /* Set to 0 when the channel operated in compatibility mode.  */
+      int 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 (bus, device, func, 4 + 2 * i);
+         bar1 = grub_pci_read (addr);
+         addr = grub_pci_make_address (bus, device, func, 5 + 2 * i);
+         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",
+                   bus, device, func, compat, rega, regb);
+
+      if (rega && regb)
+       {
+         grub_errno = GRUB_ERR_NONE;
+         grub_ata_device_initialize (controller * 2 + i, 0, rega, regb);
+
+         /* Most errors rised 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_disk_addr_t sector,
+                    grub_size_t size)
+{
+  switch (addressing)
+    {
+    case GRUB_ATA_CHS:
+      {
+       unsigned int cylinder;
+       unsigned int head;
+       unsigned int sect;
+
+       /* Calculate the sector, cylinder and head to use.  */
+       sect = ((grub_uint32_t) sector % dev->sectors_per_track) + 1;
+       cylinder = (((grub_uint32_t) sector / dev->sectors_per_track)
+                   / dev->heads);
+       head = ((grub_uint32_t) sector / dev->sectors_per_track) % dev->heads;
+
+       if (sect > dev->sectors_per_track
+           || cylinder > dev->cylinders
+           || head > dev->heads)
+         return grub_error (GRUB_ERR_OUT_OF_RANGE,
+                            "sector %d can not 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);
+
+       break;
+      }
+
+    case GRUB_ATA_LBA:
+      if (size == 256)
+       size = 0;
+      grub_ata_regset (dev, GRUB_ATA_REG_DISK,
+                      0xE0 | (dev->device << 4) | ((sector >> 24) & 0x0F));
+      if (grub_ata_check_ready (dev))
+       return grub_errno;
+
+      grub_ata_setlba (dev, sector, size);
+      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;
+
+      /* Set "Previous".  */
+      grub_ata_setlba (dev, sector >> 24, size >> 8);
+      /* Set "Current".  */
+      grub_ata_setlba (dev, sector, size);
+
+      break;
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+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=%u, rw=%d)\n", size, rw);
+
+  grub_ata_addressing_t addressing = dev->addr;
+  grub_size_t batch;
+  int cmd, cmd_write;
+
+  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;
+    }
+  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;
+    }
+
+  grub_size_t nsectors = 0;
+  while (nsectors < size)
+    {
+      if (size - nsectors < batch)
+       batch = size - nsectors;
+
+      grub_dprintf("ata", "rw=%d, sector=%llu, batch=%u\n", rw, sector, batch);
+
+      /* Send read/write commmand.  */
+      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");
+       }
+
+      sector += batch;
+      nsectors += batch;
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+\f
+
+static int
+grub_ata_iterate (int (*hook) (const char *name))
+{
+  struct grub_ata_device *dev;
+
+  for (dev = grub_ata_devices; dev; dev = dev->next)
+    {
+      char devname[5];
+      grub_sprintf (devname, "ata%d", dev->port * 2 + dev->device);
+
+      if (dev->atapi)
+       continue;
+
+      if (hook (devname))
+       return 1;
+    }
+
+  return 0;
+}
+
+static grub_err_t
+grub_ata_open (const char *name, grub_disk_t disk)
+{
+  struct grub_ata_device *dev;
+
+  for (dev = grub_ata_devices; dev; dev = dev->next)
+    {
+      char devname[5];
+      grub_sprintf (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)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk");
+
+  disk->total_sectors = dev->size;
+
+  disk->id = (unsigned long) dev;
+  
+  disk->has_partitions = 1;
+  disk->data = dev;
+
+  return 0;
+}
+
+static void
+grub_ata_close (grub_disk_t disk __attribute__((unused)))
+{
+  
+}
+
+static grub_err_t
+grub_ata_read (grub_disk_t disk, grub_disk_addr_t sector,
+              grub_size_t size, char *buf)
+{
+  return grub_ata_readwrite (disk, sector, size, buf, 0);
+}
+
+static grub_err_t
+grub_ata_write (grub_disk_t disk,
+               grub_disk_addr_t sector,
+               grub_size_t size,
+               const char *buf)
+{
+  return grub_ata_readwrite (disk, sector, size, (char *) buf, 1);
+}
+
+static struct grub_disk_dev grub_atadisk_dev =
+  {
+    .name = "ATA",
+    .id = GRUB_DISK_DEVICE_ATA_ID,
+    .iterate = grub_ata_iterate,
+    .open = grub_ata_open,
+    .close = grub_ata_close,
+    .read = grub_ata_read,
+    .write = grub_ata_write,
+    .next = 0
+  };
+
+
+\f
+/* ATAPI code.  */
+
+static int
+grub_atapi_iterate (int (*hook) (const char *name, int luns))
+{
+  struct grub_ata_device *dev;
+
+  for (dev = grub_ata_devices; dev; dev = dev->next)
+    {
+      char devname[7];
+      grub_sprintf (devname, "ata%d", dev->port * 2 + dev->device);
+
+      if (! dev->atapi)
+       continue;
+
+      if (hook (devname, 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)
+{
+  struct grub_ata_device *dev = (struct grub_ata_device *) scsi->data;
+
+  grub_dprintf("ata", "grub_atapi_read (size=%u)\n", size);
+
+  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;
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_atapi_write (struct grub_scsi *scsi __attribute__((unused)),
+                 grub_size_t cmdsize __attribute__((unused)),
+                 char *cmd __attribute__((unused)),
+                 grub_size_t size __attribute__((unused)),
+                 char *buf __attribute__((unused)))
+{
+  // XXX: scsi.mod does not use write yet.
+  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ATAPI write not implemented");
+}
+
+static grub_err_t
+grub_atapi_open (const char *name, struct grub_scsi *scsi)
+{
+  struct grub_ata_device *dev;
+  struct grub_ata_device *devfnd = 0;
+
+  for (dev = grub_ata_devices; dev; dev = dev->next)
+    {
+      char devname[7];
+      grub_sprintf (devname, "ata%d", dev->port * 2 + dev->device);
+
+      if (!grub_strcmp (devname, name))
+       {
+         devfnd = dev;
+         break;
+       }
+    }
+
+  grub_dprintf ("ata", "opening ATAPI dev `%s'\n", name);
+
+  if (! devfnd)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such ATAPI device");
+
+  scsi->data = devfnd;
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_atapi_close (struct grub_scsi *scsi)
+{
+  grub_free (scsi->name);
+}
+
+static struct grub_scsi_dev grub_atapi_dev =
+  {
+    .name = "ATAPI",
+    .iterate = grub_atapi_iterate,
+    .open = grub_atapi_open,
+    .close = grub_atapi_close,
+    .read = grub_atapi_read,
+    .write = grub_atapi_write
+  }; 
+
+\f
+
+GRUB_MOD_INIT(ata)
+{
+  (void) mod;                  /* To stop warning. */
+
+  /* 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.  */
+  grub_scsi_dev_register (&grub_atapi_dev);
+}
+
+GRUB_MOD_FINI(ata)
+{
+  grub_scsi_dev_unregister (&grub_atapi_dev);
+  grub_disk_dev_unregister (&grub_atadisk_dev);
+}
diff --git a/disk/ata_pthru.c b/disk/ata_pthru.c
new file mode 100644 (file)
index 0000000..cc74eb4
--- /dev/null
@@ -0,0 +1,109 @@
+/* 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)
+{
+  (void) mod;
+
+  /* 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/disk/dmraid_nvidia.c b/disk/dmraid_nvidia.c
new file mode 100644 (file)
index 0000000..ee43bef
--- /dev/null
@@ -0,0 +1,165 @@
+/* dmraid_nvidia.c - module to handle Nvidia fakeraid.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/raid.h>
+
+#define NV_SIGNATURES          4
+
+#define NV_IDLE                        0
+#define NV_SCDB_INIT_RAID      2
+#define NV_SCDB_REBUILD_RAID   3
+#define NV_SCDB_UPGRADE_RAID   4
+#define NV_SCDB_SYNC_RAID      5
+
+#define NV_LEVEL_UNKNOWN       0x00
+#define NV_LEVEL_JBOD          0xFF
+#define NV_LEVEL_0             0x80
+#define NV_LEVEL_1             0x81
+#define NV_LEVEL_3             0x83
+#define NV_LEVEL_5             0x85
+#define NV_LEVEL_10            0x8a
+#define NV_LEVEL_1_0           0x8180
+
+#define NV_ARRAY_FLAG_BOOT             1 /* BIOS use only.  */
+#define NV_ARRAY_FLAG_ERROR            2 /* Degraded or offling.  */
+#define NV_ARRAY_FLAG_PARITY_VALID     4 /* RAID-3/5 parity valid.  */
+
+struct grub_nv_array
+{
+  grub_uint32_t version;
+  grub_uint32_t signature[NV_SIGNATURES];
+  grub_uint8_t raid_job_code;
+  grub_uint8_t stripe_width;
+  grub_uint8_t total_volumes;
+  grub_uint8_t original_width;
+  grub_uint32_t raid_level;
+  grub_uint32_t stripe_block_size;
+  grub_uint32_t stripe_block_size_bytes;
+  grub_uint32_t stripe_block_size_log2;
+  grub_uint32_t stripe_mask;
+  grub_uint32_t stripe_size;
+  grub_uint32_t stripe_size_bytes;
+  grub_uint32_t raid_job_mask;
+  grub_uint32_t original_capacity;
+  grub_uint32_t flags;
+};
+
+#define NV_ID_LEN              8
+#define NV_ID_STRING           "NVIDIA"
+#define NV_VERSION             100
+
+#define        NV_PRODID_LEN           16
+#define        NV_PRODREV_LEN          4
+
+struct grub_nv_super
+{
+  char vendor[NV_ID_LEN];      /* 0x00 - 0x07 ID string.  */
+  grub_uint32_t size;          /* 0x08 - 0x0B Size of metadata in dwords.  */
+  grub_uint32_t chksum;                /* 0x0C - 0x0F Checksum of this struct.  */
+  grub_uint16_t version;       /* 0x10 - 0x11 NV version.  */
+  grub_uint8_t unit_number;    /* 0x12 Disk index in array.  */
+  grub_uint8_t reserved;       /* 0x13.  */
+  grub_uint32_t capacity;      /* 0x14 - 0x17 Array capacity in sectors.  */
+  grub_uint32_t sector_size;   /* 0x18 - 0x1B Sector size.  */
+  char prodid[NV_PRODID_LEN];  /* 0x1C - 0x2B Array product ID.  */
+  char prodrev[NV_PRODREV_LEN];        /* 0x2C - 0x2F Array product revision */
+  grub_uint32_t unit_flags;    /* 0x30 - 0x33 Flags for this disk */
+  struct grub_nv_array array;  /* Array information */
+} __attribute__ ((packed));
+
+static grub_err_t
+grub_dmraid_nv_detect (grub_disk_t disk, struct grub_raid_array *array)
+{
+  grub_disk_addr_t sector;
+  struct grub_nv_super sb;
+
+  if (disk->partition)
+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "skip partition");
+
+  sector = grub_disk_get_size (disk) - 2;
+
+  if (grub_disk_read (disk, sector, 0, sizeof (sb), (char *) &sb))
+    return grub_errno;
+
+  if (grub_memcmp (sb.vendor, NV_ID_STRING, 6))
+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
+
+  if (sb.version != NV_VERSION)
+    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                       "Unknown version: %d.%d", sb.version);
+
+  switch (sb.array.raid_level)
+    {
+    case NV_LEVEL_0:
+      array->level = 0;
+      array->disk_size = sb.capacity / sb.array.total_volumes;
+      break;
+
+    case NV_LEVEL_1:
+      array->level = 1;
+      array->disk_size = sb.capacity;
+      break;
+
+    case NV_LEVEL_5:
+      array->level = 5;
+      array->layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC;
+      array->disk_size = sb.capacity / (sb.array.total_volumes - 1);
+      break;
+
+    default:
+      return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                         "Unsupported RAID level: %d", sb.array.raid_level);
+    }
+
+  array->number = 0;
+  array->total_devs = sb.array.total_volumes;
+  array->chunk_size = sb.array.stripe_block_size;
+  array->index = sb.unit_number;
+  array->uuid_len = sizeof (sb.array.signature);
+  array->uuid = grub_malloc (sizeof (sb.array.signature));
+  if (! array->uuid)
+    return grub_errno;
+
+  grub_memcpy (array->uuid, (char *) &sb.array.signature,
+               sizeof (sb.array.signature));
+
+  return 0;
+}
+
+static struct grub_raid grub_dmraid_nv_dev =
+{
+  .name = "dmraid_nv",
+  .detect = grub_dmraid_nv_detect,
+  .next = 0
+};
+
+GRUB_MOD_INIT(dm_nv)
+{
+  grub_raid_register (&grub_dmraid_nv_dev);
+}
+
+GRUB_MOD_FINI(dm_nv)
+{
+  grub_raid_register (&grub_dmraid_nv_dev);
+}
diff --git a/disk/efi/efidisk.c b/disk/efi/efidisk.c
new file mode 100644 (file)
index 0000000..767ebf8
--- /dev/null
@@ -0,0 +1,859 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+#include <grub/disk.h>
+#include <grub/partition.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/term.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/disk.h>
+
+struct grub_efidisk_data
+{
+  grub_efi_handle_t handle;
+  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;
+static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID;
+
+static struct grub_efidisk_data *fd_devices;
+static struct grub_efidisk_data *hd_devices;
+static struct grub_efidisk_data *cd_devices;
+
+/* Duplicate a device path.  */
+static grub_efi_device_path_t *
+duplicate_device_path (const grub_efi_device_path_t *dp)
+{
+  grub_efi_device_path_t *p;
+  grub_size_t total_size = 0;
+  
+  for (p = (grub_efi_device_path_t *) dp;
+       ;
+       p = GRUB_EFI_NEXT_DEVICE_PATH (p))
+    {
+      total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
+      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
+       break;
+    }
+
+  p = grub_malloc (total_size);
+  if (! p)
+    return 0;
+
+  grub_memcpy (p, dp, total_size);
+  return p;
+}
+
+/* Return the device path node right before the end node.  */
+static grub_efi_device_path_t *
+find_last_device_path (const grub_efi_device_path_t *dp)
+{
+  grub_efi_device_path_t *next, *p;
+
+  if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
+    return 0;
+
+  for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p);
+       ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next);
+       p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))
+    ;
+
+  return p;
+}
+
+/* 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)
+{
+  grub_efi_uintn_t num_handles;
+  grub_efi_handle_t *handles;
+  grub_efi_handle_t *handle;
+  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,
+                                   0, &num_handles);
+  if (! handles)
+    return 0;
+
+  /* Make a linked list of devices.  */
+  for (handle = handles; num_handles--; handle++)
+    {
+      grub_efi_device_path_t *dp;
+      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)
+       continue;
+
+      ldp = find_last_device_path (dp);
+      if (! ldp)
+       /* This is empty. Why?  */
+       continue;
+      
+      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)
+       /* This should not happen... Why?  */
+       continue;
+       
+      d = grub_malloc (sizeof (*d));
+      if (! d)
+       {
+         /* Uggh.  */
+         grub_free (handles);
+         return 0;
+       }
+
+      d->handle = *handle;
+      d->device_path = dp;
+      d->last_device_path = ldp;
+      d->block_io = bio;
+      d->disk_io = dio;
+      d->next = devices;
+      devices = d;
+    }
+
+  grub_free (handles);
+  
+  return devices;
+}
+
+/* Find the parent device.  */
+static struct grub_efidisk_data *
+find_parent_device (struct grub_efidisk_data *devices,
+                   struct grub_efidisk_data *d)
+{
+  grub_efi_device_path_t *dp, *ldp;
+  struct grub_efidisk_data *parent;
+  
+  dp = duplicate_device_path (d->device_path);
+  if (! dp)
+    return 0;
+
+  ldp = find_last_device_path (dp);
+  ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+  ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+  ldp->length[0] = sizeof (*ldp);
+  ldp->length[1] = 0;
+
+  for (parent = devices; parent; parent = parent->next)
+    {
+      /* Ignore itself.  */
+      if (parent == d)
+       continue;
+      
+      if (compare_device_paths (parent->device_path, dp) == 0)
+       {
+         /* Found.  */
+         if (! parent->last_device_path)
+           parent = 0;
+         
+         break;
+       }
+    }
+
+  grub_free (dp);
+  return parent;
+}
+
+static int
+iterate_child_devices (struct grub_efidisk_data *devices,
+                      struct grub_efidisk_data *d,
+                      int (*hook) (struct grub_efidisk_data *child))
+{
+  struct grub_efidisk_data *p;
+  
+  for (p = devices; p; p = p->next)
+    {
+      grub_efi_device_path_t *dp, *ldp;
+
+      dp = duplicate_device_path (p->device_path);
+      if (! dp)
+       return 0;
+      
+      ldp = find_last_device_path (dp);
+      ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+      ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+      ldp->length[0] = sizeof (*ldp);
+      ldp->length[1] = 0;
+      
+      if (compare_device_paths (dp, d->device_path) == 0)
+       if (hook (p))
+         {
+           grub_free (dp);
+           return 1;
+         }
+
+      grub_free (dp);
+    }
+
+  return 0;
+}
+
+/* Add a device into a list of devices in an ascending order.  */
+static void
+add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d)
+{
+  struct grub_efidisk_data **p;
+  struct grub_efidisk_data *n;
+
+  for (p = devices; *p; p = &((*p)->next))
+    {
+      int ret;
+
+      ret = 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);
+      if (ret == 0)
+       return;
+      else if (ret > 0)
+       break;
+    }
+
+  n = grub_malloc (sizeof (*n));
+  if (! n)
+    return;
+
+  grub_memcpy (n, d, sizeof (*n));
+  n->next = (*p);
+  (*p) = n;
+}
+
+/* Name the devices.  */
+static void
+name_devices (struct grub_efidisk_data *devices)
+{
+  struct grub_efidisk_data *d;
+  
+  /* First, identify devices by media device paths.  */
+  for (d = devices; d; d = d->next)
+    {
+      grub_efi_device_path_t *dp;
+
+      dp = d->last_device_path;
+      if (! dp)
+       continue;
+      
+      if (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE)
+       {
+         int is_hard_drive = 0;
+         
+         switch (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp))
+           {
+           case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE:
+             is_hard_drive = 1;
+             /* Fall through by intention.  */
+           case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE:
+             {
+               struct grub_efidisk_data *parent;
+
+               parent = find_parent_device (devices, d);
+               if (parent)
+                 {
+                   if (is_hard_drive)
+                     {
+#if 0
+                       grub_printf ("adding a hard drive by a partition: ");
+                       grub_print_device_path (parent->device_path);
+#endif
+                       add_device (&hd_devices, parent);
+                     }
+                   else
+                     {
+#if 0
+                       grub_printf ("adding a cdrom by a partition: ");
+                       grub_print_device_path (parent->device_path);
+#endif
+                       add_device (&cd_devices, parent);
+                     }
+                   
+                   /* Mark the parent as used.  */
+                   parent->last_device_path = 0;
+                 }
+             }
+             /* Mark itself as used.  */
+             d->last_device_path = 0;
+             break;
+
+           default:
+             /* For now, ignore the others.  */
+             break;
+           }
+       }
+    }
+
+  /* Let's see what can be added more.  */
+  for (d = devices; d; d = d->next)
+    {
+      grub_efi_device_path_t *dp;
+      grub_efi_block_io_media_t *m;
+      
+      dp = d->last_device_path;
+      if (! dp)
+       continue;
+
+      m = d->block_io->media;
+      if (m->logical_partition)
+       {
+         /* Only one partition in a non-media device. Assume that this
+            is a floppy drive.  */
+#if 0
+         grub_printf ("adding a floppy by guessing: ");
+         grub_print_device_path (d->device_path);
+#endif
+         add_device (&fd_devices, d);
+       }
+      else if (m->read_only && m->block_size > GRUB_DISK_SECTOR_SIZE)
+       {
+         /* This check is too heuristic, but assume that this is a
+            CDROM drive.  */
+#if 0
+         grub_printf ("adding a cdrom by guessing: ");
+         grub_print_device_path (d->device_path);
+#endif
+         add_device (&cd_devices, d);
+       }
+      else
+       {
+         /* The default is a hard drive.  */
+#if 0
+         grub_printf ("adding a hard drive by guessing: ");
+         grub_print_device_path (d->device_path);
+#endif
+         add_device (&hd_devices, d);
+       }
+    }
+}
+
+static void
+free_devices (struct grub_efidisk_data *devices)
+{
+  struct grub_efidisk_data *p, *q;
+  
+  for (p = devices; p; p = q)
+    {
+      q = p->next;
+      grub_free (p);
+    }
+}
+
+/* Enumerate all disks to name devices.  */
+static void
+enumerate_disks (void)
+{
+  struct grub_efidisk_data *devices;
+  
+  devices = make_devices ();
+  if (! devices)
+    return;
+  
+  name_devices (devices);
+  free_devices (devices);
+}
+
+static int
+grub_efidisk_iterate (int (*hook) (const char *name))
+{
+  struct grub_efidisk_data *d;
+  char buf[16];
+  int count;
+  
+  for (d = fd_devices, count = 0; d; d = d->next, count++)
+    {
+      grub_sprintf (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_sprintf (buf, "hd%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_sprintf (buf, "cd%d", count);
+      grub_dprintf ("efidisk", "iterating %s\n", buf);
+      if (hook (buf))
+       return 1;
+    }
+
+  return 0;
+}
+
+static int
+get_drive_number (const char *name)
+{
+  unsigned long drive;
+
+  if ((name[0] != 'f' && name[0] != 'h' && name[0] != 'c') || name[1] != 'd')
+    goto fail;
+
+  drive = grub_strtoul (name + 2, 0, 10);
+  if (grub_errno != GRUB_ERR_NONE)
+    goto fail;
+
+  return (int) drive ;
+
+ fail:
+  grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a efidisk");
+  return -1;
+}
+
+static struct grub_efidisk_data *
+get_device (struct grub_efidisk_data *devices, int num)
+{
+  struct grub_efidisk_data *d;
+
+  for (d = devices; d && num; d = d->next, num--)
+    ;
+
+  if (num == 0)
+    return d;
+
+  return 0;
+}
+
+static grub_err_t
+grub_efidisk_open (const char *name, struct grub_disk *disk)
+{
+  int num;
+  struct grub_efidisk_data *d = 0;
+  grub_efi_block_io_media_t *m;
+
+  grub_dprintf ("efidisk", "opening %s\n", name);
+  
+  num = get_drive_number (name);
+  if (num < 0)
+    return grub_errno;
+
+  switch (name[0])
+    {
+    case 'f':
+      disk->has_partitions = 0;
+      d = get_device (fd_devices, num);
+      break;
+    case 'c':
+      /* FIXME: a CDROM should have partitions, but not implemented yet.  */
+      disk->has_partitions = 0;
+      d = get_device (cd_devices, num);
+      break;
+    case 'h':
+      disk->has_partitions = 1;
+      d = get_device (hd_devices, num);
+      break;
+    default:
+      /* Never reach here.  */
+      break;
+    }
+
+  if (! d)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such device");
+
+  disk->id = ((num << 8) | name[0]);
+  m = d->block_io->media;
+  /* FIXME: Probably it is better to store the block size in the disk,
+     and total sectors should be replaced with total blocks.  */
+  grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n",
+               m, (unsigned long long) m->last_block, m->block_size);
+  disk->total_sectors = (m->last_block
+                        * (m->block_size >> GRUB_DISK_SECTOR_BITS));
+  disk->data = d;
+
+  grub_dprintf ("efidisk", "opening %s succeeded\n", name);
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_efidisk_close (struct grub_disk *disk __attribute__ ((unused)))
+{
+  /* EFI disks do not allocate extra memory, so nothing to do here.  */
+  grub_dprintf ("efidisk", "closing %s\n", disk->name);
+}
+
+static grub_err_t
+grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector,
+                  grub_size_t size, char *buf)
+{
+  /* 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);
+  if (status != GRUB_EFI_SUCCESS)
+    return grub_error (GRUB_ERR_READ_ERROR, "efidisk read error");
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector,
+                   grub_size_t size, const char *buf)
+{
+  /* 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,
+                      (void *) buf);
+  if (status != GRUB_EFI_SUCCESS)
+    return grub_error (GRUB_ERR_WRITE_ERROR, "efidisk write error");
+  
+  return GRUB_ERR_NONE;
+}
+
+static struct grub_disk_dev grub_efidisk_dev =
+  {
+    .name = "efidisk",
+    .id = GRUB_DISK_DEVICE_EFIDISK_ID,
+    .iterate = grub_efidisk_iterate,
+    .open = grub_efidisk_open,
+    .close = grub_efidisk_close,
+    .read = grub_efidisk_read,
+    .write = grub_efidisk_write,
+    .next = 0
+  };
+
+void
+grub_efidisk_init (void)
+{
+  enumerate_disks ();
+  grub_disk_dev_register (&grub_efidisk_dev);
+}
+
+void
+grub_efidisk_fini (void)
+{
+  free_devices (fd_devices);
+  free_devices (hd_devices);
+  free_devices (cd_devices);
+  grub_disk_dev_unregister (&grub_efidisk_dev);
+}
+
+/* Some utility functions to map GRUB devices with EFI devices.  */
+grub_efi_handle_t
+grub_efidisk_get_device_handle (grub_disk_t disk)
+{
+  struct grub_efidisk_data *d;
+  char type;
+  
+  if (disk->dev->id != GRUB_DISK_DEVICE_EFIDISK_ID)
+    return 0;
+  
+  d = disk->data;
+  type = disk->name[0];
+  
+  switch (type)
+    {
+    case 'f':
+      /* This is the simplest case.  */
+      return d->handle;
+
+    case 'c':
+      /* FIXME: probably this is not correct.  */
+      return d->handle;
+
+    case 'h':
+      /* If this is the whole disk, just return its own data.  */
+      if (! disk->partition)
+       return d->handle;
+
+      /* Otherwise, we must query the corresponding device to the firmware.  */
+      {
+       struct grub_efidisk_data *devices;
+       grub_efi_handle_t handle = 0;
+       auto int find_partition (struct grub_efidisk_data *c);
+
+       int find_partition (struct grub_efidisk_data *c)
+         {
+           grub_efi_hard_drive_device_path_t hd;
+
+           grub_memcpy (&hd, c->last_device_path, sizeof (hd));
+           
+           if ((GRUB_EFI_DEVICE_PATH_TYPE (c->last_device_path)
+                == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE)
+               && (GRUB_EFI_DEVICE_PATH_SUBTYPE (c->last_device_path)
+                   == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)
+               && (grub_partition_get_start (disk->partition)
+                   == hd.partition_start)
+               && (grub_partition_get_len (disk->partition)
+                   == hd.partition_size))
+             {
+               handle = c->handle;
+               return 1;
+             }
+             
+           return 0;
+         }
+       
+       devices = make_devices ();
+       iterate_child_devices (devices, d, find_partition);
+       free_devices (devices);
+       
+       if (handle != 0)
+         return handle;
+      }
+      break;
+
+    default:
+      break;
+    }
+  
+  return 0;
+}
+
+char *
+grub_efidisk_get_device_name (grub_efi_handle_t *handle)
+{
+  grub_efi_device_path_t *dp, *ldp;
+
+  dp = grub_efi_get_device_path (handle);
+  if (! dp)
+    return 0;
+
+  ldp = find_last_device_path (dp);
+  if (! ldp)
+    return 0;
+
+  if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
+      && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)
+         == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
+    {
+      /* This is a hard disk partition.  */
+      grub_disk_t parent = 0;
+      char *partition_name = 0;
+      char *device_name;
+      grub_efi_device_path_t *dup_dp, *dup_ldp;
+      grub_efi_hard_drive_device_path_t hd;
+      auto int find_parent_disk (const char *name);
+      auto int find_partition (grub_disk_t disk, const grub_partition_t part);
+
+      /* Find the disk which is the parent of a given hard disk partition.  */
+      int find_parent_disk (const char *name)
+       {
+         grub_disk_t disk;
+
+         disk = grub_disk_open (name);
+         if (! disk)
+           return 1;
+
+         if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID)
+           {
+             struct grub_efidisk_data *d;
+             
+             d = disk->data;
+             if (compare_device_paths (d->device_path, dup_dp) == 0)
+               {
+                 parent = disk;
+                 return 1;
+               }
+           }
+
+         grub_disk_close (disk);
+         return 0;
+       }
+
+      /* Find the identical partition.  */
+      int find_partition (grub_disk_t disk __attribute__ ((unused)),
+                         const grub_partition_t part)
+       {
+         if (grub_partition_get_start (part) == hd.partition_start
+             && grub_partition_get_len (part) == hd.partition_size)
+           {
+             partition_name = grub_partition_get_name (part);
+             return 1;
+           }
+
+         return 0;
+       }
+
+      /* It is necessary to duplicate the device path so that GRUB
+        can overwrite it.  */
+      dup_dp = duplicate_device_path (dp);
+      if (! dup_dp)
+       return 0;
+
+      dup_ldp = find_last_device_path (dup_dp);
+      dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+      dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+      dup_ldp->length[0] = sizeof (*dup_ldp);
+      dup_ldp->length[1] = 0;
+
+      grub_efidisk_iterate (find_parent_disk);
+      grub_free (dup_dp);
+
+      if (! parent)
+       return 0;
+
+      /* Find a partition which matches the hard drive device path.  */
+      grub_memcpy (&hd, ldp, sizeof (hd));
+      grub_partition_iterate (parent, find_partition);
+      
+      if (! partition_name)
+       {
+         grub_disk_close (parent);
+         return 0;
+       }
+
+      device_name = grub_malloc (grub_strlen (parent->name) + 1
+                                + grub_strlen (partition_name) + 1);
+      if (! device_name)
+       {
+         grub_free (partition_name);
+         grub_disk_close (parent);
+         return 0;
+       }
+
+      grub_sprintf (device_name, "%s,%s", parent->name, partition_name);
+      grub_free (partition_name);
+      grub_disk_close (parent);
+      return device_name;
+    }
+  else
+    {
+      /* This should be an entire disk.  */
+      auto int find_disk (const char *name);
+      char *device_name = 0;
+      
+      int find_disk (const char *name)
+       {
+         grub_disk_t disk;
+         
+         disk = grub_disk_open (name);
+         if (! disk)
+           return 1;
+
+         if (disk->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;
+         
+       }
+      
+      grub_efidisk_iterate (find_disk);
+      return device_name;
+    }
+
+  return 0;
+}
diff --git a/disk/fs_uuid.c b/disk/fs_uuid.c
new file mode 100644 (file)
index 0000000..125d29b
--- /dev/null
@@ -0,0 +1,137 @@
+/* fs_uuid.c - Access disks by their filesystem UUID.  */
+/*
+ *  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/>.
+ */
+
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/kernel.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+
+#include <grub/fs.h>
+
+static grub_device_t
+search_fs_uuid (const char *key, unsigned long *count)
+{
+  *count = 0;
+  grub_device_t ret = NULL;
+
+  auto int iterate_device (const char *name);
+  int iterate_device (const char *name)
+    {
+      grub_device_t dev;
+
+      dev = grub_device_open (name);
+      if (dev)
+       {
+         grub_fs_t fs;
+         
+         fs = grub_fs_probe (dev);
+         if (fs && fs->uuid)
+           {
+             char *uuid;
+             
+             (fs->uuid) (dev, &uuid);
+             if (grub_errno == GRUB_ERR_NONE && uuid)
+               {
+                 (*count)++;
+
+                 if (grub_strcasecmp (uuid, key) == 0)
+                   {
+                     ret = dev;
+                     grub_free (uuid);
+                     return 1;
+                   }
+                 grub_free (uuid);
+               }
+           }
+         
+         grub_device_close (dev);
+       }
+
+      grub_errno = GRUB_ERR_NONE;
+      return 0;
+    }
+  
+  grub_device_iterate (iterate_device);
+  
+  return ret;
+}
+
+static grub_err_t
+grub_fs_uuid_open (const char *name, grub_disk_t disk)
+{
+  grub_device_t dev;
+
+  if (grub_strncmp (name, "UUID=", sizeof ("UUID=")-1))
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a UUID virtual volume");
+
+  dev = search_fs_uuid (name + sizeof ("UUID=") - 1, &disk->id);
+  if (! dev)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching UUID found");
+
+  disk->total_sectors = dev->disk->total_sectors;
+  disk->has_partitions = 0;
+  disk->partition = dev->disk->partition;
+  disk->data = dev->disk;
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_fs_uuid_close (grub_disk_t disk __attribute((unused)))
+{
+}
+
+static grub_err_t
+grub_fs_uuid_read (grub_disk_t disk, grub_disk_addr_t sector,
+                  grub_size_t size, char *buf)
+{
+  grub_disk_t parent = disk->data;
+  return parent->dev->read (parent, sector, size, buf);
+}
+
+static grub_err_t
+grub_fs_uuid_write (grub_disk_t disk, grub_disk_addr_t sector,
+                   grub_size_t size, const char *buf)
+{
+  grub_disk_t parent = disk->data;
+  return parent->dev->write (parent, sector, size, buf);
+}
+
+static struct grub_disk_dev grub_fs_uuid_dev =
+  {
+    .name = "fs_uuid",
+    .id = GRUB_DISK_DEVICE_UUID_ID,
+    .open = grub_fs_uuid_open,
+    .close = grub_fs_uuid_close,
+    .read = grub_fs_uuid_read,
+    .write = grub_fs_uuid_write,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(fs_uuid)
+{
+  grub_disk_dev_register (&grub_fs_uuid_dev);
+}
+
+GRUB_MOD_FINI(fs_uuid)
+{
+  grub_disk_dev_unregister (&grub_fs_uuid_dev);
+}
diff --git a/disk/host.c b/disk/host.c
new file mode 100644 (file)
index 0000000..bb8828a
--- /dev/null
@@ -0,0 +1,97 @@
+/* host.c - Dummy disk driver to provide access to the hosts filesystem  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+/* When using the disk, make a reference to this module.  Otherwise
+   the user will end up with a useless module :-).  */
+
+#include <grub/dl.h>
+#include <grub/disk.h>
+#include <grub/misc.h>
+
+int grub_disk_host_i_want_a_reference;
+
+static int
+grub_host_iterate (int (*hook) (const char *name))
+{
+  if (hook ("host"))
+    return 1;
+  return 0;
+}
+
+static grub_err_t
+grub_host_open (const char *name, grub_disk_t disk)
+{
+  if (grub_strcmp (name, "host"))
+      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a host disk");
+
+  disk->total_sectors = 0;
+  disk->id = (unsigned long) "host";
+  
+  disk->has_partitions = 0;
+  disk->data = 0;
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_host_close (grub_disk_t disk __attribute((unused)))
+{
+}
+
+static grub_err_t
+grub_host_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_host_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_host_dev =
+  {
+    /* The only important line in this file :-) */
+    .name = "host",
+    .id = GRUB_DISK_DEVICE_HOST_ID,
+    .iterate = grub_host_iterate,
+    .open = grub_host_open,
+    .close = grub_host_close,
+    .read = grub_host_read,
+    .write = grub_host_write,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(host)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_disk_dev_register (&grub_host_dev);
+}
+
+GRUB_MOD_FINI(host)
+{
+  grub_disk_dev_unregister (&grub_host_dev);
+}
diff --git a/disk/i386/pc/biosdisk.c b/disk/i386/pc/biosdisk.c
new file mode 100644 (file)
index 0000000..120d46f
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,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/>.
+ */
+
+#include <grub/machine/biosdisk.h>
+#include <grub/machine/memory.h>
+#include <grub/machine/kernel.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/term.h>
+
+static int cd_drive = 0;
+
+static int
+grub_biosdisk_get_drive (const char *name)
+{
+  unsigned long drive;
+
+  if ((name[0] != 'f' && name[0] != 'h') || name[1] != 'd')
+    goto fail;
+    
+  drive = grub_strtoul (name + 2, 0, 10);
+  if (grub_errno != GRUB_ERR_NONE)
+    goto fail;
+
+  if (name[0] == 'h')
+    drive += 0x80;
+  
+  return (int) drive ;
+
+ fail:
+  grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a biosdisk");
+  return -1;
+}
+
+static int
+grub_biosdisk_call_hook (int (*hook) (const char *name), int drive)
+{
+  char name[10];
+
+    grub_sprintf (name, (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
+  return hook (name);
+}
+
+static int
+grub_biosdisk_iterate (int (*hook) (const char *name))
+{
+  int drive;
+  int num_floppies;
+
+  /* For hard disks, attempt to read the MBR.  */
+  for (drive = 0x80; drive < 0x90; drive++)
+    {
+      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;
+    }
+
+  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;
+}
+
+static grub_err_t
+grub_biosdisk_open (const char *name, grub_disk_t disk)
+{
+  grub_uint64_t total_sectors = 0;
+  int drive;
+  struct grub_biosdisk_data *data;
+
+  drive = grub_biosdisk_get_drive (name);
+  if (drive < 0)
+    return grub_errno;
+
+  disk->has_partitions = ((drive & 0x80) && (drive != cd_drive));
+  disk->id = drive;
+  
+  data = (struct grub_biosdisk_data *) grub_malloc (sizeof (*data));
+  if (! data)
+    return grub_errno;
+  
+  data->drive = drive;
+  data->flags = 0;
+
+  if ((cd_drive) && (drive == cd_drive))
+    {
+      data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
+      data->sectors = 32;
+      total_sectors = ULONG_MAX;  /* TODO: get the correct size.  */
+    }
+  else if (drive & 0x80)
+    {
+      /* HDD */
+      int version;
+      
+      version = grub_biosdisk_check_int13_extensions (drive);
+      if (version)
+       {
+         struct grub_biosdisk_drp *drp
+           = (struct grub_biosdisk_drp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+
+         /* Clear out the DRP.  */
+         grub_memset (drp, 0, sizeof (*drp));
+         drp->size = sizeof (*drp);
+         if (! grub_biosdisk_get_diskinfo_int13_extensions (drive, drp))
+           {
+             data->flags = GRUB_BIOSDISK_FLAG_LBA;
+
+             if (drp->total_sectors)
+               total_sectors = drp->total_sectors;
+             else
+                /* Some buggy BIOSes doesn't return the total sectors
+                   correctly but returns zero. So if it is zero, compute
+                   it by C/H/S returned by the LBA BIOS call.  */
+                total_sectors = drp->cylinders * drp->heads * drp->sectors;
+           }
+       }
+    }
+
+  if (! (data->flags & GRUB_BIOSDISK_FLAG_CDROM))
+    {
+      if (grub_biosdisk_get_diskinfo_standard (drive,
+                                              &data->cylinders,
+                                              &data->heads,
+                                              &data->sectors) != 0)
+        {
+          grub_free (data);
+          return grub_error (GRUB_ERR_BAD_DEVICE, "cannot get C/H/S values");
+        }
+
+      if (! total_sectors)
+        total_sectors = data->cylinders * data->heads * data->sectors;
+    }
+
+  disk->total_sectors = total_sectors;
+  disk->data = data;
+  
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_biosdisk_close (grub_disk_t disk)
+{
+  grub_free (disk->data);
+}
+
+/* For readability.  */
+#define GRUB_BIOSDISK_READ     0
+#define GRUB_BIOSDISK_WRITE    1
+
+#define GRUB_BIOSDISK_CDROM_RETRY_COUNT 3
+
+static grub_err_t
+grub_biosdisk_rw (int cmd, grub_disk_t disk,
+                 grub_disk_addr_t sector, grub_size_t size,
+                 unsigned segment)
+{
+  struct grub_biosdisk_data *data = disk->data;
+  
+  if (data->flags & GRUB_BIOSDISK_FLAG_LBA)
+    {
+      struct grub_biosdisk_dap *dap;
+      
+      dap = (struct grub_biosdisk_dap *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR
+                                         + (data->sectors
+                                            << GRUB_DISK_SECTOR_BITS));
+      dap->length = sizeof (*dap);
+      dap->reserved = 0;
+      dap->blocks = size;
+      dap->buffer = segment << 16;     /* The format SEGMENT:ADDRESS.  */
+      dap->block = sector;
+
+      if (data->flags & GRUB_BIOSDISK_FLAG_CDROM)
+        {
+         int i;
+
+         if (cmd)
+           return grub_error (GRUB_ERR_WRITE_ERROR, "can\'t write to cdrom");
+
+         dap->blocks = (dap->blocks + 3) >> 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;
+
+         if (i == GRUB_BIOSDISK_CDROM_RETRY_COUNT)
+           return grub_error (GRUB_ERR_READ_ERROR, "cdrom read error");
+       }
+      else
+        if (grub_biosdisk_rw_int13_extensions (cmd + 0x42, data->drive, dap))
+         {
+           /* Fall back to the CHS mode.  */
+           data->flags &= ~GRUB_BIOSDISK_FLAG_LBA;
+           disk->total_sectors = data->cylinders * data->heads * data->sectors;
+           return grub_biosdisk_rw (cmd, disk, sector, size, segment);
+         }
+    }
+  else
+    {
+      unsigned coff, hoff, soff;
+      unsigned head;
+      
+      /* It is impossible to reach over 8064 MiB (a bit less than LBA24) with
+        the traditional CHS access.  */
+      if (sector >
+         1024 /* cylinders */ *
+         256 /* heads */ *
+         63 /* spt */)
+       return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of disk");
+
+      soff = ((grub_uint32_t) sector) % data->sectors + 1;
+      head = ((grub_uint32_t) sector) / data->sectors;
+      hoff = head % data->heads;
+      coff = head / data->heads;
+
+      if (coff >= data->cylinders)
+       return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of disk");
+
+      if (grub_biosdisk_rw_standard (cmd + 0x02, data->drive,
+                                    coff, hoff, soff, size, segment))
+       {
+         switch (cmd)
+           {
+           case GRUB_BIOSDISK_READ:
+             return grub_error (GRUB_ERR_READ_ERROR, "biosdisk read error");
+           case GRUB_BIOSDISK_WRITE:
+             return grub_error (GRUB_ERR_WRITE_ERROR, "biosdisk write error");
+           }
+       }
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+/* 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)
+{
+  grub_size_t size;
+  grub_uint32_t offset;
+
+  /* OFFSET = SECTOR % SECTORS */
+  grub_divmod64 (sector, sectors, &offset);
+
+  size = sectors - offset;
+
+  /* Limit the max to 0x7f because of Phoenix EDD.  */
+  if (size > 0x7f)
+    size = 0x7f;
+
+  return size;
+}
+
+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;
+
+      len = get_safe_sectors (sector, data->sectors);
+      if (len > size)
+       len = size;
+
+      if (grub_biosdisk_rw (GRUB_BIOSDISK_READ, disk, sector, len,
+                           GRUB_MEMORY_MACHINE_SCRATCH_SEG))
+       return grub_errno;
+
+      grub_memcpy (buf, (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR,
+                  len << GRUB_DISK_SECTOR_BITS);
+      buf += len << GRUB_DISK_SECTOR_BITS;
+      sector += len;
+      size -= len;
+    }
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
+                    grub_size_t size, const char *buf)
+{
+  struct grub_biosdisk_data *data = disk->data;
+
+  while (size)
+    {
+      grub_size_t len;
+
+      len = get_safe_sectors (sector, data->sectors);
+      if (len > size)
+       len = size;
+
+      grub_memcpy ((void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, buf,
+                  len << GRUB_DISK_SECTOR_BITS);
+
+      if (grub_biosdisk_rw (GRUB_BIOSDISK_WRITE, disk, sector, len,
+                           GRUB_MEMORY_MACHINE_SCRATCH_SEG))
+       return grub_errno;
+
+      buf += len << GRUB_DISK_SECTOR_BITS;
+      sector += len;
+      size -= len;
+    }
+
+  return grub_errno;
+}
+
+static struct grub_disk_dev grub_biosdisk_dev =
+  {
+    .name = "biosdisk",
+    .id = GRUB_DISK_DEVICE_BIOSDISK_ID,
+    .iterate = grub_biosdisk_iterate,
+    .open = grub_biosdisk_open,
+    .close = grub_biosdisk_close,
+    .read = grub_biosdisk_read,
+    .write = grub_biosdisk_write,
+    .next = 0
+  };
+
+static void
+grub_disk_biosdisk_fini (void)
+{
+  grub_disk_dev_unregister (&grub_biosdisk_dev);
+}
+
+GRUB_MOD_INIT(biosdisk)
+{
+  struct grub_biosdisk_cdrp *cdrp
+        = (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+
+  if (grub_disk_firmware_is_tainted)
+    {
+      grub_printf ("Firmware is marked as tainted, refusing to initialize.\n");
+      return;
+    }
+  grub_disk_firmware_fini = grub_disk_biosdisk_fini;
+
+  grub_memset (cdrp, 0, sizeof (*cdrp));
+  cdrp->size = sizeof (*cdrp);
+  cdrp->media_type = 0xFF;
+  if ((! grub_biosdisk_get_cdinfo_int13_extensions (grub_boot_drive, cdrp)) &&
+      ((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK)
+       == GRUB_BIOSDISK_CDTYPE_NO_EMUL))
+    cd_drive = cdrp->drive_no;
+
+  grub_disk_dev_register (&grub_biosdisk_dev);
+}
+
+GRUB_MOD_FINI(biosdisk)
+{
+  grub_disk_biosdisk_fini ();
+}
diff --git a/disk/ieee1275/nand.c b/disk/ieee1275/nand.c
new file mode 100644 (file)
index 0000000..ba79faa
--- /dev/null
@@ -0,0 +1,216 @@
+/* nand.c - NAND flash disk access.  */
+/*
+ *  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/misc.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+#include <grub/dl.h>
+#include <grub/ieee1275/ieee1275.h>
+
+struct grub_nand_data
+{
+  grub_ieee1275_ihandle_t handle;
+  grub_uint32_t block_size;
+};
+
+static int
+grub_nand_iterate (int (*hook) (const char *name))
+{
+  auto int dev_iterate (struct grub_ieee1275_devalias *alias);
+  int dev_iterate (struct grub_ieee1275_devalias *alias)
+    {
+      if (! grub_strcmp (alias->name, "nand"))
+        {
+          hook (alias->name);
+          return 1;
+        }
+
+      return 0;
+    }
+
+  grub_devalias_iterate (dev_iterate);
+  return 0;
+}
+
+static grub_err_t
+grub_nand_read (grub_disk_t disk, grub_disk_addr_t sector,
+                grub_size_t size, char *buf);
+
+static grub_err_t
+grub_nand_open (const char *name, grub_disk_t disk)
+{
+  grub_ieee1275_ihandle_t dev_ihandle = 0;
+  struct grub_nand_data *data = 0;
+  struct size_args
+    {
+      struct grub_ieee1275_common_hdr common;
+      char *method;
+      grub_ieee1275_ihandle_t ihandle;
+      grub_ieee1275_cell_t result;
+      grub_ieee1275_cell_t size1;
+      grub_ieee1275_cell_t size2;
+    } args;
+
+  if (! grub_strstr (name, "nand"))
+    return  grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Not a nand device");
+
+  data = grub_malloc (sizeof (*data));
+  if (! data)
+    goto fail;
+
+  grub_ieee1275_open (name, &dev_ihandle);
+  if (! dev_ihandle)
+    {
+      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't open device");
+      goto fail;
+    }
+
+  data->handle = dev_ihandle;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 2);
+  args.method = "block-size";
+  args.ihandle = dev_ihandle;
+  args.result = 1;
+
+  if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.result))
+    {
+      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't get block size");
+      goto fail;
+    }
+
+  data->block_size = (args.size1 >> GRUB_DISK_SECTOR_BITS);
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3);
+  args.method = "size";
+  args.ihandle = dev_ihandle;
+  args.result = 1;
+
+  if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.result))
+    {
+      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't get disk size");
+      goto fail;
+    }
+
+  disk->total_sectors = args.size1;
+  disk->total_sectors <<= 32;
+  disk->total_sectors += args.size2;
+  disk->total_sectors >>= GRUB_DISK_SECTOR_BITS;
+
+  disk->id = dev_ihandle;
+
+  disk->has_partitions = 0;
+  disk->data = data;
+
+  return 0;
+
+fail:
+  if (dev_ihandle)
+    grub_ieee1275_close (dev_ihandle);
+  grub_free (data);
+  return grub_errno;
+}
+
+static void
+grub_nand_close (grub_disk_t disk)
+{
+  grub_ieee1275_close (((struct grub_nand_data *) disk->data)->handle);
+  grub_free (disk->data);
+}
+
+static grub_err_t
+grub_nand_read (grub_disk_t disk, grub_disk_addr_t sector,
+                grub_size_t size, char *buf)
+{
+  struct grub_nand_data *data = disk->data;
+  grub_size_t bsize, ofs;
+
+  struct read_args
+    {
+      struct grub_ieee1275_common_hdr common;
+      char *method;
+      grub_ieee1275_ihandle_t ihandle;
+      grub_ieee1275_cell_t ofs;
+      grub_ieee1275_cell_t page;
+      grub_ieee1275_cell_t len;
+      grub_ieee1275_cell_t buf;
+      grub_ieee1275_cell_t result;
+    } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1);
+  args.method = "pio-read";
+  args.ihandle = data->handle;
+  args.buf = (grub_ieee1275_cell_t) buf;
+  args.page = (grub_ieee1275_cell_t) ((grub_size_t) sector / data->block_size);
+
+  ofs = ((grub_size_t) sector % data->block_size) << GRUB_DISK_SECTOR_BITS;
+  size <<= GRUB_DISK_SECTOR_BITS;
+  bsize = (data->block_size << GRUB_DISK_SECTOR_BITS);
+
+  do
+    {
+      grub_size_t len;
+
+      len = (ofs + size > bsize) ? (bsize - ofs) : size;
+
+      args.len = (grub_ieee1275_cell_t) len;
+      args.ofs = (grub_ieee1275_cell_t) ofs;
+      args.result = 1;
+
+      if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.result))
+        return grub_error (GRUB_ERR_READ_ERROR, "Read error");
+
+      ofs = 0;
+      size -= len;
+      args.buf += len;
+      args.page++;
+    } while (size);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_nand_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_nand_dev =
+  {
+    .name = "nand",
+    .id = GRUB_DISK_DEVICE_NAND_ID,
+    .iterate = grub_nand_iterate,
+    .open = grub_nand_open,
+    .close = grub_nand_close,
+    .read = grub_nand_read,
+    .write = grub_nand_write,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(nand)
+{
+  grub_disk_dev_register (&grub_nand_dev);
+}
+
+GRUB_MOD_FINI(nand)
+{
+  grub_disk_dev_unregister (&grub_nand_dev);
+}
diff --git a/disk/ieee1275/ofdisk.c b/disk/ieee1275/ofdisk.c
new file mode 100644 (file)
index 0000000..fec56be
--- /dev/null
@@ -0,0 +1,211 @@
+/* ofdisk.c - Open Firmware disk access.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,2006,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/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/ieee1275/ofdisk.h>
+
+static int
+grub_ofdisk_iterate (int (*hook) (const char *name))
+{
+  auto int dev_iterate (struct grub_ieee1275_devalias *alias);
+
+  int dev_iterate (struct grub_ieee1275_devalias *alias)
+    {
+      grub_dprintf ("disk", "disk name = %s\n", alias->name);
+
+      if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY))
+       {
+         grub_ieee1275_phandle_t dev;
+         char tmp[8];
+
+         if (grub_ieee1275_finddevice (alias->path, &dev))
+           {
+             grub_dprintf ("disk", "finddevice (%s) failed\n", alias->path);
+             return 0;
+           }
+
+         if (grub_ieee1275_get_property (dev, "iconname", tmp,
+                                         sizeof tmp, 0))
+           {
+             grub_dprintf ("disk", "get iconname failed\n");
+             return 0;
+           }
+
+         if (grub_strcmp (tmp, "sdmmc"))
+           {
+             grub_dprintf ("disk", "device is not an SD card\n");
+             return 0;
+           }
+       }
+
+      if (! grub_strcmp (alias->type, "block"))
+       hook (alias->name);
+      else if ((! grub_strcmp (alias->type, "scsi"))
+              || (! grub_strcmp (alias->type, "ide"))
+              || (! grub_strcmp (alias->type, "ata")))
+       /* Search for block-type children of these bus controllers.  */
+       grub_children_iterate (alias->name, dev_iterate);
+      return 0;
+    }
+
+  grub_devalias_iterate (dev_iterate);
+  return 0;
+}
+
+static grub_err_t
+grub_ofdisk_open (const char *name, grub_disk_t disk)
+{
+  grub_ieee1275_phandle_t dev;
+  grub_ieee1275_ihandle_t dev_ihandle = 0;
+  char *devpath;
+  /* XXX: This should be large enough for any possible case.  */
+  char prop[64];
+  grub_ssize_t actual;
+
+  devpath = grub_strndup (name, grub_strlen (name) + 2);
+  if (! devpath)
+    return grub_errno;
+
+  /* To access the complete disk add `:0'.  */
+  if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0))
+    grub_strcat (devpath, ":0");
+
+  grub_dprintf ("disk", "Opening `%s'.\n", devpath);
+
+  grub_ieee1275_open (devpath, &dev_ihandle);
+  if (! dev_ihandle)
+    {
+      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't open device");
+      goto fail;
+    }
+
+  grub_dprintf ("disk", "Opened `%s' as handle %p.\n", devpath, (void *) dev_ihandle);
+
+  if (grub_ieee1275_finddevice (devpath, &dev))
+    {
+      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't read device properties");
+      goto fail;
+    }
+
+  if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop),
+                                 &actual))
+    {
+      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't read the device type");
+      goto fail;
+    }
+
+  if (grub_strcmp (prop, "block"))
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, "Not a block device");
+      goto fail;
+    }
+
+  /* XXX: There is no property to read the number of blocks.  There
+     should be a property `#blocks', but it is not there.  Perhaps it
+     is possible to use seek for this.  */
+  disk->total_sectors = 0xFFFFFFFFUL;
+
+  /* XXX: Is it ok to use this?  Perhaps it is better to use the path
+     or some property.  */
+  disk->id = dev;
+
+  /* XXX: Read this, somehow.  */
+  disk->has_partitions = 1;
+  disk->data = (void *) dev_ihandle;
+  grub_free (devpath);
+  return 0;
+
+ fail:
+  if (dev_ihandle)
+    grub_ieee1275_close (dev_ihandle);
+  grub_free (devpath);
+  return grub_errno;
+}
+
+static void
+grub_ofdisk_close (grub_disk_t disk)
+{
+  grub_dprintf ("disk", "Closing handle %p.\n",
+               (void *) disk->data);
+  grub_ieee1275_close ((grub_ieee1275_ihandle_t) disk->data);
+}
+
+static grub_err_t
+grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
+                 grub_size_t size, char *buf)
+{
+  grub_ssize_t status, actual;
+  unsigned long long pos;
+
+  grub_dprintf ("disk",
+               "Reading handle %p: sector 0x%llx, size 0x%lx, buf %p.\n",
+               (void *) disk->data, sector, (long) size, buf);
+
+  pos = sector * 512UL;
+
+  grub_ieee1275_seek ((grub_ieee1275_ihandle_t) disk->data, (int) (pos >> 32),
+                     (int) pos & 0xFFFFFFFFUL, &status);
+  if (status < 0)
+    return grub_error (GRUB_ERR_READ_ERROR,
+                      "Seek error, can't seek block %llu",
+                      sector);
+  grub_ieee1275_read ((grub_ieee1275_ihandle_t) disk->data, buf,
+                     size * 512UL, &actual);
+  if (actual != actual)
+    return grub_error (GRUB_ERR_READ_ERROR, "Read error on block: %llu",
+                      sector);
+    
+  return 0;
+}
+
+static grub_err_t
+grub_ofdisk_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_ofdisk_dev =
+  {
+    .name = "ofdisk",
+    .id = GRUB_DISK_DEVICE_OFDISK_ID,
+    .iterate = grub_ofdisk_iterate,
+    .open = grub_ofdisk_open,
+    .close = grub_ofdisk_close,
+    .read = grub_ofdisk_read,
+    .write = grub_ofdisk_write,
+    .next = 0
+  };
+
+void
+grub_ofdisk_init (void)
+{
+  grub_disk_dev_register (&grub_ofdisk_dev);
+}
+
+void
+grub_ofdisk_fini (void)
+{
+  grub_disk_dev_unregister (&grub_ofdisk_dev);
+}
diff --git a/disk/loopback.c b/disk/loopback.c
new file mode 100644 (file)
index 0000000..709c422
--- /dev/null
@@ -0,0 +1,258 @@
+/* loopback.c - command to add loopback devices.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/misc.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+
+struct grub_loopback
+{
+  char *devname;
+  char *filename;
+  int has_partitions;
+  struct grub_loopback *next;
+};
+
+static struct grub_loopback *loopback_list; 
+
+static const struct grub_arg_option options[] =
+  {
+    {"delete", 'd', 0, "delete the loopback device entry", 0, 0},
+    {"partitions", 'p', 0, "simulate a hard drive with partitions", 0, 0},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+/* Delete the loopback device NAME.  */
+static grub_err_t
+delete_loopback (const char *name)
+{
+  struct grub_loopback *dev;
+  struct grub_loopback **prev;
+
+  /* Search for the device.  */
+  for (dev = loopback_list, prev = &loopback_list;
+       dev;
+       prev = &dev->next, dev = dev->next)
+    if (grub_strcmp (dev->devname, name) == 0)
+      break;
+  
+  if (! dev)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "Device not found");
+  
+  /* Remove the device from the list.  */
+  *prev = dev->next;
+
+  grub_free (dev->devname);
+  grub_free (dev->filename);
+  grub_free (dev);
+  
+  return 0;
+}
+
+/* The command to add and remove loopback devices.  */
+static grub_err_t
+grub_cmd_loopback (struct grub_arg_list *state,
+                  int argc, char **args)
+{
+  grub_file_t file;
+  struct grub_loopback *newdev;
+  
+  if (argc < 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
+  
+  /* Check if `-d' was used.  */
+  if (state[0].set)
+      return delete_loopback (args[0]);
+  
+  if (argc < 2)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
+
+  file = grub_file_open (args[1]);
+  if (! file)
+    return grub_errno;
+  
+  /* Close the file, the only reason for opening it is validation.  */
+  grub_file_close (file);
+  
+  /* First try to replace the old device.  */
+  for (newdev = loopback_list; newdev; newdev = newdev->next)
+    if (grub_strcmp (newdev->devname, args[0]) == 0)
+      break;
+  
+  if (newdev)
+    {
+      char *newname = grub_strdup (args[1]);
+      if (! newname)
+       return grub_errno;
+      
+      grub_free (newdev->filename);
+      newdev->filename = newname;
+      
+      /* Set has_partitions when `--partitions' was used.  */
+      newdev->has_partitions = state[1].set;
+      
+      return 0;
+    }
+  
+  /* Unable to replace it, make a new entry.  */
+  newdev = grub_malloc (sizeof (struct grub_loopback));
+  if (! newdev)
+    return grub_errno;
+  
+  newdev->devname = grub_strdup (args[0]);
+  if (! newdev->devname)
+    {
+      grub_free (newdev);
+      return grub_errno;
+    }
+  
+  newdev->filename = grub_strdup (args[1]);
+  if (! newdev->filename)
+    {
+      grub_free (newdev->devname);
+      grub_free (newdev);
+      return grub_errno;
+    }
+  
+  /* Set has_partitions when `--partitions' was used.  */
+  newdev->has_partitions = state[1].set;
+  
+  /* Add the new entry to the list.  */
+  newdev->next = loopback_list;
+  loopback_list = newdev;
+  
+  return 0;
+}
+
+\f
+static int
+grub_loopback_iterate (int (*hook) (const char *name))
+{
+  struct grub_loopback *d;
+  for (d = loopback_list; d; d = d->next)
+    {
+      if (hook (d->devname))
+       return 1;
+    }
+  return 0;
+}
+
+static grub_err_t
+grub_loopback_open (const char *name, grub_disk_t disk)
+{
+  grub_file_t file;
+  struct grub_loopback *dev;
+    
+  for (dev = loopback_list; dev; dev = dev->next)
+    if (grub_strcmp (dev->devname, name) == 0)
+      break;
+  
+  if (! dev)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't open device");
+
+  file = grub_file_open (dev->filename);
+  if (! file)
+    return grub_errno;
+  
+  /* Use the filesize for the disk size, round up to a complete sector.  */
+  disk->total_sectors = ((file->size + GRUB_DISK_SECTOR_SIZE - 1)
+                        / GRUB_DISK_SECTOR_SIZE);
+  disk->id = (unsigned long) dev;
+  
+  disk->has_partitions = dev->has_partitions;
+  disk->data = file;
+  
+  return 0;
+}
+
+static void
+grub_loopback_close (grub_disk_t disk)
+{
+  grub_file_t file = (grub_file_t) disk->data;
+  
+  grub_file_close (file);
+}
+
+static grub_err_t
+grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector,
+                   grub_size_t size, char *buf)
+{
+  grub_file_t file = (grub_file_t) disk->data;
+  grub_off_t pos;
+  
+  grub_file_seek (file, sector << GRUB_DISK_SECTOR_BITS);
+  
+  grub_file_read (file, buf, size << GRUB_DISK_SECTOR_BITS);
+  if (grub_errno)
+    return grub_errno;
+  
+  /* In case there is more data read than there is available, in case
+     of files that are not a multiple of GRUB_DISK_SECTOR_SIZE, fill
+     the rest with zeros.  */
+  pos = (sector + size) << GRUB_DISK_SECTOR_BITS;
+  if (pos > file->size)
+    {
+      grub_size_t amount = pos - file->size;
+      grub_memset (buf + (size << GRUB_DISK_SECTOR_BITS) - amount, 0, amount);
+    }
+  
+  return 0;
+}
+
+static grub_err_t
+grub_loopback_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_loopback_dev =
+  {
+    .name = "loopback",
+    .id = GRUB_DISK_DEVICE_LOOPBACK_ID,
+    .iterate = grub_loopback_iterate,
+    .open = grub_loopback_open,
+    .close = grub_loopback_close,
+    .read = grub_loopback_read,
+    .write = grub_loopback_write,
+    .next = 0
+  };
+
+\f
+
+GRUB_MOD_INIT(loop)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("loopback", grub_cmd_loopback, GRUB_COMMAND_FLAG_BOTH,
+                        "loopback [-d|-p] DEVICENAME FILE",
+                        "Make a device of a file.", options);
+  grub_disk_dev_register (&grub_loopback_dev);
+}
+
+GRUB_MOD_FINI(loop)
+{
+  grub_unregister_command ("loopback");
+  grub_disk_dev_unregister (&grub_loopback_dev);
+}
diff --git a/disk/lvm.c b/disk/lvm.c
new file mode 100644 (file)
index 0000000..6ebde63
--- /dev/null
@@ -0,0 +1,619 @@
+/* lvm.c - module to read Logical Volumes.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/lvm.h>
+
+static struct grub_lvm_vg *vg_list;
+static int lv_count;
+
+\f
+/* Go the string STR and return the number after STR.  *P will point
+   at the number.  In case STR is not found, *P will be NULL and the
+   return value will be 0.  */
+static int
+grub_lvm_getvalue (char **p, char *str)
+{
+  *p = grub_strstr (*p, str);
+  if (! *p)
+    return 0;
+  *p += grub_strlen (str);
+  return grub_strtoul (*p, NULL, 10);
+}
+
+static int
+grub_lvm_iterate (int (*hook) (const char *name))
+{
+  struct grub_lvm_vg *vg;
+  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 (hook (lv->name))
+           return 1;
+    }
+
+  return 0;
+}
+
+#ifdef GRUB_UTIL
+static grub_disk_memberlist_t
+grub_lvm_memberlist (grub_disk_t disk)
+{
+  struct grub_lvm_lv *lv = disk->data;
+  grub_disk_memberlist_t list = NULL, tmp;
+  struct grub_lvm_pv *pv;
+
+  if (lv->vg->pvs)
+    for (pv = lv->vg->pvs; pv; pv = pv->next)
+      {
+       tmp = grub_malloc (sizeof (*tmp));
+       tmp->disk = pv->disk;
+       tmp->next = list;
+       list = tmp;
+      }
+
+  return list;
+}
+#endif
+
+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;
+
+      if (lv)
+       break;
+    }
+
+  if (! lv)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Unknown LVM device %s", name);
+
+  disk->has_partitions = 0;
+  disk->id = lv->number;
+  disk->data = lv;
+  disk->total_sectors = lv->size;
+  
+  return 0;
+}
+
+static void
+grub_lvm_close (grub_disk_t disk __attribute ((unused)))
+{
+  return;
+}
+
+static grub_err_t
+grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
+               grub_size_t size, char *buf)
+{
+  grub_err_t err = 0;
+  struct grub_lvm_lv *lv = disk->data;
+  struct grub_lvm_vg *vg = lv->vg;
+  struct grub_lvm_segment *seg = lv->segments;
+  struct grub_lvm_pv *pv;
+  grub_uint64_t offset;
+  grub_uint64_t extent;
+  unsigned int i;
+
+  extent = grub_divmod64 (sector, vg->extent_size, NULL);
+
+  /* Find the right segment.  */
+  for (i = 0; i < lv->segment_count; i++)
+    {
+      if ((seg->start_extent <= extent)
+         && ((seg->start_extent + seg->extent_count) > extent))
+       {
+         break;
+       }
+
+      seg++;
+    }
+
+  if (seg->stripe_count == 1)
+    {
+      /* This segment is linear, so that's easy.  We just need to find
+        out the offset in the physical volume and read SIZE bytes
+        from that.  */
+      struct grub_lvm_stripe *stripe = seg->stripes;
+      grub_uint64_t seg_offset; /* Offset of the segment in PV device.  */
+
+      pv = stripe->pv;
+      seg_offset = ((grub_uint64_t) stripe->start
+                   * (grub_uint64_t) vg->extent_size) + pv->start;
+
+      offset = sector - ((grub_uint64_t) seg->start_extent
+                        * (grub_uint64_t) vg->extent_size) + seg_offset;
+    }
+  else
+    {
+      /* This is a striped segment. We have to find the right PV
+        similar to RAID0. */
+      struct grub_lvm_stripe *stripe = seg->stripes;
+      grub_uint32_t a, b;
+      grub_uint64_t seg_offset; /* Offset of the segment in PV device.  */
+      unsigned int stripenr;
+
+      offset = sector - ((grub_uint64_t) seg->start_extent
+                        * (grub_uint64_t) vg->extent_size);
+
+      a = grub_divmod64 (offset, seg->stripe_size, NULL);
+      grub_divmod64 (a, seg->stripe_count, &stripenr);
+
+      a = grub_divmod64 (offset, seg->stripe_size * seg->stripe_count, NULL);
+      grub_divmod64 (offset, seg->stripe_size, &b);
+      offset = a * seg->stripe_size + b;
+
+      stripe += stripenr;
+      pv = stripe->pv;
+      
+      seg_offset = ((grub_uint64_t) stripe->start
+                   * (grub_uint64_t) vg->extent_size) + pv->start;
+
+      offset += seg_offset;
+    }
+
+  /* Check whether we actually know the physical volume we want to
+     read from.  */
+  if (pv->disk)
+    err = grub_disk_read (pv->disk, offset, 0,
+                         size << GRUB_DISK_SECTOR_BITS, buf);
+  else
+    err = grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                     "Physical volume %s not found", pv->name);
+  
+  return err;
+}
+
+static grub_err_t
+grub_lvm_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 int
+grub_lvm_scan_device (const char *name)
+{
+  grub_err_t err;
+  grub_disk_t disk;
+  grub_uint64_t da_offset, da_size, 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;
+  
+  disk = grub_disk_open (name);
+  if (!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)
+    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;
+  da_offset = grub_le_to_cpu64 (dlocn->offset);
+  da_size = grub_le_to_cpu64 (dlocn->size);
+
+  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 data areas");
+                 
+      goto fail;
+    }
+
+  dlocn++;
+  mda_offset = grub_le_to_cpu64 (dlocn->offset);
+  mda_size = grub_le_to_cpu64 (dlocn->size);
+  dlocn++;
+  
+  if (dlocn->offset)
+    {
+      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                 "We don't support multiple metadata areas");
+                 
+      goto fail;
+    }
+
+  /* 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 metadata header");
+      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)
+    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)
+    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)
+       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)
+               goto pvs_fail;
+             
+             p = grub_strchr (p, '}');
+             if (p == NULL)
+               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;
+             struct grub_lvm_lv *lv;
+             struct grub_lvm_segment *seg;
+             
+             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->segment_count = grub_lvm_getvalue (&p, "segment_count = ");
+             if (p == NULL)
+               goto lvs_fail;
+             lv->segments = grub_malloc (sizeof (*seg) * lv->segment_count);
+             seg = lv->segments;
+             
+             for (i = 0; i < lv->segment_count; i++)
+               {
+                 struct grub_lvm_stripe *stripe;
+                 
+                 p = grub_strstr (p, "segment");
+                 if (p == NULL)
+                   goto lvs_segment_fail;
+                 
+                 seg->start_extent = grub_lvm_getvalue (&p, "start_extent = ");
+                 if (p == NULL)
+                   goto lvs_segment_fail;
+                 seg->extent_count = grub_lvm_getvalue (&p, "extent_count = ");
+                 if (p == NULL)
+                   goto lvs_segment_fail;
+                 seg->stripe_count = grub_lvm_getvalue (&p, "stripe_count = ");
+                 if (p == NULL)
+                   goto lvs_segment_fail;
+                 
+                 lv->size += seg->extent_count * vg->extent_size;
+                 
+                 if (seg->stripe_count != 1)
+                   seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
+                 
+                 seg->stripes = grub_malloc (sizeof (*stripe)
+                                             * seg->stripe_count);
+                 stripe = seg->stripes;
+                 
+                 p = grub_strstr (p, "stripes = [");
+                 if (p == NULL)
+                   goto lvs_segment_fail2;
+                 p += sizeof("stripes = [") - 1;
+                 
+                 for (j = 0; j < seg->stripe_count; j++)
+                   {
+                     char *pvname;
+                     
+                     p = grub_strchr (p, '"');
+                     if (p == NULL)
+                       continue;
+                     q = ++p;
+                     while (*q != '"')
+                       q++;
+
+                     s = q - p;
+                     
+                     pvname = grub_malloc (s + 1);
+                      if (pvname == NULL)
+                        goto lvs_segment_fail2;
+                      
+                     grub_memcpy (pvname, p, s);
+                     pvname[s] = '\0';
+                     
+                     if (vg->pvs)
+                       for (pv = vg->pvs; pv; pv = pv->next)
+                         {
+                           if (! grub_strcmp (pvname, pv->name))
+                             {
+                               stripe->pv = pv;
+                               break;
+                             }
+                         }
+                     
+                     grub_free(pvname);
+                     
+                     stripe->start = grub_lvm_getvalue (&p, ",");
+                     if (p == NULL)
+                       continue;
+                     
+                     stripe++;
+                   }
+                 
+                 seg++;
+
+                 continue;
+               lvs_segment_fail2:
+                 grub_free (seg->stripes);
+               lvs_segment_fail:
+                 goto fail4;
+               }
+
+             p = grub_strchr (p, '}');
+             if (p == NULL)
+               goto lvs_fail;
+             p += 3;
+             
+             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;
+           }
+       }
+
+       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))
+         {
+           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);
+  return 0;
+}
+
+static struct grub_disk_dev grub_lvm_dev =
+  {
+    .name = "lvm",
+    .id = GRUB_DISK_DEVICE_LVM_ID,
+    .iterate = grub_lvm_iterate,
+    .open = grub_lvm_open,
+    .close = grub_lvm_close,
+    .read = grub_lvm_read,
+    .write = grub_lvm_write,
+#ifdef GRUB_UTIL
+    .memberlist = grub_lvm_memberlist,
+#endif
+    .next = 0
+  };
+
+\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);
+}
+
+GRUB_MOD_FINI(lvm)
+{
+  grub_disk_dev_unregister (&grub_lvm_dev);
+  /* FIXME: free the lvm list. */
+}
diff --git a/disk/mdraid_linux.c b/disk/mdraid_linux.c
new file mode 100644 (file)
index 0000000..f5eb84c
--- /dev/null
@@ -0,0 +1,233 @@
+/* mdraid_linux.c - module to handle linux softraid.  */
+/*
+ *  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/dl.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/raid.h>
+
+/* Linux RAID on disk structures and constants,
+   copied from include/linux/raid/md_p.h.  */
+
+#define RESERVED_BYTES                 (64 * 1024)
+#define RESERVED_SECTORS               (RESERVED_BYTES / 512)
+
+#define NEW_SIZE_SECTORS(x)            ((x & ~(RESERVED_SECTORS - 1)) \
+                                       - RESERVED_SECTORS)
+
+#define SB_BYTES                       4096
+#define SB_WORDS                       (SB_BYTES / 4)
+#define SB_SECTORS                     (SB_BYTES / 512)
+
+/*
+ * The following are counted in 32-bit words
+ */
+#define        SB_GENERIC_OFFSET               0
+
+#define SB_PERSONALITY_OFFSET          64
+#define SB_DISKS_OFFSET                        128
+#define SB_DESCRIPTOR_OFFSET           992
+
+#define SB_GENERIC_CONSTANT_WORDS      32
+#define SB_GENERIC_STATE_WORDS         32
+#define SB_GENERIC_WORDS               (SB_GENERIC_CONSTANT_WORDS + \
+                                         SB_GENERIC_STATE_WORDS)
+
+#define SB_PERSONALITY_WORDS           64
+#define SB_DESCRIPTOR_WORDS            32
+#define SB_DISKS                       27
+#define SB_DISKS_WORDS                 (SB_DISKS * SB_DESCRIPTOR_WORDS)
+
+#define SB_RESERVED_WORDS              (1024 \
+                                         - SB_GENERIC_WORDS \
+                                         - SB_PERSONALITY_WORDS \
+                                         - SB_DISKS_WORDS \
+                                         - SB_DESCRIPTOR_WORDS)
+
+#define SB_EQUAL_WORDS                 (SB_GENERIC_WORDS \
+                                         + SB_PERSONALITY_WORDS \
+                                         + SB_DISKS_WORDS)
+
+/*
+ * Device "operational" state bits
+ */
+#define DISK_FAULTY                    0
+#define DISK_ACTIVE                    1
+#define DISK_SYNC                      2
+#define DISK_REMOVED                   3
+
+#define        DISK_WRITEMOSTLY                9
+
+#define SB_MAGIC                       0xa92b4efc
+
+/*
+ * Superblock state bits
+ */
+#define SB_CLEAN                       0
+#define SB_ERRORS                      1
+
+#define        SB_BITMAP_PRESENT               8
+
+struct grub_raid_disk_09
+{
+  grub_uint32_t number;                /* Device number in the entire set.  */
+  grub_uint32_t major;         /* Device major number.  */
+  grub_uint32_t minor;         /* Device minor number.  */
+  grub_uint32_t raid_disk;     /* The role of the device in the raid set.  */
+  grub_uint32_t state;         /* Operational state.  */
+  grub_uint32_t reserved[SB_DESCRIPTOR_WORDS - 5];
+};
+
+struct grub_raid_super_09
+{
+  /*
+   * Constant generic information
+   */
+  grub_uint32_t md_magic;      /* MD identifier.  */
+  grub_uint32_t major_version; /* Major version.  */
+  grub_uint32_t minor_version; /* Minor version.  */
+  grub_uint32_t patch_version; /* Patchlevel version.  */
+  grub_uint32_t gvalid_words;  /* Number of used words in this section.  */
+  grub_uint32_t set_uuid0;     /* Raid set identifier.  */
+  grub_uint32_t ctime;         /* Creation time.  */
+  grub_uint32_t level;         /* Raid personality.  */
+  grub_uint32_t size;          /* Apparent size of each individual disk.  */
+  grub_uint32_t nr_disks;      /* Total disks in the raid set.  */
+  grub_uint32_t raid_disks;    /* Disks in a fully functional raid set.  */
+  grub_uint32_t md_minor;      /* Preferred MD minor device number.  */
+  grub_uint32_t not_persistent;        /* Does it have a persistent superblock.  */
+  grub_uint32_t set_uuid1;     /* Raid set identifier #2.  */
+  grub_uint32_t set_uuid2;     /* Raid set identifier #3.  */
+  grub_uint32_t set_uuid3;     /* Raid set identifier #4.  */
+  grub_uint32_t gstate_creserved[SB_GENERIC_CONSTANT_WORDS - 16];
+
+  /*
+   * Generic state information
+   */
+  grub_uint32_t utime;         /* Superblock update time.  */
+  grub_uint32_t state;         /* State bits (clean, ...).  */
+  grub_uint32_t active_disks;  /* Number of currently active disks.  */
+  grub_uint32_t working_disks; /* Number of working disks.  */
+  grub_uint32_t failed_disks;  /* Number of failed disks.  */
+  grub_uint32_t spare_disks;   /* Number of spare disks.  */
+  grub_uint32_t sb_csum;       /* Checksum of the whole superblock.  */
+  grub_uint64_t events;                /* Superblock update count.  */
+  grub_uint64_t cp_events;     /* Checkpoint update count.  */
+  grub_uint32_t recovery_cp;   /* Recovery checkpoint sector count.  */
+  grub_uint32_t gstate_sreserved[SB_GENERIC_STATE_WORDS - 12];
+
+  /*
+   * Personality information
+   */
+  grub_uint32_t layout;                /* The array's physical layout.  */
+  grub_uint32_t chunk_size;    /* Chunk size in bytes.  */
+  grub_uint32_t root_pv;       /* LV root PV.  */
+  grub_uint32_t root_block;    /* LV root block.  */
+  grub_uint32_t pstate_reserved[SB_PERSONALITY_WORDS - 4];
+
+  /*
+   * Disks information
+   */
+  struct grub_raid_disk_09 disks[SB_DISKS];
+
+  /*
+   * Reserved
+   */
+  grub_uint32_t reserved[SB_RESERVED_WORDS];
+
+  /*
+   * Active descriptor
+   */
+  struct grub_raid_disk_09 this_disk;
+} __attribute__ ((packed));
+
+static grub_err_t
+grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array)
+{
+  grub_disk_addr_t sector;
+  grub_uint64_t size;
+  struct grub_raid_super_09 sb;
+  grub_uint32_t *uuid;
+
+  /* The sector where the RAID superblock is stored, if available. */
+  size = grub_disk_get_size (disk);
+  sector = NEW_SIZE_SECTORS (size);
+
+  if (grub_disk_read (disk, sector, 0, SB_BYTES, (char *) &sb))
+    return grub_errno;
+
+  /* Look whether there is a RAID superblock. */
+  if (sb.md_magic != SB_MAGIC)
+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
+
+  /* FIXME: Also support version 1.0. */
+  if (sb.major_version != 0 || sb.minor_version != 90)
+    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                      "Unsupported RAID version: %d.%d",
+                      sb.major_version, sb.minor_version);
+
+  /* FIXME: Check the checksum. */
+
+  /* Multipath.  */
+  if ((int) sb.level == -4)
+    sb.level = 1;
+
+  if (sb.level != 0 && sb.level != 1 && sb.level != 4 &&
+      sb.level != 5 && sb.level != 6 && sb.level != 10)
+    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                      "Unsupported RAID level: %d", sb.level);
+
+  array->number = sb.md_minor;
+  array->level = sb.level;
+  array->layout = sb.layout;
+  array->total_devs = sb.raid_disks;
+  array->disk_size = (sb.size) ? sb.size * 2 : sector;
+  array->chunk_size = sb.chunk_size >> 9;
+  array->index = sb.this_disk.number;
+  array->uuid_len = 16;
+  array->uuid = grub_malloc (16);
+  if (!array->uuid)
+    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;
+
+  return 0;
+}
+
+static struct grub_raid grub_mdraid_dev = {
+  .name = "mdraid",
+  .detect = grub_mdraid_detect,
+  .next = 0
+};
+
+GRUB_MOD_INIT (mdraid)
+{
+  grub_raid_register (&grub_mdraid_dev);
+}
+
+GRUB_MOD_FINI (mdraid)
+{
+  grub_raid_register (&grub_mdraid_dev);
+}
diff --git a/disk/memdisk.c b/disk/memdisk.c
new file mode 100644 (file)
index 0000000..978eae5
--- /dev/null
@@ -0,0 +1,117 @@
+/* memdisk.c - Access embedded memory disk.  */
+/*
+ *  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/>.
+ */
+
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/kernel.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/machine/kernel.h>
+
+static char *memdisk_addr;
+static grub_off_t memdisk_size = 0;
+
+static int
+grub_memdisk_iterate (int (*hook) (const char *name))
+{
+  return hook ("memdisk");
+}
+
+static grub_err_t
+grub_memdisk_open (const char *name, grub_disk_t disk)
+{
+  if (grub_strcmp (name, "memdisk"))
+      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a memdisk");
+
+  disk->total_sectors = memdisk_size / GRUB_DISK_SECTOR_SIZE;
+  disk->id = (unsigned long) "mdsk";
+  disk->has_partitions = 0;
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_memdisk_close (grub_disk_t disk __attribute((unused)))
+{
+}
+
+static grub_err_t
+grub_memdisk_read (grub_disk_t disk __attribute((unused)), grub_disk_addr_t sector,
+                   grub_size_t size, char *buf)
+{
+  grub_memcpy (buf, memdisk_addr + (sector << GRUB_DISK_SECTOR_BITS), size << GRUB_DISK_SECTOR_BITS);
+  return 0;
+}
+
+static grub_err_t
+grub_memdisk_write (grub_disk_t disk __attribute((unused)), grub_disk_addr_t sector,
+                    grub_size_t size, const char *buf)
+{
+  grub_memcpy (memdisk_addr + (sector << GRUB_DISK_SECTOR_BITS), buf, size << GRUB_DISK_SECTOR_BITS);
+  return 0;
+}
+
+static struct grub_disk_dev grub_memdisk_dev =
+  {
+    .name = "memdisk",
+    .id = GRUB_DISK_DEVICE_MEMDISK_ID,
+    .iterate = grub_memdisk_iterate,
+    .open = grub_memdisk_open,
+    .close = grub_memdisk_close,
+    .read = grub_memdisk_read,
+    .write = grub_memdisk_write,
+    .next = 0
+  };
+
+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);
+
+         grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n");
+         grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
+
+         grub_disk_dev_register (&grub_memdisk_dev);
+         return 1;
+       }
+
+      return 0;
+    }
+  
+  grub_module_iterate (hook);
+}
+
+GRUB_MOD_FINI(memdisk)
+{
+  if (! memdisk_size)
+    return;
+  grub_free (memdisk_addr);
+  grub_disk_dev_unregister (&grub_memdisk_dev);
+}
diff --git a/disk/raid.c b/disk/raid.c
new file mode 100644 (file)
index 0000000..62cbcb5
--- /dev/null
@@ -0,0 +1,723 @@
+/* raid.c - module to read RAID arrays.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/raid.h>
+
+/* 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;
+
+\f
+static char
+grub_is_array_readable (struct grub_raid_array *array)
+{
+  switch (array->level)
+    {
+    case 0:
+      if (array->nr_devs == array->total_devs)
+       return 1;
+      break;
+
+    case 1:
+      if (array->nr_devs >= 1)
+       return 1;
+      break;
+
+    case 4:
+    case 5:
+    case 6:
+    case 10:
+      {
+        unsigned int n;
+
+        if (array->level == 10)
+          {
+            n = array->layout & 0xFF;
+            if (n == 1)
+              n = (array->layout >> 8) & 0xFF;
+
+            n--;
+          }
+        else
+          n = array->level / 3;
+
+        if (array->nr_devs >= array->total_devs - n)
+          return 1;
+
+        break;
+      }
+    }
+
+  return 0;
+}
+
+static int
+grub_raid_iterate (int (*hook) (const char *name))
+{
+  struct grub_raid_array *array;
+  
+  for (array = array_list; array != NULL; array = array->next)
+    {
+      if (grub_is_array_readable (array))
+       if (hook (array->name))
+         return 1;
+    }
+
+  return 0;
+}
+
+#ifdef GRUB_UTIL
+static grub_disk_memberlist_t
+grub_raid_memberlist (grub_disk_t disk)
+{
+  struct grub_raid_array *array = disk->data;
+  grub_disk_memberlist_t list = NULL, tmp;
+  unsigned int i;
+  
+  for (i = 0; i < array->total_devs; i++)
+    if (array->device[i])
+      {
+        tmp = grub_malloc (sizeof (*tmp));
+        tmp->disk = array->device[i];
+        tmp->next = list;
+        list = tmp;
+      }
+  
+  return list;
+}
+#endif
+
+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_strcmp (array->name, name))
+       if (grub_is_array_readable (array))
+         break;
+    }
+
+  if (!array)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Unknown RAID device %s",
+                       name);
+
+  disk->has_partitions = 1;
+  disk->id = array->number;
+  disk->data = array;
+
+  grub_dprintf ("raid", "%s: total_devs=%d, disk_size=%lld\n", name,
+               array->total_devs, (unsigned long long) array->disk_size);
+
+  switch (array->level)
+    {
+    case 1:
+      disk->total_sectors = array->disk_size;
+      break;
+
+    case 10:
+      n = array->layout & 0xFF;
+      if (n == 1)
+        n = (array->layout >> 8) & 0xFF;
+
+      disk->total_sectors = grub_divmod64 (array->total_devs *
+                                           array->disk_size,
+                                           n, 0);
+      break;
+
+    case 0:
+    case 4:
+    case 5:
+    case 6:
+      n = array->level / 3;
+
+      disk->total_sectors = (array->total_devs - n) * array->disk_size;
+      break;
+    }
+
+  grub_dprintf ("raid", "%s: level=%d, total_sectors=%lld\n", name,
+               array->level, (unsigned long long) disk->total_sectors);
+  
+  return 0;
+}
+
+static void
+grub_raid_close (grub_disk_t disk __attribute ((unused)))
+{
+  return;
+}
+
+void
+grub_raid_block_xor (char *buf1, char *buf2, int size)
+{
+  grub_size_t *p1, *p2;
+
+  p1 = (grub_size_t *) buf1;
+  p2 = (grub_size_t *) buf2;
+  size /= GRUB_CPU_SIZEOF_VOID_P;
+
+  while (size)
+    {
+      *(p1++) ^= *(p2++);
+      size--;
+    }
+}
+
+static grub_err_t
+grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
+               grub_size_t size, char *buf)
+{
+  struct grub_raid_array *array = disk->data;
+  grub_err_t err = 0;
+
+  switch (array->level)
+    {
+    case 0:
+    case 1:
+    case 10:
+      {
+        grub_disk_addr_t read_sector, far_ofs;
+       grub_uint32_t disknr, b, near, far, ofs;
+
+        read_sector = grub_divmod64 (sector, array->chunk_size, &b);
+        far = ofs = near = 1;
+        far_ofs = 0;
+
+        if (array->level == 1)
+          near = array->total_devs;
+        else if (array->level == 10)
+          {
+            near = array->layout & 0xFF;
+            far = (array->layout >> 8) & 0xFF;
+            if (array->layout >> 16)
+              {
+                ofs = far;
+                far_ofs = 1;
+              }
+            else
+              far_ofs = grub_divmod64 (array->disk_size,
+                                       far * array->chunk_size, 0);
+
+            far_ofs *= array->chunk_size;
+          }
+
+        read_sector = grub_divmod64 (read_sector * near, array->total_devs,
+                                     &disknr);
+
+        ofs *= array->chunk_size;
+        read_sector *= ofs;
+
+        while (1)
+          {
+            grub_size_t read_size;
+            unsigned int i, j;
+
+            read_size = array->chunk_size - b;
+            if (read_size > size)
+              read_size = size;
+
+            for (i = 0; i < near; i++)
+              {
+                unsigned int k;
+
+                k = disknr;
+                for (j = 0; j < far; j++)
+                  {
+                    if (array->device[k])
+                      {
+                        if (grub_errno == GRUB_ERR_READ_ERROR)
+                          grub_errno = GRUB_ERR_NONE;
+
+                        err = grub_disk_read (array->device[k],
+                                              read_sector + j * far_ofs + b,
+                                              0,
+                                              read_size << GRUB_DISK_SECTOR_BITS,
+                                              buf);
+                        if (! err)
+                          break;
+                        else if (err != GRUB_ERR_READ_ERROR)
+                          return err;
+                      }
+                    else
+                      err = grub_error (GRUB_ERR_READ_ERROR,
+                                        "disk missing.");
+
+                    k++;
+                    if (k == array->total_devs)
+                      k = 0;
+                  }
+
+                if (! err)
+                  break;
+
+                disknr++;
+                if (disknr == array->total_devs)
+                  {
+                    disknr = 0;
+                    read_sector += ofs;
+                  }
+              }
+
+            if (err)
+              return err;
+
+            buf += read_size << GRUB_DISK_SECTOR_BITS;
+           size -= read_size;
+           if (! size)
+             break;
+
+            b = 0;
+            disknr += (near - i);
+            while (disknr >= array->total_devs)
+              {
+                disknr -= array->total_devs;
+                read_sector += ofs;
+              }
+          }
+        break;
+      }
+
+    case 4:
+    case 5:
+    case 6:
+      {
+       grub_disk_addr_t read_sector;
+       grub_uint32_t b, p, n, disknr, e;
+
+        /* n = 1 for level 4 and 5, 2 for level 6.  */
+        n = array->level / 3;
+
+       /* Find the first sector to read. */
+       read_sector = grub_divmod64 (sector, array->chunk_size, &b);
+       read_sector = grub_divmod64 (read_sector, array->total_devs - n,
+                                     &disknr);
+        if (array->level >= 5)
+          {
+            grub_divmod64 (read_sector, array->total_devs, &p);
+
+            if (! (array->layout & GRUB_RAID_LAYOUT_RIGHT_MASK))
+              p = array->total_devs - 1 - p;
+
+            if (array->layout & GRUB_RAID_LAYOUT_SYMMETRIC_MASK)
+              {
+                disknr += p + n;
+              }
+            else
+              {
+                grub_uint32_t q;
+
+                q = p + (n - 1);
+                if (q >= array->total_devs)
+                  q -= array->total_devs;
+
+                if (disknr >= p)
+                  disknr += n;
+                else if (disknr >= q)
+                  disknr += q + 1;
+              }
+
+            if (disknr >= array->total_devs)
+              disknr -= array->total_devs;
+          }
+        else
+          p = array->total_devs - n;
+
+       read_sector *= array->chunk_size;
+       
+       while (1)
+         {
+            grub_size_t read_size;
+            int next_level;
+
+            read_size = array->chunk_size - b;
+            if (read_size > size)
+              read_size = size;
+
+            e = 0;
+            if (array->device[disknr])
+              {
+                /* Reset read error.  */
+                if (grub_errno == GRUB_ERR_READ_ERROR)
+                  grub_errno = GRUB_ERR_NONE;
+
+                err = grub_disk_read (array->device[disknr],
+                                      read_sector + b, 0,
+                                      read_size << GRUB_DISK_SECTOR_BITS,
+                                      buf);
+
+                if ((err) && (err != GRUB_ERR_READ_ERROR))
+                  break;
+                e++;
+              }
+            else
+              err = GRUB_ERR_READ_ERROR;
+
+           if (err)
+              {
+                if (array->nr_devs < array->total_devs - n + e)
+                  break;
+
+                grub_errno = GRUB_ERR_NONE;
+                if (array->level == 6)
+                  {
+                    err = ((grub_raid6_recover_func) ?
+                           (*grub_raid6_recover_func) (array, disknr, p,
+                                                       buf, read_sector + b,
+                                                       read_size) :
+                           grub_error (GRUB_ERR_BAD_DEVICE,
+                                       "raid6rec is not loaded"));
+                  }
+                else
+                  {
+                    err = ((grub_raid5_recover_func) ?
+                           (*grub_raid5_recover_func) (array, disknr,
+                                                       buf, read_sector + b,
+                                                       read_size) :
+                           grub_error (GRUB_ERR_BAD_DEVICE,
+                                       "raid5rec is not loaded"));
+                  }
+
+                if (err)
+                  break;
+              }
+           
+           buf += read_size << GRUB_DISK_SECTOR_BITS;
+           size -= read_size;
+           if (! size)
+             break;
+
+            b = 0;
+           disknr++;
+
+            if (array->layout & GRUB_RAID_LAYOUT_SYMMETRIC_MASK)
+              {
+                if (disknr == array->total_devs)
+                  disknr = 0;
+
+                next_level = (disknr == p);
+              }
+            else
+              {
+                if (disknr == p)
+                  disknr += n;
+
+                next_level = (disknr >= array->total_devs);
+              }
+
+            if (next_level)
+              {
+                read_sector += array->chunk_size;
+
+                if (array->level >= 5)
+                  {
+                    if (array->layout & GRUB_RAID_LAYOUT_RIGHT_MASK)
+                      p = (p == array->total_devs - 1) ? 0 : p + 1;
+                    else
+                      p = (p == 0) ? array->total_devs - 1 : p - 1;
+
+                    if (array->layout & GRUB_RAID_LAYOUT_SYMMETRIC_MASK)
+                      {
+                        disknr = p + n;
+                        if (disknr >= array->total_devs)
+                          disknr -= array->total_devs;
+                      }
+                    else
+                      {
+                        disknr -= array->total_devs;
+                        if (disknr == p)
+                          disknr += n;
+                      }
+                  }
+                else
+                  disknr = 0;
+              }
+         }
+      }
+      break;
+    }
+  
+  return err;
+}
+
+static grub_err_t
+grub_raid_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 grub_err_t
+insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
+              const char *scanner_name)
+{
+  struct grub_raid_array *array = 0, *p;
+  
+  /* See whether the device is part of an array we have already seen a
+     device from. */
+  for (p = array_list; p != NULL; p = p->next)
+    if ((p->uuid_len == new_array->uuid_len) &&
+        (! grub_memcmp (p->uuid, new_array->uuid, p->uuid_len)))
+      {
+        grub_free (new_array->uuid);
+        array = p;
+
+        /* Do some checks before adding the device to the array.  */
+
+        /* FIXME: Check whether the update time of the superblocks are
+           the same. */
+
+        if (array->total_devs == array->nr_devs)
+          /* We found more members of the array than the array
+             actually has according to its superblock.  This shouldn't
+             happen normally, but what is the sanest things to do in such
+             a case? */
+          return grub_error (GRUB_ERR_BAD_NUMBER,
+                             "array->nr_devs > array->total_devs (%d)?!?",
+                             array->total_devs);
+
+        if (array->device[new_array->index] != NULL)
+          /* We found multiple devices with the same number. Again,
+             this shouldn't happen.*/
+          return grub_error (GRUB_ERR_BAD_NUMBER,
+                             "Found two disks with the number %d?!?",
+                             new_array->number);
+
+        if (new_array->disk_size < array->disk_size)
+          array->disk_size = new_array->disk_size;
+        break;
+      }
+
+  /* Add an array to the list if we didn't find any.  */
+  if (!array)
+    {
+      array = grub_malloc (sizeof (*array));
+      if (!array)
+        {
+          grub_free (new_array->uuid);
+          return grub_errno;
+        }
+
+      *array = *new_array;
+      array->nr_devs = 0;
+      grub_memset (&array->device, 0, sizeof (array->device));
+      
+      /* Check whether we don't have multiple arrays with the same number. */
+      for (p = array_list; p != NULL; p = p->next)
+        {
+          if (p->number == array->number)
+            break;
+        }
+
+      if (p)
+        {
+          /* The number is already in use, so we need to find an new number. */
+          int i = 0;
+
+          while (1)
+            {
+              for (p = array_list; p != NULL; p = p->next)
+                {
+                  if (p->number == i)
+                    break;
+                }
+
+              if (!p)
+                {
+                  /* We found an unused number.  */
+                  array->number = i;
+                  break;
+                }
+
+              i++;
+            }
+        }
+
+      array->name = grub_malloc (13);
+      if (! array->name)
+        {
+          grub_free (array->uuid);
+          grub_free (array);
+
+          return grub_errno;
+        }
+
+      grub_sprintf (array->name, "md%d", array->number);
+
+      grub_dprintf ("raid", "Found array %s (%s)\n", array->name,
+                    scanner_name);
+
+      /* Add our new array to the list.  */
+      array->next = array_list;
+      array_list = array;
+
+      /* RAID 1 doestn't use a chunksize but code assumes one so set
+        one. */
+      if (array->level == 1)
+       array->chunk_size = 64;
+    }
+
+  /* Add the device to the array. */
+  array->device[new_array->index] = disk;
+  array->nr_devs++;
+
+  return 0;
+}
+
+static grub_raid_t grub_raid_list;
+
+static void
+grub_raid_scan_device (int head_only)
+{
+  auto int hook (const char *name);
+  int hook (const char *name)
+    {
+      grub_disk_t disk;
+      struct grub_raid_array array;
+      struct grub_raid *p;
+
+      grub_dprintf ("raid", "Scanning for RAID devices\n");
+
+      disk = grub_disk_open (name);
+      if (!disk)
+        return 0;
+
+      if (disk->total_sectors == ULONG_MAX)
+        {
+          grub_disk_close (disk);
+          return 0;
+        }
+
+      for (p = grub_raid_list; p; p = p->next)
+        {
+          if (! p->detect (disk, &array))
+            {
+              if (! insert_array (disk, &array, p->name))
+                return 0;
+
+              break;
+            }
+
+          /* 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;
+          if (head_only)
+            break;
+        }
+
+      grub_disk_close (disk);
+
+      return 0;
+    }
+  
+  grub_device_iterate (&hook);
+}
+
+static void
+free_array (void)
+{
+  struct grub_raid_array *array;
+
+  array = array_list;
+  while (array)
+    {
+      struct grub_raid_array *p;
+      int i;
+         
+      p = array;
+      array = array->next;
+
+      for (i = 0; i < GRUB_RAID_MAX_DEVICES; i++)
+        if (p->device[i])
+          grub_disk_close (p->device[i]);
+
+      grub_free (p->uuid);
+      grub_free (p->name);
+      grub_free (p);
+    }
+
+  array_list = 0;
+}
+  
+void
+grub_raid_register (grub_raid_t raid)
+{
+  raid->next = grub_raid_list;
+  grub_raid_list = raid;
+  grub_raid_scan_device (1);
+}
+
+void
+grub_raid_unregister (grub_raid_t raid)
+{
+  grub_raid_t *p, q;
+
+  for (p = &grub_raid_list, q = *p; q; p = &(q->next), q = q->next)
+    if (q == raid)
+      {
+       *p = q->next;
+       break;
+      }
+}
+
+void
+grub_raid_rescan (void)
+{
+  free_array ();
+  grub_raid_scan_device (0);
+}
+
+static struct grub_disk_dev grub_raid_dev =
+  {
+    .name = "raid",
+    .id = GRUB_DISK_DEVICE_RAID_ID,
+    .iterate = grub_raid_iterate,
+    .open = grub_raid_open,
+    .close = grub_raid_close,
+    .read = grub_raid_read,
+    .write = grub_raid_write,
+#ifdef GRUB_UTIL
+    .memberlist = grub_raid_memberlist,
+#endif
+    .next = 0
+  };
+
+\f
+GRUB_MOD_INIT(raid)
+{
+  grub_disk_dev_register (&grub_raid_dev);
+}
+
+GRUB_MOD_FINI(raid)
+{
+  grub_disk_dev_unregister (&grub_raid_dev);
+  free_array ();
+}
diff --git a/disk/raid5_recover.c b/disk/raid5_recover.c
new file mode 100644 (file)
index 0000000..31cef88
--- /dev/null
@@ -0,0 +1,72 @@
+/* raid5_recover.c - module to recover from faulty RAID4/5 arrays.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/raid.h>
+
+static grub_err_t
+grub_raid5_recover (struct grub_raid_array *array, int disknr,
+                    char *buf, grub_disk_addr_t sector, int size)
+{
+  char *buf2;
+  int i;
+
+  size <<= GRUB_DISK_SECTOR_BITS;
+  buf2 = grub_malloc (size);
+  if (!buf2)
+    return grub_errno;
+
+  grub_memset (buf, 0, size);
+
+  for (i = 0; i < (int) array->total_devs; i++)
+    {
+      grub_err_t err;
+
+      if (i == disknr)
+        continue;
+
+      err = grub_disk_read (array->device[i], sector, 0, size, buf2);
+
+      if (err)
+        {
+          grub_free (buf2);
+          return err;
+        }
+
+      grub_raid_block_xor (buf, buf2, size);
+    }
+
+  grub_free (buf2);
+
+  return GRUB_ERR_NONE;
+}
+
+GRUB_MOD_INIT(raid5rec)
+{
+  grub_raid5_recover_func = grub_raid5_recover;
+}
+
+GRUB_MOD_FINI(raid5rec)
+{
+  grub_raid5_recover_func = 0;
+}
diff --git a/disk/raid6_recover.c b/disk/raid6_recover.c
new file mode 100644 (file)
index 0000000..3cb08ab
--- /dev/null
@@ -0,0 +1,216 @@
+/* raid6_recover.c - module to recover from faulty RAID6 arrays.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/raid.h>
+
+static grub_uint8_t raid6_table1[256][256];
+static grub_uint8_t raid6_table2[256][256];
+
+static void
+grub_raid_block_mul (grub_uint8_t mul, char *buf, int size)
+{
+  int i;
+  grub_uint8_t *p;
+
+  p = (grub_uint8_t *) buf;
+  for (i = 0; i < size; i++, p++)
+    *p = raid6_table1[mul][*p];
+}
+
+static void
+grub_raid6_init_table (void)
+{
+  int i, j;
+
+  for (i = 0; i < 256; i++)
+    raid6_table1[i][1] = raid6_table1[1][i] = i;
+
+  for (i = 2; i < 256; i++)
+    for (j = i; j < 256; j++)
+      {
+        int n;
+        grub_uint8_t c;
+
+        n = i >> 1;
+
+        c = raid6_table1[n][j];
+        c = (c << 1) ^ ((c & 0x80) ? 0x1d : 0);
+        if (i & 1)
+          c ^= j;
+
+        raid6_table1[j][i] = raid6_table1[i][j] = c;
+      }
+
+  raid6_table2[0][0] = 1;
+  for (i = 1; i < 256; i++)
+    raid6_table2[i][i] = raid6_table1[raid6_table2[i - 1][i - 1]][2];
+
+  for (i = 0; i < 254; i++)
+    for (j = 0; j < 254; j++)
+      {
+        grub_uint8_t c, n;
+        int k;
+
+        if (i == j)
+          continue;
+
+        k = i - j;
+        if (k < 0)
+          k += 255;
+
+        c = n = raid6_table2[k][k] ^ 1;
+        for (k = 0; k < 253; k++)
+          c = raid6_table1[c][n];
+
+        raid6_table2[i][j] = raid6_table1[raid6_table2[255 - j][255 - j]][c];
+      }
+}
+
+static grub_err_t
+grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
+                    char *buf, grub_disk_addr_t sector, int size)
+{
+  int i, q, pos;
+  int err[2], nerr;
+  char *pbuf = 0, *qbuf = 0;
+
+  size <<= GRUB_DISK_SECTOR_BITS;
+  pbuf = grub_malloc (size);
+  if (!pbuf)
+    goto quit;
+
+  qbuf = grub_malloc (size);
+  if (!qbuf)
+    goto quit;
+
+  q = p + 1;
+  if (q == (int) array->total_devs)
+    q = 0;
+
+  grub_memset (pbuf, 0, size);
+  grub_memset (qbuf, 0, size);
+
+  pos = q + 1;
+  if (pos == (int) array->total_devs)
+    pos = 0;
+
+  nerr = 1;
+  for (i = 0; i < (int) array->total_devs - 2; i++)
+    {
+      if (pos == disknr)
+        err[0] = i;
+      else
+        {
+          if ((array->device[pos]) &&
+              (! grub_disk_read (array->device[pos], sector, 0, size, buf)))
+            {
+              grub_raid_block_xor (pbuf, buf, size);
+              grub_raid_block_mul (raid6_table2[i][i], buf, size);
+              grub_raid_block_xor (qbuf, buf, size);
+            }
+          else
+            {
+              if (nerr >= 2)
+                goto quit;
+
+              err[nerr++] = i;
+              grub_errno = GRUB_ERR_NONE;
+            }
+        }
+
+      pos++;
+      if (pos == (int) array->total_devs)
+        pos = 0;
+    }
+
+  if (nerr == 1)
+    {
+      if ((array->device[p]) &&
+          (! grub_disk_read (array->device[p], sector, 0, size, buf)))
+        {
+          grub_raid_block_xor (buf, pbuf, size);
+          goto quit;
+        }
+
+      if (! array->device[q])
+        {
+          grub_error (GRUB_ERR_READ_ERROR, "Not enough disk to restore");
+          goto quit;
+        }
+
+      grub_errno = GRUB_ERR_NONE;
+      if (grub_disk_read (array->device[q], sector, 0, size, buf))
+        goto quit;
+
+      grub_raid_block_xor (buf, qbuf, size);
+      grub_raid_block_mul (raid6_table2[255 - err[0]][255 - err[0]], buf,
+                           size);
+    }
+  else
+    {
+      grub_uint8_t c;
+
+      if ((! array->device[p]) || (! array->device[q]))
+        {
+          grub_error (GRUB_ERR_READ_ERROR, "Not enough disk to restore");
+          goto quit;
+        }
+
+      if (grub_disk_read (array->device[p], sector, 0, size, buf))
+        goto quit;
+
+      grub_raid_block_xor (pbuf, buf, size);
+
+      if (grub_disk_read (array->device[q], sector, 0, size, buf))
+        goto quit;
+
+      grub_raid_block_xor (qbuf, buf, size);
+
+      c = raid6_table2[err[1]][err[0]];
+      grub_raid_block_mul (c, qbuf, size);
+
+      c = raid6_table1[raid6_table2[err[1]][err[1]]][c];
+      grub_raid_block_mul (c, pbuf, size);
+
+      grub_raid_block_xor (pbuf, qbuf, size);
+      grub_memcpy (buf, pbuf, size);
+    }
+
+quit:
+  grub_free (pbuf);
+  grub_free (qbuf);
+
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(raid6rec)
+{
+  grub_raid6_init_table ();
+  grub_raid6_recover_func = grub_raid6_recover;
+}
+
+GRUB_MOD_FINI(raid6rec)
+{
+  grub_raid6_recover_func = 0;
+}
diff --git a/disk/scsi.c b/disk/scsi.c
new file mode 100644 (file)
index 0000000..5dce288
--- /dev/null
@@ -0,0 +1,395 @@
+/* scsi.c - scsi support.  */
+/*
+ *  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/disk.h>
+#include <grub/dl.h>
+#include <grub/kernel.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/machine/kernel.h>
+#include <grub/scsi.h>
+#include <grub/scsicmd.h>
+
+\f
+static grub_scsi_dev_t grub_scsi_dev_list;
+
+void
+grub_scsi_dev_register (grub_scsi_dev_t dev)
+{
+  dev->next = grub_scsi_dev_list;
+  grub_scsi_dev_list = dev;
+}
+
+void
+grub_scsi_dev_unregister (grub_scsi_dev_t dev)
+{
+  grub_scsi_dev_t *p, q;
+
+  for (p = &grub_scsi_dev_list, q = *p; q; p = &(q->next), q = q->next)
+    if (q == dev)
+      {
+        *p = q->next;
+       break;
+      }
+}
+
+\f
+/* Determine the the device is removable and the type of the device
+   SCSI.  */
+static grub_err_t
+grub_scsi_inquiry (grub_scsi_t scsi)
+{
+  struct grub_scsi_inquiry iq;
+  struct grub_scsi_inquiry_data iqd;
+  grub_err_t err;
+
+  iq.opcode = grub_scsi_cmd_inquiry;
+  iq.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
+  iq.reserved = 0;
+  iq.alloc_length = 0x24; /* XXX: Hardcoded for now */
+  iq.reserved2 = 0;
+
+  err = scsi->dev->read (scsi, sizeof (iq), (char *) &iq,
+                        sizeof (iqd), (char *) &iqd);
+  if (err)
+    return err;
+
+  scsi->devtype = iqd.devtype & GRUB_SCSI_DEVTYPE_MASK;
+  scsi->removable = iqd.rmb >> GRUB_SCSI_REMOVABLE_BIT;
+
+  return GRUB_ERR_NONE;
+}
+
+/* Read the capacity and block size of SCSI.  */
+static grub_err_t
+grub_scsi_read_capacity (grub_scsi_t scsi)
+{
+  struct grub_scsi_read_capacity rc;
+  struct grub_scsi_read_capacity_data rcd;
+  grub_err_t err;
+
+  rc.opcode = grub_scsi_cmd_read_capacity;
+  rc.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
+  grub_memset (rc.reserved, 0, sizeof (rc.reserved));
+
+  err = scsi->dev->read (scsi, sizeof (rc), (char *) &rc,
+                        sizeof (rcd), (char *) &rcd);
+  if (err)
+    return err;
+
+  scsi->size = grub_be_to_cpu32 (rcd.size);
+  scsi->blocksize = grub_be_to_cpu32 (rcd.blocksize);
+
+  return GRUB_ERR_NONE;
+}
+
+/* Send a SCSI request for DISK: read SIZE sectors starting with
+   sector SECTOR to BUF.  */
+static grub_err_t
+grub_scsi_read10 (grub_disk_t disk, grub_disk_addr_t sector,
+                 grub_size_t size, char *buf)
+{
+  grub_scsi_t scsi;
+  struct grub_scsi_read10 rd;
+
+  scsi = disk->data;
+
+  rd.opcode = grub_scsi_cmd_read10;
+  rd.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
+  rd.lba = grub_cpu_to_be32 (sector);
+  rd.reserved = 0;
+  rd.size = grub_cpu_to_be16 (size);
+  rd.reserved2 = 0;
+  rd.pad = 0;
+
+  return scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * scsi->blocksize, buf);
+}
+
+/* Send a SCSI request for DISK: read SIZE sectors starting with
+   sector SECTOR to BUF.  */
+static grub_err_t
+grub_scsi_read12 (grub_disk_t disk, grub_disk_addr_t sector,
+                 grub_size_t size, char *buf)
+{
+  grub_scsi_t scsi;
+  struct grub_scsi_read12 rd;
+
+  scsi = disk->data;
+
+  rd.opcode = grub_scsi_cmd_read12;
+  rd.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
+  rd.lba = grub_cpu_to_be32 (sector);
+  rd.size = grub_cpu_to_be32 (size);
+  rd.reserved = 0;
+  rd.control = 0;
+
+  return scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * scsi->blocksize, buf);
+}
+
+#if 0
+/* Send a SCSI request for DISK: write the data stored in BUF to SIZE
+   sectors starting with SECTOR.  */
+static grub_err_t
+grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector,
+                  grub_size_t size, char *buf)
+{
+  grub_scsi_t scsi;
+  struct grub_scsi_write10 wr;
+
+  scsi = disk->data;
+
+  wr.opcode = grub_scsi_cmd_write10;
+  wr.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
+  wr.lba = grub_cpu_to_be32 (sector);
+  wr.reserved = 0;
+  wr.size = grub_cpu_to_be16 (size);
+  wr.reserved2 = 0;
+  wr.pad = 0;
+
+  return scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * scsi->blocksize, buf);
+}
+
+/* Send a SCSI request for DISK: write the data stored in BUF to SIZE
+   sectors starting with SECTOR.  */
+static grub_err_t
+grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector,
+                  grub_size_t size, char *buf)
+{
+  grub_scsi_t scsi;
+  struct grub_scsi_write10 wr;
+
+  scsi = disk->data;
+
+  wr.opcode = grub_scsi_cmd_write12;
+  wr.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
+  wr.lba = grub_cpu_to_be32 (sector);
+  wr.size = grub_cpu_to_be32 (size);
+  wr.reserved = 0;
+  wr.pad = 0;
+
+  return scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * scsi->blocksize, buf);
+}
+#endif
+
+\f
+static int
+grub_scsi_iterate (int (*hook) (const char *name))
+{
+  grub_scsi_dev_t p;
+
+  auto int scsi_iterate (const char *name, int luns);
+
+  int scsi_iterate (const char *name, int luns)
+    {
+      char sname[40];
+      int i;
+
+      /* In case of a single LUN, just return `usbX'.  */
+      if (luns == 1)
+       return hook (name);
+
+      /* In case of multiple LUNs, every LUN will get a prefix to
+        distinguish it.  */
+      for (i = 0; i < luns; i++)
+       {
+         grub_sprintf (sname, "%s%c", name, 'a' + i);
+         if (hook (sname))
+           return 1;
+       }
+      return 0;
+    }
+
+  for (p = grub_scsi_dev_list; p; p = p->next)
+    if (p->iterate && (p->iterate) (scsi_iterate))
+      return 1;
+
+  return 0;
+}
+
+static grub_err_t
+grub_scsi_open (const char *name, grub_disk_t disk)
+{
+  grub_scsi_dev_t p;
+  grub_scsi_t scsi;
+  grub_err_t err;
+  int len;
+  int lun;
+
+  scsi = grub_malloc (sizeof (*scsi));
+  if (! scsi)
+    return grub_errno;
+
+  len = grub_strlen (name);
+  lun = name[len - 1] - 'a';
+
+  /* Try to detect a LUN ('a'-'z'), otherwise just use the first
+     LUN.  */
+  if (lun < 0 || lun > 26)
+    lun = 0;
+
+  for (p = grub_scsi_dev_list; p; p = p->next)
+    {
+      if (! p->open (name, scsi))
+       {
+         disk->id = (unsigned long) "scsi"; /* XXX */
+         disk->data = scsi;
+         scsi->dev = p;
+         scsi->lun = lun;
+         scsi->name = grub_strdup (name);
+         if (! scsi->name)
+           {
+             return grub_errno;
+           }
+
+         grub_dprintf ("scsi", "dev opened\n");
+
+         err = grub_scsi_inquiry (scsi);
+         if (err)
+           {
+             grub_dprintf ("scsi", "inquiry failed\n");
+             return grub_errno;
+           }
+
+         grub_dprintf ("scsi", "inquiry: devtype=0x%02x removable=%d\n",
+                       scsi->devtype, scsi->removable);
+
+         /* Try to be conservative about the device types
+            supported.  */
+         if (scsi->devtype != grub_scsi_devtype_direct
+             && scsi->devtype != grub_scsi_devtype_cdrom)
+           {
+             return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                                "unknown SCSI device");
+           }
+
+         if (scsi->devtype == grub_scsi_devtype_cdrom)
+           disk->has_partitions = 0;
+         else
+           disk->has_partitions = 1;
+
+         err = grub_scsi_read_capacity (scsi);
+         if (err)
+           {
+             grub_dprintf ("scsi", "READ CAPACITY failed\n");
+             return grub_errno;
+           }
+
+         /* SCSI blocks can be something else than 512, although GRUB
+            wants 512 byte blocks.  */
+         disk->total_sectors = ((scsi->size * scsi->blocksize)
+                                << GRUB_DISK_SECTOR_BITS);
+
+         grub_dprintf ("scsi", "capacity=%llu, blksize=%d\n",
+                       disk->total_sectors, scsi->blocksize);
+
+         return GRUB_ERR_NONE;
+       }
+    }
+
+  return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a SCSI disk");
+}
+
+static void
+grub_scsi_close (grub_disk_t disk)
+{
+  grub_scsi_t scsi;
+
+  scsi = disk->data;
+  return scsi->dev->close (scsi);
+}
+
+static grub_err_t
+grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector,
+               grub_size_t size, char *buf)
+{
+  grub_scsi_t scsi;
+
+  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) == 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)
+    {
+    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);
+    }
+
+  /* XXX: Never reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_scsi_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)))
+{
+#if 0
+  /* XXX: Not tested yet!  */
+
+  /* XXX: This should depend on the device type?  */
+  return grub_scsi_write10 (disk, sector, size, buf);
+#endif
+  return GRUB_ERR_NOT_IMPLEMENTED_YET;
+}
+
+
+static struct grub_disk_dev grub_scsi_dev =
+  {
+    .name = "scsi",
+    .id = GRUB_DISK_DEVICE_SCSI_ID,
+    .iterate = grub_scsi_iterate,
+    .open = grub_scsi_open,
+    .close = grub_scsi_close,
+    .read = grub_scsi_read,
+    .write = grub_scsi_write,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(scsi)
+{
+  grub_disk_dev_register (&grub_scsi_dev);
+}
+
+GRUB_MOD_FINI(scsi)
+{
+  grub_disk_dev_unregister (&grub_scsi_dev);
+}
diff --git a/disk/usbms.c b/disk/usbms.c
new file mode 100644 (file)
index 0000000..d08256b
--- /dev/null
@@ -0,0 +1,393 @@
+/* usbms.c - USB Mass Storage Support.  */
+/*
+ *  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/dl.h>
+#include <grub/mm.h>
+#include <grub/usb.h>
+#include <grub/scsi.h>
+#include <grub/scsicmd.h>
+#include <grub/misc.h>
+
+#define GRUB_USBMS_DIRECTION_BIT       7
+
+/* The USB Mass Storage Command Block Wrapper.  */
+struct grub_usbms_cbw
+{
+  grub_uint32_t signature;
+  grub_uint32_t tag;
+  grub_uint32_t transfer_length;
+  grub_uint8_t flags;
+  grub_uint8_t lun;
+  grub_uint8_t length;
+  grub_uint8_t cbwcb[16];
+} __attribute__ ((packed));
+
+struct grub_usbms_csw
+{
+  grub_uint32_t signature;
+  grub_uint32_t tag;
+  grub_uint32_t residue;
+  grub_uint8_t status;
+} __attribute__ ((packed));
+
+struct grub_usbms_dev
+{
+  struct grub_usb_device *dev;
+
+  int luns;
+
+  int interface;
+  struct grub_usb_desc_endp *in;
+  struct grub_usb_desc_endp *out;
+
+  int in_maxsz;
+  int out_maxsz;
+
+  struct grub_usbms_dev *next;
+};
+typedef struct grub_usbms_dev *grub_usbms_dev_t;
+
+static grub_usbms_dev_t grub_usbms_dev_list;
+
+static int devcnt;
+
+static grub_err_t
+grub_usbms_reset (grub_usb_device_t dev, int interface)
+{
+  return grub_usb_control_msg (dev, 0x21, 255, 0, interface, 0, 0);
+}
+
+static void
+grub_usbms_finddevs (void)
+{
+  auto int usb_iterate (grub_usb_device_t dev);
+
+  int usb_iterate (grub_usb_device_t usbdev)
+    {
+      grub_usb_err_t err;
+      struct grub_usb_desc_device *descdev = &usbdev->descdev;
+      int i;
+
+      if (descdev->class != 0 || descdev->subclass || descdev->protocol != 0)
+       return 0;
+
+      /* XXX: Just check configuration 0 for now.  */
+      for (i = 0; i < usbdev->config[0].descconf->numif; i++)
+       {
+         struct grub_usbms_dev *usbms;
+         struct grub_usb_desc_if *interf;
+         int j;
+         grub_uint8_t luns;
+
+         interf = usbdev->config[0].interf[i].descif;
+
+         /* If this is not a USB Mass Storage device with a supported
+            protocol, just skip it.  */
+         if (interf->class != GRUB_USB_CLASS_MASS_STORAGE
+             || interf->subclass != GRUB_USBMS_SUBCLASS_BULK
+             || interf->protocol != GRUB_USBMS_PROTOCOL_BULK)
+           {
+             continue;
+           }
+
+         devcnt++;
+         usbms = grub_malloc (sizeof (struct grub_usbms_dev));
+         if (! usbms)
+           return 1;
+
+         usbms->dev = usbdev;
+         usbms->interface = i;
+         usbms->in = NULL;
+         usbms->out = NULL;
+
+         /* Iterate over all endpoints of this interface, at least a
+            IN and OUT bulk endpoint are required.  */
+         for (j = 0; j < interf->endpointcnt; j++)
+           {
+             struct grub_usb_desc_endp *endp;
+             endp = &usbdev->config[0].interf[i].descendp[j];
+
+             if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2)
+               {
+                 /* Bulk IN endpoint.  */
+                 usbms->in = endp;
+                 grub_usb_clear_halt (usbdev, endp->endp_addr & 128);
+                 usbms->in_maxsz = endp->maxpacket;
+               }
+             else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2)
+               {
+                 /* Bulk OUT endpoint.  */
+                 usbms->out = endp;
+                 grub_usb_clear_halt (usbdev, endp->endp_addr & 128);
+                 usbms->out_maxsz = endp->maxpacket;
+               }
+           }
+
+         if (!usbms->in || !usbms->out)
+           {
+             grub_free (usbms);
+             return 0;
+           }
+
+         /* Query the amount of LUNs.  */
+         err = grub_usb_control_msg (usbdev, 0xA1, 254,
+                                     0, i, 1, (char *) &luns);
+         if (err)
+           {
+             /* In case of a stall, clear the stall.  */
+             if (err == GRUB_USB_ERR_STALL)
+               {
+                 grub_usb_clear_halt (usbdev, usbms->in->endp_addr & 3);
+                 grub_usb_clear_halt (usbdev, usbms->out->endp_addr & 3);
+               }
+
+             /* Just set the amount of LUNs to one.  */
+             grub_errno = GRUB_ERR_NONE;
+             usbms->luns = 1;
+           }
+         else
+           usbms->luns = luns;
+
+         /* XXX: Check the magic values, does this really make
+            sense?  */
+         grub_usb_control_msg (usbdev, (1 << 6) | 1, 255,
+                               0, i, 0, 0);
+
+         /* XXX: To make Qemu work?  */
+         if (usbms->luns == 0)
+           usbms->luns = 1;
+
+         usbms->next = grub_usbms_dev_list;
+         grub_usbms_dev_list = usbms;
+
+         /* XXX: Activate the first configuration.  */
+         grub_usb_set_configuration (usbdev, 1);
+
+         /* Bolk-Only Mass Storage Reset, after the reset commands
+            will be accepted.  */
+         grub_usbms_reset (usbdev, i);
+
+         return 0;
+       }
+
+      return 0;
+    }
+
+  grub_usb_iterate (usb_iterate);
+}
+
+\f
+
+static int
+grub_usbms_iterate (int (*hook) (const char *name, int luns))
+{
+  grub_usbms_dev_t p;
+  int cnt = 0;
+
+  for (p = grub_usbms_dev_list; p; p = p->next)
+    {
+      char devname[20];
+      grub_sprintf (devname, "usb%d", cnt);
+
+      if (hook (devname, p->luns))
+       return 1;
+      cnt++;
+    }
+
+  return 0;
+}
+
+static grub_err_t
+grub_usbms_tranfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
+                   grub_size_t size, char *buf, int read_write)
+{
+  struct grub_usbms_cbw cbw;
+  grub_usbms_dev_t dev = (grub_usbms_dev_t) scsi->data;
+  struct grub_usbms_csw status;
+  static grub_uint32_t tag = 0;
+  grub_usb_err_t err;
+  int retrycnt = 3;
+
+ retry:
+  if (retrycnt == 0)
+    return err;
+
+  /* Setup the request.  */
+  grub_memset (&cbw, 0, sizeof (cbw));
+  cbw.signature = grub_cpu_to_le32 (0x43425355);
+  cbw.tag = tag++;
+  cbw.transfer_length = grub_cpu_to_le32 (size);
+  cbw.flags = (!read_write) << GRUB_USBMS_DIRECTION_BIT;
+  cbw.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
+  cbw.length = cmdsize;
+  grub_memcpy (cbw.cbwcb, cmd, cmdsize);
+
+  /* Write the request.  */
+  err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr & 15,
+                            sizeof (cbw), (char *) &cbw);
+  if (err)
+    {
+      if (err == GRUB_USB_ERR_STALL)
+       {
+         grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
+         goto retry;
+       }
+      return grub_error (GRUB_ERR_IO, "USB Mass Storage request failed");;
+    }
+
+  /* Read/write the data.  */
+  if (read_write == 0)
+    {
+      err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr & 15, size, buf);
+      grub_dprintf ("usb", "read: %d %d\n", err, GRUB_USB_ERR_STALL);
+      if (err)
+       {
+         if (err == GRUB_USB_ERR_STALL)
+           {
+             grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
+             goto retry;
+           }
+         return grub_error (GRUB_ERR_READ_ERROR,
+                            "can't read from USB Mass Storage device");
+       }
+    }
+  else 
+    {
+      err = grub_usb_bulk_write (dev->dev, dev->in->endp_addr & 15, size, buf);
+      grub_dprintf ("usb", "write: %d %d\n", err, GRUB_USB_ERR_STALL);
+      if (err)
+       {
+         if (err == GRUB_USB_ERR_STALL)
+           {
+             grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
+             goto retry;
+           }
+         return grub_error (GRUB_ERR_WRITE_ERROR,
+                            "can't write to USB Mass Storage device");
+       }
+    }
+
+  /* Read the status.  */
+  err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr & 15,
+                           sizeof (status), (char *) &status);
+  if (err)
+    {
+      if (err == GRUB_USB_ERR_STALL)
+       {
+         grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
+         goto retry;
+       }
+      return grub_error (GRUB_ERR_READ_ERROR,
+                        "can't read status from USB Mass Storage device");
+    }
+
+  /* XXX: Magic and check this code.  */
+  if (status.status == 2)
+    {
+      /* XXX: Phase error, reset device.  */
+      grub_usbms_reset (dev->dev, dev->interface);
+      grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
+      grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
+
+      retrycnt--;
+      if (retrycnt)
+       goto retry;
+    }
+
+  if (status.status)
+    return grub_error (GRUB_ERR_READ_ERROR,
+                      "error communication with USB Mass Storage device");
+
+  return GRUB_ERR_NONE;
+}
+
+
+static grub_err_t
+grub_usbms_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
+                grub_size_t size, char *buf)
+{
+  return grub_usbms_tranfer (scsi, cmdsize, cmd, size, buf, 0);
+}
+
+static grub_err_t
+grub_usbms_write (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
+                 grub_size_t size, char *buf)
+{
+  return grub_usbms_tranfer (scsi, cmdsize, cmd, size, buf, 1);
+}
+
+static grub_err_t
+grub_usbms_open (const char *name, struct grub_scsi *scsi)
+{
+  grub_usbms_dev_t p;
+  int devnum;
+  int i = 0;
+
+  if (grub_strncmp (name, "usb", 3))
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                      "not a USB Mass Storage device");
+
+  devnum = grub_strtoul (name + 3, NULL, 10);
+  for (p = grub_usbms_dev_list; p; p = p->next)
+    {
+      /* Check if this is the devnumth device.  */
+      if (devnum == i)
+       {
+         scsi->data = p;
+         scsi->name = grub_strdup (name);
+         scsi->luns = p->luns;
+         if (! scsi->name)
+           return grub_errno;
+
+         return GRUB_ERR_NONE;
+       }
+
+      i++;
+    }
+
+  return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                    "not a USB Mass Storage device");
+}
+
+static void
+grub_usbms_close (struct grub_scsi *scsi)
+{
+  grub_free (scsi->name);
+}
+
+static struct grub_scsi_dev grub_usbms_dev =
+  {
+    .name = "usb",
+    .iterate = grub_usbms_iterate,
+    .open = grub_usbms_open,
+    .close = grub_usbms_close,
+    .read = grub_usbms_read,
+    .write = grub_usbms_write
+  }; 
+
+GRUB_MOD_INIT(usbms)
+{
+  grub_usbms_finddevs ();
+  grub_scsi_dev_register (&grub_usbms_dev);
+}
+
+GRUB_MOD_FINI(usbms)
+{
+  grub_scsi_dev_unregister (&grub_usbms_dev);
+}
diff --git a/docs/fdl.texi b/docs/fdl.texi
new file mode 100644 (file)
index 0000000..fe78df8
--- /dev/null
@@ -0,0 +1,452 @@
+
+@node GNU Free Documentation License
+@appendixsec GNU Free Documentation License
+
+@cindex FDL, GNU Free Documentation License
+@center Version 1.2, November 2002
+
+@display
+Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
+51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+@end display
+
+@enumerate 0
+@item
+PREAMBLE
+
+The purpose of this License is to make a manual, textbook, or other
+functional and useful document @dfn{free} in the sense of freedom: to
+assure everyone the effective freedom to copy and redistribute it,
+with or without modifying it, either commercially or noncommercially.
+Secondarily, this License preserves for the author and publisher a way
+to get credit for their work, while not being considered responsible
+for modifications made by others.
+
+This License is a kind of ``copyleft'', which means that derivative
+works of the document must themselves be free in the same sense.  It
+complements the GNU General Public License, which is a copyleft
+license designed for free software.
+
+We have designed this License in order to use it for manuals for free
+software, because free software needs free documentation: a free
+program should come with manuals providing the same freedoms that the
+software does.  But this License is not limited to software manuals;
+it can be used for any textual work, regardless of subject matter or
+whether it is published as a printed book.  We recommend this License
+principally for works whose purpose is instruction or reference.
+
+@item
+APPLICABILITY AND DEFINITIONS
+
+This License applies to any manual or other work, in any medium, that
+contains a notice placed by the copyright holder saying it can be
+distributed under the terms of this License.  Such a notice grants a
+world-wide, royalty-free license, unlimited in duration, to use that
+work under the conditions stated herein.  The ``Document'', below,
+refers to any such manual or work.  Any member of the public is a
+licensee, and is addressed as ``you''.  You accept the license if you
+copy, modify or distribute the work in a way requiring permission
+under copyright law.
+
+A ``Modified Version'' of the Document means any work containing the
+Document or a portion of it, either copied verbatim, or with
+modifications and/or translated into another language.
+
+A ``Secondary Section'' is a named appendix or a front-matter section
+of the Document that deals exclusively with the relationship of the
+publishers or authors of the Document to the Document's overall
+subject (or to related matters) and contains nothing that could fall
+directly within that overall subject.  (Thus, if the Document is in
+part a textbook of mathematics, a Secondary Section may not explain
+any mathematics.)  The relationship could be a matter of historical
+connection with the subject or with related matters, or of legal,
+commercial, philosophical, ethical or political position regarding
+them.
+
+The ``Invariant Sections'' are certain Secondary Sections whose titles
+are designated, as being those of Invariant Sections, in the notice
+that says that the Document is released under this License.  If a
+section does not fit the above definition of Secondary then it is not
+allowed to be designated as Invariant.  The Document may contain zero
+Invariant Sections.  If the Document does not identify any Invariant
+Sections then there are none.
+
+The ``Cover Texts'' are certain short passages of text that are listed,
+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
+the Document is released under this License.  A Front-Cover Text may
+be at most 5 words, and a Back-Cover Text may be at most 25 words.
+
+A ``Transparent'' copy of the Document means a machine-readable copy,
+represented in a format whose specification is available to the
+general public, that is suitable for revising the document
+straightforwardly with generic text editors or (for images composed of
+pixels) generic paint programs or (for drawings) some widely available
+drawing editor, and that is suitable for input to text formatters or
+for automatic translation to a variety of formats suitable for input
+to text formatters.  A copy made in an otherwise Transparent file
+format whose markup, or absence of markup, has been arranged to thwart
+or discourage subsequent modification by readers is not Transparent.
+An image format is not Transparent if used for any substantial amount
+of text.  A copy that is not ``Transparent'' is called ``Opaque''.
+
+Examples of suitable formats for Transparent copies include plain
+@sc{ascii} without markup, Texinfo input format, La@TeX{} input
+format, @acronym{SGML} or @acronym{XML} using a publicly available
+@acronym{DTD}, and standard-conforming simple @acronym{HTML},
+PostScript or @acronym{PDF} designed for human modification.  Examples
+of transparent image formats include @acronym{PNG}, @acronym{XCF} and
+@acronym{JPG}.  Opaque formats include proprietary formats that can be
+read and edited only by proprietary word processors, @acronym{SGML} or
+@acronym{XML} for which the @acronym{DTD} and/or processing tools are
+not generally available, and the machine-generated @acronym{HTML},
+PostScript or @acronym{PDF} produced by some word processors for
+output purposes only.
+
+The ``Title Page'' means, for a printed book, the title page itself,
+plus such following pages as are needed to hold, legibly, the material
+this License requires to appear in the title page.  For works in
+formats which do not have any title page as such, ``Title Page'' means
+the text near the most prominent appearance of the work's title,
+preceding the beginning of the body of the text.
+
+A section ``Entitled XYZ'' means a named subunit of the Document whose
+title either is precisely XYZ or contains XYZ in parentheses following
+text that translates XYZ in another language.  (Here XYZ stands for a
+specific section name mentioned below, such as ``Acknowledgements'',
+``Dedications'', ``Endorsements'', or ``History''.)  To ``Preserve the Title''
+of such a section when you modify the Document means that it remains a
+section ``Entitled XYZ'' according to this definition.
+
+The Document may include Warranty Disclaimers next to the notice which
+states that this License applies to the Document.  These Warranty
+Disclaimers are considered to be included by reference in this
+License, but only as regards disclaiming warranties: any other
+implication that these Warranty Disclaimers may have is void and has
+no effect on the meaning of this License.
+
+@item
+VERBATIM COPYING
+
+You may copy and distribute the Document in any medium, either
+commercially or noncommercially, provided that this License, the
+copyright notices, and the license notice saying this License applies
+to the Document are reproduced in all copies, and that you add no other
+conditions whatsoever to those of this License.  You may not use
+technical measures to obstruct or control the reading or further
+copying of the copies you make or distribute.  However, you may accept
+compensation in exchange for copies.  If you distribute a large enough
+number of copies you must also follow the conditions in section 3.
+
+You may also lend copies, under the same conditions stated above, and
+you may publicly display copies.
+
+@item
+COPYING IN QUANTITY
+
+If you publish printed copies (or copies in media that commonly have
+printed covers) of the Document, numbering more than 100, and the
+Document's license notice requires Cover Texts, you must enclose the
+copies in covers that carry, clearly and legibly, all these Cover
+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
+the back cover.  Both covers must also clearly and legibly identify
+you as the publisher of these copies.  The front cover must present
+the full title with all words of the title equally prominent and
+visible.  You may add other material on the covers in addition.
+Copying with changes limited to the covers, as long as they preserve
+the title of the Document and satisfy these conditions, can be treated
+as verbatim copying in other respects.
+
+If the required texts for either cover are too voluminous to fit
+legibly, you should put the first ones listed (as many as fit
+reasonably) on the actual cover, and continue the rest onto adjacent
+pages.
+
+If you publish or distribute Opaque copies of the Document numbering
+more than 100, you must either include a machine-readable Transparent
+copy along with each Opaque copy, or state in or with each Opaque copy
+a computer-network location from which the general network-using
+public has access to download using public-standard network protocols
+a complete Transparent copy of the Document, free of added material.
+If you use the latter option, you must take reasonably prudent steps,
+when you begin distribution of Opaque copies in quantity, to ensure
+that this Transparent copy will remain thus accessible at the stated
+location until at least one year after the last time you distribute an
+Opaque copy (directly or through your agents or retailers) of that
+edition to the public.
+
+It is requested, but not required, that you contact the authors of the
+Document well before redistributing any large number of copies, to give
+them a chance to provide you with an updated version of the Document.
+
+@item
+MODIFICATIONS
+
+You may copy and distribute a Modified Version of the Document under
+the conditions of sections 2 and 3 above, provided that you release
+the Modified Version under precisely this License, with the Modified
+Version filling the role of the Document, thus licensing distribution
+and modification of the Modified Version to whoever possesses a copy
+of it.  In addition, you must do these things in the Modified Version:
+
+@enumerate A
+@item
+Use in the Title Page (and on the covers, if any) a title distinct
+from that of the Document, and from those of previous versions
+(which should, if there were any, be listed in the History section
+of the Document).  You may use the same title as a previous version
+if the original publisher of that version gives permission.
+
+@item
+List on the Title Page, as authors, one or more persons or entities
+responsible for authorship of the modifications in the Modified
+Version, together with at least five of the principal authors of the
+Document (all of its principal authors, if it has fewer than five),
+unless they release you from this requirement.
+
+@item
+State on the Title page the name of the publisher of the
+Modified Version, as the publisher.
+
+@item
+Preserve all the copyright notices of the Document.
+
+@item
+Add an appropriate copyright notice for your modifications
+adjacent to the other copyright notices.
+
+@item
+Include, immediately after the copyright notices, a license notice
+giving the public permission to use the Modified Version under the
+terms of this License, in the form shown in the Addendum below.
+
+@item
+Preserve in that license notice the full lists of Invariant Sections
+and required Cover Texts given in the Document's license notice.
+
+@item
+Include an unaltered copy of this License.
+
+@item
+Preserve the section Entitled ``History'', Preserve its Title, and add
+to it an item stating at least the title, year, new authors, and
+publisher of the Modified Version as given on the Title Page.  If
+there is no section Entitled ``History'' in the Document, create one
+stating the title, year, authors, and publisher of the Document as
+given on its Title Page, then add an item describing the Modified
+Version as stated in the previous sentence.
+
+@item
+Preserve the network location, if any, given in the Document for
+public access to a Transparent copy of the Document, and likewise
+the network locations given in the Document for previous versions
+it was based on.  These may be placed in the ``History'' section.
+You may omit a network location for a work that was published at
+least four years before the Document itself, or if the original
+publisher of the version it refers to gives permission.
+
+@item
+For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve
+the Title of the section, and preserve in the section all the
+substance and tone of each of the contributor acknowledgements and/or
+dedications given therein.
+
+@item
+Preserve all the Invariant Sections of the Document,
+unaltered in their text and in their titles.  Section numbers
+or the equivalent are not considered part of the section titles.
+
+@item
+Delete any section Entitled ``Endorsements''.  Such a section
+may not be included in the Modified Version.
+
+@item
+Do not retitle any existing section to be Entitled ``Endorsements'' or
+to conflict in title with any Invariant Section.
+
+@item
+Preserve any Warranty Disclaimers.
+@end enumerate
+
+If the Modified Version includes new front-matter sections or
+appendices that qualify as Secondary Sections and contain no material
+copied from the Document, you may at your option designate some or all
+of these sections as invariant.  To do this, add their titles to the
+list of Invariant Sections in the Modified Version's license notice.
+These titles must be distinct from any other section titles.
+
+You may add a section Entitled ``Endorsements'', provided it contains
+nothing but endorsements of your Modified Version by various
+parties---for example, statements of peer review or that the text has
+been approved by an organization as the authoritative definition of a
+standard.
+
+You may add a passage of up to five words as a Front-Cover Text, and a
+passage of up to 25 words as a Back-Cover Text, to the end of the list
+of Cover Texts in the Modified Version.  Only one passage of
+Front-Cover Text and one of Back-Cover Text may be added by (or
+through arrangements made by) any one entity.  If the Document already
+includes a cover text for the same cover, previously added by you or
+by arrangement made by the same entity you are acting on behalf of,
+you may not add another; but you may replace the old one, on explicit
+permission from the previous publisher that added the old one.
+
+The author(s) and publisher(s) of the Document do not by this License
+give permission to use their names for publicity for or to assert or
+imply endorsement of any Modified Version.
+
+@item
+COMBINING DOCUMENTS
+
+You may combine the Document with other documents released under this
+License, under the terms defined in section 4 above for modified
+versions, provided that you include in the combination all of the
+Invariant Sections of all of the original documents, unmodified, and
+list them all as Invariant Sections of your combined work in its
+license notice, and that you preserve all their Warranty Disclaimers.
+
+The combined work need only contain one copy of this License, and
+multiple identical Invariant Sections may be replaced with a single
+copy.  If there are multiple Invariant Sections with the same name but
+different contents, make the title of each such section unique by
+adding at the end of it, in parentheses, the name of the original
+author or publisher of that section if known, or else a unique number.
+Make the same adjustment to the section titles in the list of
+Invariant Sections in the license notice of the combined work.
+
+In the combination, you must combine any sections Entitled ``History''
+in the various original documents, forming one section Entitled
+``History''; likewise combine any sections Entitled ``Acknowledgements'',
+and any sections Entitled ``Dedications''.  You must delete all
+sections Entitled ``Endorsements.''
+
+@item
+COLLECTIONS OF DOCUMENTS
+
+You may make a collection consisting of the Document and other documents
+released under this License, and replace the individual copies of this
+License in the various documents with a single copy that is included in
+the collection, provided that you follow the rules of this License for
+verbatim copying of each of the documents in all other respects.
+
+You may extract a single document from such a collection, and distribute
+it individually under this License, provided you insert a copy of this
+License into the extracted document, and follow this License in all
+other respects regarding verbatim copying of that document.
+
+@item
+AGGREGATION WITH INDEPENDENT WORKS
+
+A compilation of the Document or its derivatives with other separate
+and independent documents or works, in or on a volume of a storage or
+distribution medium, is called an ``aggregate'' if the copyright
+resulting from the compilation is not used to limit the legal rights
+of the compilation's users beyond what the individual works permit.
+When the Document is included in an aggregate, this License does not
+apply to the other works in the aggregate which are not themselves
+derivative works of the Document.
+
+If the Cover Text requirement of section 3 is applicable to these
+copies of the Document, then if the Document is less than one half of
+the entire aggregate, the Document's Cover Texts may be placed on
+covers that bracket the Document within the aggregate, or the
+electronic equivalent of covers if the Document is in electronic form.
+Otherwise they must appear on printed covers that bracket the whole
+aggregate.
+
+@item
+TRANSLATION
+
+Translation is considered a kind of modification, so you may
+distribute translations of the Document under the terms of section 4.
+Replacing Invariant Sections with translations requires special
+permission from their copyright holders, but you may include
+translations of some or all Invariant Sections in addition to the
+original versions of these Invariant Sections.  You may include a
+translation of this License, and all the license notices in the
+Document, and any Warranty Disclaimers, provided that you also include
+the original English version of this License and the original versions
+of those notices and disclaimers.  In case of a disagreement between
+the translation and the original version of this License or a notice
+or disclaimer, the original version will prevail.
+
+If a section in the Document is Entitled ``Acknowledgements'',
+``Dedications'', or ``History'', the requirement (section 4) to Preserve
+its Title (section 1) will typically require changing the actual
+title.
+
+@item
+TERMINATION
+
+You may not copy, modify, sublicense, or distribute the Document except
+as expressly provided for under this License.  Any other attempt to
+copy, modify, sublicense or distribute the Document is void, and will
+automatically terminate your rights under this License.  However,
+parties who have received copies, or rights, from you under this
+License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+@item
+FUTURE REVISIONS OF THIS LICENSE
+
+The Free Software Foundation may publish new, revised versions
+of the GNU Free Documentation License from time to time.  Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.  See
+@uref{http://www.gnu.org/copyleft/}.
+
+Each version of the License is given a distinguishing version number.
+If the Document specifies that a particular numbered version of this
+License ``or any later version'' applies to it, you have the option of
+following the terms and conditions either of that specified version or
+of any later version that has been published (not as a draft) by the
+Free Software Foundation.  If the Document does not specify a version
+number of this License, you may choose any version ever published (not
+as a draft) by the Free Software Foundation.
+@end enumerate
+
+@page
+@appendixsubsec ADDENDUM: How to use this License for your documents
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and
+license notices just after the title page:
+
+@smallexample
+@group
+  Copyright (C)  @var{year}  @var{your name}.
+  Permission is granted to copy, distribute and/or modify this document
+  under the terms of the GNU Free Documentation License, Version 1.2
+  or any later version published by the Free Software Foundation;
+  with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+  Texts.  A copy of the license is included in the section entitled ``GNU
+  Free Documentation License''.
+@end group
+@end smallexample
+
+If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
+replace the ``with...Texts.'' line with this:
+
+@smallexample
+@group
+    with the Invariant Sections being @var{list their titles}, with
+    the Front-Cover Texts being @var{list}, and with the Back-Cover Texts
+    being @var{list}.
+@end group
+@end smallexample
+
+If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
+
+If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of
+free software license, such as the GNU General Public License,
+to permit their use in free software.
+
+@c Local Variables:
+@c ispell-local-pdict: "ispell-dict"
+@c End:
+
diff --git a/docs/grub.cfg b/docs/grub.cfg
new file mode 100644 (file)
index 0000000..7f02727
--- /dev/null
@@ -0,0 +1,69 @@
+#
+# Sample GRUB configuration file
+#
+
+# Boot automatically after 30 secs.
+set timeout=30
+
+# By default, boot the first entry.
+set default=0
+
+# Fallback to the second entry.
+set fallback=1
+
+# For booting GNU/Hurd
+menuentry "GNU (aka GNU/Hurd)" {
+       set root=(hd0,1)
+       multiboot /boot/gnumach.gz root=device:hd0s1
+       module /hurd/ext2fs.static --readonly \
+                       --multiboot-command-line='${kernel-command-line}' \
+                       --host-priv-port='${host-port}' \
+                       --device-master-port='${device-port}' \
+                       --exec-server-task='${exec-task}' -T typed '${root}' \
+                       '$(task-create)' '$(task-resume)'
+       module /lib/ld.so.1 /hurd/exec '$(exec-task=task-create)'
+}
+
+# For booting GNU/Linux
+menuentry "GNU/Linux" {
+       set root=(hd0,1)
+       linux /vmlinuz root=/dev/sda1
+       initrd /initrd.img
+}
+
+# For booting FreeBSD
+menuentry "FreeBSD (or GNU/kFreeBSD), direct boot" {
+       set root=(hd0,1,a)
+       freebsd /boot/kernel/kernel
+       freebsd_loadenv /boot/device.hints
+       freebsd_module /boot/splash.bmp type=splash_image_data
+       set FreeBSD.vfs.root.mountfrom=ufs:ad0s1a
+}
+menuentry "FreeBSD (or GNU/kFreeBSD), via /boot/loader" {
+       set root=(hd0,1,a)
+       freebsd /boot/loader
+}
+
+# For booting NetBSD
+menuentry "NetBSD" {
+       set root=(hd0,1,a)
+       netbsd /netbsd
+}
+
+# For booting OpenBSD
+menuentry "OpenBSD" {
+       set root=(hd0,1,a)
+       openbsd /bsd
+}
+
+# For booting Microsoft Windows
+menuentry "Microsoft Windows" {
+       set root=(hd0,1)
+       chainloader +1
+}
+
+# Change the colors.
+menuentry "Change the colors" {
+       set menu_color_normal=light-green/brown
+       set menu_color_highlight=red/blue
+}
diff --git a/docs/grub.texi b/docs/grub.texi
new file mode 100644 (file)
index 0000000..b8f74a0
--- /dev/null
@@ -0,0 +1,3967 @@
+\input texinfo
+@c -*-texinfo-*-
+@c %**start of header
+@setfilename grub.info
+@include version.texi
+@settitle GNU GRUB Manual @value{VERSION}
+@c Unify all our little indices for now.
+@syncodeindex fn cp
+@syncodeindex vr cp
+@syncodeindex ky cp
+@syncodeindex pg cp
+@syncodeindex tp cp
+@c %**end of header
+
+@footnotestyle separate
+@paragraphindent 3
+@finalout
+
+@copying
+This manual is for GNU GRUB (version @value{VERSION},
+@value{UPDATED}).
+
+Copyright @copyright{} 1999,2000,2001,2002,2004,2006,2008 Free Software Foundation, Inc.
+
+@quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.2 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections.
+@end quotation
+@end copying
+
+@dircategory Kernel
+@direntry
+* GRUB: (grub).                 The GRand Unified Bootloader
+* grub-install: (grub)Invoking grub-install.    Install GRUB on your drive
+* grub-md5-crypt: (grub)Invoking grub-md5-crypt.        Encrypt a password
+                                                        in MD5 format
+* grub-terminfo: (grub)Invoking grub-terminfo.  Generate a terminfo
+                                                command from a
+                                                terminfo name
+* grub-set-default: (grub)Invoking grub-set-default.    Set a default boot
+                                                        entry
+* mbchk: (grub)Invoking mbchk.  Check for the format of a Multiboot kernel
+@end direntry
+
+@setchapternewpage odd
+
+@titlepage
+@sp 10
+@title the GNU GRUB manual
+@subtitle The GRand Unified Bootloader, version @value{VERSION}, @value{UPDATED}.
+@author Gordon Matzigkeit
+@author Yoshinori K. Okuji
+@c The following two commands start the copyright page.
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+@end titlepage
+
+@c Output the table of contents at the beginning.
+@contents
+
+@finalout
+@headings double
+
+@ifnottex
+@node Top
+@top GNU GRUB manual
+
+This is the documentation of GNU GRUB, the GRand Unified Bootloader,
+a flexible and powerful boot loader program for a wide range of
+architectures.
+
+This edition documents version @value{VERSION}.
+
+@insertcopying
+@end ifnottex
+
+@menu
+* Introduction::                Capturing the spirit of GRUB
+* Naming convention::           Names of your drives in GRUB
+* Installation::                Installing GRUB on your drive
+* Booting::                     How to boot different operating systems
+* Configuration::               Writing your own configuration file
+* Network::                     Downloading OS images from a network
+* Serial terminal::             Using GRUB via a serial line
+* Preset Menu::                 Embedding a configuration file into GRUB
+* Security::                    Improving the security
+* Images::                      GRUB image files
+* Filesystem::                  Filesystem syntax and semantics
+* Interface::                   The menu and the command-line
+* Commands::                    The list of available builtin commands
+* Troubleshooting::             Error messages produced by GRUB
+* Invoking the grub shell::     How to use the grub shell
+* Invoking grub-install::       How to use the GRUB installer
+* Invoking grub-md5-crypt::     How to generate a cryptic password
+* Invoking grub-terminfo::      How to generate a terminfo command
+* Invoking grub-set-default::   How to set a default boot entry
+* Invoking mbchk::              How to use the Multiboot checker
+* Obtaining and Building GRUB:: How to obtain and build GRUB
+* Reporting bugs::              Where you should send a bug report
+* Future::                      Some future plans on GRUB
+* Internals::                   Hacking GRUB
+* Copying This Manual::         Copying This Manual
+* Index::
+@end menu
+
+
+@node Introduction
+@chapter Introduction to GRUB
+
+@menu
+* Overview::                    What exactly GRUB is and how to use it
+* History::                     From maggot to house fly
+* Features::                    GRUB features
+* Role of a boot loader::       The role of a boot loader
+@end menu
+
+
+@node Overview
+@section Overview
+
+Briefly, a @dfn{boot loader} is the first software program that runs when
+a computer starts.  It is responsible for loading and transferring
+control to an operating system @dfn{kernel} software (such as Linux or
+GNU Mach).  The kernel, in turn, initializes the rest of the operating
+system (e.g. a GNU system).
+
+GNU GRUB is a very powerful boot loader, which can load a wide variety
+of free operating systems, as well as proprietary operating systems with
+chain-loading@footnote{@dfn{chain-load} is the mechanism for loading
+unsupported operating systems by loading another boot loader. It is
+typically used for loading DOS or Windows.}. GRUB is designed to
+address the complexity of booting a personal computer; both the
+program and this manual are tightly bound to that computer platform,
+although porting to other platforms may be addressed in the future.
+
+One of the important features in GRUB is flexibility; GRUB understands
+filesystems and kernel executable formats, so you can load an arbitrary
+operating system the way you like, without recording the physical
+position of your kernel on the disk. Thus you can load the kernel
+just by specifying its file name and the drive and partition where the
+kernel resides.
+
+When booting with GRUB, you can use either a command-line interface
+(@pxref{Command-line interface}), or a menu interface (@pxref{Menu
+interface}). Using the command-line interface, you type the drive
+specification and file name of the kernel manually. In the menu
+interface, you just select an OS using the arrow keys. The menu is
+based on a configuration file which you prepare beforehand
+(@pxref{Configuration}). While in the menu, you can switch to the
+command-line mode, and vice-versa. You can even edit menu entries
+before using them.
+
+In the following chapters, you will learn how to specify a drive, a
+partition, and a file name (@pxref{Naming convention}) to GRUB, how to
+install GRUB on your drive (@pxref{Installation}), and how to boot your
+OSes (@pxref{Booting}), step by step.
+
+Besides the GRUB boot loader itself, there is a @dfn{grub shell}
+@command{grub} (@pxref{Invoking the grub shell}) which can be run when
+you are in your operating system. It emulates the boot loader and can
+be used for installing the boot loader.
+
+
+@node History
+@section History of GRUB
+
+GRUB originated in 1995 when Erich Boleyn was trying to boot the GNU
+Hurd with the University of Utah's Mach 4 microkernel (now known as GNU
+Mach).  Erich and Brian Ford designed the Multiboot Specification
+(@pxref{Top, Multiboot Specification, Motivation, multiboot, The Multiboot
+Specification}), because they were determined not to add to the large
+number of mutually-incompatible PC boot methods.
+
+Erich then began modifying the FreeBSD boot loader so that it would
+understand Multiboot. He soon realized that it would be a lot easier
+to write his own boot loader from scratch than to keep working on the
+FreeBSD boot loader, and so GRUB was born.
+
+Erich added many features to GRUB, but other priorities prevented him
+from keeping up with the demands of its quickly-expanding user base. In
+1999, Gordon Matzigkeit and Yoshinori K. Okuji adopted GRUB as an
+official GNU package, and opened its development by making the latest
+sources available via anonymous CVS. @xref{Obtaining and Building
+GRUB}, for more information.
+
+
+@node Features
+@section GRUB features
+
+The primary requirement for GRUB is that it be compliant with the
+@dfn{Multiboot Specification}, which is described in @ref{Top, Multiboot
+Specification, Motivation, multiboot, The Multiboot Specification}.
+
+The other goals, listed in approximate order of importance, are:
+
+@itemize @bullet{}
+@item
+Basic functions must be straightforward for end-users.
+
+@item
+Rich functionality to support kernel experts and designers.
+
+@item
+Backward compatibility for booting FreeBSD, NetBSD, OpenBSD, and
+Linux. Proprietary kernels (such as DOS, Windows NT, and OS/2) are
+supported via a chain-loading function.
+@end itemize
+
+Except for specific compatibility modes (chain-loading and the Linux
+@dfn{piggyback} format), all kernels will be started in much the same
+state as in the Multiboot Specification. Only kernels loaded at 1 megabyte
+or above are presently supported. Any attempt to load below that
+boundary will simply result in immediate failure and an error message
+reporting the problem.
+
+In addition to the requirements above, GRUB has the following features
+(note that the Multiboot Specification doesn't require all the features
+that GRUB supports):
+
+@table @asis
+@item Recognize multiple executable formats
+Support many of the @dfn{a.out} variants plus @dfn{ELF}. Symbol
+tables are also loaded.
+
+@item Support non-Multiboot kernels
+Support many of the various free 32-bit kernels that lack Multiboot
+compliance (primarily FreeBSD, NetBSD, OpenBSD, and
+Linux). Chain-loading of other boot loaders is also supported.
+
+@item Load multiples modules
+Fully support the Multiboot feature of loading multiple modules.
+
+@item Load a configuration file
+Support a human-readable text configuration file with preset boot
+commands. You can also load another configuration file dynamically and
+embed a preset configuration file in a GRUB image file. The list of
+commands (@pxref{Commands}) are a superset of those supported on the
+command-line. An example configuration file is provided in
+@ref{Configuration}.
+
+@item Provide a menu interface
+A menu interface listing preset boot commands, with a programmable
+timeout, is available. There is no fixed limit on the number of boot
+entries, and the current implementation has space for several hundred.
+
+@item Have a flexible command-line interface
+A fairly flexible command-line interface, accessible from the menu,
+is available to edit any preset commands, or write a new boot command
+set from scratch. If no configuration file is present, GRUB drops to
+the command-line.
+
+The list of commands (@pxref{Commands}) are a subset of those supported
+for configuration files. Editing commands closely resembles the Bash
+command-line (@pxref{Command Line Editing, Bash, Command Line Editing,
+features, Bash Features}), with @key{TAB}-completion of commands,
+devices, partitions, and files in a directory depending on context.
+
+@item Support multiple filesystem types
+Support multiple filesystem types transparently, plus a useful explicit
+blocklist notation. The currently supported filesystem types are
+@dfn{BSD FFS}, @dfn{DOS FAT16 and FAT32}, @dfn{Minix fs}, @dfn{Linux
+ext2fs}, @dfn{ReiserFS}, @dfn{JFS}, @dfn{XFS}, and @dfn{VSTa
+fs}. @xref{Filesystem}, for more information.
+
+@item Support automatic decompression
+Can decompress files which were compressed by @command{gzip}. This
+function is both automatic and transparent to the user (i.e. all
+functions operate upon the uncompressed contents of the specified
+files). This greatly reduces a file size and loading time, a
+particularly great benefit for floppies.@footnote{There are a few
+pathological cases where loading a very badly organized ELF kernel might
+take longer, but in practice this never happen.}
+
+It is conceivable that some kernel modules should be loaded in a
+compressed state, so a different module-loading command can be specified
+to avoid uncompressing the modules.
+
+@item Access data on any installed device
+Support reading data from any or all floppies or hard disk(s) recognized
+by the BIOS, independent of the setting of the root device.
+
+@item Be independent of drive geometry translations
+Unlike many other boot loaders, GRUB makes the particular drive
+translation irrelevant. A drive installed and running with one
+translation may be converted to another translation without any adverse
+effects or changes in GRUB's configuration.
+
+@item Detect all installed @sc{ram}
+GRUB can generally find all the installed @sc{ram} on a PC-compatible
+machine. It uses an advanced BIOS query technique for finding all
+memory regions. As described on the Multiboot Specification (@pxref{Top,
+Multiboot Specification, Motivation, multiboot, The Multiboot
+Specification}), not all kernels make use of this information, but GRUB
+provides it for those who do.
+
+@item Support Logical Block Address mode
+In traditional disk calls (called @dfn{CHS mode}), there is a geometry
+translation problem, that is, the BIOS cannot access over 1024
+cylinders, so the accessible space is limited to at least 508 MB and to
+at most 8GB. GRUB can't universally solve this problem, as there is no
+standard interface used in all machines. However, several newer machines
+have the new interface, Logical Block Address (@dfn{LBA}) mode. GRUB
+automatically detects if LBA mode is available and uses it if
+available. In LBA mode, GRUB can access the entire disk.
+
+@item Support network booting
+GRUB is basically a disk-based boot loader but also has network
+support. You can load OS images from a network by using the @dfn{TFTP}
+protocol.
+
+@item Support remote terminals
+To support computers with no console, GRUB provides remote terminal
+support, so that you can control GRUB from a remote host. Only serial
+terminal support is implemented at the moment.
+@end table
+
+
+@node Role of a boot loader
+@section The role of a boot loader
+
+The following is a quotation from Gordon Matzigkeit, a GRUB fanatic:
+
+@quotation
+Some people like to acknowledge both the operating system and kernel when
+they talk about their computers, so they might say they use
+``GNU/Linux'' or ``GNU/Hurd''.  Other people seem to think that the
+kernel is the most important part of the system, so they like to call
+their GNU operating systems ``Linux systems.''
+
+I, personally, believe that this is a grave injustice, because the
+@emph{boot loader} is the most important software of all. I used to
+refer to the above systems as either ``LILO''@footnote{The LInux LOader,
+a boot loader that everybody uses, but nobody likes.} or ``GRUB''
+systems.
+
+Unfortunately, nobody ever understood what I was talking about; now I
+just use the word ``GNU'' as a pseudonym for GRUB.
+
+So, if you ever hear people talking about their alleged ``GNU'' systems,
+remember that they are actually paying homage to the best boot loader
+around@dots{} GRUB!
+@end quotation
+
+We, the GRUB maintainers, do not (usually) encourage Gordon's level of
+fanaticism, but it helps to remember that boot loaders deserve
+recognition.  We hope that you enjoy using GNU GRUB as much as we did
+writing it.
+
+
+@node Naming convention
+@chapter Naming convention
+
+The device syntax used in GRUB is a wee bit different from what you may
+have seen before in your operating system(s), and you need to know it so
+that you can specify a drive/partition.
+
+Look at the following examples and explanations:
+
+@example
+(fd0)
+@end example
+
+First of all, GRUB requires that the device name be enclosed with
+@samp{(} and @samp{)}. The @samp{fd} part means that it is a floppy
+disk. The number @samp{0} is the drive number, which is counted from
+@emph{zero}. This expression means that GRUB will use the whole floppy
+disk.
+
+@example
+(hd0,1)
+@end example
+
+Here, @samp{hd} means it is a hard disk drive. The first integer
+@samp{0} indicates the drive number, that is, the first hard disk, while
+the second integer, @samp{1}, indicates the partition number (or the
+@sc{pc} slice number in the BSD terminology). Once again, please note
+that the partition numbers are counted from @emph{zero}, not from
+one. This expression means the second partition of the first hard disk
+drive. In this case, GRUB uses one partition of the disk, instead of the
+whole disk.
+
+@example
+(hd0,4)
+@end example
+
+This specifies the first @dfn{extended partition} of the first hard disk
+drive. Note that the partition numbers for extended partitions are
+counted from @samp{4}, regardless of the actual number of primary
+partitions on your hard disk.
+
+@example
+(hd1,a)
+@end example
+
+This means the BSD @samp{a} partition of the second hard disk. If you
+need to specify which @sc{pc} slice number should be used, use something
+like this: @samp{(hd1,0,a)}. If the @sc{pc} slice number is omitted,
+GRUB searches for the first @sc{pc} slice which has a BSD @samp{a}
+partition.
+
+Of course, to actually access the disks or partitions with GRUB, you
+need to use the device specification in a command, like @samp{root
+(fd0)} or @samp{unhide (hd0,2)}. To help you find out which number
+specifies a partition you want, the GRUB command-line
+(@pxref{Command-line interface}) options have argument
+completion. This means that, for example, you only need to type
+
+@example
+root (
+@end example
+
+followed by a @key{TAB}, and GRUB will display the list of drives,
+partitions, or file names. So it should be quite easy to determine the
+name of your target partition, even with minimal knowledge of the
+syntax.
+
+Note that GRUB does @emph{not} distinguish IDE from SCSI - it simply
+counts the drive numbers from zero, regardless of their type. Normally,
+any IDE drive number is less than any SCSI drive number, although that
+is not true if you change the boot sequence by swapping IDE and SCSI
+drives in your BIOS.
+
+Now the question is, how to specify a file? Again, consider an
+example:
+
+@example
+(hd0,0)/vmlinuz
+@end example
+
+This specifies the file named @samp{vmlinuz}, found on the first
+partition of the first hard disk drive. Note that the argument
+completion works with file names, too.
+
+That was easy, admit it. Now read the next chapter, to find out how to
+actually install GRUB on your drive.
+
+
+@node Installation
+@chapter Installation
+
+In order to install GRUB as your boot loader, you need to first
+install the GRUB system and utilities under your UNIX-like operating
+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).
+
+GRUB comes with boot images, which are normally put in the directory
+@file{/usr/lib/grub/i386-pc}. If you do not use grub-install, then
+you need to copy the files @file{stage1}, @file{stage2}, and
+@file{*stage1_5} to the directory @file{/boot/grub}, and run the
+@command{grub-set-default} (@pxref{Invoking grub-set-default}) if you
+intend to use @samp{default saved} (@pxref{default}) in your
+configuration file. Hereafter, the directory where GRUB images are
+initially placed (normally @file{/usr/lib/grub/i386-pc}) 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
+the @dfn{boot directory}.
+
+@menu
+* Creating a GRUB boot floppy::
+* Installing GRUB natively::
+* Installing GRUB using grub-install::
+* Making a GRUB bootable CD-ROM::
+@end menu
+
+
+@node Creating a GRUB boot floppy
+@section Creating a GRUB boot floppy
+
+To create a GRUB boot floppy, you need to take the files @file{stage1}
+and @file{stage2} from the image directory, and write them to the first
+and the second block of the floppy disk, respectively.
+
+@strong{Caution:} This procedure will destroy any data currently stored
+on the floppy.
+
+On a UNIX-like operating system, that is done with the following
+commands:
+
+@example
+@group
+# @kbd{cd /usr/lib/grub/i386-pc}
+# @kbd{dd if=stage1 of=/dev/fd0 bs=512 count=1}
+1+0 records in
+1+0 records out
+# @kbd{dd if=stage2 of=/dev/fd0 bs=512 seek=1}
+153+1 records in
+153+1 records out
+#
+@end group
+@end example
+
+The device file name may be different. Consult the manual for your OS.
+
+
+@node Installing GRUB natively
+@section Installing GRUB natively
+
+@strong{Caution:} Installing GRUB's stage1 in this manner will erase the
+normal boot-sector used by an OS.
+
+GRUB can currently boot GNU Mach, Linux, FreeBSD, NetBSD, and OpenBSD
+directly, so using it on a boot sector (the first sector of a
+partition) should be okay. But generally, it would be a good idea to
+back up the first sector of the partition on which you are installing
+GRUB's stage1. This isn't as important if you are installing GRUB on
+the first sector of a hard disk, since it's easy to reinitialize it
+(e.g. by running @samp{FDISK /MBR} from DOS).
+
+If you decide to install GRUB in the native environment, which is
+definitely desirable, you'll need to create a GRUB boot disk, and
+reboot your computer with it. Otherwise, see @ref{Installing GRUB using
+grub-install}.
+
+Once started, GRUB will show the command-line interface
+(@pxref{Command-line interface}). First, set the GRUB's @dfn{root
+device}@footnote{Note that GRUB's root device doesn't necessarily mean
+your OS's root partition; if you need to specify a root partition for
+your OS, add the argument into the command @command{kernel}.} to the
+partition containing the boot directory, like this:
+
+@example
+grub> @kbd{root (hd0,0)}
+@end example
+
+If you are not sure which partition actually holds this directory, use the
+command @command{find} (@pxref{find}), like this:
+
+@example
+grub> @kbd{find /boot/grub/stage1}
+@end example
+
+This will search for the file name @file{/boot/grub/stage1} and show the
+devices which contain the file.
+
+Once you've set the root device correctly, run the command
+@command{setup} (@pxref{setup}):
+
+@example
+grub> @kbd{setup (hd0)}
+@end example
+
+This command will install the GRUB boot loader on the Master Boot
+Record (MBR) of the first drive. If you want to put GRUB into the boot
+sector of a partition instead of putting it in the MBR, specify the
+partition into which you want to install GRUB:
+
+@example
+grub> @kbd{setup (hd0,0)}
+@end example
+
+If you install GRUB into a partition or a drive other than the first
+one, you must chain-load GRUB from another boot loader. Refer to the
+manual for the boot loader to know how to chain-load GRUB.
+
+After using the setup command, you will boot into GRUB without the
+GRUB floppy. See the chapter @ref{Booting} to find out how to boot
+your operating systems from GRUB.
+
+
+@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.
+
+If you still do want 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:
+
+@example
+# @kbd{grub-install /dev/hda}
+@end example
+
+Likewise, under GNU/Hurd, this has the same effect:
+
+@example
+# @kbd{grub-install /dev/hd0}
+@end example
+
+If it is the first BIOS drive, this is the same as well:
+
+@example
+# @kbd{grub-install '(hd0)'}
+@end example
+
+Or you can omit the parentheses:
+
+@example
+# @kbd{grub-install 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
+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{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.
+
+Note that @command{grub-install} is actually just a shell script and the
+real task is done by the grub shell @command{grub} (@pxref{Invoking the
+grub shell}). Therefore, you may run @command{grub} directly to install
+GRUB, without using @command{grub-install}. Don't do that, however,
+unless you are very familiar with the internals of GRUB. Installing a
+boot loader on a running OS may be extremely dangerous.
+
+
+@node Making a GRUB bootable CD-ROM
+@section Making a GRUB bootable CD-ROM
+
+GRUB supports the @dfn{no emulation mode} in the El Torito
+specification@footnote{El Torito is a specification for bootable CD
+using BIOS functions.}. This means that you can use the whole CD-ROM
+from GRUB and you don't have to make a floppy or hard disk image file,
+which can cause compatibility problems.
+
+For booting from a CD-ROM, GRUB uses a special Stage 2 called
+@file{stage2_eltorito}. The only GRUB files you need to have in your 
+bootable CD-ROM are this @file{stage2_eltorito} and optionally a config file
+@file{menu.lst}. You don't need to use @file{stage1} or @file{stage2},
+because El Torito is quite different from the standard boot process.
+
+Here is an example of procedures to make a bootable CD-ROM
+image. First, make a top directory for the bootable image, say,
+@samp{iso}:
+
+@example
+$ @kbd{mkdir iso}
+@end example
+
+Make a directory for GRUB:
+
+@example
+$ @kbd{mkdir -p iso/boot/grub}
+@end example
+
+Copy the file @file{stage2_eltorito}:
+
+@example
+$ @kbd{cp /usr/lib/grub/i386-pc/stage2_eltorito iso/boot/grub}
+@end example
+
+If desired, make the config file @file{menu.lst} under @file{iso/boot/grub}
+(@pxref{Configuration}), and copy any files and directories for the disc to the
+directory @file{iso/}.
+
+Finally, make a ISO9660 image file like this:
+
+@example
+$ @kbd{mkisofs -R -b boot/grub/stage2_eltorito -no-emul-boot \
+    -boot-load-size 4 -boot-info-table -o grub.iso iso}
+@end example
+
+This produces a file named @file{grub.iso}, which then can be burned
+into a CD (or a DVD).  @kbd{mkisofs} has already set up the disc to boot
+from the @kbd{boot/grub/stage2_eltorito} file, so there is no need to 
+setup GRUB on the disc.  (Note that the @kbd{-boot-load-size 4} bit is
+required for compatibility with the BIOS on many older machines.)
+
+You can use the device @samp{(cd)} to access a CD-ROM in your
+config file. This is not required; GRUB automatically sets the root device 
+to @samp{(cd)} when booted from a CD-ROM. It is only necessary to refer to 
+@samp{(cd)} if you want to access other drives as well.
+
+
+@node Booting
+@chapter Booting
+
+GRUB can load Multiboot-compliant kernels in a consistent way,
+but for some free operating systems you need to use some OS-specific
+magic.
+
+@menu
+* General boot methods::        How to boot OSes with GRUB generally
+* OS-specific notes::           Notes on some operating systems
+* Making your system robust::   How to make your system robust
+@end menu
+
+
+@node General boot methods
+@section How to boot operating systems
+
+GRUB has two distinct boot methods. One of the two is to load an
+operating system directly, and the other is to chain-load another boot
+loader which then will load an operating system actually. Generally
+speaking, the former is more desirable, because you don't need to
+install or maintain other boot loaders and GRUB is flexible enough to
+load an operating system from an arbitrary disk/partition. However,
+the latter is sometimes required, since GRUB doesn't support all the
+existing operating systems natively.
+
+@menu
+* Loading an operating system directly::
+* Chain-loading::
+@end menu
+
+
+@node Loading an operating system directly
+@subsection How to boot an OS directly with GRUB
+
+Multiboot (@pxref{Top, Multiboot Specification, Motivation, multiboot,
+The Multiboot Specification}) is the native format supported by GRUB.
+For the sake of convenience, there is also support for Linux, FreeBSD,
+NetBSD and OpenBSD. If you want to boot other operating systems, you
+will have to chain-load them (@pxref{Chain-loading}).
+
+Generally, GRUB can boot any Multiboot-compliant OS in the following
+steps:
+
+@enumerate
+@item
+Set GRUB's root device to the drive where the OS images are stored with
+the command @command{root} (@pxref{root}).
+
+@item
+Load the kernel image with the command @command{kernel} (@pxref{kernel}).
+
+@item
+If you need modules, load them with the command @command{module}
+(@pxref{module}) or @command{modulenounzip} (@pxref{modulenounzip}).
+
+@item
+Run the command @command{boot} (@pxref{boot}).
+@end enumerate
+
+Linux, FreeBSD, NetBSD and OpenBSD can be booted in a similar
+manner. You load a kernel image with the command @command{kernel} and
+then run the command @command{boot}. If the kernel requires some
+parameters, just append the parameters to @command{kernel}, after the
+file name of the kernel. Also, please refer to @ref{OS-specific notes},
+for information on your OS-specific issues.
+
+
+@node Chain-loading
+@subsection Load another boot loader to boot unsupported operating systems
+
+If you want to boot an unsupported operating system (e.g. Windows 95),
+chain-load a boot loader for the operating system. Normally, the boot
+loader is embedded in the @dfn{boot sector} of the partition on which
+the operating system is installed.
+
+@enumerate
+@item
+Set GRUB's root device to the partition by the command
+@command{rootnoverify} (@pxref{rootnoverify}):
+
+@example
+grub> @kbd{rootnoverify (hd0,0)}
+@end example
+
+@item
+Set the @dfn{active} flag in the partition using the command
+@command{makeactive}@footnote{This is not necessary for most of the
+modern operating systems.} (@pxref{makeactive}):
+
+@example
+grub> @kbd{makeactive}
+@end example
+
+@item
+Load the boot loader with the command @command{chainloader}
+(@pxref{chainloader}):
+
+@example
+grub> @kbd{chainloader +1}
+@end example
+
+@samp{+1} indicates that GRUB should read one sector from the start of
+the partition. The complete description about this syntax can be found
+in @ref{Block list syntax}.
+
+@item
+Run the command @command{boot} (@pxref{boot}).
+@end enumerate
+
+However, DOS and Windows have some deficiencies, so you might have to
+use more complicated instructions. @xref{DOS/Windows}, for more
+information.
+
+
+@node OS-specific notes
+@section Some caveats on OS-specific issues
+
+Here, we describe some caveats on several operating systems.
+
+@menu
+* GNU/Hurd::
+* GNU/Linux::
+* FreeBSD::
+* NetBSD::
+* OpenBSD::
+* DOS/Windows::
+* SCO UnixWare::
+* QNX::
+@end menu
+
+
+@node GNU/Hurd
+@subsection GNU/Hurd
+
+Since GNU/Hurd is Multiboot-compliant, it is easy to boot it; there is
+nothing special about it. But do not forget that you have to specify a
+root partition to the kernel.
+
+@enumerate
+@item
+Set GRUB's root device to the same drive as GNU/Hurd's. Probably the
+command @code{find /boot/gnumach} or similar can help you
+(@pxref{find}).
+
+@item
+Load the kernel and the module, like this:
+
+@example
+@group
+grub> @kbd{kernel /boot/gnumach root=hd0s1}
+grub> @kbd{module /boot/serverboot}
+@end group
+@end example
+
+@item
+Run the command @command{boot} (@pxref{boot}).
+@end enumerate
+
+
+@node GNU/Linux
+@subsection GNU/Linux
+
+It is relatively easy to boot GNU/Linux from GRUB, because it somewhat
+resembles to boot a Multiboot-compliant OS.
+
+@enumerate
+@item
+Set GRUB's root device to the same drive as GNU/Linux's. Probably the
+command @code{find /vmlinuz} or similar can help you (@pxref{find}).
+
+@item
+Load the kernel:
+
+@example
+grub> @kbd{kernel /vmlinuz root=/dev/hda1}
+@end example
+
+If you need to specify some kernel parameters, just append them to the
+command. For example, to set @option{vga} to @samp{ext}, do this:
+
+@example
+grub> @kbd{kernel /vmlinuz root=/dev/hda1 vga=ext}
+@end example
+
+See the documentation in the Linux source tree for complete
+information on the available options.
+
+@item
+If you use an initrd, execute the command @command{initrd}
+(@pxref{initrd}) after @command{kernel}:
+
+@example
+grub> @kbd{initrd /initrd}
+@end example
+
+@item
+Finally, run the command @command{boot} (@pxref{boot}).
+@end enumerate
+
+@strong{Caution:} If you use an initrd and specify the @samp{mem=}
+option to the kernel to let it use less than actual memory size, you
+will also have to specify the same memory size to GRUB. To let GRUB know
+the size, run the command @command{uppermem} @emph{before} loading the
+kernel. @xref{uppermem}, for more information.
+
+
+@node FreeBSD
+@subsection FreeBSD
+
+GRUB can load the kernel directly, either in ELF or a.out format. But
+this is not recommended, since FreeBSD's bootstrap interface sometimes
+changes heavily, so GRUB can't guarantee to pass kernel parameters
+correctly.
+
+Thus, we'd recommend loading the very flexible loader
+@file{/boot/loader} instead. See this example:
+
+@example
+@group
+grub> @kbd{root (hd0,a)}
+grub> @kbd{kernel /boot/loader}
+grub> @kbd{boot}
+@end group
+@end example
+
+
+@node NetBSD
+@subsection NetBSD
+
+GRUB can load NetBSD a.out and ELF directly, follow these steps:
+
+@enumerate
+@item
+Set GRUB's root device with @command{root} (@pxref{root}).
+
+@item
+Load the kernel with @command{kernel} (@pxref{kernel}). You should
+append the ugly option @option{--type=netbsd}, if you want to load an
+ELF kernel, like this:
+
+@example
+grub> @kbd{kernel --type=netbsd /netbsd-elf}
+@end example
+
+@item
+Run @command{boot} (@pxref{boot}).
+@end enumerate
+
+For now, however, GRUB doesn't allow you to pass kernel parameters, so
+it may be better to chain-load it instead. For more information, please
+see @ref{Chain-loading}.
+
+
+@node OpenBSD
+@subsection OpenBSD
+
+The booting instruction is exactly the same as for NetBSD
+(@pxref{NetBSD}).
+
+
+@node DOS/Windows
+@subsection DOS/Windows
+
+GRUB cannot boot DOS or Windows directly, so you must chain-load them
+(@pxref{Chain-loading}). However, their boot loaders have some critical
+deficiencies, so it may not work to just chain-load them. To overcome
+the problems, GRUB provides you with two helper functions.
+
+If you have installed DOS (or Windows) on a non-first hard disk, you
+have to use the disk swapping technique, because that OS cannot boot
+from any disks but the first one. The workaround used in GRUB is the
+command @command{map} (@pxref{map}), like this:
+
+@example
+@group
+grub> @kbd{map (hd0) (hd1)}
+grub> @kbd{map (hd1) (hd0)}
+@end group
+@end example
+
+This performs a @dfn{virtual} swap between your first and second hard
+drive.
+
+@strong{Caution:} This is effective only if DOS (or Windows) uses BIOS
+to access the swapped disks. If that OS uses a special driver for the
+disks, this probably won't work.
+
+Another problem arises if you installed more than one set of DOS/Windows
+onto one disk, because they could be confused if there are more than one
+primary partitions for DOS/Windows. Certainly you should avoid doing
+this, but there is a solution if you do want to do so. Use the partition
+hiding/unhiding technique.
+
+If GRUB @dfn{hide}s a DOS (or Windows) partition (@pxref{hide}), DOS (or
+Windows) will ignore the partition. If GRUB @dfn{unhide}s a DOS (or
+Windows) partition (@pxref{unhide}), DOS (or Windows) will detect the
+partition. Thus, if you have installed DOS (or Windows) on the first
+and the second partition of the first hard disk, and you want to boot
+the copy on the first partition, do the following:
+
+@example
+@group
+grub> @kbd{unhide (hd0,0)}
+grub> @kbd{hide (hd0,1)}
+grub> @kbd{rootnoverify (hd0,0)}
+grub> @kbd{chainloader +1}
+grub> @kbd{makeactive}
+grub> @kbd{boot}
+@end group
+@end example
+
+
+@node SCO UnixWare
+@subsection SCO UnixWare
+
+It is known that the signature in the boot loader for SCO UnixWare is
+wrong, so you will have to specify the option @option{--force} to
+@command{chainloader} (@pxref{chainloader}), like this:
+
+@example
+@group
+grub> @kbd{rootnoverify (hd1,0)}
+grub> @kbd{chainloader --force +1}
+grub> @kbd{makeactive}
+grub> @kbd{boot}
+@end group
+@end example
+
+
+@node QNX
+@subsection QNX
+
+QNX seems to use a bigger boot loader, so you need to boot it up, like
+this:
+
+@example
+@group
+grub> @kbd{rootnoverify (hd1,1)}
+grub> @kbd{chainloader +4}
+grub> @kbd{boot}
+@end group
+@end example
+
+
+@node Making your system robust
+@section How to make your system robust
+
+When you test a new kernel or a new OS, it is important to make sure
+that your computer can boot even if the new system is unbootable. This
+is crucial especially if you maintain servers or remote systems. To
+accomplish this goal, you need to set up two things:
+
+@enumerate
+@item
+You must maintain a system which is always bootable. For instance, if
+you test a new kernel, you need to keep a working kernel in a
+different place. And, it would sometimes be very nice to even have a
+complete copy of a working system in a different partition or disk.
+
+@item
+You must direct GRUB to boot a working system when the new system
+fails. This is possible with the @dfn{fallback} system in GRUB.
+@end enumerate
+
+The former requirement is very specific to each OS, so this
+documentation does not cover that topic. It is better to consult some
+backup tools.
+
+So let's see the GRUB part. There are two possibilities: one of them
+is quite simple but not very robust, and the other is a bit complex to
+set up but probably the best solution to make sure that your system
+can start as long as GRUB itself is bootable.
+
+@menu
+* Booting once-only::
+* Booting fallback systems::
+@end menu
+
+
+@node Booting once-only
+@subsection Booting once-only
+
+You can teach GRUB to boot an entry only at next boot time. Suppose
+that your have an old kernel @file{old_kernel} and a new kernel
+@file{new_kernel}. You know that @file{old_kernel} can boot
+your system correctly, and you want to test @file{new_kernel}.
+
+To ensure that your system will go back to the old kernel even if the
+new kernel fails (e.g. it panics), you can specify that GRUB should
+try the new kernel only once and boot the old kernel after that.
+
+First, modify your configuration file. Here is an example:
+
+@example
+@group
+default saved        # This is important!!!
+timeout 10
+
+title the old kernel
+root (hd0,0)
+kernel /old_kernel
+savedefault
+
+title the new kernel
+root (hd0,0)
+kernel /new_kernel
+savedefault 0         # This is important!!!
+@end group
+@end example
+
+Note that this configuration file uses @samp{default saved}
+(@pxref{default}) at the head and @samp{savedefault 0}
+(@pxref{savedefault}) in the entry for the new kernel. This means
+that GRUB boots a saved entry by default, and booting the entry for the
+new kernel saves @samp{0} as the saved entry.
+
+With this configuration file, after all, GRUB always tries to boot the
+old kernel after it booted the new one, because @samp{0} is the entry
+of @code{the old kernel}.
+
+The next step is to tell GRUB to boot the new kernel at next boot
+time. For this, execute @command{grub-set-default} (@pxref{Invoking
+grub-set-default}):
+
+@example
+# @kbd{grub-set-default 1}
+@end example
+
+This command sets the saved entry to @samp{1}, that is, to the new
+kernel.
+
+This method is useful, but still not very robust, because GRUB stops
+booting, if there is any error in the boot entry, such that the new
+kernel has an invalid executable format. Thus, it it even better to
+use the @dfn{fallback} mechanism of GRUB. Look at next subsection for
+this feature.
+
+
+@node Booting fallback systems
+@subsection Booting fallback systems
+
+GRUB supports a fallback mechanism of booting one or more other
+entries if a default boot entry fails. You can specify multiple
+fallback entries if you wish.
+
+Suppose that you have three systems, @samp{A}, @samp{B} and
+@samp{C}. @samp{A} is a system which you want to boot by
+default. @samp{B} is a backup system which is supposed to boot
+safely. @samp{C} is another backup system which is used in case where
+@samp{B} is broken.
+
+Then you may want GRUB to boot the first system which is bootable
+among @samp{A}, @samp{B} and @samp{C}. A configuration file can be
+written in this way:
+
+@example
+@group
+default saved        # This is important!!!
+timeout 10
+fallback 1 2         # This is important!!!
+
+title A
+root (hd0,0)
+kernel /kernel
+savedefault fallback # This is important!!!
+
+title B
+root (hd1,0)
+kernel /kernel
+savedefault fallback # This is important!!!
+
+title C
+root (hd2,0)
+kernel /kernel
+savedefault
+@end group
+@end example
+
+Note that @samp{default saved} (@pxref{default}), @samp{fallback 1 2}
+and @samp{savedefault fallback} are used. GRUB will boot a saved entry
+by default and save a fallback entry as next boot entry with this
+configuration.
+
+When GRUB tries to boot @samp{A}, GRUB saves @samp{1} as next boot
+entry, because the command @command{fallback} specifies that @samp{1}
+is the first fallback entry. The entry @samp{1} is @samp{B}, so GRUB
+will try to boot @samp{B} at next boot time.
+
+Likewise, when GRUB tries to boot @samp{B}, GRUB saves @samp{2} as
+next boot entry, because @command{fallback} specifies @samp{2} as next
+fallback entry. This makes sure that GRUB will boot @samp{C} after
+booting @samp{B}.
+
+It is noteworthy that GRUB uses fallback entries both when GRUB
+itself fails in booting an entry and when @samp{A} or @samp{B} fails
+in starting up your system. So this solution ensures that your system
+is started even if GRUB cannot find your kernel or if your kernel
+panics.
+
+However, you need to run @command{grub-set-default} (@pxref{Invoking
+grub-set-default}) when @samp{A} starts correctly or you fix @samp{A}
+after it crashes, since GRUB always sets next boot entry to a fallback
+entry. You should run this command in a startup script such as
+@file{rc.local} to boot @samp{A} by default:
+
+@example
+# @kbd{grub-set-default 0}
+@end example
+
+where @samp{0} is the number of the boot entry for the system
+@samp{A}.
+
+If you want to see what is current default entry, you can look at the
+file @file{/boot/grub/default} (or @file{/grub/default} in
+some systems). Because this file is plain-text, you can just
+@command{cat} this file. But it is strongly recommended @strong{not to
+modify this file directly}, because GRUB may fail in saving a default
+entry in this file, if you change this file in an unintended
+manner. Therefore, you should use @command{grub-set-default} when you
+need to change the default entry.
+
+
+@node Configuration
+@chapter Configuration
+
+You've probably noticed that you need to type several commands to boot your
+OS. There's a solution to that - GRUB provides a menu interface
+(@pxref{Menu interface}) from which you can select an item (using arrow
+keys) that will do everything to boot an OS.
+
+To enable the menu, you need a configuration file,
+@file{menu.lst} under the boot directory. We'll analyze an example
+file.
+
+The file first contains some general settings, the menu interface
+related options. You can put these commands (@pxref{Menu-specific
+commands}) before any of the items (starting with @command{title}
+(@pxref{title})).
+
+@example
+@group
+#
+# Sample boot menu configuration file
+#
+@end group
+@end example
+
+As you may have guessed, these lines are comments. Lines starting with a
+hash character (@samp{#}), and blank lines, are ignored by GRUB.
+
+@example
+@group
+# By default, boot the first entry.
+default 0
+@end group
+@end example
+
+The first entry (here, counting starts with number zero, not one!) will
+be the default choice.
+
+@example
+@group
+# Boot automatically after 30 secs.
+timeout 30
+@end group
+@end example
+
+As the comment says, GRUB will boot automatically in 30 seconds, unless
+interrupted with a keypress.
+
+@example
+@group
+# Fallback to the second entry.
+fallback 1
+@end group
+@end example
+
+If, for any reason, the default entry doesn't work, fall back to the
+second one (this is rarely used, for obvious reasons).
+
+Note that the complete descriptions of these commands, which are menu
+interface specific, can be found in @ref{Menu-specific
+commands}. Other descriptions can be found in @ref{Commands}.
+
+Now, on to the actual OS definitions. You will see that each entry
+begins with a special command, @command{title} (@pxref{title}), and the
+action is described after it. Note that there is no command
+@command{boot} (@pxref{boot}) at the  end of each item. That is because
+GRUB automatically executes @command{boot} if it loads other commands
+successfully.
+
+The argument for the command @command{title} is used to display a short
+title/description of the entry in the menu. Since @command{title}
+displays the argument as is, you can write basically anything there.
+
+@example
+@group
+# For booting GNU/Hurd
+title  GNU/Hurd
+root   (hd0,0)
+kernel /boot/gnumach.gz root=hd0s1
+module /boot/serverboot.gz
+@end group
+@end example
+
+This boots GNU/Hurd from the first hard disk.
+
+@example
+@group
+# For booting GNU/Linux
+title  GNU/Linux
+kernel (hd1,0)/vmlinuz root=/dev/hdb1
+@end group
+@end example
+
+This boots GNU/Linux, but from the second hard disk.
+
+@example
+@group
+# For booting Mach (getting kernel from floppy)
+title  Utah Mach4 multiboot
+root   (hd0,2)
+pause  Insert the diskette now^G!!
+kernel (fd0)/boot/kernel root=hd0s3
+module (fd0)/boot/bootstrap
+@end group
+@end example
+
+This boots Mach with a kernel on a floppy, but the root filesystem at
+hd0s3. It also contains a @command{pause} line (@pxref{pause}), which
+will cause GRUB to display a prompt and delay, before actually executing
+the rest of the commands and booting.
+
+@example
+@group
+# For booting FreeBSD
+title  FreeBSD
+root   (hd0,2,a)
+kernel /boot/loader
+@end group
+@end example
+
+This item will boot FreeBSD kernel loaded from the @samp{a} partition of
+the third @sc{pc} slice of the first hard disk.
+
+@example
+@group
+# For booting OS/2
+title OS/2
+root  (hd0,1)
+makeactive
+# chainload OS/2 bootloader from the first sector
+chainloader +1
+# This is similar to "chainload", but loads a specific file
+#chainloader /boot/chain.os2
+@end group
+@end example
+
+This will boot OS/2, using a chain-loader (@pxref{Chain-loading}).
+
+@example
+@group
+# For booting Windows NT or Windows95
+title Windows NT / Windows 95 boot menu
+root        (hd0,0)
+makeactive
+chainloader +1
+# For loading DOS if Windows NT is installed
+# chainload /bootsect.dos
+@end group
+@end example
+
+The same as the above, but for Windows.
+
+@example
+@group
+# For installing GRUB into the hard disk
+title Install GRUB into the hard disk
+root    (hd0,0)
+setup   (hd0)
+@end group
+@end example
+
+This will just (re)install GRUB onto the hard disk.
+
+@example
+# Change the colors.
+title Change the colors
+color light-green/brown blink-red/blue
+@end example
+
+In the last entry, the command @command{color} is used (@pxref{color}),
+to change the menu colors (try it!). This command is somewhat special,
+because it can be used both in the command-line and in the menu. GRUB
+has several such commands, see @ref{General commands}.
+
+We hope that you now understand how to use the basic features of
+GRUB. To learn more about GRUB, see the following chapters.
+
+
+@node Network
+@chapter Downloading OS images from a network
+
+Although GRUB is a disk-based boot loader, it does provide network
+support. To use the network support, you need to enable at least one
+network driver in the GRUB build process. For more information please
+see @file{netboot/README.netboot} in the source distribution.
+
+@menu
+* General usage of network support::
+* Diskless::
+@end menu
+
+
+@node General usage of network support
+@section How to set up your network
+
+GRUB requires a file server and optionally a server that will assign an
+IP address to the machine on which GRUB is running. For the former, only
+TFTP is supported at the moment. The latter is either BOOTP, DHCP or a
+RARP server@footnote{RARP is not advised, since it cannot serve much
+information}. It is not necessary to run both the servers on one
+computer. How to configure these servers is beyond the scope of this
+document, so please refer to the manuals specific to those
+protocols/servers.
+
+If you decided to use a server to assign an IP address, set up the
+server and run @command{bootp} (@pxref{bootp}), @command{dhcp}
+(@pxref{dhcp}) or @command{rarp} (@pxref{rarp}) for BOOTP, DHCP or RARP,
+respectively. Each command will show an assigned IP address, a netmask,
+an IP address for your TFTP server and a gateway. If any of the
+addresses is wrong or it causes an error, probably the configuration of
+your servers isn't set up properly.
+
+Otherwise, run @command{ifconfig}, like this:
+
+@example
+grub> @kbd{ifconfig --address=192.168.110.23 --server=192.168.110.14}
+@end example
+
+You can also use @command{ifconfig} in conjuction with @command{bootp},
+@command{dhcp} or @command{rarp} (e.g. to reassign the server address
+manually). @xref{ifconfig}, for more details.
+
+Finally, download your OS images from your network. The network can be
+accessed using the network drive @samp{(nd)}. Everything else is very
+similar to the normal instructions (@pxref{Booting}).
+
+Here is an example:
+
+@example
+@group
+grub> @kbd{bootp}
+Probing... [NE*000]
+NE2000 base ...
+Address: 192.168.110.23    Netmask: 255.255.255.0
+Server: 192.168.110.14     Gateway: 192.168.110.1
+
+grub> @kbd{root (nd)}
+grub> @kbd{kernel /tftproot/gnumach.gz root=sd0s1}
+grub> @kbd{module /tftproot/serverboot.gz}
+grub> @kbd{boot}
+@end group
+@end example
+
+
+@node Diskless
+@section Booting from a network
+
+It is sometimes very useful to boot from a network, especially when you
+use a machine which has no local disk. In this case, you need to obtain
+a kind of Net Boot @sc{rom}, such as a PXE @sc{rom} or a free software
+package like Etherboot. Such a Boot @sc{rom} first boots the machine,
+sets up the network card installed into the machine, and downloads a
+second stage boot image from the network. Then, the second image will
+try to boot an operating system actually from the network.
+
+GRUB provides two second stage images, @file{nbgrub} and
+@file{pxegrub} (@pxref{Images}). These images are the same as the
+normal Stage 2, except that they set up a network automatically, and try
+to load a configuration file from the network, if specified. The usage
+is very simple: If the machine has a PXE @sc{rom}, use
+@file{pxegrub}. If the machine has an NBI loader such as Etherboot, use
+@file{nbgrub}. There is no difference between them except their
+formats. Since the way to load a second stage image you want to use
+should be described in the manual on your Net Boot @sc{rom}, please
+refer to the manual, for more information.
+
+However, there is one thing specific to GRUB. Namely, how to specify a
+configuration file in a BOOTP/DHCP server. For now, GRUB uses the tag
+@samp{150}, to get the name of a configuration file. The following is an
+example with a BOOTP configuration:
+
+@example
+@group
+.allhost:hd=/tmp:bf=null:\
+        :ds=145.71.35.1 145.71.32.1:\
+        :sm=255.255.254.0:\
+        :gw=145.71.35.1:\
+        :sa=145.71.35.5:
+
+foo:ht=1:ha=63655d0334a7:ip=145.71.35.127:\
+        :bf=/nbgrub:\
+        :tc=.allhost:\
+        :T150="(nd)/tftpboot/menu.lst.foo":
+@end group
+@end example
+
+Note that you should specify the drive name @code{(nd)} in the name of
+the configuration file. This is because you might change the root drive
+before downloading the configuration from the TFTP server when the
+preset menu feature is used (@pxref{Preset Menu}).
+
+See the manual of your BOOTP/DHCP server for more information. The
+exact syntax should differ a little from the example.
+
+
+@node Serial terminal
+@chapter Using GRUB via a serial line
+
+This chapter describes how to use the serial terminal support in GRUB.
+
+If you have many computers or computers with no display/keyboard, it
+could be very useful to control the computers through serial
+communications. To connect one computer with another via a serial line,
+you need to prepare a null-modem (cross) serial cable, and you may need
+to have multiport serial boards, if your computer doesn't have extra
+serial ports. In addition, a terminal emulator is also required, such as
+minicom. Refer to a manual of your operating system, for more
+information.
+
+As for GRUB, the instruction to set up a serial terminal is quite
+simple. First of all, make sure that you haven't specified the option
+@option{--disable-serial} to the configure script when you built your
+GRUB images. If you get them in binary form, probably they have serial
+terminal support already.
+
+Then, initialize your serial terminal after GRUB starts up. Here is an
+example:
+
+@example
+@group
+grub> @kbd{serial --unit=0 --speed=9600}
+grub> @kbd{terminal serial}
+@end group
+@end example
+
+The command @command{serial} initializes the serial unit 0 with the
+speed 9600bps. The serial unit 0 is usually called @samp{COM1}, so, if
+you want to use COM2, you must specify @samp{--unit=1} instead. This
+command accepts many other options, so please refer to @ref{serial},
+for more details.
+
+The command @command{terminal} (@pxref{terminal}) chooses which type of
+terminal you want to use. In the case above, the terminal will be a
+serial terminal, but you can also pass @code{console} to the command,
+as @samp{terminal serial console}. In this case, a terminal in which
+you press any key will be selected as a GRUB terminal.
+
+However, note that GRUB assumes that your terminal emulator is
+compatible with VT100 by default. This is true for most terminal
+emulators nowadays, but you should pass the option @option{--dumb} to
+the command if your terminal emulator is not VT100-compatible or
+implements few VT100 escape sequences. If you specify this option then
+GRUB provides you with an alternative menu interface, because the normal
+menu requires several fancy features of your terminal.
+
+
+@node Preset Menu
+@chapter Embedding a configuration file into GRUB
+
+GRUB supports a @dfn{preset menu} which is to be always loaded before
+starting. The preset menu feature is useful, for example, when your
+computer has no console but a serial cable. In this case, it is
+critical to set up the serial terminal as soon as possible, since you
+cannot see any message until the serial terminal begins to work. So it
+is good to run the commands @command{serial} (@pxref{serial}) and
+@command{terminal} (@pxref{terminal}) before anything else at the
+start-up time.
+
+How the preset menu works is slightly complicated:
+
+@enumerate
+@item
+GRUB checks if the preset menu feature is used, and loads the preset
+menu, if available. This includes running commands and reading boot
+entries, like an ordinary configuration file.
+
+@item
+GRUB checks if the configuration file is available. Note that this check
+is performed @strong{regardless of the existence of the preset
+menu}. The configuration file is loaded even if the preset menu was
+loaded.
+
+@item
+If the preset menu includes any boot entries, they are cleared when
+the configuration file is loaded. It doesn't matter whether the
+configuration file has any entries or no entry. The boot entries in the
+preset menu are used only when GRUB fails in loading the configuration
+file.
+@end enumerate
+
+To enable the preset menu feature, you must rebuild GRUB specifying a
+file to the configure script with the option
+@option{--enable-preset-menu}. The file has the same semantics as
+normal configuration files (@pxref{Configuration}).
+
+Another point you should take care is that the diskless support
+(@pxref{Diskless}) diverts the preset menu. Diskless images embed a
+preset menu to execute the command @command{bootp} (@pxref{bootp})
+automatically, unless you specify your own preset menu to the configure
+script. This means that you must put commands to initialize a network in
+the preset menu yourself, because diskless images don't set it up
+implicitly, when you use the preset menu explicitly.
+
+Therefore, a typical preset menu used with diskless support would be
+like this:
+
+@example
+@group
+# Set up the serial terminal, first of all.
+serial --unit=0 --speed=19200
+terminal --timeout=0 serial
+
+# Initialize the network.
+dhcp
+@end group
+@end example
+
+
+@node Security
+@chapter Protecting your computer from cracking
+
+You may be interested in how to prevent ordinary users from doing
+whatever they like, if you share your computer with other people. So
+this chapter describes how to improve the security of GRUB.
+
+One thing which could be a security hole is that the user can do too
+many things with GRUB, because GRUB allows one to modify its configuration
+and run arbitrary commands at run-time. For example, the user can even
+read @file{/etc/passwd} in the command-line interface by the command
+@command{cat} (@pxref{cat}). So it is necessary to disable all the
+interactive operations.
+
+Thus, GRUB provides a @dfn{password} feature, so that only administrators
+can start the interactive operations (i.e. editing menu entries and
+entering the command-line interface). To use this feature, you need to
+run the command @command{password} in your configuration file
+(@pxref{password}), like this:
+
+@example
+password --md5 PASSWORD
+@end example
+
+If this is specified, GRUB disallows any interactive control, until you
+press the key @key{p} and enter a correct password.  The option
+@option{--md5} tells GRUB that @samp{PASSWORD} is in MD5 format.  If it
+is omitted, GRUB assumes the @samp{PASSWORD} is in clear text.
+
+You can encrypt your password with the command @command{md5crypt}
+(@pxref{md5crypt}). For example, run the grub shell (@pxref{Invoking the
+grub shell}), and enter your password:
+
+@example
+@group
+grub> md5crypt
+Password: **********
+Encrypted: $1$U$JK7xFegdxWH6VuppCUSIb.
+@end group
+@end example
+
+Then, cut and paste the encrypted password to your configuration file.
+
+Also, you can specify an optional argument to @command{password}. See
+this example:
+
+@example
+password PASSWORD /boot/grub/menu-admin.lst
+@end example
+
+In this case, GRUB will load @file{/boot/grub/menu-admin.lst} as a
+configuration file when you enter the valid password.
+
+Another thing which may be dangerous is that any user can choose any
+menu entry. Usually, this wouldn't be problematic, but you might want to
+permit only administrators to run some of your menu entries, such as an
+entry for booting an insecure OS like DOS.
+
+GRUB provides the command @command{lock} (@pxref{lock}). This command
+always fails until you enter the valid password, so you can use it, like
+this:
+
+@example
+@group
+title Boot DOS
+lock
+rootnoverify (hd0,1)
+makeactive
+chainload +1
+@end group
+@end example
+
+You should insert @command{lock} right after @command{title}, because
+any user can execute commands in an entry until GRUB encounters
+@command{lock}.
+
+You can also use the command @command{password} instead of
+@command{lock}. In this case the boot process will ask for the password
+and stop if it was entered incorrectly.  Since the @command{password}
+takes its own @var{PASSWORD} argument this is useful if you want
+different passwords for different entries.
+
+
+@node Images
+@chapter GRUB image files
+
+GRUB consists of several images: two essential stages, optional stages
+called @dfn{Stage 1.5}, one image for bootable CD-ROM, and two network
+boot images. Here is a short overview of them. @xref{Internals}, for
+more details.
+
+@table @file
+@item stage1
+This is an essential image used for booting up GRUB. Usually, this is
+embedded in an MBR or the boot sector of a partition. Because a PC boot
+sector is 512 bytes, the size of this image is exactly 512 bytes.
+
+All @file{stage1} must do is to load Stage 2 or Stage 1.5 from a local
+disk. Because of the size restriction, @file{stage1} encodes the
+location of Stage 2 (or Stage 1.5) in a block list format, so it never
+understand any filesystem structure.
+
+@item stage2
+This is the core image of GRUB. It does everything but booting up
+itself. Usually, this is put in a filesystem, but that is not required.
+
+@item e2fs_stage1_5
+@itemx fat_stage1_5
+@itemx ffs_stage1_5
+@itemx jfs_stage1_5
+@itemx minix_stage1_5
+@itemx reiserfs_stage1_5
+@itemx vstafs_stage1_5
+@itemx xfs_stage1_5
+
+These are called @dfn{Stage 1.5}, because they serve as a bridge
+between @file{stage1} and @file{stage2}, that is to say, Stage 1.5 is
+loaded by Stage 1 and Stage 1.5 loads Stage 2. The difference between
+@file{stage1} and @file{*_stage1_5} is that the former doesn't
+understand any filesystem while the latter understands one filesystem
+(e.g. @file{e2fs_stage1_5} understands ext2fs). So you can move the
+Stage 2 image to another location safely, even after GRUB has been
+installed.
+
+While Stage 2 cannot generally be embedded in a fixed area as the size
+is so large, Stage 1.5 can be installed into the area right after an MBR,
+or the boot loader area of a ReiserFS or a FFS.
+
+@item stage2_eltorito
+This is a boot image for CD-ROMs using the @dfn{no emulation mode} in
+El Torito specification. This is identical to Stage 2, except that
+this boots up without Stage 1 and sets up a special drive @samp{(cd)}.
+
+@item nbgrub
+This is a network boot image for the Network Image Proposal used by some
+network boot loaders, such as Etherboot. This is mostly the same as
+Stage 2, but it also sets up a network and loads a configuration file
+from the network.
+
+@item pxegrub
+This is another network boot image for the Preboot Execution Environment
+used by several Netboot ROMs. This is identical to @file{nbgrub}, except
+for the format.
+@end table
+
+
+@node Filesystem
+@chapter Filesystem syntax and semantics
+
+GRUB uses a special syntax for specifying disk drives which can be
+accessed by BIOS. Because of BIOS limitations, GRUB cannot distinguish
+between IDE, ESDI, SCSI, or others. You must know yourself which BIOS
+device is equivalent to which OS device. Normally, that will be clear if
+you see the files in a device or use the command @command{find}
+(@pxref{find}).
+
+@menu
+* Device syntax::               How to specify devices
+* File name syntax::            How to specify files
+* Block list syntax::           How to specify block lists
+@end menu
+
+
+@node Device syntax
+@section How to specify devices
+
+The device syntax is like this:
+
+@example
+@code{(@var{device}[,@var{part-num}][,@var{bsd-subpart-letter}])}
+@end example
+
+@samp{[]} means the parameter is optional. @var{device} should be
+either @samp{fd} or @samp{hd} followed by a digit, like @samp{fd0}.
+But you can also set @var{device} to a hexadecimal or a decimal number
+which is a BIOS drive number, so the following are equivalent:
+
+@example
+(hd0)
+(0x80)
+(128)
+@end example
+
+@var{part-num} represents the partition number of @var{device}, starting
+from zero for primary partitions and from four for extended partitions,
+and @var{bsd-subpart-letter} represents the BSD disklabel subpartition,
+such as @samp{a} or @samp{e}.
+
+A shortcut for specifying BSD subpartitions is
+@code{(@var{device},@var{bsd-subpart-letter})}, in this case, GRUB
+searches for the first PC partition containing a BSD disklabel, then
+finds the subpartition @var{bsd-subpart-letter}. Here is an example:
+
+@example
+(hd0,a)
+@end example
+
+The syntax @samp{(hd0)} represents using the entire disk (or the
+MBR when installing GRUB), while the syntax @samp{(hd0,0)}
+represents using the first partition of the disk (or the boot sector
+of the partition when installing GRUB).
+
+If you enabled the network support, the special drive, @samp{(nd)}, is
+also available. Before using the network drive, you must initialize the
+network. @xref{Network}, for more information.
+
+If you boot GRUB from a CD-ROM, @samp{(cd)} is available. @xref{Making
+a GRUB bootable CD-ROM}, for details.
+
+
+@node File name syntax
+@section How to specify files
+
+There are two ways to specify files, by @dfn{absolute file name} and by
+@dfn{block list}.
+
+An absolute file name resembles a Unix absolute file name, using
+@samp{/} for the directory separator (not @samp{\} as in DOS). One
+example is @samp{(hd0,0)/boot/grub/menu.lst}. This means the file
+@file{/boot/grub/menu.lst} in the first partition of the first hard
+disk. If you omit the device name in an absolute file name, GRUB uses
+GRUB's @dfn{root device} implicitly. So if you set the root device to,
+say, @samp{(hd1,0)} by the command @command{root} (@pxref{root}), then
+@code{/boot/kernel} is the same as @code{(hd1,0)/boot/kernel}.
+
+
+@node Block list syntax
+@section How to specify block lists
+
+A block list is used for specifying a file that doesn't appear in the
+filesystem, like a chainloader. The syntax is
+@code{[@var{offset}]+@var{length}[,[@var{offset}]+@var{length}]@dots{}}.
+Here is an example:
+
+@example
+@code{0+100,200+1,300+300}
+@end example
+
+This represents that GRUB should read blocks 0 through 99, block 200,
+and blocks 300 through 599. If you omit an offset, then GRUB assumes
+the offset is zero.
+
+Like the file name syntax (@pxref{File name syntax}), if a blocklist
+does not contain a device name, then GRUB uses GRUB's @dfn{root
+device}. So @code{(hd0,1)+1} is the same as @code{+1} when the root
+device is @samp{(hd0,1)}.
+
+
+@node Interface
+@chapter GRUB's user interface
+
+GRUB has both a simple menu interface for choosing preset entries from a
+configuration file, and a highly flexible command-line for performing
+any desired combination of boot commands.
+
+GRUB looks for its configuration file as soon as it is loaded. If one
+is found, then the full menu interface is activated using whatever
+entries were found in the file. If you choose the @dfn{command-line} menu
+option, or if the configuration file was not found, then GRUB drops to
+the command-line interface.
+
+@menu
+* Command-line interface::      The flexible command-line interface
+* Menu interface::              The simple menu interface
+* Menu entry editor::           Editing a menu entry
+* Hidden menu interface::       The hidden menu interface
+@end menu
+
+
+@node Command-line interface
+@section The flexible command-line interface
+
+The command-line interface provides a prompt and after it an editable
+text area much like a command-line in Unix or DOS. Each command is
+immediately executed after it is entered@footnote{However, this
+behavior will be changed in the future version, in a user-invisible
+way.}. The commands (@pxref{Command-line and menu entry commands}) are a
+subset of those available in the configuration file, used with exactly
+the same syntax.
+
+Cursor movement and editing of the text on the line can be done via a
+subset of the functions available in the Bash shell:
+
+@table @key
+@item C-f
+@itemx PC right key
+Move forward one character.
+
+@item C-b
+@itemx PC left key
+Move back one character.
+
+@item C-a
+@itemx HOME
+Move to the start of the line.
+
+@item C-e
+@itemx END
+Move the the end of the line.
+
+@item C-d
+@itemx DEL
+Delete the character underneath the cursor.
+
+@item C-h
+@itemx BS
+Delete the character to the left of the cursor.
+
+@item C-k
+Kill the text from the current cursor position to the end of the line.
+
+@item C-u
+Kill backward from the cursor to the beginning of the line.
+
+@item C-y
+Yank the killed text back into the buffer at the cursor.
+
+@item C-p
+@itemx PC up key
+Move up through the history list.
+
+@item C-n
+@itemx PC down key
+Move down through the history list.
+@end table
+
+When typing commands interactively, if the cursor is within or before
+the first word in the command-line, pressing the @key{TAB} key (or
+@key{C-i}) will display a listing of the available commands, and if the
+cursor is after the first word, the @kbd{@key{TAB}} will provide a
+completion listing of disks, partitions, and file names depending on the
+context. Note that to obtain a list of drives, one must open a
+parenthesis, as @command{root (}.
+
+Note that you cannot use the completion functionality in the TFTP
+filesystem. This is because TFTP doesn't support file name listing for
+the security.
+
+
+@node Menu interface
+@section The simple menu interface
+
+The menu interface is quite easy to use. Its commands are both
+reasonably intuitive and described on screen.
+
+Basically, the menu interface provides a list of @dfn{boot entries} to
+the user to choose from. Use the arrow keys to select the entry of
+choice, then press @key{RET} to run it.  An optional timeout is
+available to boot the default entry (the first one if not set), which is
+aborted by pressing any key.
+
+Commands are available to enter a bare command-line by pressing @key{c}
+(which operates exactly like the non-config-file version of GRUB, but
+allows one to return to the menu if desired by pressing @key{ESC}) or to
+edit any of the @dfn{boot entries} by pressing @key{e}.
+
+If you protect the menu interface with a password (@pxref{Security}),
+all you can do is choose an entry by pressing @key{RET}, or press
+@key{p} to enter the password.
+
+
+@node Menu entry editor
+@section Editing a menu entry
+
+The menu entry editor looks much like the main menu interface, but the
+lines in the menu are individual commands in the selected entry instead
+of entry names.
+
+If an @key{ESC} is pressed in the editor, it aborts all the changes made
+to the configuration entry and returns to the main menu interface.
+
+When a particular line is selected, the editor places the user in a
+special version of the GRUB command-line to edit that line.  When the
+user hits @key{RET}, GRUB replaces the line in question in the boot
+entry with the changes (unless it was aborted via @key{ESC},
+in which case the changes are thrown away).
+
+If you want to add a new line to the menu entry, press @key{o} if adding
+a line after the current line or press @key{O} if before the current
+line.
+
+To delete a line, hit the key @key{d}. Although GRUB unfortunately
+does not support @dfn{undo}, you can do almost the same thing by just
+returning to the main menu.
+
+
+@node Hidden menu interface
+@section The hidden menu interface
+
+When your terminal is dumb or you request GRUB to hide the menu
+interface explicitly with the command @command{hiddenmenu}
+(@pxref{hiddenmenu}), GRUB doesn't show the menu interface (@pxref{Menu
+interface}) and automatically boots the default entry, unless
+interrupted by pressing @key{ESC}.
+
+When you interrupt the timeout and your terminal is dumb, GRUB falls
+back to the command-line interface (@pxref{Command-line interface}).
+
+
+@node Commands
+@chapter The list of available commands
+
+In this chapter, we list all commands that are available in GRUB.
+
+Commands belong to different groups. A few can only be used in
+the global section of the configuration file (or ``menu''); most
+of them can be entered on the command-line and can be used either
+anywhere in the menu or specifically in the menu entries.
+
+@menu
+* Menu-specific commands::
+* General commands::
+* Command-line and menu entry commands::
+@end menu
+
+
+@node Menu-specific commands
+@section The list of commands for the menu only
+
+The semantics used in parsing the configuration file are the following:
+
+@itemize @bullet
+@item
+The menu-specific commands have to be used before any others.
+
+@item
+The files @emph{must} be in plain-text format.
+
+@item
+@samp{#} at the beginning of a line in a configuration file means it is
+only a comment.
+
+@item
+Options are separated by spaces.
+
+@item
+All numbers can be either decimal or hexadecimal. A hexadecimal number
+must be preceded by @samp{0x}, and is case-insensitive.
+
+@item
+Extra options or text at the end of the line are ignored unless otherwise
+specified.
+
+@item
+Unrecognized commands are added to the current entry, except before entries
+start, where they are ignored.
+@end itemize
+
+These commands can only be used in the menu:
+
+@menu
+* default::                     Set the default entry
+* fallback::                    Set the fallback entry
+* hiddenmenu::                  Hide the menu interface
+* timeout::                     Set the timeout
+* title::                       Start a menu entry
+@end menu
+
+
+@node default
+@subsection default
+
+@deffn Command default num
+Set the default entry to the entry number @var{num}. Numbering starts
+from 0, and the entry number 0 is the default if the command is not
+used.
+
+You can specify @samp{saved} instead of a number. In this case, the
+default entry is the entry saved with the command
+@command{savedefault}. @xref{savedefault}, for more information.
+@end deffn
+
+
+@node fallback
+@subsection fallback
+
+@deffn Command fallback num...
+Go into unattended boot mode: if the default boot entry has any errors,
+instead of waiting for the user to do something, immediately start
+over using the @var{num} entry (same numbering as the @code{default}
+command (@pxref{default})). This obviously won't help if the machine was
+rebooted by a kernel that GRUB loaded. You can specify multiple
+fallback entry numbers.
+@end deffn
+
+
+@node hiddenmenu
+@subsection hiddenmenu
+
+@deffn Command hiddenmenu
+Don't display the menu. If the command is used, no menu will be
+displayed on the control terminal, and the default entry will be
+booted after the timeout expired. The user can still request the
+menu to be displayed by pressing @key{ESC} before the timeout
+expires. See also @ref{Hidden menu interface}.
+@end deffn
+
+
+@node timeout
+@subsection timeout
+
+@deffn Command timeout sec
+Set a timeout, in @var{sec} seconds, before automatically booting the
+default entry (normally the first entry defined).
+@end deffn
+
+
+@node title
+@subsection title
+
+@deffn Command title name @dots{}
+Start a new boot entry, and set its name to the contents of the rest of
+the line, starting with the first non-space character.
+@end deffn
+
+
+@node General commands
+@section The list of general commands
+
+Commands usable anywhere in the menu and in the command-line.
+
+@menu
+* bootp::                       Initialize a network device via BOOTP
+* color::                       Color the menu interface
+* device::                      Specify a file as a drive
+* dhcp::                        Initialize a network device via DHCP
+* hide::                        Hide a partition
+* ifconfig::                    Configure a network device manually
+* pager::                       Change the state of the internal pager
+* partnew::                     Make a primary partition
+* parttype::                    Change the type of a partition
+* password::                    Set a password for the menu interface
+* rarp::                        Initialize a network device via RARP
+* serial::                      Set up a serial device
+* setkey::                      Configure the key map
+* terminal::                    Choose a terminal
+* terminfo::                    Define escape sequences for a terminal
+* tftpserver::                  Specify a TFTP server
+* unhide::                      Unhide a partition
+@end menu
+
+
+@node bootp
+@subsection bootp
+
+@deffn Command bootp [@option{--with-configfile}]
+Initialize a network device via the @dfn{BOOTP} protocol. This command
+is only available if GRUB is compiled with netboot support. See also
+@ref{Network}.
+
+If you specify @option{--with-configfile} to this command, GRUB will
+fetch and load a configuration file specified by your BOOTP server
+with the vendor tag @samp{150}.
+@end deffn
+
+
+@node color
+@subsection color
+
+@deffn Command color normal [highlight]
+Change the menu colors. The color @var{normal} is used for most
+lines in the menu (@pxref{Menu interface}), and the color
+@var{highlight} is used to highlight the line where the cursor
+points. If you omit @var{highlight}, then the inverted color of
+@var{normal} is used for the highlighted line. The format of a color is
+@code{@var{foreground}/@var{background}}. @var{foreground} and
+@var{background} are symbolic color names. A symbolic color name must be
+one of these:
+
+@itemize @bullet
+@item
+black
+
+@item
+blue
+
+@item
+green
+
+@item
+cyan
+
+@item
+red
+
+@item
+magenta
+
+@item
+brown
+
+@item
+light-gray
+
+@strong{These below can be specified only for the foreground.}
+
+@item
+dark-gray
+
+@item
+light-blue
+
+@item
+light-green
+
+@item
+light-cyan
+
+@item
+light-red
+
+@item
+light-magenta
+
+@item
+yellow
+
+@item
+white
+@end itemize
+
+But only the first eight names can be used for @var{background}. You can
+prefix @code{blink-} to @var{foreground} if you want a blinking
+foreground color.
+
+This command can be used in the configuration file and on the command
+line, so you may write something like this in your configuration file:
+
+@example
+@group
+# Set default colors.
+color light-gray/blue black/light-gray
+
+# Change the colors.
+title OS-BS like
+color magenta/blue black/magenta
+@end group
+@end example
+@end deffn
+
+
+@node device
+@subsection device
+
+@deffn Command device drive file
+In the grub shell, specify the file @var{file} as the actual drive for a
+@sc{bios} drive @var{drive}. You can use this command to create a disk
+image, and/or to fix the drives guessed by GRUB when GRUB fails to
+determine them correctly, like this:
+
+@example
+@group
+grub> @kbd{device (fd0) /floppy-image}
+grub> @kbd{device (hd0) /dev/sd0}
+@end group
+@end example
+
+This command can be used only in the grub shell (@pxref{Invoking the
+grub shell}).
+@end deffn
+
+
+@node dhcp
+@subsection dhcp
+
+@deffn Command dhcp [--with-configfile]
+Initialize a network device via the @dfn{DHCP} protocol. Currently,
+this command is just an alias for @command{bootp}, since the two
+protocols are very similar. This command is only available if GRUB is
+compiled with netboot support. See also @ref{Network}.
+
+If you specify @option{--with-configfile} to this command, GRUB will
+fetch and load a configuration file specified by your DHCP server
+with the vendor tag @samp{150}.
+@end deffn
+
+
+@node hide
+@subsection hide
+
+@deffn Command hide partition
+Hide the partition @var{partition} by setting the @dfn{hidden} bit in
+its partition type code. This is useful only when booting DOS or Windows
+and multiple primary FAT partitions exist in one disk. See also
+@ref{DOS/Windows}.
+@end deffn
+
+
+@node ifconfig
+@subsection ifconfig
+
+@deffn Command ifconfig [@option{--server=server}] [@option{--gateway=gateway}] [@option{--mask=mask}] [@option{--address=address}]
+Configure the IP address, the netmask, the gateway, and the server
+address of a network device manually. The values must be in dotted
+decimal format, like @samp{192.168.11.178}. The order of the options is
+not important. This command shows current network configuration, if no
+option is specified. See also @ref{Network}.
+@end deffn
+
+
+@node pager
+@subsection pager
+
+@deffn Command pager [flag]
+Toggle or set the state of the internal pager. If @var{flag} is
+@samp{on}, the internal pager is enabled. If @var{flag} is @samp{off},
+it is disabled. If no argument is given, the state is toggled.
+@end deffn
+
+
+@node partnew
+@subsection partnew
+
+@deffn Command partnew part type from len
+Create a new primary partition. @var{part} is a partition specification
+in GRUB syntax (@pxref{Naming convention}); @var{type} is the partition
+type and must be a number in the range @code{0-0xff}; @var{from} is
+the starting address and @var{len} is the length, both in sector units.
+@end deffn
+
+
+@node parttype
+@subsection parttype
+
+@deffn Command parttype part type
+Change the type of an existing partition.  @var{part} is a partition
+specification in GRUB syntax (@pxref{Naming convention}); @var{type}
+is the new partition type and must be a number in the range 0-0xff.
+@end deffn
+
+
+@node password
+@subsection password
+
+@deffn Command password [@option{--md5}] passwd [new-config-file]
+If used in the first section of a menu file, disable all interactive
+editing control (menu entry editor and command-line) and entries
+protected by the command @command{lock}. If the password @var{passwd} is
+entered, it loads the @var{new-config-file} as a new config file and
+restarts the GRUB Stage 2, if @var{new-config-file} is
+specified. Otherwise, GRUB will just unlock the privileged instructions.
+You can also use this command in the script section, in which case it
+will ask for the password, before continuing.  The option
+@option{--md5} tells GRUB that @var{passwd} is encrypted with
+@command{md5crypt} (@pxref{md5crypt}).
+@end deffn
+
+
+@node rarp
+@subsection rarp
+
+@deffn Command rarp
+Initialize a network device via the @dfn{RARP} protocol.  This command
+is only available if GRUB is compiled with netboot support. See also
+@ref{Network}.
+@end deffn
+
+
+@node serial
+@subsection serial
+
+@deffn Command serial [@option{--unit=unit}] [@option{--port=port}] [@option{--speed=speed}] [@option{--word=word}] [@option{--parity=parity}] [@option{--stop=stop}] [@option{--device=dev}]
+Initialize a serial device. @var{unit} is a number in the range 0-3
+specifying which serial port to use; default is 0, which corresponds to
+the port often called COM1. @var{port} is the I/O port where the UART
+is to be found; if specified it takes precedence over @var{unit}.
+@var{speed} is the transmission speed; default is 9600. @var{word} and
+@var{stop} are the number of data bits and stop bits. Data bits must
+be in the range 5-8 and stop bits must be 1 or 2. Default is 8 data
+bits and one stop bit. @var{parity} is one of @samp{no}, @samp{odd},
+@samp{even} and defaults to @samp{no}. The option @option{--device}
+can only be used in the grub shell and is used to specify the 
+tty device to be used in the host operating system (@pxref{Invoking the
+grub shell}).
+
+The serial port is not used as a communication channel unless the
+@command{terminal} command is used (@pxref{terminal}).
+
+This command is only available if GRUB is compiled with serial
+support. See also @ref{Serial terminal}.
+@end deffn
+
+
+@node setkey
+@subsection setkey
+
+@deffn Command setkey [to_key from_key]
+Change the keyboard map. The key @var{from_key} is mapped to the key
+@var{to_key}. If no argument is specified, reset key mappings. Note that 
+this command @emph{does not} exchange the keys. If you want to exchange 
+the keys, run this command again with the arguments exchanged, like this:
+
+@example
+grub> @kbd{setkey capslock control}
+grub> @kbd{setkey control capslock}
+@end example
+
+A key must be an alphabet letter, a digit, or one of these symbols:
+@samp{escape}, @samp{exclam}, @samp{at}, @samp{numbersign},
+@samp{dollar}, @samp{percent}, @samp{caret}, @samp{ampersand},
+@samp{asterisk}, @samp{parenleft}, @samp{parenright}, @samp{minus},
+@samp{underscore}, @samp{equal}, @samp{plus}, @samp{backspace},
+@samp{tab}, @samp{bracketleft}, @samp{braceleft}, @samp{bracketright},
+@samp{braceright}, @samp{enter}, @samp{control}, @samp{semicolon},
+@samp{colon}, @samp{quote}, @samp{doublequote}, @samp{backquote},
+@samp{tilde}, @samp{shift}, @samp{backslash}, @samp{bar}, @samp{comma},
+@samp{less}, @samp{period}, @samp{greater}, @samp{slash},
+@samp{question}, @samp{alt}, @samp{space}, @samp{capslock}, @samp{FX}
+(@samp{X} is a digit), and @samp{delete}. This table describes to which
+character each of the symbols corresponds:
+
+@table @samp
+@item exclam
+@samp{!}
+
+@item at
+@samp{@@}
+
+@item numbersign
+@samp{#}
+
+@item dollar
+@samp{$}
+
+@item percent
+@samp{%}
+
+@item caret
+@samp{^}
+
+@item ampersand
+@samp{&}
+
+@item asterisk
+@samp{*}
+
+@item parenleft
+@samp{(}
+
+@item parenright
+@samp{)}
+
+@item minus
+@samp{-}
+
+@item underscore
+@samp{_}
+
+@item equal
+@samp{=}
+
+@item plus
+@samp{+}
+
+@item bracketleft
+@samp{[}
+
+@item braceleft
+@samp{@{}
+
+@item bracketright
+@samp{]}
+
+@item braceright
+@samp{@}}
+
+@item semicolon
+@samp{;}
+
+@item colon
+@samp{:}
+
+@item quote
+@samp{'}
+
+@item doublequote
+@samp{"}
+
+@item backquote
+@samp{`}
+
+@item tilde
+@samp{~}
+
+@item backslash
+@samp{\}
+
+@item bar
+@samp{|}
+
+@item comma
+@samp{,}
+
+@item less
+@samp{<}
+
+@item period
+@samp{.}
+
+@item greater
+@samp{>}
+
+@item slash
+@samp{/}
+
+@item question
+@samp{?}
+
+@item space
+@samp{ }
+@end table
+@end deffn
+
+
+@node terminal
+@subsection terminal
+
+@deffn Command terminal [@option{--dumb}] [@option{--no-echo}] [@option{--no-edit}] [@option{--timeout=secs}] [@option{--lines=lines}] [@option{--silent}] [@option{console}] [@option{serial}] [@option{hercules}]
+Select a terminal for user interaction. The terminal is assumed to be
+VT100-compatible unless @option{--dumb} is specified. If both
+@option{console} and @option{serial} are specified, then GRUB will use
+the one where a key is entered first or the first when the timeout
+expires. If neither are specified, the current setting is
+reported. This command is only available if GRUB is compiled with serial
+support. See also @ref{Serial terminal}.
+
+This may not make sense for most users, but GRUB supports Hercules
+console as well. Hercules console is usable like the ordinary console,
+and the usage is quite similar to that for serial terminals: specify
+@option{hercules} as the argument.
+
+The option @option{--lines} defines the number of lines in your
+terminal, and it is used for the internal pager function. If you don't
+specify this option, the number is assumed as 24.
+
+The option @option{--silent} suppresses the message to prompt you to
+hit any key. This might be useful if your system has no terminal
+device.
+
+The option @option{--no-echo} has GRUB not to echo back input
+characters. This implies the option @option{--no-edit}.
+
+The option @option{--no-edit} disables the BASH-like editing feature.
+@end deffn
+
+
+@node terminfo
+@subsection terminfo
+
+@deffn Command terminfo @option{--name=name} @option{--cursor-address=seq} [@option{--clear-screen=seq}] [@option{--enter-standout-mode=seq}] [@option{--exit-standout-mode=seq}]
+Define the capabilities of your terminal. Use this command to define
+escape sequences, if it is not vt100-compatible. You may use @samp{\e}
+for @key{ESC} and @samp{^X} for a control character.
+
+You can use the utility @command{grub-terminfo} to generate
+appropriate arguments to this command. @xref{Invoking grub-terminfo}.
+
+If no option is specified, the current settings are printed.
+@end deffn
+
+
+@node tftpserver
+@subsection tftpserver
+
+@deffn Command tftpserver ipaddr
+@strong{Caution:} This command exists only for backward
+compatibility. Use @command{ifconfig} (@pxref{ifconfig}) instead.
+
+Override a TFTP server address returned by a BOOTP/DHCP/RARP server. The
+argument @var{ipaddr} must be in dotted decimal format, like
+@samp{192.168.0.15}.  This command is only available if GRUB is compiled
+with netboot support. See also @ref{Network}.
+@end deffn
+
+
+@node unhide
+@subsection unhide
+
+@deffn Command unhide partition
+Unhide the partition @var{partition} by clearing the @dfn{hidden} bit in
+its partition type code. This is useful only when booting DOS or Windows
+and multiple primary partitions exist on one disk. See also
+@ref{DOS/Windows}.
+@end deffn
+
+
+@node Command-line and menu entry commands
+@section The list of command-line and menu entry commands
+
+These commands are usable in the command-line and in menu entries.  If
+you forget a command, you can run the command @command{help}
+(@pxref{help}).
+
+@menu
+* blocklist::                   Get the block list notation of a file
+* boot::                        Start up your operating system
+* cat::                         Show the contents of a file
+* chainloader::                 Chain-load another boot loader
+* cmp::                         Compare two files
+* configfile::                  Load a configuration file
+* debug::                       Toggle the debug flag
+* displayapm::                  Display APM information
+* displaymem::                  Display memory configuration
+* embed::                       Embed Stage 1.5
+* find::                        Find a file
+* fstest::                      Test a filesystem
+* geometry::                    Manipulate the geometry of a drive
+* halt::                        Shut down your computer
+* help::                        Show help messages
+* impsprobe::                   Probe SMP
+* initrd::                      Load an initrd
+* install::                     Install GRUB
+* ioprobe::                     Probe I/O ports used for a drive
+* kernel::                      Load a kernel
+* lock::                        Lock a menu entry
+* makeactive::                  Make a partition active
+* map::                         Map a drive to another
+* md5crypt::                    Encrypt a password in MD5 format
+* module::                      Load a module
+* modulenounzip::               Load a module without decompression
+* pause::                       Wait for a key press
+* quit::                        Exit from the grub shell
+* reboot::                      Reboot your computer
+* read::                        Read data from memory
+* root::                        Set GRUB's root device
+* rootnoverify::                Set GRUB's root device without mounting
+* savedefault::                 Save current entry as the default entry
+* setup::                       Set up GRUB's installation automatically
+* testload::                    Load a file for testing a filesystem
+* testvbe::                     Test VESA BIOS EXTENSION
+* uppermem::                    Set the upper memory size
+* vbeprobe::                    Probe VESA BIOS EXTENSION
+@end menu
+
+
+@node blocklist
+@subsection blocklist
+
+@deffn Command blocklist file
+Print the block list notation of the file @var{file}. @xref{Block list
+syntax}.
+@end deffn
+
+
+@node boot
+@subsection boot
+
+@deffn Command boot
+Boot the OS or chain-loader which has been loaded. Only necessary if
+running the fully interactive command-line (it is implicit at the end of
+a menu entry).
+@end deffn
+
+
+@node cat
+@subsection cat
+
+@deffn Command cat file
+Display the contents of the file @var{file}. This command may be useful
+to remind you of your OS's root partition:
+
+@example
+grub> @kbd{cat /etc/fstab}
+@end example
+@end deffn
+
+
+@node chainloader
+@subsection chainloader
+
+@deffn Command chainloader [@option{--force}] file
+Load @var{file} as a chain-loader. Like any other file loaded by the
+filesystem code, it can use the blocklist notation to grab the first
+sector of the current partition with @samp{+1}. If you specify the
+option @option{--force}, then load @var{file} forcibly, whether it has a
+correct signature or not. This is required when you want to load a
+defective boot loader, such as SCO UnixWare 7.1 (@pxref{SCO UnixWare}).
+@end deffn
+
+
+@node cmp
+@subsection cmp
+
+@deffn Command cmp file1 file2
+Compare the file @var{file1} with the file @var{file2}. If they differ
+in size, print the sizes like this:
+
+@example
+Differ in size: 0x1234 [foo], 0x4321 [bar]
+@end example
+
+If the sizes are equal but the bytes at an offset differ, then print the
+bytes like this:
+
+@example
+Differ at the offset 777: 0xbe [foo], 0xef [bar]
+@end example
+
+If they are completely identical, nothing will be printed.
+@end deffn
+
+
+@node configfile
+@subsection configfile
+
+@deffn Command configfile file
+Load @var{file} as a configuration file.
+@end deffn
+
+
+@node debug
+@subsection debug
+
+@deffn Command debug
+Toggle debug mode (by default it is off). When debug mode is on, some
+extra messages are printed to show disk activity. This global debug flag
+is mainly useful for GRUB developers when testing new code.
+@end deffn
+
+
+@node displayapm
+@subsection displayapm
+
+@deffn Command displayapm
+Display APM BIOS information.
+@end deffn
+
+
+@node displaymem
+@subsection displaymem
+
+@deffn Command displaymem
+Display what GRUB thinks the system address space map of the machine is,
+including all regions of physical @sc{ram} installed. GRUB's
+@dfn{upper/lower memory} display uses the standard BIOS interface for
+the available memory in the first megabyte, or @dfn{lower memory}, and a
+synthesized number from various BIOS interfaces of the memory starting
+at 1MB and going up to the first chipset hole for @dfn{upper memory}
+(the standard PC @dfn{upper memory} interface is limited to reporting a
+maximum of 64MB).
+@end deffn
+
+
+@node embed
+@subsection embed
+
+@deffn Command embed stage1_5 device
+Embed the Stage 1.5 @var{stage1_5} in the sectors after the MBR if
+@var{device} is a drive, or in the @dfn{boot loader} area if @var{device}
+is a FFS partition or a ReiserFS partition.@footnote{The latter feature
+has not been implemented yet.} Print the number of sectors which
+@var{stage1_5} occupies, if successful.
+
+Usually, you don't need to run this command directly. @xref{setup}.
+@end deffn
+
+
+@node find
+@subsection find
+
+@deffn Command find filename
+Search for the file name @var{filename} in all mountable partitions
+and print the list of the devices which contain the file. The file
+name @var{filename} should be an absolute file name like
+@code{/boot/grub/stage1}.
+@end deffn
+
+
+@node fstest
+@subsection fstest
+
+@deffn Command fstest
+Toggle filesystem test mode.
+Filesystem test mode, when turned on, prints out data corresponding to
+all the device reads and what values are being sent to the low-level
+routines. The format is @samp{<@var{partition-offset-sector},
+@var{byte-offset}, @var{byte-length}>} for high-level reads inside a
+partition, and @samp{[@var{disk-offset-sector}]} for low-level sector
+requests from the disk.
+Filesystem test mode is turned off by any use of the @command{install}
+(@pxref{install}) or @command{testload} (@pxref{testload}) commands.
+@end deffn
+
+
+@node geometry
+@subsection geometry
+
+@deffn Command geometry drive [cylinder head sector [total_sector]]
+Print the information for the drive @var{drive}. In the grub shell, you
+can set the geometry of the drive arbitrarily. The number of
+cylinders, the number of heads, the number of sectors and the number of
+total sectors are set to CYLINDER, HEAD, SECTOR and TOTAL_SECTOR,
+respectively. If you omit TOTAL_SECTOR, then it will be calculated
+based on the C/H/S values automatically.
+@end deffn
+
+
+@node halt
+@subsection halt
+
+@deffn Command halt @option{--no-apm}
+The command halts the computer. If the @option{--no-apm} option
+is specified, no APM BIOS call is performed. Otherwise, the computer
+is shut down using APM.
+@end deffn
+
+
+@node help
+@subsection help
+
+@deffn Command help @option{--all} [pattern @dots{}]
+Display helpful information about builtin commands. If you do not
+specify @var{pattern}, this command shows short descriptions of most of
+available commands. If you specify the option @option{--all} to this
+command, short descriptions of rarely used commands (such as
+@ref{testload}) are displayed as well.
+
+If you specify any @var{patterns}, it displays longer information
+about each of the commands which match those @var{patterns}.
+@end deffn
+
+
+@node impsprobe
+@subsection impsprobe
+
+@deffn Command impsprobe
+Probe the Intel Multiprocessor Specification 1.1 or 1.4 configuration
+table and boot the various CPUs which are found into a tight loop. This
+command can be used only in the Stage 2, but not in the grub shell.
+@end deffn
+
+
+@node initrd
+@subsection initrd
+
+@deffn Command initrd file @dots{}
+Load an initial ramdisk for a Linux format boot image and set the
+appropriate parameters in the Linux setup area in memory. See also
+@ref{GNU/Linux}.
+@end deffn
+
+
+@node install
+@subsection install
+
+@deffn Command install [@option{--force-lba}] [@option{--stage2=os_stage2_file}] stage1_file [@option{d}] dest_dev stage2_file [addr] [@option{p}] [config_file] [real_config_file]
+This command is fairly complex, and you should not use this command
+unless you are familiar with GRUB. Use @command{setup} (@pxref{setup})
+instead.
+
+In short, it will perform a full install presuming the Stage 2 or Stage
+1.5@footnote{They're loaded the same way, so we will refer to the Stage
+1.5 as a Stage 2 from now on.} is in its final install location.
+
+In slightly more detail, it will load @var{stage1_file}, validate that
+it is a GRUB Stage 1 of the right version number, install in it a
+blocklist for loading @var{stage2_file} as a Stage 2. If the option
+@option{d} is present, the Stage 1 will always look for the actual
+disk @var{stage2_file} was installed on, rather than using the booting
+drive. The Stage 2 will be loaded at address @var{addr}, which must be
+@samp{0x8000} for a true Stage 2, and @samp{0x2000} for a Stage 1.5. If
+@var{addr} is not present, GRUB will determine the address
+automatically. It then writes the completed Stage 1 to the first block
+of the device @var{dest_dev}. If the options @option{p} or
+@var{config_file} are present, then it reads the first block of stage2,
+modifies it with the values of the partition @var{stage2_file} was found
+on (for @option{p}) or places the string @var{config_file} into the area
+telling the stage2 where to look for a configuration file at boot
+time. Likewise, if @var{real_config_file} is present and
+@var{stage2_file} is a Stage 1.5, then the Stage 2 @var{config_file} is
+patched with the configuration file name @var{real_config_file}. This
+command preserves the DOS BPB (and for hard disks, the partition table)
+of the sector the Stage 1 is to be installed into.
+
+@strong{Caution:} Several buggy BIOSes don't pass a booting drive
+properly when booting from a hard disk drive. Therefore, you will
+unfortunately have to specify the option @option{d}, whether your
+Stage2 resides at the booting drive or not, if you have such a
+BIOS. We know these are defective in this way:
+
+@table @asis
+@item
+Fujitsu LifeBook 400 BIOS version 31J0103A
+
+@item
+HP Vectra XU 6/200 BIOS version GG.06.11
+@end table
+
+@strong{Caution2:} A number of BIOSes don't return a correct LBA support
+bitmap even if they do have the support. So GRUB provides a solution to
+ignore the wrong bitmap, that is, the option @option{--force-lba}. Don't
+use this option if you know that your BIOS doesn't have LBA support.
+
+@strong{Caution3:} You must specify the option @option{--stage2} in the
+grub shell, if you cannot unmount the filesystem where your stage2 file
+resides. The argument should be the file name in your operating system.
+@end deffn
+
+
+@node ioprobe
+@subsection ioprobe
+
+@deffn Command ioprobe drive
+Probe I/O ports used for the drive @var{drive}. This command will list
+the I/O ports on the screen. For technical information,
+@xref{Internals}.
+@end deffn
+
+
+@node kernel
+@subsection kernel
+
+@deffn Command kernel [@option{--type=type}] [@option{--no-mem-option}] file @dots{}
+Attempt to load the primary boot image (Multiboot a.out or @sc{elf},
+Linux zImage or bzImage, FreeBSD a.out, NetBSD a.out, etc.) from
+@var{file}. The rest of the line is passed verbatim as the @dfn{kernel
+command-line}. Any modules must be reloaded after using this command.
+
+This command also accepts the option @option{--type} so that you can
+specify the kernel type of @var{file} explicitly. The argument
+@var{type} must be one of these: @samp{netbsd}, @samp{freebsd},
+@samp{openbsd}, @samp{linux}, @samp{biglinux}, and
+@samp{multiboot}. However, you need to specify it only if you want to
+load a NetBSD @sc{elf} kernel, because GRUB can automatically determine
+a kernel type in the other cases, quite safely.
+
+The option @option{--no-mem-option} is effective only for Linux. If the
+option is specified, GRUB doesn't pass the option @option{mem=} to the
+kernel.  This option is implied for Linux kernels 2.4.18 and newer.
+@end deffn
+
+
+@node lock
+@subsection lock
+
+@deffn Command lock
+Prevent normal users from executing arbitrary menu entries. You must use
+the command @command{password} if you really want this command to be
+useful (@pxref{password}).
+
+This command is used in a menu, as shown in this example:
+
+@example
+@group
+title This entry is too dangerous to be executed by normal users
+lock
+root (hd0,a)
+kernel /no-security-os
+@end group
+@end example
+
+See also @ref{Security}.
+@end deffn
+
+
+@node makeactive
+@subsection makeactive
+
+@deffn Command makeactive
+Set the active partition on the root disk to GRUB's root device.
+This command is limited to @emph{primary} PC partitions on a hard disk.
+@end deffn
+
+
+@node map
+@subsection map
+
+@deffn Command map to_drive from_drive
+Map the drive @var{from_drive} to the drive @var{to_drive}. This is
+necessary when you chain-load some operating systems, such as DOS, if
+such an OS resides at a non-first drive. Here is an example:
+
+@example
+@group
+grub> @kbd{map (hd0) (hd1)}
+grub> @kbd{map (hd1) (hd0)}
+@end group
+@end example
+
+The example exchanges the order between the first hard disk and the
+second hard disk. See also @ref{DOS/Windows}.
+@end deffn
+
+
+@node md5crypt
+@subsection md5crypt
+
+@deffn Command md5crypt
+Prompt to enter a password, and encrypt it in MD5 format. The encrypted
+password can be used with the command @command{password}
+(@pxref{password}). See also @ref{Security}.
+@end deffn
+
+
+@node module
+@subsection module
+
+@deffn Command module file @dots{}
+Load a boot module @var{file} for a Multiboot format boot image (no
+interpretation of the file contents are made, so the user of this
+command must know what the kernel in question expects). The rest of the
+line is passed as the @dfn{module command-line}, like the
+@command{kernel} command. You must load a Multiboot kernel image before
+loading any module. See also @ref{modulenounzip}.
+@end deffn
+
+
+@node modulenounzip
+@subsection modulenounzip
+
+@deffn Command modulenounzip file @dots{}
+The same as @command{module} (@pxref{module}), except that automatic
+decompression is disabled.
+@end deffn
+
+
+@node pause
+@subsection pause
+
+@deffn Command pause message @dots{}
+Print the @var{message}, then wait until a key is pressed. Note that
+placing @key{^G} (ASCII code 7) in the message will cause the speaker to
+emit the standard beep sound, which is useful when prompting the user to
+change floppies.
+@end deffn
+
+
+@node quit
+@subsection quit
+
+@deffn Command quit
+Exit from the grub shell @command{grub} (@pxref{Invoking the grub
+shell}). This command can be used only in the grub shell.
+@end deffn
+
+
+@node reboot
+@subsection reboot
+
+@deffn Command reboot
+Reboot the computer.
+@end deffn
+
+
+@node read
+@subsection read
+
+@deffn Command read addr
+Read a 32-bit value from memory at address @var{addr} and display it in
+hex format.
+@end deffn
+
+
+@node root
+@subsection root
+
+@deffn Command root device [hdbias]
+Set the current @dfn{root device} to the device @var{device}, then
+attempt to mount it to get the partition size (for passing the partition
+descriptor in @code{ES:ESI}, used by some chain-loaded boot loaders), the
+BSD drive-type (for booting BSD kernels using their native boot format),
+and correctly determine the PC partition where a BSD sub-partition is
+located. The optional @var{hdbias} parameter is a number to tell a BSD
+kernel how many BIOS drive numbers are on controllers before the current
+one. For example, if there is an IDE disk and a SCSI disk, and your
+FreeBSD root partition is on the SCSI disk, then use a @samp{1} for
+@var{hdbias}.
+
+See also @ref{rootnoverify}.
+@end deffn
+
+
+@node rootnoverify
+@subsection rootnoverify
+
+@deffn Command rootnoverify device [hdbias]
+Similar to @command{root} (@pxref{root}), but don't attempt to mount the
+partition. This is useful for when an OS is outside of the area of the
+disk that GRUB can read, but setting the correct root device is still
+desired. Note that the items mentioned in @command{root} above which
+derived from attempting the mount will @emph{not} work correctly.
+@end deffn
+
+
+@node savedefault
+@subsection savedefault
+
+@deffn Command savedefault num
+Save the current menu entry or @var{num} if specified as a default
+entry. Here is an example:
+
+@example
+@group
+default saved
+timeout 10
+
+title GNU/Linux
+root (hd0,0)
+kernel /boot/vmlinuz root=/dev/sda1 vga=ext
+initrd /boot/initrd
+savedefault
+
+title FreeBSD
+root (hd0,a)
+kernel /boot/loader
+savedefault
+@end group
+@end example
+
+With this configuration, GRUB will choose the entry booted previously as
+the default entry.
+
+You can specify @samp{fallback} instead of a number. Then, next
+fallback entry is saved. Next fallback entry is chosen from fallback
+entries. Normally, this will be the first entry in fallback ones.
+
+See also @ref{default} and @ref{Invoking grub-set-default}.
+@end deffn
+
+
+@node setup
+@subsection setup
+
+@deffn Command setup [@option{--force-lba}] [@option{--stage2=os_stage2_file}] [@option{--prefix=dir}] install_device [image_device]
+Set up the installation of GRUB automatically. This command uses the
+more flexible command @command{install} (@pxref{install}) in the backend
+and installs GRUB into the device @var{install_device}. If
+@var{image_device} is specified, then find the GRUB images
+(@pxref{Images}) in the device @var{image_device}, otherwise use the
+current @dfn{root device}, which can be set by the command
+@command{root}. If @var{install_device} is a hard disk, then embed a
+Stage 1.5 in the disk if possible.
+
+The option @option{--prefix} specifies the directory under which GRUB
+images are put. If it is not specified, GRUB automatically searches them
+in @file{/boot/grub} and @file{/grub}.
+
+The options @option{--force-lba} and @option{--stage2} are just passed
+to @command{install} if specified. @xref{install}, for more
+information.
+@end deffn
+
+
+@node testload
+@subsection testload
+
+@deffn Command testload file
+Read the entire contents of @var{file} in several different ways and
+compare them, to test the filesystem code. The output is somewhat
+cryptic, but if no errors are reported and the final @samp{i=@var{X},
+filepos=@var{Y}} reading has @var{X} and @var{Y} equal, then it is
+definitely consistent, and very likely works correctly subject to a
+consistent offset error. If this test succeeds, then a good next step is
+to try loading a kernel.
+@end deffn
+
+
+@node testvbe
+@subsection testvbe
+
+@deffn Command testvbe mode
+Test the VESA BIOS EXTENSION mode @var{mode}. This command will switch
+your video card to the graphics mode, and show an endless animation. Hit
+any key to return. See also @ref{vbeprobe}.
+@end deffn
+
+
+@node uppermem
+@subsection uppermem
+
+@deffn Command uppermem kbytes
+Force GRUB to assume that only @var{kbytes} kilobytes of upper memory
+are installed. Any system address range maps are discarded.
+
+@strong{Caution:} This should be used with great caution, and should
+only be necessary on some old machines. GRUB's BIOS probe can pick up
+all @sc{ram} on all new machines the author has ever heard of. It can
+also be used for debugging purposes to lie to an OS.
+@end deffn
+
+
+@node vbeprobe
+@subsection vbeprobe
+
+@deffn Command vbeprobe [mode]
+Probe VESA BIOS EXTENSION information. If the mode @var{mode} is
+specified, show only the information about @var{mode}. Otherwise, this
+command lists up available VBE modes on the screen. See also
+@ref{testvbe}.
+@end deffn
+
+
+@node Troubleshooting
+@chapter Error messages reported by GRUB
+
+This chapter describes error messages reported by GRUB when you
+encounter trouble. @xref{Invoking the grub shell}, if your problem is
+specific to the grub shell.
+
+@menu
+* Stage1 errors::               Errors reported by the Stage 1
+* Stage1.5 errors::             Errors reported by the Stage 1.5
+* Stage2 errors::               Errors reported by the Stage 2
+@end menu
+
+
+@node Stage1 errors
+@section Errors reported by the Stage 1
+
+The general way that the Stage 1 handles errors is to print an error
+string and then halt. Pressing @kbd{@key{CTRL}-@key{ALT}-@key{DEL}} will
+reboot.
+
+The following is a comprehensive list of error messages for the Stage 1:
+
+@table @asis
+@item Hard Disk Error
+The stage2 or stage1.5 is being read from a hard disk, and the attempt
+to determine the size and geometry of the hard disk failed.
+
+@item Floppy Error
+The stage2 or stage1.5 is being read from a floppy disk, and the attempt
+to determine the size and geometry of the floppy disk failed. It's listed
+as a separate error since the probe sequence is different than for hard
+disks.
+
+@item Read Error
+A disk read error happened while trying to read the stage2 or stage1.5.
+
+@item Geom Error
+The location of the stage2 or stage1.5 is not in the portion of the disk
+supported directly by the BIOS read calls.  This could occur because the
+BIOS translated geometry has been changed by the user or the disk is
+moved to another machine or controller after installation, or GRUB was
+not installed using itself (if it was, the Stage 2 version of this error
+would have been seen during that process and it would not have completed
+the install).
+@end table
+
+
+@node Stage1.5 errors
+@section Errors reported by the Stage 1.5
+
+The general way that the Stage 1.5 handles errors is to print an error
+number in the form @code{Error @var{num}} and then halt. Pressing
+@kbd{@key{CTRL}-@key{ALT}-@key{DEL}} will reboot.
+
+The error numbers correspond to the errors reported by Stage
+2. @xref{Stage2 errors}.
+
+
+@node Stage2 errors
+@section Errors reported by the Stage 2
+
+The general way that the Stage 2 handles errors is to abort the
+operation in question, print an error string, then (if possible) either
+continue based on the fact that an error occurred or wait for the user to
+deal with the error.
+
+The following is a comprehensive list of error messages for the Stage 2
+(error numbers for the Stage 1.5 are listed before the colon in each
+description):
+
+@table @asis
+@item 1 : Filename must be either an absolute filename or blocklist
+This error is returned if a file name is requested which doesn't fit the
+syntax/rules listed in the @ref{Filesystem}.
+
+@item 2 : Bad file or directory type
+This error is returned if a file requested is not a regular file, but
+something like a symbolic link, directory, or FIFO.
+
+@item 3 : Bad or corrupt data while decompressing file
+This error is returned if the run-length decompression code gets an
+internal error. This is usually from a corrupt file.
+
+@item 4 : Bad or incompatible header in compressed file
+This error is returned if the file header for a supposedly compressed
+file is bad.
+
+@item 5 : Partition table invalid or corrupt
+This error is returned if the sanity checks on the integrity of the
+partition table fail. This is a bad sign.
+
+@item 6 : Mismatched or corrupt version of stage1/stage2
+This error is returned if the install command points to incompatible
+or corrupt versions of the stage1 or stage2. It can't detect corruption
+in general, but this is a sanity check on the version numbers, which
+should be correct.
+
+@item 7 : Loading below 1MB is not supported
+This error is returned if the lowest address in a kernel is below the
+1MB boundary. The Linux zImage format is a special case and can be
+handled since it has a fixed loading address and maximum size.
+
+@item 8 : Kernel must be loaded before booting
+This error is returned if GRUB is told to execute the boot sequence
+without having a kernel to start.
+
+@item 9 : Unknown boot failure
+This error is returned if the boot attempt did not succeed for reasons
+which are unknown.
+
+@item 10 : Unsupported Multiboot features requested
+This error is returned when the Multiboot features word in the Multiboot
+header requires a feature that is not recognized. The point of this is
+that the kernel requires special handling which GRUB is probably
+unable to provide.
+
+@item 11 : Unrecognized device string
+This error is returned if a device string was expected, and the string
+encountered didn't fit the syntax/rules listed in the @ref{Filesystem}.
+
+@item 12 : Invalid device requested
+This error is returned if a device string is recognizable but does not
+fall under the other device errors.
+
+@item 13 : Invalid or unsupported executable format
+This error is returned if the kernel image being loaded is not
+recognized as Multiboot or one of the supported native formats (Linux
+zImage or bzImage, FreeBSD, or NetBSD).
+
+@item 14 : Filesystem compatibility error, cannot read whole file
+Some of the filesystem reading code in GRUB has limits on the length of
+the files it can read. This error is returned when the user runs into
+such a limit.
+
+@item 15 : File not found
+This error is returned if the specified file name cannot be found, but
+everything else (like the disk/partition info) is OK.
+
+@item 16 : Inconsistent filesystem structure
+This error is returned by the filesystem code to denote an internal
+error caused by the sanity checks of the filesystem structure on disk
+not matching what it expects. This is usually caused by a corrupt
+filesystem or bugs in the code handling it in GRUB.
+
+@item 17 : Cannot mount selected partition
+This error is returned if the partition requested exists, but the
+filesystem type cannot be recognized by GRUB.
+
+@item 18 : Selected cylinder exceeds maximum supported by BIOS
+This error is returned when a read is attempted at a linear block
+address beyond the end of the BIOS translated area. This generally
+happens if your disk is larger than the BIOS can handle (512MB for
+(E)IDE disks on older machines or larger than 8GB in general).
+
+@item 19 : Linux kernel must be loaded before initrd
+This error is returned if the initrd command is used before loading a
+Linux kernel.
+
+@item 20 : Multiboot kernel must be loaded before modules
+This error is returned if the module load command is used before loading
+a Multiboot kernel. It only makes sense in this case anyway, as GRUB has
+no idea how to communicate the presence of such modules to a
+non-Multiboot-aware kernel.
+
+@item 21 : Selected disk does not exist
+This error is returned if the device part of a device- or full file name
+refers to a disk or BIOS device that is not present or not recognized by
+the BIOS in the system.
+
+@item 22 : No such partition
+This error is returned if a partition is requested in the device part of
+a device- or full file name which isn't on the selected disk.
+
+@item 23 : Error while parsing number
+This error is returned if GRUB was expecting to read a number and
+encountered bad data.
+
+@item 24 : Attempt to access block outside partition
+This error is returned if a linear block address is outside of the disk
+partition. This generally happens because of a corrupt filesystem on the
+disk or a bug in the code handling it in GRUB (it's a great debugging
+tool).
+
+@item 25 : Disk read error
+This error is returned if there is a disk read error when trying to
+probe or read data from a particular disk.
+
+@item 26 : Too many symbolic links
+This error is returned if the link count is beyond the maximum
+(currently 5), possibly the symbolic links are looped.
+
+@item 27 : Unrecognized command
+This error is returned if an unrecognized command is entered on the
+command-line or in a boot sequence section of a configuration file and
+that entry is selected.
+
+@item 28 : Selected item cannot fit into memory
+This error is returned if a kernel, module, or raw file load command is
+either trying to load its data such that it won't fit into memory or it
+is simply too big.
+
+@item 29 : Disk write error
+This error is returned if there is a disk write error when trying to
+write to a particular disk. This would generally only occur during an
+install of set active partition command.
+
+@item 30 : Invalid argument
+This error is returned if an argument specified to a command is invalid.
+
+@item 31 : File is not sector aligned
+This error may occur only when you access a ReiserFS partition by
+block-lists (e.g. the command @command{install}). In this case, you
+should mount the partition with the @samp{-o notail} option.
+
+@item 32 : Must be authenticated
+This error is returned if you try to run a locked entry. You should
+enter a correct password before running such an entry.
+
+@item 33 : Serial device not configured
+This error is returned if you try to change your terminal to a serial
+one before initializing any serial device.
+
+@item 34 : No spare sectors on the disk
+This error is returned if a disk doesn't have enough spare space. This
+happens when you try to embed Stage 1.5 into the unused sectors after
+the MBR, but the first partition starts right after the MBR or they are
+used by EZ-BIOS.
+@end table
+
+
+@node Invoking the grub shell
+@chapter Invoking the grub shell
+
+This chapter documents the grub shell @command{grub}. Note that the grub
+shell is an emulator; it doesn't run under the native environment, so it
+sometimes does something wrong. Therefore, you shouldn't trust it too
+much. If there is anything wrong with it, don't hesitate to try the
+native GRUB environment, especially when it guesses a wrong map between
+BIOS drives and OS devices.
+
+@menu
+* Basic usage::                 How to use the grub shell
+* Installation under UNIX::     How to install GRUB via @command{grub}
+* Device map::                  The map between BIOS drives and OS devices
+@end menu
+
+
+@node Basic usage
+@section Introduction into the grub shell
+
+You can use the command @command{grub} for installing GRUB under your
+operating systems and for a testbed when you add a new feature into GRUB
+or when fixing a bug. @command{grub} is almost the same as the Stage 2,
+and, in fact, it shares the source code with the Stage 2 and you can use
+the same commands (@pxref{Commands}) in @command{grub}. It is emulated by
+replacing BIOS calls with UNIX system calls and libc functions.
+
+The command @command{grub} accepts the following options:
+
+@table @option
+@item --help
+Print a summary of the command-line options and exit.
+
+@item --version
+Print the version number of GRUB and exit.
+
+@item --verbose
+Print some verbose messages for debugging purpose.
+
+@item --device-map=@var{file}
+Use the device map file @var{file}. The format is described in
+@ref{Device map}.
+
+@item --no-floppy
+Do not probe any floppy drive. This option has no effect if the option
+@option{--device-map} is specified (@pxref{Device map}).
+
+@item --probe-second-floppy
+Probe the second floppy drive. If this option is not specified, the grub
+shell does not probe it, as that sometimes takes a long time. If you
+specify the device map file (@pxref{Device map}), the grub shell just
+ignores this option.
+
+@item --config-file=@var{file}
+Read the configuration file @var{file} instead of
+@file{/boot/grub/menu.lst}. The format is the same as the normal GRUB
+syntax. See @ref{Filesystem}, for more information.
+
+@item --boot-drive=@var{drive}
+Set the stage2 @var{boot_drive} to @var{drive}. This argument should be
+an integer (decimal, octal or hexadecimal).
+
+@item --install-partition=@var{par}
+Set the stage2 @var{install_partition} to @var{par}. This argument
+should be an integer (decimal, octal or hexadecimal).
+
+@item --no-config-file
+Do not use the configuration file even if it can be read.
+
+@item --no-curses
+Do not use the screen handling interface by the curses even if it is
+available.
+
+@item --batch
+This option has the same meaning as @samp{--no-config-file --no-curses}.
+
+@item --read-only
+Disable writing to any disk.
+
+@item --hold
+Wait until a debugger will attach. This option is useful when you want
+to debug the startup code.
+@end table
+
+
+@node Installation under UNIX
+@section How to install GRUB via @command{grub}
+
+The installation procedure is the same as under the @dfn{native} Stage
+2. @xref{Installation}, for more information. The command
+@command{grub}-specific information is described here.
+
+What you should be careful about is @dfn{buffer cache}. @command{grub}
+makes use of raw devices instead of filesystems that your operating
+systems serve, so there exists a potential problem that some cache
+inconsistency may corrupt your filesystems. What we recommend is:
+
+@itemize @bullet
+@item
+If you can unmount drives to which GRUB may write any amount of data,
+unmount them before running @command{grub}.
+
+@item
+If a drive cannot be unmounted but can be mounted with the read-only
+flag, mount it in read-only mode. That should be secure.
+
+@item
+If a drive must be mounted with the read-write flag, make sure that no
+activity is being done on it while the command @command{grub} is
+running.
+
+@item
+Reboot your operating system as soon as possible. This is probably not
+required if you follow the rules above, but reboot is the most secure
+way.
+@end itemize
+
+In addition, enter the command @command{quit} when you finish the
+installation. That is @emph{very important} because @command{quit} makes
+the buffer cache consistent. Do not push @key{C-c}.
+
+If you want to install GRUB non-interactively, specify @samp{--batch}
+option in the command-line. This is a simple example:
+
+@example
+@group
+#!/bin/sh
+
+# Use /usr/sbin/grub if you are on an older system.
+/sbin/grub --batch <<EOT 1>/dev/null 2>/dev/null
+root (hd0,0)
+setup (hd0)
+quit
+EOT
+@end group
+@end example
+
+
+@node Device map
+@section The map between BIOS drives and OS devices
+
+When you specify the option @option{--device-map} (@pxref{Basic usage}),
+the grub shell creates the @dfn{device map file} automatically unless it
+already exists. The file name @file{/boot/grub/device.map} is preferred.
+
+If the device map file exists, the grub shell reads it to map BIOS
+drives to OS devices. This file consists of lines like this:
+
+@example
+@var{device} @var{file}
+@end example
+
+@var{device} is a drive specified in the GRUB syntax (@pxref{Device
+syntax}), and @var{file} is an OS file, which is normally a device
+file.
+
+The reason why the grub shell gives you the device map file is that it
+cannot guess the map between BIOS drives and OS devices correctly in
+some environments. For example, if you exchange the boot sequence
+between IDE and SCSI in your BIOS, it gets the order wrong.
+
+Thus, edit the file if the grub shell makes a mistake. You can put any
+comments in the file if needed, as the grub shell assumes that a line is
+just a comment if the first character is @samp{#}.
+
+
+@node Invoking grub-install
+@chapter Invoking grub-install
+
+The program @command{grub-install} installs GRUB on your drive using the
+grub shell (@pxref{Invoking the grub shell}). You must specify the
+device name on which you want to install GRUB, like this:
+
+@example
+grub-install @var{install_device}
+@end example
+
+The device name @var{install_device} is an OS device name or a GRUB
+device name.
+
+@command{grub-install} accepts the following options:
+
+@table @option
+@item --help
+Print a summary of the command-line options and exit.
+
+@item --version
+Print the version number of GRUB and exit.
+
+@item --force-lba
+Force GRUB to use LBA mode even for a buggy BIOS. Use this option only
+if your BIOS doesn't work properly in LBA mode even though it supports
+LBA mode.
+
+@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}:
+
+@example
+@kbd{grub-install --root-directory=/boot hd0}
+@end example
+
+@item --grub-shell=@var{file}
+Use @var{file} as the grub shell. You can append arbitrary options to
+@var{file} after the file name, like this:
+
+@example
+@kbd{grub-install --grub-shell="grub --read-only" /dev/fd0}
+@end example
+
+@item --recheck
+Recheck the device map, even if @file{/boot/grub/device.map} already
+exists. You should use this option whenever you add/remove a disk
+into/from your computer.
+@end table
+
+
+@node Invoking grub-md5-crypt
+@chapter Invoking grub-md5-crypt
+
+The program @command{grub-md5-crypt} encrypts a password in MD5 format.
+This is just a frontend of the grub shell (@pxref{Invoking the grub
+shell}). Passwords encrypted by this program can be used with the
+command @command{password} (@pxref{password}).
+
+@command{grub-md5-crypt} accepts the following options:
+
+@table @option
+@item --help
+Print a summary of the command-line options and exit.
+
+@item --version
+Print the version information and exit.
+
+@item --grub-shell=@var{file}
+Use @var{file} as the grub shell.
+@end table
+
+
+@node Invoking grub-terminfo
+@chapter Invoking grub-terminfo
+
+The program @command{grub-terminfo} generates a terminfo command from
+a terminfo name (@pxref{terminfo}). The result can be used in the
+configuration file, to define escape sequences. Because GRUB assumes
+that your terminal is vt100-compatible by default, this would be
+useful only if your terminal is uncommon (such as vt52).
+
+@command{grub-terminfo} accepts the following options:
+
+@table @option
+@item --help
+Print a summary of the command-line options and exit.
+
+@item --version
+Print the version information and exit.
+@end table
+
+You must specify one argument to this command. For example:
+
+@example
+@kbd{grub-terminfo vt52}
+@end example
+
+
+@node Invoking grub-set-default
+@chapter Invoking grub-set-default
+
+The program @command{grub-set-default} sets the default boot entry for
+GRUB. This automatically creates a file named @file{default} under
+your GRUB directory (i.e. @file{/boot/grub}), if it is not
+present. This file is used to determine the default boot entry when
+GRUB boots up your system when you use @samp{default saved} in your
+configuration file (@pxref{default}), and to save next default boot
+entry when you use @samp{savedefault} in a boot entry
+(@pxref{savedefault}).
+
+@command{grub-set-default} accepts the following options:
+
+@table @option
+@item --help
+Print a summary of the command-line options and exit.
+
+@item --version
+Print the version information and exit.
+
+@item --root-directory=@var{dir}
+Use the directory @var{dir} instead of the root directory
+(i.e. @file{/}) to define the location of the default file. This
+is useful when you mount a disk which is used for another system.
+@end table
+
+You must specify a single argument to @command{grub-set-default}. This
+argument is normally the number of a default boot entry. For example,
+if you have this configuration file:
+
+@example
+@group
+default saved
+timeout 10
+
+title GNU/Hurd
+root (hd0,0)
+...
+
+title GNU/Linux
+root (hd0,1)
+...
+@end group
+@end example
+
+and if you want to set the next default boot entry to GNU/Linux, you
+may execute this command:
+
+@example
+@kbd{grub-set-default 1}
+@end example
+
+Because the entry for GNU/Linux is @samp{1}. Note that entries are
+counted from zero. So, if you want to specify GNU/Hurd here, then you
+should specify @samp{0}.
+
+This feature is very useful if you want to test a new kernel or to
+make your system quite robust. @xref{Making your system robust}, for
+more hints about how to set up a robust system.
+
+
+@node Invoking mbchk
+@chapter Invoking mbchk
+
+The program @command{mbchk} checks for the format of a Multiboot
+kernel. We recommend using this program before booting your own kernel
+by GRUB.
+
+@command{mbchk} accepts the following options:
+
+@table @option
+@item --help
+Print a summary of the command-line options and exit.
+
+@item --version
+Print the version number of GRUB and exit.
+
+@item --quiet
+Suppress all normal output.
+@end table
+
+
+@node Obtaining and Building GRUB
+@appendix How to obtain and build GRUB
+
+@quotation
+@strong{Caution:} GRUB requires binutils-2.9.1.0.23 or later because the
+GNU assembler has been changed so that it can produce real 16bits
+machine code between 2.9.1 and 2.9.1.0.x. See
+@uref{http://sources.redhat.com/binutils/}, to obtain information on
+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
+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}
+
+To unbundle GRUB use the instruction:
+
+@example
+@kbd{zcat grub-@value{VERSION}.tar.gz | tar xvf -}
+@end example
+
+which will create a directory called @file{grub-@value{VERSION}} with
+all the sources. You can look at the file @file{INSTALL} for detailed
+instructions on how to build and install GRUB, but you should be able to
+just do:
+
+@example
+@group
+@kbd{cd grub-@value{VERSION}}
+@kbd{./configure}
+@kbd{make install}
+@end group
+@end example
+
+This will install the grub shell @file{grub} (@pxref{Invoking the grub
+shell}), the Multiboot checker @file{mbchk} (@pxref{Invoking mbchk}),
+and the GRUB images. This will also install the GRUB manual.
+
+Also, the latest version is available from the CVS. See
+@uref{http://savannah.gnu.org/cvs/?group=grub} for more information.
+
+
+@node Reporting bugs
+@appendix Reporting bugs
+
+These are the guideline for how to report bugs. Take a look at this
+list below before you submit bugs:
+
+@enumerate
+@item
+Before getting unsettled, read this manual through and through. Also,
+see the @uref{http://www.gnu.org/software/grub/grub-faq.html, GNU GRUB FAQ}.
+
+@item
+Always mention the information on your GRUB. The version number and the
+configuration are quite important. If you build it yourself, write the
+options specified to the configure script and your operating system,
+including the versions of gcc and binutils.
+
+@item
+If you have trouble with the installation, inform us of how you
+installed GRUB. Don't omit error messages, if any. Just @samp{GRUB hangs
+up when it boots} is not enough.
+
+The information on your hardware is also essential. These are especially
+important: the geometries and the partition tables of your hard disk
+drives and your BIOS.
+
+@item
+If GRUB cannot boot your operating system, write down
+@emph{everything} you see on the screen. Don't paraphrase them, like
+@samp{The foo OS crashes with GRUB, even though it can boot with the
+bar boot loader just fine}. Mention the commands you executed, the
+messages printed by them, and information on your operating system
+including the version number.
+
+@item
+Explain what you wanted to do. It is very useful to know your purpose
+and your wish, and how GRUB didn't satisfy you.
+
+@item
+If you can investigate the problem yourself, please do. That will give
+you and us much more information on the problem. Attaching a patch is
+even better.
+
+When you attach a patch, make the patch in unified diff format, and
+write ChangeLog entries. But, even when you make a patch, don't forget
+to explain the problem, so that we can understand what your patch is
+for.
+
+@item
+Write down anything that you think might be related. Please understand
+that we often need to reproduce the same problem you encounterred in our
+environment. So your information should be sufficient for us to do the
+same thing---Don't forget that we cannot see your computer directly. If
+you are not sure whether to state a fact or leave it out, state it!
+Reporting too many things is much better than omitting something
+important.
+@end enumerate
+
+If you follow the guideline above, submit a report to the
+@uref{http://savannah.gnu.org/bugs/?group=grub, Bug Tracking System}.
+Alternatively, you can submit a report via electronic mail to
+@email{bug-grub@@gnu.org}, but we strongly recommend that you use the
+Bug Tracking System, because e-mail can be passed over easily.
+
+Once we get your report, we will try to fix the bugs.
+
+
+@node Future
+@appendix Where GRUB will go
+
+We started the next generation of GRUB, GRUB 2. This will include
+internationalization, dynamic module loading, real memory management,
+multiple architecture support, a scripting language, and many other
+nice feature. If you are interested in the development of GRUB 2, take
+a look at @uref{http://www.gnu.org/software/grub/grub.html, the
+homepage}.
+
+
+
+@node Copying This Manual
+@appendix Copying This Manual
+
+@menu
+* GNU Free Documentation License::  License for copying this manual.
+@end menu
+
+@include fdl.texi
+
+
+@node Index
+@unnumbered Index
+
+@c Currently, we use only the Concept Index.
+@printindex cp
+
+
+@bye
+
+Some notes:
+
+  This is an attempt to make a manual for GRUB 2. The contents are
+  copied from the GRUB manual in GRUB Legacy, so they are not always
+  appropriate yet for GRUB 2.
diff --git a/docs/mdate-sh b/docs/mdate-sh
new file mode 100755 (executable)
index 0000000..22f2f8b
--- /dev/null
@@ -0,0 +1,205 @@
+#!/bin/sh
+# Get modification time of a file or directory and pretty-print it.
+
+scriptversion=2007-03-30.02
+
+# Copyright (C) 1995, 1996, 1997, 2003, 2004, 2005, 2007 Free Software
+# Foundation, Inc.
+# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995
+#
+# This program 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, 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 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 Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+case $1 in
+  '')
+     echo "$0: No file.  Try \`$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: mdate-sh [--help] [--version] FILE
+
+Pretty-print the modification time of FILE.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "mdate-sh $scriptversion"
+    exit $?
+    ;;
+esac
+
+# Prevent date giving response in another language.
+LANG=C
+export LANG
+LC_ALL=C
+export LC_ALL
+LC_TIME=C
+export LC_TIME
+
+# GNU ls changes its time format in response to the TIME_STYLE
+# variable.  Since we cannot assume `unset' works, revert this
+# variable to its documented default.
+if test "${TIME_STYLE+set}" = set; then
+  TIME_STYLE=posix-long-iso
+  export TIME_STYLE
+fi
+
+save_arg1=$1
+
+# Find out how to get the extended ls output of a file or directory.
+if ls -L /dev/null 1>/dev/null 2>&1; then
+  ls_command='ls -L -l -d'
+else
+  ls_command='ls -l -d'
+fi
+# Avoid user/group names that might have spaces, when possible.
+if ls -n /dev/null 1>/dev/null 2>&1; then
+  ls_command="$ls_command -n"
+fi
+
+# A `ls -l' line looks as follows on OS/2.
+#  drwxrwx---        0 Aug 11  2001 foo
+# This differs from Unix, which adds ownership information.
+#  drwxrwx---   2 root  root      4096 Aug 11  2001 foo
+#
+# To find the date, we split the line on spaces and iterate on words
+# until we find a month.  This cannot work with files whose owner is a
+# user named `Jan', or `Feb', etc.  However, it's unlikely that `/'
+# will be owned by a user whose name is a month.  So we first look at
+# the extended ls output of the root directory to decide how many
+# words should be skipped to get the date.
+
+# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below.
+set x`$ls_command /`
+
+# Find which argument is the month.
+month=
+command=
+until test $month
+do
+  shift
+  # Add another shift to the command.
+  command="$command shift;"
+  case $1 in
+    Jan) month=January; nummonth=1;;
+    Feb) month=February; nummonth=2;;
+    Mar) month=March; nummonth=3;;
+    Apr) month=April; nummonth=4;;
+    May) month=May; nummonth=5;;
+    Jun) month=June; nummonth=6;;
+    Jul) month=July; nummonth=7;;
+    Aug) month=August; nummonth=8;;
+    Sep) month=September; nummonth=9;;
+    Oct) month=October; nummonth=10;;
+    Nov) month=November; nummonth=11;;
+    Dec) month=December; nummonth=12;;
+  esac
+done
+
+# Get the extended ls output of the file or directory.
+set dummy x`eval "$ls_command \"\$save_arg1\""`
+
+# Remove all preceding arguments
+eval $command
+
+# Because of the dummy argument above, month is in $2.
+#
+# On a POSIX system, we should have
+#
+# $# = 5
+# $1 = file size
+# $2 = month
+# $3 = day
+# $4 = year or time
+# $5 = filename
+#
+# On Darwin 7.7.0 and 7.6.0, we have
+#
+# $# = 4
+# $1 = day
+# $2 = month
+# $3 = year or time
+# $4 = filename
+
+# Get the month.
+case $2 in
+  Jan) month=January; nummonth=1;;
+  Feb) month=February; nummonth=2;;
+  Mar) month=March; nummonth=3;;
+  Apr) month=April; nummonth=4;;
+  May) month=May; nummonth=5;;
+  Jun) month=June; nummonth=6;;
+  Jul) month=July; nummonth=7;;
+  Aug) month=August; nummonth=8;;
+  Sep) month=September; nummonth=9;;
+  Oct) month=October; nummonth=10;;
+  Nov) month=November; nummonth=11;;
+  Dec) month=December; nummonth=12;;
+esac
+
+case $3 in
+  ???*) day=$1;;
+  *) day=$3; shift;;
+esac
+
+# Here we have to deal with the problem that the ls output gives either
+# the time of day or the year.
+case $3 in
+  *:*) set `date`; eval year=\$$#
+       case $2 in
+        Jan) nummonthtod=1;;
+        Feb) nummonthtod=2;;
+        Mar) nummonthtod=3;;
+        Apr) nummonthtod=4;;
+        May) nummonthtod=5;;
+        Jun) nummonthtod=6;;
+        Jul) nummonthtod=7;;
+        Aug) nummonthtod=8;;
+        Sep) nummonthtod=9;;
+        Oct) nummonthtod=10;;
+        Nov) nummonthtod=11;;
+        Dec) nummonthtod=12;;
+       esac
+       # For the first six month of the year the time notation can also
+       # be used for files modified in the last year.
+       if (expr $nummonth \> $nummonthtod) > /dev/null;
+       then
+        year=`expr $year - 1`
+       fi;;
+  *) year=$3;;
+esac
+
+# The result.
+echo $day $month $year
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/docs/texinfo.tex b/docs/texinfo.tex
new file mode 100644 (file)
index 0000000..c49e670
--- /dev/null
@@ -0,0 +1,8959 @@
+% texinfo.tex -- TeX macros to handle Texinfo files.
+%
+% Load plain if necessary, i.e., if running under initex.
+\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
+%
+\def\texinfoversion{2007-09-03.05}
+%
+% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, 2007,
+% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+% 2007 Free Software Foundation, Inc.
+%
+% This texinfo.tex file 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.
+%
+% This texinfo.tex file 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+%
+% As a special exception, when this file is read by TeX when processing
+% a Texinfo source document, you may use the result without
+% restriction.  (This has been our intent since Texinfo was invented.)
+%
+% Please try the latest version of texinfo.tex before submitting bug
+% reports; you can get the latest version from:
+%   http://www.gnu.org/software/texinfo/ (the Texinfo home page), or
+%   ftp://tug.org/tex/texinfo.tex
+%     (and all CTAN mirrors, see http://www.ctan.org).
+% The texinfo.tex in any given distribution could well be out
+% of date, so if that's what you're using, please check.
+%
+% Send bug reports to bug-texinfo@gnu.org.  Please include including a
+% complete document in each bug report with which we can reproduce the
+% problem.  Patches are, of course, greatly appreciated.
+%
+% To process a Texinfo manual with TeX, it's most reliable to use the
+% texi2dvi shell script that comes with the distribution.  For a simple
+% manual foo.texi, however, you can get away with this:
+%   tex foo.texi
+%   texindex foo.??
+%   tex foo.texi
+%   tex foo.texi
+%   dvips foo.dvi -o  # or whatever; this makes foo.ps.
+% The extra TeX runs get the cross-reference information correct.
+% Sometimes one run after texindex suffices, and sometimes you need more
+% than two; texi2dvi does it as many times as necessary.
+%
+% It is possible to adapt texinfo.tex for other languages, to some
+% extent.  You can get the existing language-specific files from the
+% full Texinfo distribution.
+%
+% The GNU Texinfo home page is http://www.gnu.org/software/texinfo.
+
+
+\message{Loading texinfo [version \texinfoversion]:}
+
+% If in a .fmt file, print the version number
+% and turn on active characters that we couldn't do earlier because
+% they might have appeared in the input file name.
+\everyjob{\message{[Texinfo version \texinfoversion]}%
+  \catcode`+=\active \catcode`\_=\active}
+
+
+\chardef\other=12
+
+% We never want plain's \outer definition of \+ in Texinfo.
+% For @tex, we can use \tabalign.
+\let\+ = \relax
+
+% Save some plain tex macros whose names we will redefine.
+\let\ptexb=\b
+\let\ptexbullet=\bullet
+\let\ptexc=\c
+\let\ptexcomma=\,
+\let\ptexdot=\.
+\let\ptexdots=\dots
+\let\ptexend=\end
+\let\ptexequiv=\equiv
+\let\ptexexclam=\!
+\let\ptexfootnote=\footnote
+\let\ptexgtr=>
+\let\ptexhat=^
+\let\ptexi=\i
+\let\ptexindent=\indent
+\let\ptexinsert=\insert
+\let\ptexlbrace=\{
+\let\ptexless=<
+\let\ptexnewwrite\newwrite
+\let\ptexnoindent=\noindent
+\let\ptexplus=+
+\let\ptexrbrace=\}
+\let\ptexslash=\/
+\let\ptexstar=\*
+\let\ptext=\t
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+  \let\linenumber = \empty % Pre-3.0.
+\else
+  \def\linenumber{l.\the\inputlineno:\space}
+\fi
+
+% Set up fixed words for English if not already set.
+\ifx\putwordAppendix\undefined  \gdef\putwordAppendix{Appendix}\fi
+\ifx\putwordChapter\undefined   \gdef\putwordChapter{Chapter}\fi
+\ifx\putwordfile\undefined      \gdef\putwordfile{file}\fi
+\ifx\putwordin\undefined        \gdef\putwordin{in}\fi
+\ifx\putwordIndexIsEmpty\undefined     \gdef\putwordIndexIsEmpty{(Index is empty)}\fi
+\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi
+\ifx\putwordInfo\undefined      \gdef\putwordInfo{Info}\fi
+\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi
+\ifx\putwordMethodon\undefined  \gdef\putwordMethodon{Method on}\fi
+\ifx\putwordNoTitle\undefined   \gdef\putwordNoTitle{No Title}\fi
+\ifx\putwordof\undefined        \gdef\putwordof{of}\fi
+\ifx\putwordon\undefined        \gdef\putwordon{on}\fi
+\ifx\putwordpage\undefined      \gdef\putwordpage{page}\fi
+\ifx\putwordsection\undefined   \gdef\putwordsection{section}\fi
+\ifx\putwordSection\undefined   \gdef\putwordSection{Section}\fi
+\ifx\putwordsee\undefined       \gdef\putwordsee{see}\fi
+\ifx\putwordSee\undefined       \gdef\putwordSee{See}\fi
+\ifx\putwordShortTOC\undefined  \gdef\putwordShortTOC{Short Contents}\fi
+\ifx\putwordTOC\undefined       \gdef\putwordTOC{Table of Contents}\fi
+%
+\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi
+\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi
+\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi
+\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi
+\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi
+\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi
+\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi
+\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi
+\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi
+\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi
+\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi
+\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi
+%
+\ifx\putwordDefmac\undefined    \gdef\putwordDefmac{Macro}\fi
+\ifx\putwordDefspec\undefined   \gdef\putwordDefspec{Special Form}\fi
+\ifx\putwordDefvar\undefined    \gdef\putwordDefvar{Variable}\fi
+\ifx\putwordDefopt\undefined    \gdef\putwordDefopt{User Option}\fi
+\ifx\putwordDeffunc\undefined   \gdef\putwordDeffunc{Function}\fi
+
+% Since the category of space is not known, we have to be careful.
+\chardef\spacecat = 10
+\def\spaceisspace{\catcode`\ =\spacecat}
+
+% sometimes characters are active, so we need control sequences.
+\chardef\colonChar = `\:
+\chardef\commaChar = `\,
+\chardef\dashChar  = `\-
+\chardef\dotChar   = `\.
+\chardef\exclamChar= `\!
+\chardef\lquoteChar= `\`
+\chardef\questChar = `\?
+\chardef\rquoteChar= `\'
+\chardef\semiChar  = `\;
+\chardef\underChar = `\_
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+% The following is used inside several \edef's.
+\def\makecsname#1{\expandafter\noexpand\csname#1\endcsname}
+
+% Hyphenation fixes.
+\hyphenation{
+  Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script
+  ap-pen-dix bit-map bit-maps
+  data-base data-bases eshell fall-ing half-way long-est man-u-script
+  man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm
+  par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces
+  spell-ing spell-ings
+  stand-alone strong-est time-stamp time-stamps which-ever white-space
+  wide-spread wrap-around
+}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen\bindingoffset
+\newdimen\normaloffset
+\newdimen\pagewidth \newdimen\pageheight
+
+% For a final copy, take out the rectangles
+% that mark overfull boxes (in case you have decided
+% that the text looks ok even though it passes the margin).
+%
+\def\finalout{\overfullrule=0pt}
+
+% @| inserts a changebar to the left of the current line.  It should
+% surround any changed text.  This approach does *not* work if the
+% change spans more than two lines of output.  To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change).
+%
+\def\|{%
+  % \vadjust can only be used in horizontal mode.
+  \leavevmode
+  %
+  % Append this vertical mode material after the current line in the output.
+  \vadjust{%
+    % We want to insert a rule with the height and depth of the current
+    % leading; that is exactly what \strutbox is supposed to record.
+    \vskip-\baselineskip
+    %
+    % \vadjust-items are inserted at the left edge of the type.  So
+    % the \llap here moves out into the left-hand margin.
+    \llap{%
+      %
+      % For a thicker or thinner bar, change the `1pt'.
+      \vrule height\baselineskip width1pt
+      %
+      % This is the space between the bar and the text.
+      \hskip 12pt
+    }%
+  }%
+}
+
+% Sometimes it is convenient to have everything in the transcript file
+% and nothing on the terminal.  We don't just call \tracingall here,
+% since that produces some useless output on the terminal.  We also make
+% some effort to order the tracing commands to reduce output in the log
+% file; cf. trace.sty in LaTeX.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\def\loggingall{%
+  \tracingstats2
+  \tracingpages1
+  \tracinglostchars2  % 2 gives us more in etex
+  \tracingparagraphs1
+  \tracingoutput1
+  \tracingmacros2
+  \tracingrestores1
+  \showboxbreadth\maxdimen \showboxdepth\maxdimen
+  \ifx\eTeXversion\undefined\else % etex gives us more logging
+    \tracingscantokens1
+    \tracingifs1
+    \tracinggroups1
+    \tracingnesting2
+    \tracingassigns1
+  \fi
+  \tracingcommands3  % 3 gives us more in etex
+  \errorcontextlines16
+}%
+
+% add check for \lastpenalty to plain's definitions.  If the last thing
+% we did was a \nobreak, we don't want to insert more space.
+%
+\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount
+  \removelastskip\penalty-50\smallskip\fi\fi}
+\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount
+  \removelastskip\penalty-100\medskip\fi\fi}
+\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount
+  \removelastskip\penalty-200\bigskip\fi\fi}
+
+% For @cropmarks command.
+% Do @cropmarks to get crop marks.
+%
+\newif\ifcropmarks
+\let\cropmarks = \cropmarkstrue
+%
+% Dimensions to add cropmarks at corners.
+% Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines
+\newdimen\cornerlong  \cornerlong=1pc
+\newdimen\cornerthick \cornerthick=.3pt
+\newdimen\topandbottommargin \topandbottommargin=.75in
+
+% Output a mark which sets \thischapter, \thissection and \thiscolor.
+% We dump everything together because we only have one kind of mark.
+% This works because we only use \botmark / \topmark, not \firstmark.
+%
+% A mark contains a subexpression of the \ifcase ... \fi construct.
+% \get*marks macros below extract the needed part using \ifcase.
+%
+% Another complication is to let the user choose whether \thischapter
+% (\thissection) refers to the chapter (section) in effect at the top
+% of a page, or that at the bottom of a page.  The solution is
+% described on page 260 of The TeXbook.  It involves outputting two
+% marks for the sectioning macros, one before the section break, and
+% one after.  I won't pretend I can describe this better than DEK...
+\def\domark{%
+  \toks0=\expandafter{\lastchapterdefs}%
+  \toks2=\expandafter{\lastsectiondefs}%
+  \toks4=\expandafter{\prevchapterdefs}%
+  \toks6=\expandafter{\prevsectiondefs}%
+  \toks8=\expandafter{\lastcolordefs}%
+  \mark{%
+                   \the\toks0 \the\toks2
+      \noexpand\or \the\toks4 \the\toks6
+    \noexpand\else \the\toks8
+  }%
+}
+% \topmark doesn't work for the very first chapter (after the title
+% page or the contents), so we use \firstmark there -- this gets us
+% the mark with the chapter defs, unless the user sneaks in, e.g.,
+% @setcolor (or @url, or @link, etc.) between @contents and the very
+% first @chapter.
+\def\gettopheadingmarks{%
+  \ifcase0\topmark\fi
+  \ifx\thischapter\empty \ifcase0\firstmark\fi \fi
+}
+\def\getbottomheadingmarks{\ifcase1\botmark\fi}
+\def\getcolormarks{\ifcase2\topmark\fi}
+
+% Avoid "undefined control sequence" errors.
+\def\lastchapterdefs{}
+\def\lastsectiondefs{}
+\def\prevchapterdefs{}
+\def\prevsectiondefs{}
+\def\lastcolordefs{}
+
+% Main output routine.
+\chardef\PAGE = 255
+\output = {\onepageout{\pagecontents\PAGE}}
+
+\newbox\headlinebox
+\newbox\footlinebox
+
+% \onepageout takes a vbox as an argument.  Note that \pagecontents
+% does insertions, but you have to call it yourself.
+\def\onepageout#1{%
+  \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi
+  %
+  \ifodd\pageno  \advance\hoffset by \bindingoffset
+  \else \advance\hoffset by -\bindingoffset\fi
+  %
+  % Do this outside of the \shipout so @code etc. will be expanded in
+  % the headline as they should be, not taken literally (outputting ''code).
+  \ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi
+  \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}%
+  \ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi
+  \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}%
+  %
+  {%
+    % Have to do this stuff outside the \shipout because we want it to
+    % take effect in \write's, yet the group defined by the \vbox ends
+    % before the \shipout runs.
+    %
+    \indexdummies         % don't expand commands in the output.
+    \normalturnoffactive  % \ in index entries must not stay \, e.g., if
+               % the page break happens to be in the middle of an example.
+               % We don't want .vr (or whatever) entries like this:
+               % \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}}
+               % "\acronym" won't work when it's read back in;
+               % it needs to be 
+               % {\code {{\tt \backslashcurfont }acronym}
+    \shipout\vbox{%
+      % Do this early so pdf references go to the beginning of the page.
+      \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi
+      %
+      \ifcropmarks \vbox to \outervsize\bgroup
+        \hsize = \outerhsize
+        \vskip-\topandbottommargin
+        \vtop to0pt{%
+          \line{\ewtop\hfil\ewtop}%
+          \nointerlineskip
+          \line{%
+            \vbox{\moveleft\cornerthick\nstop}%
+            \hfill
+            \vbox{\moveright\cornerthick\nstop}%
+          }%
+          \vss}%
+        \vskip\topandbottommargin
+        \line\bgroup
+          \hfil % center the page within the outer (page) hsize.
+          \ifodd\pageno\hskip\bindingoffset\fi
+          \vbox\bgroup
+      \fi
+      %
+      \unvbox\headlinebox
+      \pagebody{#1}%
+      \ifdim\ht\footlinebox > 0pt
+        % Only leave this space if the footline is nonempty.
+        % (We lessened \vsize for it in \oddfootingyyy.)
+        % The \baselineskip=24pt in plain's \makefootline has no effect.
+        \vskip 24pt
+        \unvbox\footlinebox
+      \fi
+      %
+      \ifcropmarks
+          \egroup % end of \vbox\bgroup
+        \hfil\egroup % end of (centering) \line\bgroup
+        \vskip\topandbottommargin plus1fill minus1fill
+        \boxmaxdepth = \cornerthick
+        \vbox to0pt{\vss
+          \line{%
+            \vbox{\moveleft\cornerthick\nsbot}%
+            \hfill
+            \vbox{\moveright\cornerthick\nsbot}%
+          }%
+          \nointerlineskip
+          \line{\ewbot\hfil\ewbot}%
+        }%
+      \egroup % \vbox from first cropmarks clause
+      \fi
+    }% end of \shipout\vbox
+  }% end of group with \indexdummies
+  \advancepageno
+  \ifnum\outputpenalty>-20000 \else\dosupereject\fi
+}
+
+\newinsert\margin \dimen\margin=\maxdimen
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+% marginal hacks, juha@viisa.uucp (Juha Takala)
+\ifvoid\margin\else % marginal info is present
+  \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi
+\dimen@=\dp#1\relax \unvbox#1\relax
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+% Here are the rules for the cropmarks.  Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+  {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+  {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1.  The argument is the rest of
+% the input line (except we remove a trailing comment).  #1 should be a
+% macro which expects an ordinary undelimited TeX argument.
+%
+\def\parsearg{\parseargusing{}}
+\def\parseargusing#1#2{%
+  \def\argtorun{#2}%
+  \begingroup
+    \obeylines
+    \spaceisspace
+    #1%
+    \parseargline\empty% Insert the \empty token, see \finishparsearg below.
+}
+
+{\obeylines %
+  \gdef\parseargline#1^^M{%
+    \endgroup % End of the group started in \parsearg.
+    \argremovecomment #1\comment\ArgTerm%
+  }%
+}
+
+% First remove any @comment, then any @c comment.
+\def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm}
+\def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm}
+
+% Each occurence of `\^^M' or `<space>\^^M' is replaced by a single space.
+%
+% \argremovec might leave us with trailing space, e.g.,
+%    @end itemize  @c foo
+% This space token undergoes the same procedure and is eventually removed
+% by \finishparsearg.
+%
+\def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M}
+\def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M}
+\def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{%
+  \def\temp{#3}%
+  \ifx\temp\empty
+    % Do not use \next, perhaps the caller of \parsearg uses it; reuse \temp:
+    \let\temp\finishparsearg
+  \else
+    \let\temp\argcheckspaces
+  \fi
+  % Put the space token in:
+  \temp#1 #3\ArgTerm
+}
+
+% If a _delimited_ argument is enclosed in braces, they get stripped; so
+% to get _exactly_ the rest of the line, we had to prevent such situation.
+% We prepended an \empty token at the very beginning and we expand it now,
+% just before passing the control to \argtorun.
+% (Similarily, we have to think about #3 of \argcheckspacesY above: it is
+% either the null string, or it ends with \^^M---thus there is no danger
+% that a pair of braces would be stripped.
+%
+% But first, we have to remove the trailing space token.
+%
+\def\finishparsearg#1 \ArgTerm{\expandafter\argtorun\expandafter{#1}}
+
+% \parseargdef\foo{...}
+%      is roughly equivalent to
+% \def\foo{\parsearg\Xfoo}
+% \def\Xfoo#1{...}
+%
+% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my
+% favourite TeX trick.  --kasal, 16nov03
+
+\def\parseargdef#1{%
+  \expandafter \doparseargdef \csname\string#1\endcsname #1%
+}
+\def\doparseargdef#1#2{%
+  \def#2{\parsearg#1}%
+  \def#1##1%
+}
+
+% Several utility definitions with active space:
+{
+  \obeyspaces
+  \gdef\obeyedspace{ }
+
+  % Make each space character in the input produce a normal interword
+  % space in the output.  Don't allow a line break at this space, as this
+  % is used only in environments like @example, where each line of input
+  % should produce a line of output anyway.
+  %
+  \gdef\sepspaces{\obeyspaces\let =\tie}
+
+  % If an index command is used in an @example environment, any spaces
+  % therein should become regular spaces in the raw index file, not the
+  % expansion of \tie (\leavevmode \penalty \@M \ ).
+  \gdef\unsepspaces{\let =\space}
+}
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+% Define the framework for environments in texinfo.tex.  It's used like this:
+%
+%   \envdef\foo{...}
+%   \def\Efoo{...}
+%
+% It's the responsibility of \envdef to insert \begingroup before the
+% actual body; @end closes the group after calling \Efoo.  \envdef also
+% defines \thisenv, so the current environment is known; @end checks
+% whether the environment name matches.  The \checkenv macro can also be
+% used to check whether the current environment is the one expected.
+%
+% Non-false conditionals (@iftex, @ifset) don't fit into this, so they
+% are not treated as enviroments; they don't open a group.  (The
+% implementation of @end takes care not to call \endgroup in this
+% special case.)
+
+
+% At runtime, environments start with this:
+\def\startenvironment#1{\begingroup\def\thisenv{#1}}
+% initialize
+\let\thisenv\empty
+
+% ... but they get defined via ``\envdef\foo{...}'':
+\long\def\envdef#1#2{\def#1{\startenvironment#1#2}}
+\def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}}
+
+% Check whether we're in the right environment:
+\def\checkenv#1{%
+  \def\temp{#1}%
+  \ifx\thisenv\temp
+  \else
+    \badenverr
+  \fi
+}
+
+% Evironment mismatch, #1 expected:
+\def\badenverr{%
+  \errhelp = \EMsimple
+  \errmessage{This command can appear only \inenvironment\temp,
+    not \inenvironment\thisenv}%
+}
+\def\inenvironment#1{%
+  \ifx#1\empty
+    out of any environment%
+  \else
+    in environment \expandafter\string#1%
+  \fi
+}
+
+% @end foo executes the definition of \Efoo.
+% But first, it executes a specialized version of \checkenv
+%
+\parseargdef\end{%
+  \if 1\csname iscond.#1\endcsname
+  \else
+    % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03
+    \expandafter\checkenv\csname#1\endcsname
+    \csname E#1\endcsname
+    \endgroup
+  \fi
+}
+
+\newhelp\EMsimple{Press RETURN to continue.}
+
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt\char64}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+\def\mylbrace {{\tt\char123}}
+\def\myrbrace {{\tt\char125}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+\begingroup
+  % Definitions to produce \{ and \} commands for indices,
+  % and @{ and @} for the aux/toc files.
+  \catcode`\{ = \other \catcode`\} = \other
+  \catcode`\[ = 1 \catcode`\] = 2
+  \catcode`\! = 0 \catcode`\\ = \other
+  !gdef!lbracecmd[\{]%
+  !gdef!rbracecmd[\}]%
+  !gdef!lbraceatcmd[@{]%
+  !gdef!rbraceatcmd[@}]%
+!endgroup
+
+% @comma{} to avoid , parsing problems.
+\let\comma = ,
+
+% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
+% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H.
+\let\, = \c
+\let\dotaccent = \.
+\def\ringaccent#1{{\accent23 #1}}
+\let\tieaccent = \t
+\let\ubaraccent = \b
+\let\udotaccent = \d
+
+% Other special characters: @questiondown @exclamdown @ordf @ordm
+% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss.
+\def\questiondown{?`}
+\def\exclamdown{!`}
+\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}}
+\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}}
+
+% Dotless i and dotless j, used for accents.
+\def\imacro{i}
+\def\jmacro{j}
+\def\dotless#1{%
+  \def\temp{#1}%
+  \ifx\temp\imacro \ptexi
+  \else\ifx\temp\jmacro \j
+  \else \errmessage{@dotless can be used only with i or j}%
+  \fi\fi
+}
+
+% The \TeX{} logo, as in plain, but resetting the spacing so that a
+% period following counts as ending a sentence.  (Idea found in latex.)
+%
+\edef\TeX{\TeX \spacefactor=1000 }
+
+% @LaTeX{} logo.  Not quite the same results as the definition in
+% latex.ltx, since we use a different font for the raised A; it's most
+% convenient for us to use an explicitly smaller font, rather than using
+% the \scriptstyle font (since we don't reset \scriptstyle and
+% \scriptscriptstyle).
+%
+\def\LaTeX{%
+  L\kern-.36em
+  {\setbox0=\hbox{T}%
+   \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}%
+  \kern-.15em
+  \TeX
+}
+
+% Be sure we're in horizontal mode when doing a tie, since we make space
+% equivalent to this in @example-like environments. Otherwise, a space
+% at the beginning of a line will start with \penalty -- and
+% since \penalty is valid in vertical mode, we'd end up putting the
+% penalty on the vertical list instead of in the new paragraph.
+{\catcode`@ = 11
+ % Avoid using \@M directly, because that causes trouble
+ % if the definition is written into an index file.
+ \global\let\tiepenalty = \@M
+ \gdef\tie{\leavevmode\penalty\tiepenalty\ }
+}
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @/ allows a line break.
+\let\/=\allowbreak
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=\endofsentencespacefactor\space}
+
+% @! is an end-of-sentence bang.
+\def\!{!\spacefactor=\endofsentencespacefactor\space}
+
+% @? is an end-of-sentence query.
+\def\?{?\spacefactor=\endofsentencespacefactor\space}
+
+% @frenchspacing on|off  says whether to put extra space after punctuation.
+% 
+\def\onword{on}
+\def\offword{off}
+%
+\parseargdef\frenchspacing{%
+  \def\temp{#1}%
+  \ifx\temp\onword \plainfrenchspacing
+  \else\ifx\temp\offword \plainnonfrenchspacing
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @frenchspacing option `\temp', must be on/off}%
+  \fi\fi
+}
+
+% @w prevents a word break.  Without the \leavevmode, @w at the
+% beginning of a paragraph, when TeX is still in vertical mode, would
+% produce a whole line of output instead of starting the paragraph.
+\def\w#1{\leavevmode\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page, by enclosing
+% it in a TeX vbox.  We use \vtop instead of \vbox to construct the box
+% to keep its height that of a normal line.  According to the rules for
+% \topskip (p.114 of the TeXbook), the glue inserted is
+% max (\topskip - \ht (first item), 0).  If that height is large,
+% therefore, no glue is inserted, and the space between the headline and
+% the text is small, which looks bad.
+%
+% Another complication is that the group might be very large.  This can
+% cause the glue on the previous page to be unduly stretched, because it
+% does not have much material.  In this case, it's better to add an
+% explicit \vfill so that the extra space is at the bottom.  The
+% threshold for doing this is if the group is more than \vfilllimit
+% percent of a page (\vfilllimit can be changed inside of @tex).
+%
+\newbox\groupbox
+\def\vfilllimit{0.7}
+%
+\envdef\group{%
+  \ifnum\catcode`\^^M=\active \else
+    \errhelp = \groupinvalidhelp
+    \errmessage{@group invalid in context where filling is enabled}%
+  \fi
+  \startsavinginserts
+  %
+  \setbox\groupbox = \vtop\bgroup
+    % Do @comment since we are called inside an environment such as
+    % @example, where each end-of-line in the input causes an
+    % end-of-line in the output.  We don't want the end-of-line after
+    % the `@group' to put extra space in the output.  Since @group
+    % should appear on a line by itself (according to the Texinfo
+    % manual), we don't worry about eating any user text.
+    \comment
+}
+%
+% The \vtop produces a box with normal height and large depth; thus, TeX puts
+% \baselineskip glue before it, and (when the next line of text is done)
+% \lineskip glue after it.  Thus, space below is not quite equal to space
+% above.  But it's pretty close.
+\def\Egroup{%
+    % To get correct interline space between the last line of the group
+    % and the first line afterwards, we have to propagate \prevdepth.
+    \endgraf % Not \par, as it may have been set to \lisppar.
+    \global\dimen1 = \prevdepth
+  \egroup           % End the \vtop.
+  % \dimen0 is the vertical size of the group's box.
+  \dimen0 = \ht\groupbox  \advance\dimen0 by \dp\groupbox
+  % \dimen2 is how much space is left on the page (more or less).
+  \dimen2 = \pageheight   \advance\dimen2 by -\pagetotal
+  % if the group doesn't fit on the current page, and it's a big big
+  % group, force a page break.
+  \ifdim \dimen0 > \dimen2
+    \ifdim \pagetotal < \vfilllimit\pageheight
+      \page
+    \fi
+  \fi
+  \box\groupbox
+  \prevdepth = \dimen1
+  \checkinserts
+}
+%
+% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+% message, so this ends up printing `@group can only ...'.
+%
+\newhelp\groupinvalidhelp{%
+group can only be used in environments such as @example,^^J%
+where each line of input produces a line of output.}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil  \mil=0.001in
+
+% Old definition--didn't work.
+%\parseargdef\need{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak
+%\prevdepth=-1000pt
+%}}
+
+\parseargdef\need{%
+  % Ensure vertical mode, so we don't make a big box in the middle of a
+  % paragraph.
+  \par
+  %
+  % If the @need value is less than one line space, it's useless.
+  \dimen0 = #1\mil
+  \dimen2 = \ht\strutbox
+  \advance\dimen2 by \dp\strutbox
+  \ifdim\dimen0 > \dimen2
+    %
+    % Do a \strut just to make the height of this box be normal, so the
+    % normal leading is inserted relative to the preceding line.
+    % And a page break here is fine.
+    \vtop to #1\mil{\strut\vfil}%
+    %
+    % TeX does not even consider page breaks if a penalty added to the
+    % main vertical list is 10000 or more.  But in order to see if the
+    % empty box we just added fits on the page, we must make it consider
+    % page breaks.  On the other hand, we don't want to actually break the
+    % page after the empty box.  So we use a penalty of 9999.
+    %
+    % There is an extremely small chance that TeX will actually break the
+    % page at this \penalty, if there are no other feasible breakpoints in
+    % sight.  (If the user is using lots of big @group commands, which
+    % almost-but-not-quite fill up a page, TeX will have a hard time doing
+    % good page breaking, for example.)  However, I could not construct an
+    % example where a page broke at this \penalty; if it happens in a real
+    % document, then we can reconsider our strategy.
+    \penalty9999
+    %
+    % Back up by the size of the box, whether we did a page break or not.
+    \kern -#1\mil
+    %
+    % Do not allow a page break right after this kern.
+    \nobreak
+  \fi
+}
+
+% @br   forces paragraph break (and is undocumented).
+
+\let\br = \par
+
+% @page forces the start of a new page.
+%
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+% This records the amount of indent in the innermost environment.
+% That's how much \exdent should take out.
+\newskip\exdentamount
+
+% This defn is used inside fill environments such as @defun.
+\parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}
+
+% This defn is used inside nofill environments such as @example.
+\parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount
+  \leftline{\hskip\leftskip{\rm#1}}}}
+
+% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current
+% paragraph.  For more general purposes, use the \margin insertion
+% class.  WHICH is `l' or `r'.
+%
+\newskip\inmarginspacing \inmarginspacing=1cm
+\def\strutdepth{\dp\strutbox}
+%
+\def\doinmargin#1#2{\strut\vadjust{%
+  \nobreak
+  \kern-\strutdepth
+  \vtop to \strutdepth{%
+    \baselineskip=\strutdepth
+    \vss
+    % if you have multiple lines of stuff to put here, you'll need to
+    % make the vbox yourself of the appropriate size.
+    \ifx#1l%
+      \llap{\ignorespaces #2\hskip\inmarginspacing}%
+    \else
+      \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}%
+    \fi
+    \null
+  }%
+}}
+\def\inleftmargin{\doinmargin l}
+\def\inrightmargin{\doinmargin r}
+%
+% @inmargin{TEXT [, RIGHT-TEXT]}
+% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right;
+% else use TEXT for both).
+%
+\def\inmargin#1{\parseinmargin #1,,\finish}
+\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing.
+  \setbox0 = \hbox{\ignorespaces #2}%
+  \ifdim\wd0 > 0pt
+    \def\lefttext{#1}%  have both texts
+    \def\righttext{#2}%
+  \else
+    \def\lefttext{#1}%  have only one text
+    \def\righttext{#1}%
+  \fi
+  %
+  \ifodd\pageno
+    \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin
+  \else
+    \def\temp{\inleftmargin\lefttext}%
+  \fi
+  \temp
+}
+
+% @include file    insert text of that file as input.
+%
+\def\include{\parseargusing\filenamecatcodes\includezzz}
+\def\includezzz#1{%
+  \pushthisfilestack
+  \def\thisfile{#1}%
+  {%
+    \makevalueexpandable
+    \def\temp{\input #1 }%
+    \expandafter
+  }\temp
+  \popthisfilestack
+}
+\def\filenamecatcodes{%
+  \catcode`\\=\other
+  \catcode`~=\other
+  \catcode`^=\other
+  \catcode`_=\other
+  \catcode`|=\other
+  \catcode`<=\other
+  \catcode`>=\other
+  \catcode`+=\other
+  \catcode`-=\other
+}
+
+\def\pushthisfilestack{%
+  \expandafter\pushthisfilestackX\popthisfilestack\StackTerm
+}
+\def\pushthisfilestackX{%
+  \expandafter\pushthisfilestackY\thisfile\StackTerm
+}
+\def\pushthisfilestackY #1\StackTerm #2\StackTerm {%
+  \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}%
+}
+
+\def\popthisfilestack{\errthisfilestackempty}
+\def\errthisfilestackempty{\errmessage{Internal error:
+  the stack of filenames is empty.}}
+
+\def\thisfile{}
+
+% @center line
+% outputs that line, centered.
+%
+\parseargdef\center{%
+  \ifhmode
+    \let\next\centerH
+  \else
+    \let\next\centerV
+  \fi
+  \next{\hfil \ignorespaces#1\unskip \hfil}%
+}
+\def\centerH#1{%
+  {%
+    \hfil\break
+    \advance\hsize by -\leftskip
+    \advance\hsize by -\rightskip
+    \line{#1}%
+    \break
+  }%
+}
+\def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}}
+
+% @sp n   outputs n lines of vertical space
+
+\parseargdef\sp{\vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore  is another way to write a comment
+
+\def\comment{\begingroup \catcode`\^^M=\other%
+\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other%
+\commentxxx}
+{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}}
+
+\let\c=\comment
+
+% @paragraphindent NCHARS
+% We'll use ems for NCHARS, close enough.
+% NCHARS can also be the word `asis' or `none'.
+% We cannot feasibly implement @paragraphindent asis, though.
+%
+\def\asisword{asis} % no translation, these are keywords
+\def\noneword{none}
+%
+\parseargdef\paragraphindent{%
+  \def\temp{#1}%
+  \ifx\temp\asisword
+  \else
+    \ifx\temp\noneword
+      \defaultparindent = 0pt
+    \else
+      \defaultparindent = #1em
+    \fi
+  \fi
+  \parindent = \defaultparindent
+}
+
+% @exampleindent NCHARS
+% We'll use ems for NCHARS like @paragraphindent.
+% It seems @exampleindent asis isn't necessary, but
+% I preserve it to make it similar to @paragraphindent.
+\parseargdef\exampleindent{%
+  \def\temp{#1}%
+  \ifx\temp\asisword
+  \else
+    \ifx\temp\noneword
+      \lispnarrowing = 0pt
+    \else
+      \lispnarrowing = #1em
+    \fi
+  \fi
+}
+
+% @firstparagraphindent WORD
+% If WORD is `none', then suppress indentation of the first paragraph
+% after a section heading.  If WORD is `insert', then do indent at such
+% paragraphs.
+%
+% The paragraph indentation is suppressed or not by calling
+% \suppressfirstparagraphindent, which the sectioning commands do.
+% We switch the definition of this back and forth according to WORD.
+% By default, we suppress indentation.
+%
+\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent}
+\def\insertword{insert}
+%
+\parseargdef\firstparagraphindent{%
+  \def\temp{#1}%
+  \ifx\temp\noneword
+    \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent
+  \else\ifx\temp\insertword
+    \let\suppressfirstparagraphindent = \relax
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @firstparagraphindent option `\temp'}%
+  \fi\fi
+}
+
+% Here is how we actually suppress indentation.  Redefine \everypar to
+% \kern backwards by \parindent, and then reset itself to empty.
+%
+% We also make \indent itself not actually do anything until the next
+% paragraph.
+%
+\gdef\dosuppressfirstparagraphindent{%
+  \gdef\indent{%
+    \restorefirstparagraphindent
+    \indent
+  }%
+  \gdef\noindent{%
+    \restorefirstparagraphindent
+    \noindent
+  }%
+  \global\everypar = {%
+    \kern -\parindent
+    \restorefirstparagraphindent
+  }%
+}
+
+\gdef\restorefirstparagraphindent{%
+  \global \let \indent = \ptexindent
+  \global \let \noindent = \ptexnoindent
+  \global \everypar = {}%
+}
+
+
+% @asis just yields its argument.  Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math outputs its argument in math mode.
+%
+% One complication: _ usually means subscripts, but it could also mean
+% an actual _ character, as in @math{@var{some_variable} + 1}.  So make
+% _ active, and distinguish by seeing if the current family is \slfam,
+% which is what @var uses.
+{
+  \catcode`\_ = \active
+  \gdef\mathunderscore{%
+    \catcode`\_=\active
+    \def_{\ifnum\fam=\slfam \_\else\sb\fi}%
+  }
+}
+% Another complication: we want \\ (and @\) to output a \ character.
+% FYI, plain.tex uses \\ as a temporary control sequence (why?), but
+% this is not advertised and we don't care.  Texinfo does not
+% otherwise define @\.
+%
+% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\.
+\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi}
+%
+\def\math{%
+  \tex
+  \mathunderscore
+  \let\\ = \mathbackslash
+  \mathactive
+  $\finishmath
+}
+\def\finishmath#1{#1$\endgroup}  % Close the group opened by \tex.
+
+% Some active characters (such as <) are spaced differently in math.
+% We have to reset their definitions in case the @math was an argument
+% to a command which sets the catcodes (such as @item or @section).
+%
+{
+  \catcode`^ = \active
+  \catcode`< = \active
+  \catcode`> = \active
+  \catcode`+ = \active
+  \gdef\mathactive{%
+    \let^ = \ptexhat
+    \let< = \ptexless
+    \let> = \ptexgtr
+    \let+ = \ptexplus
+  }
+}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{$\ptexbullet$}
+\def\minus{$-$}
+
+% @dots{} outputs an ellipsis using the current font.
+% We do .5em per period so that it has the same spacing in the cm
+% typewriter fonts as three actual period characters; on the other hand,
+% in other typewriter fonts three periods are wider than 1.5em.  So do
+% whichever is larger.
+%
+\def\dots{%
+  \leavevmode
+  \setbox0=\hbox{...}% get width of three periods
+  \ifdim\wd0 > 1.5em
+    \dimen0 = \wd0
+  \else
+    \dimen0 = 1.5em
+  \fi
+  \hbox to \dimen0{%
+    \hskip 0pt plus.25fil
+    .\hskip 0pt plus1fil
+    .\hskip 0pt plus1fil
+    .\hskip 0pt plus.5fil
+  }%
+}
+
+% @enddots{} is an end-of-sentence ellipsis.
+%
+\def\enddots{%
+  \dots
+  \spacefactor=\endofsentencespacefactor
+}
+
+% @comma{} is so commas can be inserted into text without messing up
+% Texinfo's parsing.
+%
+\let\comma = ,
+
+% @refill is a no-op.
+\let\refill=\relax
+
+% If working on a large document in chapters, it is convenient to
+% be able to disable indexing, cross-referencing, and contents, for test runs.
+% This is done with @novalidate (before @setfilename).
+%
+\newif\iflinks \linkstrue % by default we want the aux files.
+\let\novalidate = \linksfalse
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+   \fixbackslash  % Turn off hack to swallow `\input texinfo'.
+   \iflinks
+     \tryauxfile
+     % Open the new aux file.  TeX will close it automatically at exit.
+     \immediate\openout\auxfile=\jobname.aux
+   \fi % \openindices needs to do some work in any case.
+   \openindices
+   \let\setfilename=\comment % Ignore extra @setfilename cmds.
+   %
+   % If texinfo.cnf is present on the system, read it.
+   % Useful for site-wide @afourpaper, etc.
+   \openin 1 texinfo.cnf
+   \ifeof 1 \else \input texinfo.cnf \fi
+   \closein 1
+   %
+   \comment % Ignore the actual filename.
+}
+
+% Called from \setfilename.
+%
+\def\openindices{%
+  \newindex{cp}%
+  \newcodeindex{fn}%
+  \newcodeindex{vr}%
+  \newcodeindex{tp}%
+  \newcodeindex{ky}%
+  \newcodeindex{pg}%
+}
+
+% @bye.
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+
+\message{pdf,}
+% adobe `portable' document format
+\newcount\tempnum
+\newcount\lnkcount
+\newtoks\filename
+\newcount\filenamelength
+\newcount\pgn
+\newtoks\toksA
+\newtoks\toksB
+\newtoks\toksC
+\newtoks\toksD
+\newbox\boxA
+\newcount\countA
+\newif\ifpdf
+\newif\ifpdfmakepagedest
+
+% when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1
+% can be set).  So we test for \relax and 0 as well as \undefined,
+% borrowed from ifpdf.sty.
+\ifx\pdfoutput\undefined
+\else
+  \ifx\pdfoutput\relax
+  \else
+    \ifcase\pdfoutput
+    \else
+      \pdftrue
+    \fi
+  \fi
+\fi
+
+% PDF uses PostScript string constants for the names of xref targets,
+% for display in the outlines, and in other places.  Thus, we have to
+% double any backslashes.  Otherwise, a name like "\node" will be
+% interpreted as a newline (\n), followed by o, d, e.  Not good.
+% http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html
+% (and related messages, the final outcome is that it is up to the TeX
+% user to double the backslashes and otherwise make the string valid, so
+% that's what we do).
+
+% double active backslashes.
+% 
+{\catcode`\@=0 \catcode`\\=\active
+ @gdef@activebackslashdouble{%
+   @catcode`@\=@active
+   @let\=@doublebackslash}
+}
+
+% To handle parens, we must adopt a different approach, since parens are
+% not active characters.  hyperref.dtx (which has the same problem as
+% us) handles it with this amazing macro to replace tokens, with minor
+% changes for Texinfo.  It is included here under the GPL by permission
+% from the author, Heiko Oberdiek.
+% 
+% #1 is the tokens to replace.
+% #2 is the replacement.
+% #3 is the control sequence with the string.
+% 
+\def\HyPsdSubst#1#2#3{%
+  \def\HyPsdReplace##1#1##2\END{%
+    ##1%
+    \ifx\\##2\\%
+    \else
+      #2%
+      \HyReturnAfterFi{%
+        \HyPsdReplace##2\END
+      }%
+    \fi
+  }%
+  \xdef#3{\expandafter\HyPsdReplace#3#1\END}%
+}
+\long\def\HyReturnAfterFi#1\fi{\fi#1}
+
+% #1 is a control sequence in which to do the replacements.
+\def\backslashparens#1{%
+  \xdef#1{#1}% redefine it as its expansion; the definition is simply
+             % \lastnode when called from \setref -> \pdfmkdest.
+  \HyPsdSubst{(}{\realbackslash(}{#1}%
+  \HyPsdSubst{)}{\realbackslash)}{#1}%
+}
+
+\newhelp\nopdfimagehelp{Texinfo supports .png, .jpg, .jpeg, and .pdf images
+with PDF output, and none of those formats could be found.  (.eps cannot
+be supported due to the design of the PDF format; use regular TeX (DVI
+output) for that.)}
+
+\ifpdf
+  %
+  % Color manipulation macros based on pdfcolor.tex.
+  \def\cmykDarkRed{0.28 1 1 0.35}
+  \def\cmykBlack{0 0 0 1}
+  %
+  \def\pdfsetcolor#1{\pdfliteral{#1 k}}
+  % Set color, and create a mark which defines \thiscolor accordingly,
+  % so that \makeheadline knows which color to restore.
+  \def\setcolor#1{%
+    \xdef\lastcolordefs{\gdef\noexpand\thiscolor{#1}}%
+    \domark
+    \pdfsetcolor{#1}%
+  }
+  %
+  \def\maincolor{\cmykBlack}
+  \pdfsetcolor{\maincolor}
+  \edef\thiscolor{\maincolor}
+  \def\lastcolordefs{}
+  %
+  \def\makefootline{%
+    \baselineskip24pt
+    \line{\pdfsetcolor{\maincolor}\the\footline}%
+  }
+  %
+  \def\makeheadline{%
+    \vbox to 0pt{%
+      \vskip-22.5pt
+      \line{%
+        \vbox to8.5pt{}%
+        % Extract \thiscolor definition from the marks.
+        \getcolormarks
+        % Typeset the headline with \maincolor, then restore the color.
+        \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}%
+      }%
+      \vss
+    }%
+    \nointerlineskip
+  }
+  %
+  %
+  \pdfcatalog{/PageMode /UseOutlines}
+  %
+  % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto).
+  \def\dopdfimage#1#2#3{%
+    \def\imagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}%
+    \def\imageheight{#3}\setbox2 = \hbox{\ignorespaces #3}%
+    %
+    % pdftex (and the PDF format) support .png, .jpg, .pdf (among
+    % others).  Let's try in that order.
+    \let\pdfimgext=\empty
+    \begingroup
+      \openin 1 #1.png \ifeof 1
+        \openin 1 #1.jpg \ifeof 1
+          \openin 1 #1.jpeg \ifeof 1
+            \openin 1 #1.JPG \ifeof 1
+              \openin 1 #1.pdf \ifeof 1
+                \errhelp = \nopdfimagehelp
+                \errmessage{Could not find image file #1 for pdf}%
+              \else \gdef\pdfimgext{pdf}%
+              \fi
+            \else \gdef\pdfimgext{JPG}%
+            \fi
+          \else \gdef\pdfimgext{jpeg}%
+          \fi
+        \else \gdef\pdfimgext{jpg}%
+        \fi
+      \else \gdef\pdfimgext{png}%
+      \fi
+      \closein 1
+    \endgroup
+    %
+    % without \immediate, pdftex seg faults when the same image is
+    % included twice.  (Version 3.14159-pre-1.0-unofficial-20010704.)
+    \ifnum\pdftexversion < 14
+      \immediate\pdfimage
+    \else
+      \immediate\pdfximage
+    \fi
+      \ifdim \wd0 >0pt width \imagewidth \fi
+      \ifdim \wd2 >0pt height \imageheight \fi
+      \ifnum\pdftexversion<13
+         #1.\pdfimgext
+       \else
+         {#1.\pdfimgext}%
+       \fi
+    \ifnum\pdftexversion < 14 \else
+      \pdfrefximage \pdflastximage
+    \fi}
+  %
+  \def\pdfmkdest#1{{%
+    % We have to set dummies so commands such as @code, and characters
+    % such as \, aren't expanded when present in a section title.
+    \indexnofonts
+    \turnoffactive
+    \activebackslashdouble
+    \makevalueexpandable
+    \def\pdfdestname{#1}%
+    \backslashparens\pdfdestname
+    \safewhatsit{\pdfdest name{\pdfdestname} xyz}%
+  }}
+  %
+  % used to mark target names; must be expandable.
+  \def\pdfmkpgn#1{#1}
+  %
+  % by default, use a color that is dark enough to print on paper as
+  % nearly black, but still distinguishable for online viewing.
+  \def\urlcolor{\cmykDarkRed}
+  \def\linkcolor{\cmykDarkRed}
+  \def\endlink{\setcolor{\maincolor}\pdfendlink}
+  %
+  % Adding outlines to PDF; macros for calculating structure of outlines
+  % come from Petr Olsak
+  \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0%
+    \else \csname#1\endcsname \fi}
+  \def\advancenumber#1{\tempnum=\expnumber{#1}\relax
+    \advance\tempnum by 1
+    \expandafter\xdef\csname#1\endcsname{\the\tempnum}}
+  %
+  % #1 is the section text, which is what will be displayed in the
+  % outline by the pdf viewer.  #2 is the pdf expression for the number
+  % of subentries (or empty, for subsubsections).  #3 is the node text,
+  % which might be empty if this toc entry had no corresponding node.
+  % #4 is the page number
+  %
+  \def\dopdfoutline#1#2#3#4{%
+    % Generate a link to the node text if that exists; else, use the
+    % page number.  We could generate a destination for the section
+    % text in the case where a section has no node, but it doesn't
+    % seem worth the trouble, since most documents are normally structured.
+    \def\pdfoutlinedest{#3}%
+    \ifx\pdfoutlinedest\empty
+      \def\pdfoutlinedest{#4}%
+    \else
+      % Doubled backslashes in the name.
+      {\activebackslashdouble \xdef\pdfoutlinedest{#3}%
+       \backslashparens\pdfoutlinedest}%
+    \fi
+    %
+    % Also double the backslashes in the display string.
+    {\activebackslashdouble \xdef\pdfoutlinetext{#1}%
+     \backslashparens\pdfoutlinetext}%
+    %
+    \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}%
+  }
+  %
+  \def\pdfmakeoutlines{%
+    \begingroup
+      % Thanh's hack / proper braces in bookmarks
+      \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace
+      \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace
+      %
+      % Read toc silently, to get counts of subentries for \pdfoutline.
+      \def\numchapentry##1##2##3##4{%
+       \def\thischapnum{##2}%
+       \def\thissecnum{0}%
+       \def\thissubsecnum{0}%
+      }%
+      \def\numsecentry##1##2##3##4{%
+       \advancenumber{chap\thischapnum}%
+       \def\thissecnum{##2}%
+       \def\thissubsecnum{0}%
+      }%
+      \def\numsubsecentry##1##2##3##4{%
+       \advancenumber{sec\thissecnum}%
+       \def\thissubsecnum{##2}%
+      }%
+      \def\numsubsubsecentry##1##2##3##4{%
+       \advancenumber{subsec\thissubsecnum}%
+      }%
+      \def\thischapnum{0}%
+      \def\thissecnum{0}%
+      \def\thissubsecnum{0}%
+      %
+      % use \def rather than \let here because we redefine \chapentry et
+      % al. a second time, below.
+      \def\appentry{\numchapentry}%
+      \def\appsecentry{\numsecentry}%
+      \def\appsubsecentry{\numsubsecentry}%
+      \def\appsubsubsecentry{\numsubsubsecentry}%
+      \def\unnchapentry{\numchapentry}%
+      \def\unnsecentry{\numsecentry}%
+      \def\unnsubsecentry{\numsubsecentry}%
+      \def\unnsubsubsecentry{\numsubsubsecentry}%
+      \readdatafile{toc}%
+      %
+      % Read toc second time, this time actually producing the outlines.
+      % The `-' means take the \expnumber as the absolute number of
+      % subentries, which we calculated on our first read of the .toc above.
+      %
+      % We use the node names as the destinations.
+      \def\numchapentry##1##2##3##4{%
+        \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}%
+      \def\numsecentry##1##2##3##4{%
+        \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}%
+      \def\numsubsecentry##1##2##3##4{%
+        \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}%
+      \def\numsubsubsecentry##1##2##3##4{% count is always zero
+        \dopdfoutline{##1}{}{##3}{##4}}%
+      %
+      % PDF outlines are displayed using system fonts, instead of
+      % document fonts.  Therefore we cannot use special characters,
+      % since the encoding is unknown.  For example, the eogonek from
+      % Latin 2 (0xea) gets translated to a | character.  Info from
+      % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100.
+      %
+      % xx to do this right, we have to translate 8-bit characters to
+      % their "best" equivalent, based on the @documentencoding.  Right
+      % now, I guess we'll just let the pdf reader have its way.
+      \indexnofonts
+      \setupdatafile
+      \catcode`\\=\active \otherbackslash
+      \input \tocreadfilename
+    \endgroup
+  }
+  %
+  \def\skipspaces#1{\def\PP{#1}\def\D{|}%
+    \ifx\PP\D\let\nextsp\relax
+    \else\let\nextsp\skipspaces
+      \ifx\p\space\else\addtokens{\filename}{\PP}%
+        \advance\filenamelength by 1
+      \fi
+    \fi
+    \nextsp}
+  \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax}
+  \ifnum\pdftexversion < 14
+    \let \startlink \pdfannotlink
+  \else
+    \let \startlink \pdfstartlink
+  \fi
+  % make a live url in pdf output.
+  \def\pdfurl#1{%
+    \begingroup
+      % it seems we really need yet another set of dummies; have not
+      % tried to figure out what each command should do in the context
+      % of @url.  for now, just make @/ a no-op, that's the only one
+      % people have actually reported a problem with.
+      % 
+      \normalturnoffactive
+      \def\@{@}%
+      \let\/=\empty
+      \makevalueexpandable
+      \leavevmode\setcolor{\urlcolor}%
+      \startlink attr{/Border [0 0 0]}%
+        user{/Subtype /Link /A << /S /URI /URI (#1) >>}%
+    \endgroup}
+  \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}}
+  \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks}
+  \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks}
+  \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}}
+  \def\maketoks{%
+    \expandafter\poptoks\the\toksA|ENDTOKS|\relax
+    \ifx\first0\adn0
+    \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3
+    \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6
+    \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9
+    \else
+      \ifnum0=\countA\else\makelink\fi
+      \ifx\first.\let\next=\done\else
+        \let\next=\maketoks
+        \addtokens{\toksB}{\the\toksD}
+        \ifx\first,\addtokens{\toksB}{\space}\fi
+      \fi
+    \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+    \next}
+  \def\makelink{\addtokens{\toksB}%
+    {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0}
+  \def\pdflink#1{%
+    \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}}
+    \setcolor{\linkcolor}#1\endlink}
+  \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
+\else
+  \let\pdfmkdest = \gobble
+  \let\pdfurl = \gobble
+  \let\endlink = \relax
+  \let\setcolor = \gobble
+  \let\pdfsetcolor = \gobble
+  \let\pdfmakeoutlines = \relax
+\fi  % \ifx\pdfoutput
+
+
+\message{fonts,}
+
+% Change the current font style to #1, remembering it in \curfontstyle.
+% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in
+% italics, not bold italics.
+%
+\def\setfontstyle#1{%
+  \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd.
+  \csname ten#1\endcsname  % change the current font
+}
+
+% Select #1 fonts with the current style.
+%
+\def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname}
+
+\def\rm{\fam=0 \setfontstyle{rm}}
+\def\it{\fam=\itfam \setfontstyle{it}}
+\def\sl{\fam=\slfam \setfontstyle{sl}}
+\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf}
+\def\tt{\fam=\ttfam \setfontstyle{tt}}
+
+% Texinfo sort of supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf.
+\newfam\sffam
+\def\sf{\fam=\sffam \setfontstyle{sf}}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+% We don't need math for this font style.
+\def\ttsl{\setfontstyle{ttsl}}
+
+
+% Default leading.
+\newdimen\textleading  \textleading = 13.2pt
+
+% Set the baselineskip to #1, and the lineskip and strut size
+% correspondingly.  There is no deep meaning behind these magic numbers
+% used as factors; they just match (closely enough) what Knuth defined.
+%
+\def\lineskipfactor{.08333}
+\def\strutheightpercent{.70833}
+\def\strutdepthpercent {.29167}
+%
+% can get a sort of poor man's double spacing by redefining this.
+\def\baselinefactor{1}
+%
+\def\setleading#1{%
+  \dimen0 = #1\relax
+  \normalbaselineskip = \baselinefactor\dimen0
+  \normallineskip = \lineskipfactor\normalbaselineskip
+  \normalbaselines
+  \setbox\strutbox =\hbox{%
+    \vrule width0pt height\strutheightpercent\baselineskip
+                    depth \strutdepthpercent \baselineskip
+  }%
+}
+
+%
+% PDF CMaps.  See also LaTeX's t1.cmap.
+%
+% \cmapOT1
+\ifpdf
+  \begingroup
+    \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
+    \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
+%%DocumentNeededResources: ProcSet (CIDInit)
+%%IncludeResource: ProcSet (CIDInit)
+%%BeginResource: CMap (TeX-OT1-0)
+%%Title: (TeX-OT1-0 TeX OT1 0)
+%%Version: 1.000
+%%EndComments
+/CIDInit /ProcSet findresource begin
+12 dict begin
+begincmap
+/CIDSystemInfo
+<< /Registry (TeX)
+/Ordering (OT1)
+/Supplement 0
+>> def
+/CMapName /TeX-OT1-0 def
+/CMapType 2 def
+1 begincodespacerange
+<00> <7F>
+endcodespacerange
+8 beginbfrange
+<00> <01> <0393>
+<09> <0A> <03A8>
+<23> <26> <0023>
+<28> <3B> <0028>
+<3F> <5B> <003F>
+<5D> <5E> <005D>
+<61> <7A> <0061>
+<7B> <7C> <2013>
+endbfrange
+40 beginbfchar
+<02> <0398>
+<03> <039B>
+<04> <039E>
+<05> <03A0>
+<06> <03A3>
+<07> <03D2>
+<08> <03A6>
+<0B> <00660066>
+<0C> <00660069>
+<0D> <0066006C>
+<0E> <006600660069>
+<0F> <00660066006C>
+<10> <0131>
+<11> <0237>
+<12> <0060>
+<13> <00B4>
+<14> <02C7>
+<15> <02D8>
+<16> <00AF>
+<17> <02DA>
+<18> <00B8>
+<19> <00DF>
+<1A> <00E6>
+<1B> <0153>
+<1C> <00F8>
+<1D> <00C6>
+<1E> <0152>
+<1F> <00D8>
+<21> <0021>
+<22> <201D>
+<27> <2019>
+<3C> <00A1>
+<3D> <003D>
+<3E> <00BF>
+<5C> <201C>
+<5F> <02D9>
+<60> <2018>
+<7D> <02DD>
+<7E> <007E>
+<7F> <00A8>
+endbfchar
+endcmap
+CMapName currentdict /CMap defineresource pop
+end
+end
+%%EndResource
+%%EOF
+    }\endgroup
+  \expandafter\edef\csname cmapOT1\endcsname#1{%
+    \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
+  }%
+%
+% \cmapOT1IT
+  \begingroup
+    \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
+    \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
+%%DocumentNeededResources: ProcSet (CIDInit)
+%%IncludeResource: ProcSet (CIDInit)
+%%BeginResource: CMap (TeX-OT1IT-0)
+%%Title: (TeX-OT1IT-0 TeX OT1IT 0)
+%%Version: 1.000
+%%EndComments
+/CIDInit /ProcSet findresource begin
+12 dict begin
+begincmap
+/CIDSystemInfo
+<< /Registry (TeX)
+/Ordering (OT1IT)
+/Supplement 0
+>> def
+/CMapName /TeX-OT1IT-0 def
+/CMapType 2 def
+1 begincodespacerange
+<00> <7F>
+endcodespacerange
+8 beginbfrange
+<00> <01> <0393>
+<09> <0A> <03A8>
+<25> <26> <0025>
+<28> <3B> <0028>
+<3F> <5B> <003F>
+<5D> <5E> <005D>
+<61> <7A> <0061>
+<7B> <7C> <2013>
+endbfrange
+42 beginbfchar
+<02> <0398>
+<03> <039B>
+<04> <039E>
+<05> <03A0>
+<06> <03A3>
+<07> <03D2>
+<08> <03A6>
+<0B> <00660066>
+<0C> <00660069>
+<0D> <0066006C>
+<0E> <006600660069>
+<0F> <00660066006C>
+<10> <0131>
+<11> <0237>
+<12> <0060>
+<13> <00B4>
+<14> <02C7>
+<15> <02D8>
+<16> <00AF>
+<17> <02DA>
+<18> <00B8>
+<19> <00DF>
+<1A> <00E6>
+<1B> <0153>
+<1C> <00F8>
+<1D> <00C6>
+<1E> <0152>
+<1F> <00D8>
+<21> <0021>
+<22> <201D>
+<23> <0023>
+<24> <00A3>
+<27> <2019>
+<3C> <00A1>
+<3D> <003D>
+<3E> <00BF>
+<5C> <201C>
+<5F> <02D9>
+<60> <2018>
+<7D> <02DD>
+<7E> <007E>
+<7F> <00A8>
+endbfchar
+endcmap
+CMapName currentdict /CMap defineresource pop
+end
+end
+%%EndResource
+%%EOF
+    }\endgroup
+  \expandafter\edef\csname cmapOT1IT\endcsname#1{%
+    \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
+  }%
+%
+% \cmapOT1TT
+  \begingroup
+    \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
+    \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
+%%DocumentNeededResources: ProcSet (CIDInit)
+%%IncludeResource: ProcSet (CIDInit)
+%%BeginResource: CMap (TeX-OT1TT-0)
+%%Title: (TeX-OT1TT-0 TeX OT1TT 0)
+%%Version: 1.000
+%%EndComments
+/CIDInit /ProcSet findresource begin
+12 dict begin
+begincmap
+/CIDSystemInfo
+<< /Registry (TeX)
+/Ordering (OT1TT)
+/Supplement 0
+>> def
+/CMapName /TeX-OT1TT-0 def
+/CMapType 2 def
+1 begincodespacerange
+<00> <7F>
+endcodespacerange
+5 beginbfrange
+<00> <01> <0393>
+<09> <0A> <03A8>
+<21> <26> <0021>
+<28> <5F> <0028>
+<61> <7E> <0061>
+endbfrange
+32 beginbfchar
+<02> <0398>
+<03> <039B>
+<04> <039E>
+<05> <03A0>
+<06> <03A3>
+<07> <03D2>
+<08> <03A6>
+<0B> <2191>
+<0C> <2193>
+<0D> <0027>
+<0E> <00A1>
+<0F> <00BF>
+<10> <0131>
+<11> <0237>
+<12> <0060>
+<13> <00B4>
+<14> <02C7>
+<15> <02D8>
+<16> <00AF>
+<17> <02DA>
+<18> <00B8>
+<19> <00DF>
+<1A> <00E6>
+<1B> <0153>
+<1C> <00F8>
+<1D> <00C6>
+<1E> <0152>
+<1F> <00D8>
+<20> <2423>
+<27> <2019>
+<60> <2018>
+<7F> <00A8>
+endbfchar
+endcmap
+CMapName currentdict /CMap defineresource pop
+end
+end
+%%EndResource
+%%EOF
+    }\endgroup
+  \expandafter\edef\csname cmapOT1TT\endcsname#1{%
+    \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
+  }%
+\else
+  \expandafter\let\csname cmapOT1\endcsname\gobble
+  \expandafter\let\csname cmapOT1IT\endcsname\gobble
+  \expandafter\let\csname cmapOT1TT\endcsname\gobble
+\fi
+
+
+% Set the font macro #1 to the font named #2, adding on the
+% specified font prefix (normally `cm').
+% #3 is the font's design size, #4 is a scale factor, #5 is the CMap
+% encoding (currently only OT1, OT1IT and OT1TT are allowed, pass
+% empty to omit).
+\def\setfont#1#2#3#4#5{%
+  \font#1=\fontprefix#2#3 scaled #4
+  \csname cmap#5\endcsname#1%
+}
+% This is what gets called when #5 of \setfont is empty.
+\let\cmap\gobble
+
+
+% Use cm as the default font prefix.
+% To specify the font prefix, you must define \fontprefix
+% before you read in texinfo.tex.
+\ifx\fontprefix\undefined
+\def\fontprefix{cm}
+\fi
+% Support font families that don't use the same naming scheme as CM.
+\def\rmshape{r}
+\def\rmbshape{bx}               %where the normal face is bold
+\def\bfshape{b}
+\def\bxshape{bx}
+\def\ttshape{tt}
+\def\ttbshape{tt}
+\def\ttslshape{sltt}
+\def\itshape{ti}
+\def\itbshape{bxti}
+\def\slshape{sl}
+\def\slbshape{bxsl}
+\def\sfshape{ss}
+\def\sfbshape{ss}
+\def\scshape{csc}
+\def\scbshape{csc}
+
+% Definitions for a main text size of 11pt.  This is the default in
+% Texinfo.
+% 
+\def\definetextfontsizexi{%
+% Text fonts (11.2pt, magstep1).
+\def\textnominalsize{11pt}
+\edef\mainmagstep{\magstephalf}
+\setfont\textrm\rmshape{10}{\mainmagstep}{OT1}
+\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT}
+\setfont\textbf\bfshape{10}{\mainmagstep}{OT1}
+\setfont\textit\itshape{10}{\mainmagstep}{OT1IT}
+\setfont\textsl\slshape{10}{\mainmagstep}{OT1}
+\setfont\textsf\sfshape{10}{\mainmagstep}{OT1}
+\setfont\textsc\scshape{10}{\mainmagstep}{OT1}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT}
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+\def\textecsize{1095}
+
+% A few fonts for @defun names and args.
+\setfont\defbf\bfshape{10}{\magstep1}{OT1}
+\setfont\deftt\ttshape{10}{\magstep1}{OT1TT}
+\setfont\defttsl\ttslshape{10}{\magstep1}{OT1TT}
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf}
+
+% Fonts for indices, footnotes, small examples (9pt).
+\def\smallnominalsize{9pt}
+\setfont\smallrm\rmshape{9}{1000}{OT1}
+\setfont\smalltt\ttshape{9}{1000}{OT1TT}
+\setfont\smallbf\bfshape{10}{900}{OT1}
+\setfont\smallit\itshape{9}{1000}{OT1IT}
+\setfont\smallsl\slshape{9}{1000}{OT1}
+\setfont\smallsf\sfshape{9}{1000}{OT1}
+\setfont\smallsc\scshape{10}{900}{OT1}
+\setfont\smallttsl\ttslshape{10}{900}{OT1TT}
+\font\smalli=cmmi9
+\font\smallsy=cmsy9
+\def\smallecsize{0900}
+
+% Fonts for small examples (8pt).
+\def\smallernominalsize{8pt}
+\setfont\smallerrm\rmshape{8}{1000}{OT1}
+\setfont\smallertt\ttshape{8}{1000}{OT1TT}
+\setfont\smallerbf\bfshape{10}{800}{OT1}
+\setfont\smallerit\itshape{8}{1000}{OT1IT}
+\setfont\smallersl\slshape{8}{1000}{OT1}
+\setfont\smallersf\sfshape{8}{1000}{OT1}
+\setfont\smallersc\scshape{10}{800}{OT1}
+\setfont\smallerttsl\ttslshape{10}{800}{OT1TT}
+\font\smalleri=cmmi8
+\font\smallersy=cmsy8
+\def\smallerecsize{0800}
+
+% Fonts for title page (20.4pt):
+\def\titlenominalsize{20pt}
+\setfont\titlerm\rmbshape{12}{\magstep3}{OT1}
+\setfont\titleit\itbshape{10}{\magstep4}{OT1IT}
+\setfont\titlesl\slbshape{10}{\magstep4}{OT1}
+\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT}
+\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT}
+\setfont\titlesf\sfbshape{17}{\magstep1}{OT1}
+\let\titlebf=\titlerm
+\setfont\titlesc\scbshape{10}{\magstep4}{OT1}
+\font\titlei=cmmi12 scaled \magstep3
+\font\titlesy=cmsy10 scaled \magstep4
+\def\authorrm{\secrm}
+\def\authortt{\sectt}
+\def\titleecsize{2074}
+
+% Chapter (and unnumbered) fonts (17.28pt).
+\def\chapnominalsize{17pt}
+\setfont\chaprm\rmbshape{12}{\magstep2}{OT1}
+\setfont\chapit\itbshape{10}{\magstep3}{OT1IT}
+\setfont\chapsl\slbshape{10}{\magstep3}{OT1}
+\setfont\chaptt\ttbshape{12}{\magstep2}{OT1TT}
+\setfont\chapttsl\ttslshape{10}{\magstep3}{OT1TT}
+\setfont\chapsf\sfbshape{17}{1000}{OT1}
+\let\chapbf=\chaprm
+\setfont\chapsc\scbshape{10}{\magstep3}{OT1}
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+\def\chapecsize{1728}
+
+% Section fonts (14.4pt).
+\def\secnominalsize{14pt}
+\setfont\secrm\rmbshape{12}{\magstep1}{OT1}
+\setfont\secit\itbshape{10}{\magstep2}{OT1IT}
+\setfont\secsl\slbshape{10}{\magstep2}{OT1}
+\setfont\sectt\ttbshape{12}{\magstep1}{OT1TT}
+\setfont\secttsl\ttslshape{10}{\magstep2}{OT1TT}
+\setfont\secsf\sfbshape{12}{\magstep1}{OT1}
+\let\secbf\secrm
+\setfont\secsc\scbshape{10}{\magstep2}{OT1}
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+\def\sececsize{1440}
+
+% Subsection fonts (13.15pt).
+\def\ssecnominalsize{13pt}
+\setfont\ssecrm\rmbshape{12}{\magstephalf}{OT1}
+\setfont\ssecit\itbshape{10}{1315}{OT1IT}
+\setfont\ssecsl\slbshape{10}{1315}{OT1}
+\setfont\ssectt\ttbshape{12}{\magstephalf}{OT1TT}
+\setfont\ssecttsl\ttslshape{10}{1315}{OT1TT}
+\setfont\ssecsf\sfbshape{12}{\magstephalf}{OT1}
+\let\ssecbf\ssecrm
+\setfont\ssecsc\scbshape{10}{1315}{OT1}
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled 1315
+\def\ssececsize{1200}
+
+% Reduced fonts for @acro in text (10pt).
+\def\reducednominalsize{10pt}
+\setfont\reducedrm\rmshape{10}{1000}{OT1}
+\setfont\reducedtt\ttshape{10}{1000}{OT1TT}
+\setfont\reducedbf\bfshape{10}{1000}{OT1}
+\setfont\reducedit\itshape{10}{1000}{OT1IT}
+\setfont\reducedsl\slshape{10}{1000}{OT1}
+\setfont\reducedsf\sfshape{10}{1000}{OT1}
+\setfont\reducedsc\scshape{10}{1000}{OT1}
+\setfont\reducedttsl\ttslshape{10}{1000}{OT1TT}
+\font\reducedi=cmmi10
+\font\reducedsy=cmsy10
+\def\reducedecsize{1000}
+
+% reset the current fonts
+\textfonts
+\rm
+} % end of 11pt text font size definitions
+
+
+% Definitions to make the main text be 10pt Computer Modern, with
+% section, chapter, etc., sizes following suit.  This is for the GNU
+% Press printing of the Emacs 22 manual.  Maybe other manuals in the
+% future.  Used with @smallbook, which sets the leading to 12pt.
+% 
+\def\definetextfontsizex{%
+% Text fonts (10pt).
+\def\textnominalsize{10pt}
+\edef\mainmagstep{1000}
+\setfont\textrm\rmshape{10}{\mainmagstep}{OT1}
+\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT}
+\setfont\textbf\bfshape{10}{\mainmagstep}{OT1}
+\setfont\textit\itshape{10}{\mainmagstep}{OT1IT}
+\setfont\textsl\slshape{10}{\mainmagstep}{OT1}
+\setfont\textsf\sfshape{10}{\mainmagstep}{OT1}
+\setfont\textsc\scshape{10}{\mainmagstep}{OT1}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT}
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+\def\textecsize{1000}
+
+% A few fonts for @defun names and args.
+\setfont\defbf\bfshape{10}{\magstephalf}{OT1}
+\setfont\deftt\ttshape{10}{\magstephalf}{OT1TT}
+\setfont\defttsl\ttslshape{10}{\magstephalf}{OT1TT}
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf}
+
+% Fonts for indices, footnotes, small examples (9pt).
+\def\smallnominalsize{9pt}
+\setfont\smallrm\rmshape{9}{1000}{OT1}
+\setfont\smalltt\ttshape{9}{1000}{OT1TT}
+\setfont\smallbf\bfshape{10}{900}{OT1}
+\setfont\smallit\itshape{9}{1000}{OT1IT}
+\setfont\smallsl\slshape{9}{1000}{OT1}
+\setfont\smallsf\sfshape{9}{1000}{OT1}
+\setfont\smallsc\scshape{10}{900}{OT1}
+\setfont\smallttsl\ttslshape{10}{900}{OT1TT}
+\font\smalli=cmmi9
+\font\smallsy=cmsy9
+\def\smallecsize{0900}
+
+% Fonts for small examples (8pt).
+\def\smallernominalsize{8pt}
+\setfont\smallerrm\rmshape{8}{1000}{OT1}
+\setfont\smallertt\ttshape{8}{1000}{OT1TT}
+\setfont\smallerbf\bfshape{10}{800}{OT1}
+\setfont\smallerit\itshape{8}{1000}{OT1IT}
+\setfont\smallersl\slshape{8}{1000}{OT1}
+\setfont\smallersf\sfshape{8}{1000}{OT1}
+\setfont\smallersc\scshape{10}{800}{OT1}
+\setfont\smallerttsl\ttslshape{10}{800}{OT1TT}
+\font\smalleri=cmmi8
+\font\smallersy=cmsy8
+\def\smallerecsize{0800}
+
+% Fonts for title page (20.4pt):
+\def\titlenominalsize{20pt}
+\setfont\titlerm\rmbshape{12}{\magstep3}{OT1}
+\setfont\titleit\itbshape{10}{\magstep4}{OT1IT}
+\setfont\titlesl\slbshape{10}{\magstep4}{OT1}
+\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT}
+\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT}
+\setfont\titlesf\sfbshape{17}{\magstep1}{OT1}
+\let\titlebf=\titlerm
+\setfont\titlesc\scbshape{10}{\magstep4}{OT1}
+\font\titlei=cmmi12 scaled \magstep3
+\font\titlesy=cmsy10 scaled \magstep4
+\def\authorrm{\secrm}
+\def\authortt{\sectt}
+\def\titleecsize{2074}
+
+% Chapter fonts (14.4pt).
+\def\chapnominalsize{14pt}
+\setfont\chaprm\rmbshape{12}{\magstep1}{OT1}
+\setfont\chapit\itbshape{10}{\magstep2}{OT1IT}
+\setfont\chapsl\slbshape{10}{\magstep2}{OT1}
+\setfont\chaptt\ttbshape{12}{\magstep1}{OT1TT}
+\setfont\chapttsl\ttslshape{10}{\magstep2}{OT1TT}
+\setfont\chapsf\sfbshape{12}{\magstep1}{OT1}
+\let\chapbf\chaprm
+\setfont\chapsc\scbshape{10}{\magstep2}{OT1}
+\font\chapi=cmmi12 scaled \magstep1
+\font\chapsy=cmsy10 scaled \magstep2
+\def\chapecsize{1440}
+
+% Section fonts (12pt).
+\def\secnominalsize{12pt}
+\setfont\secrm\rmbshape{12}{1000}{OT1}
+\setfont\secit\itbshape{10}{\magstep1}{OT1IT}
+\setfont\secsl\slbshape{10}{\magstep1}{OT1}
+\setfont\sectt\ttbshape{12}{1000}{OT1TT}
+\setfont\secttsl\ttslshape{10}{\magstep1}{OT1TT}
+\setfont\secsf\sfbshape{12}{1000}{OT1}
+\let\secbf\secrm
+\setfont\secsc\scbshape{10}{\magstep1}{OT1}
+\font\seci=cmmi12 
+\font\secsy=cmsy10 scaled \magstep1
+\def\sececsize{1200}
+
+% Subsection fonts (10pt).
+\def\ssecnominalsize{10pt}
+\setfont\ssecrm\rmbshape{10}{1000}{OT1}
+\setfont\ssecit\itbshape{10}{1000}{OT1IT}
+\setfont\ssecsl\slbshape{10}{1000}{OT1}
+\setfont\ssectt\ttbshape{10}{1000}{OT1TT}
+\setfont\ssecttsl\ttslshape{10}{1000}{OT1TT}
+\setfont\ssecsf\sfbshape{10}{1000}{OT1}
+\let\ssecbf\ssecrm
+\setfont\ssecsc\scbshape{10}{1000}{OT1}
+\font\sseci=cmmi10
+\font\ssecsy=cmsy10
+\def\ssececsize{1000}
+
+% Reduced fonts for @acro in text (9pt).
+\def\reducednominalsize{9pt}
+\setfont\reducedrm\rmshape{9}{1000}{OT1}
+\setfont\reducedtt\ttshape{9}{1000}{OT1TT}
+\setfont\reducedbf\bfshape{10}{900}{OT1}
+\setfont\reducedit\itshape{9}{1000}{OT1IT}
+\setfont\reducedsl\slshape{9}{1000}{OT1}
+\setfont\reducedsf\sfshape{9}{1000}{OT1}
+\setfont\reducedsc\scshape{10}{900}{OT1}
+\setfont\reducedttsl\ttslshape{10}{900}{OT1TT}
+\font\reducedi=cmmi9
+\font\reducedsy=cmsy9
+\def\reducedecsize{0900}
+
+% reduce space between paragraphs
+\divide\parskip by 2
+
+% reset the current fonts
+\textfonts
+\rm
+} % end of 10pt text font size definitions
+
+
+% We provide the user-level command
+%   @fonttextsize 10
+% (or 11) to redefine the text font size.  pt is assumed.
+% 
+\def\xword{10}
+\def\xiword{11}
+%
+\parseargdef\fonttextsize{%
+  \def\textsizearg{#1}%
+  \wlog{doing @fonttextsize \textsizearg}%
+  %
+  % Set \globaldefs so that documents can use this inside @tex, since
+  % makeinfo 4.8 does not support it, but we need it nonetheless.
+  % 
+ \begingroup \globaldefs=1
+  \ifx\textsizearg\xword \definetextfontsizex
+  \else \ifx\textsizearg\xiword \definetextfontsizexi
+  \else
+    \errhelp=\EMsimple
+    \errmessage{@fonttextsize only supports `10' or `11', not `\textsizearg'}
+  \fi\fi
+ \endgroup
+}
+
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families.  Since
+% texinfo doesn't allow for producing subscripts and superscripts except
+% in the main text, we don't bother to reset \scriptfont and
+% \scriptscriptfont (which would also require loading a lot more fonts).
+%
+\def\resetmathfonts{%
+  \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy
+  \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf
+  \textfont\ttfam=\tentt \textfont\sffam=\tensf
+}
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE.  We do this because \STYLE needs to also set the
+% current \fam for math mode.  Our \STYLE (e.g., \rm) commands hardwire
+% \tenSTYLE to set the current font.
+%
+% Each font-changing command also sets the names \lsize (one size lower)
+% and \lllsize (three sizes lower).  These relative commands are used in
+% the LaTeX logo and acronyms.
+%
+% This all needs generalizing, badly.
+%
+\def\textfonts{%
+  \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+  \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+  \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy
+  \let\tenttsl=\textttsl
+  \def\curfontsize{text}%
+  \def\lsize{reduced}\def\lllsize{smaller}%
+  \resetmathfonts \setleading{\textleading}}
+\def\titlefonts{%
+  \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl
+  \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc
+  \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy
+  \let\tenttsl=\titlettsl
+  \def\curfontsize{title}%
+  \def\lsize{chap}\def\lllsize{subsec}%
+  \resetmathfonts \setleading{25pt}}
+\def\titlefont#1{{\titlefonts\rm #1}}
+\def\chapfonts{%
+  \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+  \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+  \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy
+  \let\tenttsl=\chapttsl
+  \def\curfontsize{chap}%
+  \def\lsize{sec}\def\lllsize{text}%
+  \resetmathfonts \setleading{19pt}}
+\def\secfonts{%
+  \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+  \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+  \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy
+  \let\tenttsl=\secttsl
+  \def\curfontsize{sec}%
+  \def\lsize{subsec}\def\lllsize{reduced}%
+  \resetmathfonts \setleading{16pt}}
+\def\subsecfonts{%
+  \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+  \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+  \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy
+  \let\tenttsl=\ssecttsl
+  \def\curfontsize{ssec}%
+  \def\lsize{text}\def\lllsize{small}%
+  \resetmathfonts \setleading{15pt}}
+\let\subsubsecfonts = \subsecfonts
+\def\reducedfonts{%
+  \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl
+  \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc
+  \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy
+  \let\tenttsl=\reducedttsl
+  \def\curfontsize{reduced}%
+  \def\lsize{small}\def\lllsize{smaller}%
+  \resetmathfonts \setleading{10.5pt}}
+\def\smallfonts{%
+  \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl
+  \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc
+  \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy
+  \let\tenttsl=\smallttsl
+  \def\curfontsize{small}%
+  \def\lsize{smaller}\def\lllsize{smaller}%
+  \resetmathfonts \setleading{10.5pt}}
+\def\smallerfonts{%
+  \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl
+  \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc
+  \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy
+  \let\tenttsl=\smallerttsl
+  \def\curfontsize{smaller}%
+  \def\lsize{smaller}\def\lllsize{smaller}%
+  \resetmathfonts \setleading{9.5pt}}
+
+% Set the fonts to use with the @small... environments.
+\let\smallexamplefonts = \smallfonts
+
+% About \smallexamplefonts.  If we use \smallfonts (9pt), @smallexample
+% can fit this many characters:
+%   8.5x11=86   smallbook=72  a4=90  a5=69
+% If we use \scriptfonts (8pt), then we can fit this many characters:
+%   8.5x11=90+  smallbook=80  a4=90+  a5=77
+% For me, subjectively, the few extra characters that fit aren't worth
+% the additional smallness of 8pt.  So I'm making the default 9pt.
+%
+% By the way, for comparison, here's what fits with @example (10pt):
+%   8.5x11=71  smallbook=60  a4=75  a5=58
+%
+% I wish the USA used A4 paper.
+% --karl, 24jan03.
+
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\definetextfontsizexi
+
+% Define these so they can be easily changed for other fonts.
+\def\angleleft{$\langle$}
+\def\angleright{$\rangle$}
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\setfont\shortcontrm\rmshape{12}{1000}{OT1}
+\setfont\shortcontbf\bfshape{10}{\magstep1}{OT1}  % no cmb12
+\setfont\shortcontsl\slshape{12}{1000}{OT1}
+\setfont\shortconttt\ttshape{12}{1000}{OT1TT}
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else
+                    \ptexslash\fi\fi\fi}
+\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx}
+\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx}
+
+% like \smartslanted except unconditionally uses \ttsl.
+% @var is set to this for defun arguments.
+\def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx}
+
+% like \smartslanted except unconditionally use \sl.  We never want
+% ttsl for book titles, do we?
+\def\cite#1{{\sl #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\slanted=\smartslanted
+\let\var=\smartslanted
+\let\dfn=\smartslanted
+\let\emph=\smartitalic
+
+% @b, explicit bold.
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% @sansserif, explicit sans.
+\def\sansserif#1{{\sf #1}}
+
+% We can't just use \exhyphenpenalty, because that only has effect at
+% the end of a paragraph.  Restore normal hyphenation at the end of the
+% group within which \nohyphenation is presumably called.
+%
+\def\nohyphenation{\hyphenchar\font = -1  \aftergroup\restorehyphenation}
+\def\restorehyphenation{\hyphenchar\font = `- }
+
+% Set sfcode to normal for the chars that usually have another value.
+% Can't use plain's \frenchspacing because it uses the `\x notation, and
+% sometimes \x has an active definition that messes things up.
+%
+\catcode`@=11
+  \def\plainfrenchspacing{%
+    \sfcode\dotChar  =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m
+    \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m
+    \def\endofsentencespacefactor{1000}% for @. and friends
+  }
+  \def\plainnonfrenchspacing{%
+    \sfcode`\.3000\sfcode`\?3000\sfcode`\!3000
+    \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250
+    \def\endofsentencespacefactor{3000}% for @. and friends
+  }
+\catcode`@=\other
+\def\endofsentencespacefactor{3000}% default
+
+\def\t#1{%
+  {\tt \rawbackslash \plainfrenchspacing #1}%
+  \null
+}
+\def\samp#1{`\tclose{#1}'\null}
+\setfont\keyrm\rmshape{8}{1000}{OT1}
+\font\keysy=cmsy9
+\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{%
+  \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{%
+    \vbox{\hrule\kern-0.4pt
+     \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}%
+    \kern-0.4pt\hrule}%
+  \kern-.06em\raise0.4pt\hbox{\angleright}}}}
+\def\key #1{{\nohyphenation \uppercase{#1}}\null}
+% The old definition, with no lozenge:
+%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+% @file, @option are the same as @samp.
+\let\file=\samp
+\let\option=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\def\tclose#1{%
+  {%
+    % Change normal interword space to be same as for the current font.
+    \spaceskip = \fontdimen2\font
+    %
+    % Switch to typewriter.
+    \tt
+    %
+    % But `\ ' produces the large typewriter interword space.
+    \def\ {{\spaceskip = 0pt{} }}%
+    %
+    % Turn off hyphenation.
+    \nohyphenation
+    %
+    \rawbackslash
+    \plainfrenchspacing
+    #1%
+  }%
+  \null
+}
+
+% We *must* turn on hyphenation at `-' and `_' in @code.
+% Otherwise, it is too hard to avoid overfull hboxes
+% in the Emacs manual, the Library manual, etc.
+
+% Unfortunately, TeX uses one parameter (\hyphenchar) to control
+% both hyphenation at - and hyphenation within words.
+% We must therefore turn them both off (\tclose does that)
+% and arrange explicitly to hyphenate at a dash.
+%  -- rms.
+{
+  \catcode`\-=\active \catcode`\_=\active
+  \catcode`\'=\active \catcode`\`=\active
+  %
+  \global\def\code{\begingroup
+    \catcode\rquoteChar=\active \catcode\lquoteChar=\active
+    \let'\codequoteright \let`\codequoteleft
+    %
+    \catcode\dashChar=\active  \catcode\underChar=\active
+    \ifallowcodebreaks
+     \let-\codedash
+     \let_\codeunder
+    \else
+     \let-\realdash
+     \let_\realunder
+    \fi
+    \codex
+  }
+}
+
+\def\realdash{-}
+\def\codedash{-\discretionary{}{}{}}
+\def\codeunder{%
+  % this is all so @math{@code{var_name}+1} can work.  In math mode, _
+  % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.)
+  % will therefore expand the active definition of _, which is us
+  % (inside @code that is), therefore an endless loop.
+  \ifusingtt{\ifmmode
+               \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_.
+             \else\normalunderscore \fi
+             \discretionary{}{}{}}%
+            {\_}%
+}
+\def\codex #1{\tclose{#1}\endgroup}
+
+% An additional complication: the above will allow breaks after, e.g.,
+% each of the four underscores in __typeof__.  This is undesirable in
+% some manuals, especially if they don't have long identifiers in
+% general.  @allowcodebreaks provides a way to control this.
+% 
+\newif\ifallowcodebreaks  \allowcodebreakstrue
+
+\def\keywordtrue{true}
+\def\keywordfalse{false}
+
+\parseargdef\allowcodebreaks{%
+  \def\txiarg{#1}%
+  \ifx\txiarg\keywordtrue
+    \allowcodebreakstrue
+  \else\ifx\txiarg\keywordfalse
+    \allowcodebreaksfalse
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @allowcodebreaks option `\txiarg'}%
+  \fi\fi
+}
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+
+% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always),
+%   `example' (@kbd uses ttsl only inside of @example and friends),
+%   or `code' (@kbd uses normal tty font always).
+\parseargdef\kbdinputstyle{%
+  \def\txiarg{#1}%
+  \ifx\txiarg\worddistinct
+    \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}%
+  \else\ifx\txiarg\wordexample
+    \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}%
+  \else\ifx\txiarg\wordcode
+    \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}%
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @kbdinputstyle option `\txiarg'}%
+  \fi\fi\fi
+}
+\def\worddistinct{distinct}
+\def\wordexample{example}
+\def\wordcode{code}
+
+% Default is `distinct.'
+\kbdinputstyle distinct
+
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else{\tclose{\kbdfont\look}}\fi
+\else{\tclose{\kbdfont\look}}\fi}
+
+% For @indicateurl, @env, @command quotes seem unnecessary, so use \code.
+\let\indicateurl=\code
+\let\env=\code
+\let\command=\code
+
+% @uref (abbreviation for `urlref') takes an optional (comma-separated)
+% second argument specifying the text to display and an optional third
+% arg as text to display instead of (rather than in addition to) the url
+% itself.  First (mandatory) arg is the url.  Perhaps eventually put in
+% a hypertex \special here.
+%
+\def\uref#1{\douref #1,,,\finish}
+\def\douref#1,#2,#3,#4\finish{\begingroup
+  \unsepspaces
+  \pdfurl{#1}%
+  \setbox0 = \hbox{\ignorespaces #3}%
+  \ifdim\wd0 > 0pt
+    \unhbox0 % third arg given, show only that
+  \else
+    \setbox0 = \hbox{\ignorespaces #2}%
+    \ifdim\wd0 > 0pt
+      \ifpdf
+        \unhbox0             % PDF: 2nd arg given, show only it
+      \else
+        \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url
+      \fi
+    \else
+      \code{#1}% only url given, so show it
+    \fi
+  \fi
+  \endlink
+\endgroup}
+
+% @url synonym for @uref, since that's how everyone uses it.
+%
+\let\url=\uref
+
+% rms does not like angle brackets --karl, 17may97.
+% So now @email is just like @uref, unless we are pdf.
+%
+%\def\email#1{\angleleft{\tt #1}\angleright}
+\ifpdf
+  \def\email#1{\doemail#1,,\finish}
+  \def\doemail#1,#2,#3\finish{\begingroup
+    \unsepspaces
+    \pdfurl{mailto:#1}%
+    \setbox0 = \hbox{\ignorespaces #2}%
+    \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi
+    \endlink
+  \endgroup}
+\else
+  \let\email=\uref
+\fi
+
+% Check if we are currently using a typewriter font.  Since all the
+% Computer Modern typewriter fonts have zero interword stretch (and
+% shrink), and it is reasonable to expect all typewriter fonts to have
+% this property, we can check that font parameter.
+%
+\def\ifmonospace{\ifdim\fontdimen3\font=0pt }
+
+% Typeset a dimension, e.g., `in' or `pt'.  The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt.
+%
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+% @l was never documented to mean ``switch to the Lisp font'',
+% and it is not used as such in any manual I can find.  We need it for
+% Polish suppressed-l.  --karl, 22sep96.
+%\def\l#1{{\li #1}\null}
+
+% Explicit font changes: @r, @sc, undocumented @ii.
+\def\r#1{{\rm #1}}              % roman font
+\def\sc#1{{\smallcaps#1}}       % smallcaps font
+\def\ii#1{{\it #1}}             % italic font
+
+% @acronym for "FBI", "NATO", and the like.
+% We print this one point size smaller, since it's intended for
+% all-uppercase.
+% 
+\def\acronym#1{\doacronym #1,,\finish}
+\def\doacronym#1,#2,#3\finish{%
+  {\selectfonts\lsize #1}%
+  \def\temp{#2}%
+  \ifx\temp\empty \else
+    \space ({\unsepspaces \ignorespaces \temp \unskip})%
+  \fi
+}
+
+% @abbr for "Comput. J." and the like.
+% No font change, but don't do end-of-sentence spacing.
+% 
+\def\abbr#1{\doabbr #1,,\finish}
+\def\doabbr#1,#2,#3\finish{%
+  {\plainfrenchspacing #1}%
+  \def\temp{#2}%
+  \ifx\temp\empty \else
+    \space ({\unsepspaces \ignorespaces \temp \unskip})%
+  \fi
+}
+
+% @pounds{} is a sterling sign, which Knuth put in the CM italic font.
+%
+\def\pounds{{\it\$}}
+
+% @euro{} comes from a separate font, depending on the current style.
+% We use the free feym* fonts from the eurosym package by Henrik
+% Theiling, which support regular, slanted, bold and bold slanted (and
+% "outlined" (blackboard board, sort of) versions, which we don't need).
+% It is available from http://www.ctan.org/tex-archive/fonts/eurosym.
+% 
+% Although only regular is the truly official Euro symbol, we ignore
+% that.  The Euro is designed to be slightly taller than the regular
+% font height.
+% 
+% feymr - regular
+% feymo - slanted
+% feybr - bold
+% feybo - bold slanted
+% 
+% There is no good (free) typewriter version, to my knowledge.
+% A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide.
+% Hmm.
+% 
+% Also doesn't work in math.  Do we need to do math with euro symbols?
+% Hope not.
+% 
+% 
+\def\euro{{\eurofont e}}
+\def\eurofont{%
+  % We set the font at each command, rather than predefining it in
+  % \textfonts and the other font-switching commands, so that
+  % installations which never need the symbol don't have to have the
+  % font installed.
+  % 
+  % There is only one designed size (nominal 10pt), so we always scale
+  % that to the current nominal size.
+  % 
+  % By the way, simply using "at 1em" works for cmr10 and the like, but
+  % does not work for cmbx10 and other extended/shrunken fonts.
+  % 
+  \def\eurosize{\csname\curfontsize nominalsize\endcsname}%
+  %
+  \ifx\curfontstyle\bfstylename 
+    % bold:
+    \font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize
+  \else 
+    % regular:
+    \font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize
+  \fi
+  \thiseurofont
+}
+
+% Hacks for glyphs from the EC fonts similar to \euro.  We don't
+% use \let for the aliases, because sometimes we redefine the original
+% macro, and the alias should reflect the redefinition.
+\def\guillemetleft{{\ecfont \char"13}}
+\def\guillemotleft{\guillemetleft}
+\def\guillemetright{{\ecfont \char"14}}
+\def\guillemotright{\guillemetright}
+\def\guilsinglleft{{\ecfont \char"0E}}
+\def\guilsinglright{{\ecfont \char"0F}}
+\def\quotedblbase{{\ecfont \char"12}}
+\def\quotesinglbase{{\ecfont \char"0D}}
+%
+\def\ecfont{%
+  % We can't distinguish serif/sanserif and italic/slanted, but this
+  % is used for crude hacks anyway (like adding French and German
+  % quotes to documents typeset with CM, where we lose kerning), so
+  % hopefully nobody will notice/care.
+  \edef\ecsize{\csname\curfontsize ecsize\endcsname}%
+  \edef\nominalsize{\csname\curfontsize nominalsize\endcsname}%
+  \ifx\curfontstyle\bfstylename
+    % bold:
+    \font\thisecfont = ecb\ifusingit{i}{x}\ecsize \space at \nominalsize
+  \else
+    % regular:
+    \font\thisecfont = ec\ifusingit{ti}{rm}\ecsize \space at \nominalsize
+  \fi
+  \thisecfont
+}
+
+% @registeredsymbol - R in a circle.  The font for the R should really
+% be smaller yet, but lllsize is the best we can do for now.
+% Adapted from the plain.tex definition of \copyright.
+%
+\def\registeredsymbol{%
+  $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}%
+               \hfil\crcr\Orb}}%
+    }$%
+}
+
+% @textdegree - the normal degrees sign.
+%
+\def\textdegree{$^\circ$}
+
+% Laurent Siebenmann reports \Orb undefined with:
+%  Textures 1.7.7 (preloaded format=plain 93.10.14)  (68K)  16 APR 2004 02:38
+% so we'll define it if necessary.
+% 
+\ifx\Orb\undefined
+\def\Orb{\mathhexbox20D}
+\fi
+
+% Quotes.
+\chardef\quotedblleft="5C
+\chardef\quotedblright=`\"
+\chardef\quoteleft=`\`
+\chardef\quoteright=`\'
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page.  Must do @settitle before @titlepage.
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+% Do an implicit @contents or @shortcontents after @end titlepage if the
+% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage.
+%
+\newif\ifsetcontentsaftertitlepage
+ \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue
+\newif\ifsetshortcontentsaftertitlepage
+ \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue
+
+\parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+        \endgroup\page\hbox{}\page}
+
+\envdef\titlepage{%
+  % Open one extra group, as we want to close it in the middle of \Etitlepage.
+  \begingroup
+    \parindent=0pt \textfonts
+    % Leave some space at the very top of the page.
+    \vglue\titlepagetopglue
+    % No rule at page bottom unless we print one at the top with @title.
+    \finishedtitlepagetrue
+    %
+    % Most title ``pages'' are actually two pages long, with space
+    % at the top of the second.  We don't want the ragged left on the second.
+    \let\oldpage = \page
+    \def\page{%
+      \iffinishedtitlepage\else
+        \finishtitlepage
+      \fi
+      \let\page = \oldpage
+      \page
+      \null
+    }%
+}
+
+\def\Etitlepage{%
+    \iffinishedtitlepage\else
+       \finishtitlepage
+    \fi
+    % It is important to do the page break before ending the group,
+    % because the headline and footline are only empty inside the group.
+    % If we use the new definition of \page, we always get a blank page
+    % after the title page, which we certainly don't want.
+    \oldpage
+  \endgroup
+  %
+  % Need this before the \...aftertitlepage checks so that if they are
+  % in effect the toc pages will come out with page numbers.
+  \HEADINGSon
+  %
+  % If they want short, they certainly want long too.
+  \ifsetshortcontentsaftertitlepage
+    \shortcontents
+    \contents
+    \global\let\shortcontents = \relax
+    \global\let\contents = \relax
+  \fi
+  %
+  \ifsetcontentsaftertitlepage
+    \contents
+    \global\let\contents = \relax
+    \global\let\shortcontents = \relax
+  \fi
+}
+
+\def\finishtitlepage{%
+  \vskip4pt \hrule height 2pt width \hsize
+  \vskip\titlepagebottomglue
+  \finishedtitlepagetrue
+}
+
+%%% Macros to be used within @titlepage:
+
+\let\subtitlerm=\tenrm
+\def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}
+
+\def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines
+               \let\tt=\authortt}
+
+\parseargdef\title{%
+  \checkenv\titlepage
+  \leftline{\titlefonts\rm #1}
+  % print a rule at the page bottom also.
+  \finishedtitlepagefalse
+  \vskip4pt \hrule height 4pt width \hsize \vskip4pt
+}
+
+\parseargdef\subtitle{%
+  \checkenv\titlepage
+  {\subtitlefont \rightline{#1}}%
+}
+
+% @author should come last, but may come many times.
+% It can also be used inside @quotation.
+%
+\parseargdef\author{%
+  \def\temp{\quotation}%
+  \ifx\thisenv\temp
+    \def\quotationauthor{#1}% printed in \Equotation.
+  \else
+    \checkenv\titlepage
+    \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi
+    {\authorfont \leftline{#1}}%
+  \fi
+}
+
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks\evenheadline    % headline on even pages
+\newtoks\oddheadline     % headline on odd pages
+\newtoks\evenfootline    % footline on even pages
+\newtoks\oddfootline     % footline on odd pages
+
+% Now make TeX use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+                            \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+                            \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what  @headings on  does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish}
+\def\evenheadingyyy #1\|#2\|#3\|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish}
+\def\oddheadingyyy #1\|#2\|#3\|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}%
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish}
+\def\evenfootingyyy #1\|#2\|#3\|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish}
+\def\oddfootingyyy #1\|#2\|#3\|#4\finish{%
+  \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}%
+  %
+  % Leave some space for the footline.  Hopefully ok to assume
+  % @evenfooting will not be used by itself.
+  \global\advance\pageheight by -12pt
+  \global\advance\vsize by -12pt
+}
+
+\parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}}
+
+% @evenheadingmarks top     \thischapter <- chapter at the top of a page
+% @evenheadingmarks bottom  \thischapter <- chapter at the bottom of a page
+%
+% The same set of arguments for:
+%
+% @oddheadingmarks
+% @evenfootingmarks
+% @oddfootingmarks
+% @everyheadingmarks
+% @everyfootingmarks
+
+\def\evenheadingmarks{\headingmarks{even}{heading}}
+\def\oddheadingmarks{\headingmarks{odd}{heading}}
+\def\evenfootingmarks{\headingmarks{even}{footing}}
+\def\oddfootingmarks{\headingmarks{odd}{footing}}
+\def\everyheadingmarks#1 {\headingmarks{even}{heading}{#1}
+                          \headingmarks{odd}{heading}{#1} }
+\def\everyfootingmarks#1 {\headingmarks{even}{footing}{#1}
+                          \headingmarks{odd}{footing}{#1} }
+% #1 = even/odd, #2 = heading/footing, #3 = top/bottom.
+\def\headingmarks#1#2#3 {%
+  \expandafter\let\expandafter\temp \csname get#3headingmarks\endcsname
+  \global\expandafter\let\csname get#1#2marks\endcsname \temp
+}
+
+\everyheadingmarks bottom
+\everyfootingmarks bottom
+
+% @headings double      turns headings on for double-sided printing.
+% @headings single      turns headings on for single-sided printing.
+% @headings off         turns them off.
+% @headings on          same as @headings double, retained for compatibility.
+% @headings after       turns on double-sided headings after this page.
+% @headings doubleafter turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off at the start of a document,
+% and turned `on' after @end titlepage.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{%
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{%
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+\let\contentsalignmacro = \chappager
+
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{%
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+
+% Subroutines used in generating headings
+% This produces Day Month Year style of output.
+% Only define if not already defined, in case a txi-??.tex file has set
+% up a different format (e.g., txi-cs.tex does this).
+\ifx\today\undefined
+\def\today{%
+  \number\day\space
+  \ifcase\month
+  \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr
+  \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug
+  \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec
+  \fi
+  \space\number\year}
+\fi
+
+% @settitle line...  specifies the title of the document, for headings.
+% It generates no output of its own.
+\def\thistitle{\putwordNoTitle}
+\def\settitle{\parsearg{\gdef\thistitle}}
+
+
+\message{tables,}
+% Tables -- @table, @ftable, @vtable, @item(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent  \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin  \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table, @ftable, and @vtable define @item, @itemx, etc., with
+% these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\newif\ifitemxneedsnegativevskip
+
+\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi}
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\itemxpar \parsearg\itemzzz}
+
+\def\itemzzz #1{\begingroup %
+  \advance\hsize by -\rightskip
+  \advance\hsize by -\tableindent
+  \setbox0=\hbox{\itemindicate{#1}}%
+  \itemindex{#1}%
+  \nobreak % This prevents a break before @itemx.
+  %
+  % If the item text does not fit in the space we have, put it on a line
+  % by itself, and do not allow a page break either before or after that
+  % line.  We do not start a paragraph here because then if the next
+  % command is, e.g., @kindex, the whatsit would get put into the
+  % horizontal list on a line by itself, resulting in extra blank space.
+  \ifdim \wd0>\itemmax
+    %
+    % Make this a paragraph so we get the \parskip glue and wrapping,
+    % but leave it ragged-right.
+    \begingroup
+      \advance\leftskip by-\tableindent
+      \advance\hsize by\tableindent
+      \advance\rightskip by0pt plus1fil
+      \leavevmode\unhbox0\par
+    \endgroup
+    %
+    % We're going to be starting a paragraph, but we don't want the
+    % \parskip glue -- logically it's part of the @item we just started.
+    \nobreak \vskip-\parskip
+    %
+    % Stop a page break at the \parskip glue coming up.  However, if
+    % what follows is an environment such as @example, there will be no
+    % \parskip glue; then the negative vskip we just inserted would
+    % cause the example and the item to crash together.  So we use this
+    % bizarre value of 10001 as a signal to \aboveenvbreak to insert
+    % \parskip glue after all.  Section titles are handled this way also.
+    % 
+    \penalty 10001
+    \endgroup
+    \itemxneedsnegativevskipfalse
+  \else
+    % The item text fits into the space.  Start a paragraph, so that the
+    % following text (if any) will end up on the same line.
+    \noindent
+    % Do this with kerns and \unhbox so that if there is a footnote in
+    % the item text, it can migrate to the main vertical list and
+    % eventually be printed.
+    \nobreak\kern-\tableindent
+    \dimen0 = \itemmax  \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0
+    \unhbox0
+    \nobreak\kern\dimen0
+    \endgroup
+    \itemxneedsnegativevskiptrue
+  \fi
+}
+
+\def\item{\errmessage{@item while not in a list environment}}
+\def\itemx{\errmessage{@itemx while not in a list environment}}
+
+% @table, @ftable, @vtable.
+\envdef\table{%
+  \let\itemindex\gobble
+  \tablecheck{table}%
+}
+\envdef\ftable{%
+  \def\itemindex ##1{\doind {fn}{\code{##1}}}%
+  \tablecheck{ftable}%
+}
+\envdef\vtable{%
+  \def\itemindex ##1{\doind {vr}{\code{##1}}}%
+  \tablecheck{vtable}%
+}
+\def\tablecheck#1{%
+  \ifnum \the\catcode`\^^M=\active
+    \endgroup
+    \errmessage{This command won't work in this context; perhaps the problem is
+      that we are \inenvironment\thisenv}%
+    \def\next{\doignore{#1}}%
+  \else
+    \let\next\tablex
+  \fi
+  \next
+}
+\def\tablex#1{%
+  \def\itemindicate{#1}%
+  \parsearg\tabley
+}
+\def\tabley#1{%
+  {%
+    \makevalueexpandable
+    \edef\temp{\noexpand\tablez #1\space\space\space}%
+    \expandafter
+  }\temp \endtablez
+}
+\def\tablez #1 #2 #3 #4\endtablez{%
+  \aboveenvbreak
+  \ifnum 0#1>0 \advance \leftskip by #1\mil \fi
+  \ifnum 0#2>0 \tableindent=#2\mil \fi
+  \ifnum 0#3>0 \advance \rightskip by #3\mil \fi
+  \itemmax=\tableindent
+  \advance \itemmax by -\itemmargin
+  \advance \leftskip by \tableindent
+  \exdentamount=\tableindent
+  \parindent = 0pt
+  \parskip = \smallskipamount
+  \ifdim \parskip=0pt \parskip=2pt \fi
+  \let\item = \internalBitem
+  \let\itemx = \internalBitemx
+}
+\def\Etable{\endgraf\afterenvbreak}
+\let\Eftable\Etable
+\let\Evtable\Etable
+\let\Eitemize\Etable
+\let\Eenumerate\Etable
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\envdef\itemize{\parsearg\doitemize}
+
+\def\doitemize#1{%
+  \aboveenvbreak
+  \itemmax=\itemindent
+  \advance\itemmax by -\itemmargin
+  \advance\leftskip by \itemindent
+  \exdentamount=\itemindent
+  \parindent=0pt
+  \parskip=\smallskipamount
+  \ifdim\parskip=0pt \parskip=2pt \fi
+  \def\itemcontents{#1}%
+  % @itemize with no arg is equivalent to @itemize @bullet.
+  \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi
+  \let\item=\itemizeitem
+}
+
+% Definition of @item while inside @itemize and @enumerate.
+%
+\def\itemizeitem{%
+  \advance\itemno by 1  % for enumerations
+  {\let\par=\endgraf \smallbreak}% reasonable place to break
+  {%
+   % If the document has an @itemize directly after a section title, a
+   % \nobreak will be last on the list, and \sectionheading will have
+   % done a \vskip-\parskip.  In that case, we don't want to zero
+   % parskip, or the item text will crash with the heading.  On the
+   % other hand, when there is normal text preceding the item (as there
+   % usually is), we do want to zero parskip, or there would be too much
+   % space.  In that case, we won't have a \nobreak before.  At least
+   % that's the theory.
+   \ifnum\lastpenalty<10000 \parskip=0in \fi
+   \noindent
+   \hbox to 0pt{\hss \itemcontents \kern\itemmargin}%
+   \vadjust{\penalty 1200}}% not good to break after first line of item.
+  \flushcr
+}
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+%
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list.  No
+% argument is the same as `1'.
+%
+\envparseargdef\enumerate{\enumeratey #1  \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+  % If we were given no argument, pretend we were given `1'.
+  \def\thearg{#1}%
+  \ifx\thearg\empty \def\thearg{1}\fi
+  %
+  % Detect if the argument is a single token.  If so, it might be a
+  % letter.  Otherwise, the only valid thing it can be is a number.
+  % (We will always have one token, because of the test we just made.
+  % This is a good thing, since \splitoff doesn't work given nothing at
+  % all -- the first parameter is undelimited.)
+  \expandafter\splitoff\thearg\endmark
+  \ifx\rest\empty
+    % Only one token in the argument.  It could still be anything.
+    % A ``lowercase letter'' is one whose \lccode is nonzero.
+    % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+    %   not equal to itself.
+    % Otherwise, we assume it's a number.
+    %
+    % We need the \relax at the end of the \ifnum lines to stop TeX from
+    % continuing to look for a <number>.
+    %
+    \ifnum\lccode\expandafter`\thearg=0\relax
+      \numericenumerate % a number (we hope)
+    \else
+      % It's a letter.
+      \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+        \lowercaseenumerate % lowercase letter
+      \else
+        \uppercaseenumerate % uppercase letter
+      \fi
+    \fi
+  \else
+    % Multiple tokens in the argument.  We hope it's a number.
+    \numericenumerate
+  \fi
+}
+
+% An @enumerate whose labels are integers.  The starting integer is
+% given in \thearg.
+%
+\def\numericenumerate{%
+  \itemno = \thearg
+  \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+  \itemno = \expandafter`\thearg
+  \startenumeration{%
+    % Be sure we're not beyond the end of the alphabet.
+    \ifnum\itemno=0
+      \errmessage{No more lowercase letters in @enumerate; get a bigger
+                  alphabet}%
+    \fi
+    \char\lccode\itemno
+  }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+  \itemno = \expandafter`\thearg
+  \startenumeration{%
+    % Be sure we're not beyond the end of the alphabet.
+    \ifnum\itemno=0
+      \errmessage{No more uppercase letters in @enumerate; get a bigger
+                  alphabet}
+    \fi
+    \char\uccode\itemno
+  }%
+}
+
+% Call \doitemize, adding a period to the first argument and supplying the
+% common last two arguments.  Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+%
+\def\startenumeration#1{%
+  \advance\itemno by -1
+  \doitemize{#1.}\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+%
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+
+% @multitable macros
+% Amy Hendrickson, 8/18/94, 3/6/96
+%
+% @multitable ... @end multitable will make as many columns as desired.
+% Contents of each column will wrap at width given in preamble.  Width
+% can be specified either with sample text given in a template line,
+% or in percent of \hsize, the current width of text on page.
+
+% Table can continue over pages but will only break between lines.
+
+% To make preamble:
+%
+% Either define widths of columns in terms of percent of \hsize:
+%   @multitable @columnfractions .25 .3 .45
+%   @item ...
+%
+%   Numbers following @columnfractions are the percent of the total
+%   current hsize to be used for each column. You may use as many
+%   columns as desired.
+
+
+% Or use a template:
+%   @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+%   @item ...
+%   using the widest term desired in each column.
+
+% Each new table line starts with @item, each subsequent new column
+% starts with @tab. Empty columns may be produced by supplying @tab's
+% with nothing between them for as many times as empty columns are needed,
+% ie, @tab@tab@tab will produce two empty columns.
+
+% @item, @tab do not need to be on their own lines, but it will not hurt
+% if they are.
+
+% Sample multitable:
+
+%   @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+%   @item first col stuff @tab second col stuff @tab third col
+%   @item
+%   first col stuff
+%   @tab
+%   second col stuff
+%   @tab
+%   third col
+%   @item first col stuff @tab second col stuff
+%   @tab Many paragraphs of text may be used in any column.
+%
+%         They will wrap at the width determined by the template.
+%   @item@tab@tab This will be in third column.
+%   @end multitable
+
+% Default dimensions may be reset by user.
+% @multitableparskip is vertical space between paragraphs in table.
+% @multitableparindent is paragraph indent in table.
+% @multitablecolmargin is horizontal space to be left between columns.
+% @multitablelinespace is space to leave between table items, baseline
+%                                                            to baseline.
+%   0pt means it depends on current normal line spacing.
+%
+\newskip\multitableparskip
+\newskip\multitableparindent
+\newdimen\multitablecolspace
+\newskip\multitablelinespace
+\multitableparskip=0pt
+\multitableparindent=6pt
+\multitablecolspace=12pt
+\multitablelinespace=0pt
+
+% Macros used to set up halign preamble:
+%
+\let\endsetuptable\relax
+\def\xendsetuptable{\endsetuptable}
+\let\columnfractions\relax
+\def\xcolumnfractions{\columnfractions}
+\newif\ifsetpercent
+
+% #1 is the @columnfraction, usually a decimal number like .5, but might
+% be just 1.  We just use it, whatever it is.
+%
+\def\pickupwholefraction#1 {%
+  \global\advance\colcount by 1
+  \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}%
+  \setuptable
+}
+
+\newcount\colcount
+\def\setuptable#1{%
+  \def\firstarg{#1}%
+  \ifx\firstarg\xendsetuptable
+    \let\go = \relax
+  \else
+    \ifx\firstarg\xcolumnfractions
+      \global\setpercenttrue
+    \else
+      \ifsetpercent
+         \let\go\pickupwholefraction
+      \else
+         \global\advance\colcount by 1
+         \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a
+                   % separator; typically that is always in the input, anyway.
+         \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}%
+      \fi
+    \fi
+    \ifx\go\pickupwholefraction
+      % Put the argument back for the \pickupwholefraction call, so
+      % we'll always have a period there to be parsed.
+      \def\go{\pickupwholefraction#1}%
+    \else
+      \let\go = \setuptable
+    \fi%
+  \fi
+  \go
+}
+
+% multitable-only commands.
+%
+% @headitem starts a heading row, which we typeset in bold.
+% Assignments have to be global since we are inside the implicit group
+% of an alignment entry.  Note that \everycr resets \everytab.
+\def\headitem{\checkenv\multitable \crcr \global\everytab={\bf}\the\everytab}%
+%
+% A \tab used to include \hskip1sp.  But then the space in a template
+% line is not enough.  That is bad.  So let's go back to just `&' until
+% we encounter the problem it was intended to solve again.
+%                                      --karl, nathan@acm.org, 20apr99.
+\def\tab{\checkenv\multitable &\the\everytab}%
+
+% @multitable ... @end multitable definitions:
+%
+\newtoks\everytab  % insert after every tab.
+%
+\envdef\multitable{%
+  \vskip\parskip
+  \startsavinginserts
+  %
+  % @item within a multitable starts a normal row.
+  % We use \def instead of \let so that if one of the multitable entries
+  % contains an @itemize, we don't choke on the \item (seen as \crcr aka
+  % \endtemplate) expanding \doitemize.
+  \def\item{\crcr}%
+  %
+  \tolerance=9500
+  \hbadness=9500
+  \setmultitablespacing
+  \parskip=\multitableparskip
+  \parindent=\multitableparindent
+  \overfullrule=0pt
+  \global\colcount=0
+  %
+  \everycr = {%
+    \noalign{%
+      \global\everytab={}%
+      \global\colcount=0 % Reset the column counter.
+      % Check for saved footnotes, etc.
+      \checkinserts
+      % Keeps underfull box messages off when table breaks over pages.
+      %\filbreak
+       % Maybe so, but it also creates really weird page breaks when the
+       % table breaks over pages. Wouldn't \vfil be better?  Wait until the
+       % problem manifests itself, so it can be fixed for real --karl.
+    }%
+  }%
+  %
+  \parsearg\domultitable
+}
+\def\domultitable#1{%
+  % To parse everything between @multitable and @item:
+  \setuptable#1 \endsetuptable
+  %
+  % This preamble sets up a generic column definition, which will
+  % be used as many times as user calls for columns.
+  % \vtop will set a single line and will also let text wrap and
+  % continue for many paragraphs if desired.
+  \halign\bgroup &%
+    \global\advance\colcount by 1
+    \multistrut
+    \vtop{%
+      % Use the current \colcount to find the correct column width:
+      \hsize=\expandafter\csname col\the\colcount\endcsname
+      %
+      % In order to keep entries from bumping into each other
+      % we will add a \leftskip of \multitablecolspace to all columns after
+      % the first one.
+      %
+      % If a template has been used, we will add \multitablecolspace
+      % to the width of each template entry.
+      %
+      % If the user has set preamble in terms of percent of \hsize we will
+      % use that dimension as the width of the column, and the \leftskip
+      % will keep entries from bumping into each other.  Table will start at
+      % left margin and final column will justify at right margin.
+      %
+      % Make sure we don't inherit \rightskip from the outer environment.
+      \rightskip=0pt
+      \ifnum\colcount=1
+       % The first column will be indented with the surrounding text.
+       \advance\hsize by\leftskip
+      \else
+       \ifsetpercent \else
+         % If user has not set preamble in terms of percent of \hsize
+         % we will advance \hsize by \multitablecolspace.
+         \advance\hsize by \multitablecolspace
+       \fi
+       % In either case we will make \leftskip=\multitablecolspace:
+      \leftskip=\multitablecolspace
+      \fi
+      % Ignoring space at the beginning and end avoids an occasional spurious
+      % blank line, when TeX decides to break the line at the space before the
+      % box from the multistrut, so the strut ends up on a line by itself.
+      % For example:
+      % @multitable @columnfractions .11 .89
+      % @item @code{#}
+      % @tab Legal holiday which is valid in major parts of the whole country.
+      % Is automatically provided with highlighting sequences respectively
+      % marking characters.
+      \noindent\ignorespaces##\unskip\multistrut
+    }\cr
+}
+\def\Emultitable{%
+  \crcr
+  \egroup % end the \halign
+  \global\setpercentfalse
+}
+
+\def\setmultitablespacing{%
+  \def\multistrut{\strut}% just use the standard line spacing
+  %
+  % Compute \multitablelinespace (if not defined by user) for use in
+  % \multitableparskip calculation.  We used define \multistrut based on
+  % this, but (ironically) that caused the spacing to be off.
+  % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100.
+\ifdim\multitablelinespace=0pt
+\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip
+\global\advance\multitablelinespace by-\ht0
+\fi
+%% Test to see if parskip is larger than space between lines of
+%% table. If not, do nothing.
+%%        If so, set to same dimension as multitablelinespace.
+\ifdim\multitableparskip>\multitablelinespace
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+                                      %% than skip between lines in the table.
+\fi%
+\ifdim\multitableparskip=0pt
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+                                      %% than skip between lines in the table.
+\fi}
+
+
+\message{conditionals,}
+
+% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext,
+% @ifnotxml always succeed.  They currently do nothing; we don't
+% attempt to check whether the conditionals are properly nested.  But we
+% have to remember that they are conditionals, so that @end doesn't
+% attempt to close an environment group.
+%
+\def\makecond#1{%
+  \expandafter\let\csname #1\endcsname = \relax
+  \expandafter\let\csname iscond.#1\endcsname = 1
+}
+\makecond{iftex}
+\makecond{ifnotdocbook}
+\makecond{ifnothtml}
+\makecond{ifnotinfo}
+\makecond{ifnotplaintext}
+\makecond{ifnotxml}
+
+% Ignore @ignore, @ifhtml, @ifinfo, and the like.
+%
+\def\direntry{\doignore{direntry}}
+\def\documentdescription{\doignore{documentdescription}}
+\def\docbook{\doignore{docbook}}
+\def\html{\doignore{html}}
+\def\ifdocbook{\doignore{ifdocbook}}
+\def\ifhtml{\doignore{ifhtml}}
+\def\ifinfo{\doignore{ifinfo}}
+\def\ifnottex{\doignore{ifnottex}}
+\def\ifplaintext{\doignore{ifplaintext}}
+\def\ifxml{\doignore{ifxml}}
+\def\ignore{\doignore{ignore}}
+\def\menu{\doignore{menu}}
+\def\xml{\doignore{xml}}
+
+% Ignore text until a line `@end #1', keeping track of nested conditionals.
+%
+% A count to remember the depth of nesting.
+\newcount\doignorecount
+
+\def\doignore#1{\begingroup
+  % Scan in ``verbatim'' mode:
+  \obeylines
+  \catcode`\@ = \other
+  \catcode`\{ = \other
+  \catcode`\} = \other
+  %
+  % Make sure that spaces turn into tokens that match what \doignoretext wants.
+  \spaceisspace
+  %
+  % Count number of #1's that we've seen.
+  \doignorecount = 0
+  %
+  % Swallow text until we reach the matching `@end #1'.
+  \dodoignore{#1}%
+}
+
+{ \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source.
+  \obeylines %
+  %
+  \gdef\dodoignore#1{%
+    % #1 contains the command name as a string, e.g., `ifinfo'.
+    %
+    % Define a command to find the next `@end #1'.
+    \long\def\doignoretext##1^^M@end #1{%
+      \doignoretextyyy##1^^M@#1\_STOP_}%
+    %
+    % And this command to find another #1 command, at the beginning of a
+    % line.  (Otherwise, we would consider a line `@c @ifset', for
+    % example, to count as an @ifset for nesting.)
+    \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}%
+    %
+    % And now expand that command.
+    \doignoretext ^^M%
+  }%
+}
+
+\def\doignoreyyy#1{%
+  \def\temp{#1}%
+  \ifx\temp\empty                      % Nothing found.
+    \let\next\doignoretextzzz
+  \else                                        % Found a nested condition, ...
+    \advance\doignorecount by 1
+    \let\next\doignoretextyyy          % ..., look for another.
+    % If we're here, #1 ends with ^^M\ifinfo (for example).
+  \fi
+  \next #1% the token \_STOP_ is present just after this macro.
+}
+
+% We have to swallow the remaining "\_STOP_".
+%
+\def\doignoretextzzz#1{%
+  \ifnum\doignorecount = 0     % We have just found the outermost @end.
+    \let\next\enddoignore
+  \else                                % Still inside a nested condition.
+    \advance\doignorecount by -1
+    \let\next\doignoretext      % Look for the next @end.
+  \fi
+  \next
+}
+
+% Finish off ignored text.
+{ \obeylines%
+  % Ignore anything after the last `@end #1'; this matters in verbatim
+  % environments, where otherwise the newline after an ignored conditional
+  % would result in a blank line in the output.
+  \gdef\enddoignore#1^^M{\endgroup\ignorespaces}%
+}
+
+
+% @set VAR sets the variable VAR to an empty value.
+% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+%
+% Since we want to separate VAR from REST-OF-LINE (which might be
+% empty), we can't just use \parsearg; we have to insert a space of our
+% own to delimit the rest of the line, and then take it out again if we
+% didn't need it.
+% We rely on the fact that \parsearg sets \catcode`\ =10.
+%
+\parseargdef\set{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+  {%
+    \makevalueexpandable
+    \def\temp{#2}%
+    \edef\next{\gdef\makecsname{SET#1}}%
+    \ifx\temp\empty
+      \next{}%
+    \else
+      \setzzz#2\endsetzzz
+    \fi
+  }%
+}
+% Remove the trailing space \setxxx inserted.
+\def\setzzz#1 \endsetzzz{\next{#1}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\parseargdef\clear{%
+  {%
+    \makevalueexpandable
+    \global\expandafter\let\csname SET#1\endcsname=\relax
+  }%
+}
+
+% @value{foo} gets the text saved in variable foo.
+\def\value{\begingroup\makevalueexpandable\valuexxx}
+\def\valuexxx#1{\expandablevalue{#1}\endgroup}
+{
+  \catcode`\- = \active \catcode`\_ = \active
+  %
+  \gdef\makevalueexpandable{%
+    \let\value = \expandablevalue
+    % We don't want these characters active, ...
+    \catcode`\-=\other \catcode`\_=\other
+    % ..., but we might end up with active ones in the argument if
+    % we're called from @code, as @code{@value{foo-bar_}}, though.
+    % So \let them to their normal equivalents.
+    \let-\realdash \let_\normalunderscore
+  }
+}
+
+% We have this subroutine so that we can handle at least some @value's
+% properly in indexes (we call \makevalueexpandable in \indexdummies).
+% The command has to be fully expandable (if the variable is set), since
+% the result winds up in the index file.  This means that if the
+% variable's value contains other Texinfo commands, it's almost certain
+% it will fail (although perhaps we could fix that with sufficient work
+% to do a one-level expansion on the result, instead of complete).
+%
+\def\expandablevalue#1{%
+  \expandafter\ifx\csname SET#1\endcsname\relax
+    {[No value for ``#1'']}%
+    \message{Variable `#1', used in @value, is not set.}%
+  \else
+    \csname SET#1\endcsname
+  \fi
+}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+% To get special treatment of `@end ifset,' call \makeond and the redefine.
+%
+\makecond{ifset}
+\def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}}
+\def\doifset#1#2{%
+  {%
+    \makevalueexpandable
+    \let\next=\empty
+    \expandafter\ifx\csname SET#2\endcsname\relax
+      #1% If not set, redefine \next.
+    \fi
+    \expandafter
+  }\next
+}
+\def\ifsetfail{\doignore{ifset}}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+% The `\else' inside the `\doifset' parameter is a trick to reuse the
+% above code: if the variable is not set, do nothing, if it is set,
+% then redefine \next to \ifclearfail.
+%
+\makecond{ifclear}
+\def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}}
+\def\ifclearfail{\doignore{ifclear}}
+
+% @dircategory CATEGORY  -- specify a category of the dir file
+% which this file should belong to.  Ignore this in TeX.
+\let\dircategory=\comment
+
+% @defininfoenclose.
+\let\definfoenclose=\comment
+
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within macros and \if's.
+\edef\newwrite{\makecsname{ptexnewwrite}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index.  The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+%
+\def\newindex#1{%
+  \iflinks
+    \expandafter\newwrite \csname#1indfile\endcsname
+    \openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+  \fi
+  \expandafter\xdef\csname#1index\endcsname{%     % Define @#1index
+    \noexpand\doindex{#1}}
+}
+
+% @defindex foo  ==  \newindex{foo}
+%
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+%
+\def\defcodeindex{\parsearg\newcodeindex}
+%
+\def\newcodeindex#1{%
+  \iflinks
+    \expandafter\newwrite \csname#1indfile\endcsname
+    \openout \csname#1indfile\endcsname \jobname.#1
+  \fi
+  \expandafter\xdef\csname#1index\endcsname{%
+    \noexpand\docodeindex{#1}}%
+}
+
+
+% @synindex foo bar    makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+%
+% @syncodeindex foo bar   similar, but put all entries made for index foo
+% inside @code.
+%
+\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}}
+\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}}
+
+% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo),
+% #3 the target index (bar).
+\def\dosynindex#1#2#3{%
+  % Only do \closeout if we haven't already done it, else we'll end up
+  % closing the target index.
+  \expandafter \ifx\csname donesynindex#2\endcsname \undefined
+    % The \closeout helps reduce unnecessary open files; the limit on the
+    % Acorn RISC OS is a mere 16 files.
+    \expandafter\closeout\csname#2indfile\endcsname
+    \expandafter\let\csname\donesynindex#2\endcsname = 1
+  \fi
+  % redefine \fooindfile:
+  \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname
+  \expandafter\let\csname#2indfile\endcsname=\temp
+  % redefine \fooindex:
+  \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+%  and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+% Take care of Texinfo commands that can appear in an index entry.
+% Since there are some commands we want to expand, and others we don't,
+% we have to laboriously prevent expansion for those that we don't.
+%
+\def\indexdummies{%
+  \escapechar = `\\     % use backslash in output files.
+  \def\@{@}% change to @@ when we switch to @ as escape char in index files.
+  \def\ {\realbackslash\space }%
+  %
+  % Need these in case \tex is in effect and \{ is a \delimiter again.
+  % But can't use \lbracecmd and \rbracecmd because texindex assumes
+  % braces and backslashes are used only as delimiters.
+  \let\{ = \mylbrace
+  \let\} = \myrbrace
+  %
+  % I don't entirely understand this, but when an index entry is
+  % generated from a macro call, the \endinput which \scanmacro inserts
+  % causes processing to be prematurely terminated.  This is,
+  % apparently, because \indexsorttmp is fully expanded, and \endinput
+  % is an expandable command.  The redefinition below makes \endinput
+  % disappear altogether for that purpose -- although logging shows that
+  % processing continues to some further point.  On the other hand, it
+  % seems \endinput does not hurt in the printed index arg, since that
+  % is still getting written without apparent harm.
+  % 
+  % Sample source (mac-idx3.tex, reported by Graham Percival to
+  % help-texinfo, 22may06):
+  % @macro funindex {WORD}
+  % @findex xyz
+  % @end macro
+  % ...
+  % @funindex commtest
+  % 
+  % The above is not enough to reproduce the bug, but it gives the flavor.
+  % 
+  % Sample whatsit resulting:
+  % .@write3{\entry{xyz}{@folio }{@code {xyz@endinput }}}
+  % 
+  % So:
+  \let\endinput = \empty
+  %
+  % Do the redefinitions.
+  \commondummies
+}
+
+% For the aux and toc files, @ is the escape character.  So we want to
+% redefine everything using @ as the escape character (instead of
+% \realbackslash, still used for index files).  When everything uses @,
+% this will be simpler.
+%
+\def\atdummies{%
+  \def\@{@@}%
+  \def\ {@ }%
+  \let\{ = \lbraceatcmd
+  \let\} = \rbraceatcmd
+  %
+  % Do the redefinitions.
+  \commondummies
+  \otherbackslash
+}
+
+% Called from \indexdummies and \atdummies.
+%
+\def\commondummies{%
+  %
+  % \definedummyword defines \#1 as \string\#1\space, thus effectively
+  % preventing its expansion.  This is used only for control% words,
+  % not control letters, because the \space would be incorrect for
+  % control characters, but is needed to separate the control word
+  % from whatever follows.
+  %
+  % For control letters, we have \definedummyletter, which omits the
+  % space.
+  %
+  % These can be used both for control words that take an argument and
+  % those that do not.  If it is followed by {arg} in the input, then
+  % that will dutifully get written to the index (or wherever).
+  %
+  \def\definedummyword  ##1{\def##1{\string##1\space}}%
+  \def\definedummyletter##1{\def##1{\string##1}}%
+  \let\definedummyaccent\definedummyletter
+  %
+  \commondummiesnofonts
+  %
+  \definedummyletter\_%
+  %
+  % Non-English letters.
+  \definedummyword\AA
+  \definedummyword\AE
+  \definedummyword\L
+  \definedummyword\OE
+  \definedummyword\O
+  \definedummyword\aa
+  \definedummyword\ae
+  \definedummyword\l
+  \definedummyword\oe
+  \definedummyword\o
+  \definedummyword\ss
+  \definedummyword\exclamdown
+  \definedummyword\questiondown
+  \definedummyword\ordf
+  \definedummyword\ordm
+  %
+  % Although these internal commands shouldn't show up, sometimes they do.
+  \definedummyword\bf
+  \definedummyword\gtr
+  \definedummyword\hat
+  \definedummyword\less
+  \definedummyword\sf
+  \definedummyword\sl
+  \definedummyword\tclose
+  \definedummyword\tt
+  %
+  \definedummyword\LaTeX
+  \definedummyword\TeX
+  %
+  % Assorted special characters.
+  \definedummyword\bullet
+  \definedummyword\comma
+  \definedummyword\copyright
+  \definedummyword\registeredsymbol
+  \definedummyword\dots
+  \definedummyword\enddots
+  \definedummyword\equiv
+  \definedummyword\error
+  \definedummyword\euro
+  \definedummyword\guillemetleft
+  \definedummyword\guillemetright
+  \definedummyword\guilsinglleft
+  \definedummyword\guilsinglright
+  \definedummyword\expansion
+  \definedummyword\minus
+  \definedummyword\pounds
+  \definedummyword\point
+  \definedummyword\print
+  \definedummyword\quotedblbase
+  \definedummyword\quotedblleft
+  \definedummyword\quotedblright
+  \definedummyword\quoteleft
+  \definedummyword\quoteright
+  \definedummyword\quotesinglbase
+  \definedummyword\result
+  \definedummyword\textdegree
+  %
+  % We want to disable all macros so that they are not expanded by \write.
+  \macrolist
+  %
+  \normalturnoffactive
+  %
+  % Handle some cases of @value -- where it does not contain any
+  % (non-fully-expandable) commands.
+  \makevalueexpandable
+}
+
+% \commondummiesnofonts: common to \commondummies and \indexnofonts.
+%
+\def\commondummiesnofonts{%
+  % Control letters and accents.
+  \definedummyletter\!%
+  \definedummyaccent\"%
+  \definedummyaccent\'%
+  \definedummyletter\*%
+  \definedummyaccent\,%
+  \definedummyletter\.%
+  \definedummyletter\/%
+  \definedummyletter\:%
+  \definedummyaccent\=%
+  \definedummyletter\?%
+  \definedummyaccent\^%
+  \definedummyaccent\`%
+  \definedummyaccent\~%
+  \definedummyword\u
+  \definedummyword\v
+  \definedummyword\H
+  \definedummyword\dotaccent
+  \definedummyword\ringaccent
+  \definedummyword\tieaccent
+  \definedummyword\ubaraccent
+  \definedummyword\udotaccent
+  \definedummyword\dotless
+  %
+  % Texinfo font commands.
+  \definedummyword\b
+  \definedummyword\i
+  \definedummyword\r
+  \definedummyword\sc
+  \definedummyword\t
+  %
+  % Commands that take arguments.
+  \definedummyword\acronym
+  \definedummyword\cite
+  \definedummyword\code
+  \definedummyword\command
+  \definedummyword\dfn
+  \definedummyword\emph
+  \definedummyword\env
+  \definedummyword\file
+  \definedummyword\kbd
+  \definedummyword\key
+  \definedummyword\math
+  \definedummyword\option
+  \definedummyword\pxref
+  \definedummyword\ref
+  \definedummyword\samp
+  \definedummyword\strong
+  \definedummyword\tie
+  \definedummyword\uref
+  \definedummyword\url
+  \definedummyword\var
+  \definedummyword\verb
+  \definedummyword\w
+  \definedummyword\xref
+}
+
+% \indexnofonts is used when outputting the strings to sort the index
+% by, and when constructing control sequence names.  It eliminates all
+% control sequences and just writes whatever the best ASCII sort string
+% would be for a given command (usually its argument).
+%
+\def\indexnofonts{%
+  % Accent commands should become @asis.
+  \def\definedummyaccent##1{\let##1\asis}%
+  % We can just ignore other control letters.
+  \def\definedummyletter##1{\let##1\empty}%
+  % Hopefully, all control words can become @asis.
+  \let\definedummyword\definedummyaccent
+  %
+  \commondummiesnofonts
+  %
+  % Don't no-op \tt, since it isn't a user-level command
+  % and is used in the definitions of the active chars like <, >, |, etc.
+  % Likewise with the other plain tex font commands.
+  %\let\tt=\asis
+  %
+  \def\ { }%
+  \def\@{@}%
+  % how to handle braces?
+  \def\_{\normalunderscore}%
+  %
+  % Non-English letters.
+  \def\AA{AA}%
+  \def\AE{AE}%
+  \def\L{L}%
+  \def\OE{OE}%
+  \def\O{O}%
+  \def\aa{aa}%
+  \def\ae{ae}%
+  \def\l{l}%
+  \def\oe{oe}%
+  \def\o{o}%
+  \def\ss{ss}%
+  \def\exclamdown{!}%
+  \def\questiondown{?}%
+  \def\ordf{a}%
+  \def\ordm{o}%
+  %
+  \def\LaTeX{LaTeX}%
+  \def\TeX{TeX}%
+  %
+  % Assorted special characters.
+  % (The following {} will end up in the sort string, but that's ok.)
+  \def\bullet{bullet}%
+  \def\comma{,}%
+  \def\copyright{copyright}%
+  \def\registeredsymbol{R}%
+  \def\dots{...}%
+  \def\enddots{...}%
+  \def\equiv{==}%
+  \def\error{error}%
+  \def\euro{euro}%
+  \def\guillemetleft{<<}%
+  \def\guillemetright{>>}%
+  \def\guilsinglleft{<}%
+  \def\guilsinglright{>}%
+  \def\expansion{==>}%
+  \def\minus{-}%
+  \def\pounds{pounds}%
+  \def\point{.}%
+  \def\print{-|}%
+  \def\quotedblbase{"}%
+  \def\quotedblleft{"}%
+  \def\quotedblright{"}%
+  \def\quoteleft{`}%
+  \def\quoteright{'}%
+  \def\quotesinglbase{,}%
+  \def\result{=>}%
+  \def\textdegree{degrees}%
+  %
+  % We need to get rid of all macros, leaving only the arguments (if present).
+  % Of course this is not nearly correct, but it is the best we can do for now.
+  % makeinfo does not expand macros in the argument to @deffn, which ends up
+  % writing an index entry, and texindex isn't prepared for an index sort entry
+  % that starts with \.
+  % 
+  % Since macro invocations are followed by braces, we can just redefine them
+  % to take a single TeX argument.  The case of a macro invocation that
+  % goes to end-of-line is not handled.
+  % 
+  \macrolist
+}
+
+\let\indexbackslash=0  %overridden during \printindex.
+\let\SETmarginindex=\relax % put index entries in margin (undocumented)?
+
+% Most index entries go through here, but \dosubind is the general case.
+% #1 is the index name, #2 is the entry text.
+\def\doind#1#2{\dosubind{#1}{#2}{}}
+
+% Workhorse for all \fooindexes.
+% #1 is name of index, #2 is stuff to put there, #3 is subentry --
+% empty if called from \doind, as we usually are (the main exception
+% is with most defuns, which call us directly).
+%
+\def\dosubind#1#2#3{%
+  \iflinks
+  {%
+    % Store the main index entry text (including the third arg).
+    \toks0 = {#2}%
+    % If third arg is present, precede it with a space.
+    \def\thirdarg{#3}%
+    \ifx\thirdarg\empty \else
+      \toks0 = \expandafter{\the\toks0 \space #3}%
+    \fi
+    %
+    \edef\writeto{\csname#1indfile\endcsname}%
+    %
+    \safewhatsit\dosubindwrite
+  }%
+  \fi
+}
+
+% Write the entry in \toks0 to the index file:
+%
+\def\dosubindwrite{%
+  % Put the index entry in the margin if desired.
+  \ifx\SETmarginindex\relax\else
+    \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}%
+  \fi
+  %
+  % Remember, we are within a group.
+  \indexdummies % Must do this here, since \bf, etc expand at this stage
+  \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now
+      % so it will be output as is; and it will print as backslash.
+  %
+  % Process the index entry with all font commands turned off, to
+  % get the string to sort by.
+  {\indexnofonts
+   \edef\temp{\the\toks0}% need full expansion
+   \xdef\indexsorttmp{\temp}%
+  }%
+  %
+  % Set up the complete index entry, with both the sort key and
+  % the original text, including any font commands.  We write
+  % three arguments to \entry to the .?? file (four in the
+  % subentry case), texindex reduces to two when writing the .??s
+  % sorted result.
+  \edef\temp{%
+    \write\writeto{%
+      \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}%
+  }%
+  \temp
+}
+
+% Take care of unwanted page breaks/skips around a whatsit:
+%
+% If a skip is the last thing on the list now, preserve it
+% by backing up by \lastskip, doing the \write, then inserting
+% the skip again.  Otherwise, the whatsit generated by the
+% \write or \pdfdest will make \lastskip zero.  The result is that
+% sequences like this:
+% @end defun
+% @tindex whatever
+% @defun ...
+% will have extra space inserted, because the \medbreak in the
+% start of the @defun won't see the skip inserted by the @end of
+% the previous defun.
+%
+% But don't do any of this if we're not in vertical mode.  We
+% don't want to do a \vskip and prematurely end a paragraph.
+%
+% Avoid page breaks due to these extra skips, too.
+%
+% But wait, there is a catch there:
+% We'll have to check whether \lastskip is zero skip.  \ifdim is not
+% sufficient for this purpose, as it ignores stretch and shrink parts
+% of the skip.  The only way seems to be to check the textual
+% representation of the skip.
+%
+% The following is almost like \def\zeroskipmacro{0.0pt} except that
+% the ``p'' and ``t'' characters have catcode \other, not 11 (letter).
+%
+\edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname}
+%
+\newskip\whatsitskip
+\newcount\whatsitpenalty
+%
+% ..., ready, GO:
+%
+\def\safewhatsit#1{%
+\ifhmode
+  #1%
+\else
+  % \lastskip and \lastpenalty cannot both be nonzero simultaneously.
+  \whatsitskip = \lastskip
+  \edef\lastskipmacro{\the\lastskip}%
+  \whatsitpenalty = \lastpenalty
+  %
+  % If \lastskip is nonzero, that means the last item was a
+  % skip.  And since a skip is discardable, that means this
+  % -\whatsitskip glue we're inserting is preceded by a
+  % non-discardable item, therefore it is not a potential
+  % breakpoint, therefore no \nobreak needed.
+  \ifx\lastskipmacro\zeroskipmacro
+  \else
+    \vskip-\whatsitskip
+  \fi
+  %
+  #1%
+  %
+  \ifx\lastskipmacro\zeroskipmacro
+    % If \lastskip was zero, perhaps the last item was a penalty, and
+    % perhaps it was >=10000, e.g., a \nobreak.  In that case, we want
+    % to re-insert the same penalty (values >10000 are used for various
+    % signals); since we just inserted a non-discardable item, any
+    % following glue (such as a \parskip) would be a breakpoint.  For example:
+    % 
+    %   @deffn deffn-whatever
+    %   @vindex index-whatever
+    %   Description.
+    % would allow a break between the index-whatever whatsit
+    % and the "Description." paragraph.
+    \ifnum\whatsitpenalty>9999 \penalty\whatsitpenalty \fi
+  \else
+    % On the other hand, if we had a nonzero \lastskip,
+    % this make-up glue would be preceded by a non-discardable item
+    % (the whatsit from the \write), so we must insert a \nobreak.
+    \nobreak\vskip\whatsitskip
+  \fi
+\fi
+}
+
+% The index entry written in the file actually looks like
+%  \entry {sortstring}{page}{topic}
+% or
+%  \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+%  \initial {c}
+%     before the first topic whose initial is c
+%  \entry {topic}{pagelist}
+%     for a topic that is used without subtopics
+%  \primary {topic}
+%     for the beginning of a topic that is used with subtopics
+%  \secondary {subtopic}{pagelist}
+%     for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% @printindex causes a particular index (the ??s file) to get printed.
+% It does not print any chapter heading (usually an @unnumbered).
+%
+\parseargdef\printindex{\begingroup
+  \dobreak \chapheadingskip{10000}%
+  %
+  \smallfonts \rm
+  \tolerance = 9500
+  \plainfrenchspacing
+  \everypar = {}% don't want the \kern\-parindent from indentation suppression.
+  %
+  % See if the index file exists and is nonempty.
+  % Change catcode of @ here so that if the index file contains
+  % \initial {@}
+  % as its first line, TeX doesn't complain about mismatched braces
+  % (because it thinks @} is a control sequence).
+  \catcode`\@ = 11
+  \openin 1 \jobname.#1s
+  \ifeof 1
+    % \enddoublecolumns gets confused if there is no text in the index,
+    % and it loses the chapter title and the aux file entries for the
+    % index.  The easiest way to prevent this problem is to make sure
+    % there is some text.
+    \putwordIndexNonexistent
+  \else
+    %
+    % If the index file exists but is empty, then \openin leaves \ifeof
+    % false.  We have to make TeX try to read something from the file, so
+    % it can discover if there is anything in it.
+    \read 1 to \temp
+    \ifeof 1
+      \putwordIndexIsEmpty
+    \else
+      % Index files are almost Texinfo source, but we use \ as the escape
+      % character.  It would be better to use @, but that's too big a change
+      % to make right now.
+      \def\indexbackslash{\backslashcurfont}%
+      \catcode`\\ = 0
+      \escapechar = `\\
+      \begindoublecolumns
+      \input \jobname.#1s
+      \enddoublecolumns
+    \fi
+  \fi
+  \closein 1
+\endgroup}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+\def\initial#1{{%
+  % Some minor font changes for the special characters.
+  \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+  %
+  % Remove any glue we may have, we'll be inserting our own.
+  \removelastskip
+  %
+  % We like breaks before the index initials, so insert a bonus.
+  \nobreak
+  \vskip 0pt plus 3\baselineskip
+  \penalty 0
+  \vskip 0pt plus -3\baselineskip
+  %
+  % Typeset the initial.  Making this add up to a whole number of
+  % baselineskips increases the chance of the dots lining up from column
+  % to column.  It still won't often be perfect, because of the stretch
+  % we need before each entry, but it's better.
+  %
+  % No shrink because it confuses \balancecolumns.
+  \vskip 1.67\baselineskip plus .5\baselineskip
+  \leftline{\secbf #1}%
+  % Do our best not to break after the initial.
+  \nobreak
+  \vskip .33\baselineskip plus .1\baselineskip
+}}
+
+% \entry typesets a paragraph consisting of the text (#1), dot leaders, and
+% then page number (#2) flushed to the right margin.  It is used for index
+% and table of contents entries.  The paragraph is indented by \leftskip.
+%
+% A straightforward implementation would start like this:
+%      \def\entry#1#2{...
+% But this frozes the catcodes in the argument, and can cause problems to
+% @code, which sets - active.  This problem was fixed by a kludge---
+% ``-'' was active throughout whole index, but this isn't really right.
+%
+% The right solution is to prevent \entry from swallowing the whole text.
+%                                 --kasal, 21nov03
+\def\entry{%
+  \begingroup
+    %
+    % Start a new paragraph if necessary, so our assignments below can't
+    % affect previous text.
+    \par
+    %
+    % Do not fill out the last line with white space.
+    \parfillskip = 0in
+    %
+    % No extra space above this paragraph.
+    \parskip = 0in
+    %
+    % Do not prefer a separate line ending with a hyphen to fewer lines.
+    \finalhyphendemerits = 0
+    %
+    % \hangindent is only relevant when the entry text and page number
+    % don't both fit on one line.  In that case, bob suggests starting the
+    % dots pretty far over on the line.  Unfortunately, a large
+    % indentation looks wrong when the entry text itself is broken across
+    % lines.  So we use a small indentation and put up with long leaders.
+    %
+    % \hangafter is reset to 1 (which is the value we want) at the start
+    % of each paragraph, so we need not do anything with that.
+    \hangindent = 2em
+    %
+    % When the entry text needs to be broken, just fill out the first line
+    % with blank space.
+    \rightskip = 0pt plus1fil
+    %
+    % A bit of stretch before each entry for the benefit of balancing
+    % columns.
+    \vskip 0pt plus1pt
+    %
+    % Swallow the left brace of the text (first parameter):
+    \afterassignment\doentry
+    \let\temp =
+}
+\def\doentry{%
+    \bgroup % Instead of the swallowed brace.
+      \noindent
+      \aftergroup\finishentry
+      % And now comes the text of the entry.
+}
+\def\finishentry#1{%
+    % #1 is the page number.
+    %
+    % The following is kludged to not output a line of dots in the index if
+    % there are no page numbers.  The next person who breaks this will be
+    % cursed by a Unix daemon.
+    \setbox\boxA = \hbox{#1}%
+    \ifdim\wd\boxA = 0pt
+      \ %
+    \else
+      %
+      % If we must, put the page number on a line of its own, and fill out
+      % this line with blank space.  (The \hfil is overwhelmed with the
+      % fill leaders glue in \indexdotfill if the page number does fit.)
+      \hfil\penalty50
+      \null\nobreak\indexdotfill % Have leaders before the page number.
+      %
+      % The `\ ' here is removed by the implicit \unskip that TeX does as
+      % part of (the primitive) \par.  Without it, a spurious underfull
+      % \hbox ensues.
+      \ifpdf
+       \pdfgettoks#1.%
+       \ \the\toksA
+      \else
+       \ #1%
+      \fi
+    \fi
+    \par
+  \endgroup
+}
+
+% Like plain.tex's \dotfill, except uses up at least 1 em.
+\def\indexdotfill{\cleaders
+  \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+\def\secondary#1#2{{%
+  \parfillskip=0in
+  \parskip=0in
+  \hangindent=1in
+  \hangafter=1
+  \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill
+  \ifpdf
+    \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph.
+  \else
+    #2
+  \fi
+  \par
+}}
+
+% Define two-column mode, which we use to typeset indexes.
+% Adapted from the TeXbook, page 416, which is to say,
+% the manmac.tex format used to print the TeXbook itself.
+\catcode`\@=11
+
+\newbox\partialpage
+\newdimen\doublecolumnhsize
+
+\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns
+  % Grab any single-column material above us.
+  \output = {%
+    %
+    % Here is a possibility not foreseen in manmac: if we accumulate a
+    % whole lot of material, we might end up calling this \output
+    % routine twice in a row (see the doublecol-lose test, which is
+    % essentially a couple of indexes with @setchapternewpage off).  In
+    % that case we just ship out what is in \partialpage with the normal
+    % output routine.  Generally, \partialpage will be empty when this
+    % runs and this will be a no-op.  See the indexspread.tex test case.
+    \ifvoid\partialpage \else
+      \onepageout{\pagecontents\partialpage}%
+    \fi
+    %
+    \global\setbox\partialpage = \vbox{%
+      % Unvbox the main output page.
+      \unvbox\PAGE
+      \kern-\topskip \kern\baselineskip
+    }%
+  }%
+  \eject % run that output routine to set \partialpage
+  %
+  % Use the double-column output routine for subsequent pages.
+  \output = {\doublecolumnout}%
+  %
+  % Change the page size parameters.  We could do this once outside this
+  % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+  % format, but then we repeat the same computation.  Repeating a couple
+  % of assignments once per index is clearly meaningless for the
+  % execution time, so we may as well do it in one place.
+  %
+  % First we halve the line length, less a little for the gutter between
+  % the columns.  We compute the gutter based on the line length, so it
+  % changes automatically with the paper format.  The magic constant
+  % below is chosen so that the gutter has the same value (well, +-<1pt)
+  % as it did when we hard-coded it.
+  %
+  % We put the result in a separate register, \doublecolumhsize, so we
+  % can restore it in \pagesofar, after \hsize itself has (potentially)
+  % been clobbered.
+  %
+  \doublecolumnhsize = \hsize
+    \advance\doublecolumnhsize by -.04154\hsize
+    \divide\doublecolumnhsize by 2
+  \hsize = \doublecolumnhsize
+  %
+  % Double the \vsize as well.  (We don't need a separate register here,
+  % since nobody clobbers \vsize.)
+  \vsize = 2\vsize
+}
+
+% The double-column output routine for all double-column pages except
+% the last.
+%
+\def\doublecolumnout{%
+  \splittopskip=\topskip \splitmaxdepth=\maxdepth
+  % Get the available space for the double columns -- the normal
+  % (undoubled) page height minus any material left over from the
+  % previous page.
+  \dimen@ = \vsize
+  \divide\dimen@ by 2
+  \advance\dimen@ by -\ht\partialpage
+  %
+  % box0 will be the left-hand column, box2 the right.
+  \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+  \onepageout\pagesofar
+  \unvbox255
+  \penalty\outputpenalty
+}
+%
+% Re-output the contents of the output page -- any previous material,
+% followed by the two boxes we just split, in box0 and box2.
+\def\pagesofar{%
+  \unvbox\partialpage
+  %
+  \hsize = \doublecolumnhsize
+  \wd0=\hsize \wd2=\hsize
+  \hbox to\pagewidth{\box0\hfil\box2}%
+}
+%
+% All done with double columns.
+\def\enddoublecolumns{%
+  % The following penalty ensures that the page builder is exercised
+  % _before_ we change the output routine.  This is necessary in the
+  % following situation:
+  %
+  % The last section of the index consists only of a single entry.
+  % Before this section, \pagetotal is less than \pagegoal, so no
+  % break occurs before the last section starts.  However, the last
+  % section, consisting of \initial and the single \entry, does not
+  % fit on the page and has to be broken off.  Without the following
+  % penalty the page builder will not be exercised until \eject
+  % below, and by that time we'll already have changed the output
+  % routine to the \balancecolumns version, so the next-to-last
+  % double-column page will be processed with \balancecolumns, which
+  % is wrong:  The two columns will go to the main vertical list, with
+  % the broken-off section in the recent contributions.  As soon as
+  % the output routine finishes, TeX starts reconsidering the page
+  % break.  The two columns and the broken-off section both fit on the
+  % page, because the two columns now take up only half of the page
+  % goal.  When TeX sees \eject from below which follows the final
+  % section, it invokes the new output routine that we've set after
+  % \balancecolumns below; \onepageout will try to fit the two columns
+  % and the final section into the vbox of \pageheight (see
+  % \pagebody), causing an overfull box.
+  %
+  % Note that glue won't work here, because glue does not exercise the
+  % page builder, unlike penalties (see The TeXbook, pp. 280-281).
+  \penalty0
+  %
+  \output = {%
+    % Split the last of the double-column material.  Leave it on the
+    % current page, no automatic page break.
+    \balancecolumns
+    %
+    % If we end up splitting too much material for the current page,
+    % though, there will be another page break right after this \output
+    % invocation ends.  Having called \balancecolumns once, we do not
+    % want to call it again.  Therefore, reset \output to its normal
+    % definition right away.  (We hope \balancecolumns will never be
+    % called on to balance too much material, but if it is, this makes
+    % the output somewhat more palatable.)
+    \global\output = {\onepageout{\pagecontents\PAGE}}%
+  }%
+  \eject
+  \endgroup % started in \begindoublecolumns
+  %
+  % \pagegoal was set to the doubled \vsize above, since we restarted
+  % the current page.  We're now back to normal single-column
+  % typesetting, so reset \pagegoal to the normal \vsize (after the
+  % \endgroup where \vsize got restored).
+  \pagegoal = \vsize
+}
+%
+% Called at the end of the double column material.
+\def\balancecolumns{%
+  \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120.
+  \dimen@ = \ht0
+  \advance\dimen@ by \topskip
+  \advance\dimen@ by-\baselineskip
+  \divide\dimen@ by 2 % target to split to
+  %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}%
+  \splittopskip = \topskip
+  % Loop until we get a decent breakpoint.
+  {%
+    \vbadness = 10000
+    \loop
+      \global\setbox3 = \copy0
+      \global\setbox1 = \vsplit3 to \dimen@
+    \ifdim\ht3>\dimen@
+      \global\advance\dimen@ by 1pt
+    \repeat
+  }%
+  %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}%
+  \setbox0=\vbox to\dimen@{\unvbox1}%
+  \setbox2=\vbox to\dimen@{\unvbox3}%
+  %
+  \pagesofar
+}
+\catcode`\@ = \other
+
+
+\message{sectioning,}
+% Chapters, sections, etc.
+
+% \unnumberedno is an oxymoron, of course.  But we count the unnumbered
+% sections so that we can refer to them unambiguously in the pdf
+% outlines by their "section number".  We avoid collisions with chapter
+% numbers by starting them at 10000.  (If a document ever has 10000
+% chapters, we're in trouble anyway, I'm sure.)
+\newcount\unnumberedno \unnumberedno = 10000
+\newcount\chapno
+\newcount\secno        \secno=0
+\newcount\subsecno     \subsecno=0
+\newcount\subsubsecno  \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount\appendixno  \appendixno = `\@
+%
+% \def\appendixletter{\char\the\appendixno}
+% We do the following ugly conditional instead of the above simple
+% construct for the sake of pdftex, which needs the actual
+% letter in the expansion, not just typeset.
+%
+\def\appendixletter{%
+  \ifnum\appendixno=`A A%
+  \else\ifnum\appendixno=`B B%
+  \else\ifnum\appendixno=`C C%
+  \else\ifnum\appendixno=`D D%
+  \else\ifnum\appendixno=`E E%
+  \else\ifnum\appendixno=`F F%
+  \else\ifnum\appendixno=`G G%
+  \else\ifnum\appendixno=`H H%
+  \else\ifnum\appendixno=`I I%
+  \else\ifnum\appendixno=`J J%
+  \else\ifnum\appendixno=`K K%
+  \else\ifnum\appendixno=`L L%
+  \else\ifnum\appendixno=`M M%
+  \else\ifnum\appendixno=`N N%
+  \else\ifnum\appendixno=`O O%
+  \else\ifnum\appendixno=`P P%
+  \else\ifnum\appendixno=`Q Q%
+  \else\ifnum\appendixno=`R R%
+  \else\ifnum\appendixno=`S S%
+  \else\ifnum\appendixno=`T T%
+  \else\ifnum\appendixno=`U U%
+  \else\ifnum\appendixno=`V V%
+  \else\ifnum\appendixno=`W W%
+  \else\ifnum\appendixno=`X X%
+  \else\ifnum\appendixno=`Y Y%
+  \else\ifnum\appendixno=`Z Z%
+  % The \the is necessary, despite appearances, because \appendixletter is
+  % expanded while writing the .toc file.  \char\appendixno is not
+  % expandable, thus it is written literally, thus all appendixes come out
+  % with the same letter (or @) in the toc without it.
+  \else\char\the\appendixno
+  \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+  \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}
+
+% Each @chapter defines these (using marks) as the number+name, number
+% and name of the chapter.  Page headings and footings can use
+% these.  @section does likewise.
+\def\thischapter{}
+\def\thischapternum{}
+\def\thischaptername{}
+\def\thissection{}
+\def\thissectionnum{}
+\def\thissectionname{}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count
+
+% @raisesections: treat @section as chapter, @subsection as section, etc.
+\def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
+
+% @lowersections: treat @chapter as section, @section as subsection, etc.
+\def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
+
+% we only have subsub.
+\chardef\maxseclevel = 3
+%
+% A numbered section within an unnumbered changes to unnumbered too.
+% To achive this, remember the "biggest" unnum. sec. we are currently in:
+\chardef\unmlevel = \maxseclevel
+%
+% Trace whether the current chapter is an appendix or not:
+% \chapheadtype is "N" or "A", unnumbered chapters are ignored.
+\def\chapheadtype{N}
+
+% Choose a heading macro
+% #1 is heading type
+% #2 is heading level
+% #3 is text for heading
+\def\genhead#1#2#3{%
+  % Compute the abs. sec. level:
+  \absseclevel=#2
+  \advance\absseclevel by \secbase
+  % Make sure \absseclevel doesn't fall outside the range:
+  \ifnum \absseclevel < 0
+    \absseclevel = 0
+  \else
+    \ifnum \absseclevel > 3
+      \absseclevel = 3
+    \fi
+  \fi
+  % The heading type:
+  \def\headtype{#1}%
+  \if \headtype U%
+    \ifnum \absseclevel < \unmlevel
+      \chardef\unmlevel = \absseclevel
+    \fi
+  \else
+    % Check for appendix sections:
+    \ifnum \absseclevel = 0
+      \edef\chapheadtype{\headtype}%
+    \else
+      \if \headtype A\if \chapheadtype N%
+       \errmessage{@appendix... within a non-appendix chapter}%
+      \fi\fi
+    \fi
+    % Check for numbered within unnumbered:
+    \ifnum \absseclevel > \unmlevel
+      \def\headtype{U}%
+    \else
+      \chardef\unmlevel = 3
+    \fi
+  \fi
+  % Now print the heading:
+  \if \headtype U%
+    \ifcase\absseclevel
+       \unnumberedzzz{#3}%
+    \or \unnumberedseczzz{#3}%
+    \or \unnumberedsubseczzz{#3}%
+    \or \unnumberedsubsubseczzz{#3}%
+    \fi
+  \else
+    \if \headtype A%
+      \ifcase\absseclevel
+         \appendixzzz{#3}%
+      \or \appendixsectionzzz{#3}%
+      \or \appendixsubseczzz{#3}%
+      \or \appendixsubsubseczzz{#3}%
+      \fi
+    \else
+      \ifcase\absseclevel
+         \chapterzzz{#3}%
+      \or \seczzz{#3}%
+      \or \numberedsubseczzz{#3}%
+      \or \numberedsubsubseczzz{#3}%
+      \fi
+    \fi
+  \fi
+  \suppressfirstparagraphindent
+}
+
+% an interface:
+\def\numhead{\genhead N}
+\def\apphead{\genhead A}
+\def\unnmhead{\genhead U}
+
+% @chapter, @appendix, @unnumbered.  Increment top-level counter, reset
+% all lower-level sectioning counters to zero.
+%
+% Also set \chaplevelprefix, which we prepend to @float sequence numbers
+% (e.g., figures), q.v.  By default (before any chapter), that is empty.
+\let\chaplevelprefix = \empty
+%
+\outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz#1{%
+  % section resetting is \global in case the chapter is in a group, such
+  % as an @include file.
+  \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
+    \global\advance\chapno by 1
+  %
+  % Used for \float.
+  \gdef\chaplevelprefix{\the\chapno.}%
+  \resetallfloatnos
+  %
+  \message{\putwordChapter\space \the\chapno}%
+  %
+  % Write the actual heading.
+  \chapmacro{#1}{Ynumbered}{\the\chapno}%
+  %
+  % So @section and the like are numbered underneath this chapter.
+  \global\let\section = \numberedsec
+  \global\let\subsection = \numberedsubsec
+  \global\let\subsubsection = \numberedsubsubsec
+}
+
+\outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz#1{%
+  \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
+    \global\advance\appendixno by 1
+  \gdef\chaplevelprefix{\appendixletter.}%
+  \resetallfloatnos
+  %
+  \def\appendixnum{\putwordAppendix\space \appendixletter}%
+  \message{\appendixnum}%
+  %
+  \chapmacro{#1}{Yappendix}{\appendixletter}%
+  %
+  \global\let\section = \appendixsec
+  \global\let\subsection = \appendixsubsec
+  \global\let\subsubsection = \appendixsubsubsec
+}
+
+\outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz#1{%
+  \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
+    \global\advance\unnumberedno by 1
+  %
+  % Since an unnumbered has no number, no prefix for figures.
+  \global\let\chaplevelprefix = \empty
+  \resetallfloatnos
+  %
+  % This used to be simply \message{#1}, but TeX fully expands the
+  % argument to \message.  Therefore, if #1 contained @-commands, TeX
+  % expanded them.  For example, in `@unnumbered The @cite{Book}', TeX
+  % expanded @cite (which turns out to cause errors because \cite is meant
+  % to be executed, not expanded).
+  %
+  % Anyway, we don't want the fully-expanded definition of @cite to appear
+  % as a result of the \message, we just want `@cite' itself.  We use
+  % \the<toks register> to achieve this: TeX expands \the<toks> only once,
+  % simply yielding the contents of <toks register>.  (We also do this for
+  % the toc entries.)
+  \toks0 = {#1}%
+  \message{(\the\toks0)}%
+  %
+  \chapmacro{#1}{Ynothing}{\the\unnumberedno}%
+  %
+  \global\let\section = \unnumberedsec
+  \global\let\subsection = \unnumberedsubsec
+  \global\let\subsubsection = \unnumberedsubsubsec
+}
+
+% @centerchap is like @unnumbered, but the heading is centered.
+\outer\parseargdef\centerchap{%
+  % Well, we could do the following in a group, but that would break
+  % an assumption that \chapmacro is called at the outermost level.
+  % Thus we are safer this way:                --kasal, 24feb04
+  \let\centerparametersmaybe = \centerparameters
+  \unnmhead0{#1}%
+  \let\centerparametersmaybe = \relax
+}
+
+% @top is like @unnumbered.
+\let\top\unnumbered
+
+% Sections.
+\outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz
+\def\seczzz#1{%
+  \global\subsecno=0 \global\subsubsecno=0  \global\advance\secno by 1
+  \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}%
+}
+
+\outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz#1{%
+  \global\subsecno=0 \global\subsubsecno=0  \global\advance\secno by 1
+  \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}%
+}
+\let\appendixsec\appendixsection
+
+\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz#1{%
+  \global\subsecno=0 \global\subsubsecno=0  \global\advance\secno by 1
+  \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}%
+}
+
+% Subsections.
+\outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz#1{%
+  \global\subsubsecno=0  \global\advance\subsecno by 1
+  \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}%
+}
+
+\outer\parseargdef\appendixsubsec{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz#1{%
+  \global\subsubsecno=0  \global\advance\subsecno by 1
+  \sectionheading{#1}{subsec}{Yappendix}%
+                 {\appendixletter.\the\secno.\the\subsecno}%
+}
+
+\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz#1{%
+  \global\subsubsecno=0  \global\advance\subsecno by 1
+  \sectionheading{#1}{subsec}{Ynothing}%
+                 {\the\unnumberedno.\the\secno.\the\subsecno}%
+}
+
+% Subsubsections.
+\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz#1{%
+  \global\advance\subsubsecno by 1
+  \sectionheading{#1}{subsubsec}{Ynumbered}%
+                 {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}%
+}
+
+\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz#1{%
+  \global\advance\subsubsecno by 1
+  \sectionheading{#1}{subsubsec}{Yappendix}%
+                 {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}%
+}
+
+\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz#1{%
+  \global\advance\subsubsecno by 1
+  \sectionheading{#1}{subsubsec}{Ynothing}%
+                 {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}%
+}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\let\section = \numberedsec
+\let\subsection = \numberedsubsec
+\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and such:
+%       1) We use \vbox rather than the earlier \line to permit
+%          overlong headings to fold.
+%       2) \hyphenpenalty is set to 10000 because hyphenation in a
+%          heading is obnoxious; this forbids it.
+%       3) Likewise, headings look best if no \parindent is used, and
+%          if justification is not attempted.  Hence \raggedright.
+
+
+\def\majorheading{%
+  {\advance\chapheadingskip by 10pt \chapbreak }%
+  \parsearg\chapheadingzzz
+}
+
+\def\chapheading{\chapbreak \parsearg\chapheadingzzz}
+\def\chapheadingzzz#1{%
+  {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                    \parindent=0pt\raggedright
+                    \rm #1\hfill}}%
+  \bigskip \par\penalty 200\relax
+  \suppressfirstparagraphindent
+}
+
+% @heading, @subheading, @subsubheading.
+\parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{}
+  \suppressfirstparagraphindent}
+\parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{}
+  \suppressfirstparagraphindent}
+\parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{}
+  \suppressfirstparagraphindent}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip\chapheadingskip
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+% Because \domark is called before \chapoddpage, the filler page will
+% get the headings for the next chapter, which is wrong.  But we don't
+% care -- we just disable all headings on the filler page.
+\def\chapoddpage{%
+  \chappager
+  \ifodd\pageno \else
+    \begingroup
+      \evenheadline={\hfil}\evenfootline={\hfil}%
+      \oddheadline={\hfil}\oddfootline={\hfil}%
+      \hbox to 0pt{}%
+      \chappager
+    \endgroup
+  \fi
+}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{%
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{%
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{%
+\global\let\contentsalignmacro = \chapoddpage
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+% Chapter opening.
+%
+% #1 is the text, #2 is the section type (Ynumbered, Ynothing,
+% Yappendix, Yomitfromtoc), #3 the chapter number.
+%
+% To test against our argument.
+\def\Ynothingkeyword{Ynothing}
+\def\Yomitfromtockeyword{Yomitfromtoc}
+\def\Yappendixkeyword{Yappendix}
+%
+\def\chapmacro#1#2#3{%
+  % Insert the first mark before the heading break (see notes for \domark).
+  \let\prevchapterdefs=\lastchapterdefs
+  \let\prevsectiondefs=\lastsectiondefs
+  \gdef\lastsectiondefs{\gdef\thissectionname{}\gdef\thissectionnum{}%
+                        \gdef\thissection{}}%
+  %
+  \def\temptype{#2}%
+  \ifx\temptype\Ynothingkeyword
+    \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}%
+                          \gdef\thischapter{\thischaptername}}%
+  \else\ifx\temptype\Yomitfromtockeyword
+    \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}%
+                          \gdef\thischapter{}}%
+  \else\ifx\temptype\Yappendixkeyword
+    \toks0={#1}%
+    \xdef\lastchapterdefs{%
+      \gdef\noexpand\thischaptername{\the\toks0}%
+      \gdef\noexpand\thischapternum{\appendixletter}%
+      \gdef\noexpand\thischapter{\putwordAppendix{} \noexpand\thischapternum:
+                                 \noexpand\thischaptername}%
+    }%
+  \else
+    \toks0={#1}%
+    \xdef\lastchapterdefs{%
+      \gdef\noexpand\thischaptername{\the\toks0}%
+      \gdef\noexpand\thischapternum{\the\chapno}%
+      \gdef\noexpand\thischapter{\putwordChapter{} \noexpand\thischapternum:
+                                 \noexpand\thischaptername}%
+    }%
+  \fi\fi\fi
+  %
+  % Output the mark.  Pass it through \safewhatsit, to take care of
+  % the preceding space.
+  \safewhatsit\domark
+  %
+  % Insert the chapter heading break.
+  \pchapsepmacro
+  %
+  % Now the second mark, after the heading break.  No break points
+  % between here and the heading.
+  \let\prevchapterdefs=\lastchapterdefs
+  \let\prevsectiondefs=\lastsectiondefs
+  \domark
+  %
+  {%
+    \chapfonts \rm
+    %
+    % Have to define \lastsection before calling \donoderef, because the
+    % xref code eventually uses it.  On the other hand, it has to be called
+    % after \pchapsepmacro, or the headline will change too soon.
+    \gdef\lastsection{#1}%
+    %
+    % Only insert the separating space if we have a chapter/appendix
+    % number, and don't print the unnumbered ``number''.
+    \ifx\temptype\Ynothingkeyword
+      \setbox0 = \hbox{}%
+      \def\toctype{unnchap}%
+    \else\ifx\temptype\Yomitfromtockeyword
+      \setbox0 = \hbox{}% contents like unnumbered, but no toc entry
+      \def\toctype{omit}%
+    \else\ifx\temptype\Yappendixkeyword
+      \setbox0 = \hbox{\putwordAppendix{} #3\enspace}%
+      \def\toctype{app}%
+    \else
+      \setbox0 = \hbox{#3\enspace}%
+      \def\toctype{numchap}%
+    \fi\fi\fi
+    %
+    % Write the toc entry for this chapter.  Must come before the
+    % \donoderef, because we include the current node name in the toc
+    % entry, and \donoderef resets it to empty.
+    \writetocentry{\toctype}{#1}{#3}%
+    %
+    % For pdftex, we have to write out the node definition (aka, make
+    % the pdfdest) after any page break, but before the actual text has
+    % been typeset.  If the destination for the pdf outline is after the
+    % text, then jumping from the outline may wind up with the text not
+    % being visible, for instance under high magnification.
+    \donoderef{#2}%
+    %
+    % Typeset the actual heading.
+    \nobreak % Avoid page breaks at the interline glue.
+    \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+          \hangindent=\wd0 \centerparametersmaybe
+          \unhbox0 #1\par}%
+  }%
+  \nobreak\bigskip % no page break after a chapter title
+  \nobreak
+}
+
+% @centerchap -- centered and unnumbered.
+\let\centerparametersmaybe = \relax
+\def\centerparameters{%
+  \advance\rightskip by 3\rightskip
+  \leftskip = \rightskip
+  \parfillskip = 0pt
+}
+
+
+% I don't think this chapter style is supported any more, so I'm not
+% updating it with the new noderef stuff.  We'll see.  --karl, 11aug03.
+%
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+%
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                       \parindent=0pt\raggedright
+                       \rm #1\hfill}}\bigskip \par\nobreak
+}
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+\def\centerchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                       \parindent=0pt
+                       \hfill {\rm #1}\hfill}}\bigskip \par\nobreak
+}
+\def\CHAPFopen{%
+  \global\let\chapmacro=\chfopen
+  \global\let\centerchapmacro=\centerchfopen}
+
+
+% Section titles.  These macros combine the section number parts and
+% call the generic \sectionheading to do the printing.
+%
+\newskip\secheadingskip
+\def\secheadingbreak{\dobreak \secheadingskip{-1000}}
+
+% Subsection titles.
+\newskip\subsecheadingskip
+\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}}
+
+% Subsubsection titles.
+\def\subsubsecheadingskip{\subsecheadingskip}
+\def\subsubsecheadingbreak{\subsecheadingbreak}
+
+
+% Print any size, any type, section title.
+%
+% #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is
+% the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the
+% section number.
+%
+\def\seckeyword{sec}
+%
+\def\sectionheading#1#2#3#4{%
+  {%
+    % Switch to the right set of fonts.
+    \csname #2fonts\endcsname \rm
+    %
+    \def\sectionlevel{#2}%
+    \def\temptype{#3}%
+    %
+    % Insert first mark before the heading break (see notes for \domark).
+    \let\prevsectiondefs=\lastsectiondefs
+    \ifx\temptype\Ynothingkeyword
+      \ifx\sectionlevel\seckeyword
+        \gdef\lastsectiondefs{\gdef\thissectionname{#1}\gdef\thissectionnum{}%
+                              \gdef\thissection{\thissectionname}}%
+      \fi
+    \else\ifx\temptype\Yomitfromtockeyword
+      % Don't redefine \thissection.
+    \else\ifx\temptype\Yappendixkeyword
+      \ifx\sectionlevel\seckeyword
+        \toks0={#1}%
+        \xdef\lastsectiondefs{%
+          \gdef\noexpand\thissectionname{\the\toks0}%
+          \gdef\noexpand\thissectionnum{#4}%
+          \gdef\noexpand\thissection{\putwordSection{} \noexpand\thissectionnum:
+                                     \noexpand\thissectionname}%
+        }%
+      \fi
+    \else
+      \ifx\sectionlevel\seckeyword
+        \toks0={#1}%
+        \xdef\lastsectiondefs{%
+          \gdef\noexpand\thissectionname{\the\toks0}%
+          \gdef\noexpand\thissectionnum{#4}%
+          \gdef\noexpand\thissection{\putwordSection{} \noexpand\thissectionnum:
+                                     \noexpand\thissectionname}%
+        }%
+      \fi
+    \fi\fi\fi
+    %
+    % Output the mark.  Pass it through \safewhatsit, to take care of
+    % the preceding space.
+    \safewhatsit\domark
+    %
+    % Insert space above the heading.
+    \csname #2headingbreak\endcsname
+    %
+    % Now the second mark, after the heading break.  No break points
+    % between here and the heading.
+    \let\prevsectiondefs=\lastsectiondefs
+    \domark
+    %
+    % Only insert the space after the number if we have a section number.
+    \ifx\temptype\Ynothingkeyword
+      \setbox0 = \hbox{}%
+      \def\toctype{unn}%
+      \gdef\lastsection{#1}%
+    \else\ifx\temptype\Yomitfromtockeyword
+      % for @headings -- no section number, don't include in toc,
+      % and don't redefine \lastsection.
+      \setbox0 = \hbox{}%
+      \def\toctype{omit}%
+      \let\sectionlevel=\empty
+    \else\ifx\temptype\Yappendixkeyword
+      \setbox0 = \hbox{#4\enspace}%
+      \def\toctype{app}%
+      \gdef\lastsection{#1}%
+    \else
+      \setbox0 = \hbox{#4\enspace}%
+      \def\toctype{num}%
+      \gdef\lastsection{#1}%
+    \fi\fi\fi
+    %
+    % Write the toc entry (before \donoderef).  See comments in \chapmacro.
+    \writetocentry{\toctype\sectionlevel}{#1}{#4}%
+    %
+    % Write the node reference (= pdf destination for pdftex).
+    % Again, see comments in \chapmacro.
+    \donoderef{#3}%
+    %
+    % Interline glue will be inserted when the vbox is completed.
+    % That glue will be a valid breakpoint for the page, since it'll be
+    % preceded by a whatsit (usually from the \donoderef, or from the
+    % \writetocentry if there was no node).  We don't want to allow that
+    % break, since then the whatsits could end up on page n while the
+    % section is on page n+1, thus toc/etc. are wrong.  Debian bug 276000.
+    \nobreak
+    %
+    % Output the actual section heading.
+    \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+          \hangindent=\wd0  % zero if no section number
+          \unhbox0 #1}%
+  }%
+  % Add extra space after the heading -- half of whatever came above it.
+  % Don't allow stretch, though.
+  \kern .5 \csname #2headingskip\endcsname
+  %
+  % Do not let the kern be a potential breakpoint, as it would be if it
+  % was followed by glue.
+  \nobreak
+  %
+  % We'll almost certainly start a paragraph next, so don't let that
+  % glue accumulate.  (Not a breakpoint because it's preceded by a
+  % discardable item.)
+  \vskip-\parskip
+  % 
+  % This is purely so the last item on the list is a known \penalty >
+  % 10000.  This is so \startdefun can avoid allowing breakpoints after
+  % section headings.  Otherwise, it would insert a valid breakpoint between:
+  % 
+  %   @section sec-whatever
+  %   @deffn def-whatever
+  \penalty 10001
+}
+
+
+\message{toc,}
+% Table of contents.
+\newwrite\tocfile
+
+% Write an entry to the toc file, opening it if necessary.
+% Called from @chapter, etc.
+%
+% Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno}
+% We append the current node name (if any) and page number as additional
+% arguments for the \{chap,sec,...}entry macros which will eventually
+% read this.  The node name is used in the pdf outlines as the
+% destination to jump to.
+%
+% We open the .toc file for writing here instead of at @setfilename (or
+% any other fixed time) so that @contents can be anywhere in the document.
+% But if #1 is `omit', then we don't do anything.  This is used for the
+% table of contents chapter openings themselves.
+%
+\newif\iftocfileopened
+\def\omitkeyword{omit}%
+%
+\def\writetocentry#1#2#3{%
+  \edef\writetoctype{#1}%
+  \ifx\writetoctype\omitkeyword \else
+    \iftocfileopened\else
+      \immediate\openout\tocfile = \jobname.toc
+      \global\tocfileopenedtrue
+    \fi
+    %
+    \iflinks
+      {\atdummies
+       \edef\temp{%
+         \write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}%
+       \temp
+      }%
+    \fi
+  \fi
+  %
+  % Tell \shipout to create a pdf destination on each page, if we're
+  % writing pdf.  These are used in the table of contents.  We can't
+  % just write one on every page because the title pages are numbered
+  % 1 and 2 (the page numbers aren't printed), and so are the first
+  % two pages of the document.  Thus, we'd have two destinations named
+  % `1', and two named `2'.
+  \ifpdf \global\pdfmakepagedesttrue \fi
+}
+
+
+% These characters do not print properly in the Computer Modern roman
+% fonts, so we must take special care.  This is more or less redundant
+% with the Texinfo input format setup at the end of this file.
+% 
+\def\activecatcodes{%
+  \catcode`\"=\active
+  \catcode`\$=\active
+  \catcode`\<=\active
+  \catcode`\>=\active
+  \catcode`\\=\active
+  \catcode`\^=\active
+  \catcode`\_=\active
+  \catcode`\|=\active
+  \catcode`\~=\active
+}
+
+
+% Read the toc file, which is essentially Texinfo input.
+\def\readtocfile{%
+  \setupdatafile
+  \activecatcodes
+  \input \tocreadfilename
+}
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\newcount\savepageno
+\newcount\lastnegativepageno \lastnegativepageno = -1
+
+% Prepare to read what we've written to \tocfile.
+%
+\def\startcontents#1{%
+  % If @setchapternewpage on, and @headings double, the contents should
+  % start on an odd page, unlike chapters.  Thus, we maintain
+  % \contentsalignmacro in parallel with \pagealignmacro.
+  % From: Torbjorn Granlund <tege@matematik.su.se>
+  \contentsalignmacro
+  \immediate\closeout\tocfile
+  %
+  % Don't need to put `Contents' or `Short Contents' in the headline.
+  % It is abundantly clear what they are.
+  \chapmacro{#1}{Yomitfromtoc}{}%
+  %
+  \savepageno = \pageno
+  \begingroup                  % Set up to handle contents files properly.
+    \raggedbottom              % Worry more about breakpoints than the bottom.
+    \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+    %
+    % Roman numerals for page numbers.
+    \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi
+}
+
+% redefined for the two-volume lispref.  We always output on
+% \jobname.toc even if this is redefined.
+% 
+\def\tocreadfilename{\jobname.toc}
+
+% Normal (long) toc.
+%
+\def\contents{%
+  \startcontents{\putwordTOC}%
+    \openin 1 \tocreadfilename\space
+    \ifeof 1 \else
+      \readtocfile
+    \fi
+    \vfill \eject
+    \contentsalignmacro % in case @setchapternewpage odd is in effect
+    \ifeof 1 \else
+      \pdfmakeoutlines
+    \fi
+    \closein 1
+  \endgroup
+  \lastnegativepageno = \pageno
+  \global\pageno = \savepageno
+}
+
+% And just the chapters.
+\def\summarycontents{%
+  \startcontents{\putwordShortTOC}%
+    %
+    \let\numchapentry = \shortchapentry
+    \let\appentry = \shortchapentry
+    \let\unnchapentry = \shortunnchapentry
+    % We want a true roman here for the page numbers.
+    \secfonts
+    \let\rm=\shortcontrm \let\bf=\shortcontbf
+    \let\sl=\shortcontsl \let\tt=\shortconttt
+    \rm
+    \hyphenpenalty = 10000
+    \advance\baselineskip by 1pt % Open it up a little.
+    \def\numsecentry##1##2##3##4{}
+    \let\appsecentry = \numsecentry
+    \let\unnsecentry = \numsecentry
+    \let\numsubsecentry = \numsecentry
+    \let\appsubsecentry = \numsecentry
+    \let\unnsubsecentry = \numsecentry
+    \let\numsubsubsecentry = \numsecentry
+    \let\appsubsubsecentry = \numsecentry
+    \let\unnsubsubsecentry = \numsecentry
+    \openin 1 \tocreadfilename\space
+    \ifeof 1 \else
+      \readtocfile
+    \fi
+    \closein 1
+    \vfill \eject
+    \contentsalignmacro % in case @setchapternewpage odd is in effect
+  \endgroup
+  \lastnegativepageno = \pageno
+  \global\pageno = \savepageno
+}
+\let\shortcontents = \summarycontents
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g., `A' for an appendix, or `3' for a chapter.
+%
+\def\shortchaplabel#1{%
+  % This space should be enough, since a single number is .5em, and the
+  % widest letter (M) is 1em, at least in the Computer Modern fonts.
+  % But use \hss just in case.
+  % (This space doesn't include the extra space that gets added after
+  % the label; that gets put in by \shortchapentry above.)
+  %
+  % We'd like to right-justify chapter numbers, but that looks strange
+  % with appendix letters.  And right-justifying numbers and
+  % left-justifying letters looks strange when there is less than 10
+  % chapters.  Have to read the whole toc once to know how many chapters
+  % there are before deciding ...
+  \hbox to 1em{#1\hss}%
+}
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapters, in the main contents.
+\def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}}
+%
+% Chapters, in the short toc.
+% See comments in \dochapentry re vbox and related settings.
+\def\shortchapentry#1#2#3#4{%
+  \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}%
+}
+
+% Appendices, in the main contents.
+% Need the word Appendix, and a fixed-size box.
+%
+\def\appendixbox#1{%
+  % We use M since it's probably the widest letter.
+  \setbox0 = \hbox{\putwordAppendix{} M}%
+  \hbox to \wd0{\putwordAppendix{} #1\hss}}
+%
+\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}}
+
+% Unnumbered chapters.
+\def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}}
+\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}}
+
+% Sections.
+\def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}}
+\let\appsecentry=\numsecentry
+\def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}}
+
+% Subsections.
+\def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}}
+\let\appsubsecentry=\numsubsecentry
+\def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}}
+
+% And subsubsections.
+\def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}}
+\let\appsubsubsecentry=\numsubsubsecentry
+\def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}}
+
+% This parameter controls the indentation of the various levels.
+% Same as \defaultparindent.
+\newdimen\tocindent \tocindent = 15pt
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we want it to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+   \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip
+   \begingroup
+     \chapentryfonts
+     \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+   \endgroup
+   \nobreak\vskip .25\baselineskip plus.1\baselineskip
+}
+
+\def\dosecentry#1#2{\begingroup
+  \secentryfonts \leftskip=\tocindent
+  \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+\endgroup}
+
+\def\dosubsecentry#1#2{\begingroup
+  \subsecentryfonts \leftskip=2\tocindent
+  \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+\endgroup}
+
+\def\dosubsubsecentry#1#2{\begingroup
+  \subsubsecentryfonts \leftskip=3\tocindent
+  \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+\endgroup}
+
+% We use the same \entry macro as for the index entries.
+\let\tocentry = \entry
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\def\subsecentryfonts{\textfonts}
+\def\subsubsecentryfonts{\textfonts}
+
+
+\message{environments,}
+% @foo ... @end foo.
+
+% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
+%
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+%
+\def\point{$\star$}
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% The @error{} command.
+% Adapted from the TeXbook's \boxit.
+%
+\newbox\errorbox
+%
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \reducedsf error\kern-1.5pt}
+%
+\setbox\errorbox=\hbox to \dimen0{\hfil
+   \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+   \advance\hsize by -2\dimen2 % Rules.
+   \vbox{%
+      \hrule height\dimen2
+      \hbox{\vrule width\dimen2 \kern3pt          % Space to left of text.
+         \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+         \kern3pt\vrule width\dimen2}% Space to right.
+      \hrule height\dimen2}
+    \hfil}
+%
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex    escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\envdef\tex{%
+  \catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+  \catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+  \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie
+  \catcode `\%=14
+  \catcode `\+=\other
+  \catcode `\"=\other
+  \catcode `\|=\other
+  \catcode `\<=\other
+  \catcode `\>=\other
+  \escapechar=`\\
+  %
+  \let\b=\ptexb
+  \let\bullet=\ptexbullet
+  \let\c=\ptexc
+  \let\,=\ptexcomma
+  \let\.=\ptexdot
+  \let\dots=\ptexdots
+  \let\equiv=\ptexequiv
+  \let\!=\ptexexclam
+  \let\i=\ptexi
+  \let\indent=\ptexindent
+  \let\noindent=\ptexnoindent
+  \let\{=\ptexlbrace
+  \let\+=\tabalign
+  \let\}=\ptexrbrace
+  \let\/=\ptexslash
+  \let\*=\ptexstar
+  \let\t=\ptext
+  \let\frenchspacing=\plainfrenchspacing
+  %
+  \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}%
+  \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}%
+  \def\@{@}%
+}
+% There is no need to define \Etex.
+
+% Define @lisp ... @end lisp.
+% @lisp environment forms a group so it can rebind things,
+% including the definition of @end lisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^^M gets inside @lisp, @example, and other
+% such environments.  \null is better than a space, since it doesn't
+% have any width.
+\def\lisppar{\null\endgraf}
+
+% This space is always present above and below environments.
+\newskip\envskipamount \envskipamount = 0pt
+
+% Make spacing and below environment symmetrical.  We use \parskip here
+% to help in doing that, since in @example-like environments \parskip
+% is reset to zero; thus the \afterenvbreak inserts no space -- but the
+% start of the next paragraph will insert \parskip.
+%
+\def\aboveenvbreak{{%
+  % =10000 instead of <10000 because of a special case in \itemzzz and
+  % \sectionheading, q.v.
+  \ifnum \lastpenalty=10000 \else
+    \advance\envskipamount by \parskip
+    \endgraf
+    \ifdim\lastskip<\envskipamount
+      \removelastskip
+      % it's not a good place to break if the last penalty was \nobreak
+      % or better ...
+      \ifnum\lastpenalty<10000 \penalty-50 \fi
+      \vskip\envskipamount
+    \fi
+  \fi
+}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag.  If "set", @lisp etc don't narrow margins; it will
+% also clear it, so that its embedded environments do the narrowing again.
+\let\nonarrowing=\relax
+
+% @cartouche ... @end cartouche: draw rectangle w/rounded corners around
+% environment contents.
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+        \ctl\leaders\hrule height\circthick\hfil\ctr
+        \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+        \cbl\leaders\hrule height\circthick\hfil\cbr
+        \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\envdef\cartouche{%
+  \ifhmode\par\fi  % can't be in the midst of a paragraph.
+  \startsavinginserts
+  \lskip=\leftskip \rskip=\rightskip
+  \leftskip=0pt\rightskip=0pt % we want these *outside*.
+  \cartinner=\hsize \advance\cartinner by-\lskip
+  \advance\cartinner by-\rskip
+  \cartouter=\hsize
+  \advance\cartouter by 18.4pt % allow for 3pt kerns on either
+                               % side, and for 6pt waste from
+                               % each corner char, and rule thickness
+  \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+  % Flag to tell @lisp, etc., not to narrow margin.
+  \let\nonarrowing = t%
+  \vbox\bgroup
+      \baselineskip=0pt\parskip=0pt\lineskip=0pt
+      \carttop
+      \hbox\bgroup
+         \hskip\lskip
+         \vrule\kern3pt
+         \vbox\bgroup
+             \kern3pt
+             \hsize=\cartinner
+             \baselineskip=\normbskip
+             \lineskip=\normlskip
+             \parskip=\normpskip
+             \vskip -\parskip
+             \comment % For explanation, see the end of \def\group.
+}
+\def\Ecartouche{%
+              \ifhmode\par\fi
+             \kern3pt
+         \egroup
+         \kern3pt\vrule
+         \hskip\rskip
+      \egroup
+      \cartbot
+  \egroup
+  \checkinserts
+}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+  \aboveenvbreak
+  \hfuzz = 12pt % Don't be fussy
+  \sepspaces % Make spaces be word-separators rather than space tokens.
+  \let\par = \lisppar % don't ignore blank lines
+  \obeylines % each line of input is a line of output
+  \parskip = 0pt
+  \parindent = 0pt
+  \emergencystretch = 0pt % don't try to avoid overfull boxes
+  \ifx\nonarrowing\relax
+    \advance \leftskip by \lispnarrowing
+    \exdentamount=\lispnarrowing
+  \else
+    \let\nonarrowing = \relax
+  \fi
+  \let\exdent=\nofillexdent
+}
+
+% If you want all examples etc. small: @set dispenvsize small.
+% If you want even small examples the full size: @set dispenvsize nosmall.
+% This affects the following displayed environments:
+%    @example, @display, @format, @lisp
+%
+\def\smallword{small}
+\def\nosmallword{nosmall}
+\let\SETdispenvsize\relax
+\def\setnormaldispenv{%
+  \ifx\SETdispenvsize\smallword
+    % end paragraph for sake of leading, in case document has no blank
+    % line.  This is redundant with what happens in \aboveenvbreak, but
+    % we need to do it before changing the fonts, and it's inconvenient
+    % to change the fonts afterward.
+    \ifnum \lastpenalty=10000 \else \endgraf \fi
+    \smallexamplefonts \rm
+  \fi
+}
+\def\setsmalldispenv{%
+  \ifx\SETdispenvsize\nosmallword
+  \else
+    \ifnum \lastpenalty=10000 \else \endgraf \fi
+    \smallexamplefonts \rm
+  \fi
+}
+
+% We often define two environments, @foo and @smallfoo.
+% Let's do it by one command:
+\def\makedispenv #1#2{
+  \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2}
+  \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2}
+  \expandafter\let\csname E#1\endcsname \afterenvbreak
+  \expandafter\let\csname Esmall#1\endcsname \afterenvbreak
+}
+
+% Define two synonyms:
+\def\maketwodispenvs #1#2#3{
+  \makedispenv{#1}{#3}
+  \makedispenv{#2}{#3}
+}
+
+% @lisp: indented, narrowed, typewriter font; @example: same as @lisp.
+%
+% @smallexample and @smalllisp: use smaller fonts.
+% Originally contributed by Pavel@xerox.
+%
+\maketwodispenvs {lisp}{example}{%
+  \nonfillstart
+  \tt\quoteexpand
+  \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special.
+  \gobble       % eat return
+}
+% @display/@smalldisplay: same as @lisp except keep current font.
+%
+\makedispenv {display}{%
+  \nonfillstart
+  \gobble
+}
+
+% @format/@smallformat: same as @display except don't narrow margins.
+%
+\makedispenv{format}{%
+  \let\nonarrowing = t%
+  \nonfillstart
+  \gobble
+}
+
+% @flushleft: same as @format, but doesn't obey \SETdispenvsize.
+\envdef\flushleft{%
+  \let\nonarrowing = t%
+  \nonfillstart
+  \gobble
+}
+\let\Eflushleft = \afterenvbreak
+
+% @flushright.
+%
+\envdef\flushright{%
+  \let\nonarrowing = t%
+  \nonfillstart
+  \advance\leftskip by 0pt plus 1fill
+  \gobble
+}
+\let\Eflushright = \afterenvbreak
+
+
+% @quotation does normal linebreaking (hence we can't use \nonfillstart)
+% and narrows the margins.  We keep \parskip nonzero in general, since
+% we're doing normal filling.  So, when using \aboveenvbreak and
+% \afterenvbreak, temporarily make \parskip 0.
+%
+\envdef\quotation{%
+  {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
+  \parindent=0pt
+  %
+  % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
+  \ifx\nonarrowing\relax
+    \advance\leftskip by \lispnarrowing
+    \advance\rightskip by \lispnarrowing
+    \exdentamount = \lispnarrowing
+  \else
+    \let\nonarrowing = \relax
+  \fi
+  \parsearg\quotationlabel
+}
+
+% We have retained a nonzero parskip for the environment, since we're
+% doing normal filling.
+%
+\def\Equotation{%
+  \par
+  \ifx\quotationauthor\undefined\else
+    % indent a bit.
+    \leftline{\kern 2\leftskip \sl ---\quotationauthor}%
+  \fi
+  {\parskip=0pt \afterenvbreak}%
+}
+
+% If we're given an argument, typeset it in bold with a colon after.
+\def\quotationlabel#1{%
+  \def\temp{#1}%
+  \ifx\temp\empty \else
+    {\bf #1: }%
+  \fi
+}
+
+
+% LaTeX-like @verbatim...@end verbatim and @verb{<char>...<char>}
+% If we want to allow any <char> as delimiter,
+% we need the curly braces so that makeinfo sees the @verb command, eg:
+% `@verbx...x' would look like the '@verbx' command.  --janneke@gnu.org
+%
+% [Knuth]: Donald Ervin Knuth, 1996.  The TeXbook.
+%
+% [Knuth] p.344; only we need to do the other characters Texinfo sets
+% active too.  Otherwise, they get lost as the first character on a
+% verbatim line.
+\def\dospecials{%
+  \do\ \do\\\do\{\do\}\do\$\do\&%
+  \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~%
+  \do\<\do\>\do\|\do\@\do+\do\"%
+}
+%
+% [Knuth] p. 380
+\def\uncatcodespecials{%
+  \def\do##1{\catcode`##1=\other}\dospecials}
+%
+% [Knuth] pp. 380,381,391
+% Disable Spanish ligatures ?` and !` of \tt font
+\begingroup
+  \catcode`\`=\active\gdef`{\relax\lq}
+\endgroup
+%
+% Setup for the @verb command.
+%
+% Eight spaces for a tab
+\begingroup
+  \catcode`\^^I=\active
+  \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }}
+\endgroup
+%
+\def\setupverb{%
+  \tt  % easiest (and conventionally used) font for verbatim
+  \def\par{\leavevmode\endgraf}%
+  \catcode`\`=\active
+  \tabeightspaces
+  % Respect line breaks,
+  % print special symbols as themselves, and
+  % make each space count
+  % must do in this order:
+  \obeylines \uncatcodespecials \sepspaces
+}
+
+% Setup for the @verbatim environment
+%
+% Real tab expansion
+\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount
+%
+\def\starttabbox{\setbox0=\hbox\bgroup}
+
+% Allow an option to not replace quotes with a regular directed right
+% quote/apostrophe (char 0x27), but instead use the undirected quote
+% from cmtt (char 0x0d).  The undirected quote is ugly, so don't make it
+% the default, but it works for pasting with more pdf viewers (at least
+% evince), the lilypond developers report.  xpdf does work with the
+% regular 0x27.  
+% 
+\def\codequoteright{%
+  \expandafter\ifx\csname SETtxicodequoteundirected\endcsname\relax
+    \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax
+      '%
+    \else \char'15 \fi
+  \else \char'15 \fi
+}
+%
+% and a similar option for the left quote char vs. a grave accent.
+% Modern fonts display ASCII 0x60 as a grave accent, so some people like
+% the code environments to do likewise.
+% 
+\def\codequoteleft{%
+  \expandafter\ifx\csname SETtxicodequotebacktick\endcsname\relax
+    \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax
+      `%
+    \else \char'22 \fi
+  \else \char'22 \fi
+}
+%
+\begingroup
+  \catcode`\^^I=\active
+  \gdef\tabexpand{%
+    \catcode`\^^I=\active
+    \def^^I{\leavevmode\egroup
+      \dimen0=\wd0 % the width so far, or since the previous tab
+      \divide\dimen0 by\tabw
+      \multiply\dimen0 by\tabw % compute previous multiple of \tabw
+      \advance\dimen0 by\tabw  % advance to next multiple of \tabw
+      \wd0=\dimen0 \box0 \starttabbox
+    }%
+  }
+  \catcode`\'=\active
+  \gdef\rquoteexpand{\catcode\rquoteChar=\active \def'{\codequoteright}}%
+  %
+  \catcode`\`=\active
+  \gdef\lquoteexpand{\catcode\lquoteChar=\active \def`{\codequoteleft}}%
+  %
+  \gdef\quoteexpand{\rquoteexpand \lquoteexpand}%
+\endgroup
+
+% start the verbatim environment.
+\def\setupverbatim{%
+  \let\nonarrowing = t%
+  \nonfillstart
+  % Easiest (and conventionally used) font for verbatim
+  \tt
+  \def\par{\leavevmode\egroup\box0\endgraf}%
+  \catcode`\`=\active
+  \tabexpand
+  \quoteexpand
+  % Respect line breaks,
+  % print special symbols as themselves, and
+  % make each space count
+  % must do in this order:
+  \obeylines \uncatcodespecials \sepspaces
+  \everypar{\starttabbox}%
+}
+
+% Do the @verb magic: verbatim text is quoted by unique
+% delimiter characters.  Before first delimiter expect a
+% right brace, after last delimiter expect closing brace:
+%
+%    \def\doverb'{'<char>#1<char>'}'{#1}
+%
+% [Knuth] p. 382; only eat outer {}
+\begingroup
+  \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other
+  \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next]
+\endgroup
+%
+\def\verb{\begingroup\setupverb\doverb}
+%
+%
+% Do the @verbatim magic: define the macro \doverbatim so that
+% the (first) argument ends when '@end verbatim' is reached, ie:
+%
+%     \def\doverbatim#1@end verbatim{#1}
+%
+% For Texinfo it's a lot easier than for LaTeX,
+% because texinfo's \verbatim doesn't stop at '\end{verbatim}':
+% we need not redefine '\', '{' and '}'.
+%
+% Inspired by LaTeX's verbatim command set [latex.ltx]
+%
+\begingroup
+  \catcode`\ =\active
+  \obeylines %
+  % ignore everything up to the first ^^M, that's the newline at the end
+  % of the @verbatim input line itself.  Otherwise we get an extra blank
+  % line in the output.
+  \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}%
+  % We really want {...\end verbatim} in the body of the macro, but
+  % without the active space; thus we have to use \xdef and \gobble.
+\endgroup
+%
+\envdef\verbatim{%
+    \setupverbatim\doverbatim
+}
+\let\Everbatim = \afterenvbreak
+
+
+% @verbatiminclude FILE - insert text of file in verbatim environment.
+%
+\def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude}
+%
+\def\doverbatiminclude#1{%
+  {%
+    \makevalueexpandable
+    \setupverbatim
+    \input #1
+    \afterenvbreak
+  }%
+}
+
+% @copying ... @end copying.
+% Save the text away for @insertcopying later.
+%
+% We save the uninterpreted tokens, rather than creating a box.
+% Saving the text in a box would be much easier, but then all the
+% typesetting commands (@smallbook, font changes, etc.) have to be done
+% beforehand -- and a) we want @copying to be done first in the source
+% file; b) letting users define the frontmatter in as flexible order as
+% possible is very desirable.
+%
+\def\copying{\checkenv{}\begingroup\scanargctxt\docopying}
+\def\docopying#1@end copying{\endgroup\def\copyingtext{#1}}
+%
+\def\insertcopying{%
+  \begingroup
+    \parindent = 0pt  % paragraph indentation looks wrong on title page
+    \scanexp\copyingtext
+  \endgroup
+}
+
+
+\message{defuns,}
+% @defun etc.
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+\newcount\defunpenalty
+
+% Start the processing of @deffn:
+\def\startdefun{%
+  \ifnum\lastpenalty<10000
+    \medbreak
+    \defunpenalty=10003 % Will keep this @deffn together with the
+                        % following @def command, see below.
+  \else
+    % If there are two @def commands in a row, we'll have a \nobreak,
+    % which is there to keep the function description together with its
+    % header.  But if there's nothing but headers, we need to allow a
+    % break somewhere.  Check specifically for penalty 10002, inserted
+    % by \printdefunline, instead of 10000, since the sectioning
+    % commands also insert a nobreak penalty, and we don't want to allow
+    % a break between a section heading and a defun.
+    %
+    % As a minor refinement, we avoid "club" headers by signalling
+    % with penalty of 10003 after the very first @deffn in the
+    % sequence (see above), and penalty of 10002 after any following
+    % @def command.
+    \ifnum\lastpenalty=10002 \penalty2000 \else \defunpenalty=10002 \fi
+    %
+    % Similarly, after a section heading, do not allow a break.
+    % But do insert the glue.
+    \medskip  % preceded by discardable penalty, so not a breakpoint
+  \fi
+  %
+  \parindent=0in
+  \advance\leftskip by \defbodyindent
+  \exdentamount=\defbodyindent
+}
+
+\def\dodefunx#1{%
+  % First, check whether we are in the right environment:
+  \checkenv#1%
+  %
+  % As above, allow line break if we have multiple x headers in a row.
+  % It's not a great place, though.
+  \ifnum\lastpenalty=10002 \penalty3000 \else \defunpenalty=10002 \fi
+  %
+  % And now, it's time to reuse the body of the original defun:
+  \expandafter\gobbledefun#1%
+}
+\def\gobbledefun#1\startdefun{}
+
+% \printdefunline \deffnheader{text}
+%
+\def\printdefunline#1#2{%
+  \begingroup
+    % call \deffnheader:
+    #1#2 \endheader
+    % common ending:
+    \interlinepenalty = 10000
+    \advance\rightskip by 0pt plus 1fil
+    \endgraf
+    \nobreak\vskip -\parskip
+    \penalty\defunpenalty  % signal to \startdefun and \dodefunx
+    % Some of the @defun-type tags do not enable magic parentheses,
+    % rendering the following check redundant.  But we don't optimize.
+    \checkparencounts
+  \endgroup
+}
+
+\def\Edefun{\endgraf\medbreak}
+
+% \makedefun{deffn} creates \deffn, \deffnx and \Edeffn;
+% the only thing remainnig is to define \deffnheader.
+%
+\def\makedefun#1{%
+  \expandafter\let\csname E#1\endcsname = \Edefun
+  \edef\temp{\noexpand\domakedefun
+    \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}%
+  \temp
+}
+
+% \domakedefun \deffn \deffnx \deffnheader
+%
+% Define \deffn and \deffnx, without parameters.
+% \deffnheader has to be defined explicitly.
+%
+\def\domakedefun#1#2#3{%
+  \envdef#1{%
+    \startdefun
+    \parseargusing\activeparens{\printdefunline#3}%
+  }%
+  \def#2{\dodefunx#1}%
+  \def#3%
+}
+
+%%% Untyped functions:
+
+% @deffn category name args
+\makedefun{deffn}{\deffngeneral{}}
+
+% @deffn category class name args
+\makedefun{defop}#1 {\defopon{#1\ \putwordon}}
+
+% \defopon {category on}class name args
+\def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} }
+
+% \deffngeneral {subind}category name args
+%
+\def\deffngeneral#1#2 #3 #4\endheader{%
+  % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}.
+  \dosubind{fn}{\code{#3}}{#1}%
+  \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}%
+}
+
+%%% Typed functions:
+
+% @deftypefn category type name args
+\makedefun{deftypefn}{\deftypefngeneral{}}
+
+% @deftypeop category class type name args
+\makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}}
+
+% \deftypeopon {category on}class type name args
+\def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} }
+
+% \deftypefngeneral {subind}category type name args
+%
+\def\deftypefngeneral#1#2 #3 #4 #5\endheader{%
+  \dosubind{fn}{\code{#4}}{#1}%
+  \defname{#2}{#3}{#4}\defunargs{#5\unskip}%
+}
+
+%%% Typed variables:
+
+% @deftypevr category type var args
+\makedefun{deftypevr}{\deftypecvgeneral{}}
+
+% @deftypecv category class type var args
+\makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}}
+
+% \deftypecvof {category of}class type var args
+\def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} }
+
+% \deftypecvgeneral {subind}category type var args
+%
+\def\deftypecvgeneral#1#2 #3 #4 #5\endheader{%
+  \dosubind{vr}{\code{#4}}{#1}%
+  \defname{#2}{#3}{#4}\defunargs{#5\unskip}%
+}
+
+%%% Untyped variables:
+
+% @defvr category var args
+\makedefun{defvr}#1 {\deftypevrheader{#1} {} }
+
+% @defcv category class var args
+\makedefun{defcv}#1 {\defcvof{#1\ \putwordof}}
+
+% \defcvof {category of}class var args
+\def\defcvof#1#2 {\deftypecvof{#1}#2 {} }
+
+%%% Type:
+% @deftp category name args
+\makedefun{deftp}#1 #2 #3\endheader{%
+  \doind{tp}{\code{#2}}%
+  \defname{#1}{}{#2}\defunargs{#3\unskip}%
+}
+
+% Remaining @defun-like shortcuts:
+\makedefun{defun}{\deffnheader{\putwordDeffunc} }
+\makedefun{defmac}{\deffnheader{\putwordDefmac} }
+\makedefun{defspec}{\deffnheader{\putwordDefspec} }
+\makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} }
+\makedefun{defvar}{\defvrheader{\putwordDefvar} }
+\makedefun{defopt}{\defvrheader{\putwordDefopt} }
+\makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} }
+\makedefun{defmethod}{\defopon\putwordMethodon}
+\makedefun{deftypemethod}{\deftypeopon\putwordMethodon}
+\makedefun{defivar}{\defcvof\putwordInstanceVariableof}
+\makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof}
+
+% \defname, which formats the name of the @def (not the args).
+% #1 is the category, such as "Function".
+% #2 is the return type, if any.
+% #3 is the function name.
+%
+% We are followed by (but not passed) the arguments, if any.
+%
+\def\defname#1#2#3{%
+  % Get the values of \leftskip and \rightskip as they were outside the @def...
+  \advance\leftskip by -\defbodyindent
+  %
+  % How we'll format the type name.  Putting it in brackets helps
+  % distinguish it from the body text that may end up on the next line
+  % just below it.
+  \def\temp{#1}%
+  \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi}
+  %
+  % Figure out line sizes for the paragraph shape.
+  % The first line needs space for \box0; but if \rightskip is nonzero,
+  % we need only space for the part of \box0 which exceeds it:
+  \dimen0=\hsize  \advance\dimen0 by -\wd0  \advance\dimen0 by \rightskip
+  % The continuations:
+  \dimen2=\hsize  \advance\dimen2 by -\defargsindent
+  % (plain.tex says that \dimen1 should be used only as global.)
+  \parshape 2 0in \dimen0 \defargsindent \dimen2
+  %
+  % Put the type name to the right margin.
+  \noindent
+  \hbox to 0pt{%
+    \hfil\box0 \kern-\hsize
+    % \hsize has to be shortened this way:
+    \kern\leftskip
+    % Intentionally do not respect \rightskip, since we need the space.
+  }%
+  %
+  % Allow all lines to be underfull without complaint:
+  \tolerance=10000 \hbadness=10000
+  \exdentamount=\defbodyindent
+  {%
+    % defun fonts. We use typewriter by default (used to be bold) because:
+    % . we're printing identifiers, they should be in tt in principle.
+    % . in languages with many accents, such as Czech or French, it's
+    %   common to leave accents off identifiers.  The result looks ok in
+    %   tt, but exceedingly strange in rm.
+    % . we don't want -- and --- to be treated as ligatures.
+    % . this still does not fix the ?` and !` ligatures, but so far no
+    %   one has made identifiers using them :).
+    \df \tt
+    \def\temp{#2}% return value type
+    \ifx\temp\empty\else \tclose{\temp} \fi
+    #3% output function name
+  }%
+  {\rm\enskip}% hskip 0.5 em of \tenrm
+  %
+  \boldbrax
+  % arguments will be output next, if any.
+}
+
+% Print arguments in slanted roman (not ttsl), inconsistently with using
+% tt for the name.  This is because literal text is sometimes needed in
+% the argument list (groff manual), and ttsl and tt are not very
+% distinguishable.  Prevent hyphenation at `-' chars.
+%
+\def\defunargs#1{%
+  % use sl by default (not ttsl),
+  % tt for the names.
+  \df \sl \hyphenchar\font=0
+  %
+  % On the other hand, if an argument has two dashes (for instance), we
+  % want a way to get ttsl.  Let's try @var for that.
+  \let\var=\ttslanted
+  #1%
+  \sl\hyphenchar\font=45
+}
+
+% We want ()&[] to print specially on the defun line.
+%
+\def\activeparens{%
+  \catcode`\(=\active \catcode`\)=\active
+  \catcode`\[=\active \catcode`\]=\active
+  \catcode`\&=\active
+}
+
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
+
+% Be sure that we always have a definition for `(', etc.  For example,
+% if the fn name has parens in it, \boldbrax will not be in effect yet,
+% so TeX would otherwise complain about undefined control sequence.
+{
+  \activeparens
+  \global\let(=\lparen \global\let)=\rparen
+  \global\let[=\lbrack \global\let]=\rbrack
+  \global\let& = \&
+
+  \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+  \gdef\magicamp{\let&=\amprm}
+}
+
+\newcount\parencount
+
+% If we encounter &foo, then turn on ()-hacking afterwards
+\newif\ifampseen
+\def\amprm#1 {\ampseentrue{\bf\&#1 }}
+
+\def\parenfont{%
+  \ifampseen
+    % At the first level, print parens in roman,
+    % otherwise use the default font.
+    \ifnum \parencount=1 \rm \fi
+  \else
+    % The \sf parens (in \boldbrax) actually are a little bolder than
+    % the contained text.  This is especially needed for [ and ] .
+    \sf
+  \fi
+}
+\def\infirstlevel#1{%
+  \ifampseen
+    \ifnum\parencount=1
+      #1%
+    \fi
+  \fi
+}
+\def\bfafterword#1 {#1 \bf}
+
+\def\opnr{%
+  \global\advance\parencount by 1
+  {\parenfont(}%
+  \infirstlevel \bfafterword
+}
+\def\clnr{%
+  {\parenfont)}%
+  \infirstlevel \sl
+  \global\advance\parencount by -1
+}
+
+\newcount\brackcount
+\def\lbrb{%
+  \global\advance\brackcount by 1
+  {\bf[}%
+}
+\def\rbrb{%
+  {\bf]}%
+  \global\advance\brackcount by -1
+}
+
+\def\checkparencounts{%
+  \ifnum\parencount=0 \else \badparencount \fi
+  \ifnum\brackcount=0 \else \badbrackcount \fi
+}
+% these should not use \errmessage; the glibc manual, at least, actually
+% has such constructs (when documenting function pointers).
+\def\badparencount{%
+  \message{Warning: unbalanced parentheses in @def...}%
+  \global\parencount=0
+}
+\def\badbrackcount{%
+  \message{Warning: unbalanced square brackets in @def...}%
+  \global\brackcount=0
+}
+
+
+\message{macros,}
+% @macro.
+
+% To do this right we need a feature of e-TeX, \scantokens,
+% which we arrange to emulate with a temporary file in ordinary TeX.
+\ifx\eTeXversion\undefined
+  \newwrite\macscribble
+  \def\scantokens#1{%
+    \toks0={#1}%
+    \immediate\openout\macscribble=\jobname.tmp
+    \immediate\write\macscribble{\the\toks0}%
+    \immediate\closeout\macscribble
+    \input \jobname.tmp
+  }
+\fi
+
+\def\scanmacro#1{%
+  \begingroup
+    \newlinechar`\^^M
+    \let\xeatspaces\eatspaces
+    % Undo catcode changes of \startcontents and \doprintindex
+    % When called from @insertcopying or (short)caption, we need active
+    % backslash to get it printed correctly.  Previously, we had
+    % \catcode`\\=\other instead.  We'll see whether a problem appears
+    % with macro expansion.                            --kasal, 19aug04
+    \catcode`\@=0 \catcode`\\=\active \escapechar=`\@
+    % ... and \example
+    \spaceisspace
+    %
+    % Append \endinput to make sure that TeX does not see the ending newline.
+    % I've verified that it is necessary both for e-TeX and for ordinary TeX
+    %                                                  --kasal, 29nov03
+    \scantokens{#1\endinput}%
+  \endgroup
+}
+
+\def\scanexp#1{%
+  \edef\temp{\noexpand\scanmacro{#1}}%
+  \temp
+}
+
+\newcount\paramno   % Count of parameters
+\newtoks\macname    % Macro name
+\newif\ifrecursive  % Is it recursive?
+
+% List of all defined macros in the form
+%    \definedummyword\macro1\definedummyword\macro2...
+% Currently is also contains all @aliases; the list can be split
+% if there is a need.
+\def\macrolist{}
+
+% Add the macro to \macrolist
+\def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname}
+\def\addtomacrolistxxx#1{%
+     \toks0 = \expandafter{\macrolist\definedummyword#1}%
+     \xdef\macrolist{\the\toks0}%
+}
+
+% Utility routines.
+% This does \let #1 = #2, with \csnames; that is,
+%   \let \csname#1\endcsname = \csname#2\endcsname
+% (except of course we have to play expansion games).
+% 
+\def\cslet#1#2{%
+  \expandafter\let
+  \csname#1\expandafter\endcsname
+  \csname#2\endcsname
+}
+
+% Trim leading and trailing spaces off a string.
+% Concepts from aro-bend problem 15 (see CTAN).
+{\catcode`\@=11
+\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }}
+\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@}
+\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @}
+\def\unbrace#1{#1}
+\unbrace{\gdef\trim@@@ #1 } #2@{#1}
+}
+
+% Trim a single trailing ^^M off a string.
+{\catcode`\^^M=\other \catcode`\Q=3%
+\gdef\eatcr #1{\eatcra #1Q^^MQ}%
+\gdef\eatcra#1^^MQ{\eatcrb#1Q}%
+\gdef\eatcrb#1Q#2Q{#1}%
+}
+
+% Macro bodies are absorbed as an argument in a context where
+% all characters are catcode 10, 11 or 12, except \ which is active
+% (as in normal texinfo). It is necessary to change the definition of \.
+
+% Non-ASCII encodings make 8-bit characters active, so un-activate
+% them to avoid their expansion.  Must do this non-globally, to
+% confine the change to the current group.
+
+% It's necessary to have hard CRs when the macro is executed. This is
+% done by  making ^^M (\endlinechar) catcode 12 when reading the macro
+% body, and then making it the \newlinechar in \scanmacro.
+
+\def\scanctxt{%
+  \catcode`\"=\other
+  \catcode`\+=\other
+  \catcode`\<=\other
+  \catcode`\>=\other
+  \catcode`\@=\other
+  \catcode`\^=\other
+  \catcode`\_=\other
+  \catcode`\|=\other
+  \catcode`\~=\other
+  \ifx\declaredencoding\ascii \else \setnonasciicharscatcodenonglobal\other \fi
+}
+
+\def\scanargctxt{%
+  \scanctxt
+  \catcode`\\=\other
+  \catcode`\^^M=\other
+}
+
+\def\macrobodyctxt{%
+  \scanctxt
+  \catcode`\{=\other
+  \catcode`\}=\other
+  \catcode`\^^M=\other
+  \usembodybackslash
+}
+
+\def\macroargctxt{%
+  \scanctxt
+  \catcode`\\=\other
+}
+
+% \mbodybackslash is the definition of \ in @macro bodies.
+% It maps \foo\ => \csname macarg.foo\endcsname => #N
+% where N is the macro parameter number.
+% We define \csname macarg.\endcsname to be \realbackslash, so
+% \\ in macro replacement text gets you a backslash.
+
+{\catcode`@=0 @catcode`@\=@active
+ @gdef@usembodybackslash{@let\=@mbodybackslash}
+ @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname}
+}
+\expandafter\def\csname macarg.\endcsname{\realbackslash}
+
+\def\macro{\recursivefalse\parsearg\macroxxx}
+\def\rmacro{\recursivetrue\parsearg\macroxxx}
+
+\def\macroxxx#1{%
+  \getargs{#1}%           now \macname is the macname and \argl the arglist
+  \ifx\argl\empty       % no arguments
+     \paramno=0%
+  \else
+     \expandafter\parsemargdef \argl;%
+  \fi
+  \if1\csname ismacro.\the\macname\endcsname
+     \message{Warning: redefining \the\macname}%
+  \else
+     \expandafter\ifx\csname \the\macname\endcsname \relax
+     \else \errmessage{Macro name \the\macname\space already defined}\fi
+     \global\cslet{macsave.\the\macname}{\the\macname}%
+     \global\expandafter\let\csname ismacro.\the\macname\endcsname=1%
+     \addtomacrolist{\the\macname}%
+  \fi
+  \begingroup \macrobodyctxt
+  \ifrecursive \expandafter\parsermacbody
+  \else \expandafter\parsemacbody
+  \fi}
+
+\parseargdef\unmacro{%
+  \if1\csname ismacro.#1\endcsname
+    \global\cslet{#1}{macsave.#1}%
+    \global\expandafter\let \csname ismacro.#1\endcsname=0%
+    % Remove the macro name from \macrolist:
+    \begingroup
+      \expandafter\let\csname#1\endcsname \relax
+      \let\definedummyword\unmacrodo
+      \xdef\macrolist{\macrolist}%
+    \endgroup
+  \else
+    \errmessage{Macro #1 not defined}%
+  \fi
+}
+
+% Called by \do from \dounmacro on each macro.  The idea is to omit any
+% macro definitions that have been changed to \relax.
+%
+\def\unmacrodo#1{%
+  \ifx #1\relax
+    % remove this
+  \else
+    \noexpand\definedummyword \noexpand#1%
+  \fi
+}
+
+% This makes use of the obscure feature that if the last token of a
+% <parameter list> is #, then the preceding argument is delimited by
+% an opening brace, and that opening brace is not consumed.
+\def\getargs#1{\getargsxxx#1{}}
+\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs}
+\def\getmacname #1 #2\relax{\macname={#1}}
+\def\getmacargs#1{\def\argl{#1}}
+
+% Parse the optional {params} list.  Set up \paramno and \paramlist
+% so \defmacro knows what to do.  Define \macarg.blah for each blah
+% in the params list, to be ##N where N is the position in that list.
+% That gets used by \mbodybackslash (above).
+
+% We need to get `macro parameter char #' into several definitions.
+% The technique used is stolen from LaTeX:  let \hash be something
+% unexpandable, insert that wherever you need a #, and then redefine
+% it to # just before using the token list produced.
+%
+% The same technique is used to protect \eatspaces till just before
+% the macro is used.
+
+\def\parsemargdef#1;{\paramno=0\def\paramlist{}%
+        \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,}
+\def\parsemargdefxxx#1,{%
+  \if#1;\let\next=\relax
+  \else \let\next=\parsemargdefxxx
+    \advance\paramno by 1%
+    \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname
+        {\xeatspaces{\hash\the\paramno}}%
+    \edef\paramlist{\paramlist\hash\the\paramno,}%
+  \fi\next}
+
+% These two commands read recursive and nonrecursive macro bodies.
+% (They're different since rec and nonrec macros end differently.)
+
+\long\def\parsemacbody#1@end macro%
+{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+\long\def\parsermacbody#1@end rmacro%
+{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+
+% This defines the macro itself. There are six cases: recursive and
+% nonrecursive macros of zero, one, and many arguments.
+% Much magic with \expandafter here.
+% \xdef is used so that macro definitions will survive the file
+% they're defined in; @include reads the file inside a group.
+\def\defmacro{%
+  \let\hash=##% convert placeholders to macro parameter chars
+  \ifrecursive
+    \ifcase\paramno
+    % 0
+      \expandafter\xdef\csname\the\macname\endcsname{%
+        \noexpand\scanmacro{\temp}}%
+    \or % 1
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \noexpand\braceorline
+         \expandafter\noexpand\csname\the\macname xxx\endcsname}%
+      \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
+         \egroup\noexpand\scanmacro{\temp}}%
+    \else % many
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \noexpand\csname\the\macname xx\endcsname}%
+      \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+          \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
+      \expandafter\expandafter
+      \expandafter\xdef
+      \expandafter\expandafter
+        \csname\the\macname xxx\endcsname
+          \paramlist{\egroup\noexpand\scanmacro{\temp}}%
+    \fi
+  \else
+    \ifcase\paramno
+    % 0
+      \expandafter\xdef\csname\the\macname\endcsname{%
+        \noexpand\norecurse{\the\macname}%
+        \noexpand\scanmacro{\temp}\egroup}%
+    \or % 1
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \noexpand\braceorline
+         \expandafter\noexpand\csname\the\macname xxx\endcsname}%
+      \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
+        \egroup
+        \noexpand\norecurse{\the\macname}%
+        \noexpand\scanmacro{\temp}\egroup}%
+    \else % many
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \expandafter\noexpand\csname\the\macname xx\endcsname}%
+      \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+          \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
+      \expandafter\expandafter
+      \expandafter\xdef
+      \expandafter\expandafter
+      \csname\the\macname xxx\endcsname
+      \paramlist{%
+          \egroup
+          \noexpand\norecurse{\the\macname}%
+          \noexpand\scanmacro{\temp}\egroup}%
+    \fi
+  \fi}
+
+\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}}
+
+% \braceorline decides whether the next nonwhitespace character is a
+% {.  If so it reads up to the closing }, if not, it reads the whole
+% line.  Whatever was read is then fed to the next control sequence
+% as an argument (by \parsebrace or \parsearg)
+\def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx}
+\def\braceorlinexxx{%
+  \ifx\nchar\bgroup\else
+    \expandafter\parsearg
+  \fi \macnamexxx}
+
+
+% @alias.
+% We need some trickery to remove the optional spaces around the equal
+% sign.  Just make them active and then expand them all to nothing.
+\def\alias{\parseargusing\obeyspaces\aliasxxx}
+\def\aliasxxx #1{\aliasyyy#1\relax}
+\def\aliasyyy #1=#2\relax{%
+  {%
+    \expandafter\let\obeyedspace=\empty
+    \addtomacrolist{#1}%
+    \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}%
+  }%
+  \next
+}
+
+
+\message{cross references,}
+
+\newwrite\auxfile
+\newif\ifhavexrefs    % True if xref values are known.
+\newif\ifwarnedxrefs  % True if we warned once that they aren't known.
+
+% @inforef is relatively simple.
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
+  node \samp{\ignorespaces#1{}}}
+
+% @node's only job in TeX is to define \lastnode, which is used in
+% cross-references.  The @node line might or might not have commas, and
+% might or might not have spaces before the first comma, like:
+% @node foo , bar , ...
+% We don't want such trailing spaces in the node name.
+%
+\parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse}
+%
+% also remove a trailing comma, in case of something like this:
+% @node Help-Cross,  ,  , Cross-refs
+\def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse}
+\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}}
+
+\let\nwnode=\node
+\let\lastnode=\empty
+
+% Write a cross-reference definition for the current node.  #1 is the
+% type (Ynumbered, Yappendix, Ynothing).
+%
+\def\donoderef#1{%
+  \ifx\lastnode\empty\else
+    \setref{\lastnode}{#1}%
+    \global\let\lastnode=\empty
+  \fi
+}
+
+% @anchor{NAME} -- define xref target at arbitrary point.
+%
+\newcount\savesfregister
+%
+\def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi}
+\def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi}
+\def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces}
+
+% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an
+% anchor), which consists of three parts:
+% 1) NAME-title - the current sectioning name taken from \lastsection,
+%                 or the anchor name.
+% 2) NAME-snt   - section number and type, passed as the SNT arg, or
+%                 empty for anchors.
+% 3) NAME-pg    - the page number.
+%
+% This is called from \donoderef, \anchor, and \dofloat.  In the case of
+% floats, there is an additional part, which is not written here:
+% 4) NAME-lof   - the text as it should appear in a @listoffloats.
+%
+\def\setref#1#2{%
+  \pdfmkdest{#1}%
+  \iflinks
+    {%
+      \atdummies  % preserve commands, but don't expand them
+      \edef\writexrdef##1##2{%
+       \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef
+         ##1}{##2}}% these are parameters of \writexrdef
+      }%
+      \toks0 = \expandafter{\lastsection}%
+      \immediate \writexrdef{title}{\the\toks0 }%
+      \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc.
+      \safewhatsit{\writexrdef{pg}{\folio}}% will be written later, during \shipout
+    }%
+  \fi
+}
+
+% @xref, @pxref, and @ref generate cross-references.  For \xrefX, #1 is
+% the node name, #2 the name of the Info cross-reference, #3 the printed
+% node name, #4 the name of the Info file, #5 the name of the printed
+% manual.  All but the node name can be omitted.
+%
+\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]}
+\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup
+  \unsepspaces
+  \def\printedmanual{\ignorespaces #5}%
+  \def\printedrefname{\ignorespaces #3}%
+  \setbox1=\hbox{\printedmanual\unskip}%
+  \setbox0=\hbox{\printedrefname\unskip}%
+  \ifdim \wd0 = 0pt
+    % No printed node name was explicitly given.
+    \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax
+      % Use the node name inside the square brackets.
+      \def\printedrefname{\ignorespaces #1}%
+    \else
+      % Use the actual chapter/section title appear inside
+      % the square brackets.  Use the real section title if we have it.
+      \ifdim \wd1 > 0pt
+        % It is in another manual, so we don't have it.
+        \def\printedrefname{\ignorespaces #1}%
+      \else
+        \ifhavexrefs
+          % We know the real title if we have the xref values.
+          \def\printedrefname{\refx{#1-title}{}}%
+        \else
+          % Otherwise just copy the Info node name.
+          \def\printedrefname{\ignorespaces #1}%
+        \fi%
+      \fi
+    \fi
+  \fi
+  %
+  % Make link in pdf output.
+  \ifpdf
+    \leavevmode
+    \getfilename{#4}%
+    {\indexnofonts
+     \turnoffactive
+     % See comments at \activebackslashdouble.
+     {\activebackslashdouble \xdef\pdfxrefdest{#1}%
+      \backslashparens\pdfxrefdest}%
+     %
+     \ifnum\filenamelength>0
+       \startlink attr{/Border [0 0 0]}%
+         goto file{\the\filename.pdf} name{\pdfxrefdest}%
+     \else
+       \startlink attr{/Border [0 0 0]}%
+         goto name{\pdfmkpgn{\pdfxrefdest}}%
+     \fi
+    }%
+    \setcolor{\linkcolor}%
+  \fi
+  %
+  % Float references are printed completely differently: "Figure 1.2"
+  % instead of "[somenode], p.3".  We distinguish them by the
+  % LABEL-title being set to a magic string.
+  {%
+    % Have to otherify everything special to allow the \csname to
+    % include an _ in the xref name, etc.
+    \indexnofonts
+    \turnoffactive
+    \expandafter\global\expandafter\let\expandafter\Xthisreftitle
+      \csname XR#1-title\endcsname
+  }%
+  \iffloat\Xthisreftitle
+    % If the user specified the print name (third arg) to the ref,
+    % print it instead of our usual "Figure 1.2".
+    \ifdim\wd0 = 0pt
+      \refx{#1-snt}{}%
+    \else
+      \printedrefname
+    \fi
+    %
+    % if the user also gave the printed manual name (fifth arg), append
+    % "in MANUALNAME".
+    \ifdim \wd1 > 0pt
+      \space \putwordin{} \cite{\printedmanual}%
+    \fi
+  \else
+    % node/anchor (non-float) references.
+    %
+    % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not
+    % insert empty discretionaries after hyphens, which means that it will
+    % not find a line break at a hyphen in a node names.  Since some manuals
+    % are best written with fairly long node names, containing hyphens, this
+    % is a loss.  Therefore, we give the text of the node name again, so it
+    % is as if TeX is seeing it for the first time.
+    \ifdim \wd1 > 0pt
+      \putwordSection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}%
+    \else
+      % _ (for example) has to be the character _ for the purposes of the
+      % control sequence corresponding to the node, but it has to expand
+      % into the usual \leavevmode...\vrule stuff for purposes of
+      % printing. So we \turnoffactive for the \refx-snt, back on for the
+      % printing, back off for the \refx-pg.
+      {\turnoffactive
+       % Only output a following space if the -snt ref is nonempty; for
+       % @unnumbered and @anchor, it won't be.
+       \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}%
+       \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi
+      }%
+      % output the `[mynode]' via a macro so it can be overridden.
+      \xrefprintnodename\printedrefname
+      %
+      % But we always want a comma and a space:
+      ,\space
+      %
+      % output the `page 3'.
+      \turnoffactive \putwordpage\tie\refx{#1-pg}{}%
+    \fi
+  \fi
+  \endlink
+\endgroup}
+
+% This macro is called from \xrefX for the `[nodename]' part of xref
+% output.  It's a separate macro only so it can be changed more easily,
+% since square brackets don't work well in some documents.  Particularly
+% one that Bob is working on :).
+%
+\def\xrefprintnodename#1{[#1]}
+
+% Things referred to by \setref.
+%
+\def\Ynothing{}
+\def\Yomitfromtoc{}
+\def\Ynumbered{%
+  \ifnum\secno=0
+    \putwordChapter@tie \the\chapno
+  \else \ifnum\subsecno=0
+    \putwordSection@tie \the\chapno.\the\secno
+  \else \ifnum\subsubsecno=0
+    \putwordSection@tie \the\chapno.\the\secno.\the\subsecno
+  \else
+    \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno
+  \fi\fi\fi
+}
+\def\Yappendix{%
+  \ifnum\secno=0
+     \putwordAppendix@tie @char\the\appendixno{}%
+  \else \ifnum\subsecno=0
+     \putwordSection@tie @char\the\appendixno.\the\secno
+  \else \ifnum\subsubsecno=0
+    \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno
+  \else
+    \putwordSection@tie
+      @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno
+  \fi\fi\fi
+}
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+%
+\def\refx#1#2{%
+  {%
+    \indexnofonts
+    \otherbackslash
+    \expandafter\global\expandafter\let\expandafter\thisrefX
+      \csname XR#1\endcsname
+  }%
+  \ifx\thisrefX\relax
+    % If not defined, say something at least.
+    \angleleft un\-de\-fined\angleright
+    \iflinks
+      \ifhavexrefs
+        \message{\linenumber Undefined cross reference `#1'.}%
+      \else
+        \ifwarnedxrefs\else
+          \global\warnedxrefstrue
+          \message{Cross reference values unknown; you must run TeX again.}%
+        \fi
+      \fi
+    \fi
+  \else
+    % It's defined, so just use it.
+    \thisrefX
+  \fi
+  #2% Output the suffix in any case.
+}
+
+% This is the macro invoked by entries in the aux file.  Usually it's
+% just a \def (we prepend XR to the control sequence name to avoid
+% collisions).  But if this is a float type, we have more work to do.
+%
+\def\xrdef#1#2{%
+  {% The node name might contain 8-bit characters, which in our current
+   % implementation are changed to commands like @'e.  Don't let these
+   % mess up the control sequence name.
+    \indexnofonts
+    \turnoffactive
+    \xdef\safexrefname{#1}%
+  }%
+  %
+  \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% remember this xref
+  %
+  % Was that xref control sequence that we just defined for a float?
+  \expandafter\iffloat\csname XR\safexrefname\endcsname
+    % it was a float, and we have the (safe) float type in \iffloattype.
+    \expandafter\let\expandafter\floatlist
+      \csname floatlist\iffloattype\endcsname
+    %
+    % Is this the first time we've seen this float type?
+    \expandafter\ifx\floatlist\relax
+      \toks0 = {\do}% yes, so just \do
+    \else
+      % had it before, so preserve previous elements in list.
+      \toks0 = \expandafter{\floatlist\do}%
+    \fi
+    %
+    % Remember this xref in the control sequence \floatlistFLOATTYPE,
+    % for later use in \listoffloats.
+    \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0
+      {\safexrefname}}%
+  \fi
+}
+
+% Read the last existing aux file, if any.  No error if none exists.
+%
+\def\tryauxfile{%
+  \openin 1 \jobname.aux
+  \ifeof 1 \else
+    \readdatafile{aux}%
+    \global\havexrefstrue
+  \fi
+  \closein 1
+}
+
+\def\setupdatafile{%
+  \catcode`\^^@=\other
+  \catcode`\^^A=\other
+  \catcode`\^^B=\other
+  \catcode`\^^C=\other
+  \catcode`\^^D=\other
+  \catcode`\^^E=\other
+  \catcode`\^^F=\other
+  \catcode`\^^G=\other
+  \catcode`\^^H=\other
+  \catcode`\^^K=\other
+  \catcode`\^^L=\other
+  \catcode`\^^N=\other
+  \catcode`\^^P=\other
+  \catcode`\^^Q=\other
+  \catcode`\^^R=\other
+  \catcode`\^^S=\other
+  \catcode`\^^T=\other
+  \catcode`\^^U=\other
+  \catcode`\^^V=\other
+  \catcode`\^^W=\other
+  \catcode`\^^X=\other
+  \catcode`\^^Z=\other
+  \catcode`\^^[=\other
+  \catcode`\^^\=\other
+  \catcode`\^^]=\other
+  \catcode`\^^^=\other
+  \catcode`\^^_=\other
+  % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc.
+  % in xref tags, i.e., node names.  But since ^^e4 notation isn't
+  % supported in the main text, it doesn't seem desirable.  Furthermore,
+  % that is not enough: for node names that actually contain a ^
+  % character, we would end up writing a line like this: 'xrdef {'hat
+  % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first
+  % argument, and \hat is not an expandable control sequence.  It could
+  % all be worked out, but why?  Either we support ^^ or we don't.
+  %
+  % The other change necessary for this was to define \auxhat:
+  % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter
+  % and then to call \auxhat in \setq.
+  %
+  \catcode`\^=\other
+  %
+  % Special characters.  Should be turned off anyway, but...
+  \catcode`\~=\other
+  \catcode`\[=\other
+  \catcode`\]=\other
+  \catcode`\"=\other
+  \catcode`\_=\other
+  \catcode`\|=\other
+  \catcode`\<=\other
+  \catcode`\>=\other
+  \catcode`\$=\other
+  \catcode`\#=\other
+  \catcode`\&=\other
+  \catcode`\%=\other
+  \catcode`+=\other % avoid \+ for paranoia even though we've turned it off
+  %
+  % This is to support \ in node names and titles, since the \
+  % characters end up in a \csname.  It's easier than
+  % leaving it active and making its active definition an actual \
+  % character.  What I don't understand is why it works in the *value*
+  % of the xrdef.  Seems like it should be a catcode12 \, and that
+  % should not typeset properly.  But it works, so I'm moving on for
+  % now.  --karl, 15jan04.
+  \catcode`\\=\other
+  %
+  % Make the characters 128-255 be printing characters.
+  {%
+    \count1=128
+    \def\loop{%
+      \catcode\count1=\other
+      \advance\count1 by 1
+      \ifnum \count1<256 \loop \fi
+    }%
+  }%
+  %
+  % @ is our escape character in .aux files, and we need braces.
+  \catcode`\{=1
+  \catcode`\}=2
+  \catcode`\@=0
+}
+
+\def\readdatafile#1{%
+\begingroup
+  \setupdatafile
+  \input\jobname.#1
+\endgroup}
+
+
+\message{insertions,}
+% including footnotes.
+
+\newcount \footnoteno
+
+% The trailing space in the following definition for supereject is
+% vital for proper filling; pages come out unaligned when you do a
+% pagealignmacro call if that space before the closing brace is
+% removed. (Generally, numeric constants should always be followed by a
+% space to prevent strange expansion errors.)
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only.
+\let\footnotestyle=\comment
+
+{\catcode `\@=11
+%
+% Auto-number footnotes.  Otherwise like plain.
+\gdef\footnote{%
+  \let\indent=\ptexindent
+  \let\noindent=\ptexnoindent
+  \global\advance\footnoteno by \@ne
+  \edef\thisfootno{$^{\the\footnoteno}$}%
+  %
+  % In case the footnote comes at the end of a sentence, preserve the
+  % extra spacing after we do the footnote number.
+  \let\@sf\empty
+  \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi
+  %
+  % Remove inadvertent blank space before typesetting the footnote number.
+  \unskip
+  \thisfootno\@sf
+  \dofootnote
+}%
+
+% Don't bother with the trickery in plain.tex to not require the
+% footnote text as a parameter.  Our footnotes don't need to be so general.
+%
+% Oh yes, they do; otherwise, @ifset (and anything else that uses
+% \parseargline) fails inside footnotes because the tokens are fixed when
+% the footnote is read.  --karl, 16nov96.
+%
+\gdef\dofootnote{%
+  \insert\footins\bgroup
+  % We want to typeset this text as a normal paragraph, even if the
+  % footnote reference occurs in (for example) a display environment.
+  % So reset some parameters.
+  \hsize=\pagewidth
+  \interlinepenalty\interfootnotelinepenalty
+  \splittopskip\ht\strutbox % top baseline for broken footnotes
+  \splitmaxdepth\dp\strutbox
+  \floatingpenalty\@MM
+  \leftskip\z@skip
+  \rightskip\z@skip
+  \spaceskip\z@skip
+  \xspaceskip\z@skip
+  \parindent\defaultparindent
+  %
+  \smallfonts \rm
+  %
+  % Because we use hanging indentation in footnotes, a @noindent appears
+  % to exdent this text, so make it be a no-op.  makeinfo does not use
+  % hanging indentation so @noindent can still be needed within footnote
+  % text after an @example or the like (not that this is good style).
+  \let\noindent = \relax
+  %
+  % Hang the footnote text off the number.  Use \everypar in case the
+  % footnote extends for more than one paragraph.
+  \everypar = {\hang}%
+  \textindent{\thisfootno}%
+  %
+  % Don't crash into the line above the footnote text.  Since this
+  % expands into a box, it must come within the paragraph, lest it
+  % provide a place where TeX can split the footnote.
+  \footstrut
+  \futurelet\next\fo@t
+}
+}%end \catcode `\@=11
+
+% In case a @footnote appears in a vbox, save the footnote text and create
+% the real \insert just after the vbox finished.  Otherwise, the insertion
+% would be lost.
+% Similarily, if a @footnote appears inside an alignment, save the footnote
+% text to a box and make the \insert when a row of the table is finished.
+% And the same can be done for other insert classes.  --kasal, 16nov03.
+
+% Replace the \insert primitive by a cheating macro.
+% Deeper inside, just make sure that the saved insertions are not spilled
+% out prematurely.
+%
+\def\startsavinginserts{%
+  \ifx \insert\ptexinsert
+    \let\insert\saveinsert
+  \else
+    \let\checkinserts\relax
+  \fi
+}
+
+% This \insert replacement works for both \insert\footins{foo} and
+% \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}.
+%
+\def\saveinsert#1{%
+  \edef\next{\noexpand\savetobox \makeSAVEname#1}%
+  \afterassignment\next
+  % swallow the left brace
+  \let\temp =
+}
+\def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}}
+\def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1}
+
+\def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi}
+
+\def\placesaveins#1{%
+  \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname
+    {\box#1}%
+}
+
+% eat @SAVE -- beware, all of them have catcode \other:
+{
+  \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials  %  ;-)
+  \gdef\gobblesave @SAVE{}
+}
+
+% initialization:
+\def\newsaveins #1{%
+  \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}%
+  \next
+}
+\def\newsaveinsX #1{%
+  \csname newbox\endcsname #1%
+  \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts
+    \checksaveins #1}%
+}
+
+% initialize:
+\let\checkinserts\empty
+\newsaveins\footins
+\newsaveins\margin
+
+
+% @image.  We use the macros from epsf.tex to support this.
+% If epsf.tex is not installed and @image is used, we complain.
+%
+% Check for and read epsf.tex up front.  If we read it only at @image
+% time, we might be inside a group, and then its definitions would get
+% undone and the next image would fail.
+\openin 1 = epsf.tex
+\ifeof 1 \else
+  % Do not bother showing banner with epsf.tex v2.7k (available in
+  % doc/epsf.tex and on ctan).
+  \def\epsfannounce{\toks0 = }%
+  \input epsf.tex
+\fi
+\closein 1
+%
+% We will only complain once about lack of epsf.tex.
+\newif\ifwarnednoepsf
+\newhelp\noepsfhelp{epsf.tex must be installed for images to
+  work.  It is also included in the Texinfo distribution, or you can get
+  it from ftp://tug.org/tex/epsf.tex.}
+%
+\def\image#1{%
+  \ifx\epsfbox\undefined
+    \ifwarnednoepsf \else
+      \errhelp = \noepsfhelp
+      \errmessage{epsf.tex not found, images will be ignored}%
+      \global\warnednoepsftrue
+    \fi
+  \else
+    \imagexxx #1,,,,,\finish
+  \fi
+}
+%
+% Arguments to @image:
+% #1 is (mandatory) image filename; we tack on .eps extension.
+% #2 is (optional) width, #3 is (optional) height.
+% #4 is (ignored optional) html alt text.
+% #5 is (ignored optional) extension.
+% #6 is just the usual extra ignored arg for parsing this stuff.
+\newif\ifimagevmode
+\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup
+  \catcode`\^^M = 5     % in case we're inside an example
+  \normalturnoffactive  % allow _ et al. in names
+  % If the image is by itself, center it.
+  \ifvmode
+    \imagevmodetrue
+    \nobreak\bigskip
+    % Usually we'll have text after the image which will insert
+    % \parskip glue, so insert it here too to equalize the space
+    % above and below.
+    \nobreak\vskip\parskip
+    \nobreak
+    \line\bgroup
+  \fi
+  %
+  % Output the image.
+  \ifpdf
+    \dopdfimage{#1}{#2}{#3}%
+  \else
+    % \epsfbox itself resets \epsf?size at each figure.
+    \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi
+    \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi
+    \epsfbox{#1.eps}%
+  \fi
+  %
+  \ifimagevmode \egroup \bigbreak \fi  % space after the image
+\endgroup}
+
+
+% @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables,
+% etc.  We don't actually implement floating yet, we always include the
+% float "here".  But it seemed the best name for the future.
+%
+\envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish}
+
+% There may be a space before second and/or third parameter; delete it.
+\def\eatcommaspace#1, {#1,}
+
+% #1 is the optional FLOATTYPE, the text label for this float, typically
+% "Figure", "Table", "Example", etc.  Can't contain commas.  If omitted,
+% this float will not be numbered and cannot be referred to.
+%
+% #2 is the optional xref label.  Also must be present for the float to
+% be referable.
+%
+% #3 is the optional positioning argument; for now, it is ignored.  It
+% will somehow specify the positions allowed to float to (here, top, bottom).
+%
+% We keep a separate counter for each FLOATTYPE, which we reset at each
+% chapter-level command.
+\let\resetallfloatnos=\empty
+%
+\def\dofloat#1,#2,#3,#4\finish{%
+  \let\thiscaption=\empty
+  \let\thisshortcaption=\empty
+  %
+  % don't lose footnotes inside @float.
+  %
+  % BEWARE: when the floats start float, we have to issue warning whenever an
+  % insert appears inside a float which could possibly float. --kasal, 26may04
+  %
+  \startsavinginserts
+  %
+  % We can't be used inside a paragraph.
+  \par
+  %
+  \vtop\bgroup
+    \def\floattype{#1}%
+    \def\floatlabel{#2}%
+    \def\floatloc{#3}% we do nothing with this yet.
+    %
+    \ifx\floattype\empty
+      \let\safefloattype=\empty
+    \else
+      {%
+        % the floattype might have accents or other special characters,
+        % but we need to use it in a control sequence name.
+        \indexnofonts
+        \turnoffactive
+        \xdef\safefloattype{\floattype}%
+      }%
+    \fi
+    %
+    % If label is given but no type, we handle that as the empty type.
+    \ifx\floatlabel\empty \else
+      % We want each FLOATTYPE to be numbered separately (Figure 1,
+      % Table 1, Figure 2, ...).  (And if no label, no number.)
+      %
+      \expandafter\getfloatno\csname\safefloattype floatno\endcsname
+      \global\advance\floatno by 1
+      %
+      {%
+        % This magic value for \lastsection is output by \setref as the
+        % XREFLABEL-title value.  \xrefX uses it to distinguish float
+        % labels (which have a completely different output format) from
+        % node and anchor labels.  And \xrdef uses it to construct the
+        % lists of floats.
+        %
+        \edef\lastsection{\floatmagic=\safefloattype}%
+        \setref{\floatlabel}{Yfloat}%
+      }%
+    \fi
+    %
+    % start with \parskip glue, I guess.
+    \vskip\parskip
+    %
+    % Don't suppress indentation if a float happens to start a section.
+    \restorefirstparagraphindent
+}
+
+% we have these possibilities:
+% @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap
+% @float Foo,lbl & no caption:    Foo 1.1
+% @float Foo & @caption{Cap}:     Foo: Cap
+% @float Foo & no caption:        Foo
+% @float ,lbl & Caption{Cap}:     1.1: Cap
+% @float ,lbl & no caption:       1.1
+% @float & @caption{Cap}:         Cap
+% @float & no caption:
+%
+\def\Efloat{%
+    \let\floatident = \empty
+    %
+    % In all cases, if we have a float type, it comes first.
+    \ifx\floattype\empty \else \def\floatident{\floattype}\fi
+    %
+    % If we have an xref label, the number comes next.
+    \ifx\floatlabel\empty \else
+      \ifx\floattype\empty \else % if also had float type, need tie first.
+        \appendtomacro\floatident{\tie}%
+      \fi
+      % the number.
+      \appendtomacro\floatident{\chaplevelprefix\the\floatno}%
+    \fi
+    %
+    % Start the printed caption with what we've constructed in
+    % \floatident, but keep it separate; we need \floatident again.
+    \let\captionline = \floatident
+    %
+    \ifx\thiscaption\empty \else
+      \ifx\floatident\empty \else
+       \appendtomacro\captionline{: }% had ident, so need a colon between
+      \fi
+      %
+      % caption text.
+      \appendtomacro\captionline{\scanexp\thiscaption}%
+    \fi
+    %
+    % If we have anything to print, print it, with space before.
+    % Eventually this needs to become an \insert.
+    \ifx\captionline\empty \else
+      \vskip.5\parskip
+      \captionline
+      %
+      % Space below caption.
+      \vskip\parskip
+    \fi
+    %
+    % If have an xref label, write the list of floats info.  Do this
+    % after the caption, to avoid chance of it being a breakpoint.
+    \ifx\floatlabel\empty \else
+      % Write the text that goes in the lof to the aux file as
+      % \floatlabel-lof.  Besides \floatident, we include the short
+      % caption if specified, else the full caption if specified, else nothing.
+      {%
+        \atdummies
+        %
+        % since we read the caption text in the macro world, where ^^M
+        % is turned into a normal character, we have to scan it back, so
+        % we don't write the literal three characters "^^M" into the aux file.
+       \scanexp{%
+         \xdef\noexpand\gtemp{%
+           \ifx\thisshortcaption\empty
+             \thiscaption
+           \else
+             \thisshortcaption
+           \fi
+         }%
+       }%
+        \immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident
+         \ifx\gtemp\empty \else : \gtemp \fi}}%
+      }%
+    \fi
+  \egroup  % end of \vtop
+  %
+  % place the captured inserts
+  %
+  % BEWARE: when the floats start floating, we have to issue warning
+  % whenever an insert appears inside a float which could possibly
+  % float. --kasal, 26may04
+  %
+  \checkinserts
+}
+
+% Append the tokens #2 to the definition of macro #1, not expanding either.
+%
+\def\appendtomacro#1#2{%
+  \expandafter\def\expandafter#1\expandafter{#1#2}%
+}
+
+% @caption, @shortcaption
+%
+\def\caption{\docaption\thiscaption}
+\def\shortcaption{\docaption\thisshortcaption}
+\def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption}
+\def\defcaption#1#2{\egroup \def#1{#2}}
+
+% The parameter is the control sequence identifying the counter we are
+% going to use.  Create it if it doesn't exist and assign it to \floatno.
+\def\getfloatno#1{%
+  \ifx#1\relax
+      % Haven't seen this figure type before.
+      \csname newcount\endcsname #1%
+      %
+      % Remember to reset this floatno at the next chap.
+      \expandafter\gdef\expandafter\resetallfloatnos
+        \expandafter{\resetallfloatnos #1=0 }%
+  \fi
+  \let\floatno#1%
+}
+
+% \setref calls this to get the XREFLABEL-snt value.  We want an @xref
+% to the FLOATLABEL to expand to "Figure 3.1".  We call \setref when we
+% first read the @float command.
+%
+\def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}%
+
+% Magic string used for the XREFLABEL-title value, so \xrefX can
+% distinguish floats from other xref types.
+\def\floatmagic{!!float!!}
+
+% #1 is the control sequence we are passed; we expand into a conditional
+% which is true if #1 represents a float ref.  That is, the magic
+% \lastsection value which we \setref above.
+%
+\def\iffloat#1{\expandafter\doiffloat#1==\finish}
+%
+% #1 is (maybe) the \floatmagic string.  If so, #2 will be the
+% (safe) float type for this float.  We set \iffloattype to #2.
+%
+\def\doiffloat#1=#2=#3\finish{%
+  \def\temp{#1}%
+  \def\iffloattype{#2}%
+  \ifx\temp\floatmagic
+}
+
+% @listoffloats FLOATTYPE - print a list of floats like a table of contents.
+%
+\parseargdef\listoffloats{%
+  \def\floattype{#1}% floattype
+  {%
+    % the floattype might have accents or other special characters,
+    % but we need to use it in a control sequence name.
+    \indexnofonts
+    \turnoffactive
+    \xdef\safefloattype{\floattype}%
+  }%
+  %
+  % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE.
+  \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax
+    \ifhavexrefs
+      % if the user said @listoffloats foo but never @float foo.
+      \message{\linenumber No `\safefloattype' floats to list.}%
+    \fi
+  \else
+    \begingroup
+      \leftskip=\tocindent  % indent these entries like a toc
+      \let\do=\listoffloatsdo
+      \csname floatlist\safefloattype\endcsname
+    \endgroup
+  \fi
+}
+
+% This is called on each entry in a list of floats.  We're passed the
+% xref label, in the form LABEL-title, which is how we save it in the
+% aux file.  We strip off the -title and look up \XRLABEL-lof, which
+% has the text we're supposed to typeset here.
+%
+% Figures without xref labels will not be included in the list (since
+% they won't appear in the aux file).
+%
+\def\listoffloatsdo#1{\listoffloatsdoentry#1\finish}
+\def\listoffloatsdoentry#1-title\finish{{%
+  % Can't fully expand XR#1-lof because it can contain anything.  Just
+  % pass the control sequence.  On the other hand, XR#1-pg is just the
+  % page number, and we want to fully expand that so we can get a link
+  % in pdf output.
+  \toksA = \expandafter{\csname XR#1-lof\endcsname}%
+  %
+  % use the same \entry macro we use to generate the TOC and index.
+  \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}%
+  \writeentry
+}}
+
+
+\message{localization,}
+
+% @documentlanguage is usually given very early, just after
+% @setfilename.  If done too late, it may not override everything
+% properly.  Single argument is the language (de) or locale (de_DE)
+% abbreviation.  It would be nice if we could set up a hyphenation file.
+%
+{
+  \catcode`\_ = \active
+  \globaldefs=1
+\parseargdef\documentlanguage{\begingroup
+  \let_=\normalunderscore  % normal _ character for filenames
+  \tex % read txi-??.tex file in plain TeX.
+    % Read the file by the name they passed if it exists.
+    \openin 1 txi-#1.tex
+    \ifeof 1
+      \documentlanguagetrywithoutunderscore{#1_\finish}%
+    \else
+      \input txi-#1.tex
+    \fi
+    \closein 1
+  \endgroup
+\endgroup}
+}
+%
+% If they passed de_DE, and txi-de_DE.tex doesn't exist,
+% try txi-de.tex.
+% 
+\def\documentlanguagetrywithoutunderscore#1_#2\finish{%
+  \openin 1 txi-#1.tex
+  \ifeof 1
+    \errhelp = \nolanghelp
+    \errmessage{Cannot read language file txi-#1.tex}%
+  \else
+    \input txi-#1.tex
+  \fi
+  \closein 1
+}
+%
+\newhelp\nolanghelp{The given language definition file cannot be found or
+is empty.  Maybe you need to install it?  In the current directory
+should work if nowhere else does.}
+
+% Set the catcode of characters 128 through 255 to the specified number.
+%
+\def\setnonasciicharscatcode#1{%
+   \count255=128
+   \loop\ifnum\count255<256
+      \global\catcode\count255=#1\relax
+      \advance\count255 by 1
+   \repeat
+}
+
+\def\setnonasciicharscatcodenonglobal#1{%
+   \count255=128
+   \loop\ifnum\count255<256
+      \catcode\count255=#1\relax
+      \advance\count255 by 1
+   \repeat
+}
+
+% @documentencoding sets the definition of non-ASCII characters
+% according to the specified encoding.
+%
+\parseargdef\documentencoding{%
+  % Encoding being declared for the document.
+  \def\declaredencoding{\csname #1.enc\endcsname}%
+  %
+  % Supported encodings: names converted to tokens in order to be able
+  % to compare them with \ifx.
+  \def\ascii{\csname US-ASCII.enc\endcsname}%
+  \def\latnine{\csname ISO-8859-15.enc\endcsname}%
+  \def\latone{\csname ISO-8859-1.enc\endcsname}%
+  \def\lattwo{\csname ISO-8859-2.enc\endcsname}%
+  \def\utfeight{\csname UTF-8.enc\endcsname}%
+  %
+  \ifx \declaredencoding \ascii
+     \asciichardefs
+  %
+  \else \ifx \declaredencoding \lattwo
+     \setnonasciicharscatcode\active
+     \lattwochardefs
+  %
+  \else \ifx \declaredencoding \latone 
+     \setnonasciicharscatcode\active
+     \latonechardefs
+  %
+  \else \ifx \declaredencoding \latnine
+     \setnonasciicharscatcode\active
+     \latninechardefs
+  %
+  \else \ifx \declaredencoding \utfeight
+     \setnonasciicharscatcode\active
+     \utfeightchardefs
+  %
+  \else 
+    \message{Unknown document encoding #1, ignoring.}%
+  %
+  \fi % utfeight
+  \fi % latnine
+  \fi % latone
+  \fi % lattwo
+  \fi % ascii
+}
+
+% A message to be logged when using a character that isn't available
+% the default font encoding (OT1).
+% 
+\def\missingcharmsg#1{\message{Character missing in OT1 encoding: #1.}}
+
+% Take account of \c (plain) vs. \, (Texinfo) difference.
+\def\cedilla#1{\ifx\c\ptexc\c{#1}\else\,{#1}\fi}
+
+% First, make active non-ASCII characters in order for them to be
+% correctly categorized when TeX reads the replacement text of
+% macros containing the character definitions.
+\setnonasciicharscatcode\active
+%
+% Latin1 (ISO-8859-1) character definitions.
+\def\latonechardefs{%
+  \gdef^^a0{~} 
+  \gdef^^a1{\exclamdown}
+  \gdef^^a2{\missingcharmsg{CENT SIGN}} 
+  \gdef^^a3{{\pounds}}
+  \gdef^^a4{\missingcharmsg{CURRENCY SIGN}}
+  \gdef^^a5{\missingcharmsg{YEN SIGN}}
+  \gdef^^a6{\missingcharmsg{BROKEN BAR}} 
+  \gdef^^a7{\S}
+  \gdef^^a8{\"{}} 
+  \gdef^^a9{\copyright} 
+  \gdef^^aa{\ordf}
+  \gdef^^ab{\missingcharmsg{LEFT-POINTING DOUBLE ANGLE QUOTATION MARK}} 
+  \gdef^^ac{$\lnot$}
+  \gdef^^ad{\-} 
+  \gdef^^ae{\registeredsymbol} 
+  \gdef^^af{\={}}
+  %
+  \gdef^^b0{\textdegree}
+  \gdef^^b1{$\pm$}
+  \gdef^^b2{$^2$}
+  \gdef^^b3{$^3$}
+  \gdef^^b4{\'{}}
+  \gdef^^b5{$\mu$}
+  \gdef^^b6{\P}
+  %
+  \gdef^^b7{$^.$}
+  \gdef^^b8{\cedilla\ }
+  \gdef^^b9{$^1$}
+  \gdef^^ba{\ordm}
+  %
+  \gdef^^bb{\missingcharmsg{RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK}}
+  \gdef^^bc{$1\over4$}
+  \gdef^^bd{$1\over2$}
+  \gdef^^be{$3\over4$}
+  \gdef^^bf{\questiondown}
+  %
+  \gdef^^c0{\`A}
+  \gdef^^c1{\'A}
+  \gdef^^c2{\^A}
+  \gdef^^c3{\~A}
+  \gdef^^c4{\"A}
+  \gdef^^c5{\ringaccent A} 
+  \gdef^^c6{\AE}
+  \gdef^^c7{\cedilla C}
+  \gdef^^c8{\`E}
+  \gdef^^c9{\'E}
+  \gdef^^ca{\^E}
+  \gdef^^cb{\"E}
+  \gdef^^cc{\`I}
+  \gdef^^cd{\'I}
+  \gdef^^ce{\^I}
+  \gdef^^cf{\"I}
+  %
+  \gdef^^d0{\missingcharmsg{LATIN CAPITAL LETTER ETH}}
+  \gdef^^d1{\~N}
+  \gdef^^d2{\`O}
+  \gdef^^d3{\'O}
+  \gdef^^d4{\^O}
+  \gdef^^d5{\~O}
+  \gdef^^d6{\"O}
+  \gdef^^d7{$\times$}
+  \gdef^^d8{\O}
+  \gdef^^d9{\`U}
+  \gdef^^da{\'U}
+  \gdef^^db{\^U}
+  \gdef^^dc{\"U}
+  \gdef^^dd{\'Y}
+  \gdef^^de{\missingcharmsg{LATIN CAPITAL LETTER THORN}}
+  \gdef^^df{\ss}
+  %
+  \gdef^^e0{\`a}
+  \gdef^^e1{\'a}
+  \gdef^^e2{\^a}
+  \gdef^^e3{\~a}
+  \gdef^^e4{\"a}
+  \gdef^^e5{\ringaccent a}
+  \gdef^^e6{\ae}
+  \gdef^^e7{\cedilla c}
+  \gdef^^e8{\`e}
+  \gdef^^e9{\'e}
+  \gdef^^ea{\^e}
+  \gdef^^eb{\"e}
+  \gdef^^ec{\`{\dotless i}}
+  \gdef^^ed{\'{\dotless i}}
+  \gdef^^ee{\^{\dotless i}}
+  \gdef^^ef{\"{\dotless i}}
+  %
+  \gdef^^f0{\missingcharmsg{LATIN SMALL LETTER ETH}}
+  \gdef^^f1{\~n}
+  \gdef^^f2{\`o}
+  \gdef^^f3{\'o}
+  \gdef^^f4{\^o}
+  \gdef^^f5{\~o}
+  \gdef^^f6{\"o}
+  \gdef^^f7{$\div$}
+  \gdef^^f8{\o}
+  \gdef^^f9{\`u}
+  \gdef^^fa{\'u}
+  \gdef^^fb{\^u}
+  \gdef^^fc{\"u}
+  \gdef^^fd{\'y}
+  \gdef^^fe{\missingcharmsg{LATIN SMALL LETTER THORN}}
+  \gdef^^ff{\"y}
+}
+
+% Latin9 (ISO-8859-15) encoding character definitions.
+\def\latninechardefs{%
+  % Encoding is almost identical to Latin1.
+  \latonechardefs
+  %
+  \gdef^^a4{\euro}
+  \gdef^^a6{\v S}
+  \gdef^^a8{\v s}
+  \gdef^^b4{\v Z}
+  \gdef^^b8{\v z}
+  \gdef^^bc{\OE}
+  \gdef^^bd{\oe}
+  \gdef^^be{\"Y}
+}
+
+% Latin2 (ISO-8859-2) character definitions.
+\def\lattwochardefs{%
+  \gdef^^a0{~}
+  \gdef^^a1{\missingcharmsg{LATIN CAPITAL LETTER A WITH OGONEK}}
+  \gdef^^a2{\u{}}
+  \gdef^^a3{\L}
+  \gdef^^a4{\missingcharmsg{CURRENCY SIGN}}
+  \gdef^^a5{\v L}
+  \gdef^^a6{\'S}
+  \gdef^^a7{\S}
+  \gdef^^a8{\"{}}
+  \gdef^^a9{\v S}
+  \gdef^^aa{\cedilla S}
+  \gdef^^ab{\v T}
+  \gdef^^ac{\'Z}
+  \gdef^^ad{\-}
+  \gdef^^ae{\v Z}
+  \gdef^^af{\dotaccent Z}
+  %
+  \gdef^^b0{\textdegree}
+  \gdef^^b1{\missingcharmsg{LATIN SMALL LETTER A WITH OGONEK}}
+  \gdef^^b2{\missingcharmsg{OGONEK}}
+  \gdef^^b3{\l}
+  \gdef^^b4{\'{}}
+  \gdef^^b5{\v l}
+  \gdef^^b6{\'s}
+  \gdef^^b7{\v{}}
+  \gdef^^b8{\cedilla\ }
+  \gdef^^b9{\v s}
+  \gdef^^ba{\cedilla s}
+  \gdef^^bb{\v t}
+  \gdef^^bc{\'z}
+  \gdef^^bd{\H{}}
+  \gdef^^be{\v z}
+  \gdef^^bf{\dotaccent z}
+  %
+  \gdef^^c0{\'R}
+  \gdef^^c1{\'A}
+  \gdef^^c2{\^A}
+  \gdef^^c3{\u A}
+  \gdef^^c4{\"A}
+  \gdef^^c5{\'L}
+  \gdef^^c6{\'C}
+  \gdef^^c7{\cedilla C}
+  \gdef^^c8{\v C}
+  \gdef^^c9{\'E}
+  \gdef^^ca{\missingcharmsg{LATIN CAPITAL LETTER E WITH OGONEK}}
+  \gdef^^cb{\"E}
+  \gdef^^cc{\v E}
+  \gdef^^cd{\'I}
+  \gdef^^ce{\^I}
+  \gdef^^cf{\v D}
+  %
+  \gdef^^d0{\missingcharmsg{LATIN CAPITAL LETTER D WITH STROKE}}
+  \gdef^^d1{\'N}
+  \gdef^^d2{\v N}
+  \gdef^^d3{\'O}
+  \gdef^^d4{\^O}
+  \gdef^^d5{\H O}
+  \gdef^^d6{\"O}
+  \gdef^^d7{$\times$}
+  \gdef^^d8{\v R}
+  \gdef^^d9{\ringaccent U} 
+  \gdef^^da{\'U}
+  \gdef^^db{\H U}
+  \gdef^^dc{\"U}
+  \gdef^^dd{\'Y}
+  \gdef^^de{\cedilla T}
+  \gdef^^df{\ss}
+  %
+  \gdef^^e0{\'r}
+  \gdef^^e1{\'a}
+  \gdef^^e2{\^a}
+  \gdef^^e3{\u a}
+  \gdef^^e4{\"a}
+  \gdef^^e5{\'l}
+  \gdef^^e6{\'c}
+  \gdef^^e7{\cedilla c}
+  \gdef^^e8{\v c}
+  \gdef^^e9{\'e}
+  \gdef^^ea{\missingcharmsg{LATIN SMALL LETTER E WITH OGONEK}}
+  \gdef^^eb{\"e}
+  \gdef^^ec{\v e}
+  \gdef^^ed{\'\i}
+  \gdef^^ee{\^\i}
+  \gdef^^ef{\v d}
+  %
+  \gdef^^f0{\missingcharmsg{LATIN SMALL LETTER D WITH STROKE}}
+  \gdef^^f1{\'n}
+  \gdef^^f2{\v n}
+  \gdef^^f3{\'o}
+  \gdef^^f4{\^o}
+  \gdef^^f5{\H o}
+  \gdef^^f6{\"o}
+  \gdef^^f7{$\div$}
+  \gdef^^f8{\v r}
+  \gdef^^f9{\ringaccent u}
+  \gdef^^fa{\'u}
+  \gdef^^fb{\H u}
+  \gdef^^fc{\"u}
+  \gdef^^fd{\'y}
+  \gdef^^fe{\cedilla t}
+  \gdef^^ff{\dotaccent{}}
+}
+
+% UTF-8 character definitions.
+% 
+% This code to support UTF-8 is based on LaTeX's utf8.def, with some
+% changes for Texinfo conventions.  It is included here under the GPL by
+% permission from Frank Mittelbach and the LaTeX team.
+% 
+\newcount\countUTFx
+\newcount\countUTFy
+\newcount\countUTFz
+
+\gdef\UTFviiiTwoOctets#1#2{\expandafter
+   \UTFviiiDefined\csname u8:#1\string #2\endcsname}
+%
+\gdef\UTFviiiThreeOctets#1#2#3{\expandafter
+   \UTFviiiDefined\csname u8:#1\string #2\string #3\endcsname}
+%
+\gdef\UTFviiiFourOctets#1#2#3#4{\expandafter
+   \UTFviiiDefined\csname u8:#1\string #2\string #3\string #4\endcsname}
+
+\gdef\UTFviiiDefined#1{%
+  \ifx #1\relax
+    \message{\linenumber Unicode char \string #1 not defined for Texinfo}%
+  \else
+    \expandafter #1%
+  \fi
+}
+
+\begingroup
+  \catcode`\~13
+  \catcode`\"12
+
+  \def\UTFviiiLoop{%
+    \global\catcode\countUTFx\active
+    \uccode`\~\countUTFx
+    \uppercase\expandafter{\UTFviiiTmp}%
+    \advance\countUTFx by 1
+    \ifnum\countUTFx < \countUTFy
+      \expandafter\UTFviiiLoop
+    \fi}
+
+  \countUTFx = "C2
+  \countUTFy = "E0
+  \def\UTFviiiTmp{%
+    \xdef~{\noexpand\UTFviiiTwoOctets\string~}}
+  \UTFviiiLoop
+
+  \countUTFx = "E0
+  \countUTFy = "F0
+  \def\UTFviiiTmp{%
+    \xdef~{\noexpand\UTFviiiThreeOctets\string~}}
+  \UTFviiiLoop
+
+  \countUTFx = "F0
+  \countUTFy = "F4
+  \def\UTFviiiTmp{%
+    \xdef~{\noexpand\UTFviiiFourOctets\string~}}
+  \UTFviiiLoop
+\endgroup
+
+\begingroup
+  \catcode`\"=12
+  \catcode`\<=12
+  \catcode`\.=12
+  \catcode`\,=12
+  \catcode`\;=12
+  \catcode`\!=12
+  \catcode`\~=13
+
+  \gdef\DeclareUnicodeCharacter#1#2{%
+    \countUTFz = "#1\relax
+    \wlog{\space\space defining Unicode char U+#1 (decimal \the\countUTFz)}%
+    \begingroup
+      \parseXMLCharref
+      \def\UTFviiiTwoOctets##1##2{%
+        \csname u8:##1\string ##2\endcsname}%
+      \def\UTFviiiThreeOctets##1##2##3{%
+        \csname u8:##1\string ##2\string ##3\endcsname}%
+      \def\UTFviiiFourOctets##1##2##3##4{%
+        \csname u8:##1\string ##2\string ##3\string ##4\endcsname}%
+      \expandafter\expandafter\expandafter\expandafter
+       \expandafter\expandafter\expandafter
+       \gdef\UTFviiiTmp{#2}%
+    \endgroup}
+
+  \gdef\parseXMLCharref{%
+    \ifnum\countUTFz < "A0\relax
+      \errhelp = \EMsimple
+      \errmessage{Cannot define Unicode char value < 00A0}%
+    \else\ifnum\countUTFz < "800\relax
+      \parseUTFviiiA,%
+      \parseUTFviiiB C\UTFviiiTwoOctets.,%
+    \else\ifnum\countUTFz < "10000\relax
+      \parseUTFviiiA;%
+      \parseUTFviiiA,%
+      \parseUTFviiiB E\UTFviiiThreeOctets.{,;}%
+    \else
+      \parseUTFviiiA;%
+      \parseUTFviiiA,%
+      \parseUTFviiiA!%
+      \parseUTFviiiB F\UTFviiiFourOctets.{!,;}%
+    \fi\fi\fi
+  }
+
+  \gdef\parseUTFviiiA#1{%
+    \countUTFx = \countUTFz
+    \divide\countUTFz by 64
+    \countUTFy = \countUTFz
+    \multiply\countUTFz by 64
+    \advance\countUTFx by -\countUTFz
+    \advance\countUTFx by 128
+    \uccode `#1\countUTFx
+    \countUTFz = \countUTFy}
+
+  \gdef\parseUTFviiiB#1#2#3#4{%
+    \advance\countUTFz by "#10\relax
+    \uccode `#3\countUTFz
+    \uppercase{\gdef\UTFviiiTmp{#2#3#4}}}
+\endgroup
+
+\def\utfeightchardefs{%
+  \DeclareUnicodeCharacter{00A0}{\tie}
+  \DeclareUnicodeCharacter{00A1}{\exclamdown}
+  \DeclareUnicodeCharacter{00A3}{\pounds}
+  \DeclareUnicodeCharacter{00A8}{\"{ }}
+  \DeclareUnicodeCharacter{00A9}{\copyright}
+  \DeclareUnicodeCharacter{00AA}{\ordf}
+  \DeclareUnicodeCharacter{00AB}{\guillemetleft}
+  \DeclareUnicodeCharacter{00AD}{\-}
+  \DeclareUnicodeCharacter{00AE}{\registeredsymbol}
+  \DeclareUnicodeCharacter{00AF}{\={ }}
+
+  \DeclareUnicodeCharacter{00B0}{\ringaccent{ }}
+  \DeclareUnicodeCharacter{00B4}{\'{ }}
+  \DeclareUnicodeCharacter{00B8}{\cedilla{ }}
+  \DeclareUnicodeCharacter{00BA}{\ordm}
+  \DeclareUnicodeCharacter{00BB}{\guillemetright}
+  \DeclareUnicodeCharacter{00BF}{\questiondown}
+
+  \DeclareUnicodeCharacter{00C0}{\`A}
+  \DeclareUnicodeCharacter{00C1}{\'A}
+  \DeclareUnicodeCharacter{00C2}{\^A}
+  \DeclareUnicodeCharacter{00C3}{\~A}
+  \DeclareUnicodeCharacter{00C4}{\"A}
+  \DeclareUnicodeCharacter{00C5}{\AA}
+  \DeclareUnicodeCharacter{00C6}{\AE}
+  \DeclareUnicodeCharacter{00C7}{\cedilla{C}}
+  \DeclareUnicodeCharacter{00C8}{\`E}
+  \DeclareUnicodeCharacter{00C9}{\'E}
+  \DeclareUnicodeCharacter{00CA}{\^E}
+  \DeclareUnicodeCharacter{00CB}{\"E}
+  \DeclareUnicodeCharacter{00CC}{\`I}
+  \DeclareUnicodeCharacter{00CD}{\'I}
+  \DeclareUnicodeCharacter{00CE}{\^I}
+  \DeclareUnicodeCharacter{00CF}{\"I}
+
+  \DeclareUnicodeCharacter{00D1}{\~N}
+  \DeclareUnicodeCharacter{00D2}{\`O}
+  \DeclareUnicodeCharacter{00D3}{\'O}
+  \DeclareUnicodeCharacter{00D4}{\^O}
+  \DeclareUnicodeCharacter{00D5}{\~O}
+  \DeclareUnicodeCharacter{00D6}{\"O}
+  \DeclareUnicodeCharacter{00D8}{\O}
+  \DeclareUnicodeCharacter{00D9}{\`U}
+  \DeclareUnicodeCharacter{00DA}{\'U}
+  \DeclareUnicodeCharacter{00DB}{\^U}
+  \DeclareUnicodeCharacter{00DC}{\"U}
+  \DeclareUnicodeCharacter{00DD}{\'Y}
+  \DeclareUnicodeCharacter{00DF}{\ss}
+
+  \DeclareUnicodeCharacter{00E0}{\`a}
+  \DeclareUnicodeCharacter{00E1}{\'a}
+  \DeclareUnicodeCharacter{00E2}{\^a}
+  \DeclareUnicodeCharacter{00E3}{\~a}
+  \DeclareUnicodeCharacter{00E4}{\"a}
+  \DeclareUnicodeCharacter{00E5}{\aa}
+  \DeclareUnicodeCharacter{00E6}{\ae}
+  \DeclareUnicodeCharacter{00E7}{\cedilla{c}}
+  \DeclareUnicodeCharacter{00E8}{\`e}
+  \DeclareUnicodeCharacter{00E9}{\'e}
+  \DeclareUnicodeCharacter{00EA}{\^e}
+  \DeclareUnicodeCharacter{00EB}{\"e}
+  \DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}}
+  \DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}}
+  \DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}}
+  \DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}}
+
+  \DeclareUnicodeCharacter{00F1}{\~n}
+  \DeclareUnicodeCharacter{00F2}{\`o}
+  \DeclareUnicodeCharacter{00F3}{\'o}
+  \DeclareUnicodeCharacter{00F4}{\^o}
+  \DeclareUnicodeCharacter{00F5}{\~o}
+  \DeclareUnicodeCharacter{00F6}{\"o}
+  \DeclareUnicodeCharacter{00F8}{\o}
+  \DeclareUnicodeCharacter{00F9}{\`u}
+  \DeclareUnicodeCharacter{00FA}{\'u}
+  \DeclareUnicodeCharacter{00FB}{\^u}
+  \DeclareUnicodeCharacter{00FC}{\"u}
+  \DeclareUnicodeCharacter{00FD}{\'y}
+  \DeclareUnicodeCharacter{00FF}{\"y}
+
+  \DeclareUnicodeCharacter{0100}{\=A}
+  \DeclareUnicodeCharacter{0101}{\=a}
+  \DeclareUnicodeCharacter{0102}{\u{A}}
+  \DeclareUnicodeCharacter{0103}{\u{a}}
+  \DeclareUnicodeCharacter{0106}{\'C}
+  \DeclareUnicodeCharacter{0107}{\'c}
+  \DeclareUnicodeCharacter{0108}{\^C}
+  \DeclareUnicodeCharacter{0109}{\^c}
+  \DeclareUnicodeCharacter{010A}{\dotaccent{C}}
+  \DeclareUnicodeCharacter{010B}{\dotaccent{c}}
+  \DeclareUnicodeCharacter{010C}{\v{C}}
+  \DeclareUnicodeCharacter{010D}{\v{c}}
+  \DeclareUnicodeCharacter{010E}{\v{D}}
+
+  \DeclareUnicodeCharacter{0112}{\=E}
+  \DeclareUnicodeCharacter{0113}{\=e}
+  \DeclareUnicodeCharacter{0114}{\u{E}}
+  \DeclareUnicodeCharacter{0115}{\u{e}}
+  \DeclareUnicodeCharacter{0116}{\dotaccent{E}}
+  \DeclareUnicodeCharacter{0117}{\dotaccent{e}}
+  \DeclareUnicodeCharacter{011A}{\v{E}}
+  \DeclareUnicodeCharacter{011B}{\v{e}}
+  \DeclareUnicodeCharacter{011C}{\^G}
+  \DeclareUnicodeCharacter{011D}{\^g}
+  \DeclareUnicodeCharacter{011E}{\u{G}}
+  \DeclareUnicodeCharacter{011F}{\u{g}}
+
+  \DeclareUnicodeCharacter{0120}{\dotaccent{G}}
+  \DeclareUnicodeCharacter{0121}{\dotaccent{g}}
+  \DeclareUnicodeCharacter{0124}{\^H}
+  \DeclareUnicodeCharacter{0125}{\^h}
+  \DeclareUnicodeCharacter{0128}{\~I}
+  \DeclareUnicodeCharacter{0129}{\~{\dotless{i}}}
+  \DeclareUnicodeCharacter{012A}{\=I}
+  \DeclareUnicodeCharacter{012B}{\={\dotless{i}}}
+  \DeclareUnicodeCharacter{012C}{\u{I}}
+  \DeclareUnicodeCharacter{012D}{\u{\dotless{i}}}
+
+  \DeclareUnicodeCharacter{0130}{\dotaccent{I}}
+  \DeclareUnicodeCharacter{0131}{\dotless{i}}
+  \DeclareUnicodeCharacter{0132}{IJ}
+  \DeclareUnicodeCharacter{0133}{ij}
+  \DeclareUnicodeCharacter{0134}{\^J}
+  \DeclareUnicodeCharacter{0135}{\^{\dotless{j}}}
+  \DeclareUnicodeCharacter{0139}{\'L}
+  \DeclareUnicodeCharacter{013A}{\'l}
+
+  \DeclareUnicodeCharacter{0141}{\L}
+  \DeclareUnicodeCharacter{0142}{\l}
+  \DeclareUnicodeCharacter{0143}{\'N}
+  \DeclareUnicodeCharacter{0144}{\'n}
+  \DeclareUnicodeCharacter{0147}{\v{N}}
+  \DeclareUnicodeCharacter{0148}{\v{n}}
+  \DeclareUnicodeCharacter{014C}{\=O}
+  \DeclareUnicodeCharacter{014D}{\=o}
+  \DeclareUnicodeCharacter{014E}{\u{O}}
+  \DeclareUnicodeCharacter{014F}{\u{o}}
+
+  \DeclareUnicodeCharacter{0150}{\H{O}}
+  \DeclareUnicodeCharacter{0151}{\H{o}}
+  \DeclareUnicodeCharacter{0152}{\OE}
+  \DeclareUnicodeCharacter{0153}{\oe}
+  \DeclareUnicodeCharacter{0154}{\'R}
+  \DeclareUnicodeCharacter{0155}{\'r}
+  \DeclareUnicodeCharacter{0158}{\v{R}}
+  \DeclareUnicodeCharacter{0159}{\v{r}}
+  \DeclareUnicodeCharacter{015A}{\'S}
+  \DeclareUnicodeCharacter{015B}{\'s}
+  \DeclareUnicodeCharacter{015C}{\^S}
+  \DeclareUnicodeCharacter{015D}{\^s}
+  \DeclareUnicodeCharacter{015E}{\cedilla{S}}
+  \DeclareUnicodeCharacter{015F}{\cedilla{s}}
+
+  \DeclareUnicodeCharacter{0160}{\v{S}}
+  \DeclareUnicodeCharacter{0161}{\v{s}}
+  \DeclareUnicodeCharacter{0162}{\cedilla{t}}
+  \DeclareUnicodeCharacter{0163}{\cedilla{T}}
+  \DeclareUnicodeCharacter{0164}{\v{T}}
+
+  \DeclareUnicodeCharacter{0168}{\~U}
+  \DeclareUnicodeCharacter{0169}{\~u}
+  \DeclareUnicodeCharacter{016A}{\=U}
+  \DeclareUnicodeCharacter{016B}{\=u}
+  \DeclareUnicodeCharacter{016C}{\u{U}}
+  \DeclareUnicodeCharacter{016D}{\u{u}}
+  \DeclareUnicodeCharacter{016E}{\ringaccent{U}}
+  \DeclareUnicodeCharacter{016F}{\ringaccent{u}}
+
+  \DeclareUnicodeCharacter{0170}{\H{U}}
+  \DeclareUnicodeCharacter{0171}{\H{u}}
+  \DeclareUnicodeCharacter{0174}{\^W}
+  \DeclareUnicodeCharacter{0175}{\^w}
+  \DeclareUnicodeCharacter{0176}{\^Y}
+  \DeclareUnicodeCharacter{0177}{\^y}
+  \DeclareUnicodeCharacter{0178}{\"Y}
+  \DeclareUnicodeCharacter{0179}{\'Z}
+  \DeclareUnicodeCharacter{017A}{\'z}
+  \DeclareUnicodeCharacter{017B}{\dotaccent{Z}}
+  \DeclareUnicodeCharacter{017C}{\dotaccent{z}}
+  \DeclareUnicodeCharacter{017D}{\v{Z}}
+  \DeclareUnicodeCharacter{017E}{\v{z}}
+
+  \DeclareUnicodeCharacter{01C4}{D\v{Z}}
+  \DeclareUnicodeCharacter{01C5}{D\v{z}}
+  \DeclareUnicodeCharacter{01C6}{d\v{z}}
+  \DeclareUnicodeCharacter{01C7}{LJ}
+  \DeclareUnicodeCharacter{01C8}{Lj}
+  \DeclareUnicodeCharacter{01C9}{lj}
+  \DeclareUnicodeCharacter{01CA}{NJ}
+  \DeclareUnicodeCharacter{01CB}{Nj}
+  \DeclareUnicodeCharacter{01CC}{nj}
+  \DeclareUnicodeCharacter{01CD}{\v{A}}
+  \DeclareUnicodeCharacter{01CE}{\v{a}}
+  \DeclareUnicodeCharacter{01CF}{\v{I}}
+
+  \DeclareUnicodeCharacter{01D0}{\v{\dotless{i}}}
+  \DeclareUnicodeCharacter{01D1}{\v{O}}
+  \DeclareUnicodeCharacter{01D2}{\v{o}}
+  \DeclareUnicodeCharacter{01D3}{\v{U}}
+  \DeclareUnicodeCharacter{01D4}{\v{u}}
+
+  \DeclareUnicodeCharacter{01E2}{\={\AE}}
+  \DeclareUnicodeCharacter{01E3}{\={\ae}}
+  \DeclareUnicodeCharacter{01E6}{\v{G}}
+  \DeclareUnicodeCharacter{01E7}{\v{g}}
+  \DeclareUnicodeCharacter{01E8}{\v{K}}
+  \DeclareUnicodeCharacter{01E9}{\v{k}}
+
+  \DeclareUnicodeCharacter{01F0}{\v{\dotless{j}}}
+  \DeclareUnicodeCharacter{01F1}{DZ}
+  \DeclareUnicodeCharacter{01F2}{Dz}
+  \DeclareUnicodeCharacter{01F3}{dz}
+  \DeclareUnicodeCharacter{01F4}{\'G}
+  \DeclareUnicodeCharacter{01F5}{\'g}
+  \DeclareUnicodeCharacter{01F8}{\`N}
+  \DeclareUnicodeCharacter{01F9}{\`n}
+  \DeclareUnicodeCharacter{01FC}{\'{\AE}}
+  \DeclareUnicodeCharacter{01FD}{\'{\ae}}
+  \DeclareUnicodeCharacter{01FE}{\'{\O}}
+  \DeclareUnicodeCharacter{01FF}{\'{\o}}
+
+  \DeclareUnicodeCharacter{021E}{\v{H}}
+  \DeclareUnicodeCharacter{021F}{\v{h}}
+
+  \DeclareUnicodeCharacter{0226}{\dotaccent{A}}
+  \DeclareUnicodeCharacter{0227}{\dotaccent{a}}
+  \DeclareUnicodeCharacter{0228}{\cedilla{E}}
+  \DeclareUnicodeCharacter{0229}{\cedilla{e}}
+  \DeclareUnicodeCharacter{022E}{\dotaccent{O}}
+  \DeclareUnicodeCharacter{022F}{\dotaccent{o}}
+
+  \DeclareUnicodeCharacter{0232}{\=Y}
+  \DeclareUnicodeCharacter{0233}{\=y}
+  \DeclareUnicodeCharacter{0237}{\dotless{j}}
+
+  \DeclareUnicodeCharacter{1E02}{\dotaccent{B}}
+  \DeclareUnicodeCharacter{1E03}{\dotaccent{b}}
+  \DeclareUnicodeCharacter{1E04}{\udotaccent{B}}
+  \DeclareUnicodeCharacter{1E05}{\udotaccent{b}}
+  \DeclareUnicodeCharacter{1E06}{\ubaraccent{B}}
+  \DeclareUnicodeCharacter{1E07}{\ubaraccent{b}}
+  \DeclareUnicodeCharacter{1E0A}{\dotaccent{D}}
+  \DeclareUnicodeCharacter{1E0B}{\dotaccent{d}}
+  \DeclareUnicodeCharacter{1E0C}{\udotaccent{D}}
+  \DeclareUnicodeCharacter{1E0D}{\udotaccent{d}}
+  \DeclareUnicodeCharacter{1E0E}{\ubaraccent{D}}
+  \DeclareUnicodeCharacter{1E0F}{\ubaraccent{d}}
+
+  \DeclareUnicodeCharacter{1E1E}{\dotaccent{F}}
+  \DeclareUnicodeCharacter{1E1F}{\dotaccent{f}}
+
+  \DeclareUnicodeCharacter{1E20}{\=G}
+  \DeclareUnicodeCharacter{1E21}{\=g}
+  \DeclareUnicodeCharacter{1E22}{\dotaccent{H}}
+  \DeclareUnicodeCharacter{1E23}{\dotaccent{h}}
+  \DeclareUnicodeCharacter{1E24}{\udotaccent{H}}
+  \DeclareUnicodeCharacter{1E25}{\udotaccent{h}}
+  \DeclareUnicodeCharacter{1E26}{\"H}
+  \DeclareUnicodeCharacter{1E27}{\"h}
+
+  \DeclareUnicodeCharacter{1E30}{\'K}
+  \DeclareUnicodeCharacter{1E31}{\'k}
+  \DeclareUnicodeCharacter{1E32}{\udotaccent{K}}
+  \DeclareUnicodeCharacter{1E33}{\udotaccent{k}}
+  \DeclareUnicodeCharacter{1E34}{\ubaraccent{K}}
+  \DeclareUnicodeCharacter{1E35}{\ubaraccent{k}}
+  \DeclareUnicodeCharacter{1E36}{\udotaccent{L}}
+  \DeclareUnicodeCharacter{1E37}{\udotaccent{l}}
+  \DeclareUnicodeCharacter{1E3A}{\ubaraccent{L}}
+  \DeclareUnicodeCharacter{1E3B}{\ubaraccent{l}}
+  \DeclareUnicodeCharacter{1E3E}{\'M}
+  \DeclareUnicodeCharacter{1E3F}{\'m}
+
+  \DeclareUnicodeCharacter{1E40}{\dotaccent{M}}
+  \DeclareUnicodeCharacter{1E41}{\dotaccent{m}}
+  \DeclareUnicodeCharacter{1E42}{\udotaccent{M}}
+  \DeclareUnicodeCharacter{1E43}{\udotaccent{m}}
+  \DeclareUnicodeCharacter{1E44}{\dotaccent{N}}
+  \DeclareUnicodeCharacter{1E45}{\dotaccent{n}}
+  \DeclareUnicodeCharacter{1E46}{\udotaccent{N}}
+  \DeclareUnicodeCharacter{1E47}{\udotaccent{n}}
+  \DeclareUnicodeCharacter{1E48}{\ubaraccent{N}}
+  \DeclareUnicodeCharacter{1E49}{\ubaraccent{n}}
+
+  \DeclareUnicodeCharacter{1E54}{\'P}
+  \DeclareUnicodeCharacter{1E55}{\'p}
+  \DeclareUnicodeCharacter{1E56}{\dotaccent{P}}
+  \DeclareUnicodeCharacter{1E57}{\dotaccent{p}}
+  \DeclareUnicodeCharacter{1E58}{\dotaccent{R}}
+  \DeclareUnicodeCharacter{1E59}{\dotaccent{r}}
+  \DeclareUnicodeCharacter{1E5A}{\udotaccent{R}}
+  \DeclareUnicodeCharacter{1E5B}{\udotaccent{r}}
+  \DeclareUnicodeCharacter{1E5E}{\ubaraccent{R}}
+  \DeclareUnicodeCharacter{1E5F}{\ubaraccent{r}}
+
+  \DeclareUnicodeCharacter{1E60}{\dotaccent{S}}
+  \DeclareUnicodeCharacter{1E61}{\dotaccent{s}}
+  \DeclareUnicodeCharacter{1E62}{\udotaccent{S}}
+  \DeclareUnicodeCharacter{1E63}{\udotaccent{s}}
+  \DeclareUnicodeCharacter{1E6A}{\dotaccent{T}}
+  \DeclareUnicodeCharacter{1E6B}{\dotaccent{t}}
+  \DeclareUnicodeCharacter{1E6C}{\udotaccent{T}}
+  \DeclareUnicodeCharacter{1E6D}{\udotaccent{t}}
+  \DeclareUnicodeCharacter{1E6E}{\ubaraccent{T}}
+  \DeclareUnicodeCharacter{1E6F}{\ubaraccent{t}}
+
+  \DeclareUnicodeCharacter{1E7C}{\~V}
+  \DeclareUnicodeCharacter{1E7D}{\~v}
+  \DeclareUnicodeCharacter{1E7E}{\udotaccent{V}}
+  \DeclareUnicodeCharacter{1E7F}{\udotaccent{v}}
+
+  \DeclareUnicodeCharacter{1E80}{\`W}
+  \DeclareUnicodeCharacter{1E81}{\`w}
+  \DeclareUnicodeCharacter{1E82}{\'W}
+  \DeclareUnicodeCharacter{1E83}{\'w}
+  \DeclareUnicodeCharacter{1E84}{\"W}
+  \DeclareUnicodeCharacter{1E85}{\"w}
+  \DeclareUnicodeCharacter{1E86}{\dotaccent{W}}
+  \DeclareUnicodeCharacter{1E87}{\dotaccent{w}}
+  \DeclareUnicodeCharacter{1E88}{\udotaccent{W}}
+  \DeclareUnicodeCharacter{1E89}{\udotaccent{w}}
+  \DeclareUnicodeCharacter{1E8A}{\dotaccent{X}}
+  \DeclareUnicodeCharacter{1E8B}{\dotaccent{x}}
+  \DeclareUnicodeCharacter{1E8C}{\"X}
+  \DeclareUnicodeCharacter{1E8D}{\"x}
+  \DeclareUnicodeCharacter{1E8E}{\dotaccent{Y}}
+  \DeclareUnicodeCharacter{1E8F}{\dotaccent{y}}
+
+  \DeclareUnicodeCharacter{1E90}{\^Z}
+  \DeclareUnicodeCharacter{1E91}{\^z}
+  \DeclareUnicodeCharacter{1E92}{\udotaccent{Z}}
+  \DeclareUnicodeCharacter{1E93}{\udotaccent{z}}
+  \DeclareUnicodeCharacter{1E94}{\ubaraccent{Z}}
+  \DeclareUnicodeCharacter{1E95}{\ubaraccent{z}}
+  \DeclareUnicodeCharacter{1E96}{\ubaraccent{h}}
+  \DeclareUnicodeCharacter{1E97}{\"t}
+  \DeclareUnicodeCharacter{1E98}{\ringaccent{w}}
+  \DeclareUnicodeCharacter{1E99}{\ringaccent{y}}
+
+  \DeclareUnicodeCharacter{1EA0}{\udotaccent{A}}
+  \DeclareUnicodeCharacter{1EA1}{\udotaccent{a}}
+
+  \DeclareUnicodeCharacter{1EB8}{\udotaccent{E}}
+  \DeclareUnicodeCharacter{1EB9}{\udotaccent{e}}
+  \DeclareUnicodeCharacter{1EBC}{\~E}
+  \DeclareUnicodeCharacter{1EBD}{\~e}
+
+  \DeclareUnicodeCharacter{1ECA}{\udotaccent{I}}
+  \DeclareUnicodeCharacter{1ECB}{\udotaccent{i}}
+  \DeclareUnicodeCharacter{1ECC}{\udotaccent{O}}
+  \DeclareUnicodeCharacter{1ECD}{\udotaccent{o}}
+
+  \DeclareUnicodeCharacter{1EE4}{\udotaccent{U}}
+  \DeclareUnicodeCharacter{1EE5}{\udotaccent{u}}
+
+  \DeclareUnicodeCharacter{1EF2}{\`Y}
+  \DeclareUnicodeCharacter{1EF3}{\`y}
+  \DeclareUnicodeCharacter{1EF4}{\udotaccent{Y}}
+
+  \DeclareUnicodeCharacter{1EF8}{\~Y}
+  \DeclareUnicodeCharacter{1EF9}{\~y}
+
+  \DeclareUnicodeCharacter{2013}{--}
+  \DeclareUnicodeCharacter{2014}{---}
+  \DeclareUnicodeCharacter{2018}{\quoteleft}
+  \DeclareUnicodeCharacter{2019}{\quoteright}
+  \DeclareUnicodeCharacter{201A}{\quotesinglbase}
+  \DeclareUnicodeCharacter{201C}{\quotedblleft}
+  \DeclareUnicodeCharacter{201D}{\quotedblright}
+  \DeclareUnicodeCharacter{201E}{\quotedblbase}
+  \DeclareUnicodeCharacter{2022}{\bullet}
+  \DeclareUnicodeCharacter{2026}{\dots}
+  \DeclareUnicodeCharacter{2039}{\guilsinglleft}
+  \DeclareUnicodeCharacter{203A}{\guilsinglright}
+  \DeclareUnicodeCharacter{20AC}{\euro}
+
+  \DeclareUnicodeCharacter{2192}{\expansion}
+  \DeclareUnicodeCharacter{21D2}{\result}
+
+  \DeclareUnicodeCharacter{2212}{\minus}
+  \DeclareUnicodeCharacter{2217}{\point}
+  \DeclareUnicodeCharacter{2261}{\equiv}
+}% end of \utfeightchardefs
+
+
+% US-ASCII character definitions.
+\def\asciichardefs{% nothing need be done
+   \relax
+}
+
+% Make non-ASCII characters printable again for compatibility with
+% existing Texinfo documents that may use them, even without declaring a
+% document encoding.
+%
+\setnonasciicharscatcode \other
+
+
+\message{formatting,}
+
+\newdimen\defaultparindent \defaultparindent = 15pt
+
+\chapheadingskip = 15pt plus 4pt minus 2pt
+\secheadingskip = 12pt plus 3pt minus 2pt
+\subsecheadingskip = 9pt plus 2pt minus 2pt
+
+% Prevent underfull vbox error messages.
+\vbadness = 10000
+
+% Don't be so finicky about underfull hboxes, either.
+\hbadness = 2000
+
+% Following George Bush, get rid of widows and orphans.
+\widowpenalty=10000
+\clubpenalty=10000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything.  We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize.  We call this whenever the paper size is set.
+%
+\def\setemergencystretch{%
+  \ifx\emergencystretch\thisisundefined
+    % Allow us to assign to \emergencystretch anyway.
+    \def\emergencystretch{\dimen0}%
+  \else
+    \emergencystretch = .15\hsize
+  \fi
+}
+
+% Parameters in order: 1) textheight; 2) textwidth;
+% 3) voffset; 4) hoffset; 5) binding offset; 6) topskip;
+% 7) physical page height; 8) physical page width.
+%
+% We also call \setleading{\textleading}, so the caller should define
+% \textleading.  The caller should also set \parskip.
+%
+\def\internalpagesizes#1#2#3#4#5#6#7#8{%
+  \voffset = #3\relax
+  \topskip = #6\relax
+  \splittopskip = \topskip
+  %
+  \vsize = #1\relax
+  \advance\vsize by \topskip
+  \outervsize = \vsize
+  \advance\outervsize by 2\topandbottommargin
+  \pageheight = \vsize
+  %
+  \hsize = #2\relax
+  \outerhsize = \hsize
+  \advance\outerhsize by 0.5in
+  \pagewidth = \hsize
+  %
+  \normaloffset = #4\relax
+  \bindingoffset = #5\relax
+  %
+  \ifpdf
+    \pdfpageheight #7\relax
+    \pdfpagewidth #8\relax
+    % if we don't reset these, they will remain at "1 true in" of
+    % whatever layout pdftex was dumped with.
+    \pdfhorigin = 1 true in
+    \pdfvorigin = 1 true in
+  \fi
+  %
+  \setleading{\textleading}
+  %
+  \parindent = \defaultparindent
+  \setemergencystretch
+}
+
+% @letterpaper (the default).
+\def\letterpaper{{\globaldefs = 1
+  \parskip = 3pt plus 2pt minus 1pt
+  \textleading = 13.2pt
+  %
+  % If page is nothing but text, make it come out even.
+  \internalpagesizes{607.2pt}{6in}% that's 46 lines
+                    {\voffset}{.25in}%
+                    {\bindingoffset}{36pt}%
+                    {11in}{8.5in}%
+}}
+
+% Use @smallbook to reset parameters for 7x9.25 trim size.
+\def\smallbook{{\globaldefs = 1
+  \parskip = 2pt plus 1pt
+  \textleading = 12pt
+  %
+  \internalpagesizes{7.5in}{5in}%
+                    {-.2in}{0in}%
+                    {\bindingoffset}{16pt}%
+                    {9.25in}{7in}%
+  %
+  \lispnarrowing = 0.3in
+  \tolerance = 700
+  \hfuzz = 1pt
+  \contentsrightmargin = 0pt
+  \defbodyindent = .5cm
+}}
+
+% Use @smallerbook to reset parameters for 6x9 trim size.
+% (Just testing, parameters still in flux.)
+\def\smallerbook{{\globaldefs = 1
+  \parskip = 1.5pt plus 1pt
+  \textleading = 12pt
+  %
+  \internalpagesizes{7.4in}{4.8in}%
+                    {-.2in}{-.4in}%
+                    {0pt}{14pt}%
+                    {9in}{6in}%
+  %
+  \lispnarrowing = 0.25in
+  \tolerance = 700
+  \hfuzz = 1pt
+  \contentsrightmargin = 0pt
+  \defbodyindent = .4cm
+}}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{{\globaldefs = 1
+  \parskip = 3pt plus 2pt minus 1pt
+  \textleading = 13.2pt
+  %
+  % Double-side printing via postscript on Laserjet 4050
+  % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm.
+  % To change the settings for a different printer or situation, adjust
+  % \normaloffset until the front-side and back-side texts align.  Then
+  % do the same for \bindingoffset.  You can set these for testing in
+  % your texinfo source file like this:
+  % @tex
+  % \global\normaloffset = -6mm
+  % \global\bindingoffset = 10mm
+  % @end tex
+  \internalpagesizes{673.2pt}{160mm}% that's 51 lines
+                    {\voffset}{\hoffset}%
+                    {\bindingoffset}{44pt}%
+                    {297mm}{210mm}%
+  %
+  \tolerance = 700
+  \hfuzz = 1pt
+  \contentsrightmargin = 0pt
+  \defbodyindent = 5mm
+}}
+
+% Use @afivepaper to print on European A5 paper.
+% From romildo@urano.iceb.ufop.br, 2 July 2000.
+% He also recommends making @example and @lisp be small.
+\def\afivepaper{{\globaldefs = 1
+  \parskip = 2pt plus 1pt minus 0.1pt
+  \textleading = 12.5pt
+  %
+  \internalpagesizes{160mm}{120mm}%
+                    {\voffset}{\hoffset}%
+                    {\bindingoffset}{8pt}%
+                    {210mm}{148mm}%
+  %
+  \lispnarrowing = 0.2in
+  \tolerance = 800
+  \hfuzz = 1.2pt
+  \contentsrightmargin = 0pt
+  \defbodyindent = 2mm
+  \tableindent = 12mm
+}}
+
+% A specific text layout, 24x15cm overall, intended for A4 paper.
+\def\afourlatex{{\globaldefs = 1
+  \afourpaper
+  \internalpagesizes{237mm}{150mm}%
+                    {\voffset}{4.6mm}%
+                    {\bindingoffset}{7mm}%
+                    {297mm}{210mm}%
+  %
+  % Must explicitly reset to 0 because we call \afourpaper.
+  \globaldefs = 0
+}}
+
+% Use @afourwide to print on A4 paper in landscape format.
+\def\afourwide{{\globaldefs = 1
+  \afourpaper
+  \internalpagesizes{241mm}{165mm}%
+                    {\voffset}{-2.95mm}%
+                    {\bindingoffset}{7mm}%
+                    {297mm}{210mm}%
+  \globaldefs = 0
+}}
+
+% @pagesizes TEXTHEIGHT[,TEXTWIDTH]
+% Perhaps we should allow setting the margins, \topskip, \parskip,
+% and/or leading, also. Or perhaps we should compute them somehow.
+%
+\parseargdef\pagesizes{\pagesizesyyy #1,,\finish}
+\def\pagesizesyyy#1,#2,#3\finish{{%
+  \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi
+  \globaldefs = 1
+  %
+  \parskip = 3pt plus 2pt minus 1pt
+  \setleading{\textleading}%
+  %
+  \dimen0 = #1\relax
+  \advance\dimen0 by \voffset
+  %
+  \dimen2 = \hsize
+  \advance\dimen2 by \normaloffset
+  %
+  \internalpagesizes{#1}{\hsize}%
+                    {\voffset}{\normaloffset}%
+                    {\bindingoffset}{44pt}%
+                    {\dimen0}{\dimen2}%
+}}
+
+% Set default to letter.
+%
+\letterpaper
+
+
+\message{and turning on texinfo input format.}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\catcode`\$=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+\def\normaldollar{$}%$ font-lock fix
+
+% This macro is used to make a character print one way in \tt
+% (where it can probably be output as-is), and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise.  Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi}
+
+% Same as above, but check for italic font.  Actually this also catches
+% non-italic slanted fonts since it is impossible to distinguish them from
+% italic fonts.  But since this is only used by $ and it uses \sl anyway
+% this is not a problem.
+\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt\char34}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt\char126}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+\let\realunder=_
+% Subroutine for the previous macro.
+\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em }
+
+\catcode`\|=\active
+\def|{{\tt\char124}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+\catcode`\$=\active
+\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix
+
+% If a .fmt file is being used, characters that might appear in a file
+% name cannot be active until we have parsed the command line.
+% So turn them off again, and have \everyjob (or @setfilename) turn them on.
+% \otherifyactive is called near the end of this file.
+\def\otherifyactive{\catcode`+=\other \catcode`\_=\other}
+
+% Used sometimes to turn off (effectively) the active characters even after
+% parsing them.
+\def\turnoffactive{%
+  \normalturnoffactive
+  \otherbackslash
+}
+
+\catcode`\@=0
+
+% \backslashcurfont outputs one backslash character in current font,
+% as in \char`\\.
+\global\chardef\backslashcurfont=`\\
+\global\let\rawbackslashxx=\backslashcurfont  % let existing .??s files work
+
+% \realbackslash is an actual character `\' with catcode other, and
+% \doublebackslash is two of them (for the pdf outlines).
+{\catcode`\\=\other @gdef@realbackslash{\} @gdef@doublebackslash{\\}}
+
+% In texinfo, backslash is an active character; it prints the backslash
+% in fixed width font.
+\catcode`\\=\active
+@def@normalbackslash{{@tt@backslashcurfont}}
+% On startup, @fixbackslash assigns:
+%  @let \ = @normalbackslash
+
+% \rawbackslash defines an active \ to do \backslashcurfont.
+% \otherbackslash defines an active \ to be a literal `\' character with
+% catcode other.
+@gdef@rawbackslash{@let\=@backslashcurfont}
+@gdef@otherbackslash{@let\=@realbackslash}
+
+% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of
+% the literal character `\'.
+% 
+@def@normalturnoffactive{%
+  @let\=@normalbackslash
+  @let"=@normaldoublequote
+  @let~=@normaltilde
+  @let^=@normalcaret
+  @let_=@normalunderscore
+  @let|=@normalverticalbar
+  @let<=@normalless
+  @let>=@normalgreater
+  @let+=@normalplus
+  @let$=@normaldollar %$ font-lock fix
+  @unsepspaces
+}
+
+% Make _ and + \other characters, temporarily.
+% This is canceled by @fixbackslash.
+@otherifyactive
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\' in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+% Also turn back on active characters that might appear in the input
+% file name, in case not using a pre-dumped format.
+%
+@gdef@fixbackslash{%
+  @ifx\@eatinput @let\ = @normalbackslash @fi
+  @catcode`+=@active
+  @catcode`@_=@active
+}
+
+% Say @foo, not \foo, in error messages.
+@escapechar = `@@
+
+% These look ok in all fonts, so just make them not special.
+@catcode`@& = @other
+@catcode`@# = @other
+@catcode`@% = @other
+
+
+@c Local variables:
+@c eval: (add-hook 'write-file-hooks 'time-stamp)
+@c page-delimiter: "^\\\\message"
+@c time-stamp-start: "def\\\\texinfoversion{"
+@c time-stamp-format: "%:y-%02m-%02d.%02H"
+@c time-stamp-end: "}"
+@c End:
+
+@c vim:sw=2:
+
+@ignore
+   arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115
+@end ignore
diff --git a/font/font.c b/font/font.c
new file mode 100644 (file)
index 0000000..cfe1ee4
--- /dev/null
@@ -0,0 +1,1026 @@
+/* font.c - Font API and font file loader.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,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/>.
+ */
+
+#include <grub/bufio.h>
+#include <grub/dl.h>
+#include <grub/file.h>
+#include <grub/font.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/video.h>
+#include <grub/bitmap.h>
+
+#ifndef FONT_DEBUG
+#define FONT_DEBUG 0
+#endif
+
+struct char_index_entry
+{
+  grub_uint32_t code;
+  grub_uint8_t storage_flags;
+  grub_uint32_t offset;
+  
+  /* Glyph if loaded, or NULL otherwise.  */
+  struct grub_font_glyph *glyph;
+};
+
+#define FONT_WEIGHT_NORMAL 100
+#define FONT_WEIGHT_BOLD 200
+
+struct grub_font
+{
+  char *name;
+  grub_file_t file;
+  char *family;
+  short point_size;
+  short weight;
+  short max_char_width;
+  short max_char_height;
+  short ascent;
+  short descent;
+  short leading;
+  grub_uint32_t num_chars;
+  struct char_index_entry *char_index;
+};
+
+/* Definition of font registry.  */
+struct grub_font_node *grub_font_list;
+
+static int register_font (grub_font_t font);
+static void font_init (grub_font_t font);
+static void free_font (grub_font_t font);
+static void remove_font (grub_font_t font);
+
+struct font_file_section
+{
+  /* The file this section is in.  */
+  grub_file_t file;
+  
+  /* FOURCC name of the section.  */
+  char name[4];
+  
+  /* Length of the section contents.  */
+  grub_uint32_t length;
+  
+  /* Set by open_section() on EOF.  */
+  int eof;
+};
+
+/* Font file format constants.  */
+static const char pff2_magic[4] = { 'P', 'F', 'F', '2' };
+static const char section_names_file[4] = { 'F', 'I', 'L', 'E' };
+static const char section_names_font_name[4] = { 'N', 'A', 'M', 'E' };
+static const char section_names_point_size[4] = { 'P', 'T', 'S', 'Z' };
+static const char section_names_weight[4] = { 'W', 'E', 'I', 'G' };
+static const char section_names_max_char_width[4] = { 'M', 'A', 'X', 'W' };
+static const char section_names_max_char_height[4] = { 'M', 'A', 'X', 'H' };
+static const char section_names_ascent[4] = { 'A', 'S', 'C', 'E' };
+static const char section_names_descent[4] = { 'D', 'E', 'S', 'C' };
+static const char section_names_char_index[4] = { 'C', 'H', 'I', 'X' };
+static const char section_names_data[4] = { 'D', 'A', 'T', 'A' };
+
+/* Replace unknown glyphs with a rounded question mark.  */
+static grub_uint8_t unknown_glyph_bitmap[] =
+{
+  /*       76543210 */
+  0x7C, /*  ooooo   */
+  0x82, /* o     o  */
+  0xBA, /* o ooo o  */
+  0xAA, /* o o o o  */
+  0xAA, /* o o o o  */
+  0x8A, /* o   o o  */
+  0x9A, /* o  oo o  */
+  0x92, /* o  o  o  */
+  0x92, /* o  o  o  */
+  0x92, /* o  o  o  */
+  0x92, /* o  o  o  */
+  0x82, /* o     o  */
+  0x92, /* o  o  o  */
+  0x82, /* o     o  */
+  0x7C, /*  ooooo   */
+  0x00  /*          */
+};
+
+/* The "unknown glyph" glyph, used as a last resort.  */
+static struct grub_font_glyph *unknown_glyph;
+
+/* The font structure used when no other font is loaded.  This functions
+   as a "Null Object" pattern, so that code everywhere does not have to
+   check for a NULL grub_font_t to avoid dereferencing a null pointer.  */
+static struct grub_font null_font;
+
+/* Flag to ensure module is initialized only once.  */
+static grub_uint8_t font_loader_initialized;
+
+void
+grub_font_loader_init (void)
+{
+  /* Only initialize font loader once.  */
+  if (font_loader_initialized)
+    return;
+
+  /* Make glyph for unknown glyph.  */
+  unknown_glyph = grub_malloc(sizeof(struct grub_font_glyph)
+                              + sizeof(unknown_glyph_bitmap));
+  if (! unknown_glyph)
+    return;
+
+  unknown_glyph->width = 8;
+  unknown_glyph->height = 16;
+  unknown_glyph->offset_x = 0;
+  unknown_glyph->offset_y = -3;
+  unknown_glyph->device_width = 8;
+  grub_memcpy(unknown_glyph->bitmap,
+              unknown_glyph_bitmap, sizeof(unknown_glyph_bitmap));
+
+  /* Initialize the null font.  */
+  font_init (&null_font);
+  null_font.name = "<No Font>";
+  null_font.ascent = unknown_glyph->height-3;
+  null_font.descent = 3;
+  null_font.max_char_width = unknown_glyph->width;
+  null_font.max_char_height = unknown_glyph->height;
+
+  font_loader_initialized = 1;
+}
+
+/* Initialize the font object with initial default values.  */
+static void
+font_init (grub_font_t font)
+{
+  font->name = 0;
+  font->file = 0;
+  font->family = 0;
+  font->point_size = 0;
+  font->weight = 0;
+  
+  /* Default leading value, not in font file yet.  */
+  font->leading = 1;
+  
+  font->max_char_width = 0;
+  font->max_char_height = 0;
+  font->ascent = 0;
+  font->descent = 0;
+  font->num_chars = 0;
+  font->char_index = 0;
+}
+
+/* Open the next section in the file.
+
+   On success, the section name is stored in section->name and the length in
+   section->length, and 0 is returned.  On failure, 1 is returned and
+   grub_errno is set approriately with an error message.
+
+   If 1 is returned due to being at the end of the file, then section->eof is
+   set to 1; otherwise, section->eof is set to 0.  */
+static int
+open_section (grub_file_t file, struct font_file_section *section)
+{
+  grub_ssize_t retval;
+  grub_uint32_t raw_length;
+
+  section->file = file;
+  section->eof = 0;
+
+  /* Read the FOURCC section name.  */
+  retval = grub_file_read (file, section->name, 4);
+  if (retval >= 0 && retval < 4)
+    {
+      /* EOF encountered.  */
+      section->eof = 1;
+      return 1;
+    }
+  else if (retval < 0)
+    {
+      grub_error (GRUB_ERR_BAD_FONT,
+                  "Font format error: can't read section name");
+      return 1;
+    }
+
+  /* Read the big-endian 32-bit section length.  */
+  retval = grub_file_read (file, (char *) &raw_length, 4);
+  if (retval >= 0 && retval < 4)
+    {
+      /* EOF encountered.  */
+      section->eof = 1;
+      return 1;
+    }
+  else if (retval < 0)
+    {
+      grub_error (GRUB_ERR_BAD_FONT,
+                  "Font format error: can't read section length");
+      return 1;
+    }
+
+  /* Convert byte-order and store in *length.  */
+  section->length = grub_be_to_cpu32 (raw_length);
+
+  return 0;
+}
+
+/* Size in bytes of each character index (CHIX section)
+   entry in the font file.  */
+#define FONT_CHAR_INDEX_ENTRY_SIZE (4 + 1 + 4)
+
+/* Load the character index (CHIX) section contents from the font file.  This
+   presumes that the position of FILE is positioned immediately after the
+   section length for the CHIX section (i.e., at the start of the section
+   contents).  Returns 0 upon success, nonzero for failure (in which case
+   grub_errno is set appropriately).  */
+static int
+load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
+                 grub_font *font)
+{
+  unsigned i;
+
+#if FONT_DEBUG >= 2
+  grub_printf("load_font_index(sect_length=%d)\n", sect_length);
+#endif
+
+  /* Sanity check: ensure section length is divisible by the entry size.  */
+  if ((sect_length % FONT_CHAR_INDEX_ENTRY_SIZE) != 0)
+    {
+      grub_error (GRUB_ERR_BAD_FONT,
+                  "Font file format error: character index length %d "
+                  "is not a multiple of the entry size %d",
+                  sect_length, FONT_CHAR_INDEX_ENTRY_SIZE);
+      return 1;
+    }
+
+  /* Calculate the number of characters.  */
+  font->num_chars = sect_length / FONT_CHAR_INDEX_ENTRY_SIZE;
+
+  /* Allocate the character index array.  */
+  font->char_index = grub_malloc (font->num_chars
+                                  * sizeof (struct char_index_entry));
+  if (! font->char_index)
+    return 1;
+
+#if FONT_DEBUG >= 2
+  grub_printf("num_chars=%d)\n", font->num_chars);
+#endif
+
+  /* Load the character index data from the file.  */
+  for (i = 0; i < font->num_chars; i++)
+    {
+      struct char_index_entry *entry = &font->char_index[i];
+
+      /* Read code point value; convert to native byte order.  */
+      if (grub_file_read (file, (char *) &entry->code, 4) != 4)
+        return 1;
+      entry->code = grub_be_to_cpu32 (entry->code);
+
+      /* Read storage flags byte.  */
+      if (grub_file_read (file, (char *) &entry->storage_flags, 1) != 1)
+        return 1;
+
+      /* Read glyph data offset; convert to native byte order.  */
+      if (grub_file_read (file, (char *) &entry->offset, 4) != 4)
+        return 1;
+      entry->offset = grub_be_to_cpu32 (entry->offset);
+
+      /* No glyph loaded.  Will be loaded on demand and cached thereafter.  */
+      entry->glyph = 0;
+
+#if FONT_DEBUG >= 5
+      /* Print the 1st 10 characters.  */
+      if (i < 10)
+        grub_printf("c=%d o=%d\n", entry->code, entry->offset);
+#endif
+    }
+
+  return 0;
+}
+
+/* Read the contents of the specified section as a string, which is
+   allocated on the heap.  Returns 0 if there is an error.  */
+static char *
+read_section_as_string (struct font_file_section *section)
+{
+  char *str;
+  grub_ssize_t ret;
+
+  str = grub_malloc (section->length + 1);
+  if (! str)
+    return 0;
+
+  ret = grub_file_read (section->file, str, section->length);
+  if (ret < 0 || ret != (grub_ssize_t) section->length)
+    {
+      grub_free (str);
+      return 0;
+    }
+
+  str[section->length] = '\0';
+  return str;
+}
+
+/* Read the contents of the current section as a 16-bit integer value,
+   which is stored into *VALUE.
+   Returns 0 upon success, nonzero upon failure.  */
+static int
+read_section_as_short (struct font_file_section *section, grub_int16_t *value)
+{
+  grub_uint16_t raw_value;
+
+  if (section->length != 2)
+    {
+      grub_error (GRUB_ERR_BAD_FONT,
+                  "Font file format error: section %c%c%c%c length "
+                  "is %d but should be 2",
+                  section->name[0], section->name[1],
+                  section->name[2], section->name[3],
+                  section->length);
+      return 1;
+    }
+  if (grub_file_read (section->file, (char *) &raw_value, 2) != 2)
+    return 1;
+
+  *value = grub_be_to_cpu16 (raw_value);
+  return 0;
+}
+
+/* Load a font and add it to the beginning of the global font list.
+   Returns 0 upon success, nonzero upon failure.  */
+int
+grub_font_load (const char *filename)
+{
+  grub_file_t file = 0;
+  struct font_file_section section;
+  char magic[4];
+  grub_font_t font = 0;
+
+#if FONT_DEBUG >= 1
+  grub_printf("add_font(%s)\n", filename);
+#endif
+
+  file = grub_buffile_open (filename, 1024);
+  if (!file)
+    goto fail;
+
+#if FONT_DEBUG >= 3
+  grub_printf("file opened\n");
+#endif
+
+  /* Read the FILE section.  It indicates the file format.  */
+  if (open_section (file, &section) != 0)
+    goto fail;
+
+#if FONT_DEBUG >= 3
+  grub_printf("opened FILE section\n");
+#endif
+  if (grub_memcmp (section.name, section_names_file, 4) != 0)
+    {
+      grub_error (GRUB_ERR_BAD_FONT,
+                  "Font file format error: 1st section must be FILE");
+      goto fail;
+    }
+
+#if FONT_DEBUG >= 3
+  grub_printf("section name ok\n");
+#endif
+  if (section.length != 4)
+    {
+      grub_error (GRUB_ERR_BAD_FONT,
+                  "Font file format error (file type ID length is %d "
+                  "but should be 4)", section.length);
+      goto fail;
+    }
+
+#if FONT_DEBUG >= 3
+  grub_printf("section length ok\n");
+#endif
+  /* Check the file format type code.  */
+  if (grub_file_read (file, magic, 4) != 4)
+    goto fail;
+
+#if FONT_DEBUG >= 3
+  grub_printf("read magic ok\n");
+#endif
+
+  if (grub_memcmp (magic, pff2_magic, 4) != 0)
+    {
+      grub_error (GRUB_ERR_BAD_FONT, "Invalid font magic %x %x %x %x",
+                  magic[0], magic[1], magic[2], magic[3]);
+      goto fail;
+    }
+
+#if FONT_DEBUG >= 3
+  grub_printf("compare magic ok\n");
+#endif
+
+  /* Allocate the font object.  */
+  font = (grub_font_t) grub_malloc (sizeof (struct grub_font));
+  if (! font)
+    goto fail;
+
+  font_init (font);
+  font->file = file;
+
+#if FONT_DEBUG >= 3
+  grub_printf("allocate font ok; loading font info\n");
+#endif
+
+  /* Load the font information.  */
+  while (1)
+    {
+      if (open_section (file, &section) != 0)
+        {
+          if (section.eof)
+            break;              /* Done reading the font file.  */
+          else
+            goto fail;
+        }
+
+#if FONT_DEBUG >= 2
+      grub_printf("opened section %c%c%c%c ok\n",
+                  section.name[0], section.name[1],
+                  section.name[2], section.name[3]);
+#endif
+
+      if (grub_memcmp (section.name, section_names_font_name, 4) == 0)
+        {
+          font->name = read_section_as_string (&section);
+          if (!font->name)
+            goto fail;
+        }
+      else if (grub_memcmp (section.name, section_names_point_size, 4) == 0)
+        {
+          if (read_section_as_short (&section, &font->point_size) != 0)
+            goto fail;
+        }
+      else if (grub_memcmp (section.name, section_names_weight, 4) == 0)
+        {
+          char *wt;
+          wt = read_section_as_string (&section);
+          if (!wt)
+            continue;
+          /* Convert the weight string 'normal' or 'bold' into a number.  */
+          if (grub_strcmp (wt, "normal") == 0)
+            font->weight = FONT_WEIGHT_NORMAL;
+          else if (grub_strcmp (wt, "bold") == 0)
+            font->weight = FONT_WEIGHT_BOLD;
+          grub_free (wt);
+        }
+      else if (grub_memcmp (section.name, section_names_max_char_width, 4) == 0)
+        {
+          if (read_section_as_short (&section, &font->max_char_width) != 0)
+            goto fail;
+        }
+      else if (grub_memcmp (section.name, section_names_max_char_height, 4) == 0)
+        {
+          if (read_section_as_short (&section, &font->max_char_height) != 0)
+            goto fail;
+        }
+      else if (grub_memcmp (section.name, section_names_ascent, 4) == 0)
+        {
+          if (read_section_as_short (&section, &font->ascent) != 0)
+            goto fail;
+        }
+      else if (grub_memcmp (section.name, section_names_descent, 4) == 0)
+        {
+          if (read_section_as_short (&section, &font->descent) != 0)
+            goto fail;
+        }
+      else if (grub_memcmp (section.name, section_names_char_index, 4) == 0)
+        {
+          if (load_font_index (file, section.length, font) != 0)
+            goto fail;
+        }
+      else if (grub_memcmp (section.name, section_names_data, 4) == 0)
+        {
+          /* When the DATA section marker is reached, we stop reading.  */
+          break;
+        }
+      else
+        {
+          /* Unhandled section type, simply skip past it.  */
+#if FONT_DEBUG >= 3
+          grub_printf("Unhandled section type, skipping.\n");
+#endif
+          grub_off_t section_end = grub_file_tell (file) + section.length;
+          if ((int) grub_file_seek (file, section_end) == -1)
+            goto fail;
+        }
+    }
+
+  if (! font->name)
+    {
+      grub_printf ("Note: Font has no name.\n");
+      font->name = grub_strdup ("Unknown");
+    }
+
+#if FONT_DEBUG >= 1
+  grub_printf ("Loaded font `%s'.\n"
+               "Ascent=%d Descent=%d MaxW=%d MaxH=%d Number of characters=%d.\n",
+               font->name,
+               font->ascent, font->descent,
+               font->max_char_width, font->max_char_height,
+               font->num_chars);
+#endif
+
+  if (font->max_char_width == 0
+      || font->max_char_height == 0
+      || font->num_chars == 0
+      || font->char_index == 0
+      || font->ascent == 0
+      || font->descent == 0)
+    {
+      grub_error (GRUB_ERR_BAD_FONT,
+                  "Invalid font file: missing some required data.");
+      goto fail;
+    }
+
+  /* Add the font to the global font registry.  */
+  if (register_font (font) != 0)
+    goto fail;
+
+  return 0;
+
+fail:
+  free_font (font);
+  return 1;
+}
+
+/* Read a 16-bit big-endian integer from FILE, convert it to native byte
+   order, and store it in *VALUE.
+   Returns 0 on success, 1 on failure.  */
+static int
+read_be_uint16 (grub_file_t file, grub_uint16_t * value)
+{
+  if (grub_file_read (file, (char *) value, 2) != 2)
+    return 1;
+  *value = grub_be_to_cpu16 (*value);
+  return 0;
+}
+
+static int
+read_be_int16 (grub_file_t file, grub_int16_t * value)
+{
+  /* For the signed integer version, use the same code as for unsigned.  */
+  return read_be_uint16 (file, (grub_uint16_t *) value);
+}
+
+/* Return a pointer to the character index entry for the glyph corresponding to
+   the codepoint CODE in the font FONT.  If not found, return zero.  */
+static struct char_index_entry *
+find_glyph (const grub_font_t font, grub_uint32_t code)
+{
+  grub_uint32_t i;
+  grub_uint32_t len = font->num_chars;
+  struct char_index_entry *table = font->char_index;
+
+  /* Do a linear search.  */
+  for (i = 0; i < len; i++)
+    {
+      if (table[i].code == code)
+        return &table[i];
+    }
+
+  return 0;
+}
+
+/* Get a glyph for the Unicode character CODE in FONT.  The glyph is loaded
+   from the font file if has not been loaded yet.
+   Returns a pointer to the glyph if found, or 0 if it is not found.  */
+static struct grub_font_glyph *
+grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
+{
+  struct char_index_entry *index_entry;
+
+  index_entry = find_glyph (font, code);
+  if (index_entry)
+    {
+      struct grub_font_glyph *glyph = 0;
+      grub_uint16_t width;
+      grub_uint16_t height;
+      grub_int16_t xoff;
+      grub_int16_t yoff;
+      grub_int16_t dwidth;
+      int len;
+
+      if (index_entry->glyph)
+        /* Return cached glyph.  */
+        return index_entry->glyph;
+
+      if (! font->file)
+        /* No open file, can't load any glyphs.  */
+        return 0;     
+
+      /* Make sure we can find glyphs for error messages.  Push active
+         error message to error stack and reset error message.  */
+      grub_error_push ();
+
+      grub_file_seek (font->file, index_entry->offset);
+
+      /* Read the glyph width, height, and baseline.  */
+      if (read_be_uint16(font->file, &width) != 0
+          || read_be_uint16(font->file, &height) != 0
+          || read_be_int16(font->file, &xoff) != 0
+          || read_be_int16(font->file, &yoff) != 0
+          || read_be_int16(font->file, &dwidth) != 0)
+        {
+          remove_font (font);
+          return 0;
+        }
+
+      len = (width * height + 7) / 8;
+      glyph = grub_malloc (sizeof (struct grub_font_glyph) + len);
+      if (! glyph)
+        {
+          remove_font (font);
+          return 0;
+        }
+
+      glyph->font = font;
+      glyph->width = width;
+      glyph->height = height;
+      glyph->offset_x = xoff;
+      glyph->offset_y = yoff;
+      glyph->device_width = dwidth;
+
+      /* Don't try to read empty bitmaps (e.g., space characters).  */
+      if (len != 0)
+        {
+          if (grub_file_read (font->file, (char *) glyph->bitmap, len) != len)
+            {
+              remove_font (font);
+              return 0;
+            }
+        }
+
+      /* Restore old error message.  */
+      grub_error_pop ();
+
+      /* Cache the glyph.  */
+      index_entry->glyph = glyph;
+
+      return glyph;
+    }
+
+  return 0;
+}
+
+/* Free the memory used by FONT.
+   This should not be called if the font has been made available to
+   users (once it is added to the global font list), since there would
+   be the possibility of a dangling pointer.  */
+static void
+free_font (grub_font_t font)
+{
+  if (font)
+    {
+      if (font->file)
+        grub_file_close (font->file);
+      grub_free (font->name);
+      grub_free (font->family);
+      grub_free (font->char_index);
+      grub_free (font);
+    }
+}
+
+/* Add FONT to the global font registry.
+   Returns 0 upon success, nonzero on failure
+   (the font was not registered).  */
+static int
+register_font (grub_font_t font)
+{
+  struct grub_font_node *node = 0;
+
+  node = grub_malloc (sizeof (struct grub_font_node));
+  if (! node)
+    return 1;
+
+  node->value = font;
+  node->next = grub_font_list;
+  grub_font_list = node;
+
+  return 0;
+}
+
+/* Remove the font from the global font list.  We don't actually free the
+   font's memory since users could be holding references to the font.  */
+static void
+remove_font (grub_font_t font)
+{
+  struct grub_font_node **nextp, *cur;
+
+  for (nextp = &grub_font_list, cur = *nextp;
+       cur;
+       nextp = &cur->next, cur = cur->next)
+    {
+      if (cur->value == font)
+        {
+          *nextp = cur->next;
+
+          /* Free the node, but not the font itself.  */
+          grub_free (cur);
+
+          return;
+        }
+    }
+}
+
+/* Get a font from the list of loaded fonts.  This function will return
+   another font if the requested font is not available.  If no fonts are
+   loaded, then a special 'null font' is returned, which contains no glyphs,
+   but is not a null pointer so the caller may omit checks for NULL.  */
+grub_font_t
+grub_font_get (const char *font_name)
+{
+  struct grub_font_node *node;
+
+  for (node = grub_font_list; node; node = node->next)
+    {
+      grub_font_t font = node->value;
+      if (grub_strcmp (font->name, font_name) == 0)
+        return font;
+    }
+
+  /* If no font by that name is found, return the first font in the list
+     as a fallback.  */
+  if (grub_font_list && grub_font_list->value)
+    return grub_font_list->value;
+  else
+    /* The null_font is a last resort.  */
+    return &null_font;
+}
+
+/* Get the full name of the font.  For instance, "Helvetica Bold 12".  */
+const char *
+grub_font_get_name (grub_font_t font)
+{
+  return font->name;
+}
+
+/* Get the maximum width of any character in the font in pixels.  */
+int
+grub_font_get_max_char_width (grub_font_t font)
+{
+  return font->max_char_width;
+}
+
+/* Get the maximum height of any character in the font in pixels.  */
+int
+grub_font_get_max_char_height (grub_font_t font)
+{
+  return font->max_char_height;
+}
+
+/* Get the distance in pixels from the top of characters to the baseline.  */
+int
+grub_font_get_ascent (grub_font_t font)
+{
+  return font->ascent;
+}
+
+/* Get the distance in pixels from the baseline to the lowest descenders
+   (for instance, in a lowercase 'y', 'g', etc.).  */
+int
+grub_font_get_descent (grub_font_t font)
+{
+  return font->descent;
+}
+
+/* Get the *standard leading* of the font in pixel, which is the spacing
+   between two lines of text.  Specifically, it is the space between the
+   descent of one line and the ascent of the next line.  This is included
+   in the *height* metric.  */
+int
+grub_font_get_leading (grub_font_t font)
+{
+  return font->leading;
+}
+
+/* Get the distance in pixels between baselines of adjacent lines of text.  */
+int
+grub_font_get_height (grub_font_t font)
+{
+  return font->ascent + font->descent + font->leading;
+}
+
+/* Get the width in pixels of the specified UTF-8 string, when rendered in
+   in the specified font (but falling back on other fonts for glyphs that
+   are missing).  */
+int
+grub_font_get_string_width (grub_font_t font, const char *str)
+{
+  int width;
+  struct grub_font_glyph *glyph;
+  grub_uint32_t code;
+  const grub_uint8_t *ptr;
+
+  for (ptr = (const grub_uint8_t *) str, width = 0;
+       grub_utf8_to_ucs4 (&code, 1, ptr, -1, &ptr) > 0; )
+    {
+      glyph = grub_font_get_glyph_with_fallback (font, code);
+      width += glyph->device_width;
+    }
+
+  return width;
+}
+
+/* Get the glyph for FONT corresponding to the Unicode code point CODE.
+   Returns a pointer to an glyph indicating there is no glyph available
+   if CODE does not exist in the font.  The glyphs are cached once loaded.  */
+struct grub_font_glyph *
+grub_font_get_glyph (grub_font_t font, grub_uint32_t code)
+{
+  struct grub_font_glyph *glyph;
+  glyph = grub_font_get_glyph_internal (font, code);
+  if (glyph == 0)
+    glyph = unknown_glyph;
+  return glyph;
+}
+
+
+/* Calculate a subject value representing "how similar" two fonts are.
+   This is used to prioritize the order that fonts are scanned for missing
+   glyphs.  The object is to select glyphs from the most similar font
+   possible, for the best appearance.
+   The heuristic is crude, but it helps greatly when fonts of similar
+   sizes are used so that tiny 8 point glyphs are not mixed into a string
+   of 24 point text unless there is no other choice.  */
+static int
+get_font_diversity(grub_font_t a, grub_font_t b)
+{
+  int d;
+
+  d = 0;
+
+  if (a->ascent && b->ascent)
+    d += grub_abs (a->ascent - b->ascent) * 8;
+  else
+    /* Penalty for missing attributes.  */
+    d += 50;
+
+  if (a->max_char_height && b->max_char_height)
+    d += grub_abs (a->max_char_height - b->max_char_height) * 8;
+  else
+    /* Penalty for missing attributes.  */
+    d += 50;
+  
+  /* Weight is a minor factor. */
+  d += (a->weight != b->weight) ? 5 : 0;
+
+  return d;
+}
+
+/* Get a glyph corresponding to the codepoint CODE.  If FONT contains the
+   specified glyph, then it is returned.  Otherwise, all other loaded fonts
+   are searched until one is found that contains a glyph for CODE.
+   If no glyph is available for CODE in the loaded fonts, then a glyph
+   representing an unknown character is returned.
+   This function never returns NULL.
+   The returned glyph is owned by the font manager and should not be freed
+   by the caller.  The glyphs are cached.  */
+struct grub_font_glyph *
+grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code)
+{
+  struct grub_font_glyph *glyph;
+  struct grub_font_node *node;
+  /* Keep track of next node, in case there's an I/O error in
+     grub_font_get_glyph_internal() and the font is removed from the list.  */
+  struct grub_font_node *next;
+  /* Information on the best glyph found so far, to help find the glyph in
+     the best matching to the requested one.  */
+  int best_diversity;
+  struct grub_font_glyph *best_glyph;
+
+  if (font)
+    {
+      /* First try to get the glyph from the specified font.  */
+      glyph = grub_font_get_glyph_internal (font, code);
+      if (glyph)
+        return glyph;
+    }
+
+  /* Otherwise, search all loaded fonts for the glyph and use the one from
+     the font that best matches the requested font.  */
+  best_diversity = 10000;
+  best_glyph = 0;
+
+  for (node = grub_font_list; node; node = next)
+    {
+      grub_font_t curfont;
+
+      curfont = node->value;
+      next = node->next;
+
+      glyph = grub_font_get_glyph_internal (curfont, code);
+      if (glyph)
+        {
+          int d;
+
+          d = get_font_diversity (curfont, font);
+          if (d < best_diversity)
+            {
+              best_diversity = d;
+              best_glyph = glyph;
+            }
+        }
+    }
+
+  if (best_glyph)
+    return best_glyph;
+  else
+    /* Glyph not available in any font.  Return unknown glyph.  */
+    return unknown_glyph;
+}
+
+
+/* Draw the specified glyph at (x, y).  The y coordinate designates the
+   baseline of the character, while the x coordinate designates the left
+   side location of the character.  */
+grub_err_t
+grub_font_draw_glyph (struct grub_font_glyph *glyph,
+                      grub_video_color_t color,
+                      int left_x, int baseline_y)
+{
+  struct grub_video_bitmap glyph_bitmap;
+
+  /* Don't try to draw empty glyphs (U+0020, etc.).  */
+  if (glyph->width == 0 || glyph->height == 0)
+    return GRUB_ERR_NONE;
+
+  glyph_bitmap.mode_info.width = glyph->width;
+  glyph_bitmap.mode_info.height = glyph->height;
+  glyph_bitmap.mode_info.mode_type =
+    (1 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
+    | GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP;
+  glyph_bitmap.mode_info.blit_format = GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED;
+  glyph_bitmap.mode_info.bpp = 1;
+  
+  /* Really 1 bit per pixel.  */
+  glyph_bitmap.mode_info.bytes_per_pixel = 0;
+  
+  /* Packed densely as bits.  */
+  glyph_bitmap.mode_info.pitch = glyph->width;
+  
+  glyph_bitmap.mode_info.number_of_colors = 2;
+  glyph_bitmap.mode_info.bg_red = 0;
+  glyph_bitmap.mode_info.bg_green = 0;
+  glyph_bitmap.mode_info.bg_blue = 0;
+  glyph_bitmap.mode_info.bg_alpha = 0;
+  grub_video_unmap_color(color,
+                         &glyph_bitmap.mode_info.fg_red,
+                         &glyph_bitmap.mode_info.fg_green,
+                         &glyph_bitmap.mode_info.fg_blue,
+                         &glyph_bitmap.mode_info.fg_alpha);
+  glyph_bitmap.data = glyph->bitmap;
+
+  int bitmap_left = left_x + glyph->offset_x;
+  int bitmap_bottom = baseline_y - glyph->offset_y;
+  int bitmap_top = bitmap_bottom - glyph->height;
+
+  return grub_video_blit_bitmap (&glyph_bitmap, GRUB_VIDEO_BLIT_BLEND,
+                                 bitmap_left, bitmap_top,
+                                 0, 0,
+                                 glyph->width, glyph->height);
+}
+
+/* Draw a UTF-8 string of text on the current video render target.
+   The x coordinate specifies the starting x position for the first character,
+   while the y coordinate specifies the baseline position.
+   If the string contains a character that FONT does not contain, then
+   a glyph from another loaded font may be used instead.  */
+grub_err_t
+grub_font_draw_string (const char *str, grub_font_t font,
+                       grub_video_color_t color,
+                       int left_x, int baseline_y)
+{
+  int x;
+  struct grub_font_glyph *glyph;
+  grub_uint32_t code;
+  const grub_uint8_t *ptr;
+
+  for (ptr = (const grub_uint8_t *) str, x = left_x;
+       grub_utf8_to_ucs4 (&code, 1, ptr, -1, &ptr) > 0; )
+    {
+      glyph = grub_font_get_glyph_with_fallback (font, code);
+      if (grub_font_draw_glyph (glyph, color, x, baseline_y)
+          != GRUB_ERR_NONE)
+        return grub_errno;
+      x += glyph->device_width;
+    }
+
+  return GRUB_ERR_NONE;
+}
+
diff --git a/font/font_cmd.c b/font/font_cmd.c
new file mode 100644 (file)
index 0000000..6cbae5b
--- /dev/null
@@ -0,0 +1,77 @@
+/* font_cmd.c - Font command definition. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,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/>.
+ */
+
+#include <grub/font.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/misc.h>
+
+static grub_err_t
+loadfont_command (struct grub_arg_list *state __attribute__ ((unused)),
+             int argc,
+             char **args)
+{
+  if (argc == 0)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "no font specified");
+
+  while (argc--)
+    if (grub_font_load (*args++) != 0)
+      return GRUB_ERR_BAD_FONT;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+lsfonts_command (struct grub_arg_list *state __attribute__ ((unused)),
+                 int argc __attribute__ ((unused)),
+                 char **args __attribute__ ((unused)))
+{
+  struct grub_font_node *node;
+
+  grub_printf ("Loaded fonts:\n");
+  for (node = grub_font_list; node; node = node->next)
+    {
+      grub_font_t font = node->value;
+      grub_printf ("%s\n", grub_font_get_name (font));
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+GRUB_MOD_INIT(font_manager)
+{
+  grub_font_loader_init ();
+
+  grub_register_command ("loadfont", loadfont_command, GRUB_COMMAND_FLAG_BOTH,
+                        "loadfont FILE...",
+                        "Specify one or more font files to load.", 0);
+
+  grub_register_command ("lsfonts", lsfonts_command, GRUB_COMMAND_FLAG_BOTH,
+                        "lsfonts",
+                        "List the loaded fonts.", 0);
+}
+
+GRUB_MOD_FINI(font_manager)
+{
+  /* TODO: Determine way to free allocated resources.  
+     Warning: possible pointer references could be in use.  */
+
+  grub_unregister_command ("loadfont");
+}
+
diff --git a/fs/affs.c b/fs/affs.c
new file mode 100644 (file)
index 0000000..bc7bc21
--- /dev/null
+++ b/fs/affs.c
@@ -0,0 +1,570 @@
+/* affs.c - Amiga Fast FileSystem.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2006,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/>.
+ */
+
+#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>
+
+/* The affs bootblock.  */
+struct grub_affs_bblock
+{
+  grub_uint8_t type[3];
+  grub_uint8_t flags;
+  grub_uint32_t checksum;
+  grub_uint32_t rootblock;
+} __attribute__ ((packed));
+
+/* Set if the filesystem is a AFFS filesystem.  Otherwise this is an
+   OFS filesystem.  */
+#define GRUB_AFFS_FLAG_FFS     1
+
+/* The affs rootblock.  */
+struct grub_affs_rblock
+{
+  grub_uint8_t type[4];
+  grub_uint8_t unused1[8];
+  grub_uint32_t htsize;
+  grub_uint32_t unused2;
+  grub_uint32_t checksum;
+  grub_uint32_t hashtable[1];
+} __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 namelen;
+  grub_uint8_t name[30];
+  grub_uint8_t unused3[33];
+  grub_uint32_t next;
+  grub_uint32_t parent;
+  grub_uint32_t extension;
+  grub_int32_t type;
+} __attribute__ ((packed));
+
+/* The location of `struct grub_affs_file' relative to the end of a
+   file header block.  */
+#define        GRUB_AFFS_FILE_LOCATION         200
+
+/* The offset in both the rootblock and the file header block for the
+   hashtable, symlink and block pointers (all synonyms).  */
+#define GRUB_AFFS_HASHTABLE_OFFSET     24
+#define GRUB_AFFS_BLOCKPTR_OFFSET      24
+#define GRUB_AFFS_SYMLINK_OFFSET       24
+
+#define GRUB_AFFS_SYMLINK_SIZE(blocksize) ((blocksize) - 225)
+
+#define GRUB_AFFS_FILETYPE_DIR         -3
+#define GRUB_AFFS_FILETYPE_REG         2
+#define GRUB_AFFS_FILETYPE_SYMLINK     3
+\f
+
+struct grub_fshelp_node
+{
+  struct grub_affs_data *data;
+  int block;
+  int size;
+  int parent;
+};
+
+/* Information about a "mounted" affs filesystem.  */
+struct grub_affs_data
+{
+  struct grub_affs_bblock bblock;
+  struct grub_fshelp_node diropen;
+  grub_disk_t disk;
+
+  /* Blocksize in sectors.  */
+  int blocksize;
+
+  /* The number of entries in the hashtable.  */
+  int htsize;
+};
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+\f
+static grub_disk_addr_t
+grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
+{
+  int links;
+  grub_uint32_t pos;
+  int block = node->block;
+  struct grub_affs_file file;
+  struct grub_affs_data *data = node->data;
+  grub_uint32_t mod;
+
+  /* Find the block that points to the fileblock we are looking up by
+     following the chain until the right table is reached.  */
+  for (links = grub_divmod64 (fileblock, data->htsize, &mod); links; links--)
+    {
+      grub_disk_read (data->disk, block + data->blocksize - 1,
+                     data->blocksize * (GRUB_DISK_SECTOR_SIZE
+                                        - GRUB_AFFS_FILE_LOCATION),
+                     sizeof (file), (char *) &file);
+      if (grub_errno)
+       return 0;
+         
+      block = grub_be_to_cpu32 (file.extension);
+    }
+
+  /* Translate the fileblock to the block within the right table.  */
+  fileblock = mod;
+  grub_disk_read (data->disk, block,
+                 GRUB_AFFS_BLOCKPTR_OFFSET
+                 + (data->htsize - fileblock - 1) * sizeof (pos),
+                 sizeof (pos), (char *) &pos);
+  if (grub_errno)
+    return 0;
+  
+  return grub_be_to_cpu32 (pos);
+}
+
+
+/* Read LEN bytes from the file described by DATA starting with byte
+   POS.  Return the amount of read bytes in READ.  */
+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)
+{
+  return grub_fshelp_read_file (node->data->disk, node, read_hook,
+                               pos, len, buf, grub_affs_read_block,
+                               node->size, 0);
+}
+
+
+static struct grub_affs_data *
+grub_affs_mount (grub_disk_t disk)
+{
+  struct grub_affs_data *data;
+  grub_uint32_t *rootblock = 0;
+  struct grub_affs_rblock *rblock;
+
+  int checksum = 0;
+  int checksumr = 0;
+  int blocksize = 0;
+
+  data = grub_malloc (sizeof (struct grub_affs_data));
+  if (!data)
+    return 0;
+
+  /* Read the bootblock.  */
+  grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock),
+                 (char *) &data->bblock);
+  if (grub_errno)
+    goto fail;
+
+  /* Make sure this is an affs filesystem.  */
+  if (grub_strncmp ((char *) (data->bblock.type), "DOS", 3))
+    {
+      grub_error (GRUB_ERR_BAD_FS, "not an affs filesystem");
+      goto fail;
+    }
+
+  /* Test if the filesystem is a OFS filesystem.  */
+  if (! (data->bblock.flags & GRUB_AFFS_FLAG_FFS))
+    {
+      grub_error (GRUB_ERR_BAD_FS, "ofs not yet supported");
+      goto fail;
+    }
+
+  /* Read the bootblock.  */
+  grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock),
+                 (char *) &data->bblock);
+  if (grub_errno)
+    goto fail;
+
+  /* No sane person uses more than 8KB for a block.  At least I hope
+     for that person because in that case this won't work.  */
+  rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE * 16);
+  if (!rootblock)
+    goto fail;
+
+  rblock = (struct grub_affs_rblock *) rootblock;
+
+  /* Read the rootblock.  */
+  grub_disk_read (disk, (disk->total_sectors >> 1) + blocksize, 0,
+                 GRUB_DISK_SECTOR_SIZE * 16, (char *) rootblock);
+  if (grub_errno)
+    goto fail;
+
+  /* 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;
+      unsigned int i;
+
+      for (i = 0; i < GRUB_DISK_SECTOR_SIZE / sizeof (*currblock); i++)
+       checksum += grub_be_to_cpu32 (currblock[i]);
+
+      if (checksumr == -checksum)
+       break;
+    }
+  if (-checksum != checksumr)
+    {
+      grub_error (GRUB_ERR_BAD_FS, "affs blocksize could not be determined");
+      goto fail;
+    }
+  blocksize++;
+
+  data->blocksize = blocksize;
+  data->disk = disk;
+  data->htsize = grub_be_to_cpu32 (rblock->htsize);
+  data->diropen.data = data;
+  data->diropen.block = (disk->total_sectors >> 1);
+
+  grub_free (rootblock);
+
+  return data;
+
+ fail:
+  if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+    grub_error (GRUB_ERR_BAD_FS, "not an affs filesystem");
+
+  grub_free (data);
+  grub_free (rootblock);
+  return 0;
+}
+
+
+static char *
+grub_affs_read_symlink (grub_fshelp_node_t node)
+{
+  struct grub_affs_data *data = node->data;
+  char *symlink;
+
+  symlink = grub_malloc (GRUB_AFFS_SYMLINK_SIZE (data->blocksize));
+  if (!symlink)
+    return 0;
+
+  grub_disk_read (data->disk, node->block, GRUB_AFFS_SYMLINK_OFFSET,
+                 GRUB_AFFS_SYMLINK_SIZE (data->blocksize), symlink);
+  if (grub_errno)
+    {
+      grub_free (symlink);
+      return 0;
+    }
+  grub_printf ("Symlink: `%s'\n", symlink);
+  return symlink;
+}
+
+
+static int
+grub_affs_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))
+{
+  int i;
+  struct grub_affs_file file;
+  struct grub_fshelp_node *node = 0;
+  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);
+
+  int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int block,
+                                             int size, int type)
+    {
+      node = grub_malloc (sizeof (*node));
+      if (!node)
+       {
+         grub_free (hashtable);
+         return 1;
+       }
+
+      node->data = data;
+      node->size = size;
+      node->block = block;
+      node->parent = grub_be_to_cpu32 (file.parent);
+
+      if (hook (name, type, node))
+       {
+         grub_free (hashtable);
+         return 1;
+       }
+      return 0;
+    }
+
+  hashtable = grub_malloc (data->htsize * sizeof (*hashtable));
+  if (!hashtable)
+    return 1;
+
+  grub_disk_read (data->disk, dir->block, GRUB_AFFS_HASHTABLE_OFFSET,
+                 data->htsize * sizeof (*hashtable), (char *) hashtable);
+  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])
+       continue;
+
+      /* Every entry in the hashtable can be chained.  Read the entire
+        chain.  */
+      next = grub_be_to_cpu32 (hashtable[i]);
+
+      while (next)
+       {
+         grub_disk_read (data->disk, next + data->blocksize - 1,
+                         data->blocksize * GRUB_DISK_SECTOR_SIZE
+                         - GRUB_AFFS_FILE_LOCATION,
+                         sizeof (file), (char *) &file);
+         if (grub_errno)
+           goto fail;
+         
+         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))
+           return 1;
+
+         next = grub_be_to_cpu32 (file.next);
+       }      
+    }
+
+  grub_free (hashtable);
+  return 0;
+
+ fail:
+  grub_free (node);
+  grub_free (hashtable);
+  return 0;
+}
+
+
+/* Open a file named NAME and initialize FILE.  */
+static grub_err_t
+grub_affs_open (struct grub_file *file, const char *name)
+{
+  struct grub_affs_data *data;
+  struct grub_fshelp_node *fdiro = 0;
+  
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  
+  data = grub_affs_mount (file->device->disk);
+  if (!data)
+    goto fail;
+  
+  grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_affs_iterate_dir,
+                        grub_affs_read_symlink, GRUB_FSHELP_REG);
+  if (grub_errno)
+    goto fail;
+  
+  file->size = fdiro->size;
+  data->diropen = *fdiro;
+  grub_free (fdiro);
+
+  file->data = data;
+  file->offset = 0;
+
+  return 0;
+
+ fail:
+  if (data && fdiro != &data->diropen)
+    grub_free (fdiro);
+  grub_free (data);
+  
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+
+static grub_err_t
+grub_affs_close (grub_file_t file)
+{
+  grub_free (file->data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
+
+/* Read LEN bytes data from FILE into BUF.  */
+static grub_ssize_t
+grub_affs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_affs_data *data = 
+    (struct grub_affs_data *) file->data;
+
+  int size = grub_affs_read_file (&data->diropen, file->read_hook,
+                             file->offset, len, buf);
+
+  return size;
+}
+
+
+static grub_err_t
+grub_affs_dir (grub_device_t device, const char *path, 
+              int (*hook) (const char *filename, int dir))
+{
+  struct grub_affs_data *data = 0;
+  struct grub_fshelp_node *fdiro = 0;
+  
+  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)
+    {
+      grub_free (node);
+      
+      if (filetype == GRUB_FSHELP_DIR)
+       return hook (filename, 1);
+      else 
+       return hook (filename, 0);
+      
+      return 0;
+    }
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  
+  data = grub_affs_mount (device->disk);
+  if (!data)
+    goto fail;
+  
+  grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_affs_iterate_dir,
+                        grub_affs_read_symlink, GRUB_FSHELP_DIR);
+  if (grub_errno)
+    goto fail;
+
+  grub_affs_iterate_dir (fdiro, iterate);
+  
+ fail:
+  if (data && fdiro != &data->diropen)
+    grub_free (fdiro);
+  grub_free (data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+
+static grub_err_t
+grub_affs_label (grub_device_t device, char **label)
+{
+  struct grub_affs_data *data;
+  struct grub_affs_file file;
+  grub_disk_t disk = device->disk;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_affs_mount (disk);
+  if (data)
+    {
+      /* The rootblock maps quite well on a file header block, it's
+        something we can use here.  */
+      grub_disk_read (data->disk, disk->total_sectors >> 1,
+                     data->blocksize * (GRUB_DISK_SECTOR_SIZE
+                                        - GRUB_AFFS_FILE_LOCATION),
+                     sizeof (file), (char *) &file);
+      if (grub_errno)
+       return 0;
+
+      *label = grub_strndup ((char *) (file.name), file.namelen);
+    }
+  else
+    *label = 0;
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+}
+
+\f
+static struct grub_fs grub_affs_fs =
+  {
+    .name = "affs",
+    .dir = grub_affs_dir,
+    .open = grub_affs_open,
+    .read = grub_affs_read,
+    .close = grub_affs_close,
+    .label = grub_affs_label,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(affs)
+{
+  grub_fs_register (&grub_affs_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(affs)
+{
+  grub_fs_unregister (&grub_affs_fs);
+}
diff --git a/fs/afs.c b/fs/afs.c
new file mode 100644 (file)
index 0000000..3f7efa7
--- /dev/null
+++ b/fs/afs.c
@@ -0,0 +1,636 @@
+/* afs.c - The native AtheOS file-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/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>
+
+#define        GRUB_AFS_DIRECT_BLOCK_COUNT     12
+#define        GRUB_AFS_BLOCKS_PER_DI_RUN      4
+
+#define        GRUB_AFS_SBLOCK_MAGIC1  0x41465331      /* AFS1 */
+#define        GRUB_AFS_SBLOCK_MAGIC2  0xdd121031
+#define        GRUB_AFS_SBLOCK_MAGIC3  0x15b6830e
+
+#define        GRUB_AFS_INODE_MAGIC    0x64358428
+
+#define GRUB_AFS_BTREE_MAGIC   0x65768995
+
+#define GRUB_AFS_BNODE_SIZE    1024
+
+#define GRUB_AFS_S_IFMT                00170000
+#define GRUB_AFS_S_IFLNK       0120000
+
+#define GRUB_AFS_S_IFREG       0100000
+#define GRUB_AFS_S_IFDIR       0040000
+#define GRUB_AFS_S_IFIFO       0010000
+
+#define GRUB_AFS_NULL_VAL      ((grub_afs_bvalue_t)-1)
+
+#define U16(sb, u) (((sb)->byte_order == GRUB_AFS_BO_LITTLE_ENDIAN) ? \
+                    grub_le_to_cpu16 (u) : grub_be_to_cpu16 (u))
+
+#define U32(sb, u) (((sb)->byte_order == GRUB_AFS_BO_LITTLE_ENDIAN) ? \
+                    grub_le_to_cpu32 (u) : grub_be_to_cpu32 (u))
+
+#define U64(sb, u) (((sb)->byte_order == GRUB_AFS_BO_LITTLE_ENDIAN) ? \
+                    grub_le_to_cpu64 (u) : grub_be_to_cpu64 (u))
+
+#define B_KEY_INDEX_OFFSET(node) ((grub_uint16_t *) \
+                                   ((char *) (node) + \
+                                    sizeof (struct grub_afs_bnode) + \
+                                    ((node->key_size + 3) & ~3)))
+
+#define B_KEY_VALUE_OFFSET(node) ((grub_afs_bvalue_t *) \
+                                   ((char *) B_KEY_INDEX_OFFSET (node) + \
+                                    node->key_count * 2))
+
+enum
+{
+  GRUB_AFS_BO_LITTLE_ENDIAN,
+  GRUB_AFS_BO_BIG_ENDIAN
+};
+
+typedef grub_uint64_t grub_afs_off_t;
+typedef grub_uint64_t grub_afs_bigtime;
+typedef grub_uint64_t grub_afs_bvalue_t;
+
+struct grub_afs_blockrun
+{
+  grub_uint32_t group;
+  grub_uint16_t start;
+  grub_uint16_t len;
+};
+
+struct grub_afs_datastream
+{
+  struct grub_afs_blockrun direct[GRUB_AFS_DIRECT_BLOCK_COUNT];
+  grub_afs_off_t max_direct_range;
+  struct grub_afs_blockrun indirect;
+  grub_afs_off_t max_indirect_range;
+  struct grub_afs_blockrun double_indirect;
+  grub_afs_off_t max_double_indirect_range;
+  grub_afs_off_t size;
+};
+
+struct grub_afs_bnode
+{
+  grub_afs_bvalue_t left;
+  grub_afs_bvalue_t right;
+  grub_afs_bvalue_t overflow;
+  grub_uint32_t key_count;
+  grub_uint32_t key_size;
+  char key_data[0];
+};
+
+struct grub_afs_btree
+{
+  grub_uint32_t magic;
+  grub_afs_bvalue_t root;
+  grub_uint32_t tree_depth;
+  grub_afs_bvalue_t last_node;
+  grub_afs_bvalue_t first_free;
+} ;
+
+struct grub_afs_sblock
+{
+  grub_uint8_t name[32];
+  grub_uint32_t magic1;
+  grub_uint32_t byte_order;
+  grub_uint32_t        block_size;
+  grub_uint32_t block_shift;
+  grub_afs_off_t num_blocks;
+  grub_afs_off_t used_blocks;
+  grub_uint32_t        inode_size;
+  grub_uint32_t        magic2;
+  grub_uint32_t        block_per_group;        // Number of blocks per allocation group (Max 65536)
+  grub_uint32_t        alloc_group_shift;      // Number of bits to shift a group number to get a byte address.
+  grub_uint32_t        alloc_group_count;
+  grub_uint32_t        flags;
+  struct grub_afs_blockrun log_block;
+  grub_afs_off_t log_start;
+  grub_uint32_t valid_log_blocks;
+  grub_uint32_t log_size;
+  grub_uint32_t        magic3;
+  struct grub_afs_blockrun root_dir;   // Root dir inode.
+  struct grub_afs_blockrun deleted_files; // Directory containing files scheduled for deletion.
+  struct grub_afs_blockrun index_dir;  // Directory of index files.
+  grub_uint32_t boot_loader_size;
+  grub_uint32_t        pad[7];
+};
+
+struct grub_afs_inode
+{
+  grub_uint32_t magic1;
+  struct grub_afs_blockrun inode_num;
+  grub_uint32_t uid;
+  grub_uint32_t gid;
+  grub_uint32_t mode;
+  grub_uint32_t flags;
+  grub_uint32_t link_count;
+  grub_afs_bigtime create_time;
+  grub_afs_bigtime modified_time;
+  struct grub_afs_blockrun parent;
+  struct grub_afs_blockrun attrib_dir;
+  grub_uint32_t index_type;            /* Key data-key only used for index files */
+  grub_uint32_t inode_size;
+  void* vnode;
+  struct grub_afs_datastream stream;
+  grub_uint32_t        pad[4];
+  grub_uint32_t small_data[1];
+};
+
+struct grub_fshelp_node
+{
+  struct grub_afs_data *data;
+  struct grub_afs_inode inode;
+};
+
+struct grub_afs_data
+{
+  grub_disk_t disk;
+  struct grub_afs_sblock sblock;
+  struct grub_afs_inode *inode;
+  struct grub_fshelp_node diropen;
+};
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+static grub_afs_off_t
+grub_afs_run_to_num (struct grub_afs_sblock *sb,
+                     struct grub_afs_blockrun *run)
+{
+  return ((grub_afs_off_t) U32 (sb, run->group) * sb->block_per_group +
+          U16 (sb, run->start));
+}
+
+static grub_err_t
+grub_afs_read_inode (struct grub_afs_data *data,
+                     grub_uint32_t ino, struct grub_afs_inode *inode)
+{
+  return grub_disk_read (data->disk,
+                         ino *
+                         (data->sblock.block_size >> GRUB_DISK_SECTOR_BITS),
+                         0, sizeof (struct grub_afs_inode),
+                         (char *) inode);
+}
+
+static grub_disk_addr_t
+grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
+{
+  struct grub_afs_sblock *sb = &node->data->sblock;
+  struct grub_afs_datastream *ds = &node->inode.stream;
+
+  if (fileblock < U64 (sb, ds->max_direct_range))
+    {
+      int i;
+
+      for (i = 0; i < GRUB_AFS_DIRECT_BLOCK_COUNT; i++)
+        {
+          if (fileblock < U16 (sb, ds->direct[i].len))
+            return grub_afs_run_to_num (sb, &ds->direct[i]) + fileblock;
+          fileblock -= U16 (sb, ds->direct[i].len);
+        }
+    }
+  else if (fileblock < U64 (sb, ds->max_indirect_range))
+    {
+      int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun);
+      struct grub_afs_blockrun indir[ptrs_per_blk];
+      grub_afs_off_t blk = grub_afs_run_to_num (sb, &ds->indirect);
+      int i;
+
+      fileblock -= U64 (sb, ds->max_direct_range);
+      for (i = 0; i < ds->indirect.len; i++, blk++)
+        {
+          int j;
+
+          if (grub_disk_read (node->data->disk,
+                              blk * (sb->block_size >> GRUB_DISK_SECTOR_BITS),
+                              0, sizeof (indir),
+                              (char *) indir))
+            return 0;
+
+          for (j = 0; j < ptrs_per_blk; j++)
+            {
+              if (fileblock < U16 (sb, indir[j].len))
+                return grub_afs_run_to_num (sb, &indir[j]) + fileblock;
+
+              fileblock -= U16 (sb, indir[j].len);
+            }
+        }
+    }
+  else
+    {
+      int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun);
+      struct grub_afs_blockrun indir[ptrs_per_blk];
+
+      /* ([idblk][idptr]) ([dblk][dptr]) [blk]  */
+      int cur_pos = fileblock - U64 (sb, ds->max_indirect_range);
+
+      int dptr_size = GRUB_AFS_BLOCKS_PER_DI_RUN;
+      int dblk_size = dptr_size * ptrs_per_blk;
+      int idptr_size = dblk_size * GRUB_AFS_BLOCKS_PER_DI_RUN;
+      int idblk_size = idptr_size * ptrs_per_blk;
+
+      int off = cur_pos % GRUB_AFS_BLOCKS_PER_DI_RUN;
+      int dptr = (cur_pos / dptr_size) % ptrs_per_blk;
+      int dblk = (cur_pos / dblk_size) % GRUB_AFS_BLOCKS_PER_DI_RUN;
+      int idptr = (cur_pos / idptr_size) % ptrs_per_blk;
+      int idblk = (cur_pos / idblk_size);
+
+      if (grub_disk_read (node->data->disk,
+                          (grub_afs_run_to_num (sb, &ds->double_indirect)
+                           + idblk) *
+                          (sb->block_size >> GRUB_DISK_SECTOR_BITS),
+                          0, sizeof (indir),
+                          (char *) indir))
+        return 0;
+
+      if (grub_disk_read (node->data->disk,
+                          (grub_afs_run_to_num (sb, &indir[idptr]) + dblk) *
+                          (sb->block_size >> GRUB_DISK_SECTOR_BITS),
+                          0, sizeof (indir),
+                          (char *) indir))
+        return 0;
+
+      return grub_afs_run_to_num (sb, &indir[dptr]) + off;
+    }
+
+  return 0;
+}
+
+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)
+{
+  return grub_fshelp_read_file (node->data->disk, node, read_hook,
+                               pos, len, buf, grub_afs_read_block,
+                                U64 (&node->data->sblock,
+                                     node->inode.stream.size),
+                               node->data->sblock.block_shift
+                                - GRUB_DISK_SECTOR_BITS);
+}
+
+static int
+grub_afs_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))
+{
+  struct grub_afs_btree head;
+  char node_data [GRUB_AFS_BNODE_SIZE];
+  struct grub_afs_bnode *node = (struct grub_afs_bnode *) node_data;
+  struct grub_afs_sblock *sb = &dir->data->sblock;
+  int i;
+
+  if ((! dir->inode.stream.size) ||
+      ((U32 (sb, dir->inode.mode) & GRUB_AFS_S_IFMT) != GRUB_AFS_S_IFDIR))
+    return 0;
+
+  grub_afs_read_file (dir, 0, 0, sizeof (head), (char *) &head);
+  if (grub_errno)
+    return 0;
+
+  grub_afs_read_file (dir, 0, U64 (sb, head.root),
+                      GRUB_AFS_BNODE_SIZE, (char *) node);
+  if (grub_errno)
+    return 0;
+
+  for (i = 0; i < (int) U32 (sb, head.tree_depth) - 1; i++)
+    {
+      grub_afs_bvalue_t blk;
+
+      blk = U64(sb, B_KEY_VALUE_OFFSET (node) [0]);
+      grub_afs_read_file (dir, 0, blk, GRUB_AFS_BNODE_SIZE, (char *) node);
+      if (grub_errno)
+        return 0;
+    }
+
+  if (node->key_count)
+    {
+      grub_uint32_t cur_key = 0;
+
+      while (1)
+        {
+          int key_start, key_size;
+          grub_uint16_t *index;
+
+          index = B_KEY_INDEX_OFFSET (node);
+
+          key_start = U16 (sb, (cur_key > 0) ? index[cur_key - 1] : 0);
+          key_size = U16 (sb, index[cur_key]) - key_start;
+          if (key_size)
+            {
+              char filename [key_size + 1];
+              struct grub_fshelp_node *fdiro;
+              int mode, type;
+
+              fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
+              if (! fdiro)
+                return 0;
+
+              fdiro->data = dir->data;
+              if (grub_afs_read_inode (dir->data,
+                                       U64 (sb, B_KEY_VALUE_OFFSET (node) [cur_key]),
+                                       &fdiro->inode))
+                return 0;
+
+              grub_memcpy (filename, &node->key_data[key_start], key_size);
+              filename [key_size] = 0;
+
+              mode = (U32 (sb, fdiro->inode.mode) & GRUB_AFS_S_IFMT);
+              if (mode == GRUB_AFS_S_IFDIR)
+                type = GRUB_FSHELP_DIR;
+              else if (mode == GRUB_AFS_S_IFREG)
+                type = GRUB_FSHELP_REG;
+              else
+                type = GRUB_FSHELP_UNKNOWN;
+
+              if (hook (filename, type, fdiro))
+                return 1;
+            }
+
+          cur_key++;
+          if (cur_key >= U32 (sb, node->key_count))
+            {
+              if (node->right == GRUB_AFS_NULL_VAL)
+                break;
+
+              grub_afs_read_file (dir, 0, U64 (sb, node->right),
+                                  GRUB_AFS_BNODE_SIZE, (char *) node);
+              if (grub_errno)
+                return 0;
+
+              cur_key = 0;
+            }
+        }
+    }
+
+  return 0;
+}
+
+static int
+grub_afs_validate_sblock (struct grub_afs_sblock *sb)
+{
+  if (grub_le_to_cpu32 (sb->magic1) == GRUB_AFS_SBLOCK_MAGIC1)
+    {
+      if (grub_le_to_cpu32 (sb->byte_order) != GRUB_AFS_BO_LITTLE_ENDIAN)
+        return 0;
+
+      sb->byte_order = GRUB_AFS_BO_LITTLE_ENDIAN;
+      sb->magic2 = grub_le_to_cpu32 (sb->magic2);
+      sb->magic3 = grub_le_to_cpu32 (sb->magic3);
+      sb->block_shift = grub_le_to_cpu32 (sb->block_shift);
+      sb->block_size = grub_le_to_cpu32 (sb->block_size);
+      sb->used_blocks = grub_le_to_cpu64 (sb->used_blocks);
+      sb->num_blocks = grub_le_to_cpu64 (sb->num_blocks);
+      sb->inode_size = grub_le_to_cpu32 (sb->inode_size);
+      sb->alloc_group_count = grub_le_to_cpu32 (sb->alloc_group_count);
+      sb->alloc_group_shift = grub_le_to_cpu32 (sb->alloc_group_shift);
+      sb->block_per_group = grub_le_to_cpu32 (sb->block_per_group);
+      sb->alloc_group_count = grub_le_to_cpu32 (sb->alloc_group_count);
+      sb->log_size = grub_le_to_cpu32 (sb->log_size);
+    }
+  else if (grub_be_to_cpu32 (sb->magic1) == GRUB_AFS_SBLOCK_MAGIC1)
+    {
+      if (grub_be_to_cpu32 (sb->byte_order) != GRUB_AFS_BO_BIG_ENDIAN)
+        return 0;
+
+      sb->byte_order = GRUB_AFS_BO_BIG_ENDIAN;
+      sb->magic2 = grub_be_to_cpu32 (sb->magic2);
+      sb->magic3 = grub_be_to_cpu32 (sb->magic3);
+      sb->block_shift = grub_be_to_cpu32 (sb->block_shift);
+      sb->block_size = grub_be_to_cpu32 (sb->block_size);
+      sb->used_blocks = grub_be_to_cpu64 (sb->used_blocks);
+      sb->num_blocks = grub_be_to_cpu64 (sb->num_blocks);
+      sb->inode_size = grub_be_to_cpu32 (sb->inode_size);
+      sb->alloc_group_count = grub_be_to_cpu32 (sb->alloc_group_count);
+      sb->alloc_group_shift = grub_be_to_cpu32 (sb->alloc_group_shift);
+      sb->block_per_group = grub_be_to_cpu32 (sb->block_per_group);
+      sb->alloc_group_count = grub_be_to_cpu32 (sb->alloc_group_count);
+      sb->log_size = grub_be_to_cpu32 (sb->log_size);
+    }
+  else
+    return 0;
+
+  if ((sb->magic2 != GRUB_AFS_SBLOCK_MAGIC2) ||
+      (sb->magic3 != GRUB_AFS_SBLOCK_MAGIC3))
+    return 0;
+
+  if (((grub_uint32_t) (1 << sb->block_shift) != sb->block_size) ||
+      (sb->used_blocks > sb->num_blocks ) ||
+      (sb->inode_size != sb->block_size) ||
+      (0 == sb->block_size) ||
+      ((grub_uint32_t) (1 << sb->alloc_group_shift) !=
+       sb->block_per_group * sb->block_size) ||
+      (sb->alloc_group_count * sb->block_per_group < sb->num_blocks) ||
+      (U16 (sb, sb->log_block.len) != sb->log_size) ||
+      (U32 (sb, sb->valid_log_blocks) > sb->log_size))
+    return 0;
+
+  return 1;
+}
+
+static struct grub_afs_data *
+grub_afs_mount (grub_disk_t disk)
+{
+  struct grub_afs_data *data = 0;
+
+  data = grub_malloc (sizeof (struct grub_afs_data));
+  if (!data)
+    return 0;
+
+  /* Read the superblock.  */
+  if (grub_disk_read (disk, 1 * 2, 0, sizeof (struct grub_afs_sblock),
+                      (char *) &data->sblock))
+    goto fail;
+
+  if (! grub_afs_validate_sblock (&data->sblock))
+    {
+      if (grub_disk_read (disk, 1 * 2, 0, sizeof (struct grub_afs_sblock),
+                          (char *) &data->sblock))
+        goto fail;
+
+      if (! grub_afs_validate_sblock (&data->sblock))
+        goto fail;
+    }
+
+  data->diropen.data = data;
+  data->inode = &data->diropen.inode;
+  data->disk = disk;
+
+  if (grub_afs_read_inode (data,
+                           grub_afs_run_to_num (&data->sblock,
+                                                &data->sblock.root_dir),
+                           data->inode))
+    goto fail;
+
+  return data;
+
+fail:
+  grub_error (GRUB_ERR_BAD_FS, "not an afs filesystem");
+  grub_free (data);
+  return 0;
+}
+
+static grub_err_t
+grub_afs_open (struct grub_file *file, const char *name)
+{
+  struct grub_afs_data *data;
+  struct grub_fshelp_node *fdiro = 0;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_afs_mount (file->device->disk);
+  if (! data)
+    goto fail;
+
+  grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_afs_iterate_dir,
+                        0, GRUB_FSHELP_REG);
+  if (grub_errno)
+    goto fail;
+
+  grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_afs_inode));
+  grub_free (fdiro);
+
+  file->size = U64 (&data->sblock, data->inode->stream.size);
+  file->data = data;
+  file->offset = 0;
+
+  return 0;
+
+fail:
+  if (fdiro != &data->diropen)
+    grub_free (fdiro);
+  grub_free (data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+static grub_ssize_t
+grub_afs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_afs_data *data = (struct grub_afs_data *) file->data;
+
+  return grub_afs_read_file (&data->diropen, file->read_hook,
+                             file->offset, len, buf);
+}
+
+static grub_err_t
+grub_afs_close (grub_file_t file)
+{
+  grub_free (file->data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_afs_dir (grub_device_t device, const char *path,
+              int (*hook) (const char *filename, int dir))
+{
+  struct grub_afs_data *data = 0;;
+  struct grub_fshelp_node *fdiro = 0;
+
+  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)
+    {
+      grub_free (node);
+
+      if (filetype == GRUB_FSHELP_DIR)
+       return hook (filename, 1);
+      else
+       return hook (filename, 0);
+
+      return 0;
+    }
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_afs_mount (device->disk);
+  if (! data)
+    goto fail;
+
+  grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_afs_iterate_dir,
+                        0, GRUB_FSHELP_DIR);
+  if (grub_errno)
+    goto fail;
+
+  grub_afs_iterate_dir (fdiro, iterate);
+
+ fail:
+  if (fdiro != &data->diropen)
+    grub_free (fdiro);
+  grub_free (data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+static struct grub_fs grub_afs_fs = {
+  .name = "afs",
+  .dir = grub_afs_dir,
+  .open = grub_afs_open,
+  .read = grub_afs_read,
+  .close = grub_afs_close,
+  .label = 0,
+  .next = 0
+};
+
+GRUB_MOD_INIT (afs)
+{
+  grub_fs_register (&grub_afs_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI (afs)
+{
+  grub_fs_unregister (&grub_afs_fs);
+}
diff --git a/fs/cpio.c b/fs/cpio.c
new file mode 100644 (file)
index 0000000..3d8078a
--- /dev/null
+++ b/fs/cpio.c
@@ -0,0 +1,380 @@
+/* cpio.c - cpio and tar filesystem.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007,2008 Free Software Foundation, Inc.
+ *
+ *  This program 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.
+ *
+ *  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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+
+#define        MAGIC_BCPIO     070707
+
+struct HEAD_BCPIO
+{
+  grub_uint16_t magic;
+  grub_uint16_t dev;
+  grub_uint16_t ino;
+  grub_uint16_t mode;
+  grub_uint16_t uid;
+  grub_uint16_t gid;
+  grub_uint16_t nlink;
+  grub_uint16_t rdev;
+  grub_uint16_t mtime_1;
+  grub_uint16_t mtime_2;
+  grub_uint16_t namesize;
+  grub_uint16_t filesize_1;
+  grub_uint16_t filesize_2;
+} __attribute__ ((packed));
+
+#define MAGIC_USTAR    "ustar"
+
+struct HEAD_USTAR
+{
+  char name[100];
+  char mode[8];
+  char uid[8];
+  char gid[8];
+  char size[12];
+  char mtime[12];
+  char chksum[8];
+  char typeflag;
+  char linkname[100];
+  char magic[6];
+  char version[2];
+  char uname[32];
+  char gname[32];
+  char devmajor[8];
+  char devminor[8];
+  char prefix[155];
+} __attribute__ ((packed));
+
+#define HEAD_LENG      sizeof(struct HEAD_USTAR)
+
+struct grub_cpio_data
+{
+  grub_disk_t disk;
+  grub_uint32_t hofs;
+  grub_uint32_t dofs;
+  grub_uint32_t size;
+};
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+static grub_err_t
+grub_cpio_find_file (struct grub_cpio_data *data, char **name,
+                    grub_uint32_t * ofs)
+{
+#ifndef MODE_USTAR
+      struct HEAD_BCPIO hd;
+
+      if (grub_disk_read
+         (data->disk, 0, data->hofs, sizeof (hd), (char *) &hd))
+       return grub_errno;
+
+      if (hd.magic != MAGIC_BCPIO)
+       return grub_error (GRUB_ERR_BAD_FS, "Invalid cpio archive");
+
+      data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2;
+
+      if (hd.namesize & 1)
+       hd.namesize++;
+
+      if ((*name = grub_malloc (hd.namesize)) == NULL)
+       return grub_errno;
+
+      if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd),
+                         hd.namesize, *name))
+       {
+         grub_free (*name);
+         return grub_errno;
+       }
+
+      if (data->size == 0 && hd.mode == 0 && hd.namesize == 11 + 1
+         && ! grub_memcmp(*name, "TRAILER!!!", 11))
+       {
+         *ofs = 0;
+         return GRUB_ERR_NONE;
+       }
+
+      data->dofs = data->hofs + sizeof (hd) + hd.namesize;
+      *ofs = data->dofs + data->size;
+      if (data->size & 1)
+       (*ofs)++;
+#else
+      struct HEAD_USTAR hd;
+
+      if (grub_disk_read
+         (data->disk, 0, data->hofs, sizeof (hd), (char *) &hd))
+       return grub_errno;
+
+      if (!hd.name[0])
+       {
+         *ofs = 0;
+         return GRUB_ERR_NONE;
+       }
+
+      if (grub_memcmp (hd.magic, MAGIC_USTAR, sizeof (MAGIC_USTAR) - 1))
+       return grub_error (GRUB_ERR_BAD_FS, "Invalid tar archive");
+
+      if ((*name = grub_strdup (hd.name)) == NULL)
+       return grub_errno;
+
+      data->size = grub_strtoul (hd.size, NULL, 8);
+      data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE;
+      *ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) &
+                          ~(GRUB_DISK_SECTOR_SIZE - 1));
+#endif
+  return GRUB_ERR_NONE;
+}
+
+static struct grub_cpio_data *
+grub_cpio_mount (grub_disk_t disk)
+{
+  char hd[HEAD_LENG];
+  struct grub_cpio_data *data;
+
+  if (grub_disk_read (disk, 0, 0, sizeof (hd), hd))
+    goto fail;
+
+#ifndef MODE_USTAR
+  if (((struct HEAD_BCPIO *) hd)->magic != MAGIC_BCPIO)
+#else
+  if (grub_memcmp (((struct HEAD_USTAR *) hd)->magic, MAGIC_USTAR,
+                        sizeof (MAGIC_USTAR) - 1))
+#endif
+    goto fail;
+
+  data = (struct grub_cpio_data *) grub_malloc (sizeof (*data));
+  if (!data)
+    goto fail;
+
+  data->disk = disk;
+
+  return data;
+
+fail:
+  grub_error (GRUB_ERR_BAD_FS, "not a "
+#ifdef MODE_USTAR
+             "tar"
+#else
+             "cpio"
+#endif
+             " filesystem");
+  return 0;
+}
+
+static grub_err_t
+grub_cpio_dir (grub_device_t device, const char *path,
+              int (*hook) (const char *filename, int dir))
+{
+  struct grub_cpio_data *data;
+  grub_uint32_t ofs;
+  char *prev, *name;
+  const char *np;
+  int len;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  prev = 0;
+
+  data = grub_cpio_mount (device->disk);
+  if (!data)
+    goto fail;
+
+  np = path + 1;
+  len = grub_strlen (path) - 1;
+
+  data->hofs = 0;
+  while (1)
+    {
+      if (grub_cpio_find_file (data, &name, &ofs))
+       goto fail;
+
+      if (!ofs)
+       break;
+
+      if (grub_memcmp (np, name, len) == 0)
+       {
+         char *p, *n;
+
+         n = name + len;
+         if (*n == '/')
+           n++;
+
+         p = grub_strchr (name + len, '/');
+         if (p)
+           *p = 0;
+
+         if ((!prev) || (grub_strcmp (prev, name) != 0))
+           {
+             hook (name + len, p != NULL);
+             if (prev)
+               grub_free (prev);
+             prev = name;
+           }
+         else
+           grub_free (name);
+       }
+      data->hofs = ofs;
+    }
+
+fail:
+
+  if (prev)
+    grub_free (prev);
+
+  if (data)
+    grub_free (data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_cpio_open (grub_file_t file, const char *name)
+{
+  struct grub_cpio_data *data;
+  grub_uint32_t ofs;
+  char *fn;
+  int i, j;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_cpio_mount (file->device->disk);
+  if (!data)
+    goto fail;
+
+  data->hofs = 0;
+  while (1)
+    {
+      if (grub_cpio_find_file (data, &fn, &ofs))
+       goto fail;
+
+      if (!ofs)
+       {
+         grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+         break;
+       }
+
+      /* Compare NAME and FN by hand in order to cope with duplicate
+        slashes.  */
+      i = 1;
+      j = 0;
+      while (1)
+       {
+         if (name[i] != fn[j])
+           goto no_match;
+         
+         if (name[i] == '\0')
+           break;
+         
+         if (name[i] == '/' && name[i+1] == '/')
+           i++;
+         
+         i++;
+         j++;
+       }
+
+      file->data = data;
+      file->size = data->size;
+      grub_free (fn);
+
+      return GRUB_ERR_NONE;
+
+    no_match:
+      
+      grub_free (fn);
+      data->hofs = ofs;
+    }
+
+fail:
+
+  if (data)
+    grub_free (data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+static grub_ssize_t
+grub_cpio_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_cpio_data *data;
+
+  data = file->data;
+  return (grub_disk_read (data->disk, 0, data->dofs + file->offset,
+                         len, buf)) ? -1 : (grub_ssize_t) len;
+}
+
+static grub_err_t
+grub_cpio_close (grub_file_t file)
+{
+  grub_free (file->data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+static struct grub_fs grub_cpio_fs = {
+#ifdef MODE_USTAR
+  .name = "tarfs",
+#else
+  .name = "cpiofs",
+#endif
+  .dir = grub_cpio_dir,
+  .open = grub_cpio_open,
+  .read = grub_cpio_read,
+  .close = grub_cpio_close,
+};
+
+#ifdef MODE_USTAR
+GRUB_MOD_INIT (cpio)
+#else
+GRUB_MOD_INIT (tar)
+#endif
+{
+  grub_fs_register (&grub_cpio_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+#ifdef MODE_USTAR
+GRUB_MOD_FINI (cpio)
+#else
+GRUB_MOD_FINI (tar)
+#endif
+{
+  grub_fs_unregister (&grub_cpio_fs);
+}
diff --git a/fs/ext2.c b/fs/ext2.c
new file mode 100644 (file)
index 0000000..ac0757e
--- /dev/null
+++ b/fs/ext2.c
@@ -0,0 +1,922 @@
+/* ext2.c - Second Extended filesystem */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,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/>.
+ */
+
+/* Magic value used to identify an ext2 filesystem.  */
+#define        EXT2_MAGIC              0xEF53
+/* Amount of indirect blocks in an inode.  */
+#define INDIRECT_BLOCKS                12
+/* Maximum length of a pathname.  */
+#define EXT2_PATH_MAX          4096
+/* Maximum nesting of symlinks, used to prevent a loop.  */
+#define        EXT2_MAX_SYMLINKCNT     8
+
+/* The good old revision and the default inode size.  */
+#define EXT2_GOOD_OLD_REVISION         0
+#define EXT2_GOOD_OLD_INODE_SIZE       128
+
+/* Filetype used in directory entry.  */
+#define        FILETYPE_UNKNOWN        0
+#define        FILETYPE_REG            1
+#define        FILETYPE_DIRECTORY      2
+#define        FILETYPE_SYMLINK        7
+
+/* Filetype information as used in inodes.  */
+#define FILETYPE_INO_MASK      0170000
+#define FILETYPE_INO_REG       0100000
+#define FILETYPE_INO_DIRECTORY 0040000
+#define FILETYPE_INO_SYMLINK   0120000
+
+#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>
+
+/* Log2 size of ext2 block in 512 blocks.  */
+#define LOG2_EXT2_BLOCK_SIZE(data)                     \
+       (grub_le_to_cpu32 (data->sblock.log2_block_size) + 1)
+     
+/* Log2 size of ext2 block in bytes.  */
+#define LOG2_BLOCK_SIZE(data)                                  \
+       (grub_le_to_cpu32 (data->sblock.log2_block_size) + 10)
+
+/* The size of an ext2 block in bytes.  */
+#define EXT2_BLOCK_SIZE(data)          (1 << LOG2_BLOCK_SIZE (data))
+
+/* The revision level.  */
+#define EXT2_REVISION(data)    grub_le_to_cpu32 (data->sblock.revision_level)
+
+/* The inode size.  */
+#define EXT2_INODE_SIZE(data)  \
+        (EXT2_REVISION (data) == EXT2_GOOD_OLD_REVISION \
+         ? EXT2_GOOD_OLD_INODE_SIZE \
+         : grub_le_to_cpu16 (data->sblock.inode_size))
+
+/* Superblock filesystem feature flags (RW compatible)
+ * A filesystem with any of these enabled can be read and written by a driver
+ * that does not understand them without causing metadata/data corruption.  */
+#define EXT2_FEATURE_COMPAT_DIR_PREALLOC       0x0001
+#define EXT2_FEATURE_COMPAT_IMAGIC_INODES      0x0002
+#define EXT3_FEATURE_COMPAT_HAS_JOURNAL                0x0004
+#define EXT2_FEATURE_COMPAT_EXT_ATTR           0x0008
+#define EXT2_FEATURE_COMPAT_RESIZE_INODE       0x0010
+#define EXT2_FEATURE_COMPAT_DIR_INDEX          0x0020
+/* Superblock filesystem feature flags (RO compatible)
+ * A filesystem with any of these enabled can be safely read by a driver that
+ * does not understand them, but should not be written to, usually because
+ * additional metadata is required.  */
+#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER    0x0001
+#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE      0x0002
+#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR       0x0004
+#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM                0x0010
+#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK       0x0020
+#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE     0x0040
+/* Superblock filesystem feature flags (back-incompatible)
+ * A filesystem with any of these enabled should not be attempted to be read
+ * by a driver that does not understand them, since they usually indicate
+ * metadata format changes that might confuse the reader.  */
+#define EXT2_FEATURE_INCOMPAT_COMPRESSION      0x0001
+#define EXT2_FEATURE_INCOMPAT_FILETYPE         0x0002
+#define EXT3_FEATURE_INCOMPAT_RECOVER          0x0004 /* Needs recovery */
+#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV      0x0008 /* Volume is journal device */
+#define EXT2_FEATURE_INCOMPAT_META_BG          0x0010
+#define EXT4_FEATURE_INCOMPAT_EXTENTS          0x0040 /* Extents used */
+#define EXT4_FEATURE_INCOMPAT_64BIT            0x0080
+#define EXT4_FEATURE_INCOMPAT_FLEX_BG          0x0200
+
+/* The set of back-incompatible features this driver DOES support. Add (OR)
+ * flags here as the related features are implemented into the driver.  */
+#define EXT2_DRIVER_SUPPORTED_INCOMPAT ( EXT2_FEATURE_INCOMPAT_FILETYPE \
+                                       | EXT4_FEATURE_INCOMPAT_EXTENTS  \
+                                       | EXT4_FEATURE_INCOMPAT_FLEX_BG )
+/* List of rationales for the ignored "incompatible" features:
+ * needs_recovery: Not really back-incompatible - was added as such to forbid
+ *                 ext2 drivers from mounting an ext3 volume with a dirty
+ *                 journal because they will ignore the journal, but the next
+ *                 ext3 driver to mount the volume will find the journal and
+ *                 replay it, potentially corrupting the metadata written by
+ *                 the ext2 drivers. Safe to ignore for this RO driver.  */
+#define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER )
+
+
+#define EXT3_JOURNAL_MAGIC_NUMBER      0xc03b3998U
+
+#define EXT3_JOURNAL_DESCRIPTOR_BLOCK  1
+#define EXT3_JOURNAL_COMMIT_BLOCK      2
+#define EXT3_JOURNAL_SUPERBLOCK_V1     3
+#define EXT3_JOURNAL_SUPERBLOCK_V2     4
+#define EXT3_JOURNAL_REVOKE_BLOCK      5
+
+#define EXT3_JOURNAL_FLAG_ESCAPE       1
+#define EXT3_JOURNAL_FLAG_SAME_UUID    2
+#define EXT3_JOURNAL_FLAG_DELETED      4
+#define EXT3_JOURNAL_FLAG_LAST_TAG     8
+
+#define EXT4_EXTENTS_FLAG              0x80000
+
+/* The ext2 superblock.  */
+struct grub_ext2_sblock
+{
+  grub_uint32_t total_inodes;
+  grub_uint32_t total_blocks;
+  grub_uint32_t reserved_blocks;
+  grub_uint32_t free_blocks;
+  grub_uint32_t free_inodes;
+  grub_uint32_t first_data_block;
+  grub_uint32_t log2_block_size;
+  grub_uint32_t log2_fragment_size;
+  grub_uint32_t blocks_per_group;
+  grub_uint32_t fragments_per_group;
+  grub_uint32_t inodes_per_group;
+  grub_uint32_t mtime;
+  grub_uint32_t utime;
+  grub_uint16_t mnt_count;
+  grub_uint16_t max_mnt_count;
+  grub_uint16_t magic;
+  grub_uint16_t fs_state;
+  grub_uint16_t error_handling;
+  grub_uint16_t minor_revision_level;
+  grub_uint32_t lastcheck;
+  grub_uint32_t checkinterval;
+  grub_uint32_t creator_os;
+  grub_uint32_t revision_level;
+  grub_uint16_t uid_reserved;
+  grub_uint16_t gid_reserved;
+  grub_uint32_t first_inode;
+  grub_uint16_t inode_size;
+  grub_uint16_t block_group_number;
+  grub_uint32_t feature_compatibility;
+  grub_uint32_t feature_incompat;
+  grub_uint32_t feature_ro_compat;
+  grub_uint16_t uuid[8];
+  char volume_name[16];
+  char last_mounted_on[64];
+  grub_uint32_t compression_info;
+  grub_uint8_t prealloc_blocks;
+  grub_uint8_t prealloc_dir_blocks;
+  grub_uint16_t reserved_gdt_blocks;
+  grub_uint8_t journal_uuid[16];
+  grub_uint32_t journal_inum;
+  grub_uint32_t journal_dev;
+  grub_uint32_t last_orphan;
+  grub_uint32_t hash_seed[4];
+  grub_uint8_t def_hash_version;
+  grub_uint8_t jnl_backup_type;
+  grub_uint16_t reserved_word_pad;
+  grub_uint32_t default_mount_opts;
+  grub_uint32_t first_meta_bg;
+  grub_uint32_t mkfs_time;
+  grub_uint32_t jnl_blocks[17];
+};
+
+/* The ext2 blockgroup.  */
+struct grub_ext2_block_group
+{
+  grub_uint32_t block_id;
+  grub_uint32_t inode_id;
+  grub_uint32_t inode_table_id;
+  grub_uint16_t free_blocks;
+  grub_uint16_t free_inodes;
+  grub_uint16_t used_dirs;
+  grub_uint16_t pad;
+  grub_uint32_t reserved[3];
+};
+
+/* The ext2 inode.  */
+struct grub_ext2_inode
+{
+  grub_uint16_t mode;
+  grub_uint16_t uid;
+  grub_uint32_t size;
+  grub_uint32_t atime;
+  grub_uint32_t ctime;
+  grub_uint32_t mtime;
+  grub_uint32_t dtime;
+  grub_uint16_t gid;
+  grub_uint16_t nlinks;
+  grub_uint32_t blockcnt;  /* Blocks of 512 bytes!! */
+  grub_uint32_t flags;
+  grub_uint32_t osd1;
+  union
+  {
+    struct datablocks
+    {
+      grub_uint32_t dir_blocks[INDIRECT_BLOCKS];
+      grub_uint32_t indir_block;
+      grub_uint32_t double_indir_block;
+      grub_uint32_t triple_indir_block;
+    } blocks;
+    char symlink[60];
+  };
+  grub_uint32_t version;
+  grub_uint32_t acl;
+  grub_uint32_t dir_acl;
+  grub_uint32_t fragment_addr;
+  grub_uint32_t osd2[3];
+};
+
+/* The header of an ext2 directory entry.  */
+struct ext2_dirent
+{
+  grub_uint32_t inode;
+  grub_uint16_t direntlen;
+  grub_uint8_t namelen;
+  grub_uint8_t filetype;
+};
+
+struct grub_ext3_journal_header
+{
+  grub_uint32_t magic;
+  grub_uint32_t block_type;
+  grub_uint32_t sequence;
+};
+
+struct grub_ext3_journal_revoke_header
+{
+  struct grub_ext3_journal_header header;
+  grub_uint32_t count;
+  grub_uint32_t data[0];
+};
+
+struct grub_ext3_journal_block_tag
+{
+  grub_uint32_t block;
+  grub_uint32_t flags;
+};
+
+struct grub_ext3_journal_sblock
+{
+  struct grub_ext3_journal_header header;
+  grub_uint32_t block_size;
+  grub_uint32_t maxlen;
+  grub_uint32_t first;
+  grub_uint32_t sequence;
+  grub_uint32_t start;
+};
+
+#define EXT4_EXT_MAGIC         0xf30a
+
+struct grub_ext4_extent_header
+{
+  grub_uint16_t magic;
+  grub_uint16_t entries;
+  grub_uint16_t max;
+  grub_uint16_t depth;
+  grub_uint32_t generation;
+};
+
+struct grub_ext4_extent
+{
+  grub_uint32_t block;
+  grub_uint16_t len;
+  grub_uint16_t start_hi;
+  grub_uint32_t start;
+};
+
+struct grub_ext4_extent_idx
+{
+  grub_uint32_t block;
+  grub_uint32_t leaf;
+  grub_uint16_t leaf_hi;
+  grub_uint16_t unused;
+};
+
+struct grub_fshelp_node
+{
+  struct grub_ext2_data *data;
+  struct grub_ext2_inode inode;
+  int ino;
+  int inode_read;
+};
+
+/* Information about a "mounted" ext2 filesystem.  */
+struct grub_ext2_data
+{
+  struct grub_ext2_sblock sblock;
+  grub_disk_t disk;
+  struct grub_ext2_inode *inode;
+  struct grub_fshelp_node diropen;
+};
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+\f
+
+/* Read into BLKGRP the blockgroup descriptor of blockgroup GROUP of
+   the mounted filesystem DATA.  */
+inline static grub_err_t
+grub_ext2_blockgroup (struct grub_ext2_data *data, int group, 
+                     struct grub_ext2_block_group *blkgrp)
+{
+  return grub_disk_read (data->disk,
+                         ((grub_le_to_cpu32 (data->sblock.first_data_block) + 1)
+                          << LOG2_EXT2_BLOCK_SIZE (data)),
+                        group * sizeof (struct grub_ext2_block_group),
+                        sizeof (struct grub_ext2_block_group), (char *) blkgrp);
+}
+
+static struct grub_ext4_extent_header *
+grub_ext4_find_leaf (struct grub_ext2_data *data, char *buf,
+                     struct grub_ext4_extent_header *ext_block,
+                     grub_uint32_t fileblock)
+{
+  struct grub_ext4_extent_idx *index;
+
+  while (1)
+    {
+      int i;
+      grub_disk_addr_t block;
+
+      index = (struct grub_ext4_extent_idx *) (ext_block + 1);
+
+      if (grub_le_to_cpu16(ext_block->magic) != EXT4_EXT_MAGIC)
+        return 0;
+
+      if (ext_block->depth == 0)
+        return ext_block;
+
+      for (i = 0; i < grub_le_to_cpu16 (ext_block->entries); i++)
+        {
+          if (fileblock < grub_le_to_cpu32(index[i].block))
+            break;
+        }
+
+      if (--i < 0)
+        return 0;
+
+      block = grub_le_to_cpu16 (index[i].leaf_hi);
+      block = (block << 32) + grub_le_to_cpu32 (index[i].leaf);
+      if (grub_disk_read (data->disk,
+                          block << LOG2_EXT2_BLOCK_SIZE (data),
+                          0, EXT2_BLOCK_SIZE(data), buf))
+        return 0;
+
+      ext_block = (struct grub_ext4_extent_header *) buf;
+    }
+}
+
+static grub_disk_addr_t
+grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
+{
+  struct grub_ext2_data *data = node->data;
+  struct grub_ext2_inode *inode = &node->inode;
+  int blknr = -1;
+  unsigned int blksz = EXT2_BLOCK_SIZE (data);
+  int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data);
+  
+  if (inode->flags & EXT4_EXTENTS_FLAG)
+    {
+      char buf[EXT2_BLOCK_SIZE(data)];
+      struct grub_ext4_extent_header *leaf;
+      struct grub_ext4_extent *ext;
+      int i;
+
+      leaf = grub_ext4_find_leaf (data, buf,
+                                  (struct grub_ext4_extent_header *) inode->blocks.dir_blocks,
+                                  fileblock);
+      if (! leaf)
+        {
+          grub_error (GRUB_ERR_BAD_FS, "invalid extent");
+          return -1;
+        }
+
+      ext = (struct grub_ext4_extent *) (leaf + 1);
+      for (i = 0; i < grub_le_to_cpu16 (leaf->entries); i++)
+        {
+          if (fileblock < grub_le_to_cpu32 (ext[i].block))
+            break;
+        }
+
+      if (--i >= 0)
+        {
+          fileblock -= grub_le_to_cpu32 (ext[i].block);
+          if (fileblock >= grub_le_to_cpu16 (ext[i].len))
+            return 0;
+          else
+            {
+              grub_disk_addr_t start;
+
+              start = grub_le_to_cpu16 (ext[i].start_hi);
+              start = (start << 32) + grub_le_to_cpu32 (ext[i].start);
+
+              return fileblock + start;
+            }
+        }
+      else
+        {
+          grub_error (GRUB_ERR_BAD_FS, "something wrong with extent");
+          return -1;
+        }
+    }
+  /* Direct blocks.  */
+  if (fileblock < INDIRECT_BLOCKS)
+    blknr = grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]);
+  /* Indirect.  */
+  else if (fileblock < INDIRECT_BLOCKS + blksz / 4)
+    {
+      grub_uint32_t indir[blksz / 4];
+
+      if (grub_disk_read (data->disk,
+                         grub_le_to_cpu32 (inode->blocks.indir_block)
+                         << log2_blksz,
+                         0, blksz, (char *) indir))
+       return grub_errno;
+         
+      blknr = grub_le_to_cpu32 (indir[fileblock - INDIRECT_BLOCKS]);
+    }
+  /* Double indirect.  */
+  else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1))
+    {
+      unsigned int perblock = blksz / 4;
+      unsigned int rblock = fileblock - (INDIRECT_BLOCKS 
+                                        + blksz / 4);
+      grub_uint32_t indir[blksz / 4];
+
+      if (grub_disk_read (data->disk,
+                         grub_le_to_cpu32 (inode->blocks.double_indir_block)
+                         << log2_blksz,
+                         0, blksz, (char *) indir))
+       return grub_errno;
+
+      if (grub_disk_read (data->disk,
+                         grub_le_to_cpu32 (indir[rblock / perblock])
+                         << log2_blksz,
+                         0, blksz, (char *) indir))
+       return grub_errno;
+
+      
+      blknr = grub_le_to_cpu32 (indir[rblock % perblock]);
+    }
+  /* triple indirect.  */
+  else
+    {
+      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                 "ext2fs doesn't support triple indirect blocks");
+    }
+
+  return blknr;
+}
+
+/* Read LEN bytes from the file described by DATA starting with byte
+   POS.  Return the amount of read bytes in READ.  */
+static grub_ssize_t
+grub_ext2_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)
+{
+  return grub_fshelp_read_file (node->data->disk, node, read_hook,
+                               pos, len, buf, grub_ext2_read_block,
+                               node->inode.size,
+                               LOG2_EXT2_BLOCK_SIZE (node->data));
+    
+}
+
+
+/* Read the inode INO for the file described by DATA into INODE.  */
+static grub_err_t
+grub_ext2_read_inode (struct grub_ext2_data *data,
+                     int ino, struct grub_ext2_inode *inode)
+{
+  struct grub_ext2_block_group blkgrp;
+  struct grub_ext2_sblock *sblock = &data->sblock;
+  int inodes_per_block;
+  unsigned int blkno;
+  unsigned int blkoff;
+
+  /* It is easier to calculate if the first inode is 0.  */
+  ino--;
+  
+  grub_ext2_blockgroup (data,
+                        ino / grub_le_to_cpu32 (sblock->inodes_per_group),
+                       &blkgrp);
+  if (grub_errno)
+    return grub_errno;
+
+  inodes_per_block = EXT2_BLOCK_SIZE (data) / EXT2_INODE_SIZE (data);
+  blkno = (ino % grub_le_to_cpu32 (sblock->inodes_per_group))
+    / inodes_per_block;
+  blkoff = (ino % grub_le_to_cpu32 (sblock->inodes_per_group))
+    % inodes_per_block;
+
+  /* Read the inode.  */
+  if (grub_disk_read (data->disk,
+                     ((grub_le_to_cpu32 (blkgrp.inode_table_id) + blkno)
+                       << LOG2_EXT2_BLOCK_SIZE (data)),
+                     EXT2_INODE_SIZE (data) * blkoff,
+                     sizeof (struct grub_ext2_inode), (char *) inode))
+    return grub_errno;
+  
+  return 0;
+}
+
+static struct grub_ext2_data *
+grub_ext2_mount (grub_disk_t disk)
+{
+  struct grub_ext2_data *data;
+
+  data = grub_malloc (sizeof (struct grub_ext2_data));
+  if (!data)
+    return 0;
+
+  /* Read the superblock.  */
+  grub_disk_read (disk, 1 * 2, 0, sizeof (struct grub_ext2_sblock),
+                  (char *) &data->sblock);
+  if (grub_errno)
+    goto fail;
+
+  /* Make sure this is an ext2 filesystem.  */
+  if (grub_le_to_cpu16 (data->sblock.magic) != EXT2_MAGIC)
+    {
+      grub_error (GRUB_ERR_BAD_FS, "not an ext2 filesystem");
+      goto fail;
+    }
+  
+  /* Check the FS doesn't have feature bits enabled that we don't support. */
+  if (grub_le_to_cpu32 (data->sblock.feature_incompat)
+        & ~(EXT2_DRIVER_SUPPORTED_INCOMPAT | EXT2_DRIVER_IGNORED_INCOMPAT))
+    {
+      grub_error (GRUB_ERR_BAD_FS, "filesystem has unsupported incompatible features");
+      goto fail;
+    }
+    
+  
+  data->disk = disk;
+
+  data->diropen.data = data;
+  data->diropen.ino = 2;
+  data->diropen.inode_read = 1;
+
+  data->inode = &data->diropen.inode;
+
+  grub_ext2_read_inode (data, 2, data->inode);
+  if (grub_errno)
+    goto fail;
+  
+  return data;
+
+ fail:
+  grub_free (data);
+  return 0;
+}
+
+static char *
+grub_ext2_read_symlink (grub_fshelp_node_t node)
+{
+  char *symlink;
+  struct grub_fshelp_node *diro = node;
+  
+  if (! diro->inode_read)
+    {
+      grub_ext2_read_inode (diro->data, diro->ino, &diro->inode);
+      if (grub_errno)
+       return 0;
+    }
+  
+  symlink = grub_malloc (grub_le_to_cpu32 (diro->inode.size) + 1);
+  if (! symlink)
+    return 0;
+  
+  /* If the filesize of the symlink is bigger than
+     60 the symlink is stored in a separate block,
+     otherwise it is stored in the inode.  */
+  if (grub_le_to_cpu32 (diro->inode.size) <= 60)
+    grub_strncpy (symlink, 
+                 diro->inode.symlink,
+                 grub_le_to_cpu32 (diro->inode.size));
+  else
+    {
+      grub_ext2_read_file (diro, 0, 0,
+                          grub_le_to_cpu32 (diro->inode.size),
+                          symlink);
+      if (grub_errno)
+       {
+         grub_free (symlink);
+         return 0;
+       }
+    }
+  
+  symlink[grub_le_to_cpu32 (diro->inode.size)] = '\0';
+  return symlink;
+}
+
+static int
+grub_ext2_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))
+{
+  unsigned int fpos = 0;
+  struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
+  
+  if (! diro->inode_read)
+    {
+      grub_ext2_read_inode (diro->data, diro->ino, &diro->inode);
+      if (grub_errno)
+       return 0;
+    }
+  
+  /* Search the file.  */
+  while (fpos < grub_le_to_cpu32 (diro->inode.size))
+    {
+      struct ext2_dirent dirent;
+
+      grub_ext2_read_file (diro, 0, fpos, sizeof (struct ext2_dirent),
+                          (char *) &dirent);
+      if (grub_errno)
+       return 0;
+      
+      if (dirent.namelen != 0)
+       {
+         char filename[dirent.namelen + 1];
+         struct grub_fshelp_node *fdiro;
+         enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
+         
+         grub_ext2_read_file (diro, 0, fpos + sizeof (struct ext2_dirent),
+                              dirent.namelen, filename);
+         if (grub_errno)
+           return 0;
+         
+         fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
+         if (! fdiro)
+           return 0;
+         
+         fdiro->data = diro->data;
+         fdiro->ino = grub_le_to_cpu32 (dirent.inode);
+         
+         filename[dirent.namelen] = '\0';
+
+         if (dirent.filetype != FILETYPE_UNKNOWN)
+           {
+             fdiro->inode_read = 0;
+
+             if (dirent.filetype == FILETYPE_DIRECTORY)
+               type = GRUB_FSHELP_DIR;
+             else if (dirent.filetype == FILETYPE_SYMLINK)
+               type = GRUB_FSHELP_SYMLINK;
+             else if (dirent.filetype == FILETYPE_REG)
+               type = GRUB_FSHELP_REG;
+           }
+         else
+           {
+             /* The filetype can not be read from the dirent, read
+                the inode to get more information.  */
+             grub_ext2_read_inode (diro->data,
+                                    grub_le_to_cpu32 (dirent.inode),
+                                   &fdiro->inode);
+             if (grub_errno)
+               {
+                 grub_free (fdiro);
+                 return 0;
+               }
+             
+             fdiro->inode_read = 1;
+             
+             if ((grub_le_to_cpu16 (fdiro->inode.mode)
+                  & FILETYPE_INO_MASK) == FILETYPE_INO_DIRECTORY)
+               type = GRUB_FSHELP_DIR;
+             else if ((grub_le_to_cpu16 (fdiro->inode.mode)
+                       & FILETYPE_INO_MASK) == FILETYPE_INO_SYMLINK)
+               type = GRUB_FSHELP_SYMLINK;
+             else if ((grub_le_to_cpu16 (fdiro->inode.mode)
+                       & FILETYPE_INO_MASK) == FILETYPE_INO_REG)
+               type = GRUB_FSHELP_REG;
+           }
+         
+         if (hook (filename, type, fdiro))
+           return 1;
+       }
+      
+      fpos += grub_le_to_cpu16 (dirent.direntlen);
+    }
+  
+  return 0;
+}
+
+/* Open a file named NAME and initialize FILE.  */
+static grub_err_t
+grub_ext2_open (struct grub_file *file, const char *name)
+{
+  struct grub_ext2_data *data;
+  struct grub_fshelp_node *fdiro = 0;
+  
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  
+  data = grub_ext2_mount (file->device->disk);
+  if (! data)
+    goto fail;
+  
+  grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_ext2_iterate_dir,
+                        grub_ext2_read_symlink, GRUB_FSHELP_REG);
+  if (grub_errno)
+    goto fail;
+  
+  if (! fdiro->inode_read)
+    {
+      grub_ext2_read_inode (data, fdiro->ino, &fdiro->inode);
+      if (grub_errno)
+       goto fail;
+    }
+  
+  grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_ext2_inode));
+  grub_free (fdiro);
+
+  file->size = grub_le_to_cpu32 (data->inode->size);
+  file->data = data;
+  file->offset = 0;
+
+  return 0;
+
+ fail:
+  if (fdiro != &data->diropen)
+    grub_free (fdiro);
+  grub_free (data);
+  
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_ext2_close (grub_file_t file)
+{
+  grub_free (file->data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
+/* Read LEN bytes data from FILE into BUF.  */
+static grub_ssize_t
+grub_ext2_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_ext2_data *data = (struct grub_ext2_data *) file->data;
+  
+  return grub_ext2_read_file (&data->diropen, file->read_hook,
+                             file->offset, len, buf);
+}
+
+
+static grub_err_t
+grub_ext2_dir (grub_device_t device, const char *path, 
+              int (*hook) (const char *filename, int dir))
+{
+  struct grub_ext2_data *data = 0;;
+  struct grub_fshelp_node *fdiro = 0;
+  
+  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)
+    {
+      grub_free (node);
+      
+      if (filetype == GRUB_FSHELP_DIR)
+       return hook (filename, 1);
+      else 
+       return hook (filename, 0);
+      
+      return 0;
+    }
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  
+  data = grub_ext2_mount (device->disk);
+  if (! data)
+    goto fail;
+  
+  grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_ext2_iterate_dir,
+                        grub_ext2_read_symlink, GRUB_FSHELP_DIR);
+  if (grub_errno)
+    goto fail;
+  
+  grub_ext2_iterate_dir (fdiro, iterate);
+  
+ fail:
+  if (fdiro != &data->diropen)
+    grub_free (fdiro);
+  grub_free (data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_ext2_label (grub_device_t device, char **label)
+{
+  struct grub_ext2_data *data;
+  grub_disk_t disk = device->disk;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_ext2_mount (disk);
+  if (data)
+    *label = grub_strndup (data->sblock.volume_name, 14);
+  else
+    *label = NULL;
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_ext2_uuid (grub_device_t device, char **uuid)
+{
+  struct grub_ext2_data *data;
+  grub_disk_t disk = device->disk;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_ext2_mount (disk);
+  if (data)
+    {
+      *uuid = grub_malloc (40 + sizeof ('\0'));
+      grub_sprintf (*uuid, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
+                   grub_be_to_cpu16 (data->sblock.uuid[0]), grub_be_to_cpu16 (data->sblock.uuid[1]),
+                   grub_be_to_cpu16 (data->sblock.uuid[2]), grub_be_to_cpu16 (data->sblock.uuid[3]),
+                   grub_be_to_cpu16 (data->sblock.uuid[4]), grub_be_to_cpu16 (data->sblock.uuid[5]),
+                   grub_be_to_cpu16 (data->sblock.uuid[6]), grub_be_to_cpu16 (data->sblock.uuid[7]));
+    }
+  else
+    *uuid = NULL;
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+}
+
+\f
+static struct grub_fs grub_ext2_fs =
+  {
+    .name = "ext2",
+    .dir = grub_ext2_dir,
+    .open = grub_ext2_open,
+    .read = grub_ext2_read,
+    .close = grub_ext2_close,
+    .label = grub_ext2_label,
+    .uuid = grub_ext2_uuid,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(ext2)
+{
+  grub_fs_register (&grub_ext2_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(ext2)
+{
+  grub_fs_unregister (&grub_ext2_fs);
+}
diff --git a/fs/fat.c b/fs/fat.c
new file mode 100644 (file)
index 0000000..acaa027
--- /dev/null
+++ b/fs/fat.c
@@ -0,0 +1,888 @@
+/* fat.c - FAT filesystem */
+/*
+ *  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/>.
+ */
+
+#include <grub/fs.h>
+#include <grub/disk.h>
+#include <grub/file.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+
+#define GRUB_FAT_DIR_ENTRY_SIZE        32
+
+#define GRUB_FAT_ATTR_READ_ONLY        0x01
+#define GRUB_FAT_ATTR_HIDDEN   0x02
+#define GRUB_FAT_ATTR_SYSTEM   0x04
+#define GRUB_FAT_ATTR_VOLUME_ID        0x08
+#define GRUB_FAT_ATTR_DIRECTORY        0x10
+#define GRUB_FAT_ATTR_ARCHIVE  0x20
+
+#define GRUB_FAT_MAXFILE       256
+
+#define GRUB_FAT_ATTR_LONG_NAME        (GRUB_FAT_ATTR_READ_ONLY \
+                                | GRUB_FAT_ATTR_HIDDEN \
+                                | GRUB_FAT_ATTR_SYSTEM \
+                                | GRUB_FAT_ATTR_VOLUME_ID)
+#define 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)
+
+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));
+
+struct grub_fat_dir_entry
+{
+  grub_uint8_t name[11];
+  grub_uint8_t attr;
+  grub_uint8_t nt_reserved;
+  grub_uint8_t c_time_tenth;
+  grub_uint16_t c_time;
+  grub_uint16_t c_date;
+  grub_uint16_t a_date;
+  grub_uint16_t first_cluster_high;
+  grub_uint16_t w_time;
+  grub_uint16_t w_date;
+  grub_uint16_t first_cluster_low;
+  grub_uint32_t file_size;
+} __attribute__ ((packed));
+
+struct grub_fat_long_name_entry
+{
+  grub_uint8_t id;
+  grub_uint16_t name1[5];
+  grub_uint8_t attr;
+  grub_uint8_t reserved;
+  grub_uint8_t checksum;
+  grub_uint16_t name2[6];
+  grub_uint16_t first_cluster;
+  grub_uint16_t name3[2];
+} __attribute__ ((packed));
+
+struct grub_fat_data
+{
+  int logical_sector_bits;
+  grub_uint32_t num_sectors;
+  
+  grub_uint16_t fat_sector;
+  grub_uint32_t sectors_per_fat;
+  int fat_size;
+  
+  grub_uint32_t root_cluster;
+  grub_uint32_t root_sector;
+  grub_uint32_t num_root_sectors;
+  
+  int cluster_bits;
+  grub_uint32_t cluster_eof_mark;
+  grub_uint32_t cluster_sector;
+  grub_uint32_t num_clusters;
+
+  grub_uint8_t attr;
+  grub_ssize_t file_size;
+  grub_uint32_t file_cluster;
+  grub_uint32_t cur_cluster_num;
+  grub_uint32_t cur_cluster;
+
+  grub_uint32_t uuid;
+};
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+static int
+fat_log2 (unsigned x)
+{
+  int i;
+  
+  if (x == 0)
+    return -1;
+
+  for (i = 0; (x & 1) == 0; i++)
+    x >>= 1;
+
+  if (x != 1)
+    return -1;
+
+  return i;
+}
+
+static struct grub_fat_data *
+grub_fat_mount (grub_disk_t disk)
+{
+  struct grub_fat_bpb bpb;
+  struct grub_fat_data *data = 0;
+  grub_uint32_t first_fat, magic;
+
+  if (! disk)
+    goto fail;
+
+  data = (struct grub_fat_data *) grub_malloc (sizeof (*data));
+  if (! data)
+    goto fail;
+
+  /* Read the BPB.  */
+  if (grub_disk_read (disk, 0, 0, sizeof (bpb), (char *) &bpb))
+    goto fail;
+
+  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))
+    goto fail;
+  
+  /* Get the sizes of logical sectors and clusters.  */
+  data->logical_sector_bits =
+    fat_log2 (grub_le_to_cpu16 (bpb.bytes_per_sector));
+  if (data->logical_sector_bits < GRUB_DISK_SECTOR_BITS)
+    goto fail;
+  data->logical_sector_bits -= GRUB_DISK_SECTOR_BITS;
+  
+  data->cluster_bits = fat_log2 (bpb.sectors_per_cluster);
+  if (data->cluster_bits < 0)
+    goto fail;
+  data->cluster_bits += data->logical_sector_bits;
+
+  /* Get information about FATs.  */
+  data->fat_sector = (grub_le_to_cpu16 (bpb.num_reserved_sectors)
+                     << data->logical_sector_bits);
+  if (data->fat_sector == 0)
+    goto fail;
+
+  data->sectors_per_fat = ((bpb.sectors_per_fat_16
+                           ? grub_le_to_cpu16 (bpb.sectors_per_fat_16)
+                           : grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32))
+                          << data->logical_sector_bits);
+  if (data->sectors_per_fat == 0)
+    goto fail;
+
+  /* Get the number of sectors in this volume.  */
+  data->num_sectors = ((bpb.num_total_sectors_16
+                       ? grub_le_to_cpu16 (bpb.num_total_sectors_16)
+                       : grub_le_to_cpu32 (bpb.num_total_sectors_32))
+                      << data->logical_sector_bits);
+  if (data->num_sectors == 0)
+    goto fail;
+
+  /* Get information about the root directory.  */
+  if (bpb.num_fats == 0)
+    goto fail;
+
+  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
+        + grub_le_to_cpu16 (bpb.bytes_per_sector) - 1)
+       >> (data->logical_sector_bits + GRUB_DISK_SECTOR_BITS))
+       << (data->logical_sector_bits));
+
+  data->cluster_sector = data->root_sector + data->num_root_sectors;
+  data->num_clusters = (((data->num_sectors - data->cluster_sector)
+                        >> (data->cluster_bits + data->logical_sector_bits))
+                       + 2);
+
+  if (data->num_clusters <= 2)
+    goto fail;
+
+  if (! bpb.sectors_per_fat_16)
+    {
+      /* FAT32.  */
+      grub_uint16_t flags = grub_le_to_cpu16 (bpb.version_specific.fat32.extended_flags);
+      
+      data->root_cluster = grub_le_to_cpu32 (bpb.version_specific.fat32.root_cluster);
+      data->fat_size = 32;
+      data->cluster_eof_mark = 0x0ffffff8;
+      
+      if (flags & 0x80)
+       {
+         /* Get an active FAT.  */
+         unsigned active_fat = flags & 0xf;
+         
+         if (active_fat > bpb.num_fats)
+           goto fail;
+
+         data->fat_sector += active_fat * data->sectors_per_fat;
+       }
+
+      if (bpb.num_root_entries != 0 || bpb.version_specific.fat32.fs_version != 0)
+       goto fail;
+    }
+  else
+    {
+      /* FAT12 or FAT16.  */
+      data->root_cluster = ~0U;
+
+      if (data->num_clusters <= 4085 + 2)
+       {
+         /* FAT12.  */
+         data->fat_size = 12;
+         data->cluster_eof_mark = 0x0ff8;
+       }
+      else
+       {
+         /* FAT16.  */
+         data->fat_size = 16;
+         data->cluster_eof_mark = 0xfff8;
+       }
+    }
+
+  /* More sanity checks.  */
+  if (data->num_sectors <= data->fat_sector)
+    goto fail;
+
+  if (grub_disk_read (disk,
+                     data->fat_sector,
+                     0,
+                     sizeof (first_fat),
+                     (char *) &first_fat))
+    goto fail;
+
+  first_fat = grub_le_to_cpu32 (first_fat);
+
+  if (data->fat_size == 32)
+    {
+      first_fat &= 0x0fffffff;
+      magic = 0x0fffff00;
+    }
+  else if (data->fat_size == 16)
+    {
+      first_fat &= 0x0000ffff;
+      magic = 0xff00;
+    }
+  else
+    {
+      first_fat &= 0x00000fff;
+      magic = 0x0f00;
+    }
+
+  /* Serial number.  */
+  if (bpb.sectors_per_fat_16)
+    data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat12_or_fat16.num_serial);
+  else
+    data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat32.num_serial);
+  
+  /* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media
+     descriptor, even if it is a so-called superfloppy (e.g. an USB key).
+     The check may be too strict for this kind of stupid BIOSes, as
+     they overwrite the media descriptor.  */
+  if ((first_fat | 0x8) != (magic | bpb.media | 0x8))
+    goto fail;
+
+  /* Start from the root directory.  */
+  data->file_cluster = data->root_cluster;
+  data->cur_cluster_num = ~0U;
+  data->attr = GRUB_FAT_ATTR_DIRECTORY;
+  return data;
+
+ fail:
+
+  grub_free (data);
+  grub_error (GRUB_ERR_BAD_FS, "not a fat filesystem");
+  return 0;
+}
+
+static grub_ssize_t
+grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
+                   void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
+                                      unsigned offset, unsigned length),
+                   grub_off_t offset, grub_size_t len, char *buf)
+{
+  grub_size_t size;
+  grub_uint32_t logical_cluster;
+  unsigned logical_cluster_bits;
+  grub_ssize_t ret = 0;
+  unsigned long sector;
+  
+  /* This is a special case. FAT12 and FAT16 doesn't have the root directory
+     in clusters.  */
+  if (data->file_cluster == ~0U)
+    {
+      size = (data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset;
+      if (size > len)
+       size = len;
+
+      if (grub_disk_read (disk, data->root_sector, offset, size, buf))
+       return -1;
+
+      return size;
+    }
+
+  /* Calculate the logical cluster number and offset.  */
+  logical_cluster_bits = (data->cluster_bits
+                         + data->logical_sector_bits
+                         + GRUB_DISK_SECTOR_BITS);
+  logical_cluster = offset >> logical_cluster_bits;
+  offset &= (1 << logical_cluster_bits) - 1;
+
+  if (logical_cluster < data->cur_cluster_num)
+    {
+      data->cur_cluster_num = 0;
+      data->cur_cluster = data->file_cluster;
+    }
+
+  while (len)
+    {
+      while (logical_cluster > data->cur_cluster_num)
+       {
+         /* Find next cluster.  */
+         grub_uint32_t next_cluster;
+         unsigned long fat_offset;
+
+         switch (data->fat_size)
+           {
+           case 32:
+             fat_offset = data->cur_cluster << 2;
+             break;
+           case 16:
+             fat_offset = data->cur_cluster << 1;
+             break;
+           default:
+             /* case 12: */
+             fat_offset = data->cur_cluster + (data->cur_cluster >> 1);
+             break;
+           }
+
+         /* Read the FAT.  */
+         if (grub_disk_read (disk, data->fat_sector, fat_offset,
+                             (data->fat_size + 7) >> 3,
+                             (char *) &next_cluster))
+           return -1;
+
+         next_cluster = grub_le_to_cpu32 (next_cluster);
+         switch (data->fat_size)
+           {
+           case 16:
+             next_cluster &= 0xFFFF;
+             break;
+           case 12:
+             if (data->cur_cluster & 1)
+               next_cluster >>= 4;
+             
+             next_cluster &= 0x0FFF;
+             break;
+           }
+
+#if 0
+         grub_printf ("%s:%d: fat_size=%d, next_cluster=%u\n",
+                      __FILE__, __LINE__, data->fat_size, next_cluster);
+#endif
+         
+         /* Check the end.  */
+         if (next_cluster >= data->cluster_eof_mark)
+           return ret;
+
+         if (next_cluster < 2 || next_cluster >= data->num_clusters)
+           {
+             grub_error (GRUB_ERR_BAD_FS, "invalid cluster %u",
+                         next_cluster);
+             return -1;
+           }
+
+         data->cur_cluster = next_cluster;
+         data->cur_cluster_num++;
+       }
+
+      /* Read the data here.  */
+      sector = (data->cluster_sector
+               + ((data->cur_cluster - 2)
+                  << (data->cluster_bits + data->logical_sector_bits)));
+      size = (1 << logical_cluster_bits) - offset;
+      if (size > len)
+       size = len;
+
+      disk->read_hook = read_hook;
+      grub_disk_read (disk, sector, offset, size, buf);
+      disk->read_hook = 0;
+      if (grub_errno)
+       return -1;
+
+      len -= size;
+      buf += size;
+      ret += size;
+      logical_cluster++;
+      offset = 0;
+    }
+
+  return ret;
+}
+
+/* Find the underlying directory or file in PATH and return the
+   next path. If there is no next path or an error occurs, return NULL.
+   If HOOK is specified, call it with each file name.  */
+static char *
+grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
+                  const char *path,
+                  int (*hook) (const char *filename, int dir))
+{
+  struct grub_fat_dir_entry dir;
+  char *dirname, *dirp;
+  char *filename, *filep = 0;
+  grub_uint16_t *unibuf;
+  int slot = -1, slots = -1;
+  int checksum = -1;
+  grub_ssize_t offset = -sizeof(dir);
+  int call_hook;
+  
+  if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+      return 0;
+    }
+  
+  /* Extract a directory name.  */
+  while (*path == '/')
+    path++;
+
+  dirp = grub_strchr (path, '/');
+  if (dirp)
+    {
+      unsigned len = dirp - path;
+      
+      dirname = grub_malloc (len + 1);
+      if (! dirname)
+       return 0;
+
+      grub_memcpy (dirname, path, len);
+      dirname[len] = '\0';
+    }
+  else
+    /* This is actually a file.  */
+    dirname = grub_strdup (path);
+
+  call_hook = (! dirp && hook);
+  
+  /* Allocate space enough to hold a long name.  */
+  filename = grub_malloc (0x40 * 13 * 4 + 1);
+  unibuf = (grub_uint16_t *) grub_malloc (0x40 * 13 * 2);
+  if (! filename || ! unibuf)
+    {
+      grub_free (filename);
+      grub_free (unibuf);
+      grub_free (dirname);
+      return 0;
+    }
+      
+  while (1)
+    {
+      unsigned i;
+
+      /* Adjust the offset.  */
+      offset += sizeof (dir);
+
+      /* Read a directory entry.  */
+      if ((grub_fat_read_data (disk, data, 0,
+                              offset, sizeof (dir), (char *) &dir)
+          != sizeof (dir))
+         || dir.name[0] == 0)
+       {
+         if (grub_errno == GRUB_ERR_NONE && ! call_hook)
+           grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+
+         break;
+       }
+
+      /* Handle long name entries.  */
+      if (dir.attr == GRUB_FAT_ATTR_LONG_NAME)
+       {
+         struct grub_fat_long_name_entry *long_name
+           = (struct grub_fat_long_name_entry *) &dir;
+         grub_uint8_t id = long_name->id;
+         
+         if (id & 0x40)
+           {
+             id &= 0x3f;
+             slots = slot = id;
+             checksum = long_name->checksum;
+           }
+
+         if (id != slot || slot == 0 || checksum != long_name->checksum)
+           {
+             checksum = -1;
+             continue;
+           }
+
+         slot--;
+         grub_memcpy (unibuf + slot * 13, long_name->name1, 5 * 2);
+         grub_memcpy (unibuf + slot * 13 + 5, long_name->name2, 6 * 2);
+         grub_memcpy (unibuf + slot * 13 + 11, long_name->name3, 2 * 2);
+         continue;
+       }
+
+      /* Check if this entry is valid.  */
+      if (dir.name[0] == 0xe5 || (dir.attr & ~GRUB_FAT_ATTR_VALID))
+       continue;
+
+      /* This is a workaround for Japanese.  */
+      if (dir.name[0] == 0x05)
+       dir.name[0] = 0xe5;
+      
+      if (checksum != -1 && slot == 0)
+       {
+         grub_uint8_t sum;
+         
+         for (sum = 0, i = 0; i < sizeof (dir.name); i++)
+           sum = ((sum >> 1) | (sum << 7)) + dir.name[i];
+
+         if (sum == checksum)
+           {
+             int u;
+
+             for (u = 0; u < slots * 13; u++)
+               unibuf[u] = grub_le_to_cpu16 (unibuf[u]);
+             
+             *grub_utf16_to_utf8 ((grub_uint8_t *) filename, unibuf,
+                                  slots * 13) = '\0';
+             
+             if (*dirname == '\0' && call_hook)
+               {
+                 if (hook (filename, dir.attr & GRUB_FAT_ATTR_DIRECTORY))
+                   break;
+                 
+                 checksum = -1;
+                 continue;
+               }
+
+             if (grub_strcmp (dirname, filename) == 0)
+               {
+                 if (call_hook)
+                   hook (filename, dir.attr & GRUB_FAT_ATTR_DIRECTORY);
+                 
+                 break;
+               }
+           }
+
+         checksum = -1;
+       }
+
+      /* Convert the 8.3 file name.  */
+      filep = filename;
+      
+      for (i = 0; i < 8 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
+       *filep++ = grub_tolower (dir.name[i]);
+      
+      *filep = '.';
+      
+      for (i = 8; i < 11 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
+       *++filep = grub_tolower (dir.name[i]);
+
+      if (*filep != '.')
+       filep++;
+      
+      *filep = '\0';
+
+      if (*dirname == '\0' && call_hook)
+       {
+         if (hook (filename, dir.attr & GRUB_FAT_ATTR_DIRECTORY))
+           break;
+       }
+      else if (grub_strncasecmp (dirname, filename, GRUB_FAT_MAXFILE) == 0)
+       {
+         if (call_hook)
+           hook (filename, dir.attr & GRUB_FAT_ATTR_DIRECTORY);
+
+         break;
+       }
+    }
+
+  grub_free (filename);
+  grub_free (dirname);
+
+  data->attr = dir.attr;
+  data->file_size = grub_le_to_cpu32 (dir.file_size);
+  data->file_cluster = ((grub_le_to_cpu16 (dir.first_cluster_high) << 16)
+                       | grub_le_to_cpu16 (dir.first_cluster_low));
+  data->cur_cluster_num = ~0U;
+  
+  return dirp;
+}
+
+static grub_err_t
+grub_fat_dir (grub_device_t device, const char *path,
+             int (*hook) (const char *filename, int dir))
+{
+  struct grub_fat_data *data = 0;
+  grub_disk_t disk = device->disk;
+  grub_size_t len;
+  char *dirname = 0;
+  char *p;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  
+  data = grub_fat_mount (disk);
+  if (! data)
+    goto fail;
+
+  /* Make sure that DIRNAME terminates with '/'.  */
+  len = grub_strlen (path);
+  dirname = grub_malloc (len + 1 + 1);
+  if (! dirname)
+    goto fail;
+  grub_memcpy (dirname, path, len);
+  p = dirname + len;
+  if (path[len - 1] != '/')
+    *p++ = '/';
+  *p = '\0';
+  p = dirname;
+  
+  do
+    {
+      p = grub_fat_find_dir (disk, data, p, hook);
+    }
+  while (p && grub_errno == GRUB_ERR_NONE);
+
+ fail:
+
+  grub_free (dirname);
+  grub_free (data);
+  
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+  
+  return grub_errno;
+}
+
+static grub_err_t
+grub_fat_open (grub_file_t file, const char *name)
+{
+  struct grub_fat_data *data = 0;
+  char *p = (char *) name;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  
+  data = grub_fat_mount (file->device->disk);
+  if (! data)
+    goto fail;
+
+  do
+    {
+      p = grub_fat_find_dir (file->device->disk, data, p, 0);
+      if (grub_errno != GRUB_ERR_NONE)
+       goto fail;
+    }
+  while (p);
+
+  if (data->attr & GRUB_FAT_ATTR_DIRECTORY)
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a file");
+      goto fail;
+    }
+
+  file->data = data;
+  file->size = data->file_size;
+  
+  return GRUB_ERR_NONE;
+
+ fail:
+  
+  grub_free (data);
+  
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+  
+  return grub_errno;
+}
+
+static grub_ssize_t
+grub_fat_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  return grub_fat_read_data (file->device->disk, file->data, file->read_hook,
+                            file->offset, len, buf);
+}
+
+static grub_err_t
+grub_fat_close (grub_file_t file)
+{
+  grub_free (file->data);
+  
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+  
+  return grub_errno;
+}
+
+static grub_err_t
+grub_fat_label (grub_device_t device, char **label)
+{
+  struct grub_fat_data *data;
+  grub_disk_t disk = device->disk;
+  grub_ssize_t offset = -sizeof(struct grub_fat_dir_entry);
+
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  
+  data = grub_fat_mount (disk);
+  if (! data)
+    goto fail;
+
+  if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+      return 0;
+    }
+
+  while (1)
+    {
+      struct grub_fat_dir_entry dir;
+
+      /* Adjust the offset.  */
+      offset += sizeof (dir);
+      
+      /* Read a directory entry.  */
+      if ((grub_fat_read_data (disk, data, 0,
+                              offset, sizeof (dir), (char *) &dir)
+          != sizeof (dir))
+         || dir.name[0] == 0)
+       {
+         if (grub_errno != GRUB_ERR_NONE)
+           goto fail;
+         else
+           {
+             *label = 0;
+             return GRUB_ERR_NONE;
+           }
+       }
+
+      if (dir.attr == GRUB_FAT_ATTR_VOLUME_ID)
+       {
+         *label = grub_strndup ((char *) dir.name, 11);
+         return GRUB_ERR_NONE;
+       }
+    }
+
+  *label = 0;
+  
+ fail:
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_fat_uuid (grub_device_t device, char **uuid)
+{
+  struct grub_fat_data *data;
+  grub_disk_t disk = device->disk;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_fat_mount (disk);
+  if (data)
+    {
+      *uuid = grub_malloc (sizeof ("xxxx-xxxx"));
+      grub_sprintf (*uuid, "%04x-%04x", (grub_uint16_t) (data->uuid >> 16),
+                   (grub_uint16_t) data->uuid);
+    }
+  else
+    *uuid = NULL;
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+}
+
+static struct grub_fs grub_fat_fs =
+  {
+    .name = "fat",
+    .dir = grub_fat_dir,
+    .open = grub_fat_open,
+    .read = grub_fat_read,
+    .close = grub_fat_close,
+    .label = grub_fat_label,
+    .uuid = grub_fat_uuid,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(fat)
+{
+  grub_fs_register (&grub_fat_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(fat)
+{
+  grub_fs_unregister (&grub_fat_fs);
+}
+
diff --git a/fs/fshelp.c b/fs/fshelp.c
new file mode 100644 (file)
index 0000000..a5eccdd
--- /dev/null
@@ -0,0 +1,315 @@
+/* fshelp.c -- Filesystem helper functions */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,2005,2006,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/>.
+ */
+
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/fshelp.h>
+
+
+/* Lookup the node PATH.  The node ROOTNODE describes the root of the
+   directory tree.  The node found is returned in FOUNDNODE, which is
+   either a ROOTNODE or a new malloc'ed node.  ITERATE_DIR is used to
+   iterate over all directory entries in the current node.
+   READ_SYMLINK is used to read the symlink if a node is a symlink.
+   EXPECTTYPE is the type node that is expected by the called, an
+   error is generated if the node is not of the expected type.  Make
+   sure you use the NESTED_FUNC_ATTR macro for HOOK, this is required
+   because GCC has a nasty bug when using regparm=3.  */
+grub_err_t
+grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
+                      grub_fshelp_node_t *foundnode,
+                      int (*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)),
+                      char *(*read_symlink) (grub_fshelp_node_t node),
+                      enum grub_fshelp_filetype expecttype)
+{
+  grub_err_t err;
+  enum grub_fshelp_filetype foundtype = GRUB_FSHELP_DIR;
+  int symlinknest = 0;
+  
+  auto grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath,
+                                             grub_fshelp_node_t currroot,
+                                             grub_fshelp_node_t *currfound);
+
+  grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath,
+                                        grub_fshelp_node_t currroot,
+                                        grub_fshelp_node_t *currfound)
+    {
+      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;
+
+      auto int NESTED_FUNC_ATTR iterate (const char *filename,
+                                        enum grub_fshelp_filetype filetype,
+                                        grub_fshelp_node_t node);
+
+      auto void free_node (grub_fshelp_node_t node);
+      
+      void free_node (grub_fshelp_node_t node)
+       {
+          if (node != rootnode && node != currroot)
+           grub_free (node);
+       }
+      
+      int NESTED_FUNC_ATTR iterate (const char *filename,
+                                   enum grub_fshelp_filetype filetype,
+                                   grub_fshelp_node_t node)
+       {
+         if (filetype == GRUB_FSHELP_UNKNOWN ||
+              (grub_strcmp (name, filename) &&
+               (! (filetype & GRUB_FSHELP_CASE_INSENSITIVE) ||
+                grub_strncasecmp (name, filename, LONG_MAX))))
+           {
+             grub_free (node);
+             return 0;
+           }
+         
+         /* The node is found, stop iterating over the nodes.  */
+         type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE;
+         oldnode = currnode;
+         currnode = node;
+         
+         return 1;
+       }
+  
+      grub_strncpy (fpath, currpath, grub_strlen (currpath) + 1);
+      
+      /* Remove all leading slashes.  */
+      while (*name == '/')
+       name++;
+  
+      if (! *name)
+       {
+         *currfound = currnode;
+         return 0;
+       }
+      
+      for (;;)
+       {
+         int found;
+      
+         /* Extract the actual part from the pathname.  */
+         next = grub_strchr (name, '/');
+         if (next)
+           {
+             /* Remove all leading slashes.  */
+             while (*next == '/')
+               *(next++) = '\0';
+           }
+         
+         /* At this point it is expected that the current node is a
+            directory, check if this is true.  */
+         if (type != GRUB_FSHELP_DIR)
+           {
+             free_node (currnode);
+             return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+           }
+         
+         /* Iterate over the directory.  */
+         found = iterate_dir (currnode, iterate);
+         if (! found)
+           {
+             if (grub_errno)
+               return grub_errno;
+             
+             break;
+           }
+         
+         /* Read in the symlink and follow it.  */
+         if (type == GRUB_FSHELP_SYMLINK)
+           {
+             char *symlink;
+             
+             /* Test if the symlink does not loop.  */
+             if (++symlinknest == 8)
+               {
+                 free_node (currnode);
+                 free_node (oldnode);
+                 return grub_error (GRUB_ERR_SYMLINK_LOOP,
+                                     "too deep nesting of symlinks");
+               }
+             
+             symlink = read_symlink (currnode);
+             free_node (currnode);
+             
+             if (!symlink)
+               {
+                 free_node (oldnode);
+                 return grub_errno;
+               }
+             
+             /* The symlink is an absolute path, go back to the root inode.  */
+             if (symlink[0] == '/')
+               {
+                 free_node (oldnode);
+                 oldnode = rootnode;
+               }       
+             
+             /* Lookup the node the symlink points to.  */
+             find_file (symlink, oldnode, &currnode);
+             type = foundtype;
+             grub_free (symlink);
+             
+             if (grub_errno)
+               {
+                 free_node (oldnode);
+                 return grub_errno;
+               }
+           }
+      
+         free_node (oldnode);
+         
+         /* Found the node!  */
+         if (! next || *next == '\0')
+           {
+             *currfound = currnode;
+             foundtype = type;
+             return 0;
+           }
+      
+         name = next;
+       }
+      
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+    }
+
+  if (!path || path[0] != '/')
+    {
+      grub_error (GRUB_ERR_BAD_FILENAME, "bad filename");
+      return grub_errno;
+    }
+  
+  err = find_file (path, rootnode, foundnode);
+  if (err)
+    return err;
+  
+  /* Check if the node that was found was of the expected type.  */
+  if (expecttype == GRUB_FSHELP_REG && foundtype != expecttype)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a regular file");
+  else if (expecttype == GRUB_FSHELP_DIR && foundtype != expecttype)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+  
+  return 0;
+}
+
+/* Read LEN bytes from the file NODE on disk DISK into the buffer BUF,
+   beginning with the block POS.  READ_HOOK should be set before
+   reading a block from the file.  GET_BLOCK is used to translate file
+   blocks to disk blocks.  The file is FILESIZE bytes big and the
+   blocks have a size of LOG2BLOCKSIZE (in log2).  */
+grub_ssize_t
+grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
+                      void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
+                                                           unsigned offset,
+                                                           unsigned length),
+                      grub_off_t pos, grub_size_t len, char *buf,
+                      grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
+                                                      grub_disk_addr_t block),
+                      grub_off_t filesize, int log2blocksize)
+{
+  grub_disk_addr_t i, blockcnt;
+  int blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS);
+
+  /* Adjust LEN so it we can't read past the end of the file.  */
+  if (pos + len > filesize)
+    len = filesize - pos;
+
+  blockcnt = ((len + pos) + blocksize - 1) >> (log2blocksize + GRUB_DISK_SECTOR_BITS);
+
+  for (i = pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS); i < blockcnt; i++)
+    {
+      grub_disk_addr_t blknr;
+      int blockoff = pos & (blocksize - 1);
+      int blockend = blocksize;
+
+      int skipfirst = 0;
+
+      blknr = get_block (node, i);
+      if (grub_errno)
+       return -1;
+      
+      blknr = blknr << log2blocksize;
+
+      /* Last block.  */
+      if (i == blockcnt - 1)
+       {
+         blockend = (len + pos) & (blocksize - 1);
+         
+         /* The last portion is exactly blocksize.  */
+         if (! blockend)
+           blockend = blocksize;
+       }
+
+      /* First block.  */
+      if (i == (pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS)))
+       {
+         skipfirst = blockoff;
+         blockend -= skipfirst;
+       }
+      
+      /* If the block number is 0 this block is not stored on disk but
+        is zero filled instead.  */
+      if (blknr)
+       {
+         disk->read_hook = read_hook;    
+
+         grub_disk_read (disk, blknr, skipfirst,
+                         blockend, buf);
+         disk->read_hook = 0;
+         if (grub_errno)
+           return -1;
+       }
+      else
+       grub_memset (buf, 0, blockend);
+
+      buf += blocksize - skipfirst;
+    }
+
+  return len;
+}
+
+unsigned int
+grub_fshelp_log2blksize (unsigned int blksize, unsigned int *pow)
+{
+  int mod;
+  
+  *pow = 0;
+  while (blksize > 1)
+    {
+      mod = blksize - ((blksize >> 1) << 1);
+      blksize >>= 1;
+
+      /* Check if it really is a power of two.  */
+      if (mod)
+       return grub_error (GRUB_ERR_BAD_NUMBER,
+                          "the blocksize is not a power of two");
+      (*pow)++;
+    }
+
+  return GRUB_ERR_NONE;
+}
diff --git a/fs/hfs.c b/fs/hfs.c
new file mode 100644 (file)
index 0000000..b01c42e
--- /dev/null
+++ b/fs/hfs.c
@@ -0,0 +1,886 @@
+/* hfs.c - HFS.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,2005,2006,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/>.
+ */
+
+/* HFS is documented at
+   http://developer.apple.com/documentation/mac/Files/Files-2.html */
+
+#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/hfs.h>
+
+#define        GRUB_HFS_SBLOCK         2
+#define GRUB_HFS_EMBED_HFSPLUS_SIG 0x482B
+
+#define GRUB_HFS_BLKS          (data->blksz >> 9)
+
+#define GRUB_HFS_NODE_LEAF     0xFF
+
+/* The two supported filesystems a record can have.  */
+enum
+  {
+    GRUB_HFS_FILETYPE_DIR = 1,
+    GRUB_HFS_FILETYPE_FILE = 2
+  };
+
+/* Catalog node ID (CNID).  */
+enum grub_hfs_cnid_type
+  {
+    GRUB_HFS_CNID_ROOT_PARENT = 1,
+    GRUB_HFS_CNID_ROOT = 2,
+    GRUB_HFS_CNID_EXT = 3,
+    GRUB_HFS_CNID_CAT = 4,
+    GRUB_HFS_CNID_BAD = 5
+  };
+
+/* A node descriptor.  This is the header of every node.  */
+struct grub_hfs_node
+{
+  grub_uint32_t next;
+  grub_uint32_t prev;
+  grub_uint8_t type;
+  grub_uint8_t level;
+  grub_uint16_t reccnt;
+  grub_uint16_t unused;
+} __attribute__ ((packed));
+
+/* The head of the B*-Tree.  */
+struct grub_hfs_treeheader
+{
+  grub_uint16_t tree_depth;
+  /* The number of the first node.  */
+  grub_uint32_t root_node;
+  grub_uint32_t leaves;
+  grub_uint32_t first_leaf;
+  grub_uint32_t last_leaf;
+  grub_uint16_t node_size;
+  grub_uint16_t key_size;
+  grub_uint32_t nodes;
+  grub_uint32_t free_nodes;
+  grub_uint8_t unused[76];
+} __attribute__ ((packed));
+
+/* The state of a mounted HFS filesystem.  */
+struct grub_hfs_data
+{
+  struct grub_hfs_sblock sblock;
+  grub_disk_t disk;
+  grub_hfs_datarecord_t extents;
+  int fileid;
+  int size;
+  int ext_root;
+  int ext_size;
+  int cat_root;
+  int cat_size;
+  int blksz;
+  int log2_blksz;
+  int rootdir;
+};
+
+/* The key as used on disk in a catalog tree.  This is used to lookup
+   file/directory nodes by parent directory ID and filename.  */
+struct grub_hfs_catalog_key
+{
+  grub_uint8_t unused;
+  grub_uint32_t parent_dir;
+  
+  /* Filename length.  */
+  grub_uint8_t strlen;
+
+  /* Filename.  */
+  grub_uint8_t str[31];
+} __attribute__ ((packed));
+
+/* The key as used on disk in a extent overflow tree.  Using this key
+   the extents can be looked up using a fileid and logical start block
+   as index.  */
+struct grub_hfs_extent_key
+{
+  /* The kind of fork.  This is used to store meta information like
+     icons, attributes, etc.  We will only use the datafork, which is
+     0.  */
+  grub_uint8_t forktype;
+  grub_uint32_t fileid;
+  grub_uint16_t first_block;
+} __attribute__ ((packed));
+
+/* A dirrect record.  This is used to find out the directory ID.  */
+struct grub_hfs_dirrec
+{
+  /* For a directory, type == 1.  */
+  grub_uint8_t type;
+  grub_uint8_t unused[5];
+  grub_uint32_t dirid;
+} __attribute__ ((packed));
+
+/* Information about a file.  */
+struct grub_hfs_filerec
+{
+  /* For a file, type == 2.  */
+  grub_uint8_t type;
+  grub_uint8_t unused[19];
+  grub_uint32_t fileid;
+  grub_uint8_t unused2[2];
+  grub_uint32_t size;
+  grub_uint8_t unused3[44];
+
+  /* The first 3 extents of the file.  The other extents can be found
+     in the extent overflow file.  */
+  grub_hfs_datarecord_t extents;
+} __attribute__ ((packed));
+
+/* A record descriptor, both key and data, used to pass to call back
+   functions.  */
+struct grub_hfs_record
+{
+  void *key;
+  int keylen;
+  void *data;
+  int datalen;
+};
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+\f
+static int grub_hfs_find_node (struct grub_hfs_data *, char *,
+                              grub_uint32_t, int, char *, int);
+
+/* Find block BLOCK of the file FILE in the mounted UFS filesystem
+   DATA.  The first 3 extents are described by DAT.  If cache is set,
+   using caching to improve non-random reads.  */
+static unsigned int
+grub_hfs_block (struct grub_hfs_data *data, grub_hfs_datarecord_t dat,
+               int file, int block, int cache)
+{
+  grub_hfs_datarecord_t dr;
+  int pos = 0;
+  struct grub_hfs_extent_key key;
+  
+  int tree = 0;
+  static int cache_file = 0;
+  static int cache_pos = 0;  
+  static grub_hfs_datarecord_t cache_dr;
+  
+  grub_memcpy (dr, dat, sizeof (dr));
+  
+  key.forktype = 0;
+  key.fileid = grub_cpu_to_be32 (file);
+  
+  if (cache && cache_file == file  && block > cache_pos)
+    {
+      pos = cache_pos;
+      key.first_block = grub_cpu_to_be16 (pos);
+      grub_memcpy (dr, cache_dr, sizeof (cache_dr));
+    }
+  
+  for (;;)
+    {
+      int i;
+      
+      /* Try all 3 extents.  */
+      for (i = 0; i < 3; i++)
+       {
+         /* Check if the block is stored in this extent.  */
+         if (grub_be_to_cpu16 (dr[i].count) + pos > block)
+           {
+             int first = grub_be_to_cpu16 (dr[i].first_block);
+             
+             /* If the cache is enabled, store the current position
+                in the tree.  */
+             if (tree && cache)
+               {
+                 cache_file = file;
+                 cache_pos = pos;
+                 grub_memcpy (cache_dr, dr, sizeof (cache_dr));
+               }
+             
+             return (grub_be_to_cpu16 (data->sblock.first_block)
+                     + (first + block - pos) * GRUB_HFS_BLKS);
+           }
+         
+         /* Try the next extent.  */
+         pos += grub_be_to_cpu16 (dr[i].count);
+       }
+      
+      /* Lookup the block in the extent overflow file.  */
+      key.first_block = grub_cpu_to_be16 (pos);
+      tree = 1;
+      grub_hfs_find_node (data, (char *) &key, data->ext_root,
+                         1, (char *) &dr, sizeof (dr));
+      if (grub_errno)
+       return 0;
+    }
+}
+
+
+/* Read LEN bytes from the file described by DATA starting with byte
+   POS.  Return the amount of read bytes in READ.  */
+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)
+{
+  int i;
+  int blockcnt;
+
+  /* Adjust len so it we can't read past the end of the file.  */
+  if (len > grub_le_to_cpu32 (data->size))
+    len = grub_le_to_cpu32 (data->size);
+
+  blockcnt = ((len + pos) 
+             + data->blksz - 1) / data->blksz;
+
+  for (i = pos / data->blksz; i < blockcnt; i++)
+    {
+      int blknr;
+      int blockoff = pos % data->blksz;
+      int blockend = data->blksz;
+
+      int skipfirst = 0;
+      
+      blknr = grub_hfs_block (data, data->extents, data->fileid, i, 1);
+      if (grub_errno)
+       return -1;
+      
+      /* Last block.  */
+      if (i == blockcnt - 1)
+       {
+         blockend = (len + pos) % data->blksz;
+         
+         /* The last portion is exactly EXT2_BLOCK_SIZE (data).  */
+         if (! blockend)
+           blockend = data->blksz;
+       }
+
+      /* First block.  */
+      if (i == pos / data->blksz)
+       {
+         skipfirst = blockoff;
+         blockend -= skipfirst;
+       }
+
+      /* If the block number is 0 this block is not stored on disk but
+        is zero filled instead.  */
+      if (blknr)
+       {
+         data->disk->read_hook = read_hook;      
+         grub_disk_read (data->disk, blknr, skipfirst,
+                         blockend, buf);
+         data->disk->read_hook = 0;
+         if (grub_errno)
+           return -1;
+       }
+      
+      buf += data->blksz - skipfirst;
+    }
+  
+  return len;
+}
+
+
+/* Mount the filesystem on the disk DISK.  */
+static struct grub_hfs_data *
+grub_hfs_mount (grub_disk_t disk)
+{
+  struct grub_hfs_data *data;
+  struct grub_hfs_catalog_key key;
+  struct grub_hfs_dirrec dir;
+  int first_block;
+  
+  struct
+  {
+    struct grub_hfs_node node;
+    struct grub_hfs_treeheader head;
+  } treehead;
+  
+  data = grub_malloc (sizeof (struct grub_hfs_data));
+  if (!data)
+    return 0;
+
+  /* Read the superblock.  */
+  if (grub_disk_read (disk, GRUB_HFS_SBLOCK, 0,
+                     sizeof (struct grub_hfs_sblock), (char *) &data->sblock))
+    goto fail;
+  
+  /* Check if this is a HFS filesystem.  */
+  if (grub_be_to_cpu16 (data->sblock.magic) != GRUB_HFS_MAGIC)
+    {
+      grub_error (GRUB_ERR_BAD_FS, "not an HFS filesystem");
+      goto fail;
+    }
+
+  /* Check if this is an embedded HFS+ filesystem.  */
+  if (grub_be_to_cpu16 (data->sblock.embed_sig) == GRUB_HFS_EMBED_HFSPLUS_SIG)
+    {
+      grub_error (GRUB_ERR_BAD_FS, "embedded HFS+ filesystem");
+      goto fail;
+    }
+  
+  data->blksz = grub_be_to_cpu32 (data->sblock.blksz);
+  data->disk = disk;
+  
+  /* Lookup the root node of the extent overflow tree.  */
+  first_block = ((grub_be_to_cpu16 (data->sblock.extent_recs[0].first_block) 
+                 * GRUB_HFS_BLKS)
+                + grub_be_to_cpu16 (data->sblock.first_block));
+  
+  if (grub_disk_read (data->disk, first_block, 0,
+                     sizeof (treehead), (char *)  &treehead))
+    goto fail;
+  data->ext_root = grub_be_to_cpu32 (treehead.head.root_node);
+  data->ext_size = grub_be_to_cpu16 (treehead.head.node_size);
+  
+  /* Lookup the root node of the catalog tree.  */
+  first_block = ((grub_be_to_cpu16 (data->sblock.catalog_recs[0].first_block) 
+                 * GRUB_HFS_BLKS)
+                + grub_be_to_cpu16 (data->sblock.first_block));
+  if (grub_disk_read (data->disk, first_block, 0,
+                     sizeof (treehead), (char *)  &treehead))
+    goto fail;
+  data->cat_root = grub_be_to_cpu32 (treehead.head.root_node);
+  data->cat_size = grub_be_to_cpu16 (treehead.head.node_size);
+  
+  /* Lookup the root directory node in the catalog tree using the
+     volume name.  */
+  key.parent_dir = grub_cpu_to_be32 (1);
+  key.strlen = data->sblock.volname[0];
+  grub_strcpy ((char *) key.str, (char *) (data->sblock.volname + 1));
+  
+  if (grub_hfs_find_node (data, (char *) &key, data->cat_root,
+                         0, (char *) &dir, sizeof (dir)) == 0)
+    {
+      grub_error (GRUB_ERR_BAD_FS, "can not find the hfs root directory");
+      goto fail;
+    }
+    
+  if (grub_errno)
+    goto fail;
+
+  data->rootdir = grub_be_to_cpu32 (dir.dirid);
+  
+  return data;
+ fail:
+  grub_free (data);
+  
+  if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+    grub_error (GRUB_ERR_BAD_FS, "not a hfs filesystem");
+  
+  return 0;
+}
+
+
+/* Compare the K1 and K2 catalog file keys.  */
+static int
+grub_hfs_cmp_catkeys (struct grub_hfs_catalog_key *k1,
+                     struct grub_hfs_catalog_key *k2)
+{
+  int cmp = (grub_be_to_cpu32 (k1->parent_dir)
+            - grub_be_to_cpu32 (k2->parent_dir));
+  
+  if (cmp != 0)
+    return cmp;
+  
+  cmp = grub_strncasecmp ((char *) (k1->str), (char *) (k2->str), k1->strlen);
+  
+  /* This is required because the compared strings are not of equal
+     length.  */
+  if (cmp == 0 && k1->strlen < k2->strlen)
+    return -1;
+  return cmp;
+}
+
+
+/* Compare the K1 and K2 extent overflow file keys.  */
+static int
+grub_hfs_cmp_extkeys (struct grub_hfs_extent_key *k1,
+                     struct grub_hfs_extent_key *k2)
+{
+  int cmp = k1->forktype - k2->forktype;
+  if (cmp == 0)
+    cmp = grub_be_to_cpu32 (k1->fileid) - grub_be_to_cpu32 (k2->fileid);
+  if (cmp == 0)
+    cmp = (grub_be_to_cpu16 (k1->first_block) 
+          - grub_be_to_cpu16 (k2->first_block));
+  return cmp;
+}
+
+
+/* Iterate the records in the node with index IDX in the mounted HFS
+   filesystem DATA.  This node holds data of the type TYPE (0 =
+   catalog node, 1 = extent overflow node).  If this is set, continue
+   iterating to the next node.  For every records, call NODE_HOOK.  */
+static grub_err_t
+grub_hfs_iterate_records (struct grub_hfs_data *data, int type, int idx,
+                         int this, int (*node_hook) (struct grub_hfs_node *hnd,
+                                                     struct grub_hfs_record *))
+{
+  int nodesize = type == 0 ? data->cat_size : data->ext_size;
+  
+  union
+  {
+    struct grub_hfs_node node;
+    char rawnode[nodesize];
+    grub_uint16_t offsets[nodesize / 2];
+  } node;
+  
+  do
+    {
+      int i;
+      struct grub_hfs_extent *dat;
+      int blk;
+      
+      dat = (struct grub_hfs_extent *) (type == 0 
+                                       ? (&data->sblock.catalog_recs)
+                                       : (&data->sblock.extent_recs));
+      
+      /* Read the node into memory.  */
+      blk = grub_hfs_block (data, dat,
+                            (type == 0) ? GRUB_HFS_CNID_CAT : GRUB_HFS_CNID_EXT,
+                           idx / (data->blksz / nodesize), 0);
+      blk += (idx % (data->blksz / nodesize));
+      if (grub_errno)
+       return grub_errno;
+      
+      if (grub_disk_read (data->disk, blk, 0,
+                         sizeof (node), (char *)  &node))
+       return grub_errno;
+      
+      /* Iterate over all records in this node.  */
+      for (i = 0; i < grub_be_to_cpu16 (node.node.reccnt); i++)
+       {
+         int pos = (nodesize >> 1) - 1 - i;
+         struct pointer
+         {
+           grub_uint8_t keylen;
+           grub_uint8_t key;
+         } __attribute__ ((packed)) *pnt;
+         pnt = (struct pointer *) (grub_be_to_cpu16 (node.offsets[pos])
+                                   + node.rawnode);
+         
+         struct grub_hfs_record rec = 
+           {
+             &pnt->key,
+             pnt->keylen,
+             &pnt->key + pnt->keylen +(pnt->keylen + 1) % 2,
+             nodesize - grub_be_to_cpu16 (node.offsets[pos]) 
+             - pnt->keylen - 1
+           };
+         
+         if (node_hook (&node.node, &rec))
+           return 0;
+       }
+      
+      idx = grub_be_to_cpu32 (node.node.next);
+    } while (idx && this);
+  
+  return 0;
+}
+
+
+/* Lookup a record in the mounted filesystem DATA using the key KEY.
+   The index of the node on top of the tree is IDX.  The tree is of
+   the type TYPE (0 = catalog node, 1 = extent overflow node).  Return
+   the data in DATAR with a maximum length of DATALEN.  */
+static int
+grub_hfs_find_node (struct grub_hfs_data *data, char *key,
+                   grub_uint32_t idx, int type, char *datar, int datalen)
+{
+  int found = -1;
+  int isleaf = 0;
+  int done = 0;
+  
+  auto int node_found (struct grub_hfs_node *, struct grub_hfs_record *);
+    
+  int node_found (struct grub_hfs_node *hnd, struct grub_hfs_record *rec)
+    {
+      int cmp = 1;
+      
+      if (type == 0)
+       cmp = grub_hfs_cmp_catkeys (rec->key, (void *) key);
+      else
+       cmp = grub_hfs_cmp_extkeys (rec->key, (void *) key);
+      
+      /* If the key is smaller or equal to the currect node, mark the
+        entry.  In case of a non-leaf mode it will be used to lookup
+        the rest of the tree.  */
+      if (cmp <= 0)
+       {
+         grub_uint32_t *node = (grub_uint32_t *) rec->data;
+         found = grub_be_to_cpu32 (*node);
+       }
+      else /* The key can not be found in the tree. */
+       return 1;
+      
+      /* Check if this node is a leaf node.  */
+      if (hnd->type == GRUB_HFS_NODE_LEAF)
+       {
+         isleaf = 1;
+         
+         /* Found it!!!!  */
+         if (cmp == 0)
+           {
+              done = 1;
+
+             grub_memcpy (datar, rec->data,
+                          rec->datalen < datalen ? rec->datalen : datalen);
+             return 1;
+           }
+       }
+      
+      return 0;
+    }
+  
+  do
+    {
+      found = -1;
+
+      if (grub_hfs_iterate_records (data, type, idx, 0, node_found))
+        return 0;
+  
+      if (found == -1)
+        return 0;
+
+      idx = found;
+    } while (! isleaf);
+  
+  return done;
+}
+
+
+/* Iterate over the directory with the id DIR.  The tree is searched
+   starting with the node ROOT_IDX.  For every entry in this directory
+   call HOOK.  */
+static grub_err_t
+grub_hfs_iterate_dir (struct grub_hfs_data *data, grub_uint32_t root_idx,
+                     unsigned int dir, int (*hook) (struct grub_hfs_record *))
+{
+  int found = -1;
+  int isleaf = 0;
+  int next = 0;
+  
+  /* The lowest key possible with DIR as root directory.  */
+  struct grub_hfs_catalog_key key = {0, grub_cpu_to_be32 (dir), 0, ""};
+
+  auto int node_found (struct grub_hfs_node *, struct grub_hfs_record *);
+  auto int it_dir (struct grub_hfs_node * __attribute ((unused)),
+                  struct grub_hfs_record *);
+
+  
+  int node_found (struct grub_hfs_node *hnd, struct grub_hfs_record *rec)
+    {
+      struct grub_hfs_catalog_key *ckey = rec->key;
+      
+      if (grub_hfs_cmp_catkeys (rec->key, (void *) &key) <= 0)
+       found = grub_be_to_cpu32 (*(grub_uint32_t *) rec->data);
+      
+      if (hnd->type == 0xFF && ckey->strlen > 0)
+       {
+         isleaf = 1;
+         next = grub_be_to_cpu32 (hnd->next);
+         
+         /* An entry was found.  */
+         if (grub_be_to_cpu32 (ckey->parent_dir) == dir)
+           return hook (rec);
+       }
+      
+      return 0;
+    }
+  
+  int it_dir (struct grub_hfs_node *hnd __attribute ((unused)),
+             struct grub_hfs_record *rec)
+    {
+      struct grub_hfs_catalog_key *ckey = rec->key;
+      struct grub_hfs_catalog_key *origkey = &key;
+      
+      /* Stop when the entries do not match anymore.  */
+      if (grub_be_to_cpu32 (ckey->parent_dir) 
+         != grub_be_to_cpu32 ((origkey)->parent_dir))
+       return 1;
+      
+      return hook (rec);
+    }
+  
+  do
+    {
+      found = -1;
+
+      if (grub_hfs_iterate_records (data, 0, root_idx, 0, node_found))
+        return grub_errno;
+  
+      if (found == -1)
+        return 0;
+  
+      root_idx = found;
+    } while (! isleaf);
+
+  /* If there was a matching record in this leaf node, continue the
+     iteration until the last record was found.  */
+  grub_hfs_iterate_records (data, 0, next, 1, it_dir);
+  return grub_errno;
+}
+
+
+/* Find a file or directory with the pathname PATH in the filesystem
+   DATA.  Return the file record in RETDATA when it is non-zero.
+   Return the directory number in RETINODE when it is non-zero.  */
+static grub_err_t
+grub_hfs_find_dir (struct grub_hfs_data *data, const char *path,
+                  struct grub_hfs_filerec *retdata, int *retinode)
+{
+  int inode = data->rootdir;
+  char *next;
+  char *origpath;
+  struct grub_hfs_filerec frec;
+  struct grub_hfs_dirrec *dir = (struct grub_hfs_dirrec *) &frec;
+  frec.type = GRUB_HFS_FILETYPE_DIR;
+  
+  if (path[0] != '/')
+    {
+      grub_error (GRUB_ERR_BAD_FILENAME, "bad filename");
+      return 0;
+    }
+  
+  origpath = grub_strdup (path);
+  if (!origpath)
+    return grub_errno;
+  
+  path = origpath;
+  path++;
+  
+  while (path && grub_strlen (path))
+    {
+      if (frec.type != GRUB_HFS_FILETYPE_DIR)
+       {
+         grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+         goto fail;
+       }
+      
+      /* Isolate a part of the path.  */
+      next = grub_strchr (path, '/');
+      if (next)
+       {
+         next[0] = '\0';
+         next++;
+       }
+      
+      struct grub_hfs_catalog_key key;
+      
+      key.parent_dir = grub_cpu_to_be32 (inode);
+      key.strlen = grub_strlen (path);
+      grub_strcpy ((char *) (key.str), path);
+      
+      /* Lookup this node.  */
+      if (! grub_hfs_find_node (data, (char *) &key, data->cat_root,
+                               0, (char *) &frec, sizeof (frec)))
+       {
+         grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+         goto fail;
+       }
+
+      if (grub_errno)
+       goto fail;
+      
+      inode = grub_be_to_cpu32 (dir->dirid);
+      path = next;
+    }
+
+  if (retdata)
+    grub_memcpy (retdata, &frec, sizeof (frec));
+  
+  if (retinode)
+    *retinode = inode;
+  
+ fail:
+  grub_free (origpath);
+  return grub_errno;
+}
+
+
+\f
+static grub_err_t
+grub_hfs_dir (grub_device_t device, const char *path, 
+                 int (*hook) (const char *filename, int dir))
+{
+  int inode;
+
+  auto int dir_hook (struct grub_hfs_record *rec);
+
+  int dir_hook (struct grub_hfs_record *rec)
+    {
+      char fname[32] = { 0 };
+      char *filetype = rec->data;
+      struct grub_hfs_catalog_key *ckey = rec->key;
+      
+      grub_strncpy (fname, (char *) (ckey->str), ckey->strlen);
+      
+      if (*filetype == GRUB_HFS_FILETYPE_DIR)
+       return hook (fname, 1);
+      else if (*filetype == GRUB_HFS_FILETYPE_FILE)
+       return hook (fname, 0);
+      return 0;
+    }
+  
+  struct grub_hfs_data *data;
+  struct grub_hfs_filerec frec;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  
+  data = grub_hfs_mount (device->disk);
+  if (!data)
+    goto fail;
+  
+  /* First the directory ID for the directory.  */
+  if (grub_hfs_find_dir (data, path, &frec, &inode))
+    goto fail;
+
+  if (frec.type != GRUB_HFS_FILETYPE_DIR)
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+      goto fail;
+    }
+  
+  grub_hfs_iterate_dir (data, data->cat_root, inode, dir_hook);
+  
+ fail:
+  grub_free (data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+  
+  return grub_errno;
+}
+
+
+/* Open a file named NAME and initialize FILE.  */
+static grub_err_t
+grub_hfs_open (struct grub_file *file, const char *name)
+{
+  struct grub_hfs_data *data;
+  struct grub_hfs_filerec frec;
+  
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_hfs_mount (file->device->disk);
+  
+  if (grub_hfs_find_dir (data, name, &frec, 0))
+    {
+      grub_free (data);
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+      return grub_errno;
+    }
+  
+  if (frec.type != GRUB_HFS_FILETYPE_FILE)
+    {
+      grub_free (data);
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a file");
+#ifndef GRUB_UTIL
+      grub_dl_unref (my_mod);
+#endif
+      return grub_errno;
+    }
+  
+  grub_memcpy (data->extents, frec.extents, sizeof (grub_hfs_datarecord_t));
+  file->size = grub_be_to_cpu32 (frec.size);
+  data->size = grub_be_to_cpu32 (frec.size);
+  data->fileid = grub_be_to_cpu32 (frec.fileid);
+  file->offset = 0;
+
+  file->data = data;
+  
+  return 0;
+}
+
+static grub_ssize_t
+grub_hfs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_hfs_data *data = 
+    (struct grub_hfs_data *) file->data;
+  
+  return grub_hfs_read_file (data, file->read_hook, file->offset, len, buf);
+}
+
+
+static grub_err_t
+grub_hfs_close (grub_file_t file)
+{
+  grub_free (file->data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return 0;
+}
+
+
+static grub_err_t
+grub_hfs_label (grub_device_t device, char **label)
+{
+  struct grub_hfs_data *data;
+
+  data = grub_hfs_mount (device->disk);
+  
+  if (data)
+    *label = grub_strndup ((char *) (data->sblock.volname + 1),
+                          *data->sblock.volname);
+  else
+    *label = 0;
+
+  grub_free (data);
+  return grub_errno;
+}
+
+
+\f
+static struct grub_fs grub_hfs_fs =
+  {
+    .name = "hfs",
+    .dir = grub_hfs_dir,
+    .open = grub_hfs_open,
+    .read = grub_hfs_read,
+    .close = grub_hfs_close,
+    .label = grub_hfs_label,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(hfs)
+{
+  grub_fs_register (&grub_hfs_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(hfs)
+{
+  grub_fs_unregister (&grub_hfs_fs);
+}
diff --git a/fs/hfsplus.c b/fs/hfsplus.c
new file mode 100644 (file)
index 0000000..7022f98
--- /dev/null
@@ -0,0 +1,975 @@
+/* hfsplus.c - HFS+ Filesystem.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2006,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/>.
+ */
+
+/* HFS+ is documented at http://developer.apple.com/technotes/tn/tn1150.html */
+
+#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/hfs.h>
+
+#define GRUB_HFSPLUS_MAGIC 0x482B
+#define GRUB_HFSPLUSX_MAGIC 0x4858
+#define GRUB_HFSPLUS_SBLOCK 2
+
+/* A HFS+ extent.  */
+struct grub_hfsplus_extent
+{
+  /* The first block of a file on disk.  */
+  grub_uint32_t start;
+  /* The amount of blocks described by this extent.  */
+  grub_uint32_t count;
+} __attribute__ ((packed));
+
+/* The descriptor of a fork.  */
+struct grub_hfsplus_forkdata
+{
+  grub_uint64_t size;
+  grub_uint32_t clumpsize;
+  grub_uint32_t blocks;
+  struct grub_hfsplus_extent extents[8];
+} __attribute__ ((packed));
+
+/* The HFS+ Volume Header.  */
+struct grub_hfsplus_volheader
+{
+  grub_uint16_t magic;
+  grub_uint16_t version;
+  grub_uint32_t attributes;
+  grub_uint8_t unused[32];
+  grub_uint32_t blksize;
+  grub_uint8_t unused2[68];
+  struct grub_hfsplus_forkdata allocations_file;
+  struct grub_hfsplus_forkdata extents_file;
+  struct grub_hfsplus_forkdata catalog_file;
+  struct grub_hfsplus_forkdata attrib_file;
+  struct grub_hfsplus_forkdata startup_file;
+} __attribute__ ((packed));
+
+/* The type of node.  */
+enum grub_hfsplus_btnode_type
+  {
+    GRUB_HFSPLUS_BTNODE_TYPE_LEAF = -1,
+    GRUB_HFSPLUS_BTNODE_TYPE_INDEX = 0,
+    GRUB_HFSPLUS_BTNODE_TYPE_HEADER = 1,
+    GRUB_HFSPLUS_BTNODE_TYPE_MAP = 2,
+  };
+
+struct grub_hfsplus_btnode
+{
+  grub_uint32_t next;
+  grub_uint32_t prev;
+  grub_int8_t type;
+  grub_uint8_t height;
+  grub_uint16_t count;
+  grub_uint16_t unused;
+} __attribute__ ((packed));
+
+/* The header of a HFS+ B+ Tree.  */
+struct grub_hfsplus_btheader
+{
+  grub_uint16_t depth;
+  grub_uint32_t root;
+  grub_uint32_t leaf_records;
+  grub_uint32_t first_leaf_node;
+  grub_uint32_t last_leaf_node;
+  grub_uint16_t nodesize;
+  grub_uint16_t keysize;
+} __attribute__ ((packed));
+
+/* The on disk layout of a catalog key.  */
+struct grub_hfsplus_catkey
+{
+  grub_uint16_t keylen;
+  grub_uint32_t parent;
+  grub_uint16_t namelen;
+  grub_uint16_t name[30];
+} __attribute__ ((packed));
+
+/* The on disk layout of an extent overflow file key.  */
+struct grub_hfsplus_extkey
+{
+  grub_uint16_t keylen;
+  grub_uint8_t type;
+  grub_uint8_t unused;
+  grub_uint32_t fileid;
+  grub_uint32_t start;
+} __attribute__ ((packed));
+
+struct grub_hfsplus_key
+{
+  union
+  {
+    struct grub_hfsplus_extkey extkey;
+    struct grub_hfsplus_catkey catkey;
+    grub_uint16_t keylen;
+  };
+} __attribute__ ((packed));
+
+struct grub_hfsplus_catfile
+{
+  grub_uint16_t type;
+  grub_uint16_t flags;
+  grub_uint32_t reserved;
+  grub_uint32_t fileid;
+  grub_uint8_t unused1[30];
+  grub_uint16_t mode;
+  grub_uint8_t unused2[44];
+  struct grub_hfsplus_forkdata data;
+  struct grub_hfsplus_forkdata resource;
+} __attribute__ ((packed));
+
+/* Filetype information as used in inodes.  */
+#define GRUB_HFSPLUS_FILEMODE_MASK     0170000
+#define GRUB_HFSPLUS_FILEMODE_REG      0100000
+#define GRUB_HFSPLUS_FILEMODE_DIRECTORY        0040000
+#define GRUB_HFSPLUS_FILEMODE_SYMLINK  0120000
+
+/* Some pre-defined file IDs.  */
+#define GRUB_HFSPLUS_FILEID_ROOTDIR    2
+#define GRUB_HFSPLUS_FILEID_OVERFLOW   3
+#define GRUB_HFSPLUS_FILEID_CATALOG    4
+
+enum grub_hfsplus_filetype
+  {
+    GRUB_HFSPLUS_FILETYPE_DIR = 1,
+    GRUB_HFSPLUS_FILETYPE_REG = 2,
+    GRUB_HFSPLUS_FILETYPE_DIR_THREAD = 3,
+    GRUB_HFSPLUS_FILETYPE_REG_THREAD = 4
+  };
+
+/* Internal representation of a catalog key.  */
+struct grub_hfsplus_catkey_internal
+{
+  int parent;
+  char *name;
+};
+
+/* Internal representation of an extent overflow key.  */
+struct grub_hfsplus_extkey_internal
+{
+  grub_uint32_t fileid;
+  grub_uint32_t start;
+};
+
+struct grub_hfsplus_key_internal
+{
+  union
+  {
+    struct grub_hfsplus_extkey_internal extkey;
+    struct grub_hfsplus_catkey_internal catkey;
+  };
+};
+
+\f
+
+struct grub_fshelp_node
+{
+  struct grub_hfsplus_data *data;
+  struct grub_hfsplus_extent extents[8];
+  grub_uint64_t size;
+  grub_uint32_t fileid;
+};
+
+struct grub_hfsplus_btree
+{
+  grub_uint32_t root;
+  int nodesize;
+
+  /* Catalog file node.  */
+  struct grub_fshelp_node file;
+};
+
+/* Information about a "mounted" HFS+ filesystem.  */
+struct grub_hfsplus_data
+{
+  struct grub_hfsplus_volheader volheader;
+  grub_disk_t disk;
+
+  unsigned int log2blksize;
+
+  struct grub_hfsplus_btree catalog_tree;
+  struct grub_hfsplus_btree extoverflow_tree;
+
+  struct grub_fshelp_node dirroot;
+  struct grub_fshelp_node opened_file;
+
+  /* This is the offset into the physical disk for an embedded HFS+
+     filesystem (one inside a plain HFS wrapper).  */
+  int embedded_offset;
+};
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+\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
+grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree,
+                          struct grub_hfsplus_btnode *node, int index)
+{
+  char *cnode = (char *) node;
+  grub_uint16_t *recptr;
+  recptr = (grub_uint16_t *) (&cnode[btree->nodesize
+                                    - index * sizeof (grub_uint16_t) - 2]);
+  return grub_be_to_cpu16 (*recptr);
+}
+
+/* Return a pointer to the record with the index INDEX, in the node
+   NODE which is part of the B+ tree BTREE.  */
+static inline struct grub_hfsplus_key *
+grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree,
+                          struct grub_hfsplus_btnode *node, int index)
+{
+  char *cnode = (char *) node;
+  unsigned int offset;
+  offset = grub_hfsplus_btree_recoffset (btree, node, index);
+  return (struct grub_hfsplus_key *) &cnode[offset];
+}
+
+
+/* Find the extent that points to FILEBLOCK.  If it is not in one of
+   the 8 extents described by EXTENT, return -1.  In that case set
+   FILEBLOCK to the next block.  */
+static int
+grub_hfsplus_find_block (struct grub_hfsplus_extent *extent,
+                        int *fileblock)
+{
+  int i;
+  grub_size_t blksleft = *fileblock;
+
+  /* First lookup the file in the given extents.  */
+  for (i = 0; i < 8; i++)
+    {
+      if (blksleft < grub_be_to_cpu32 (extent[i].count))
+       return grub_be_to_cpu32 (extent[i].start) + blksleft;
+      blksleft -= grub_be_to_cpu32 (extent[i].count);
+    }
+
+  *fileblock = blksleft;
+  return -1;
+}
+
+static grub_err_t
+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);
+
+static int grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya,
+                                   struct grub_hfsplus_key_internal *keyb);
+
+/* Search for the block FILEBLOCK inside the file NODE.  Return the
+   blocknumber of this block on disk.  */
+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;
+  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;
+
+      /* Try to find this block in the current set of extents.  */
+      blk = grub_hfsplus_find_block (extents, &blksleft);
+
+      /* The previous iteration of this loop allocated memory.  The
+        code above used this memory, it can be freed now.  */
+      grub_free (nnode);
+      nnode = 0;
+      
+      if (blk != -1)
+       return (blk
+               + (node->data->embedded_offset >> (node->data->log2blksize
+                                                  - GRUB_DISK_SECTOR_BITS)));
+
+      /* For the extent overflow file, extra extents can't be found in
+        the extent overflow file.  If this happens, you found a
+        bug...  */
+      if (node->fileid == GRUB_HFSPLUS_FILEID_OVERFLOW)
+       {
+         grub_error (GRUB_ERR_READ_ERROR,
+                     "extra extents found in an extend overflow file");
+         break;
+       }
+
+      /* Set up the key to look for in the extent overflow file.  */
+      extoverflow.fileid = node->fileid;
+      extoverflow.start = fileblock - blksleft;
+
+      if (grub_hfsplus_btree_search (&node->data->extoverflow_tree,
+                                    (struct grub_hfsplus_key_internal *) &extoverflow,
+                                    grub_hfsplus_cmp_extkey, &nnode, &ptr))
+       {
+         grub_error (GRUB_ERR_READ_ERROR,
+                     "no block found for the file id 0x%x and the block offset 0x%x",
+                     node->fileid, fileblock);
+         break;
+       }
+
+      /* The extent overflow file has 8 extents right after the key.  */
+      key = (struct grub_hfsplus_extkey *)
+       grub_hfsplus_btree_recptr (&node->data->extoverflow_tree, nnode, ptr);
+      extents = (struct grub_hfsplus_extent *) (key + 1);
+
+      /* The block wasn't found.  Perhaps the next iteration will find
+        it.  The last block we found is stored in BLKSLEFT now.  */
+    }
+
+  grub_free (nnode);
+
+  /* Too bad, you lose.  */
+  return -1;
+}
+
+
+/* Read LEN bytes from the file described by DATA starting with byte
+   POS.  Return the amount of read bytes in READ.  */
+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)
+{
+  return grub_fshelp_read_file (node->data->disk, node, read_hook,
+                               pos, len, buf, grub_hfsplus_read_block,
+                               node->size,
+                               node->data->log2blksize - GRUB_DISK_SECTOR_BITS);
+}
+
+static struct grub_hfsplus_data *
+grub_hfsplus_mount (grub_disk_t disk)
+{
+  struct grub_hfsplus_data *data;
+  struct grub_hfsplus_btheader header;
+  struct grub_hfsplus_btnode node;
+  union {
+    struct grub_hfs_sblock hfs;
+    struct grub_hfsplus_volheader hfsplus;
+  } volheader;
+
+  data = grub_malloc (sizeof (*data));
+  if (!data)
+    return 0;
+
+  data->disk = disk;
+
+  /* Read the bootblock.  */
+  grub_disk_read (disk, GRUB_HFSPLUS_SBLOCK, 0, sizeof (volheader),
+                 (char *) &volheader);
+  if (grub_errno)
+    goto fail;
+
+  data->embedded_offset = 0;
+  if (grub_be_to_cpu16 (volheader.hfs.magic) == GRUB_HFS_MAGIC)
+    {
+      int extent_start;
+      int ablk_size;
+      int ablk_start;
+
+      /* See if there's an embedded HFS+ filesystem.  */
+      if (grub_be_to_cpu16 (volheader.hfs.embed_sig) != GRUB_HFSPLUS_MAGIC)
+       {
+         grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem");
+         goto fail;
+       }
+
+      /* Calculate the offset needed to translate HFS+ sector numbers.  */
+      extent_start = grub_be_to_cpu16 (volheader.hfs.embed_extent.first_block);
+      ablk_size = grub_be_to_cpu32 (volheader.hfs.blksz);
+      ablk_start = grub_be_to_cpu16 (volheader.hfs.first_block);
+      data->embedded_offset = (ablk_start
+                              + extent_start
+                              * (ablk_size >> GRUB_DISK_SECTOR_BITS));
+
+      grub_disk_read (disk, data->embedded_offset + GRUB_HFSPLUS_SBLOCK, 0,
+                     sizeof (volheader), (char *) &volheader);
+      if (grub_errno)
+       goto fail;
+    }
+
+  /* Make sure this is an HFS+ filesystem.  XXX: Do we really support
+     HFX?  */
+  if ((grub_be_to_cpu16 (volheader.hfsplus.magic) != GRUB_HFSPLUS_MAGIC)
+      && (grub_be_to_cpu16 (volheader.hfsplus.magic) != GRUB_HFSPLUSX_MAGIC))
+    {
+      grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem");
+      goto fail;
+    }
+
+  grub_memcpy (&data->volheader, &volheader.hfsplus,
+      sizeof (volheader.hfsplus));
+
+  if (grub_fshelp_log2blksize (grub_be_to_cpu32 (data->volheader.blksize),
+                              &data->log2blksize))
+    goto fail;
+
+  /* Make a new node for the catalog tree.  */
+  data->catalog_tree.file.data = data;
+  data->catalog_tree.file.fileid = GRUB_HFSPLUS_FILEID_CATALOG;
+  grub_memcpy (&data->catalog_tree.file.extents,
+              data->volheader.catalog_file.extents,
+              sizeof data->volheader.catalog_file.extents);
+  data->catalog_tree.file.size = 
+    grub_be_to_cpu64 (data->volheader.catalog_file.size);
+
+  /* Make a new node for the extent overflow file.  */
+  data->extoverflow_tree.file.data = data;
+  data->extoverflow_tree.file.fileid = GRUB_HFSPLUS_FILEID_OVERFLOW;
+  grub_memcpy (&data->extoverflow_tree.file.extents,
+              data->volheader.extents_file.extents,
+              sizeof data->volheader.catalog_file.extents);
+
+  data->extoverflow_tree.file.size = 
+    grub_be_to_cpu64 (data->volheader.extents_file.size);
+
+  /* Read the essential information about the trees.  */
+  if (! grub_hfsplus_read_file (&data->catalog_tree.file, 0,
+                               sizeof (struct grub_hfsplus_btnode),
+                               sizeof (header), (char *) &header))
+    goto fail;
+
+  data->catalog_tree.root = grub_be_to_cpu32 (header.root);
+  data->catalog_tree.nodesize = grub_be_to_cpu16 (header.nodesize);
+
+  if (! grub_hfsplus_read_file (&data->extoverflow_tree.file, 0,
+                               sizeof (struct grub_hfsplus_btnode),
+                               sizeof (header), (char *) &header))
+    goto fail;
+
+  data->extoverflow_tree.root = grub_be_to_cpu32 (header.root);
+
+  if (! grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0,
+                               sizeof (node), (char *) &node))
+    goto fail;
+
+  data->extoverflow_tree.root = grub_be_to_cpu32 (header.root);
+  data->extoverflow_tree.nodesize = grub_be_to_cpu16 (header.nodesize);
+
+  data->dirroot.data = data;
+  data->dirroot.fileid = GRUB_HFSPLUS_FILEID_ROOTDIR;
+
+  return data;
+
+ fail:
+
+  if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+    grub_error (GRUB_ERR_BAD_FS, "not a hfsplus filesystem");
+
+  grub_free (data);
+  return 0;
+}
+
+/* Compare the on disk catalog key KEYA with the catalog key we are
+   looking for (KEYB).  */
+static int
+grub_hfsplus_cmp_catkey (struct grub_hfsplus_key *keya,
+                        struct grub_hfsplus_key_internal *keyb)
+{
+  struct grub_hfsplus_catkey *catkey_a = &keya->catkey;
+  struct grub_hfsplus_catkey_internal *catkey_b = &keyb->catkey;
+  char *filename;
+  int i;
+  int diff;
+  
+  diff = grub_be_to_cpu32 (catkey_a->parent) - catkey_b->parent;
+  if (diff)
+    return diff; 
+
+  /* Change the filename in keya so the endianness is correct.  */
+  for (i = 0; i < grub_be_to_cpu16 (catkey_a->namelen); i++)
+    catkey_a->name[i] = grub_be_to_cpu16 (catkey_a->name[i]);
+
+  filename = grub_malloc (grub_be_to_cpu16 (catkey_a->namelen) + 1);
+
+  if (! grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey_a->name,
+                           grub_be_to_cpu16 (catkey_a->namelen)))
+    return -1; /* XXX: This error never occurs, but in case it happens
+                 just skip this entry.  */
+
+  diff = grub_strncmp (filename, catkey_b->name,
+                      grub_be_to_cpu16 (catkey_a->namelen));
+
+  grub_free (filename);
+
+  /* The endianness was changed to host format, change it back to
+     whatever it was.  */
+  for (i = 0; i < grub_be_to_cpu16 (catkey_a->namelen); i++)
+    catkey_a->name[i] = grub_cpu_to_be16 (catkey_a->name[i]);
+  return diff;
+}
+
+/* Compare the on disk extent overflow key KEYA with the extent
+   overflow key we are looking for (KEYB).  */
+static int
+grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya,
+                        struct grub_hfsplus_key_internal *keyb)
+{
+  struct grub_hfsplus_extkey *extkey_a = &keya->extkey;
+  struct grub_hfsplus_extkey_internal *extkey_b = &keyb->extkey;
+  int diff;
+
+  diff = grub_be_to_cpu32 (extkey_a->fileid) - extkey_b->fileid;
+
+  if (diff)
+    return diff;
+
+  diff = grub_be_to_cpu32 (extkey_a->start) - extkey_b->start;
+  return diff;
+}
+
+static char *
+grub_hfsplus_read_symlink (grub_fshelp_node_t node)
+{
+  char *symlink;
+  grub_ssize_t numread;
+
+  symlink = grub_malloc (node->size + 1);
+  if (!symlink)
+    return 0;
+
+  numread = grub_hfsplus_read_file (node, 0, 0, node->size, symlink);
+  if (numread != (grub_ssize_t) node->size)
+    {
+      grub_free (symlink);
+      return 0;
+    }
+  symlink[node->size] = '\0';
+
+  return symlink;
+}
+
+static int
+grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree,
+                                struct grub_hfsplus_btnode *first_node,
+                                int first_rec,
+                                int (*hook) (void *record))
+{
+  int rec;  
+
+  for (;;)
+    {
+      char *cnode = (char *) first_node;
+
+      /* Iterate over all records in this node.  */
+      for (rec = first_rec; rec < grub_be_to_cpu16 (first_node->count); rec++)
+       {
+         if (hook (grub_hfsplus_btree_recptr (btree, first_node, rec)))
+           return 1;
+       }
+
+      if (! first_node->next)
+       break;
+
+      if (! grub_hfsplus_read_file (&btree->file, 0,
+                                   (grub_be_to_cpu32 (first_node->next)
+                                    * btree->nodesize),
+                                   btree->nodesize, cnode))
+       return 1;
+
+      /* Don't skip any record in the next iteration.  */
+      first_rec = 0;
+    }
+
+  return 0;
+}
+
+/* Lookup the node described by KEY in the B+ Tree BTREE.  Compare
+   keys using the function COMPARE_KEYS.  When a match is found,
+   return the node in MATCHNODE and a pointer to the data in this node
+   in KEYOFFSET.  MATCHNODE should be freed by the caller.  */
+static grub_err_t
+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)
+{
+  grub_uint64_t currnode;
+  char *node;
+  struct grub_hfsplus_btnode *nodedesc;
+  int rec;
+
+  node = grub_malloc (btree->nodesize);
+  if (! node)
+    return grub_errno;
+
+  currnode = btree->root;
+  while (1)
+    {
+      int match = 0;
+
+      /* Read a node.  */
+      if (! grub_hfsplus_read_file (&btree->file, 0,
+                                   (long)currnode * (long)btree->nodesize,
+                                   btree->nodesize, (char *) node))
+       {
+         grub_free (node);
+         return grub_errno;
+       }
+
+      nodedesc = (struct grub_hfsplus_btnode *) node;
+
+      /* Find the record in this tree.  */
+      for (rec = 0; rec < grub_be_to_cpu16 (nodedesc->count); rec++)
+       {
+         struct grub_hfsplus_key *currkey;
+         currkey = grub_hfsplus_btree_recptr (btree, nodedesc, rec);   
+  
+         /* The action that has to be taken depend on the type of
+            record.  */
+         if (nodedesc->type == GRUB_HFSPLUS_BTNODE_TYPE_LEAF
+             && compare_keys (currkey, key) == 0)
+           {
+             /* An exact match was found!  */
+
+             *matchnode = nodedesc;
+             *keyoffset = rec;
+
+             return 0;
+           }
+         else if (nodedesc->type == GRUB_HFSPLUS_BTNODE_TYPE_INDEX)
+           {
+             grub_uint32_t *pointer;
+
+             /* The place where the key could have been found didn't
+                contain the key.  This means that the previous match
+                is the one that should be followed.  */
+             if (compare_keys (currkey, key) > 0)
+               break;
+
+             /* Mark the last key which is lower or equal to the key
+                that we are looking for.  The last match that is
+                found will be used to locate the child which can
+                contain the record.  */
+             pointer = (grub_uint32_t *) ((char *) currkey
+                                          + grub_be_to_cpu16 (currkey->keylen)
+                                          + 2);
+             currnode = grub_be_to_cpu32 (*pointer);
+             match = 1;
+           }
+       }
+
+      /* No match is found, no record with this key exists in the
+        tree.  */
+      if (! match)
+       {
+         *matchnode = 0;
+         grub_free (node);
+         return 1;
+       }
+    }
+}
+
+static int
+grub_hfsplus_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))
+{
+  int ret = 0;
+  
+  auto int list_nodes (void *record);
+  int list_nodes (void *record)
+    {
+      struct grub_hfsplus_catkey *catkey;
+      char *filename;
+      int i;
+      struct grub_fshelp_node *node;
+      struct grub_hfsplus_catfile *fileinfo;
+      enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
+
+      catkey = (struct grub_hfsplus_catkey *) record;
+
+      fileinfo =
+       (struct grub_hfsplus_catfile *) ((char *) record 
+                                        + grub_be_to_cpu16 (catkey->keylen)
+                                        + 2 + (grub_be_to_cpu16(catkey->keylen)
+                                               % 2));
+
+      /* Stop iterating when the last directory entry is found.  */
+      if (grub_be_to_cpu32 (catkey->parent) != dir->fileid)
+       return 1;
+
+      /* Determine the type of the node that is found.  */
+      if (grub_be_to_cpu16 (fileinfo->type) == GRUB_HFSPLUS_FILETYPE_REG)
+       {
+         int mode = (grub_be_to_cpu16 (fileinfo->mode)
+                     & GRUB_HFSPLUS_FILEMODE_MASK);
+
+         if (mode == GRUB_HFSPLUS_FILEMODE_REG)
+           type = GRUB_FSHELP_REG;
+         else if (mode == GRUB_HFSPLUS_FILEMODE_SYMLINK)
+           type = GRUB_FSHELP_SYMLINK;
+         else
+           type = GRUB_FSHELP_UNKNOWN;
+       }
+      else if (grub_be_to_cpu16 (fileinfo->type) == GRUB_HFSPLUS_FILETYPE_DIR)
+       type = GRUB_FSHELP_DIR;
+
+      if (type == GRUB_FSHELP_UNKNOWN)
+       return 0;
+
+      /* Make sure the byte order of the UTF16 string is correct.  */
+      for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++)
+       {
+         catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]);
+
+         /* If the name is obviously invalid, skip this node.  */
+         if (catkey->name[i] == 0)
+           return 0;
+       }
+
+      filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen) + 1);
+      if (! filename)
+       return 0;
+
+      if (! grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name,
+                               grub_be_to_cpu16 (catkey->namelen)))
+       {
+         grub_free (filename);
+         return 0;
+       }
+
+      filename[grub_be_to_cpu16 (catkey->namelen)] = '\0';
+
+      /* Restore the byte order to what it was previously.  */
+      for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++)
+       catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]);
+
+      /* hfs+ is case insensitive.  */
+      type |= GRUB_FSHELP_CASE_INSENSITIVE;
+
+      /* Only accept valid nodes.  */
+      if (grub_strlen (filename) == grub_be_to_cpu16 (catkey->namelen))
+       {
+         /* A valid node is found; setup the node and call the
+            callback function.  */
+         node = grub_malloc (sizeof (*node));
+         node->data = dir->data;
+         
+         grub_memcpy (node->extents, fileinfo->data.extents,
+                      sizeof (node->extents));
+         node->size = grub_be_to_cpu64 (fileinfo->data.size);
+         node->fileid = grub_be_to_cpu32 (fileinfo->fileid);
+
+         ret = hook (filename, type, node);
+       }
+
+      grub_free (filename);
+
+      return ret;
+    }
+
+  struct grub_hfsplus_key_internal intern;
+  struct grub_hfsplus_btnode *node;
+  int ptr;
+
+  /* Create a key that points to the first entry in the directory.  */
+  intern.catkey.parent = dir->fileid;
+  intern.catkey.name = "";
+
+  /* First lookup the first entry.  */
+  if (grub_hfsplus_btree_search (&dir->data->catalog_tree, &intern,
+                                grub_hfsplus_cmp_catkey, &node, &ptr))
+    return 0;
+
+  /* Iterate over all entries in this directory.  */
+  grub_hfsplus_btree_iterate_node (&dir->data->catalog_tree, node, ptr,
+                                  list_nodes);
+
+  grub_free (node);
+
+  return ret;
+}
+
+/* Open a file named NAME and initialize FILE.  */
+static grub_err_t
+grub_hfsplus_open (struct grub_file *file, const char *name)
+{
+  struct grub_hfsplus_data *data;
+  struct grub_fshelp_node *fdiro = 0;
+  
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  
+  data = grub_hfsplus_mount (file->device->disk);
+  if (!data)
+    goto fail;
+
+  grub_fshelp_find_file (name, &data->dirroot, &fdiro,
+                        grub_hfsplus_iterate_dir,
+                        grub_hfsplus_read_symlink, GRUB_FSHELP_REG);
+  if (grub_errno)
+    goto fail;
+
+  file->size = fdiro->size;
+  data->opened_file = *fdiro;
+  grub_free (fdiro);
+
+  file->data = data;
+  file->offset = 0;
+
+  return 0;
+
+ fail:
+  if (data && fdiro != &data->dirroot)
+    grub_free (fdiro);
+  grub_free (data);
+  
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+
+static grub_err_t
+grub_hfsplus_close (grub_file_t file)
+{
+  grub_free (file->data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
+
+/* Read LEN bytes data from FILE into BUF.  */
+static grub_ssize_t
+grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_hfsplus_data *data = 
+    (struct grub_hfsplus_data *) file->data;
+
+  int size = grub_hfsplus_read_file (&data->opened_file, file->read_hook,
+                                    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, int dir))
+{
+  struct grub_hfsplus_data *data = 0;
+  struct grub_fshelp_node *fdiro = 0;
+  
+  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)
+    {
+      grub_free (node);
+      
+      if (filetype == GRUB_FSHELP_DIR)
+       return hook (filename, 1);
+      else 
+       return hook (filename, 0);
+      
+      return 0;
+    }
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  
+  data = grub_hfsplus_mount (device->disk);
+  if (!data)
+    goto fail;
+
+  /* Find the directory that should be opened.  */
+  grub_fshelp_find_file (path, &data->dirroot, &fdiro,
+                        grub_hfsplus_iterate_dir,
+                        grub_hfsplus_read_symlink, GRUB_FSHELP_DIR);
+  if (grub_errno)
+    goto fail;
+
+  /* Iterate over all entries in this directory.  */
+  grub_hfsplus_iterate_dir (fdiro, iterate);
+  
+ fail:
+  if (data && fdiro != &data->dirroot)
+    grub_free (fdiro);
+  grub_free (data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+
+static grub_err_t
+grub_hfsplus_label (grub_device_t device __attribute__((unused))
+                   , char **label __attribute__((unused)))
+{
+  /* XXX: It's not documented how to read a label.  */
+  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                    "reading the label of a HFS+ "
+                    "partition is not implemented");
+}
+
+\f
+static struct grub_fs grub_hfsplus_fs =
+  {
+    .name = "hfsplus",
+    .dir = grub_hfsplus_dir,
+    .open = grub_hfsplus_open,
+    .read = grub_hfsplus_read,
+    .close = grub_hfsplus_close,
+    .label = grub_hfsplus_label,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(hfsplus)
+{
+  grub_fs_register (&grub_hfsplus_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(hfsplus)
+{
+  grub_fs_unregister (&grub_hfsplus_fs);
+}
diff --git a/fs/i386/pc/pxe.c b/fs/i386/pc/pxe.c
new file mode 100644 (file)
index 0000000..e12ca18
--- /dev/null
@@ -0,0 +1,321 @@
+/* pxe.c - Driver to provide access to the pxe filesystem  */
+/*
+ *  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/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/machine/pxe.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_pxenv *grub_pxe_pxenv;
+grub_uint32_t grub_pxe_your_ip;
+grub_uint32_t grub_pxe_server_ip;
+grub_uint32_t grub_pxe_gateway_ip;
+int 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 int
+grub_pxe_iterate (int (*hook) (const char *name))
+{
+  if (hook ("pxe"))
+    return 1;
+  return 0;
+}
+
+static grub_err_t
+grub_pxe_open (const char *name, grub_disk_t disk)
+{
+  if (grub_strcmp (name, "pxe"))
+      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a pxe disk");
+
+  disk->total_sectors = 0;
+  disk->id = (unsigned long) "pxe";
+
+  disk->has_partitions = 0;
+  disk->data = 0;
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_pxe_close (grub_disk_t disk __attribute((unused)))
+{
+}
+
+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 __attribute((unused)),
+                const char *path __attribute((unused)),
+                int (*hook) (const char *filename, int dir) __attribute((unused)))
+{
+  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;
+  grub_file_t file_int, bufio;
+
+  if (curr_file != 0)
+    {
+      grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c.c2);
+      curr_file = 0;
+    }
+
+  c.c1.server_ip = grub_pxe_server_ip;
+  c.c1.gateway_ip = grub_pxe_gateway_ip;
+  grub_strcpy ((char *)&c.c1.filename[0], name);
+  grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1);
+  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);
+  if (c.c2.status)
+    return grub_error (GRUB_ERR_BAD_FS, "open fails");
+
+  data = grub_malloc (sizeof (struct grub_pxe_data) + grub_strlen (name) + 1);
+  if (! data)
+    return grub_errno;
+
+  data->packet_number = 0;
+  data->block_size = grub_pxe_blksize;
+  grub_strcpy (data->filename, name);
+
+  file_int = grub_malloc (sizeof (*file_int));
+  if (! file_int)
+    {
+      grub_free (data);
+      return grub_errno;
+    }
+
+  file->data = data;
+  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;
+  grub_uint32_t pn, r;
+
+  data = file->data;
+
+  pn = grub_divmod64 (file->offset, data->block_size, &r);
+  if (r)
+    return grub_error (GRUB_ERR_BAD_FS,
+                       "read access must be aligned to packet size");
+
+  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);
+
+      o.server_ip = grub_pxe_server_ip;
+      o.gateway_ip = grub_pxe_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);
+      if (o.status)
+        return grub_error (GRUB_ERR_BAD_FS, "open fails");
+      data->packet_number = 0;
+      curr_file = file;
+    }
+
+  c.buffer = SEGOFS (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+  while (pn >= data->packet_number)
+    {
+      c.buffer_size = grub_pxe_blksize;
+      grub_pxe_call (GRUB_PXENV_TFTP_READ, &c);
+      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);
+      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 void
+grub_pxe_detect (void)
+{
+  struct grub_pxenv *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);
+  if (ci.status)
+    return;
+
+  bp = LINEAR (ci.buffer);
+
+  grub_pxe_your_ip = bp->your_ip;
+  grub_pxe_server_ip = bp->server_ip;
+  grub_pxe_gateway_ip = bp->gateway_ip;
+
+  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;
+    }
+}
+
+GRUB_MOD_INIT(pxe)
+{
+  (void) mod;                  /* To stop warning. */
+
+  grub_pxe_detect ();
+  if (grub_pxe_pxenv)
+    {
+      grub_disk_dev_register (&grub_pxe_dev);
+      grub_fs_register (&grub_pxefs_fs);
+    }
+}
+
+GRUB_MOD_FINI(pxe)
+{
+  grub_pxe_unload ();
+}
diff --git a/fs/iso9660.c b/fs/iso9660.c
new file mode 100644 (file)
index 0000000..6db2283
--- /dev/null
@@ -0,0 +1,907 @@
+/* iso9660.c - iso9660 implementation with extensions:
+   SUSP, Rock Ridge.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,2005,2006,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/>.
+ */
+
+#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>
+
+#define GRUB_ISO9660_FSTYPE_DIR                0040000
+#define GRUB_ISO9660_FSTYPE_REG                0100000
+#define GRUB_ISO9660_FSTYPE_SYMLINK    0120000
+#define GRUB_ISO9660_FSTYPE_MASK       0170000
+
+#define GRUB_ISO9660_LOG2_BLKSZ                2
+#define GRUB_ISO9660_BLKSZ             2048
+
+#define GRUB_ISO9660_RR_DOT            2
+#define GRUB_ISO9660_RR_DOTDOT         4
+
+#define GRUB_ISO9660_VOLDESC_BOOT      0
+#define GRUB_ISO9660_VOLDESC_PRIMARY   1
+#define GRUB_ISO9660_VOLDESC_SUPP      2
+#define GRUB_ISO9660_VOLDESC_PART      3
+#define GRUB_ISO9660_VOLDESC_END       255
+
+/* The head of a volume descriptor.  */
+struct grub_iso9660_voldesc
+{
+  grub_uint8_t type;
+  grub_uint8_t magic[5];
+  grub_uint8_t version;
+} __attribute__ ((packed));
+
+/* A directory entry.  */
+struct grub_iso9660_dir
+{
+  grub_uint8_t len;
+  grub_uint8_t ext_sectors;
+  grub_uint32_t first_sector;
+  grub_uint32_t first_sector_be;
+  grub_uint32_t size;
+  grub_uint32_t size_be;
+  grub_uint8_t unused1[7];
+  grub_uint8_t flags;
+  grub_uint8_t unused2[6];
+  grub_uint8_t namelen;
+} __attribute__ ((packed));
+
+struct grub_iso9660_date
+{
+  grub_uint8_t year[4];
+  grub_uint8_t month[2];
+  grub_uint8_t day[2];
+  grub_uint8_t hour[2];
+  grub_uint8_t minute[2];
+  grub_uint8_t second[2];
+  grub_uint8_t hundredth[2];
+  grub_uint8_t offset;
+} __attribute__ ((packed));
+
+/* The primary volume descriptor.  Only little endian is used.  */
+struct grub_iso9660_primary_voldesc
+{
+  struct grub_iso9660_voldesc voldesc;
+  grub_uint8_t unused1[33];
+  grub_uint8_t volname[32];
+  grub_uint8_t unused2[16];
+  grub_uint8_t escape[32];
+  grub_uint8_t unused3[12];
+  grub_uint32_t path_table_size;
+  grub_uint8_t unused4[4];
+  grub_uint32_t path_table;
+  grub_uint8_t unused5[12];
+  struct grub_iso9660_dir rootdir;
+  grub_uint8_t unused6[624];
+  struct grub_iso9660_date created;
+  struct grub_iso9660_date modified;
+} __attribute__ ((packed));
+
+/* A single entry in the path table.  */
+struct grub_iso9660_path
+{
+  grub_uint8_t len;
+  grub_uint8_t sectors;
+  grub_uint32_t first_sector;
+  grub_uint16_t parentdir;
+  grub_uint8_t name[0];
+} __attribute__ ((packed));
+
+/* An entry in the System Usage area of the directory entry.  */
+struct grub_iso9660_susp_entry
+{
+  grub_uint8_t sig[2];
+  grub_uint8_t len;
+  grub_uint8_t version;
+  grub_uint8_t data[0];
+} __attribute__ ((packed));
+
+/* The CE entry.  This is used to describe the next block where data
+   can be found.  */
+struct grub_iso9660_susp_ce
+{
+  struct grub_iso9660_susp_entry entry;
+  grub_uint32_t blk;
+  grub_uint32_t blk_be;
+  grub_uint32_t off;
+  grub_uint32_t off_be;
+  grub_uint32_t len;
+  grub_uint32_t len_be;
+} __attribute__ ((packed));
+
+struct grub_iso9660_data
+{
+  struct grub_iso9660_primary_voldesc voldesc;
+  grub_disk_t disk;
+  unsigned int first_sector;
+  unsigned int length;
+  int rockridge;
+  int susp_skip;
+  int joliet;
+};
+
+struct grub_fshelp_node
+{
+  struct grub_iso9660_data *data;
+  unsigned int size;
+  unsigned int blk;
+  unsigned int dir_blk;
+  unsigned int dir_off;
+};
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+\f
+
+/* Iterate over the susp entries, starting with block SUA_BLOCK on the
+   offset SUA_POS with a size of SUA_SIZE bytes.  Hook is called for
+   every entry.  */
+static grub_err_t
+grub_iso9660_susp_iterate (struct grub_iso9660_data *data,
+                          int sua_block, int sua_pos, int sua_size,
+                          grub_err_t (*hook)
+                          (struct grub_iso9660_susp_entry *entry))
+{
+  char *sua;
+  struct grub_iso9660_susp_entry *entry;
+  
+  auto grub_err_t load_sua (void);
+  
+  /* Load a part of the System Usage Area.  */
+  grub_err_t load_sua (void)
+    {
+      sua = grub_malloc (sua_size);
+      if (!sua)
+       return grub_errno;
+      
+      if (grub_disk_read (data->disk, sua_block, sua_pos,
+                         sua_size, sua))
+       return grub_errno;
+      
+      entry = (struct grub_iso9660_susp_entry *) sua;
+      return 0;
+    }
+  
+  if (load_sua ())
+    return grub_errno;
+  
+  for (; (char *) entry < (char *) sua + sua_size - 1;
+       entry = (struct grub_iso9660_susp_entry *)
+        ((char *) entry + entry->len))
+    {
+      /* The last entry.  */
+      if (grub_strncmp ((char *) entry->sig, "ST", 2) == 0)
+       break;
+      
+      /* Additional entries are stored elsewhere.  */
+      if (grub_strncmp ((char *) entry->sig, "CE", 2) == 0)
+       {
+         struct grub_iso9660_susp_ce *ce;
+         
+         ce = (struct grub_iso9660_susp_ce *) entry;
+         sua_size = grub_le_to_cpu32 (ce->len);
+         sua_pos = grub_le_to_cpu32 (ce->off);
+         sua_block = grub_le_to_cpu32 (ce->blk) << GRUB_ISO9660_LOG2_BLKSZ;
+         
+         grub_free (sua);
+         if (load_sua ())
+           return grub_errno;
+       }
+      
+      if (hook (entry))
+       {
+         grub_free (sua);
+         return 0;
+       }
+    }
+  
+  grub_free (sua);
+  return 0;
+}
+
+static char *
+grub_iso9660_convert_string (grub_uint16_t *us, int len)
+{
+  char *p;
+  int i;
+
+  p = grub_malloc (len * 4 + 1);
+  if (! p)
+    return p;
+
+  for (i=0; i<len; i++)
+    us[i] = grub_be_to_cpu16 (us[i]);
+
+  *grub_utf16_to_utf8 ((grub_uint8_t *) p, us, len) = '\0';
+
+  return p;
+}
+
+static struct grub_iso9660_data *
+grub_iso9660_mount (grub_disk_t disk)
+{
+  struct grub_iso9660_data *data = 0;
+  struct grub_iso9660_dir rootdir;
+  int sua_pos;
+  int sua_size;
+  char *sua;
+  struct grub_iso9660_susp_entry *entry;
+  struct grub_iso9660_primary_voldesc voldesc;
+  int block;
+  
+  auto grub_err_t susp_iterate (struct grub_iso9660_susp_entry *);
+  
+  grub_err_t susp_iterate (struct grub_iso9660_susp_entry *susp_entry)
+    {
+      /* The "ER" entry is used to detect extensions.  The
+        `IEEE_P1285' extension means Rock ridge.  */
+      if (grub_strncmp ((char *) susp_entry->sig, "ER", 2) == 0)
+       {
+         data->rockridge = 1;
+         return 1;
+       }
+      return 0;
+    }
+  
+  data = grub_malloc (sizeof (struct grub_iso9660_data));
+  if (! data)
+    return 0;
+  
+  data->disk = disk;
+  data->rockridge = 0;
+  data->joliet = 0;
+
+  block = 16;
+  do
+    {
+      int copy_voldesc = 0;
+
+      /* Read the superblock.  */
+      if (grub_disk_read (disk, block << GRUB_ISO9660_LOG2_BLKSZ, 0,
+                         sizeof (struct grub_iso9660_primary_voldesc),
+                         (char *) &voldesc))
+        {
+          grub_error (GRUB_ERR_BAD_FS, "not a iso9660 filesystem");
+          goto fail;
+        }
+
+      if (grub_strncmp ((char *) voldesc.voldesc.magic, "CD001", 5) != 0)
+        {
+          grub_error (GRUB_ERR_BAD_FS, "not a iso9660 filesystem");
+          goto fail;
+        }
+
+      if (voldesc.voldesc.type == GRUB_ISO9660_VOLDESC_PRIMARY)
+        copy_voldesc = 1;
+      else if ((voldesc.voldesc.type == GRUB_ISO9660_VOLDESC_SUPP) &&
+               (voldesc.escape[0] == 0x25) && (voldesc.escape[1] == 0x2f) &&
+               ((voldesc.escape[2] == 0x40) || /* UCS-2 Level 1.  */
+                (voldesc.escape[2] == 0x43) ||  /* UCS-2 Level 2.  */
+                (voldesc.escape[2] == 0x45)))  /* UCS-2 Level 3.  */
+        {
+          copy_voldesc = 1;
+          data->joliet = 1;
+        }
+
+      if (copy_voldesc)
+        grub_memcpy((char *) &data->voldesc, (char *) &voldesc,
+                    sizeof (struct grub_iso9660_primary_voldesc));
+
+      block++;
+    } while (voldesc.voldesc.type != GRUB_ISO9660_VOLDESC_END);
+
+  /* Read the system use area and test it to see if SUSP is
+     supported.  */
+  if (grub_disk_read (disk, (grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
+                            << GRUB_ISO9660_LOG2_BLKSZ), 0,
+                     sizeof (rootdir), (char *) &rootdir))
+    {
+      grub_error (GRUB_ERR_BAD_FS, "not a iso9660 filesystem");
+      goto fail;
+    }
+  
+  sua_pos = (sizeof (rootdir) + rootdir.namelen
+            + (rootdir.namelen % 2) - 1);
+  sua_size = rootdir.len - sua_pos;
+
+  sua = grub_malloc (sua_size);
+  if (! sua)
+    goto fail;
+  
+  if (grub_disk_read (disk, (grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
+                            << GRUB_ISO9660_LOG2_BLKSZ), sua_pos,
+                     sua_size, sua))
+    {
+      grub_error (GRUB_ERR_BAD_FS, "not a iso9660 filesystem");
+      goto fail;
+    }
+  
+  entry = (struct grub_iso9660_susp_entry *) sua;
+  
+  /* Test if the SUSP protocol is used on this filesystem.  */
+  if (grub_strncmp ((char *) entry->sig, "SP", 2) == 0)
+    {
+      /* The 2nd data byte stored how many bytes are skipped every time
+        to get to the SUA (System Usage Area).  */
+      data->susp_skip = entry->data[2];
+      entry = (struct grub_iso9660_susp_entry *) ((char *) entry + entry->len);
+      
+      /* Iterate over the entries in the SUA area to detect
+        extensions.  */
+      if (grub_iso9660_susp_iterate (data,
+                                    (grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
+                                     << GRUB_ISO9660_LOG2_BLKSZ),
+                                    sua_pos, sua_size, susp_iterate))
+       goto fail;
+    }
+  
+  return data;
+    
+ fail:
+  grub_free (data);
+  return 0;
+}
+
+
+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;
+  int addslash = 0;
+  
+  auto void add_part (const char *part, int len);
+  auto grub_err_t susp_iterate_sl (struct grub_iso9660_susp_entry *);
+
+  /* Extend the symlink.  */
+  void add_part (const char *part, int len)
+    {
+      int size = grub_strlen (symlink);
+      
+      symlink = grub_realloc (symlink, size + len + 1);
+      if (! symlink)
+       return;
+      
+      grub_strncat (symlink, part, len);
+    }
+    
+  /* Read in a symlink.  */
+  grub_err_t susp_iterate_sl (struct grub_iso9660_susp_entry *entry)
+    {
+      if (grub_strncmp ("SL", (char *) entry->sig, 2) == 0)
+       {
+         unsigned int pos = 1;
+
+         /* The symlink is not stored as a POSIX symlink, translate it.  */
+         while (pos < grub_le_to_cpu32 (entry->len))
+           {
+             if (addslash)
+               {
+                 add_part ("/", 1);
+                 addslash = 0;
+               }
+             
+             /* The current position is the `Component Flag'.  */
+             switch (entry->data[pos] & 30)
+               {
+               case 0:
+                 {
+                   /* The data on pos + 2 is the actual data, pos + 1
+                      is the length.  Both are part of the `Component
+                      Record'.  */
+                   add_part ((char *) &entry->data[pos + 2],
+                             entry->data[pos + 1]);
+                   if ((entry->data[pos] & 1))
+                     addslash = 1;
+
+                   break;
+                 }
+               
+               case 2:
+                 add_part ("./", 2);
+                 break;
+               
+               case 4:
+                 add_part ("../", 3);
+                 break;
+                 
+               case 8:
+                 add_part ("/", 1);
+                 break;
+               }
+             /* In pos + 1 the length of the `Component Record' is
+                stored.  */
+             pos += entry->data[pos + 1] + 2;
+           }
+         
+         /* Check if `grub_realloc' failed.  */
+         if (grub_errno)
+           return grub_errno;
+       }
+      
+      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)
+            + node->data->susp_skip);
+  sua_size = dirent.len - sua_off;
+  
+  symlink = grub_malloc (1);
+  if (!symlink)
+    return 0;
+  
+  *symlink = '\0';
+  
+  if (grub_iso9660_susp_iterate (node->data, node->dir_blk,
+                                node->dir_off + sua_off,
+                                sua_size, susp_iterate_sl))
+    {
+      grub_free (symlink);
+      return 0;
+    }
+  
+  return symlink;
+}
+
+
+static int
+grub_iso9660_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))
+{
+  struct grub_iso9660_dir dirent;
+  unsigned int offset = 0;
+  char *filename;
+  int filename_alloc = 0;
+  enum grub_fshelp_filetype type;
+  
+  auto grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *);
+
+  grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *entry)
+    {
+      /* The filename in the rock ridge entry.  */
+      if (grub_strncmp ("NM", (char *) entry->sig, 2) == 0)
+       {
+         /* The flags are stored at the data position 0, here the
+            filename type is stored.  */
+         if (entry->data[0] & GRUB_ISO9660_RR_DOT)
+           filename = ".";
+         else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT)
+           filename = "..";
+         else
+           {
+             int size = 1;
+             if (filename)
+               {
+                 size += grub_strlen (filename);
+                 grub_realloc (filename,
+                               grub_strlen (filename)
+                               + entry->len);
+               }
+             else
+               {
+                 size = entry->len - 5;
+                 filename = grub_malloc (size + 1);
+                 filename[0] = '\0';
+               }
+             filename_alloc = 1;
+             grub_strncpy (filename, (char *) &entry->data[1], size);
+             filename[size] = '\0';
+           }
+       }
+      /* The mode information (st_mode).  */
+      else if (grub_strncmp ((char *) entry->sig, "PX", 2) == 0)
+       {
+         /* At position 0 of the PX record the st_mode information is
+            stored.  */
+         grub_uint32_t mode = ((*(grub_uint32_t *) &entry->data[0])
+                               & GRUB_ISO9660_FSTYPE_MASK);
+
+         switch (mode)
+           {
+           case GRUB_ISO9660_FSTYPE_DIR:
+             type = GRUB_FSHELP_DIR;
+             break;
+           case GRUB_ISO9660_FSTYPE_REG:
+             type = GRUB_FSHELP_REG;
+             break;
+           case GRUB_ISO9660_FSTYPE_SYMLINK:
+             type = GRUB_FSHELP_SYMLINK;
+             break;
+           default:
+             type = GRUB_FSHELP_UNKNOWN;
+           }
+       }
+      
+      return 0;
+    }
+
+  while (offset < dir->size)
+    {
+      if (grub_disk_read (dir->data->disk,
+                         (dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
+                         + offset / GRUB_DISK_SECTOR_SIZE,
+                         offset % GRUB_DISK_SECTOR_SIZE,
+                         sizeof (dirent), (char *) &dirent))
+       return 0;
+      
+      /* The end of the block, skip to the next one.  */
+      if (!dirent.len)
+       {
+         offset = (offset / GRUB_ISO9660_BLKSZ + 1) * GRUB_ISO9660_BLKSZ;
+         continue;
+       }
+      
+      {
+       char name[dirent.namelen + 1];
+       int nameoffset = offset + sizeof (dirent);
+       struct grub_fshelp_node *node;
+       int sua_off = (sizeof (dirent) + dirent.namelen + 1
+                      - (dirent.namelen % 2));;
+       int sua_size = dirent.len - sua_off;
+       
+       sua_off += offset + dir->data->susp_skip;
+       
+       filename = 0;
+       filename_alloc = 0;
+       type = GRUB_FSHELP_UNKNOWN;
+
+       if (dir->data->rockridge
+           && grub_iso9660_susp_iterate (dir->data,
+                                         (dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
+                                         + (sua_off
+                                            / GRUB_DISK_SECTOR_SIZE),
+                                         sua_off % GRUB_DISK_SECTOR_SIZE,
+                                         sua_size, susp_iterate_dir))
+         return 0;
+       
+       /* Read the name.  */
+       if (grub_disk_read (dir->data->disk,
+                           (dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
+                           + nameoffset / GRUB_DISK_SECTOR_SIZE,
+                           nameoffset % GRUB_DISK_SECTOR_SIZE,
+                           dirent.namelen, (char *) name))
+         return 0;
+       
+       node = grub_malloc (sizeof (struct grub_fshelp_node));
+       if (!node)
+         return 0;
+       
+       /* Setup a new node.  */
+       node->data = dir->data;
+       node->size = grub_le_to_cpu32 (dirent.size);
+       node->blk = grub_le_to_cpu32 (dirent.first_sector);
+       node->dir_blk = ((dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
+                        + offset / GRUB_DISK_SECTOR_SIZE);
+       node->dir_off = offset % GRUB_DISK_SECTOR_SIZE;
+       
+       /* If the filetype was not stored using rockridge, use
+          whatever is stored in the iso9660 filesystem.  */
+       if (type == GRUB_FSHELP_UNKNOWN)
+         {
+           if ((dirent.flags & 3) == 2)
+             type = GRUB_FSHELP_DIR;
+           else
+             type = GRUB_FSHELP_REG;
+         }
+       
+       /* The filename was not stored in a rock ridge entry.  Read it
+          from the iso9660 filesystem.  */
+       if (!filename)
+         {
+           name[dirent.namelen] = '\0';
+           filename = grub_strrchr (name, ';');
+           if (filename)
+             *filename = '\0';
+           
+           if (dirent.namelen == 1 && name[0] == 0)
+             filename = ".";
+           else if (dirent.namelen == 1 && name[0] == 1)
+             filename = "..";
+           else
+             filename = name;
+         }
+       
+        if (dir->data->joliet)
+          {
+            char *oldname;
+
+            oldname = filename;
+            filename = grub_iso9660_convert_string
+                  ((grub_uint16_t *) oldname, dirent.namelen >> 1);
+
+            if (filename_alloc)
+              grub_free (oldname);
+
+            filename_alloc = 1;
+          }
+
+       if (hook (filename, type, node))
+         {
+           if (filename_alloc)
+             grub_free (filename);
+           return 1;
+         }
+       if (filename_alloc)
+         grub_free (filename);
+      }
+      
+      offset += dirent.len;
+    }
+  
+  return 0;
+}
+
+
+\f
+static grub_err_t
+grub_iso9660_dir (grub_device_t device, const char *path, 
+                 int (*hook) (const char *filename, int dir))
+{
+  struct grub_iso9660_data *data = 0;
+  struct grub_fshelp_node rootnode;
+  struct grub_fshelp_node *foundnode;
+  
+  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)
+    {
+      grub_free (node);
+      
+      if (filetype == GRUB_FSHELP_DIR)
+       return hook (filename, 1);
+      else 
+       return hook (filename, 0);
+      
+      return 0;
+    }
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_iso9660_mount (device->disk);
+  if (! data)
+    goto fail;
+  
+  rootnode.data = data;
+  rootnode.blk = grub_le_to_cpu32 (data->voldesc.rootdir.first_sector);
+  rootnode.size = grub_le_to_cpu32 (data->voldesc.rootdir.size);
+  
+  /* Use the fshelp function to traverse the path.  */
+  if (grub_fshelp_find_file (path, &rootnode,
+                            &foundnode,
+                            grub_iso9660_iterate_dir,
+                            grub_iso9660_read_symlink,
+                            GRUB_FSHELP_DIR))
+    goto fail;
+  
+  /* List the files in the directory.  */
+  grub_iso9660_iterate_dir (foundnode, iterate);
+  
+  if (foundnode != &rootnode)
+    grub_free (foundnode);
+  
+ fail:
+  grub_free (data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+
+/* Open a file named NAME and initialize FILE.  */
+static grub_err_t
+grub_iso9660_open (struct grub_file *file, const char *name)
+{
+  struct grub_iso9660_data *data;
+  struct grub_fshelp_node rootnode;
+  struct grub_fshelp_node *foundnode;
+  
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_iso9660_mount (file->device->disk);
+  if (!data)
+    goto fail;
+  
+  rootnode.data = data;
+  rootnode.blk = grub_le_to_cpu32 (data->voldesc.rootdir.first_sector);
+  rootnode.size = grub_le_to_cpu32 (data->voldesc.rootdir.size);
+  
+  /* Use the fshelp function to traverse the path.  */
+  if (grub_fshelp_find_file (name, &rootnode,
+                            &foundnode,
+                            grub_iso9660_iterate_dir,
+                            grub_iso9660_read_symlink,
+                            GRUB_FSHELP_REG))
+    goto fail;
+  
+  data->first_sector = foundnode->blk;
+  data->length = foundnode->size;
+  
+  file->data = data;
+  file->size = foundnode->size;
+  file->offset = 0;
+  
+  return 0;
+  
+ fail:
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+  
+  grub_free (data);
+  
+  return grub_errno;;
+}
+
+
+static grub_ssize_t
+grub_iso9660_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_iso9660_data *data = 
+    (struct grub_iso9660_data *) file->data;
+  
+  /* XXX: The file is stored in as a single extent.  */
+  data->disk->read_hook = file->read_hook;       
+  grub_disk_read (data->disk,
+                 data->first_sector << GRUB_ISO9660_LOG2_BLKSZ,
+                 file->offset,
+                 len, buf);
+  data->disk->read_hook = 0;
+  
+  return len;
+}
+
+
+static grub_err_t
+grub_iso9660_close (grub_file_t file)
+{
+  grub_free (file->data);
+  
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+  
+  return GRUB_ERR_NONE;
+}
+
+
+static grub_err_t
+grub_iso9660_label (grub_device_t device, char **label)
+{
+  struct grub_iso9660_data *data;
+  data = grub_iso9660_mount (device->disk);
+  
+  if (data)
+    {
+      if (data->joliet)
+        *label = grub_iso9660_convert_string
+                 ((grub_uint16_t *) &data->voldesc.volname, 16);
+      else
+        *label = grub_strndup ((char *) data->voldesc.volname, 32);
+      grub_free (data);
+    }
+  else
+    *label = 0;
+
+  return grub_errno;
+}
+
+
+static grub_err_t
+grub_iso9660_uuid (grub_device_t device, char **uuid)
+{
+  struct grub_iso9660_data *data;
+  grub_disk_t disk = device->disk;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_iso9660_mount (disk);
+  if (data)
+    {
+      if (! data->voldesc.modified.year[0] && ! data->voldesc.modified.year[1]
+         && ! data->voldesc.modified.year[2] && ! data->voldesc.modified.year[3]
+         && ! data->voldesc.modified.month[0] && ! data->voldesc.modified.month[1]
+         && ! data->voldesc.modified.day[0] && ! data->voldesc.modified.day[1]
+         && ! data->voldesc.modified.hour[0] && ! data->voldesc.modified.hour[1]
+         && ! data->voldesc.modified.minute[0] && ! data->voldesc.modified.minute[1]
+         && ! data->voldesc.modified.second[0] && ! data->voldesc.modified.second[1]
+         && ! data->voldesc.modified.hundredth[0] && ! data->voldesc.modified.hundredth[1])
+       {
+         grub_error (GRUB_ERR_BAD_NUMBER, "No creation date in filesystem to generate UUID.");
+         *uuid = NULL;
+       }
+      else 
+       {
+         *uuid = grub_malloc (sizeof ("YYYY-MM-DD-HH-mm-ss-hh"));
+         grub_sprintf (*uuid, "%c%c%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c",
+                       data->voldesc.modified.year[0], data->voldesc.modified.year[1], 
+                       data->voldesc.modified.year[2], data->voldesc.modified.year[3],
+                       data->voldesc.modified.month[0], data->voldesc.modified.month[1],
+                       data->voldesc.modified.day[0], data->voldesc.modified.day[1],
+                       data->voldesc.modified.hour[0], data->voldesc.modified.hour[1],
+                       data->voldesc.modified.minute[0], data->voldesc.modified.minute[1],
+                       data->voldesc.modified.second[0], data->voldesc.modified.second[1],
+                       data->voldesc.modified.hundredth[0], data->voldesc.modified.hundredth[1]);
+       }
+    }
+  else
+    *uuid = NULL;
+
+#ifndef GRUB_UTIL
+       grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+}
+
+\f
+
+static struct grub_fs grub_iso9660_fs =
+  {
+    .name = "iso9660",
+    .dir = grub_iso9660_dir,
+    .open = grub_iso9660_open,
+    .read = grub_iso9660_read,
+    .close = grub_iso9660_close,
+    .label = grub_iso9660_label,
+    .uuid = grub_iso9660_uuid,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(iso9660)
+{
+  grub_fs_register (&grub_iso9660_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(iso9660)
+{
+  grub_fs_unregister (&grub_iso9660_fs);
+}
diff --git a/fs/jfs.c b/fs/jfs.c
new file mode 100644 (file)
index 0000000..fc9dab8
--- /dev/null
+++ b/fs/jfs.c
@@ -0,0 +1,885 @@
+/* jfs.c - JFS.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,2005,2006,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/>.
+ */
+
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/types.h>
+
+#define GRUB_JFS_MAX_SYMLNK_CNT        8
+#define GRUB_JFS_FILETYPE_MASK 0170000
+#define GRUB_JFS_FILETYPE_REG  0100000
+#define GRUB_JFS_FILETYPE_LNK  0120000
+#define GRUB_JFS_FILETYPE_DIR  0040000
+
+#define GRUB_JFS_SBLOCK                64
+#define GRUB_JFS_AGGR_INODE    2
+#define GRUB_JFS_FS1_INODE_BLK 104
+
+#define GRUB_JFS_TREE_LEAF     2
+
+struct grub_jfs_sblock
+{
+  /* The magic for JFS.  It should contain the string "JFS1".  */
+  grub_uint8_t magic[4];
+  grub_uint32_t version;
+  grub_uint64_t ag_size;
+  
+  /* The size of a filesystem block in bytes.  XXX: currently only
+     4096 was tested.  */
+  grub_uint32_t blksz;
+  grub_uint16_t log2_blksz;
+  
+  grub_uint8_t unused[71];
+  grub_uint8_t volname[11];  
+};
+
+struct grub_jfs_extent
+{
+  /* The length of the extent in filesystem blocks.  */
+  grub_uint16_t length;
+  grub_uint8_t length2;
+  
+  /* The physical offset of the first block on the disk.  */
+  grub_uint8_t blk1;
+  grub_uint32_t blk2;
+} __attribute__ ((packed));
+
+struct grub_jfs_iag
+{
+  grub_uint8_t unused[3072];
+  struct grub_jfs_extent inodes[128];
+} __attribute__ ((packed));
+
+
+/* The head of the tree used to find extents.  */
+struct grub_jfs_treehead
+{
+  grub_uint64_t next;
+  grub_uint64_t prev;
+  
+  grub_uint8_t flags; 
+  grub_uint8_t unused;
+  
+  grub_uint16_t count;
+  grub_uint16_t max;
+  grub_uint8_t unused2[10];
+} __attribute__ ((packed));
+
+/* A node in the extent tree.  */
+struct grub_jfs_tree_extent
+{
+  grub_uint8_t flags;
+  grub_uint16_t unused;
+
+  /* The offset is the key used to lookup an extent.  */
+  grub_uint8_t offset1;
+  grub_uint32_t offset2;
+  
+  struct grub_jfs_extent extent;
+} __attribute__ ((packed));
+
+/* The tree of directory entries.  */
+struct grub_jfs_tree_dir
+{
+  /* Pointers to the previous and next tree headers of other nodes on
+     this level.  */
+  grub_uint64_t nextb;
+  grub_uint64_t prevb;
+  
+  grub_uint8_t flags;
+  
+  /* The amount of dirents in this node.  */
+  grub_uint8_t count;
+  grub_uint8_t freecnt;
+  grub_uint8_t freelist;
+  grub_uint8_t maxslot;
+  
+  /* The location of the sorted array of pointers to dirents.  */
+  grub_uint8_t sindex;
+  grub_uint8_t unused[10];
+} __attribute__ ((packed));
+
+/* An internal node in the dirents tree.  */
+struct grub_jfs_internal_dirent
+{
+  struct grub_jfs_extent ex;
+  grub_uint8_t next;
+  grub_uint8_t len;
+  grub_uint16_t namepart[11];
+} __attribute__ ((packed));
+
+/* A leaf node in the dirents tree.  */
+struct grub_jfs_leaf_dirent
+{
+  /* The inode for this dirent.  */
+  grub_uint32_t inode;
+  grub_uint8_t next;
+
+  /* The size of the name.  */
+  grub_uint8_t len;
+  grub_uint16_t namepart[11];
+  grub_uint32_t index;
+} __attribute__ ((packed));
+
+/* A leaf in the dirents tree.  This one is used if the previously
+   dirent was not big enough to store the name.  */
+struct grub_jfs_leaf_next_dirent
+{
+  grub_uint8_t next;
+  grub_uint8_t len;
+  grub_uint16_t namepart[15];
+} __attribute__ ((packed));
+
+struct grub_jfs_inode
+{
+  grub_uint32_t stamp;
+  grub_uint32_t fileset;
+  grub_uint32_t inode;
+  grub_uint8_t unused[12];
+  grub_uint64_t size;
+  grub_uint8_t unused2[20];
+  grub_uint32_t mode;
+  grub_uint8_t unused3[72];
+  grub_uint8_t unused4[96];
+  
+  union
+  {
+    /* The tree describing the extents of the file.  */
+    struct __attribute__ ((packed))
+    {
+      struct grub_jfs_treehead tree;
+      struct grub_jfs_tree_extent extents[16];
+    } file;
+    union
+    {
+      /* The tree describing the dirents.  */
+      struct
+      {
+       grub_uint8_t unused[16];
+       grub_uint8_t flags;
+       
+       /* Amount of dirents in this node.  */
+       grub_uint8_t count;
+       grub_uint8_t freecnt;
+       grub_uint8_t freelist;
+       grub_uint32_t idotdot;
+       grub_uint8_t sorted[8];
+      } header;
+      struct grub_jfs_leaf_dirent dirents[8];
+    } dir __attribute__ ((packed));
+    /* Fast symlink.  */
+    struct
+    {
+      grub_uint8_t unused[32];
+      grub_uint8_t path[128];
+    } symlink;
+  } __attribute__ ((packed));
+} __attribute__ ((packed));
+
+struct grub_jfs_data
+{
+  struct grub_jfs_sblock sblock;
+  grub_disk_t disk;
+  struct grub_jfs_inode fileset;
+  struct grub_jfs_inode currinode;
+  int pos;
+  int linknest;
+} __attribute__ ((packed));
+
+struct grub_jfs_diropen
+{
+  int index;
+  union
+  {
+    struct grub_jfs_tree_dir header;
+    struct grub_jfs_leaf_dirent dirent[0];
+    struct grub_jfs_leaf_next_dirent next_dirent[0];
+    char sorted[0];
+  } *dirpage __attribute__ ((packed));
+  struct grub_jfs_data *data;
+  struct grub_jfs_inode *inode;
+  int count;
+  char *sorted;
+  struct grub_jfs_leaf_dirent *leaf;
+  struct grub_jfs_leaf_next_dirent *next_leaf;
+  
+  /* The filename and inode of the last read dirent.  */
+  char name[255];
+  grub_uint32_t ino;
+} __attribute__ ((packed));
+
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+\f
+static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, int ino);
+
+/* Get the block number for the block BLK in the node INODE in the
+   mounted filesystem DATA.  */
+static int
+grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode,
+               unsigned int blk)
+{
+  auto int getblk (struct grub_jfs_treehead *treehead,
+                  struct grub_jfs_tree_extent *extents);
+  
+  int getblk (struct grub_jfs_treehead *treehead,
+             struct grub_jfs_tree_extent *extents)
+    {
+      int found = -1;
+      int i;
+      
+      for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2; i++)
+       {
+         if (treehead->flags & GRUB_JFS_TREE_LEAF)
+           {
+             /* Read the leafnode.  */
+             if (grub_le_to_cpu32 (extents[i].offset2) <= blk 
+                 && ((grub_le_to_cpu16 (extents[i].extent.length))
+                     + (extents[i].extent.length2 << 8)
+                     + grub_le_to_cpu32 (extents[i].offset2)) > blk)
+               return (blk - grub_le_to_cpu32 (extents[i].offset2)
+                       + grub_le_to_cpu32 (extents[i].extent.blk2));
+           }
+         else
+           if (blk >= grub_le_to_cpu32 (extents[i].offset2))
+             found = i;
+       }
+      
+      if (found != -1)
+       {
+         struct
+         {
+           struct grub_jfs_treehead treehead;
+           struct grub_jfs_tree_extent extents[254];
+         } tree;
+                 
+         if (grub_disk_read (data->disk,
+                             grub_le_to_cpu32 (extents[found].extent.blk2)
+                             << (grub_le_to_cpu16 (data->sblock.log2_blksz)
+                                 - GRUB_DISK_SECTOR_BITS), 0,
+                             sizeof (tree), (char *) &tree))
+           return -1;
+         
+         return getblk (&tree.treehead, &tree.extents[0]);
+       }
+      
+      return -1;
+    }
+  
+  return getblk (&inode->file.tree, &inode->file.extents[0]);
+}
+
+
+static grub_err_t
+grub_jfs_read_inode (struct grub_jfs_data *data, int ino,
+                    struct grub_jfs_inode *inode)
+{
+  struct grub_jfs_iag iag;
+  int iagnum = ino / 4096;
+  int inoext = (ino % 4096) / 32;
+  int inonum = (ino % 4096) % 32;
+  grub_uint32_t iagblk;
+  grub_uint32_t inoblk;
+
+  iagblk = grub_jfs_blkno (data, &data->fileset, iagnum + 1);
+  if (grub_errno)
+    return grub_errno;
+
+  /* Read in the IAG.  */
+  if (grub_disk_read (data->disk,
+                     iagblk << (grub_le_to_cpu16 (data->sblock.log2_blksz)
+                                - GRUB_DISK_SECTOR_BITS), 0,
+                     sizeof (struct grub_jfs_iag), (char *) &iag))
+    return grub_errno;
+  
+  inoblk = grub_le_to_cpu32 (iag.inodes[inoext].blk2);
+  inoblk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz)
+             - GRUB_DISK_SECTOR_BITS);
+  inoblk += inonum;
+  
+  if (grub_disk_read (data->disk, inoblk, 0,
+                     sizeof (struct grub_jfs_inode), (char *) inode))
+    return grub_errno;
+
+  return 0;
+}
+
+
+static struct grub_jfs_data *
+grub_jfs_mount (grub_disk_t disk)
+{
+  struct grub_jfs_data *data = 0;
+
+  data = grub_malloc (sizeof (struct grub_jfs_data));
+  if (!data)
+    return 0;
+
+  /* Read the superblock.  */
+  if (grub_disk_read (disk, GRUB_JFS_SBLOCK, 0,
+                     sizeof (struct grub_jfs_sblock), (char *) &data->sblock))
+    goto fail;
+  
+  if (grub_strncmp ((char *) (data->sblock.magic), "JFS1", 4))
+    {
+      grub_error (GRUB_ERR_BAD_FS, "not a jfs filesystem");
+      goto fail;
+    }
+  
+  data->disk = disk;
+  data->pos = 0;
+  data->linknest = 0;
+
+  /* Read the inode of the first fileset.  */
+  if (grub_disk_read (data->disk, GRUB_JFS_FS1_INODE_BLK, 0,
+                     sizeof (struct grub_jfs_inode), (char *) &data->fileset))
+    goto fail;
+  
+  return data;
+  
+ fail:
+  grub_free (data);
+  
+  if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+    grub_error (GRUB_ERR_BAD_FS, "not a jfs filesystem");
+  
+  return 0;
+}
+
+
+static struct grub_jfs_diropen *
+grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
+{
+  struct grub_jfs_internal_dirent *de;
+  struct grub_jfs_diropen *diro;
+  int blk;
+  
+  de = (struct grub_jfs_internal_dirent *) inode->dir.dirents;
+  
+  if (!((grub_le_to_cpu32 (inode->mode)
+        & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR))
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+      return 0;
+    }
+  
+  diro = grub_malloc (sizeof (struct grub_jfs_diropen));
+  if (!diro)
+    return 0;
+  
+  diro->index = 0;
+  diro->data = data;
+  diro->inode = inode;
+
+  /* Check if the entire tree is contained within the inode.  */
+  if (inode->file.tree.flags & GRUB_JFS_TREE_LEAF)
+    {
+      diro->leaf = inode->dir.dirents;
+      diro->next_leaf = (struct grub_jfs_leaf_next_dirent *) de;
+      diro->sorted = (char *) (inode->dir.header.sorted);
+      diro->count = inode->dir.header.count;
+      diro->dirpage = 0;
+
+      return diro;
+    }
+
+  diro->dirpage = grub_malloc (grub_le_to_cpu32 (data->sblock.blksz));
+  if (!diro->dirpage)
+    {
+      grub_free (diro);
+      return 0;
+    }
+  
+  blk = grub_le_to_cpu32 (de[inode->dir.header.sorted[0]].ex.blk2);
+  blk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS);
+  
+  /* Read in the nodes until we are on the leaf node level.  */
+  do
+    {
+      int index;
+      if (grub_disk_read (data->disk, blk, 0,
+                         grub_le_to_cpu32 (data->sblock.blksz),
+                         diro->dirpage->sorted))
+       {
+         grub_free (diro->dirpage);
+         grub_free (diro);
+         return 0;
+       }
+
+      de = (struct grub_jfs_internal_dirent *) diro->dirpage->dirent;
+      index = diro->dirpage->sorted[diro->dirpage->header.sindex * 32];
+      blk = (grub_le_to_cpu32 (de[index].ex.blk2)
+            << (grub_le_to_cpu16 (data->sblock.log2_blksz)
+                - GRUB_DISK_SECTOR_BITS));
+    } while (!(diro->dirpage->header.flags & GRUB_JFS_TREE_LEAF));
+
+  diro->leaf = diro->dirpage->dirent;
+  diro->next_leaf = diro->dirpage->next_dirent;
+  diro->sorted = &diro->dirpage->sorted[diro->dirpage->header.sindex * 32];
+  diro->count = diro->dirpage->header.count;
+  
+  return diro;
+}
+
+
+static void
+grub_jfs_closedir (struct grub_jfs_diropen *diro)
+{
+  if (!diro)
+    return;
+  grub_free (diro->dirpage);
+  grub_free (diro);
+}
+
+
+/* Read in the next dirent from the directory described by DIRO.  */
+static grub_err_t
+grub_jfs_getent (struct grub_jfs_diropen *diro)
+{
+  int strpos = 0;
+  struct grub_jfs_leaf_dirent *leaf;
+  struct grub_jfs_leaf_next_dirent *next_leaf;
+  int len;
+  int nextent;
+  grub_uint16_t filename[255];
+  
+  auto void addstr (grub_uint16_t *uname, int ulen);
+  
+  /* Add the unicode string to the utf16 filename buffer.  */
+  void addstr (grub_uint16_t *name, int ulen)
+    {
+      while (ulen--)
+       filename[strpos++] = *(name++);
+    }
+  
+  /* The last node, read in more.  */
+  if (diro->index == diro->count)
+    {
+      unsigned int next;
+      
+      /* If the inode contains the entry tree or if this was the last
+        node, there is nothing to read.  */
+      if ((diro->inode->file.tree.flags & GRUB_JFS_TREE_LEAF)
+         || !grub_le_to_cpu64 (diro->dirpage->header.nextb))
+       return GRUB_ERR_OUT_OF_RANGE;
+      
+      next = grub_le_to_cpu64 (diro->dirpage->header.nextb);
+      next <<= (grub_le_to_cpu16 (diro->data->sblock.log2_blksz)
+               - GRUB_DISK_SECTOR_BITS);
+      
+      if (grub_disk_read (diro->data->disk, next, 0,
+                         grub_le_to_cpu32 (diro->data->sblock.blksz),
+                         diro->dirpage->sorted))
+       return grub_errno;
+
+      diro->leaf = diro->dirpage->dirent;
+      diro->next_leaf = diro->dirpage->next_dirent;
+      diro->sorted = &diro->dirpage->sorted[diro->dirpage->header.sindex * 32];
+      diro->count = diro->dirpage->header.count;
+      diro->index = 0;
+    }
+
+  leaf = &diro->leaf[(int) diro->sorted[diro->index]];
+  next_leaf = &diro->next_leaf[diro->index];
+  
+  len = leaf->len;
+  if (!len)
+    {
+      diro->index++;
+      return grub_jfs_getent (diro);
+    }
+  
+  addstr (leaf->namepart, len < 11 ? len : 11);
+  diro->ino = grub_le_to_cpu32 (leaf->inode);
+  len -= 11;
+  
+  /* Move down to the leaf level.  */
+  nextent = leaf->next;
+  if (leaf->next != 255)
+    do
+      {
+       next_leaf = &diro->next_leaf[nextent];
+       addstr (next_leaf->namepart, len < 15 ? len : 15 );
+       
+       len -= 15;
+       nextent = next_leaf->next;
+      } while (next_leaf->next != 255 && len > 0);
+
+  diro->index++;
+
+  /* Convert the temporary UTF16 filename to UTF8.  */
+  *grub_utf16_to_utf8 ((grub_uint8_t *) (diro->name), filename, strpos) = '\0';
+  
+  return 0;
+}
+
+
+/* Read LEN bytes from the file described by DATA starting with byte
+   POS.  Return the amount of read bytes in READ.  */
+static grub_ssize_t
+grub_jfs_read_file (struct grub_jfs_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)
+{
+  int i;
+  int blockcnt;
+
+  /* Adjust len so it we can't read past the end of the file.  */
+  if (len > data->currinode.size)
+    len = data->currinode.size;
+
+  blockcnt = ((len + pos + grub_le_to_cpu32 (data->sblock.blksz) - 1)
+             / grub_le_to_cpu32 (data->sblock.blksz));
+  
+  for (i = pos / grub_le_to_cpu32 (data->sblock.blksz); i < blockcnt; i++)
+    {
+      int blknr;
+      int blockoff = pos % grub_le_to_cpu32 (data->sblock.blksz);
+      int blockend = grub_le_to_cpu32 (data->sblock.blksz);
+      
+      int skipfirst = 0;
+      
+      blknr = grub_jfs_blkno (data, &data->currinode, i);
+      if (grub_errno)
+       return -1;
+
+      /* Last block.  */
+      if (i == blockcnt - 1)
+       {
+         blockend = (len + pos) % grub_le_to_cpu32 (data->sblock.blksz);
+         
+         if (!blockend)
+           blockend = grub_le_to_cpu32 (data->sblock.blksz);
+       }
+      
+      /* First block.  */
+      if (i == (pos / (int) grub_le_to_cpu32 (data->sblock.blksz)))
+       {
+         skipfirst = blockoff;
+         blockend -= skipfirst;
+       }
+      
+      data->disk->read_hook = read_hook;
+      grub_disk_read (data->disk,
+                     blknr << (grub_le_to_cpu16 (data->sblock.log2_blksz)
+                               - GRUB_DISK_SECTOR_BITS),
+                     skipfirst, blockend, buf);
+      
+      data->disk->read_hook = 0;
+      if (grub_errno)
+       return -1;
+      
+      buf += grub_le_to_cpu32 (data->sblock.blksz) - skipfirst;
+    }
+  
+  return len;
+}
+
+
+/* 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)
+{
+  char fpath[grub_strlen (path)];
+  char *name = fpath;
+  char *next;
+  unsigned int pos = 0;
+  struct grub_jfs_diropen *diro;
+  
+  grub_strncpy (fpath, path, grub_strlen (path) + 1);
+  
+  if (grub_jfs_read_inode (data, GRUB_JFS_AGGR_INODE, &data->currinode))
+    return grub_errno;
+
+  /* Skip the first slashes.  */
+  while (*name == '/')
+    {
+      name++;
+      if (!*name)
+       return 0;
+    }
+
+  /* Extract the actual part from the pathname.  */
+  next = grub_strchr (name, '/');
+  if (next)
+    {
+      while (*next == '/')
+       {
+         next[0] = '\0';
+         next++;
+       }
+    }
+  diro = grub_jfs_opendir (data, &data->currinode);
+  if (!diro)
+    return grub_errno;
+    
+  for (;;)
+    {
+      if (grub_strlen (name) == 0)
+       return GRUB_ERR_NONE;
+      
+      if (grub_jfs_getent (diro) == GRUB_ERR_OUT_OF_RANGE)
+       break;
+      
+      /* Check if the current direntry matches the current part of the
+        pathname.  */
+      if (!grub_strcmp (name, diro->name))
+       {
+         int ino = diro->ino;
+         int dirino = grub_le_to_cpu32 (data->currinode.inode);
+         
+         grub_jfs_closedir (diro);
+         diro = 0;
+         
+         if (grub_jfs_read_inode (data, ino, &data->currinode))
+           break;
+         
+         /* Check if this is a symlink.  */
+         if ((grub_le_to_cpu32 (data->currinode.mode)
+              & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_LNK)
+           {
+             grub_jfs_lookup_symlink (data, dirino);
+             if (grub_errno)
+               return grub_errno;
+           }
+         
+         if (!next)
+           return 0;
+
+         pos = 0;
+         
+         name = next;
+         next = grub_strchr (name, '/');
+         if (next)
+           {
+             next[0] = '\0';
+             next++;
+           }
+         
+         /* Open this directory for reading dirents.  */
+         diro = grub_jfs_opendir (data, &data->currinode);
+         if (!diro)
+           return grub_errno;
+         
+         continue;
+       }
+    }
+
+  grub_jfs_closedir (diro);
+  grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+  return grub_errno;
+}
+
+
+static grub_err_t
+grub_jfs_lookup_symlink (struct grub_jfs_data *data, int ino)
+{
+  int size = grub_le_to_cpu64 (data->currinode.size);
+  char symlink[size + 1];
+
+  if (++data->linknest > GRUB_JFS_MAX_SYMLNK_CNT)
+    return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks");
+  
+  if (size <= 128)
+    grub_strncpy (symlink, (char *) (data->currinode.symlink.path), 128);
+  else if (grub_jfs_read_file (data, 0, 0, size, symlink) < 0)
+    return grub_errno;
+
+  symlink[size] = '\0';
+  
+  /* The symlink is an absolute path, go back to the root inode.  */
+  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);
+  if (grub_errno)
+    grub_error (grub_errno, "Can not follow symlink `%s'.", symlink);
+  
+  return grub_errno;
+}
+\f
+
+static grub_err_t
+grub_jfs_dir (grub_device_t device, const char *path, 
+             int (*hook) (const char *filename, int dir))
+{
+  struct grub_jfs_data *data = 0;
+  struct grub_jfs_diropen *diro = 0;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_jfs_mount (device->disk);
+  if (!data)
+    goto fail;
+
+  if (grub_jfs_find_file (data, path))
+    goto fail;
+  
+  diro = grub_jfs_opendir (data, &data->currinode);
+  if (!diro)
+    goto fail;
+
+  /* Iterate over the dirents in the directory that was found.  */
+  while (grub_jfs_getent (diro) != GRUB_ERR_OUT_OF_RANGE)
+    {
+      struct grub_jfs_inode inode;
+      int isdir;
+      
+      if (grub_jfs_read_inode (data, diro->ino, &inode))
+       goto fail;
+      
+      isdir = (grub_le_to_cpu32 (inode.mode)
+              & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR;
+      if (hook (diro->name, isdir))
+       goto fail;
+    }
+  
+  /* XXX: GRUB_ERR_OUT_OF_RANGE is used for the last dirent.  */
+  if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+    grub_errno = 0;
+
+ fail:
+  grub_jfs_closedir (diro);
+  grub_free (data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+
+/* Open a file named NAME and initialize FILE.  */
+static grub_err_t
+grub_jfs_open (struct grub_file *file, const char *name)
+{
+  struct grub_jfs_data *data;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_jfs_mount (file->device->disk);
+  if (!data)
+    goto fail;
+  
+  grub_jfs_find_file (data, name);
+  if (grub_errno)
+    goto fail;
+  
+  /* It is only possible for open regular files.  */
+  if (! ((grub_le_to_cpu32 (data->currinode.mode)
+         & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_REG))
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a regular file");
+      goto fail;
+    }
+  
+  file->data = data;
+  file->size = grub_le_to_cpu64 (data->currinode.size);
+  
+  return 0;
+  
+ fail:
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+  
+  grub_free (data);
+  
+  return grub_errno;;
+}
+
+
+static grub_ssize_t
+grub_jfs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_jfs_data *data = 
+    (struct grub_jfs_data *) file->data;
+  
+  return grub_jfs_read_file (data, file->read_hook, file->offset, len, buf);
+}
+
+
+static grub_err_t
+grub_jfs_close (grub_file_t file)
+{
+  grub_free (file->data);
+  
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+  
+  return GRUB_ERR_NONE;
+}
+
+
+static grub_err_t
+grub_jfs_label (grub_device_t device, char **label)
+{
+  struct grub_jfs_data *data;
+  data = grub_jfs_mount (device->disk);
+  
+  if (data)
+    *label = grub_strndup ((char *) (data->sblock.volname), 11);
+  else
+    *label = 0;
+  
+  return grub_errno;
+}
+\f
+
+static struct grub_fs grub_jfs_fs =
+  {
+    .name = "jfs",
+    .dir = grub_jfs_dir,
+    .open = grub_jfs_open,
+    .read = grub_jfs_read,
+    .close = grub_jfs_close,
+    .label = grub_jfs_label,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(jfs)
+{
+  grub_fs_register (&grub_jfs_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(jfs)
+{
+  grub_fs_unregister (&grub_jfs_fs);
+}
diff --git a/fs/minix.c b/fs/minix.c
new file mode 100644 (file)
index 0000000..cc03d7d
--- /dev/null
@@ -0,0 +1,613 @@
+/* minix.c - The minix filesystem, version 1 and 2.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,2005,2006,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/>.
+ */
+
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/types.h>
+
+#define GRUB_MINIX_MAGIC       0x137F
+#define GRUB_MINIX2_MAGIC      0x2468
+#define GRUB_MINIX_MAGIC_30    0x138F
+#define GRUB_MINIX2_MAGIC_30   0x2478
+#define GRUB_MINIX_BSIZE       1024U
+#define GRUB_MINIX_LOG2_BSIZE  1
+#define GRUB_MINIX_ROOT_INODE  1
+#define GRUB_MINIX_MAX_SYMLNK_CNT      8
+#define GRUB_MINIX_SBLOCK      2
+
+#define GRUB_MINIX_IFDIR       0040000U
+#define GRUB_MINIX_IFLNK       0120000U
+
+#define GRUB_MINIX_INODE(data,field) (data->version == 1 ? \
+                           data->inode.  field : data->inode2.  field)
+#define GRUB_MINIX_INODE_ENDIAN(data,field,bits1,bits2) (data->version == 1 ?  \
+                        grub_le_to_cpu##bits1 (data->inode.field) :            \
+                        grub_le_to_cpu##bits2 (data->inode2.field))
+#define GRUB_MINIX_INODE_SIZE(data) GRUB_MINIX_INODE_ENDIAN (data,size,16,32)
+#define GRUB_MINIX_INODE_MODE(data) GRUB_MINIX_INODE_ENDIAN (data,mode,16,16)
+#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) GRUB_MINIX_INODE_ENDIAN           \
+                                               (data,dir_zones[blk],16,32)
+#define GRUB_MINIX_INODE_INDIR_ZONE(data)                              \
+                        GRUB_MINIX_INODE_ENDIAN (data,indir_zone,16,32)
+#define GRUB_MINIX_INODE_DINDIR_ZONE(data)                                     \
+                        GRUB_MINIX_INODE_ENDIAN (data,double_indir_zone,16,32)
+#define GRUB_MINIX_INODE_BLKSZ(data) (data->version == 1 ? 2 : 4)
+#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))
+
+struct grub_minix_sblock
+{
+  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;
+};
+
+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;
+};
+
+struct grub_minix2_inode
+{
+  grub_uint16_t mode;
+  grub_uint16_t nlinks;
+  grub_uint16_t uid;
+  grub_uint16_t gid;
+  grub_uint32_t size;
+  grub_uint32_t atime;
+  grub_uint32_t mtime;
+  grub_uint32_t ctime;
+  grub_uint32_t dir_zones[7];
+  grub_uint32_t indir_zone;
+  grub_uint32_t double_indir_zone;
+  grub_uint32_t unused;
+  
+};
+
+/* Information about a "mounted" minix filesystem.  */
+struct grub_minix_data
+{
+  struct grub_minix_sblock sblock;
+  struct grub_minix_inode inode;
+  struct grub_minix2_inode inode2;
+  int ino;
+  int linknest;
+  grub_disk_t disk;
+  int version;
+  int filename_size;
+};
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+\f
+static grub_err_t grub_minix_find_file (struct grub_minix_data *data,
+                                       const char *path);
+
+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);
+
+  /* Read the block pointer in ZONE, on the offset NUM.  */
+  int grub_get_indir (int zone, int num)
+    {
+      if (data->version == 1)
+       {
+         grub_uint16_t indir16;
+         grub_disk_read (data->disk,
+                         zone << GRUB_MINIX_LOG2_ZONESZ,
+                         sizeof (grub_uint16_t) * num,
+                         sizeof (grub_uint16_t), (char *) &indir16);
+         return grub_le_to_cpu16 (indir16);
+       }
+      else
+       {
+         grub_uint32_t indir32;
+         grub_disk_read (data->disk,
+                         zone << GRUB_MINIX_LOG2_ZONESZ,
+                         sizeof (grub_uint32_t) * num,
+                         sizeof (grub_uint32_t), (char *) &indir32);
+         return grub_le_to_cpu32 (indir32);
+       }
+    }
+  
+  /* Direct block.  */
+  if (blk < 7)
+    return GRUB_MINIX_INODE_DIR_ZONES (data, blk);
+  
+  /* Indirect block.  */
+  blk -= 7;
+  if (blk < GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))
+    {
+      indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk);
+      return indir;
+    }
+  
+  /* Double indirect block.  */
+  blk -= GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data);
+  if (blk < (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))
+      * (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data)))
+    {
+      indir = grub_get_indir (GRUB_MINIX_INODE_DINDIR_ZONE (data), 
+                             blk / GRUB_MINIX_ZONESZ);
+      
+      indir = grub_get_indir (indir, blk % GRUB_MINIX_ZONESZ);
+      
+      return indir;
+    }
+  
+  /* This should never happen.  */
+  grub_error (GRUB_ERR_OUT_OF_RANGE, "file bigger than maximum size");
+  
+  return 0;
+}
+
+
+/* Read LEN bytes from the file described by DATA starting with byte
+   POS.  Return the amount of read bytes in READ.  */
+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)
+{
+  struct grub_minix_sblock *sblock = &data->sblock;
+  int i;
+  int blockcnt;
+
+  /* Adjust len so it we can't read past the end of the file.  */
+  if (len > GRUB_MINIX_INODE_SIZE (data))
+    len = GRUB_MINIX_INODE_SIZE (data);
+
+  blockcnt = (len + pos + GRUB_MINIX_BSIZE - 1) / GRUB_MINIX_BSIZE;
+  
+  for (i = pos / GRUB_MINIX_BSIZE; i < blockcnt; i++)
+    {
+      int blknr;
+      int blockoff = pos % GRUB_MINIX_BSIZE;
+      int blockend = GRUB_MINIX_BSIZE;
+      
+      int skipfirst = 0;
+      
+      blknr = grub_minix_get_file_block (data, i);
+      if (grub_errno)
+       return -1;
+      
+      /* Last block.  */
+      if (i == blockcnt - 1)
+       {
+         blockend = (len + pos) % GRUB_MINIX_BSIZE;
+         
+         if (!blockend)
+           blockend = GRUB_MINIX_BSIZE;
+       }
+      
+      /* First block.  */
+      if (i == (pos / (int) GRUB_MINIX_BSIZE))
+       {
+         skipfirst = blockoff;
+         blockend -= skipfirst;
+       }
+      
+      data->disk->read_hook = read_hook;
+      grub_disk_read (data->disk, blknr << GRUB_MINIX_LOG2_ZONESZ,
+                     skipfirst, blockend, buf);
+      
+      data->disk->read_hook = 0;
+      if (grub_errno)
+       return -1;
+      
+      buf += GRUB_MINIX_BSIZE - skipfirst;
+    }
+  
+  return len;
+}
+
+
+/* Read inode INO from the mounted filesystem described by DATA.  This
+   inode is used by default now.  */
+static grub_err_t
+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;
+  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);
+  
+  if (data->version == 1)
+    {
+      block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode));
+      int offs = (ino % (GRUB_DISK_SECTOR_SIZE 
+                        / sizeof (struct grub_minix_inode))
+                 * sizeof (struct grub_minix_inode));
+      
+      grub_disk_read (data->disk, block, offs,
+                     sizeof (struct grub_minix_inode), (char *) &data->inode);
+    }
+  else
+    {
+      block += ino / (GRUB_DISK_SECTOR_SIZE 
+                     / sizeof (struct grub_minix2_inode));
+      int offs = (ino 
+                 % (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix2_inode))
+                 * sizeof (struct grub_minix2_inode));
+      
+      grub_disk_read (data->disk, block, offs,
+                     sizeof (struct grub_minix2_inode),(char *) &data->inode2);
+    }
+  
+  return GRUB_ERR_NONE;
+}
+
+
+/* Lookup the symlink the current inode points to.  INO is the inode
+   number of the directory the symlink is relative to.  */
+static grub_err_t
+grub_minix_lookup_symlink (struct grub_minix_data *data, int ino)
+{
+  char symlink[GRUB_MINIX_INODE_SIZE (data) + 1];
+  
+  if (++data->linknest > GRUB_MINIX_MAX_SYMLNK_CNT)
+    return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks");
+  
+  if (grub_minix_read_file (data, 0, 0,
+                           GRUB_MINIX_INODE_SIZE (data), symlink) < 0)
+    return grub_errno;
+
+  symlink[GRUB_MINIX_INODE_SIZE (data)] = '\0';
+  
+  /* The symlink is an absolute path, go back to the root inode.  */
+  if (symlink[0] == '/')
+    ino = GRUB_MINIX_ROOT_INODE;
+  
+  /* Now load in the old inode.  */
+  if (grub_minix_read_inode (data, ino))
+    return grub_errno;
+  
+  grub_minix_find_file (data, symlink);
+  if (grub_errno)
+    grub_error (grub_errno, "Can not follow symlink `%s'.", symlink);
+  
+  return grub_errno;
+}
+
+
+/* Find the file with the pathname PATH on the filesystem described by
+   DATA.  */
+static grub_err_t
+grub_minix_find_file (struct grub_minix_data *data, const char *path)
+{
+  char fpath[grub_strlen (path) + 1];
+  char *name = fpath;
+  char *next;
+  unsigned int pos = 0;
+  int dirino;
+  
+  grub_strcpy (fpath, path);
+  
+  /* Skip the first slash.  */
+  if (name[0] == '/')
+    {
+      name++;
+      if (!*name)
+       return 0;
+    }
+
+  /* Extract the actual part from the pathname.  */
+  next = grub_strchr (name, '/');
+  if (next)
+    {
+      next[0] = '\0';
+      next++;
+    }
+  
+  do
+    {
+      grub_uint16_t ino;
+      char filename[data->filename_size + 1];
+      
+      if (grub_strlen (name) == 0)
+       return GRUB_ERR_NONE;
+      
+      if (grub_minix_read_file (data, 0, pos, sizeof (ino),
+                               (char *) &ino) < 0)
+       return grub_errno;
+      if (grub_minix_read_file (data, 0, pos + sizeof (ino),
+                               data->filename_size, (char *) filename)< 0)
+       return grub_errno;
+
+      filename[data->filename_size] = '\0';
+      
+      /* Check if the current direntry matches the current part of the
+        pathname.  */
+      if (!grub_strcmp (name, filename))
+       {
+         dirino = data->ino;
+         grub_minix_read_inode (data, grub_le_to_cpu16 (ino));
+         
+         /* Follow the symlink.  */
+         if ((GRUB_MINIX_INODE_MODE (data) 
+              & GRUB_MINIX_IFLNK) == GRUB_MINIX_IFLNK)
+           {
+             grub_minix_lookup_symlink (data, dirino);
+             if (grub_errno)
+               return grub_errno;
+           }
+         
+         if (!next)
+           return 0;
+         
+         pos = 0;
+         
+         name = next;
+         next = grub_strchr (name, '/');
+         if (next)
+           {
+             next[0] = '\0';
+             next++;
+           }
+         
+         if ((GRUB_MINIX_INODE_MODE (data)
+              & GRUB_MINIX_IFDIR) != GRUB_MINIX_IFDIR)
+           return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+         
+         continue;
+       }
+      
+      pos += sizeof (ino) + data->filename_size;
+    } while (pos < GRUB_MINIX_INODE_SIZE (data));
+  
+  grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+  return grub_errno;
+}
+
+
+/* Mount the filesystem on the disk DISK.  */
+static struct grub_minix_data *
+grub_minix_mount (grub_disk_t disk)
+{
+  struct grub_minix_data *data;
+  
+  data = grub_malloc (sizeof (struct grub_minix_data));
+  if (!data)
+    return 0;
+  
+  /* Read the superblock.  */
+  grub_disk_read (disk, GRUB_MINIX_SBLOCK, 0,
+                 sizeof (struct grub_minix_sblock),(char *) &data->sblock);
+  if (grub_errno)
+    goto fail;
+
+  if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC)
+    {
+      data->version = 1;
+      data->filename_size = 14;
+    }
+  else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX2_MAGIC)
+    {
+      data->version = 2;
+      data->filename_size = 14;
+    }
+  else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC_30)
+    {
+      data->version = 1;
+      data->filename_size = 30;
+    }
+  else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX2_MAGIC_30)
+    {
+      data->version = 2;
+      data->filename_size = 30;
+    }
+  else
+    goto fail;
+
+  data->disk = disk;
+  data->linknest = 0;
+
+  return data;
+
+ fail:
+  grub_free (data);
+  grub_error (GRUB_ERR_BAD_FS, "not a minix filesystem");
+  return 0;
+}
+\f
+static grub_err_t
+grub_minix_dir (grub_device_t device, const char *path, 
+                 int (*hook) (const char *filename, int dir))
+{
+  struct grub_minix_data *data = 0;
+  struct grub_minix_sblock *sblock;
+  unsigned int pos = 0;
+  
+  data = grub_minix_mount (device->disk);
+  if (!data)
+    return grub_errno;
+  
+  grub_minix_read_inode (data, GRUB_MINIX_ROOT_INODE);
+  if (grub_errno)
+    goto fail;
+  
+  sblock = &data->sblock;
+
+  grub_minix_find_file (data, path);
+  if (grub_errno)
+    goto fail;
+  
+  if ((GRUB_MINIX_INODE_MODE (data) & GRUB_MINIX_IFDIR) != GRUB_MINIX_IFDIR)
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+      goto fail;
+    }
+  
+  while (pos < GRUB_MINIX_INODE_SIZE (data))
+    {
+      grub_uint16_t ino;
+      char filename[data->filename_size + 1];
+      int dirino = data->ino;
+      
+      if (grub_minix_read_file (data, 0, pos, sizeof (ino),
+                               (char *) &ino) < 0)
+       return grub_errno;
+      
+      if (grub_minix_read_file (data, 0, pos + sizeof (ino),
+                               data->filename_size,
+                               (char *) filename) < 0)
+       return grub_errno;
+      filename[data->filename_size] = '\0';
+      
+      /* 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));
+      if (hook (filename, ((GRUB_MINIX_INODE_MODE (data) 
+                           & GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR)) ? 1 : 0)
+       break;
+      
+      /* Load the old inode back in.  */
+      grub_minix_read_inode (data, dirino);
+
+      pos += sizeof (ino) + data->filename_size;
+    }
+  
+ fail:
+  grub_free (data);
+  return grub_errno;
+}
+
+
+/* Open a file named NAME and initialize FILE.  */
+static grub_err_t
+grub_minix_open (struct grub_file *file, const char *name)
+{
+  struct grub_minix_data *data;
+  data = grub_minix_mount (file->device->disk);
+  if (!data)
+    return grub_errno;
+
+  /* Open the inode op the root directory.  */
+  grub_minix_read_inode (data, GRUB_MINIX_ROOT_INODE);
+  if (grub_errno)
+    {
+      grub_free (data);
+      return grub_errno;
+    }
+    
+  if (!name || name[0] != '/')
+    {
+      grub_error (GRUB_ERR_BAD_FILENAME, "bad filename");
+      return grub_errno;
+    }
+  
+  /* Traverse the directory tree to the node that should be
+     opened.  */
+  grub_minix_find_file (data, name);
+  if (grub_errno)
+    {
+      grub_free (data);
+      return grub_errno;
+    }
+  
+  file->data = data;
+  file->size = GRUB_MINIX_INODE_SIZE (data);
+  
+  return GRUB_ERR_NONE;
+}
+
+
+static grub_ssize_t
+grub_minix_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_minix_data *data = 
+    (struct grub_minix_data *) file->data;
+  
+  return grub_minix_read_file (data, file->read_hook, file->offset, len, buf);
+}
+
+
+static grub_err_t
+grub_minix_close (grub_file_t file)
+{
+  grub_free (file->data);
+  
+  return GRUB_ERR_NONE;
+}
+
+
+static grub_err_t
+grub_minix_label (grub_device_t device __attribute ((unused)),
+               char **label __attribute ((unused)))
+{
+  return GRUB_ERR_NONE;
+}
+
+\f
+static struct grub_fs grub_minix_fs =
+  {
+    .name = "minix",
+    .dir = grub_minix_dir,
+    .open = grub_minix_open,
+    .read = grub_minix_read,
+    .close = grub_minix_close,
+    .label = grub_minix_label,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(minix)
+{
+  grub_fs_register (&grub_minix_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(minix)
+{
+  grub_fs_unregister (&grub_minix_fs);
+}
diff --git a/fs/ntfs.c b/fs/ntfs.c
new file mode 100644 (file)
index 0000000..22477c5
--- /dev/null
+++ b/fs/ntfs.c
@@ -0,0 +1,1141 @@
+/* ntfs.c - NTFS filesystem */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007,2008 Free Software Foundation, Inc.
+ *
+ *  This program 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.
+ *
+ *  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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/fshelp.h>
+#include <grub/ntfs.h>
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+ntfscomp_func_t grub_ntfscomp_func;
+
+static grub_err_t
+fixup (struct grub_ntfs_data *data, char *buf, int len, char *magic)
+{
+  int ss;
+  char *pu;
+  grub_uint16_t us;
+
+  if (grub_memcmp (buf, magic, 4))
+    return grub_error (GRUB_ERR_BAD_FS, "%s label not found", magic);
+
+  ss = u16at (buf, 6) - 1;
+  if (ss * (int) data->blocksize != len * GRUB_DISK_SECTOR_SIZE)
+    return grub_error (GRUB_ERR_BAD_FS, "Size not match",
+                      ss * (int) data->blocksize,
+                      len * GRUB_DISK_SECTOR_SIZE);
+  pu = buf + u16at (buf, 4);
+  us = u16at (pu, 0);
+  buf -= 2;
+  while (ss > 0)
+    {
+      buf += data->blocksize;
+      pu += 2;
+      if (u16at (buf, 0) != us)
+       return grub_error (GRUB_ERR_BAD_FS, "Fixup signature not match");
+      v16at (buf, 0) = v16at (pu, 0);
+      ss--;
+    }
+
+  return 0;
+}
+
+static grub_err_t read_mft (struct grub_ntfs_data *data, char *buf,
+                           grub_uint32_t mftno);
+static grub_err_t read_attr (struct grub_ntfs_attr *at, char *dest,
+                            grub_uint32_t ofs, grub_uint32_t len,
+                            int cached,
+                            void
+                            NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t
+                                                           sector,
+                                                           unsigned offset,
+                                                           unsigned length));
+
+static grub_err_t read_data (struct grub_ntfs_attr *at, char *pa, char *dest,
+                            grub_uint32_t ofs, grub_uint32_t len,
+                            int cached,
+                            void
+                            NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t
+                                                           sector,
+                                                           unsigned offset,
+                                                           unsigned length));
+
+static void
+init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft)
+{
+  at->mft = mft;
+  at->flags = (mft == &mft->data->mmft) ? AF_MMFT : 0;
+  at->attr_nxt = mft->buf + u16at (mft->buf, 0x14);
+  at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL;
+}
+
+static void
+free_attr (struct grub_ntfs_attr *at)
+{
+  grub_free (at->emft_buf);
+  grub_free (at->edat_buf);
+  grub_free (at->sbuf);
+}
+
+static char *
+find_attr (struct grub_ntfs_attr *at, unsigned char attr)
+{
+  if (at->flags & AF_ALST)
+    {
+    retry:
+      while (at->attr_nxt < at->attr_end)
+       {
+         at->attr_cur = at->attr_nxt;
+         at->attr_nxt += u16at (at->attr_cur, 4);
+         if (((unsigned char) *at->attr_cur == attr) || (attr == 0))
+           {
+             char *new_pos;
+
+             if (at->flags & AF_MMFT)
+               {
+                 if ((grub_disk_read
+                      (at->mft->data->disk, v32at (at->attr_cur, 0x10), 0,
+                       512, at->emft_buf))
+                     ||
+                     (grub_disk_read
+                      (at->mft->data->disk, v32at (at->attr_cur, 0x14), 0,
+                       512, at->emft_buf + 512)))
+                   return NULL;
+
+                 if (fixup
+                     (at->mft->data, at->emft_buf, at->mft->data->mft_size,
+                      "FILE"))
+                   return NULL;
+               }
+             else
+               {
+                 if (read_mft (at->mft->data, at->emft_buf,
+                               u32at (at->attr_cur, 0x10)))
+                   return NULL;
+               }
+
+             new_pos = &at->emft_buf[u16at (at->emft_buf, 0x14)];
+             while ((unsigned char) *new_pos != 0xFF)
+               {
+                 if (((unsigned char) *new_pos ==
+                      (unsigned char) *at->attr_cur)
+                     && (u16at (new_pos, 0xE) == u16at (at->attr_cur, 0x18)))
+                   {
+                     return new_pos;
+                   }
+                 new_pos += u16at (new_pos, 4);
+               }
+             grub_error (GRUB_ERR_BAD_FS,
+                         "Can\'t find 0x%X in attribute list",
+                         (unsigned char) *at->attr_cur);
+             return NULL;
+           }
+       }
+      return NULL;
+    }
+  at->attr_cur = at->attr_nxt;
+  while ((unsigned char) *at->attr_cur != 0xFF)
+    {
+      at->attr_nxt += u16at (at->attr_cur, 4);
+      if ((unsigned char) *at->attr_cur == AT_ATTRIBUTE_LIST)
+       at->attr_end = at->attr_cur;
+      if (((unsigned char) *at->attr_cur == attr) || (attr == 0))
+       return at->attr_cur;
+      at->attr_cur = at->attr_nxt;
+    }
+  if (at->attr_end)
+    {
+      char *pa;
+
+      at->emft_buf = grub_malloc (at->mft->data->mft_size << BLK_SHR);
+      if (at->emft_buf == NULL)
+       return NULL;
+
+      pa = at->attr_end;
+      if (pa[8])
+       {
+          int n;
+
+          n = ((u32at (pa, 0x30) + GRUB_DISK_SECTOR_SIZE - 1)
+               & (~(GRUB_DISK_SECTOR_SIZE - 1)));
+         at->attr_cur = at->attr_end;
+         at->edat_buf = grub_malloc (n);
+         if (!at->edat_buf)
+           return NULL;
+         if (read_data (at, pa, at->edat_buf, 0, n, 0, 0))
+           {
+             grub_error (GRUB_ERR_BAD_FS,
+                         "Fail to read non-resident attribute list");
+             return NULL;
+           }
+         at->attr_nxt = at->edat_buf;
+         at->attr_end = at->edat_buf + u32at (pa, 0x30);
+       }
+      else
+       {
+         at->attr_nxt = at->attr_end + u16at (pa, 0x14);
+         at->attr_end = at->attr_end + u32at (pa, 4);
+       }
+      at->flags |= AF_ALST;
+      while (at->attr_nxt < at->attr_end)
+       {
+         if (((unsigned char) *at->attr_nxt == attr) || (attr == 0))
+           break;
+         at->attr_nxt += u16at (at->attr_nxt, 4);
+       }
+      if (at->attr_nxt >= at->attr_end)
+       return NULL;
+
+      if ((at->flags & AF_MMFT) && (attr == AT_DATA))
+       {
+         at->flags |= AF_GPOS;
+         at->attr_cur = at->attr_nxt;
+         pa = at->attr_cur;
+         v32at (pa, 0x10) = at->mft->data->mft_start;
+         v32at (pa, 0x14) = at->mft->data->mft_start + 1;
+         pa = at->attr_nxt + u16at (pa, 4);
+         while (pa < at->attr_end)
+           {
+             if ((unsigned char) *pa != attr)
+               break;
+             if (read_attr
+                 (at, pa + 0x10,
+                  u32at (pa, 0x10) * (at->mft->data->mft_size << BLK_SHR),
+                  at->mft->data->mft_size << BLK_SHR, 0, 0))
+               return NULL;
+             pa += u16at (pa, 4);
+           }
+         at->attr_nxt = at->attr_cur;
+         at->flags &= ~AF_GPOS;
+       }
+      goto retry;
+    }
+  return NULL;
+}
+
+static char *
+locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft,
+            unsigned char attr)
+{
+  char *pa;
+
+  init_attr (at, mft);
+  if ((pa = find_attr (at, attr)) == NULL)
+    return NULL;
+  if ((at->flags & AF_ALST) == 0)
+    {
+      while (1)
+       {
+         if ((pa = find_attr (at, attr)) == NULL)
+           break;
+         if (at->flags & AF_ALST)
+           return pa;
+       }
+      grub_errno = GRUB_ERR_NONE;
+      free_attr (at);
+      init_attr (at, mft);
+      pa = find_attr (at, attr);
+    }
+  return pa;
+}
+
+static char *
+read_run_data (char *run, int nn, grub_uint32_t * val, int sig)
+{
+  grub_uint32_t r, v;
+
+  r = 0;
+  v = 1;
+
+  while (nn--)
+    {
+      r += v * (*(unsigned char *) (run++));
+      v <<= 8;
+    }
+
+  if ((sig) && (r & (v >> 1)))
+    r -= v;
+
+  *val = r;
+  return run;
+}
+
+grub_err_t
+grub_ntfs_read_run_list (struct grub_ntfs_rlst * ctx)
+{
+  int c1, c2;
+  grub_uint32_t val;
+  char *run;
+
+  run = ctx->cur_run;
+retry:
+  c1 = ((unsigned char) (*run) & 0xF);
+  c2 = ((unsigned char) (*run) >> 4);
+  if (!c1)
+    {
+      if ((ctx->attr) && (ctx->attr->flags & AF_ALST))
+       {
+         void NESTED_FUNC_ATTR (*save_hook) (grub_disk_addr_t sector,
+                                             unsigned offset,
+                                             unsigned length);
+
+         save_hook = ctx->comp.disk->read_hook;
+         ctx->comp.disk->read_hook = 0;
+         run = find_attr (ctx->attr, (unsigned char) *ctx->attr->attr_cur);
+         ctx->comp.disk->read_hook = save_hook;
+         if (run)
+           {
+             if (run[8] == 0)
+               return grub_error (GRUB_ERR_BAD_FS,
+                                  "$DATA should be non-resident");
+
+             run += u16at (run, 0x20);
+             ctx->curr_lcn = 0;
+             goto retry;
+           }
+       }
+      return grub_error (GRUB_ERR_BAD_FS, "Run list overflown");
+    }
+  run = read_run_data (run + 1, c1, &val, 0);  /* length of current VCN */
+  ctx->curr_vcn = ctx->next_vcn;
+  ctx->next_vcn += val;
+  run = read_run_data (run, c2, &val, 1);      /* offset to previous LCN */
+  ctx->curr_lcn += val;
+  if (val == 0)
+    ctx->flags |= RF_BLNK;
+  else
+    ctx->flags &= ~RF_BLNK;
+  ctx->cur_run = run;
+  return 0;
+}
+
+static grub_disk_addr_t
+grub_ntfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t block)
+{
+  struct grub_ntfs_rlst *ctx;
+
+  ctx = (struct grub_ntfs_rlst *) node;
+  if ((grub_uint32_t) block >= ctx->next_vcn)
+    {
+      if (grub_ntfs_read_run_list (ctx))
+       return -1;
+      return ctx->curr_lcn;
+    }
+  else
+    return (ctx->flags & RF_BLNK) ? 0 : ((grub_uint32_t) block -
+                                        ctx->curr_vcn + ctx->curr_lcn);
+}
+
+static grub_err_t
+read_data (struct grub_ntfs_attr *at, char *pa, char *dest, grub_uint32_t ofs,
+          grub_uint32_t len, int cached,
+          void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
+                                              unsigned offset,
+                                              unsigned length))
+{
+  grub_uint32_t vcn;
+  struct grub_ntfs_rlst cc, *ctx;
+
+  if (len == 0)
+    return 0;
+
+  grub_memset (&cc, 0, sizeof (cc));
+  ctx = &cc;
+  ctx->attr = at;
+  ctx->comp.spc = at->mft->data->spc;
+  ctx->comp.disk = at->mft->data->disk;
+
+  if (pa[8] == 0)
+    {
+      if (ofs + len > u32at (pa, 0x10))
+       return grub_error (GRUB_ERR_BAD_FS, "Read out of range");
+      grub_memcpy (dest, pa + u32at (pa, 0x14) + ofs, len);
+      return 0;
+    }
+
+  if (u16at (pa, 0xC) & FLAG_COMPRESSED)
+    ctx->flags |= RF_COMP;
+  else
+    ctx->flags &= ~RF_COMP;
+  ctx->cur_run = pa + u16at (pa, 0x20);
+
+  if (ctx->flags & RF_COMP)
+    {
+      if (!cached)
+       return grub_error (GRUB_ERR_BAD_FS, "Attribute can\'t be compressed");
+
+      if (at->sbuf)
+       {
+         if ((ofs & (~(COM_LEN - 1))) == at->save_pos)
+           {
+             grub_uint32_t n;
+
+             n = COM_LEN - (ofs - at->save_pos);
+             if (n > len)
+               n = len;
+
+             grub_memcpy (dest, at->sbuf + ofs - at->save_pos, n);
+             if (n == len)
+               return 0;
+
+             dest += n;
+             len -= n;
+             ofs += n;
+           }
+       }
+      else
+       {
+         at->sbuf = grub_malloc (COM_LEN);
+         if (at->sbuf == NULL)
+           return grub_errno;
+         at->save_pos = 1;
+       }
+
+      vcn = ctx->target_vcn = (ofs / COM_LEN) * (COM_SEC / ctx->comp.spc);
+      ctx->target_vcn &= ~0xF;
+    }
+  else
+    vcn = ctx->target_vcn = (ofs >> BLK_SHR) / ctx->comp.spc;
+
+  ctx->next_vcn = u32at (pa, 0x10);
+  ctx->curr_lcn = 0;
+  while (ctx->next_vcn <= ctx->target_vcn)
+    {
+      if (grub_ntfs_read_run_list (ctx))
+       return grub_errno;
+    }
+
+  if (at->flags & AF_GPOS)
+    {
+      grub_uint32_t st0, st1;
+
+      st0 =
+       (ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) * ctx->comp.spc +
+       ((ofs >> BLK_SHR) % ctx->comp.spc);
+      st1 = st0 + 1;
+      if (st1 ==
+         (ctx->next_vcn - ctx->curr_vcn + ctx->curr_lcn) * ctx->comp.spc)
+       {
+         if (grub_ntfs_read_run_list (ctx))
+           return grub_errno;
+         st1 = ctx->curr_lcn * ctx->comp.spc;
+       }
+      v32at (dest, 0) = st0;
+      v32at (dest, 4) = st1;
+      return 0;
+    }
+
+  if (!(ctx->flags & RF_COMP))
+    {
+      unsigned int pow;
+
+      if (!grub_fshelp_log2blksize (ctx->comp.spc, &pow))
+       grub_fshelp_read_file (ctx->comp.disk, (grub_fshelp_node_t) ctx,
+                              read_hook, ofs, len, dest,
+                              grub_ntfs_read_block, ofs + len, pow);
+      return grub_errno;
+    }
+
+  return (grub_ntfscomp_func) ? grub_ntfscomp_func (at, dest, ofs, len, ctx,
+                                                   vcn) :
+    grub_error (GRUB_ERR_BAD_FS, "ntfscomp module not loaded");
+}
+
+static grub_err_t
+read_attr (struct grub_ntfs_attr *at, char *dest, grub_uint32_t ofs,
+          grub_uint32_t len, int cached,
+          void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
+                                              unsigned offset,
+                                              unsigned length))
+{
+  char *save_cur;
+  unsigned char attr;
+  char *pp;
+  grub_err_t ret;
+
+  save_cur = at->attr_cur;
+  at->attr_nxt = at->attr_cur;
+  attr = (unsigned char) *at->attr_nxt;
+  if (at->flags & AF_ALST)
+    {
+      char *pa;
+      grub_uint32_t vcn;
+
+      vcn = ofs / (at->mft->data->spc << BLK_SHR);
+      pa = at->attr_nxt + u16at (at->attr_nxt, 4);
+      while (pa < at->attr_end)
+       {
+         if ((unsigned char) *pa != attr)
+           break;
+         if (u32at (pa, 8) > vcn)
+           break;
+         at->attr_nxt = pa;
+         pa += u16at (pa, 4);
+       }
+    }
+  pp = find_attr (at, attr);
+  if (pp)
+    ret = read_data (at, pp, dest, ofs, len, cached, read_hook);
+  else
+    ret =
+      (grub_errno) ? grub_errno : grub_error (GRUB_ERR_BAD_FS,
+                                             "Attribute not found");
+  at->attr_cur = save_cur;
+  return ret;
+}
+
+static grub_err_t
+read_mft (struct grub_ntfs_data *data, char *buf, grub_uint32_t mftno)
+{
+  if (read_attr
+      (&data->mmft.attr, buf, mftno * (data->mft_size << BLK_SHR),
+       data->mft_size << BLK_SHR, 0, 0))
+    return grub_error (GRUB_ERR_BAD_FS, "Read MFT 0x%X fails", mftno);
+  return fixup (data, buf, data->mft_size, "FILE");
+}
+
+static grub_err_t
+init_file (struct grub_ntfs_file *mft, grub_uint32_t mftno)
+{
+  unsigned short flag;
+
+  mft->inode_read = 1;
+
+  mft->buf = grub_malloc (mft->data->mft_size << BLK_SHR);
+  if (mft->buf == NULL)
+    return grub_errno;
+
+  if (read_mft (mft->data, mft->buf, mftno))
+    return grub_errno;
+
+  flag = u16at (mft->buf, 0x16);
+  if ((flag & 1) == 0)
+    return grub_error (GRUB_ERR_BAD_FS, "MFT 0x%X is not in use", mftno);
+
+  if ((flag & 2) == 0)
+    {
+      char *pa;
+
+      pa = locate_attr (&mft->attr, mft, AT_DATA);
+      if (pa == NULL)
+       return grub_error (GRUB_ERR_BAD_FS, "No $DATA in MFT 0x%X", mftno);
+
+      if (!pa[8])
+       mft->size = u32at (pa, 0x10);
+      else
+       mft->size = u32at (pa, 0x30);
+
+      if ((mft->attr.flags & AF_ALST) == 0)
+       mft->attr.attr_end = 0; /*  Don't jump to attribute list */
+    }
+  else
+    init_attr (&mft->attr, mft);
+
+  return 0;
+}
+
+static void
+free_file (struct grub_ntfs_file *mft)
+{
+  free_attr (&mft->attr);
+  grub_free (mft->buf);
+}
+
+static int
+list_file (struct grub_ntfs_file *diro, char *pos,
+          int NESTED_FUNC_ATTR
+          (*hook) (const char *filename,
+                   enum grub_fshelp_filetype filetype,
+                   grub_fshelp_node_t node))
+{
+  char *np;
+  int ns;
+
+  while (1)
+    {
+      char *ustr, namespace;
+
+      if (pos[0xC] & 2)                /* end signature */
+       break;
+
+      np = pos + 0x50;
+      ns = (unsigned char) *(np++);
+      namespace = *(np++);
+
+      /*
+       *  Ignore files in DOS namespace, as they will reappear as Win32
+       *  names.
+       */
+      if ((ns) && (namespace != 2))
+       {
+         enum grub_fshelp_filetype type;
+         struct grub_ntfs_file *fdiro;
+
+         if (u16at (pos, 4))
+           {
+             grub_error (GRUB_ERR_BAD_FS, "64-bit MFT number");
+             return 0;
+           }
+
+         type =
+           (u32at (pos, 0x48) & ATTR_DIRECTORY) ? GRUB_FSHELP_DIR :
+           GRUB_FSHELP_REG;
+
+         fdiro = grub_malloc (sizeof (struct grub_ntfs_file));
+         if (!fdiro)
+           return 0;
+
+         grub_memset (fdiro, 0, sizeof (*fdiro));
+         fdiro->data = diro->data;
+         fdiro->ino = u32at (pos, 0);
+
+         ustr = grub_malloc (ns * 4 + 1);
+         if (ustr == NULL)
+           return 0;
+         *grub_utf16_to_utf8 ((grub_uint8_t *) ustr, (grub_uint16_t *) np,
+                              ns) = '\0';
+
+          if (namespace)
+            type |= GRUB_FSHELP_CASE_INSENSITIVE;
+
+         if (hook (ustr, type, fdiro))
+           {
+             grub_free (ustr);
+             return 1;
+           }
+
+         grub_free (ustr);
+       }
+      pos += u16at (pos, 8);
+    }
+  return 0;
+}
+
+static int
+grub_ntfs_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))
+{
+  unsigned char *bitmap;
+  struct grub_ntfs_attr attr, *at;
+  char *cur_pos, *indx, *bmp;
+  int bitmap_len, ret = 0;
+  struct grub_ntfs_file *mft;
+
+  mft = (struct grub_ntfs_file *) dir;
+
+  if (!mft->inode_read)
+    {
+      if (init_file (mft, mft->ino))
+       return 0;
+    }
+
+  indx = NULL;
+  bmp = NULL;
+
+  at = &attr;
+  init_attr (at, mft);
+  while (1)
+    {
+      if ((cur_pos = find_attr (at, AT_INDEX_ROOT)) == NULL)
+       {
+         grub_error (GRUB_ERR_BAD_FS, "No $INDEX_ROOT");
+         goto done;
+       }
+
+      /* Resident, Namelen=4, Offset=0x18, Flags=0x00, Name="$I30" */
+      if ((u32at (cur_pos, 8) != 0x180400) ||
+         (u32at (cur_pos, 0x18) != 0x490024) ||
+         (u32at (cur_pos, 0x1C) != 0x300033))
+       continue;
+      cur_pos += u16at (cur_pos, 0x14);
+      if (*cur_pos != 0x30)    /* Not filename index */
+       continue;
+      break;
+    }
+
+  cur_pos += 0x10;             /* Skip index root */
+  ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook);
+  if (ret)
+    goto done;
+
+  bitmap = NULL;
+  bitmap_len = 0;
+  free_attr (at);
+  init_attr (at, mft);
+  while ((cur_pos = find_attr (at, AT_BITMAP)) != NULL)
+    {
+      int ofs;
+
+      ofs = (unsigned char) cur_pos[0xA];
+      /* Namelen=4, Name="$I30" */
+      if ((cur_pos[9] == 4) &&
+         (u32at (cur_pos, ofs) == 0x490024) &&
+         (u32at (cur_pos, ofs + 4) == 0x300033))
+       {
+          int is_resident = (cur_pos[8] == 0);
+
+          bitmap_len = ((is_resident) ? u32at (cur_pos, 0x10) :
+                        u32at (cur_pos, 0x28));
+
+          bmp = grub_malloc (bitmap_len);
+          if (bmp == NULL)
+            goto done;
+
+         if (is_resident)
+           {
+              grub_memcpy (bmp, (char *) (cur_pos + u16at (cur_pos, 0x14)),
+                           bitmap_len);
+           }
+          else
+            {
+              if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0))
+                {
+                  grub_error (GRUB_ERR_BAD_FS,
+                              "Fails to read non-resident $BITMAP");
+                  goto done;
+                }
+              bitmap_len = u32at (cur_pos, 0x30);
+            }
+
+          bitmap = (unsigned char *) bmp;
+         break;
+       }
+    }
+
+  free_attr (at);
+  cur_pos = locate_attr (at, mft, AT_INDEX_ALLOCATION);
+  while (cur_pos != NULL)
+    {
+      /* Non-resident, Namelen=4, Offset=0x40, Flags=0, Name="$I30" */
+      if ((u32at (cur_pos, 8) == 0x400401) &&
+         (u32at (cur_pos, 0x40) == 0x490024) &&
+         (u32at (cur_pos, 0x44) == 0x300033))
+       break;
+      cur_pos = find_attr (at, AT_INDEX_ALLOCATION);
+    }
+
+  if ((!cur_pos) && (bitmap))
+    {
+      grub_error (GRUB_ERR_BAD_FS, "$BITMAP without $INDEX_ALLOCATION");
+      goto done;
+    }
+
+  if (bitmap)
+    {
+      grub_uint32_t v, i;
+
+      indx = grub_malloc (mft->data->idx_size << BLK_SHR);
+      if (indx == NULL)
+       goto done;
+
+      v = 1;
+      for (i = 0; i < (grub_uint32_t) bitmap_len * 8; i++)
+       {
+         if (*bitmap & v)
+           {
+             if ((read_attr
+                  (at, indx, i * (mft->data->idx_size << BLK_SHR),
+                   (mft->data->idx_size << BLK_SHR), 0, 0))
+                 || (fixup (mft->data, indx, mft->data->idx_size, "INDX")))
+               goto done;
+             ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)], hook);
+             if (ret)
+               goto done;
+           }
+         v <<= 1;
+         if (v >= 0x100)
+           {
+             v = 1;
+             bitmap++;
+           }
+       }
+    }
+
+done:
+  free_attr (at);
+  grub_free (indx);
+  grub_free (bmp);
+
+  return ret;
+}
+
+static struct grub_ntfs_data *
+grub_ntfs_mount (grub_disk_t disk)
+{
+  struct grub_ntfs_bpb bpb;
+  struct grub_ntfs_data *data = 0;
+
+  if (!disk)
+    goto fail;
+
+  data = (struct grub_ntfs_data *) grub_malloc (sizeof (*data));
+  if (!data)
+    goto fail;
+
+  grub_memset (data, 0, sizeof (*data));
+
+  data->disk = disk;
+
+  /* Read the BPB.  */
+  if (grub_disk_read (disk, 0, 0, sizeof (bpb), (char *) &bpb))
+    goto fail;
+
+  if (grub_memcmp ((char *) &bpb.oem_name, "NTFS", 4))
+    goto fail;
+
+  data->blocksize = grub_le_to_cpu16 (bpb.bytes_per_sector);
+  data->spc = bpb.sectors_per_cluster * (data->blocksize >> BLK_SHR);
+
+  if (bpb.clusters_per_mft > 0)
+    data->mft_size = data->spc * bpb.clusters_per_mft;
+  else
+    data->mft_size = 1 << (-bpb.clusters_per_mft - BLK_SHR);
+
+  if (bpb.clusters_per_index > 0)
+    data->idx_size = data->spc * bpb.clusters_per_index;
+  else
+    data->idx_size = 1 << (-bpb.clusters_per_index - BLK_SHR);
+
+  data->mft_start = grub_le_to_cpu64 (bpb.mft_lcn) * data->spc;
+
+  if ((data->mft_size > MAX_MFT) || (data->idx_size > MAX_IDX))
+    goto fail;
+
+  data->mmft.data = data;
+  data->cmft.data = data;
+
+  data->mmft.buf = grub_malloc (data->mft_size << BLK_SHR);
+  if (!data->mmft.buf)
+    goto fail;
+
+  if (grub_disk_read
+      (disk, data->mft_start, 0, data->mft_size << BLK_SHR, data->mmft.buf))
+    goto fail;
+
+  data->uuid = grub_le_to_cpu64 (bpb.num_serial);
+
+  if (fixup (data, data->mmft.buf, data->mft_size, "FILE"))
+    goto fail;
+
+  if (!locate_attr (&data->mmft.attr, &data->mmft, AT_DATA))
+    goto fail;
+
+  if (init_file (&data->cmft, FILE_ROOT))
+    goto fail;
+
+  return data;
+
+fail:
+  grub_error (GRUB_ERR_BAD_FS, "not an ntfs filesystem");
+
+  if (data)
+    {
+      free_file (&data->mmft);
+      free_file (&data->cmft);
+      grub_free (data);
+    }
+  return 0;
+}
+
+static grub_err_t
+grub_ntfs_dir (grub_device_t device, const char *path,
+              int (*hook) (const char *filename, int dir))
+{
+  struct grub_ntfs_data *data = 0;
+  struct grub_fshelp_node *fdiro = 0;
+
+  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)
+  {
+    grub_free (node);
+
+    if (filetype == GRUB_FSHELP_DIR)
+      return hook (filename, 1);
+    else
+      return hook (filename, 0);
+
+    return 0;
+  }
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+
+  data = grub_ntfs_mount (device->disk);
+  if (!data)
+    goto fail;
+
+  grub_fshelp_find_file (path, &data->cmft, &fdiro, grub_ntfs_iterate_dir,
+                        0, GRUB_FSHELP_DIR);
+
+  if (grub_errno)
+    goto fail;
+
+  grub_ntfs_iterate_dir (fdiro, iterate);
+
+fail:
+  if ((fdiro) && (fdiro != &data->cmft))
+    {
+      free_file (fdiro);
+      grub_free (fdiro);
+    }
+  if (data)
+    {
+      free_file (&data->mmft);
+      free_file (&data->cmft);
+      grub_free (data);
+    }
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_ntfs_open (grub_file_t file, const char *name)
+{
+  struct grub_ntfs_data *data = 0;
+  struct grub_fshelp_node *mft = 0;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_ntfs_mount (file->device->disk);
+  if (!data)
+    goto fail;
+
+  grub_fshelp_find_file (name, &data->cmft, &mft, grub_ntfs_iterate_dir,
+                        0, GRUB_FSHELP_REG);
+
+  if (grub_errno)
+    goto fail;
+
+  if (mft != &data->cmft)
+    {
+      free_file (&data->cmft);
+      grub_memcpy (&data->cmft, mft, sizeof (*mft));
+      grub_free (mft);
+      if (!data->cmft.inode_read)
+       {
+         if (init_file (&data->cmft, data->cmft.ino))
+           goto fail;
+       }
+    }
+
+  file->size = data->cmft.size;
+  file->data = data;
+  file->offset = 0;
+
+  return 0;
+
+fail:
+  if (data)
+    {
+      free_file (&data->mmft);
+      free_file (&data->cmft);
+      grub_free (data);
+    }
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+static grub_ssize_t
+grub_ntfs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_ntfs_file *mft;
+
+  mft = &((struct grub_ntfs_data *) file->data)->cmft;
+  if (file->read_hook)
+    mft->attr.save_pos = 1;
+
+  if (file->offset > file->size)
+    {
+      grub_error (GRUB_ERR_BAD_FS, "Bad offset");
+      return -1;
+    }
+
+  if (file->offset + len > file->size)
+    len = file->size - file->offset;
+
+  read_attr (&mft->attr, buf, file->offset, len, 1, file->read_hook);
+  return (grub_errno) ? 0 : len;
+}
+
+static grub_err_t
+grub_ntfs_close (grub_file_t file)
+{
+  struct grub_ntfs_data *data;
+
+  data = file->data;
+
+  if (data)
+    {
+      free_file (&data->mmft);
+      free_file (&data->cmft);
+      grub_free (data);
+    }
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_ntfs_label (grub_device_t device, char **label)
+{
+  struct grub_ntfs_data *data = 0;
+  struct grub_fshelp_node *mft = 0;
+  char *pa;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  *label = 0;
+
+  data = grub_ntfs_mount (device->disk);
+  if (!data)
+    goto fail;
+
+  grub_fshelp_find_file ("/$Volume", &data->cmft, &mft, grub_ntfs_iterate_dir,
+                        0, GRUB_FSHELP_REG);
+
+  if (grub_errno)
+    goto fail;
+
+  if (!mft->inode_read)
+    {
+      mft->buf = grub_malloc (mft->data->mft_size << BLK_SHR);
+      if (mft->buf == NULL)
+       goto fail;
+
+      if (read_mft (mft->data, mft->buf, mft->ino))
+       goto fail;
+    }
+
+  init_attr (&mft->attr, mft);
+  pa = find_attr (&mft->attr, AT_VOLUME_NAME);
+  if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10)))
+    {
+      char *buf;
+      int len;
+
+      len = u32at (pa, 0x10) / 2;
+      buf = grub_malloc (len * 4 + 1);
+      pa += u16at (pa, 0x14);
+      *grub_utf16_to_utf8 ((grub_uint8_t *) buf, (grub_uint16_t *) pa, len) =
+       '\0';
+      *label = buf;
+    }
+
+fail:
+  if ((mft) && (mft != &data->cmft))
+    {
+      free_file (mft);
+      grub_free (mft);
+    }
+  if (data)
+    {
+      free_file (&data->mmft);
+      free_file (&data->cmft);
+      grub_free (data);
+    }
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_ntfs_uuid (grub_device_t device, char **uuid)
+{
+  struct grub_ntfs_data *data;
+  grub_disk_t disk = device->disk;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_ntfs_mount (disk);
+  if (data)
+    {
+      *uuid = grub_malloc (16 + sizeof ('\0'));
+      grub_sprintf (*uuid, "%016llx", (unsigned long long) data->uuid);
+    }
+  else
+    *uuid = NULL;
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+}
+
+static struct grub_fs grub_ntfs_fs = {
+  .name = "ntfs",
+  .dir = grub_ntfs_dir,
+  .open = grub_ntfs_open,
+  .read = grub_ntfs_read,
+  .close = grub_ntfs_close,
+  .label = grub_ntfs_label,
+  .uuid = grub_ntfs_uuid,
+  .next = 0
+};
+
+GRUB_MOD_INIT (ntfs)
+{
+  grub_fs_register (&grub_ntfs_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI (ntfs)
+{
+  grub_fs_unregister (&grub_ntfs_fs);
+}
diff --git a/fs/ntfscomp.c b/fs/ntfscomp.c
new file mode 100644 (file)
index 0000000..db8b506
--- /dev/null
@@ -0,0 +1,375 @@
+/* ntfscomp.c - compression support for the NTFS filesystem */
+/*
+ *  Copyright (C) 2007 Free Software Foundation, Inc.
+ *
+ *  This program 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.
+ *
+ *  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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/fshelp.h>
+#include <grub/ntfs.h>
+
+static grub_err_t
+decomp_nextvcn (struct grub_ntfs_comp *cc)
+{
+  if (cc->comp_head >= cc->comp_tail)
+    return grub_error (GRUB_ERR_BAD_FS, "Compression block overflown");
+  if (grub_disk_read
+      (cc->disk,
+       (cc->comp_table[cc->comp_head][1] -
+       (cc->comp_table[cc->comp_head][0] - cc->cbuf_vcn)) * cc->spc, 0,
+       cc->spc << BLK_SHR, cc->cbuf))
+    return grub_errno;
+  cc->cbuf_vcn++;
+  if ((cc->cbuf_vcn >= cc->comp_table[cc->comp_head][0]))
+    cc->comp_head++;
+  cc->cbuf_ofs = 0;
+  return 0;
+}
+
+static grub_err_t
+decomp_getch (struct grub_ntfs_comp *cc, unsigned char *res)
+{
+  if (cc->cbuf_ofs >= (cc->spc << BLK_SHR))
+    {
+      if (decomp_nextvcn (cc))
+       return grub_errno;
+    }
+  *res = (unsigned char) cc->cbuf[cc->cbuf_ofs++];
+  return 0;
+}
+
+static grub_err_t
+decomp_get16 (struct grub_ntfs_comp *cc, grub_uint16_t * res)
+{
+  unsigned char c1, c2;
+
+  if ((decomp_getch (cc, &c1)) || (decomp_getch (cc, &c2)))
+    return grub_errno;
+  *res = ((grub_uint16_t) c2) * 256 + ((grub_uint16_t) c1);
+  return 0;
+}
+
+/* Decompress a block (4096 bytes) */
+static grub_err_t
+decomp_block (struct grub_ntfs_comp *cc, char *dest)
+{
+  grub_uint16_t flg, cnt;
+
+  if (decomp_get16 (cc, &flg))
+    return grub_errno;
+  cnt = (flg & 0xFFF) + 1;
+
+  if (dest)
+    {
+      if (flg & 0x8000)
+       {
+         unsigned char tag;
+         grub_uint32_t bits, copied;
+
+         bits = copied = tag = 0;
+         while (cnt > 0)
+           {
+             if (copied > COM_LEN)
+               return grub_error (GRUB_ERR_BAD_FS,
+                                  "Compression block too large");
+
+             if (!bits)
+               {
+                 if (decomp_getch (cc, &tag))
+                   return grub_errno;
+
+                 bits = 8;
+                 cnt--;
+                 if (cnt <= 0)
+                   break;
+               }
+             if (tag & 1)
+               {
+                 grub_uint32_t i, len, delta, code, lmask, dshift;
+                 grub_uint16_t word;
+
+                 if (decomp_get16 (cc, &word))
+                   return grub_errno;
+
+                 code = word;
+                 cnt -= 2;
+
+                 if (!copied)
+                   {
+                     grub_error (GRUB_ERR_BAD_FS, "Context window empty");
+                     return 0;
+                   }
+
+                 for (i = copied - 1, lmask = 0xFFF, dshift = 12; i >= 0x10;
+                      i >>= 1)
+                   {
+                     lmask >>= 1;
+                     dshift--;
+                   }
+
+                 delta = code >> dshift;
+                 len = (code & lmask) + 3;
+
+                 for (i = 0; i < len; i++)
+                   {
+                     dest[copied] = dest[copied - delta - 1];
+                     copied++;
+                   }
+               }
+             else
+               {
+                 unsigned char ch;
+
+                 if (decomp_getch (cc, &ch))
+                   return grub_errno;
+                 dest[copied++] = ch;
+                 cnt--;
+               }
+             tag >>= 1;
+             bits--;
+           }
+         return 0;
+       }
+      else
+       {
+         if (cnt != COM_LEN)
+           return grub_error (GRUB_ERR_BAD_FS,
+                              "Invalid compression block size");
+       }
+    }
+
+  while (cnt > 0)
+    {
+      int n;
+
+      n = (cc->spc << BLK_SHR) - cc->cbuf_ofs;
+      if (n > cnt)
+       n = cnt;
+      if ((dest) && (n))
+       {
+         memcpy (dest, &cc->cbuf[cc->cbuf_ofs], n);
+         dest += n;
+       }
+      cnt -= n;
+      cc->cbuf_ofs += n;
+      if ((cnt) && (decomp_nextvcn (cc)))
+       return grub_errno;
+    }
+  return 0;
+}
+
+static grub_err_t
+read_block (struct grub_ntfs_rlst *ctx, char *buf, int num)
+{
+  int cpb = COM_SEC / ctx->comp.spc;
+
+  while (num)
+    {
+      int nn;
+
+      if ((ctx->target_vcn & 0xF) == 0)
+       {
+
+         if (ctx->comp.comp_head != ctx->comp.comp_tail)
+           return grub_error (GRUB_ERR_BAD_FS, "Invalid compression block");
+         ctx->comp.comp_head = ctx->comp.comp_tail = 0;
+         ctx->comp.cbuf_vcn = ctx->target_vcn;
+         ctx->comp.cbuf_ofs = (ctx->comp.spc << BLK_SHR);
+         if (ctx->target_vcn >= ctx->next_vcn)
+           {
+             if (grub_ntfs_read_run_list (ctx))
+               return grub_errno;
+           }
+         while (ctx->target_vcn + 16 > ctx->next_vcn)
+           {
+             if (ctx->flags & RF_BLNK)
+               break;
+             ctx->comp.comp_table[ctx->comp.comp_tail][0] = ctx->next_vcn;
+             ctx->comp.comp_table[ctx->comp.comp_tail][1] =
+               ctx->curr_lcn + ctx->next_vcn - ctx->curr_vcn;
+             ctx->comp.comp_tail++;
+             if (grub_ntfs_read_run_list (ctx))
+               return grub_errno;
+           }
+       }
+
+      nn = (16 - (ctx->target_vcn & 0xF)) / cpb;
+      if (nn > num)
+       nn = num;
+      num -= nn;
+
+      if (ctx->flags & RF_BLNK)
+       {
+         ctx->target_vcn += nn * cpb;
+         if (ctx->comp.comp_tail == 0)
+           {
+             if (buf)
+               {
+                 grub_memset (buf, 0, nn * COM_LEN);
+                 buf += nn * COM_LEN;
+               }
+           }
+         else
+           {
+             while (nn)
+               {
+                 if (decomp_block (&ctx->comp, buf))
+                   return grub_errno;
+                 if (buf)
+                   buf += COM_LEN;
+                 nn--;
+               }
+           }
+       }
+      else
+       {
+         nn *= cpb;
+         while ((ctx->comp.comp_head < ctx->comp.comp_tail) && (nn))
+           {
+             int tt;
+
+             tt =
+               ctx->comp.comp_table[ctx->comp.comp_head][0] -
+               ctx->target_vcn;
+             if (tt > nn)
+               tt = nn;
+             ctx->target_vcn += tt;
+             if (buf)
+               {
+                 if (grub_disk_read
+                     (ctx->comp.disk,
+                      (ctx->comp.comp_table[ctx->comp.comp_head][1] -
+                       (ctx->comp.comp_table[ctx->comp.comp_head][0] -
+                        ctx->target_vcn)) * ctx->comp.spc, 0,
+                      tt * (ctx->comp.spc << BLK_SHR), buf))
+                   return grub_errno;
+                 buf += tt * (ctx->comp.spc << BLK_SHR);
+               }
+             nn -= tt;
+             if (ctx->target_vcn >=
+                 ctx->comp.comp_table[ctx->comp.comp_head][0])
+               ctx->comp.comp_head++;
+           }
+         if (nn)
+           {
+             if (buf)
+               {
+                 if (grub_disk_read
+                     (ctx->comp.disk,
+                      (ctx->target_vcn - ctx->curr_vcn +
+                       ctx->curr_lcn) * ctx->comp.spc, 0,
+                      nn * (ctx->comp.spc << BLK_SHR), buf))
+                   return grub_errno;
+                 buf += nn * (ctx->comp.spc << BLK_SHR);
+               }
+             ctx->target_vcn += nn;
+           }
+       }
+    }
+  return 0;
+}
+
+static grub_err_t
+ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_uint32_t ofs,
+         grub_uint32_t len, struct grub_ntfs_rlst *ctx, grub_uint32_t vcn)
+{
+  grub_err_t ret;
+
+  ctx->comp.comp_head = ctx->comp.comp_tail = 0;
+  ctx->comp.cbuf = grub_malloc ((ctx->comp.spc) << BLK_SHR);
+  if (!ctx->comp.cbuf)
+    return 0;
+
+  ret = 0;
+
+  //ctx->comp.disk->read_hook = read_hook;
+
+  if ((vcn > ctx->target_vcn) &&
+      (read_block
+       (ctx, NULL, ((vcn - ctx->target_vcn) * ctx->comp.spc) / COM_SEC)))
+    {
+      ret = grub_errno;
+      goto quit;
+    }
+
+  if (ofs % COM_LEN)
+    {
+      grub_uint32_t t, n, o;
+
+      t = ctx->target_vcn * (ctx->comp.spc << BLK_SHR);
+      if (read_block (ctx, at->sbuf, 1))
+       {
+         ret = grub_errno;
+         goto quit;
+       }
+
+      at->save_pos = t;
+
+      o = ofs % COM_LEN;
+      n = COM_LEN - o;
+      if (n > len)
+       n = len;
+      grub_memcpy (dest, &at->sbuf[o], n);
+      if (n == len)
+       goto quit;
+      dest += n;
+      len -= n;
+    }
+
+  if (read_block (ctx, dest, len / COM_LEN))
+    {
+      ret = grub_errno;
+      goto quit;
+    }
+
+  dest += (len / COM_LEN) * COM_LEN;
+  len = len % COM_LEN;
+  if (len)
+    {
+      grub_uint32_t t;
+
+      t = ctx->target_vcn * (ctx->comp.spc << BLK_SHR);
+      if (read_block (ctx, at->sbuf, 1))
+       {
+         ret = grub_errno;
+         goto quit;
+       }
+
+      at->save_pos = t;
+
+      grub_memcpy (dest, at->sbuf, len);
+    }
+
+quit:
+  //ctx->comp.disk->read_hook = 0;
+  if (ctx->comp.cbuf)
+    grub_free (ctx->comp.cbuf);
+  return ret;
+}
+
+GRUB_MOD_INIT (ntfscomp)
+{
+  (void) mod;
+  grub_ntfscomp_func = ntfscomp;
+}
+
+GRUB_MOD_FINI (ntfscomp)
+{
+  grub_ntfscomp_func = NULL;
+}
diff --git a/fs/reiserfs.c b/fs/reiserfs.c
new file mode 100644 (file)
index 0000000..8e91149
--- /dev/null
@@ -0,0 +1,1399 @@
+/* reiserfs.c - ReiserFS versions up to 3.6 */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,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/>.
+ */
+
+/*
+  TODO:
+  implement journal handling (ram replay)
+  test tail packing & direct files
+  validate partition label position
+*/
+
+#if 0
+# define GRUB_REISERFS_DEBUG
+# define GRUB_REISERFS_JOURNALING
+# define GRUB_HEXDUMP
+#endif
+
+#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>
+
+#define MIN(a, b) \
+  ({ typeof (a) _a = (a); \
+     typeof (b) _b = (b); \
+     _a < _b ? _a : _b; })
+
+#define MAX(a, b) \
+  ({ typeof (a) _a = (a); \
+     typeof (b) _b = (b); \
+     _a > _b ? _a : _b; })
+
+#define REISERFS_SUPER_BLOCK_OFFSET 0x10000
+#define REISERFS_MAGIC_LEN 12
+#define REISERFS_MAGIC_STRING "ReIsEr"
+#define REISERFS_MAGIC_DESC_BLOCK "ReIsErLB"
+/* If the 3rd bit of an item state is set, then it's visible.  */
+#define GRUB_REISERFS_VISIBLE_MASK ((grub_uint16_t) 0x04)
+#define REISERFS_MAX_LABEL_LENGTH 16
+#define REISERFS_LABEL_OFFSET 0x64
+
+#define S_IFLNK 0xA000
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+#define assert(boolean) real_assert (boolean, __FILE__, __LINE__)
+static inline void
+real_assert (int boolean, const char *file, const int line)
+{
+  if (! boolean)
+    grub_printf ("Assertion failed at %s:%d\n", file, line);
+}
+
+enum grub_reiserfs_item_type
+  {
+    GRUB_REISERFS_STAT,
+    GRUB_REISERFS_DIRECTORY,
+    GRUB_REISERFS_DIRECT,
+    GRUB_REISERFS_INDIRECT,
+    /* Matches both _DIRECT and _INDIRECT when searching.  */
+    GRUB_REISERFS_ANY,
+    GRUB_REISERFS_UNKNOWN
+  };
+
+struct grub_reiserfs_superblock
+{
+  grub_uint32_t block_count;
+  grub_uint32_t block_free_count;
+  grub_uint32_t root_block;
+  grub_uint32_t journal_block;
+  grub_uint32_t journal_device;
+  grub_uint32_t journal_original_size;
+  grub_uint32_t journal_max_transaction_size;
+  grub_uint32_t journal_block_count;
+  grub_uint32_t journal_max_batch;
+  grub_uint32_t journal_max_commit_age;
+  grub_uint32_t journal_max_transaction_age;
+  grub_uint16_t block_size;
+  grub_uint16_t oid_max_size;
+  grub_uint16_t oid_current_size;
+  grub_uint16_t state;
+  grub_uint8_t magic_string[REISERFS_MAGIC_LEN];
+  grub_uint32_t function_hash_code;
+  grub_uint16_t tree_height;
+  grub_uint16_t bitmap_number;
+  grub_uint16_t version;
+  grub_uint16_t reserved;
+  grub_uint32_t inode_generation;
+  grub_uint8_t unused[4];
+  grub_uint16_t uuid[8];
+} __attribute__ ((packed));
+
+struct grub_reiserfs_journal_header
+{
+  grub_uint32_t last_flush_uid;
+  grub_uint32_t unflushed_offset;
+  grub_uint32_t mount_id;
+} __attribute__ ((packed));
+
+struct grub_reiserfs_description_block
+{
+  grub_uint32_t id;
+  grub_uint32_t len;
+  grub_uint32_t mount_id;
+  grub_uint32_t real_blocks[0];
+} __attribute__ ((packed));
+
+struct grub_reiserfs_commit_block
+{
+  grub_uint32_t id;
+  grub_uint32_t len;
+  grub_uint32_t real_blocks[0];
+} __attribute__ ((packed));
+
+struct grub_reiserfs_stat_item_v1
+{
+  grub_uint16_t mode;
+  grub_uint16_t hardlink_count;
+  grub_uint16_t uid;
+  grub_uint16_t gid;
+  grub_uint32_t size;
+  grub_uint32_t atime;
+  grub_uint32_t mtime;
+  grub_uint32_t ctime;
+  grub_uint32_t rdev;
+  grub_uint32_t first_direct_byte;
+} __attribute__ ((packed));
+
+struct grub_reiserfs_stat_item_v2
+{
+  grub_uint16_t mode;
+  grub_uint16_t reserved;
+  grub_uint32_t hardlink_count;
+  grub_uint64_t size;
+  grub_uint32_t uid;
+  grub_uint32_t gid;
+  grub_uint32_t atime;
+  grub_uint32_t mtime;
+  grub_uint32_t ctime;
+  grub_uint32_t blocks;
+  grub_uint32_t first_direct_byte;
+} __attribute__ ((packed));
+
+struct grub_reiserfs_key
+{
+  grub_uint32_t directory_id;
+  grub_uint32_t object_id;
+  union
+  {
+    struct
+    {
+      grub_uint32_t offset;
+      grub_uint32_t type;
+    } v1 __attribute__ ((packed));
+    struct
+    {
+      grub_uint64_t offset_type;
+    } v2 __attribute__ ((packed));
+  } u;
+} __attribute__ ((packed));
+
+struct grub_reiserfs_item_header
+{
+  struct grub_reiserfs_key key;
+  union
+  {
+    grub_uint16_t free_space;
+    grub_uint16_t entry_count;
+  } u __attribute__ ((packed));
+  grub_uint16_t item_size;
+  grub_uint16_t item_location;
+  grub_uint16_t version;
+} __attribute__ ((packed));
+
+struct grub_reiserfs_block_header
+{
+  grub_uint16_t level;
+  grub_uint16_t item_count;
+  grub_uint16_t free_space;
+  grub_uint16_t reserved;
+  struct grub_reiserfs_key block_right_delimiting_key;
+} __attribute__ ((packed));
+
+struct grub_reiserfs_disk_child
+{
+  grub_uint32_t block_number;
+  grub_uint16_t size;
+  grub_uint16_t reserved;
+} __attribute__ ((packed));
+
+struct grub_reiserfs_directory_header
+{
+  grub_uint32_t offset;
+  grub_uint32_t directory_id;
+  grub_uint32_t object_id;
+  grub_uint16_t location;
+  grub_uint16_t state;
+} __attribute__ ((packed));
+
+struct grub_fshelp_node
+{
+  struct grub_reiserfs_data *data;
+  grub_uint32_t block_number; /* 0 if node is not found.  */
+  grub_uint16_t block_position;
+  grub_uint64_t next_offset;
+  enum grub_reiserfs_item_type type; /* To know how to read the header.  */
+  struct grub_reiserfs_item_header header;
+};
+
+/* Returned when opening a file.  */
+struct grub_reiserfs_data
+{
+  struct grub_reiserfs_superblock superblock;
+  grub_disk_t disk;
+};
+
+/* Internal-only functions. Not to be used outside of this file.  */
+
+/* Return the type of given v2 key.  */
+static enum grub_reiserfs_item_type
+grub_reiserfs_get_key_v2_type (const struct grub_reiserfs_key *key)
+{
+  switch (grub_le_to_cpu64 (key->u.v2.offset_type) >> 60)
+    {
+    case 0:
+      return GRUB_REISERFS_STAT;
+    case 15:
+      return GRUB_REISERFS_ANY;
+    case 3:
+      return GRUB_REISERFS_DIRECTORY;
+    case 2:
+      return GRUB_REISERFS_DIRECT;
+    case 1:
+      return GRUB_REISERFS_INDIRECT;
+    }
+  return GRUB_REISERFS_UNKNOWN;
+}
+
+/* Return the type of given v1 key.  */
+static enum grub_reiserfs_item_type
+grub_reiserfs_get_key_v1_type (const struct grub_reiserfs_key *key)
+{
+  switch (grub_le_to_cpu32 (key->u.v1.type))
+    {
+    case 0:
+      return GRUB_REISERFS_STAT;
+    case 555:
+      return GRUB_REISERFS_ANY;
+    case 500:
+      return GRUB_REISERFS_DIRECTORY;
+    case 0x20000000:
+    case 0xFFFFFFFF:
+      return GRUB_REISERFS_DIRECT;
+    case 0x10000000:
+    case 0xFFFFFFFE:
+      return GRUB_REISERFS_INDIRECT;
+    }
+  return GRUB_REISERFS_UNKNOWN;
+}
+
+/* Return 1 if the given key is version 1 key, 2 otherwise.  */
+static int
+grub_reiserfs_get_key_version (const struct grub_reiserfs_key *key)
+{
+  return grub_reiserfs_get_key_v1_type (key) == GRUB_REISERFS_UNKNOWN ? 2 : 1;
+}
+
+#ifdef GRUB_HEXDUMP
+static void
+grub_hexdump (char *buffer, grub_size_t len)
+{
+  grub_size_t a;
+  for (a = 0; a < len; a++)
+    {
+      if (! (a & 0x0F))
+        grub_printf ("\n%08x  ", a);
+      grub_printf ("%02x ",
+                   ((unsigned int) ((unsigned char *) buffer)[a]) & 0xFF);
+    }
+  grub_printf ("\n");
+}
+#endif
+
+#ifdef GRUB_REISERFS_DEBUG
+static grub_uint64_t
+grub_reiserfs_get_key_offset (const struct grub_reiserfs_key *key);
+
+static enum grub_reiserfs_item_type
+grub_reiserfs_get_key_type (const struct grub_reiserfs_key *key);
+
+static void
+grub_reiserfs_print_key (const struct grub_reiserfs_key *key)
+{
+  unsigned int a;
+  char *reiserfs_type_strings[] = {
+    "stat     ",
+    "directory",
+    "direct   ",
+    "indirect ",
+    "any      ",
+    "unknown  "
+  };
+  
+  for (a = 0; a < sizeof (struct grub_reiserfs_key); a++)
+    grub_printf ("%02x ", ((unsigned int) ((unsigned char *) key)[a]) & 0xFF);
+  grub_printf ("parent id = 0x%08x, self id = 0x%08x, type = %s, offset = ",
+               grub_le_to_cpu32 (key->directory_id),
+               grub_le_to_cpu32 (key->object_id),
+               reiserfs_type_strings [grub_reiserfs_get_key_type (key)]);
+  if (grub_reiserfs_get_key_version (key) == 1)
+    grub_printf("%08x", (unsigned int) grub_reiserfs_get_key_offset (key));
+  else
+    grub_printf("0x%07x%08x",
+                (unsigned) (grub_reiserfs_get_key_offset (key) >> 32),
+                (unsigned) (grub_reiserfs_get_key_offset (key) & 0xFFFFFFFF));
+  grub_printf ("\n");
+}
+#endif
+
+/* Return the offset of given key.  */
+static grub_uint64_t
+grub_reiserfs_get_key_offset (const struct grub_reiserfs_key *key)
+{
+  if (grub_reiserfs_get_key_version (key) == 1)
+    return grub_le_to_cpu32 (key->u.v1.offset);
+  else
+    return grub_le_to_cpu64 (key->u.v2.offset_type) & (~0ULL >> 4);
+}
+
+/* Set the offset of given key.  */
+static void
+grub_reiserfs_set_key_offset (struct grub_reiserfs_key *key,
+                              grub_uint64_t value)
+{
+  if (grub_reiserfs_get_key_version (key) == 1)
+    key->u.v1.offset = grub_cpu_to_le32 (value);
+  else
+    key->u.v2.offset_type \
+      = ((key->u.v2.offset_type & grub_cpu_to_le64 (15ULL << 60))
+         | grub_cpu_to_le64 (value & (~0ULL >> 4)));
+}
+
+/* Return the type of given key.  */
+static enum grub_reiserfs_item_type
+grub_reiserfs_get_key_type (const struct grub_reiserfs_key *key)
+{
+  if (grub_reiserfs_get_key_version (key) == 1)
+    return grub_reiserfs_get_key_v1_type (key);
+  else
+    return grub_reiserfs_get_key_v2_type (key);
+}
+
+/* Set the type of given key, with given version number.  */
+static void
+grub_reiserfs_set_key_type (struct grub_reiserfs_key *key,
+                            enum grub_reiserfs_item_type grub_type,
+                            int version)
+{
+  grub_uint32_t type;
+  
+  switch (grub_type)
+    {
+    case GRUB_REISERFS_STAT:
+      type = 0;
+      break;
+    case GRUB_REISERFS_ANY:
+      type = (version == 1) ? 555 : 15;
+      break;
+    case GRUB_REISERFS_DIRECTORY:
+      type = (version == 1) ? 500 : 3;
+      break;
+    case GRUB_REISERFS_DIRECT:
+      type = (version == 1) ? 0xFFFFFFFF : 2;
+      break;
+    case GRUB_REISERFS_INDIRECT:
+      type = (version == 1) ? 0xFFFFFFFE : 1;
+      break;
+    default:
+      return;
+    }
+  
+  if (version == 1)
+    key->u.v1.type = grub_cpu_to_le32 (type);
+  else
+    key->u.v2.offset_type
+      = ((key->u.v2.offset_type & grub_cpu_to_le64 (~0ULL >> 4))
+         | grub_cpu_to_le64 ((grub_uint64_t) type << 60));
+  
+  assert (grub_reiserfs_get_key_type (key) == grub_type);
+}
+
+/* -1 if key 1 if lower than key 2.
+   0 if key 1 is equal to key 2.
+   1 if key 1 is higher than key 2.  */
+static int
+grub_reiserfs_compare_keys (const struct grub_reiserfs_key *key1,
+                            const struct grub_reiserfs_key *key2)
+{
+  grub_uint64_t offset1, offset2;
+  enum grub_reiserfs_item_type type1, type2;
+  grub_uint32_t id1, id2;
+  
+  if (! key1 || ! key2)
+    return -2;
+  
+  id1 = grub_le_to_cpu32 (key1->directory_id);
+  id2 = grub_le_to_cpu32 (key2->directory_id);
+  if (id1 < id2)
+    return -1;
+  if (id1 > id2)
+    return 1;
+  
+  id1 = grub_le_to_cpu32 (key1->object_id);
+  id2 = grub_le_to_cpu32 (key2->object_id);
+  if (id1 < id2)
+    return -1;
+  if (id1 > id2)
+    return 1;
+  
+  offset1 = grub_reiserfs_get_key_offset (key1);
+  offset2 = grub_reiserfs_get_key_offset (key2);
+  if (offset1 < offset2)
+    return -1;
+  if (offset1 > offset2)
+    return 1;
+  
+  type1 = grub_reiserfs_get_key_type (key1);
+  type2 = grub_reiserfs_get_key_type (key2);
+  if ((type1 == GRUB_REISERFS_ANY
+       && (type2 == GRUB_REISERFS_DIRECT
+           || type2 == GRUB_REISERFS_INDIRECT))
+      || (type2 == GRUB_REISERFS_ANY
+          && (type1 == GRUB_REISERFS_DIRECT
+              || type1 == GRUB_REISERFS_INDIRECT)))
+    return 0;
+  if (type1 < type2)
+    return -1;
+  if (type1 > type2)
+    return 1;
+  
+  return 0;
+}
+
+/* Find the item identified by KEY in mounted filesystem DATA, and fill ITEM
+   accordingly to what was found.  */
+static grub_err_t
+grub_reiserfs_get_item (struct grub_reiserfs_data *data,
+                        const struct grub_reiserfs_key *key,
+                        struct grub_fshelp_node *item)
+{
+  grub_uint32_t block_number;
+  struct grub_reiserfs_block_header *block_header = 0;
+  struct grub_reiserfs_key *block_key = 0;
+  grub_uint16_t block_size, item_count, current_level;
+  grub_uint16_t i;
+  grub_uint16_t previous_level = ~0;
+  struct grub_reiserfs_item_header *item_headers = 0;
+  
+  if (! data)
+    {
+      grub_error (GRUB_ERR_TEST_FAILURE, "data is NULL");
+      goto fail;
+    }
+
+  if (! key)
+    {
+      grub_error (GRUB_ERR_TEST_FAILURE, "key is NULL");
+      goto fail;
+    }
+
+  if (! item)
+    {
+      grub_error (GRUB_ERR_TEST_FAILURE, "item is NULL");
+      goto fail;
+    }
+  
+  block_size = grub_le_to_cpu16 (data->superblock.block_size);
+  block_number = grub_le_to_cpu32 (data->superblock.root_block);
+#ifdef GRUB_REISERFS_DEBUG
+  grub_printf("Searching for ");
+  grub_reiserfs_print_key (key);
+#endif
+  block_header = grub_malloc (block_size);
+  if (! block_header)
+    goto fail;
+  
+  item->next_offset = 0;
+  do
+    {
+      grub_disk_read (data->disk,
+                      block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
+                      (((grub_off_t) block_number * block_size)
+                       & (GRUB_DISK_SECTOR_SIZE - 1)),
+                      block_size, (char *) block_header);
+      if (grub_errno)
+        goto fail;
+      current_level = grub_le_to_cpu16 (block_header->level);
+      grub_dprintf ("reiserfs_tree", " at level %d\n", current_level);
+      if (current_level >= previous_level)
+        {
+          grub_dprintf ("reiserfs_tree", "level loop detected, aborting\n");
+          grub_error (GRUB_ERR_FILE_READ_ERROR, "level loop");
+          goto fail;
+        }
+      previous_level = current_level;
+      item_count = grub_le_to_cpu16 (block_header->item_count);
+      grub_dprintf ("reiserfs_tree", " number of contained items : %d\n",
+                    item_count);
+      if (current_level > 1)
+        {
+          /* Internal node. Navigate to the child that should contain
+             the searched key.  */
+          struct grub_reiserfs_key *keys
+            = (struct grub_reiserfs_key *) (block_header + 1);
+          struct grub_reiserfs_disk_child *children
+            = ((struct grub_reiserfs_disk_child *)
+               (keys + item_count));
+          
+          for (i = 0;
+               i < item_count
+                 && grub_reiserfs_compare_keys (key, &(keys[i])) >= 0;
+               i++)
+            {
+#ifdef GRUB_REISERFS_DEBUG
+              grub_printf("i %03d/%03d ", i + 1, item_count + 1);
+              grub_reiserfs_print_key (&(keys[i]));
+#endif
+            }
+          block_number = grub_le_to_cpu32 (children[i].block_number);
+         if ((i < item_count) && (key->directory_id == keys[i].directory_id)
+              && (key->object_id == keys[i].object_id))
+           item->next_offset = grub_reiserfs_get_key_offset(&(keys[i]));
+#ifdef GRUB_REISERFS_DEBUG
+          if (i == item_count
+              || grub_reiserfs_compare_keys (key, &(keys[i])) == 0)
+            grub_printf(">");
+          else
+            grub_printf("<");
+          if (i < item_count)
+            {
+              grub_printf (" %03d/%03d ", i + 1, item_count + 1);
+              grub_reiserfs_print_key (&(keys[i]));
+              if (i + 1 < item_count)
+                {
+                  grub_printf ("+ %03d/%03d ", i + 2, item_count);
+                  grub_reiserfs_print_key (&(keys[i + 1]));
+                }
+            }
+          else
+            grub_printf ("Accessing rightmost child at block %d.\n",
+                         block_number);
+#endif
+        }
+      else
+        {
+          /* Leaf node.  Check that the key is actually present.  */
+          item_headers
+            = (struct grub_reiserfs_item_header *) (block_header + 1);
+          for (i = 0;
+               i < item_count
+                 && (grub_reiserfs_compare_keys (key, &(item_headers[i].key))
+                     != 0);
+               i++)
+            {
+#ifdef GRUB_REISERFS_DEBUG
+              if (key->directory_id == item_headers[i].key.directory_id && \
+                  key->object_id == item_headers[i].key.object_id)
+                grub_printf("C");
+              else
+                grub_printf(" ");
+              grub_printf(" %03d/%03d ", i + 1, item_count);
+              grub_reiserfs_print_key (&(item_headers[i].key));
+#endif
+            }
+          if (i < item_count)
+            block_key = &(item_headers[i].key);
+        }
+    }
+  while (current_level > 1);
+
+  item->data = data;
+
+  if (i == item_count || grub_reiserfs_compare_keys (key, block_key))
+    {
+      item->block_number = 0;
+      item->block_position = 0;
+      item->type = GRUB_REISERFS_UNKNOWN;
+#ifdef GRUB_REISERFS_DEBUG
+      grub_printf("Not found.\n");
+#endif
+    }
+  else
+    {
+      item->block_number = block_number;
+      item->block_position = i;
+      item->type = grub_reiserfs_get_key_type (block_key);
+      grub_memcpy (&(item->header), &(item_headers[i]),
+                   sizeof (struct grub_reiserfs_item_header));
+#ifdef GRUB_REISERFS_DEBUG
+      grub_printf ("F %03d/%03d ", i + 1, item_count);
+      grub_reiserfs_print_key (block_key);
+#endif
+    }
+  
+  assert (grub_errno == GRUB_ERR_NONE);
+  grub_free (block_header);
+  return GRUB_ERR_NONE;
+
+ fail:
+  assert (grub_errno != GRUB_ERR_NONE);
+  grub_free (block_header);
+  assert (grub_errno != GRUB_ERR_NONE);
+  return grub_errno;
+}
+
+/* Return the path of the file which is pointed at by symlink NODE.  */
+static char *
+grub_reiserfs_read_symlink (grub_fshelp_node_t node)
+{
+  char *symlink_buffer = 0;
+  grub_uint16_t block_size;
+  grub_disk_addr_t block;
+  grub_off_t offset;
+  grub_size_t len;
+  struct grub_fshelp_node found;
+  struct grub_reiserfs_key key;
+
+  grub_memcpy (&key, &(node->header.key), sizeof (key));
+  grub_reiserfs_set_key_offset (&key, 1);
+  grub_reiserfs_set_key_type (&key, GRUB_REISERFS_DIRECT,
+                              grub_reiserfs_get_key_version (&key));
+
+  if (grub_reiserfs_get_item (node->data, &key, &found) != GRUB_ERR_NONE)
+    goto fail;
+
+  if (found.block_number == 0)
+    goto fail;
+
+  block_size = grub_le_to_cpu16 (node->data->superblock.block_size);
+  len = grub_le_to_cpu16 (found.header.item_size);
+  block = found.block_number * (block_size  >> GRUB_DISK_SECTOR_BITS);
+  offset = grub_le_to_cpu16 (found.header.item_location);
+
+  symlink_buffer = grub_malloc (len + 1);
+  if (! symlink_buffer)
+    goto fail;
+
+  grub_disk_read (node->data->disk, block, offset, len, symlink_buffer);
+  if (grub_errno)
+    goto fail;
+
+  symlink_buffer[len] = 0;
+  return symlink_buffer;
+
+ fail:
+  grub_free (symlink_buffer);
+  return 0;
+}
+
+/* Fill the mounted filesystem structure and return it.  */
+static struct grub_reiserfs_data *
+grub_reiserfs_mount (grub_disk_t disk)
+{
+  struct grub_reiserfs_data *data = 0;
+  data = grub_malloc (sizeof (*data));
+  if (! data)
+    goto fail;
+  grub_disk_read (disk, REISERFS_SUPER_BLOCK_OFFSET / GRUB_DISK_SECTOR_SIZE,
+                  0, sizeof (data->superblock), (char *) &(data->superblock));
+  if (grub_errno)
+    goto fail;
+  if (grub_memcmp (data->superblock.magic_string,
+                   REISERFS_MAGIC_STRING, sizeof (REISERFS_MAGIC_STRING) - 1))
+    {
+      grub_error (GRUB_ERR_BAD_FS, "not a reiserfs filesystem");
+      goto fail;
+    }
+  data->disk = disk;
+  return data;
+
+ fail:
+  /* Disk is too small to contain a ReiserFS.  */
+  if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+    grub_error (GRUB_ERR_BAD_FS, "not a reiserfs filesystem");
+
+  grub_free (data);
+  return 0;
+}
+
+/* Call HOOK for each file in directory ITEM.  */
+static int
+grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
+                           int NESTED_FUNC_ATTR
+                           (*hook) (const char *filename,
+                                    enum grub_fshelp_filetype filetype,
+                                    grub_fshelp_node_t node))
+{
+  struct grub_reiserfs_data *data = item->data;
+  struct grub_reiserfs_block_header *block_header = 0;
+  grub_uint16_t block_size, block_position;
+  grub_uint32_t block_number;
+  grub_uint64_t next_offset = item->next_offset;
+  int ret = 0;
+
+  if (item->type != GRUB_REISERFS_DIRECTORY)
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                  "grub_reiserfs_iterate_dir called on a non-directory item");
+      goto fail;
+    }
+  block_size = grub_le_to_cpu16 (data->superblock.block_size);
+  block_header = grub_malloc (block_size);
+  if (! block_header)
+    goto fail;
+  block_number = item->block_number;
+  block_position = item->block_position;
+  grub_dprintf ("reiserfs", "Iterating directory...\n");
+  do
+    {
+      struct grub_reiserfs_directory_header *directory_headers;
+      struct grub_fshelp_node directory_item;
+      grub_uint16_t entry_count, entry_number;
+      struct grub_reiserfs_item_header *item_headers;
+      
+      grub_disk_read (data->disk,
+                      block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
+                      (((grub_off_t) block_number * block_size)
+                       & (GRUB_DISK_SECTOR_SIZE - 1)),
+                      block_size, (char *) block_header);
+      if (grub_errno)
+        goto fail;
+
+#if 0
+      if (grub_le_to_cpu16 (block_header->level) != 1)
+        {
+          grub_error (GRUB_ERR_TEST_FAILURE,
+                      "reiserfs: block %d is not a leaf block",
+                      block_number);
+          goto fail;
+        }
+#endif
+      
+      item_headers = (struct grub_reiserfs_item_header *) (block_header + 1);
+      directory_headers
+        = ((struct grub_reiserfs_directory_header *)
+           ((char *) block_header
+            + grub_le_to_cpu16 (item_headers[block_position].item_location)));
+      entry_count
+        = grub_le_to_cpu16 (item_headers[block_position].u.entry_count);
+      for (entry_number = 0; entry_number < entry_count; entry_number++)
+        {
+          struct grub_reiserfs_directory_header *directory_header
+            = &directory_headers[entry_number];
+          grub_uint16_t entry_state
+            = grub_le_to_cpu16 (directory_header->state);
+          
+          if (entry_state & GRUB_REISERFS_VISIBLE_MASK)
+            {
+              grub_fshelp_node_t entry_item;
+              struct grub_reiserfs_key entry_key;
+              enum grub_reiserfs_item_type entry_type;
+              char *entry_name;
+
+              entry_name = (((char *) directory_headers)
+                            + grub_le_to_cpu16 (directory_header->location));
+              entry_key.directory_id = directory_header->directory_id;
+              entry_key.object_id = directory_header->object_id;
+              entry_key.u.v2.offset_type = 0;
+              grub_reiserfs_set_key_type (&entry_key, GRUB_REISERFS_DIRECTORY,
+                                          2);
+              grub_reiserfs_set_key_offset (&entry_key, 1);
+
+              entry_item = grub_malloc (sizeof (*entry_item));
+              if (! entry_item)
+                goto fail;
+              
+              if (grub_reiserfs_get_item (data, &entry_key, entry_item)
+                  != GRUB_ERR_NONE)
+                {
+                  grub_free (entry_item);
+                  goto fail;
+                }
+              
+              if (entry_item->type == GRUB_REISERFS_DIRECTORY)
+                entry_type = GRUB_FSHELP_DIR;
+              else
+                {
+                  grub_uint32_t entry_block_number;
+                  /* Order is very important here.
+                     First set the offset to 0 using current key version.
+                     Then change the key type, which influes on key version
+                     detection.  */
+                  grub_reiserfs_set_key_offset (&entry_key, 0);
+                  grub_reiserfs_set_key_type (&entry_key, GRUB_REISERFS_STAT,
+                                              2);
+                  if (grub_reiserfs_get_item (data, &entry_key, entry_item)
+                      != GRUB_ERR_NONE)
+                    {
+                      grub_free (entry_item);
+                      goto fail;
+                    }
+
+                  if (entry_item->block_number != 0)
+                    {
+                      grub_uint16_t entry_version;
+                      entry_version
+                        = grub_le_to_cpu16 (entry_item->header.version);
+                      entry_block_number = entry_item->block_number;
+#if 0
+                     grub_dprintf ("reiserfs",
+                                    "version %04x block %08x (%08x) position %08x\n",
+                                    entry_version, entry_block_number,
+                                    ((grub_disk_addr_t) entry_block_number * block_size) / GRUB_DISK_SECTOR_SIZE,
+                                    grub_le_to_cpu16 (entry_item->header.item_location));
+#endif
+                      if (entry_version == 0) /* Version 1 stat item. */
+                        {
+                          struct grub_reiserfs_stat_item_v1 entry_v1_stat;
+                          grub_disk_read (data->disk,
+                                          entry_block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
+                                          grub_le_to_cpu16 (entry_item->header.item_location),
+                                          sizeof (entry_v1_stat),
+                                          (char *) &entry_v1_stat);
+                          if (grub_errno)
+                            goto fail;
+#if 0
+                         grub_dprintf ("reiserfs",
+                                        "%04x %04x %04x %04x %08x %08x | %08x %08x %08x %08x\n",
+                                        grub_le_to_cpu16 (entry_v1_stat.mode),
+                                        grub_le_to_cpu16 (entry_v1_stat.hardlink_count),
+                                        grub_le_to_cpu16 (entry_v1_stat.uid),
+                                        grub_le_to_cpu16 (entry_v1_stat.gid),
+                                        grub_le_to_cpu32 (entry_v1_stat.size),
+                                        grub_le_to_cpu32 (entry_v1_stat.atime),
+                                        grub_le_to_cpu32 (entry_v1_stat.mtime),
+                                        grub_le_to_cpu32 (entry_v1_stat.ctime),
+                                        grub_le_to_cpu32 (entry_v1_stat.rdev),
+                                        grub_le_to_cpu32 (entry_v1_stat.first_direct_byte));
+                         grub_dprintf ("reiserfs",
+                                        "%04x %04x %04x %04x %08x %08x | %08x %08x %08x %08x\n",
+                                        entry_v1_stat.mode,
+                                        entry_v1_stat.hardlink_count,
+                                        entry_v1_stat.uid,
+                                        entry_v1_stat.gid,
+                                        entry_v1_stat.size,
+                                        entry_v1_stat.atime,
+                                        entry_v1_stat.mtime,
+                                        entry_v1_stat.ctime,
+                                        entry_v1_stat.rdev,
+                                        entry_v1_stat.first_direct_byte);
+#endif
+                          if ((grub_le_to_cpu16 (entry_v1_stat.mode) & S_IFLNK)
+                              == S_IFLNK)
+                            entry_type = GRUB_FSHELP_SYMLINK;
+                          else
+                            entry_type = GRUB_FSHELP_REG;
+                        }
+                      else
+                        {
+                          struct grub_reiserfs_stat_item_v2 entry_v2_stat;
+                          grub_disk_read (data->disk,
+                                          entry_block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
+                                          grub_le_to_cpu16 (entry_item->header.item_location),
+                                          sizeof (entry_v2_stat),
+                                          (char *) &entry_v2_stat);
+                          if (grub_errno)
+                            goto fail;
+#if 0
+                         grub_dprintf ("reiserfs",
+                                        "%04x %04x %08x %08x%08x | %08x %08x %08x %08x | %08x %08x %08x\n",
+                                        grub_le_to_cpu16 (entry_v2_stat.mode),
+                                        grub_le_to_cpu16 (entry_v2_stat.reserved),
+                                        grub_le_to_cpu32 (entry_v2_stat.hardlink_count),
+                                        (unsigned int) (grub_le_to_cpu64 (entry_v2_stat.size) >> 32),
+                                        (unsigned int) (grub_le_to_cpu64 (entry_v2_stat.size) && 0xFFFFFFFF),
+                                        grub_le_to_cpu32 (entry_v2_stat.uid),
+                                        grub_le_to_cpu32 (entry_v2_stat.gid),
+                                        grub_le_to_cpu32 (entry_v2_stat.atime),
+                                        grub_le_to_cpu32 (entry_v2_stat.mtime),
+                                        grub_le_to_cpu32 (entry_v2_stat.ctime),
+                                        grub_le_to_cpu32 (entry_v2_stat.blocks),
+                                        grub_le_to_cpu32 (entry_v2_stat.first_direct_byte));
+                         grub_dprintf ("reiserfs",
+                                        "%04x %04x %08x %08x%08x | %08x %08x %08x %08x | %08x %08x %08x\n",
+                                        entry_v2_stat.mode,
+                                        entry_v2_stat.reserved,
+                                        entry_v2_stat.hardlink_count,
+                                        (unsigned int) (entry_v2_stat.size >> 32),
+                                        (unsigned int) (entry_v2_stat.size && 0xFFFFFFFF),
+                                        entry_v2_stat.uid,
+                                        entry_v2_stat.gid,
+                                        entry_v2_stat.atime,
+                                        entry_v2_stat.mtime,
+                                        entry_v2_stat.ctime,
+                                        entry_v2_stat.blocks,
+                                        entry_v2_stat.first_direct_byte);
+#endif
+                          if ((grub_le_to_cpu16 (entry_v2_stat.mode) & S_IFLNK)
+                              == S_IFLNK)
+                            entry_type = GRUB_FSHELP_SYMLINK;
+                          else
+                            entry_type = GRUB_FSHELP_REG;
+                        }
+                    }
+                  else
+                    {
+                      /* Pseudo file ".." never has stat block.  */
+                      if (grub_strcmp (entry_name, ".."))
+                        grub_dprintf ("reiserfs",
+                                      "Warning : %s has no stat block !\n",
+                                      entry_name);
+                      grub_free (entry_item);
+                      continue;
+                    }
+                }
+              if (hook (entry_name, entry_type, entry_item))
+                {
+                  grub_dprintf ("reiserfs", "Found : %s, type=%d\n",
+                                entry_name, entry_type);
+                  ret = 1;
+                  goto found;
+                }
+
+              *entry_name = 0; /* Make sure next entry name (which is just
+                                  before this one in disk order) stops before
+                                  the current one.  */
+            }
+        }
+      
+      if (next_offset == 0)
+        break;
+
+      grub_reiserfs_set_key_offset (&(item_headers[block_position].key),
+                                    next_offset);
+      if (grub_reiserfs_get_item (data, &(item_headers[block_position].key),
+                                  &directory_item) != GRUB_ERR_NONE)
+        goto fail;
+      block_number = directory_item.block_number;
+      block_position = directory_item.block_position;
+      next_offset = directory_item.next_offset;
+    }
+  while (block_number);
+
+ found:
+  assert (grub_errno == GRUB_ERR_NONE);
+  grub_free (block_header);
+  return ret;
+ fail:
+  assert (grub_errno != GRUB_ERR_NONE);
+  grub_free (block_header);
+  return 0;
+}
+
+/****************************************************************************/
+/* grub api functions */
+/****************************************************************************/
+
+/* Open a file named NAME and initialize FILE.  */
+static grub_err_t
+grub_reiserfs_open (struct grub_file *file, const char *name)
+{
+  struct grub_reiserfs_data *data = 0;
+  struct grub_fshelp_node root, *found = 0, info;
+  struct grub_reiserfs_key key;
+  grub_uint32_t block_number;
+  grub_uint16_t entry_version, block_size, entry_location;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  data = grub_reiserfs_mount (file->device->disk);
+  if (! data)
+    goto fail;
+  block_size = grub_le_to_cpu16 (data->superblock.block_size);
+  key.directory_id = grub_cpu_to_le32 (1);
+  key.object_id = grub_cpu_to_le32 (2);
+  key.u.v2.offset_type = 0;
+  grub_reiserfs_set_key_type (&key, GRUB_REISERFS_DIRECTORY, 2);
+  grub_reiserfs_set_key_offset (&key, 1);
+  if (grub_reiserfs_get_item (data, &key, &root) != GRUB_ERR_NONE)
+    goto fail;
+  if (root.block_number == 0)
+    {
+      grub_error (GRUB_ERR_BAD_FS, "Unable to find root item");
+      goto fail; /* Should never happen since checked at mount.  */
+    }
+  grub_fshelp_find_file (name, &root, &found,
+                         grub_reiserfs_iterate_dir,
+                         grub_reiserfs_read_symlink, GRUB_FSHELP_REG);
+  if (grub_errno)
+    goto fail;
+  key.directory_id = found->header.key.directory_id;
+  key.object_id = found->header.key.object_id;
+  grub_reiserfs_set_key_type (&key, GRUB_REISERFS_STAT, 2);
+  grub_reiserfs_set_key_offset (&key, 0);
+  if (grub_reiserfs_get_item (data, &key, &info) != GRUB_ERR_NONE)
+    goto fail;
+  if (info.block_number == 0)
+    {
+      grub_error (GRUB_ERR_BAD_FS, "Unable to find searched item");
+      goto fail;
+    }
+  entry_version = grub_le_to_cpu16 (info.header.version);
+  entry_location = grub_le_to_cpu16 (info.header.item_location);
+  block_number = info.block_number;
+  if (entry_version == 0) /* Version 1 stat item. */
+    {
+      struct grub_reiserfs_stat_item_v1 entry_v1_stat;
+      grub_disk_read (data->disk,
+                      block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
+                      entry_location
+                      + (((grub_off_t) block_number * block_size)
+                         & (GRUB_DISK_SECTOR_SIZE - 1)),
+                      sizeof (entry_v1_stat), (char *) &entry_v1_stat);
+      if (grub_errno)
+        goto fail;
+      file->size = (grub_off_t) grub_le_to_cpu64 (entry_v1_stat.size);
+    }
+  else
+    {
+      struct grub_reiserfs_stat_item_v2 entry_v2_stat;
+      grub_disk_read (data->disk,
+                      block_number * (block_size  >> GRUB_DISK_SECTOR_BITS),
+                      entry_location
+                      + (((grub_off_t) block_number * block_size)
+                         & (GRUB_DISK_SECTOR_SIZE - 1)),
+                      sizeof (entry_v2_stat), (char *) &entry_v2_stat);
+      if (grub_errno)
+        goto fail;
+      file->size = (grub_off_t) grub_le_to_cpu64 (entry_v2_stat.size);
+    }
+  grub_dprintf ("reiserfs", "file size : %d (%08x%08x)\n",
+                (unsigned int) file->size,
+                (unsigned int) (file->size >> 32), (unsigned int) file->size);
+  file->offset = 0;
+  file->data = found;
+  return GRUB_ERR_NONE;
+
+ fail:
+  assert (grub_errno != GRUB_ERR_NONE);
+  grub_free (found);
+  grub_free (data);
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+  return grub_errno;
+}
+
+static grub_ssize_t
+grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  unsigned int indirect_block, indirect_block_count;
+  struct grub_reiserfs_key key;
+  struct grub_fshelp_node *node = file->data;
+  struct grub_reiserfs_data *data = node->data;
+  struct grub_fshelp_node found;
+  grub_uint16_t block_size = grub_le_to_cpu16 (data->superblock.block_size);
+  grub_uint16_t item_size;
+  grub_uint32_t *indirect_block_ptr = 0;
+  grub_uint64_t current_key_offset = 1;
+  grub_off_t initial_position, current_position, final_position, length;
+  grub_disk_addr_t block;
+  grub_off_t offset;
+
+  if (file->offset >= file->size)
+    return 0;
+
+  key.directory_id = node->header.key.directory_id;
+  key.object_id = node->header.key.object_id;
+  key.u.v2.offset_type = 0;
+  grub_reiserfs_set_key_type (&key, GRUB_REISERFS_ANY, 2);
+  initial_position = file->offset;
+  current_position = 0;
+  final_position = MIN (len + initial_position, file->size);
+  grub_dprintf ("reiserfs",
+               "Reading from %lld to %lld (%lld instead of requested %ld)\n",
+               (unsigned long long) initial_position,
+               (unsigned long long) final_position,
+               (unsigned long long) (final_position - initial_position),
+               (unsigned long) len);
+  while (current_position < final_position)
+    {
+      grub_reiserfs_set_key_offset (&key, current_key_offset);
+    
+      if (grub_reiserfs_get_item (data, &key, &found) != GRUB_ERR_NONE)
+        goto fail;
+      if (found.block_number == 0)
+        goto fail;
+      item_size = grub_le_to_cpu16 (found.header.item_size);
+      switch (found.type)
+        {
+        case GRUB_REISERFS_DIRECT:
+          block = found.block_number * (block_size  >> GRUB_DISK_SECTOR_BITS);
+          grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block);
+          if (initial_position < current_position + item_size)
+            {
+              offset = MAX ((signed) (initial_position - current_position), 0);
+              length = (MIN (item_size, final_position - current_position)
+                        - offset);
+              grub_dprintf ("reiserfs",
+                            "Reading direct block %u from %u to %u...\n",
+                            (unsigned) block, (unsigned) offset,
+                            (unsigned) (offset + length));
+              found.data->disk->read_hook = file->read_hook;
+              grub_disk_read (found.data->disk,
+                              block,
+                              offset
+                              + grub_le_to_cpu16 (found.header.item_location),
+                              length, buf);
+              found.data->disk->read_hook = 0;
+              if (grub_errno)
+                goto fail;
+              buf += length;
+              current_position += offset + length;
+            }
+          else
+            current_position += item_size;
+          break;
+        case GRUB_REISERFS_INDIRECT:
+          indirect_block_count = item_size / sizeof (*indirect_block_ptr);
+          indirect_block_ptr = grub_malloc (item_size);
+          if (! indirect_block_ptr)
+            goto fail;
+          grub_disk_read (found.data->disk,
+                          found.block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
+                          grub_le_to_cpu16 (found.header.item_location),
+                          item_size, (char *) indirect_block_ptr);
+          if (grub_errno)
+            goto fail;
+          found.data->disk->read_hook = file->read_hook;
+          for (indirect_block = 0;
+               indirect_block < indirect_block_count
+                 && current_position < final_position;
+               indirect_block++)
+            {
+              block = grub_le_to_cpu32 (indirect_block_ptr[indirect_block]) *
+                      (block_size >> GRUB_DISK_SECTOR_BITS);
+              grub_dprintf ("reiserfs_blocktype", "I: %u\n", (unsigned) block);
+              if (current_position + block_size >= initial_position)
+                {
+                  offset = MAX ((signed) (initial_position - current_position),
+                                0);
+                  length = (MIN (block_size, final_position - current_position)
+                            - offset);
+                  grub_dprintf ("reiserfs",
+                                "Reading indirect block %u from %u to %u...\n",
+                                (unsigned) block, (unsigned) offset,
+                                (unsigned) (offset + length));
+#if 0
+                  grub_dprintf ("reiserfs",
+                                "\nib=%04d/%04d, ip=%d, cp=%d, fp=%d, off=%d, l=%d, tl=%d\n",
+                                indirect_block + 1, indirect_block_count,
+                                initial_position, current_position,
+                                final_position, offset, length, len);
+#endif
+                  grub_disk_read (found.data->disk, block, offset, length, buf);
+                  if (grub_errno)
+                    goto fail;
+                  buf += length;
+                  current_position += offset + length;
+                }
+              else
+                current_position += block_size;
+            }
+          found.data->disk->read_hook = 0;
+          grub_free (indirect_block_ptr);
+          indirect_block_ptr = 0;
+          break;
+        default:
+          goto fail;
+        }
+      current_key_offset = current_position + 1;
+    }
+  
+  grub_dprintf ("reiserfs",
+               "Have successfully read %lld bytes (%ld requested)\n",
+               (unsigned long long) (current_position - initial_position),
+               (unsigned long) len);
+  return current_position - initial_position;
+/*
+  switch (found.type)
+    {
+      case GRUB_REISERFS_DIRECT:
+        read_length = MIN (len, item_size - file->offset);
+        grub_disk_read (found.data->disk,
+                        (found.block_number * block_size) / GRUB_DISK_SECTOR_SIZE,
+                        grub_le_to_cpu16 (found.header.item_location) + file->offset,
+                        read_length, buf);
+        if (grub_errno)
+          goto fail;
+        break;
+      case GRUB_REISERFS_INDIRECT:
+        indirect_block_count = item_size / sizeof (*indirect_block_ptr);
+        indirect_block_ptr = grub_malloc (item_size);
+        if (!indirect_block_ptr)
+          goto fail;
+        grub_disk_read (found.data->disk,
+                        (found.block_number * block_size) / GRUB_DISK_SECTOR_SIZE,
+                        grub_le_to_cpu16 (found.header.item_location),
+                        item_size, (char *) indirect_block_ptr);
+        if (grub_errno)
+          goto fail;
+        len = MIN (len, file->size - file->offset);
+        for (indirect_block = file->offset / block_size;
+             indirect_block < indirect_block_count && read_length < len;
+             indirect_block++)
+          {
+            read = MIN (block_size, len - read_length);
+            grub_disk_read (found.data->disk,
+                            (grub_le_to_cpu32 (indirect_block_ptr[indirect_block]) * block_size) / GRUB_DISK_SECTOR_SIZE,
+                            file->offset % block_size, read,
+                            ((void *) buf) + read_length);
+            if (grub_errno)
+              goto fail;
+            read_length += read;
+          }
+        grub_free (indirect_block_ptr);
+        break;
+      default:
+        goto fail;
+    }
+
+  return read_length;*/
+
+ fail:
+  grub_free (indirect_block_ptr);
+  return 0;
+}
+
+/* Close the file FILE.  */
+static grub_err_t
+grub_reiserfs_close (grub_file_t file)
+{
+  struct grub_fshelp_node *node = file->data;
+  struct grub_reiserfs_data *data = node->data;
+
+  grub_free (data);
+  grub_free (node);
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+  return GRUB_ERR_NONE;
+}
+
+/* Call HOOK with each file under DIR.  */
+static grub_err_t
+grub_reiserfs_dir (grub_device_t device, const char *path,
+                   int (*hook) (const char *filename, int dir))
+{
+  struct grub_reiserfs_data *data = 0;
+  struct grub_fshelp_node root, *found;
+  struct grub_reiserfs_key root_key;
+
+  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)
+    {
+      grub_free (node);
+      
+      if (filetype == GRUB_FSHELP_DIR)
+        return hook (filename, 1);
+      else
+        return hook (filename, 0);
+    }
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  data = grub_reiserfs_mount (device->disk);
+  if (! data)
+    goto fail;
+  root_key.directory_id = grub_cpu_to_le32 (1);
+  root_key.object_id = grub_cpu_to_le32 (2);
+  root_key.u.v2.offset_type = 0;
+  grub_reiserfs_set_key_type (&root_key, GRUB_REISERFS_DIRECTORY, 2);
+  grub_reiserfs_set_key_offset (&root_key, 1);
+  if (grub_reiserfs_get_item (data, &root_key, &root) != GRUB_ERR_NONE)
+    goto fail;
+  if (root.block_number == 0)
+    {
+      grub_error(GRUB_ERR_BAD_FS, "Root not found");
+      goto fail;
+    }
+  grub_fshelp_find_file (path, &root, &found, grub_reiserfs_iterate_dir,
+                         grub_reiserfs_read_symlink, GRUB_FSHELP_DIR);
+  if (grub_errno)
+    goto fail;
+  grub_reiserfs_iterate_dir (found, iterate);
+  grub_free (data);
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+  return GRUB_ERR_NONE;
+
+ fail:
+  grub_free (data);
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+  return grub_errno;
+}
+
+/* Return the label of the device DEVICE in LABEL.  The label is
+   returned in a grub_malloc'ed buffer and should be freed by the
+   caller.  */
+static grub_err_t
+grub_reiserfs_label (grub_device_t device, char **label)
+{
+  *label = grub_malloc (REISERFS_MAX_LABEL_LENGTH);
+  if (*label)
+    {
+      grub_disk_read (device->disk,
+                      REISERFS_SUPER_BLOCK_OFFSET / GRUB_DISK_SECTOR_SIZE,
+                      REISERFS_LABEL_OFFSET, REISERFS_MAX_LABEL_LENGTH,
+                      *label);
+    }
+  return grub_errno;
+}
+
+static grub_err_t
+grub_reiserfs_uuid (grub_device_t device, char **uuid)
+{
+  struct grub_reiserfs_data *data;
+  grub_disk_t disk = device->disk;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_reiserfs_mount (disk);
+  if (data)
+    {
+      *uuid = grub_malloc (sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"));
+      grub_sprintf (*uuid, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
+                   grub_be_to_cpu16 (data->superblock.uuid[0]), grub_be_to_cpu16 (data->superblock.uuid[1]),
+                   grub_be_to_cpu16 (data->superblock.uuid[2]), grub_be_to_cpu16 (data->superblock.uuid[3]),
+                   grub_be_to_cpu16 (data->superblock.uuid[4]), grub_be_to_cpu16 (data->superblock.uuid[5]),
+                   grub_be_to_cpu16 (data->superblock.uuid[6]), grub_be_to_cpu16 (data->superblock.uuid[7]));
+    }
+  else
+    *uuid = NULL;
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+}
+
+static struct grub_fs grub_reiserfs_fs =
+  {
+    .name = "reiserfs",
+    .dir = grub_reiserfs_dir,
+    .open = grub_reiserfs_open,
+    .read = grub_reiserfs_read,
+    .close = grub_reiserfs_close,
+    .label = grub_reiserfs_label,
+    .uuid = grub_reiserfs_uuid,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(reiserfs)
+{
+  grub_fs_register (&grub_reiserfs_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(reiserfs)
+{
+  grub_fs_unregister (&grub_reiserfs_fs);
+}
diff --git a/fs/sfs.c b/fs/sfs.c
new file mode 100644 (file)
index 0000000..910bbf2
--- /dev/null
+++ b/fs/sfs.c
@@ -0,0 +1,621 @@
+/* sfs.c - Amiga Smart FileSystem.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2006,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/>.
+ */
+
+#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>
+
+/* The common header for a block.  */
+struct grub_sfs_bheader
+{
+  grub_uint8_t magic[4];
+  grub_uint32_t chksum;
+  grub_uint32_t ipointtomyself;
+} __attribute__ ((packed));
+
+/* The sfs rootblock.  */
+struct grub_sfs_rblock
+{
+  struct grub_sfs_bheader header;
+  grub_uint32_t version;
+  grub_uint8_t unused1[36];
+  grub_uint32_t blocksize;
+  grub_uint8_t unused2[40];
+  grub_uint8_t unused3[8];
+  grub_uint32_t rootobject;
+  grub_uint32_t btree;
+} __attribute__ ((packed));
+
+/* A SFS object container.  */
+struct grub_sfs_obj
+{
+  grub_uint8_t unused1[4];
+  grub_uint32_t nodeid;
+  grub_uint8_t unused2[4];
+  union
+  {
+    struct
+    {
+      grub_uint32_t first_block;
+      grub_uint32_t size;
+    } file __attribute__ ((packed));
+    struct
+    {
+      grub_uint32_t hashtable;
+      grub_uint32_t dir_objc;
+    } dir __attribute__ ((packed));
+  } file_dir;
+  grub_uint8_t unused3[4];
+  grub_uint8_t type;
+  grub_uint8_t filename[1];
+  grub_uint8_t comment[1];
+} __attribute__ ((packed));
+
+#define        GRUB_SFS_TYPE_DELETED   32
+#define        GRUB_SFS_TYPE_SYMLINK   64
+#define        GRUB_SFS_TYPE_DIR       128
+
+/* A SFS object container.  */
+struct grub_sfs_objc
+{
+  struct grub_sfs_bheader header;
+  grub_uint32_t parent;
+  grub_uint32_t next;
+  grub_uint32_t prev;
+  /* The amount of objects depends on the blocksize.  */
+  struct grub_sfs_obj objects[1];
+} __attribute__ ((packed));
+
+struct grub_sfs_btree_node
+{
+  grub_uint32_t key;
+  grub_uint32_t data;
+} __attribute__ ((packed));
+
+struct grub_sfs_btree_extent
+{
+  grub_uint32_t key;
+  grub_uint32_t next;
+  grub_uint32_t prev;
+  grub_uint16_t size;
+} __attribute__ ((packed));
+
+struct grub_sfs_btree
+{
+  struct grub_sfs_bheader header;
+  grub_uint16_t nodes;
+  grub_uint8_t leaf;
+  grub_uint8_t nodesize;
+  /* Normally this can be kind of node, but just extents are
+     supported.  */
+  struct grub_sfs_btree_node node[1];
+} __attribute__ ((packed));
+
+\f
+
+struct grub_fshelp_node
+{
+  struct grub_sfs_data *data;
+  int block;
+  int size;
+};
+
+/* Information about a "mounted" sfs filesystem.  */
+struct grub_sfs_data
+{
+  struct grub_sfs_rblock rblock;
+  struct grub_fshelp_node diropen;
+  grub_disk_t disk;
+
+  /* Blocksize in sectors.  */
+  unsigned int blocksize;
+
+  /* Label of the filesystem.  */
+  char *label;
+};
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+\f
+/* Lookup the extent starting with BLOCK in the filesystem described
+   by DATA.  Return the extent size in SIZE and the following extent
+   in NEXTEXT.  */
+static grub_err_t
+grub_sfs_read_extent (struct grub_sfs_data *data, unsigned int block,
+                     int *size, int *nextext)
+{
+  char *treeblock;
+  struct grub_sfs_btree *tree;
+  int i;
+  int next;
+  int prev;
+
+  treeblock = grub_malloc (data->blocksize);
+  if (!block)
+    return 0;
+
+  next = grub_be_to_cpu32 (data->rblock.btree);
+  tree = (struct grub_sfs_btree *) treeblock;
+
+  /* Handle this level in the btree.  */
+  do
+    {
+      prev = 0;
+
+      grub_disk_read (data->disk, next, 0, data->blocksize, treeblock);
+      if (grub_errno)
+       {
+         grub_free (treeblock);
+         return grub_errno;
+       }
+
+      for (i = 0; i < grub_be_to_cpu16 (tree->nodes); i++)
+       {
+
+#define EXTNODE(tree, index)                                           \
+       ((struct grub_sfs_btree_node *) (((char *) &(tree)->node[0])    \
+                                        + (index) * (tree)->nodesize))
+
+         /* Follow the tree down to the leaf level.  */
+         if ((grub_be_to_cpu32 (EXTNODE(tree, i)->key) >= block)
+             && !tree->leaf)
+           {
+             next = grub_be_to_cpu32 (EXTNODE (tree, i - 1)->data);
+             break;
+           }
+
+         /* In case the last node is reached just use that one, it is
+            the right match.  */
+         if (i + 1 == grub_be_to_cpu16 (tree->nodes) && !tree->leaf)
+           {
+             next = grub_be_to_cpu32 (EXTNODE (tree, i)->data);
+             break;
+           }
+
+         /* If the leaf level is reached, just find the correct extent.  */
+         if (grub_be_to_cpu32 (EXTNODE (tree, i)->key) == block && tree->leaf)
+           {
+             struct grub_sfs_btree_extent *extent;
+             extent = (struct grub_sfs_btree_extent *) EXTNODE (tree, i);
+
+             /* We found a correct leaf.  */
+             *size = grub_be_to_cpu16 (extent->size);
+             *nextext = grub_be_to_cpu32 (extent->next);
+             
+             grub_free (treeblock);
+             return 0;
+           }
+
+#undef EXTNODE
+
+       }
+    } while (!tree->leaf);
+
+  grub_free (treeblock);
+
+  return grub_error (GRUB_ERR_FILE_READ_ERROR, "SFS extent not found");
+}
+
+static grub_disk_addr_t
+grub_sfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
+{
+  int blk = node->block;
+  int size = 0;
+  int next = 0;
+
+  while (blk)
+    {
+      grub_err_t err;
+
+      /* In case of the first block we don't have to lookup the
+        extent, the minimum size is always 1.  */
+      if (fileblock == 0)
+       return blk;
+
+      err = grub_sfs_read_extent (node->data, blk, &size, &next);
+      if (err)
+       return 0;
+
+      if (fileblock < (unsigned int) size)
+       return fileblock + blk;
+
+      fileblock -= size;
+
+      blk = next;
+    }
+
+  grub_error (GRUB_ERR_FILE_READ_ERROR,
+             "reading a SFS block outside the extent");
+
+  return 0;
+}
+
+
+/* Read LEN bytes from the file described by DATA starting with byte
+   POS.  Return the amount of read bytes in READ.  */
+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)
+{
+  return grub_fshelp_read_file (node->data->disk, node, read_hook,
+                               pos, len, buf, grub_sfs_read_block,
+                               node->size, 0);
+}
+
+
+static struct grub_sfs_data *
+grub_sfs_mount (grub_disk_t disk)
+{
+  struct grub_sfs_data *data;
+  struct grub_sfs_objc *rootobjc;
+  char *rootobjc_data = 0;
+  unsigned int blk;
+
+  data = grub_malloc (sizeof (*data));
+  if (!data)
+    return 0;
+
+  /* Read the rootblock.  */
+  grub_disk_read (disk, 0, 0, sizeof (struct grub_sfs_rblock),
+                 (char *) &data->rblock);
+  if (grub_errno)
+    goto fail;
+
+  /* Make sure this is a sfs filesystem.  */
+  if (grub_strncmp ((char *) (data->rblock.header.magic), "SFS", 4))
+    {
+      grub_error (GRUB_ERR_BAD_FS, "not a sfs filesystem");
+      goto fail;
+    }
+
+  data->blocksize = grub_be_to_cpu32 (data->rblock.blocksize);
+  rootobjc_data = grub_malloc (data->blocksize);
+  if (! rootobjc_data)
+    goto fail;
+
+  /* Read the root object container.  */
+  grub_disk_read (disk, grub_be_to_cpu32 (data->rblock.rootobject), 0,
+                 data->blocksize, rootobjc_data);
+  if (grub_errno)
+    goto fail;
+
+  rootobjc = (struct grub_sfs_objc *) rootobjc_data;
+
+  blk = grub_be_to_cpu32 (rootobjc->objects[0].file_dir.dir.dir_objc);
+  data->diropen.size = 0;
+  data->diropen.block = blk;
+  data->diropen.data = data;
+  data->disk = disk;
+  data->label = grub_strdup ((char *) (rootobjc->objects[0].filename));
+
+  return data;
+
+ fail:
+  if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+    grub_error (GRUB_ERR_BAD_FS, "not an sfs filesystem");
+
+  grub_free (data);
+  grub_free (rootobjc_data);
+  return 0;
+}
+
+
+static char *
+grub_sfs_read_symlink (grub_fshelp_node_t node)
+{
+  struct grub_sfs_data *data = node->data;
+  char *symlink;
+  char *block;
+
+  block = grub_malloc (data->blocksize);
+  if (!block)
+    return 0;
+
+  grub_disk_read (data->disk, node->block, 0, data->blocksize, block);
+  if (grub_errno)
+    {
+      grub_free (block);
+      return 0;
+    }
+
+  /* This is just a wild guess, but it always worked for me.  How the
+     SLNK block looks like is not documented in the SFS docs.  */
+  symlink = grub_strdup (&block[24]);
+  grub_free (block);
+  if (!symlink)
+    return 0;
+
+  return symlink;
+}
+
+static int
+grub_sfs_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))
+{
+  struct grub_fshelp_node *node = 0;
+  struct grub_sfs_data *data = dir->data;
+  char *objc_data;
+  struct grub_sfs_objc *objc;
+  unsigned int next = dir->block;
+  int pos;
+
+  auto int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block,
+                                                 int size, int type);
+
+  int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block,
+                                            int size, int type)
+    {
+      node = grub_malloc (sizeof (*node));
+      if (!node)
+       return 1;
+
+      node->data = data;
+      node->size = size;
+      node->block = block;
+      
+      return hook (name, type, node);
+    }
+
+  objc_data = grub_malloc (data->blocksize);
+  if (!objc_data)
+    goto fail;
+
+  /* The Object container can consist of multiple blocks, iterate over
+     every block.  */
+  while (next)
+    {
+      grub_disk_read (data->disk, next, 0, data->blocksize, objc_data);
+      if (grub_errno)
+       goto fail;
+
+      objc = (struct grub_sfs_objc *) objc_data;
+
+      pos = (char *) &objc->objects[0] - (char *) objc;
+
+      /* Iterate over all entries in this block.  */
+      while (pos + sizeof (struct grub_sfs_obj) < data->blocksize)
+       {
+         struct grub_sfs_obj *obj;
+         obj = (struct grub_sfs_obj *) ((char *) objc + pos);
+         char *filename = (char *) (obj->filename);
+         int len;
+         enum grub_fshelp_filetype type;
+         unsigned int block;
+
+         /* The filename and comment dynamically increase the size of
+            the object.  */
+         len = grub_strlen (filename);
+         len += grub_strlen (filename + len + 1);
+
+         pos += sizeof (*obj) + len;
+         /* Round up to a multiple of two bytes.  */
+         pos = ((pos + 1) >> 1) << 1;
+
+         if (grub_strlen (filename) == 0)
+           continue;
+
+         /* First check if the file was not deleted.  */
+         if (obj->type & GRUB_SFS_TYPE_DELETED)
+           continue;
+         else if (obj->type & GRUB_SFS_TYPE_SYMLINK)
+           type = GRUB_FSHELP_SYMLINK;
+         else if (obj->type & GRUB_SFS_TYPE_DIR)
+           type = GRUB_FSHELP_DIR;
+         else
+           type = GRUB_FSHELP_REG;
+
+         if (type == GRUB_FSHELP_DIR)
+           block = grub_be_to_cpu32 (obj->file_dir.dir.dir_objc);
+         else
+           block = grub_be_to_cpu32 (obj->file_dir.file.first_block);
+
+         if (grub_sfs_create_node (filename, block,
+                                   grub_be_to_cpu32 (obj->file_dir.file.size),
+                                   type))
+           {
+             grub_free (objc_data);
+             return 1;
+           }
+       }
+
+      next = grub_be_to_cpu32 (objc->next);
+    }
+
+ fail:
+  grub_free (objc_data);
+  return 0;
+}
+
+
+/* Open a file named NAME and initialize FILE.  */
+static grub_err_t
+grub_sfs_open (struct grub_file *file, const char *name)
+{
+  struct grub_sfs_data *data;
+  struct grub_fshelp_node *fdiro = 0;
+  
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  
+  data = grub_sfs_mount (file->device->disk);
+  if (!data)
+    goto fail;
+  
+  grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_sfs_iterate_dir,
+                        grub_sfs_read_symlink, GRUB_FSHELP_REG);
+  if (grub_errno)
+    goto fail;
+  
+  file->size = fdiro->size;
+  data->diropen = *fdiro;
+  grub_free (fdiro);
+
+  file->data = data;
+  file->offset = 0;
+
+  return 0;
+
+ fail:
+  if (data && fdiro != &data->diropen)
+    grub_free (fdiro);
+  if (data)
+    grub_free (data->label);
+  grub_free (data);
+  
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+
+static grub_err_t
+grub_sfs_close (grub_file_t file)
+{
+  grub_free (file->data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
+
+/* Read LEN bytes data from FILE into BUF.  */
+static grub_ssize_t
+grub_sfs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_sfs_data *data = (struct grub_sfs_data *) file->data;
+
+  int size = grub_sfs_read_file (&data->diropen, file->read_hook,
+                                file->offset, len, buf);
+
+  return size;
+}
+
+
+static grub_err_t
+grub_sfs_dir (grub_device_t device, const char *path, 
+              int (*hook) (const char *filename, int dir))
+{
+  struct grub_sfs_data *data = 0;
+  struct grub_fshelp_node *fdiro = 0;
+  
+  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)
+    {
+      grub_free (node);
+      
+      if (filetype == GRUB_FSHELP_DIR)
+       return hook (filename, 1);
+      else
+       return hook (filename, 0);
+      
+      return 0;
+    }
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  
+  data = grub_sfs_mount (device->disk);
+  if (!data)
+    goto fail;
+
+  grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_sfs_iterate_dir,
+                       grub_sfs_read_symlink, GRUB_FSHELP_DIR);
+  if (grub_errno)
+    goto fail;
+
+  grub_sfs_iterate_dir (fdiro, iterate);
+  
+ fail:
+  if (data && fdiro != &data->diropen)
+    grub_free (fdiro);
+  if (data)
+    grub_free (data->label);
+  grub_free (data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+
+static grub_err_t
+grub_sfs_label (grub_device_t device, char **label)
+{
+  struct grub_sfs_data *data;
+  grub_disk_t disk = device->disk;
+
+  data = grub_sfs_mount (disk);
+  if (data)
+    *label = data->label;
+
+  grub_free (data);
+
+  return grub_errno;
+}
+
+\f
+static struct grub_fs grub_sfs_fs =
+  {
+    .name = "sfs",
+    .dir = grub_sfs_dir,
+    .open = grub_sfs_open,
+    .read = grub_sfs_read,
+    .close = grub_sfs_close,
+    .label = grub_sfs_label,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(sfs)
+{
+  grub_fs_register (&grub_sfs_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(sfs)
+{
+  grub_fs_unregister (&grub_sfs_fs);
+}
diff --git a/fs/tar.c b/fs/tar.c
new file mode 100644 (file)
index 0000000..6ab62bc
--- /dev/null
+++ b/fs/tar.c
@@ -0,0 +1,2 @@
+#define MODE_USTAR 1
+#include "cpio.c"
diff --git a/fs/udf.c b/fs/udf.c
new file mode 100644 (file)
index 0000000..072e44f
--- /dev/null
+++ b/fs/udf.c
@@ -0,0 +1,929 @@
+/* udf.c - Universal Disk Format filesystem.  */
+/*
+ *  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/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>
+
+#define GRUB_UDF_MAX_PDS               2
+#define GRUB_UDF_MAX_PMS               6
+
+#define U16                            grub_le_to_cpu16
+#define U32                            grub_le_to_cpu32
+#define U64                            grub_le_to_cpu64
+
+#define GRUB_UDF_LOG2_BLKSZ            2
+#define GRUB_UDF_BLKSZ                 2048
+
+#define GRUB_UDF_TAG_IDENT_PVD         0x0001
+#define GRUB_UDF_TAG_IDENT_AVDP                0x0002
+#define GRUB_UDF_TAG_IDENT_VDP         0x0003
+#define GRUB_UDF_TAG_IDENT_IUVD                0x0004
+#define GRUB_UDF_TAG_IDENT_PD          0x0005
+#define GRUB_UDF_TAG_IDENT_LVD         0x0006
+#define GRUB_UDF_TAG_IDENT_USD         0x0007
+#define GRUB_UDF_TAG_IDENT_TD          0x0008
+#define GRUB_UDF_TAG_IDENT_LVID                0x0009
+
+#define GRUB_UDF_TAG_IDENT_FSD         0x0100
+#define GRUB_UDF_TAG_IDENT_FID         0x0101
+#define GRUB_UDF_TAG_IDENT_AED         0x0102
+#define GRUB_UDF_TAG_IDENT_IE          0x0103
+#define GRUB_UDF_TAG_IDENT_TE          0x0104
+#define GRUB_UDF_TAG_IDENT_FE          0x0105
+#define GRUB_UDF_TAG_IDENT_EAHD                0x0106
+#define GRUB_UDF_TAG_IDENT_USE         0x0107
+#define GRUB_UDF_TAG_IDENT_SBD         0x0108
+#define GRUB_UDF_TAG_IDENT_PIE         0x0109
+#define GRUB_UDF_TAG_IDENT_EFE         0x010A
+
+#define GRUB_UDF_ICBTAG_TYPE_UNDEF     0x00
+#define GRUB_UDF_ICBTAG_TYPE_USE       0x01
+#define GRUB_UDF_ICBTAG_TYPE_PIE       0x02
+#define GRUB_UDF_ICBTAG_TYPE_IE                0x03
+#define GRUB_UDF_ICBTAG_TYPE_DIRECTORY 0x04
+#define GRUB_UDF_ICBTAG_TYPE_REGULAR   0x05
+#define GRUB_UDF_ICBTAG_TYPE_BLOCK     0x06
+#define GRUB_UDF_ICBTAG_TYPE_CHAR      0x07
+#define GRUB_UDF_ICBTAG_TYPE_EA                0x08
+#define GRUB_UDF_ICBTAG_TYPE_FIFO      0x09
+#define GRUB_UDF_ICBTAG_TYPE_SOCKET    0x0A
+#define GRUB_UDF_ICBTAG_TYPE_TE                0x0B
+#define GRUB_UDF_ICBTAG_TYPE_SYMLINK   0x0C
+#define GRUB_UDF_ICBTAG_TYPE_STREAMDIR 0x0D
+
+#define GRUB_UDF_ICBTAG_FLAG_AD_MASK   0x0007
+#define GRUB_UDF_ICBTAG_FLAG_AD_SHORT  0x0000
+#define GRUB_UDF_ICBTAG_FLAG_AD_LONG   0x0001
+#define GRUB_UDF_ICBTAG_FLAG_AD_EXT    0x0002
+#define GRUB_UDF_ICBTAG_FLAG_AD_IN_ICB 0x0003
+
+#define GRUB_UDF_EXT_NORMAL            0x00000000
+#define GRUB_UDF_EXT_NREC_ALLOC                0x40000000
+#define GRUB_UDF_EXT_NREC_NALLOC       0x80000000
+#define GRUB_UDF_EXT_MASK              0xC0000000
+
+#define GRUB_UDF_FID_CHAR_HIDDEN       0x01
+#define GRUB_UDF_FID_CHAR_DIRECTORY    0x02
+#define GRUB_UDF_FID_CHAR_DELETED      0x04
+#define GRUB_UDF_FID_CHAR_PARENT       0x08
+#define GRUB_UDF_FID_CHAR_METADATA     0x10
+
+#define GRUB_UDF_STD_IDENT_BEA01       "BEA01"
+#define GRUB_UDF_STD_IDENT_BOOT2       "BOOT2"
+#define GRUB_UDF_STD_IDENT_CD001       "CD001"
+#define GRUB_UDF_STD_IDENT_CDW02       "CDW02"
+#define GRUB_UDF_STD_IDENT_NSR02       "NSR02"
+#define GRUB_UDF_STD_IDENT_NSR03       "NSR03"
+#define GRUB_UDF_STD_IDENT_TEA01       "TEA01"
+
+#define GRUB_UDF_CHARSPEC_TYPE_CS0     0x00
+#define GRUB_UDF_CHARSPEC_TYPE_CS1     0x01
+#define GRUB_UDF_CHARSPEC_TYPE_CS2     0x02
+#define GRUB_UDF_CHARSPEC_TYPE_CS3     0x03
+#define GRUB_UDF_CHARSPEC_TYPE_CS4     0x04
+#define GRUB_UDF_CHARSPEC_TYPE_CS5     0x05
+#define GRUB_UDF_CHARSPEC_TYPE_CS6     0x06
+#define GRUB_UDF_CHARSPEC_TYPE_CS7     0x07
+#define GRUB_UDF_CHARSPEC_TYPE_CS8     0x08
+
+#define GRUB_UDF_PARTMAP_TYPE_1                1
+#define GRUB_UDF_PARTMAP_TYPE_2                2
+
+struct grub_udf_lb_addr
+{
+  grub_uint32_t block_num;
+  grub_uint16_t part_ref;
+} __attribute__ ((packed));
+
+struct grub_udf_short_ad
+{
+  grub_uint32_t length;
+  grub_uint32_t position;
+} __attribute__ ((packed));
+
+struct grub_udf_long_ad
+{
+  grub_uint32_t length;
+  struct grub_udf_lb_addr block;
+  grub_uint8_t imp_use[6];
+} __attribute__ ((packed));
+
+struct grub_udf_extent_ad
+{
+  grub_uint32_t length;
+  grub_uint32_t start;
+} __attribute__ ((packed));
+
+struct grub_udf_charspec
+{
+  grub_uint8_t charset_type;
+  grub_uint8_t charset_info[63];
+} __attribute__ ((packed));
+
+struct grub_udf_timestamp
+{
+  grub_uint16_t type_and_timezone;
+  grub_uint16_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 centi_seconds;
+  grub_uint8_t hundreds_of_micro_seconds;
+  grub_uint8_t micro_seconds;
+} __attribute__ ((packed));
+
+struct grub_udf_regid
+{
+  grub_uint8_t flags;
+  grub_uint8_t ident[23];
+  grub_uint8_t ident_suffix[8];
+} __attribute__ ((packed));
+
+struct grub_udf_tag
+{
+  grub_uint16_t tag_ident;
+  grub_uint16_t desc_version;
+  grub_uint8_t tag_checksum;
+  grub_uint8_t reserved;
+  grub_uint16_t tag_serial_number;
+  grub_uint16_t desc_crc;
+  grub_uint16_t desc_crc_length;
+  grub_uint32_t tag_location;
+} __attribute__ ((packed));
+
+struct grub_udf_fileset
+{
+  struct grub_udf_tag tag;
+  struct grub_udf_timestamp datetime;
+  grub_uint16_t interchange_level;
+  grub_uint16_t max_interchange_level;
+  grub_uint32_t charset_list;
+  grub_uint32_t max_charset_list;
+  grub_uint32_t fileset_num;
+  grub_uint32_t fileset_desc_num;
+  struct grub_udf_charspec vol_charset;
+  grub_uint8_t vol_ident[128];
+  struct grub_udf_charspec fileset_charset;
+  grub_uint8_t fileset_ident[32];
+  grub_uint8_t copyright_file_ident[32];
+  grub_uint8_t abstract_file_ident[32];
+  struct grub_udf_long_ad root_icb;
+  struct grub_udf_regid domain_ident;
+  struct grub_udf_long_ad next_ext;
+  struct grub_udf_long_ad streamdir_icb;
+} __attribute__ ((packed));
+
+struct grub_udf_icbtag
+{
+  grub_uint32_t prior_recorded_num_direct_entries;
+  grub_uint16_t strategy_type;
+  grub_uint16_t strategy_parameter;
+  grub_uint16_t num_entries;
+  grub_uint8_t reserved;
+  grub_uint8_t file_type;
+  struct grub_udf_lb_addr parent_idb;
+  grub_uint16_t flags;
+} __attribute__ ((packed));
+
+struct grub_udf_file_ident
+{
+  struct grub_udf_tag tag;
+  grub_uint16_t version_num;
+  grub_uint8_t characteristics;
+  grub_uint8_t file_ident_length;
+  struct grub_udf_long_ad icb;
+  grub_uint16_t imp_use_length;
+} __attribute__ ((packed));
+
+struct grub_udf_file_entry
+{
+  struct grub_udf_tag tag;
+  struct grub_udf_icbtag icbtag;
+  grub_uint32_t uid;
+  grub_uint32_t gid;
+  grub_uint32_t permissions;
+  grub_uint16_t link_count;
+  grub_uint8_t record_format;
+  grub_uint8_t record_display_attr;
+  grub_uint32_t record_length;
+  grub_uint64_t file_size;
+  grub_uint64_t blocks_recorded;
+  struct grub_udf_timestamp access_time;
+  struct grub_udf_timestamp modification_time;
+  struct grub_udf_timestamp attr_time;
+  grub_uint32_t checkpoint;
+  struct grub_udf_long_ad extended_attr_idb;
+  struct grub_udf_regid imp_ident;
+  grub_uint64_t unique_id;
+  grub_uint32_t ext_attr_length;
+  grub_uint32_t alloc_descs_length;
+  grub_uint8_t ext_attr[1872];
+} __attribute__ ((packed));
+
+struct grub_udf_extended_file_entry
+{
+  struct grub_udf_tag tag;
+  struct grub_udf_icbtag icbtag;
+  grub_uint32_t uid;
+  grub_uint32_t gid;
+  grub_uint32_t permissions;
+  grub_uint16_t link_count;
+  grub_uint8_t record_format;
+  grub_uint8_t record_display_attr;
+  grub_uint32_t record_length;
+  grub_uint64_t file_size;
+  grub_uint64_t object_size;
+  grub_uint64_t blocks_recorded;
+  struct grub_udf_timestamp access_time;
+  struct grub_udf_timestamp modification_time;
+  struct grub_udf_timestamp create_time;
+  struct grub_udf_timestamp attr_time;
+  grub_uint32_t checkpoint;
+  grub_uint32_t reserved;
+  struct grub_udf_long_ad extended_attr_icb;
+  struct grub_udf_long_ad streamdir_icb;
+  struct grub_udf_regid imp_ident;
+  grub_uint64_t unique_id;
+  grub_uint32_t ext_attr_length;
+  grub_uint32_t alloc_descs_length;
+  grub_uint8_t ext_attr[1832];
+} __attribute__ ((packed));
+
+struct grub_udf_vrs
+{
+  grub_uint8_t type;
+  grub_uint8_t magic[5];
+  grub_uint8_t version;
+} __attribute__ ((packed));
+
+struct grub_udf_avdp
+{
+  struct grub_udf_tag tag;
+  struct grub_udf_extent_ad vds;
+} __attribute__ ((packed));
+
+struct grub_udf_pd
+{
+  struct grub_udf_tag tag;
+  grub_uint32_t seq_num;
+  grub_uint16_t flags;
+  grub_uint16_t part_num;
+  struct grub_udf_regid contents;
+  grub_uint8_t contents_use[128];
+  grub_uint32_t access_type;
+  grub_uint32_t start;
+  grub_uint32_t length;
+} __attribute__ ((packed));
+
+struct grub_udf_partmap
+{
+  grub_uint8_t type;
+  grub_uint8_t length;
+  union
+  {
+    struct
+    {
+      grub_uint16_t seq_num;
+      grub_uint16_t part_num;
+    } type1;
+
+    struct
+    {
+      grub_uint8_t ident[62];
+    } type2;
+  };
+};
+
+struct grub_udf_lvd
+{
+  struct grub_udf_tag tag;
+  grub_uint32_t seq_num;
+  struct grub_udf_charspec charset;
+  grub_uint8_t ident[128];
+  grub_uint32_t bsize;
+  struct grub_udf_regid domain_ident;
+  struct grub_udf_long_ad root_fileset;
+  grub_uint32_t map_table_length;
+  grub_uint32_t num_part_maps;
+  struct grub_udf_regid imp_ident;
+  grub_uint8_t imp_use[128];
+  struct grub_udf_extent_ad integrity_seq_ext;
+  grub_uint8_t part_maps[1608];
+} __attribute__ ((packed));
+
+struct grub_udf_data
+{
+  grub_disk_t disk;
+  struct grub_udf_lvd lvd;
+  struct grub_udf_pd pds[GRUB_UDF_MAX_PDS];
+  struct grub_udf_partmap *pms[GRUB_UDF_MAX_PMS];
+  struct grub_udf_long_ad root_icb;
+  int npd, npm;
+};
+
+struct grub_fshelp_node
+{
+  struct grub_udf_data *data;
+  union
+  {
+    struct grub_udf_file_entry fe;
+    struct grub_udf_extended_file_entry efe;
+  };
+  int part_ref;
+};
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+static grub_uint32_t
+grub_udf_get_block (struct grub_udf_data *data,
+                   grub_uint16_t part_ref, grub_uint32_t block)
+{
+  part_ref = U16 (part_ref);
+
+  if (part_ref >= data->npm)
+    {
+      grub_error (GRUB_ERR_BAD_FS, "invalid part ref");
+      return 0;
+    }
+
+  return (U32 (data->pds[data->pms[part_ref]->type1.part_num].start)
+          + U32 (block));
+}
+
+static grub_err_t
+grub_udf_read_icb (struct grub_udf_data *data,
+                  struct grub_udf_long_ad *icb,
+                  struct grub_fshelp_node *node)
+{
+  grub_uint32_t block;
+
+  block = grub_udf_get_block (data,
+                             icb->block.part_ref,
+                              icb->block.block_num);
+
+  if (grub_errno)
+    return grub_errno;
+
+  if (grub_disk_read (data->disk, block << GRUB_UDF_LOG2_BLKSZ, 0,
+                     sizeof (struct grub_udf_file_entry),
+                     (char *) &node->fe))
+    return grub_errno;
+
+  if ((U16 (node->fe.tag.tag_ident) != GRUB_UDF_TAG_IDENT_FE) &&
+      (U16 (node->fe.tag.tag_ident) != GRUB_UDF_TAG_IDENT_EFE))
+    return grub_error (GRUB_ERR_BAD_FS, "invalid fe/efe descriptor");
+
+  node->part_ref = icb->block.part_ref;
+  node->data = data;
+  return 0;
+}
+
+static grub_disk_addr_t
+grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
+{
+  char *ptr;
+  int len;
+
+  if (U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE)
+    {
+      ptr = (char *) &node->fe.ext_attr[0] + U32 (node->fe.ext_attr_length);
+      len = U32 (node->fe.alloc_descs_length);
+    }
+  else
+    {
+      ptr = (char *) &node->efe.ext_attr[0] + U32 (node->efe.ext_attr_length);
+      len = U32 (node->efe.alloc_descs_length);
+    }
+
+  if ((U16 (node->fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK)
+      == GRUB_UDF_ICBTAG_FLAG_AD_SHORT)
+    {
+      struct grub_udf_short_ad *ad = (struct grub_udf_short_ad *) ptr;
+
+      len /= sizeof (struct grub_udf_short_ad);
+      while (len > 0)
+       {
+         if (fileblock < U32 (ad->length))
+           return ((U32 (ad->position) & GRUB_UDF_EXT_MASK) ? 0 :
+                    (grub_udf_get_block (node->data,
+                                         node->part_ref,
+                                         ad->position)
+                     + fileblock));
+
+         fileblock -= U32 (ad->length);
+         ad++;
+         len--;
+       }
+    }
+  else
+    {
+      struct grub_udf_long_ad *ad = (struct grub_udf_long_ad *) ptr;
+
+      len /= sizeof (struct grub_udf_long_ad);
+      while (len > 0)
+       {
+         if (fileblock < U32 (ad->length))
+           return ((U32 (ad->block.block_num) & GRUB_UDF_EXT_MASK) ?  0 :
+                    (grub_udf_get_block (node->data,
+                                         ad->block.part_ref,
+                                         ad->block.block_num)
+                    + fileblock));
+
+         fileblock -= U32 (ad->length);
+         ad++;
+         len--;
+       }
+    }
+
+  return 0;
+}
+
+static grub_ssize_t
+grub_udf_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)
+{
+  switch (U16 (node->fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK)
+    {
+    case GRUB_UDF_ICBTAG_FLAG_AD_IN_ICB:
+      {
+       char *ptr;
+
+       ptr = ((U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE) ?
+              ((char *) &node->fe.ext_attr[0]
+                + U32 (node->fe.ext_attr_length)) :
+              ((char *) &node->efe.ext_attr[0]
+                + U32 (node->efe.ext_attr_length)));
+
+       grub_memcpy (buf, ptr + pos, len);
+
+       return len;
+      }
+
+    case GRUB_UDF_ICBTAG_FLAG_AD_EXT:
+      grub_error (GRUB_ERR_BAD_FS, "invalid extent type");
+      return 0;
+    }
+
+  return  grub_fshelp_read_file (node->data->disk, node, read_hook,
+                                 pos, len, buf, grub_udf_read_block,
+                                 U64 (node->fe.file_size),
+                                 GRUB_UDF_LOG2_BLKSZ);
+}
+
+static int sblocklist[] = { 256, 512, 0 };
+
+static struct grub_udf_data *
+grub_udf_mount (grub_disk_t disk)
+{
+  struct grub_udf_data *data = 0;
+  struct grub_udf_fileset root_fs;
+  int *sblklist = sblocklist;
+  grub_uint32_t block;
+  int i;
+
+  data = grub_malloc (sizeof (struct grub_udf_data));
+  if (!data)
+    return 0;
+
+  data->disk = disk;
+
+  /* Search for Volume Recognition Sequence (VRS).  */
+  for (block = 16;; block++)
+    {
+      struct grub_udf_vrs vrs;
+
+      if (grub_disk_read (disk, block << GRUB_UDF_LOG2_BLKSZ, 0,
+                         sizeof (struct grub_udf_vrs), (char *) &vrs))
+       {
+         grub_error (GRUB_ERR_BAD_FS, "not an udf filesystem");
+         goto fail;
+       }
+
+      if ((!grub_memcmp (vrs.magic, GRUB_UDF_STD_IDENT_NSR03, 5)) ||
+         (!grub_memcmp (vrs.magic, GRUB_UDF_STD_IDENT_NSR02, 5)))
+       break;
+
+      if ((grub_memcmp (vrs.magic, GRUB_UDF_STD_IDENT_BEA01, 5)) &&
+         (grub_memcmp (vrs.magic, GRUB_UDF_STD_IDENT_BOOT2, 5)) &&
+         (grub_memcmp (vrs.magic, GRUB_UDF_STD_IDENT_CD001, 5)) &&
+         (grub_memcmp (vrs.magic, GRUB_UDF_STD_IDENT_CDW02, 5)) &&
+         (grub_memcmp (vrs.magic, GRUB_UDF_STD_IDENT_TEA01, 5)))
+       {
+         grub_error (GRUB_ERR_BAD_FS, "not an udf filesystem");
+         goto fail;
+       }
+    }
+
+  /* Search for Anchor Volume Descriptor Pointer (AVDP).  */
+  while (1)
+    {
+      struct grub_udf_avdp avdp;
+
+      if (grub_disk_read (disk, *sblklist << GRUB_UDF_LOG2_BLKSZ, 0,
+                         sizeof (struct grub_udf_avdp), (char *) &avdp))
+       {
+         grub_error (GRUB_ERR_BAD_FS, "not an udf filesystem");
+         goto fail;
+       }
+
+      if (U16 (avdp.tag.tag_ident) == GRUB_UDF_TAG_IDENT_AVDP)
+       {
+         block = U32 (avdp.vds.start);
+         break;
+       }
+
+      sblklist++;
+      if (*sblklist == 0)
+       {
+         grub_error (GRUB_ERR_BAD_FS, "not an udf filesystem");
+         goto fail;
+       }
+    }
+
+  data->npd = data->npm = 0;
+  /* Locate Partiton Descriptor (PD) and Logical Volume Descriptor (LVD).  */
+  while (1)
+    {
+      struct grub_udf_tag tag;
+
+      if (grub_disk_read (disk, block << GRUB_UDF_LOG2_BLKSZ, 0,
+                         sizeof (struct grub_udf_tag), (char *) &tag))
+       {
+         grub_error (GRUB_ERR_BAD_FS, "not an udf filesystem");
+         goto fail;
+       }
+
+      tag.tag_ident = U16 (tag.tag_ident);
+      if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PD)
+       {
+         if (data->npd >= GRUB_UDF_MAX_PDS)
+           {
+             grub_error (GRUB_ERR_BAD_FS, "too many PDs");
+             goto fail;
+           }
+
+         if (grub_disk_read (disk, block << GRUB_UDF_LOG2_BLKSZ, 0,
+                             sizeof (struct grub_udf_pd),
+                             (char *) &data->pds[data->npd]))
+           {
+             grub_error (GRUB_ERR_BAD_FS, "not an udf filesystem");
+             goto fail;
+           }
+
+         data->npd++;
+       }
+      else if (tag.tag_ident == GRUB_UDF_TAG_IDENT_LVD)
+       {
+         int k;
+
+         struct grub_udf_partmap *ppm;
+
+         if (grub_disk_read (disk, block << GRUB_UDF_LOG2_BLKSZ, 0,
+                             sizeof (struct grub_udf_lvd),
+                             (char *) &data->lvd))
+           {
+             grub_error (GRUB_ERR_BAD_FS, "not an udf filesystem");
+             goto fail;
+           }
+
+         if (data->npm + U32 (data->lvd.num_part_maps) > GRUB_UDF_MAX_PMS)
+           {
+             grub_error (GRUB_ERR_BAD_FS, "too many partition maps");
+             goto fail;
+           }
+
+         ppm = (struct grub_udf_partmap *) &data->lvd.part_maps;
+         for (k = U32 (data->lvd.num_part_maps); k > 0; k--)
+           {
+             if (ppm->type != GRUB_UDF_PARTMAP_TYPE_1)
+               {
+                 grub_error (GRUB_ERR_BAD_FS, "partmap type not supported");
+                 goto fail;
+               }
+
+             data->pms[data->npm++] = ppm;
+             ppm = (struct grub_udf_partmap *) ((char *) ppm +
+                                                 U32 (ppm->length));
+           }
+       }
+      else if (tag.tag_ident > GRUB_UDF_TAG_IDENT_TD)
+       {
+         grub_error (GRUB_ERR_BAD_FS, "invalid tag ident");
+         goto fail;
+       }
+      else if (tag.tag_ident == GRUB_UDF_TAG_IDENT_TD)
+       break;
+
+      block++;
+    }
+
+  for (i = 0; i < data->npm; i++)
+    {
+      int j;
+
+      for (j = 0; j < data->npd; j++)
+       if (data->pms[i]->type1.part_num == data->pds[j].part_num)
+         {
+           data->pms[i]->type1.part_num = j;
+           break;
+         }
+
+      if (j == data->npd)
+       {
+         grub_error (GRUB_ERR_BAD_FS, "can\'t find PD");
+         goto fail;
+       }
+    }
+
+  block = grub_udf_get_block (data,
+                             data->lvd.root_fileset.block.part_ref,
+                             data->lvd.root_fileset.block.block_num);
+
+  if (grub_errno)
+    goto fail;
+
+  if (grub_disk_read (disk, block << GRUB_UDF_LOG2_BLKSZ, 0,
+                     sizeof (struct grub_udf_fileset), (char *) &root_fs))
+    {
+      grub_error (GRUB_ERR_BAD_FS, "not an udf filesystem");
+      goto fail;
+    }
+
+  if (U16 (root_fs.tag.tag_ident) != GRUB_UDF_TAG_IDENT_FSD)
+    {
+      grub_error (GRUB_ERR_BAD_FS, "invalid fileset descriptor");
+      goto fail;
+    }
+
+  data->root_icb = root_fs.root_icb;
+
+  return data;
+
+fail:
+  grub_free (data);
+  return 0;
+}
+
+static int
+grub_udf_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_fshelp_node_t child;
+  struct grub_udf_file_ident dirent;
+  grub_uint32_t offset = 0;
+
+  child = grub_malloc (sizeof (struct grub_fshelp_node));
+  if (!child)
+    return 0;
+
+  /* The current directory is not stored.  */
+  grub_memcpy ((char *) child, (char *) dir,
+              sizeof (struct grub_fshelp_node));
+
+  if (hook (".", GRUB_FSHELP_DIR, child))
+    return 1;
+
+  while (offset < U64 (dir->fe.file_size))
+    {
+      if (grub_udf_read_file (dir, 0, offset, sizeof (dirent),
+                             (char *) &dirent) != sizeof (dirent))
+       return 0;
+
+      if (U16 (dirent.tag.tag_ident) != GRUB_UDF_TAG_IDENT_FID)
+       {
+         grub_error (GRUB_ERR_BAD_FS, "invalid fid tag");
+         return 0;
+       }
+
+      child = grub_malloc (sizeof (struct grub_fshelp_node));
+      if (!child)
+       return 0;
+
+      if (grub_udf_read_icb (dir->data, &dirent.icb, child))
+       return 0;
+
+      offset += sizeof (dirent) + U16 (dirent.imp_use_length);
+      if (dirent.characteristics & GRUB_UDF_FID_CHAR_PARENT)
+       {
+         /* This is the parent directory.  */
+         if (hook ("..", GRUB_FSHELP_DIR, child))
+           return 1;
+       }
+      else
+       {
+         enum grub_fshelp_filetype type;
+         char filename[dirent.file_ident_length + 1];
+
+         type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ?
+                 (GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG));
+
+         if ((grub_udf_read_file (dir, 0, offset,
+                                  dirent.file_ident_length, filename))
+             != dirent.file_ident_length)
+           return 0;
+
+         filename[dirent.file_ident_length] = 0;
+         if (hook (&filename[1], type, child))
+           return 1;
+       }
+
+      /* Align to dword boundary.  */
+      offset = (offset + dirent.file_ident_length + 3) & (~3);
+    }
+
+  return 0;
+}
+
+static grub_err_t
+grub_udf_dir (grub_device_t device, const char *path,
+             int (*hook) (const char *filename, int dir))
+{
+  struct grub_udf_data *data = 0;
+  struct grub_fshelp_node rootnode;
+  struct grub_fshelp_node *foundnode;
+
+  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)
+  {
+    grub_free (node);
+
+    if (filetype == GRUB_FSHELP_DIR)
+      return hook (filename, 1);
+    else
+      return hook (filename, 0);
+
+    return 0;
+  }
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_udf_mount (device->disk);
+  if (!data)
+    goto fail;
+
+  if (grub_udf_read_icb (data, &data->root_icb, &rootnode))
+    goto fail;
+
+  if (grub_fshelp_find_file (path, &rootnode,
+                            &foundnode,
+                            grub_udf_iterate_dir, 0, GRUB_FSHELP_DIR))
+    goto fail;
+
+  grub_udf_iterate_dir (foundnode, iterate);
+
+  if (foundnode != &rootnode)
+    grub_free (foundnode);
+
+fail:
+  grub_free (data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_udf_open (struct grub_file *file, const char *name)
+{
+  struct grub_udf_data *data;
+  struct grub_fshelp_node rootnode;
+  struct grub_fshelp_node *foundnode;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_udf_mount (file->device->disk);
+  if (!data)
+    goto fail;
+
+  if (grub_udf_read_icb (data, &data->root_icb, &rootnode))
+    goto fail;
+
+  if (grub_fshelp_find_file (name, &rootnode,
+                            &foundnode,
+                            grub_udf_iterate_dir, 0, GRUB_FSHELP_REG))
+    goto fail;
+
+  file->data = foundnode;
+  file->offset = 0;
+  file->size = U64 (foundnode->fe.file_size);
+
+  return 0;
+
+fail:
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+}
+
+static grub_ssize_t
+grub_udf_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_fshelp_node *node = (struct grub_fshelp_node *) file->data;
+
+  return grub_udf_read_file (node, file->read_hook, file->offset, len, buf);
+}
+
+static grub_err_t
+grub_udf_close (grub_file_t file)
+{
+  if (file->data)
+    {
+      struct grub_fshelp_node *node = (struct grub_fshelp_node *) file->data;
+
+      grub_free (node->data);
+      grub_free (node);
+    }
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_udf_label (grub_device_t device, char **label)
+{
+  struct grub_udf_data *data;
+  data = grub_udf_mount (device->disk);
+
+  if (data)
+    {
+      *label = grub_strdup ((char *) &data->lvd.ident[1]);
+      grub_free (data);
+    }
+  else
+    *label = 0;
+
+  return grub_errno;
+}
+
+static struct grub_fs grub_udf_fs = {
+  .name = "udf",
+  .dir = grub_udf_dir,
+  .open = grub_udf_open,
+  .read = grub_udf_read,
+  .close = grub_udf_close,
+  .label = grub_udf_label,
+  .next = 0
+};
+
+GRUB_MOD_INIT (udf)
+{
+  grub_fs_register (&grub_udf_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI (udf)
+{
+  grub_fs_unregister (&grub_udf_fs);
+}
diff --git a/fs/ufs.c b/fs/ufs.c
new file mode 100644 (file)
index 0000000..1f333b0
--- /dev/null
+++ b/fs/ufs.c
@@ -0,0 +1,715 @@
+/* ufs.c - Unix File System */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,2005,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/>.
+ */
+
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/types.h>
+
+
+#define GRUB_UFS_MAGIC         0x11954
+#define GRUB_UFS2_MAGIC                0x19540119
+#define GRUB_UFS_INODE         2
+#define GRUB_UFS_FILETYPE_DIR  4
+#define GRUB_UFS_FILETYPE_LNK  10
+#define GRUB_UFS_MAX_SYMLNK_CNT        8
+
+#define GRUB_UFS_DIRBLKS       12
+#define GRUB_UFS_INDIRBLKS     3
+
+#define GRUB_UFS_ATTR_DIR      040000
+
+#define GRUB_UFS_VOLNAME_LEN   32
+
+/* Calculate in which group the inode can be found.  */
+#define inode_group(inode,sblock) ()
+
+#define UFS_BLKSZ(sblock) (grub_le_to_cpu32 (sblock->bsize))
+
+#define INODE(data,field) (data->ufs_type == UFS1 ? \
+                           data->inode.  field : data->inode2.  field)
+#define INODE_ENDIAN(data,field,bits1,bits2) (data->ufs_type == UFS1 ? \
+                           grub_le_to_cpu##bits1 (data->inode.field) : \
+                           grub_le_to_cpu##bits2 (data->inode2.field))
+#define INODE_SIZE(data) INODE_ENDIAN (data,size,32,64)
+#define INODE_MODE(data) INODE_ENDIAN (data,mode,16,16)
+#define INODE_BLKSZ(data) (data->ufs_type == UFS1 ? 4 : 8)
+#define INODE_DIRBLOCKS(data,blk) INODE_ENDIAN \
+                                   (data,blocks.dir_blocks[blk],32,64)
+#define INODE_INDIRBLOCKS(data,blk) INODE_ENDIAN \
+                                     (data,blocks.indir_blocks[blk],32,64)
+
+/* The blocks on which the superblock can be found.  */
+static int sblocklist[] = { 128, 16, 0, 512, -1 };
+
+struct grub_ufs_sblock
+{
+  grub_uint8_t unused[16];
+  /* The offset of the inodes in the cylinder group.  */
+  grub_uint32_t inoblk_offs;
+  
+  grub_uint8_t unused2[4];
+  
+  /* The start of the cylinder group.  */
+  grub_uint32_t cylg_offset;
+  
+  grub_uint8_t unused3[20];
+  
+  /* The size of a block in bytes.  */
+  grub_int32_t bsize;
+  grub_uint8_t unused4[48];
+  
+  /* The size of filesystem blocks to disk blocks.  */
+  grub_uint32_t log2_blksz;
+  grub_uint8_t unused5[80];
+  
+  /* Inodes stored per cylinder group.  */
+  grub_uint32_t ino_per_group;
+  
+  /* The frags per cylinder group.  */
+  grub_uint32_t frags_per_group;
+  
+  grub_uint8_t unused7[488];
+
+  /* Volume name for UFS2.  */
+  grub_uint8_t volume_name[GRUB_UFS_VOLNAME_LEN];
+
+  grub_uint8_t unused8[660];
+  
+  /* Magic value to check if this is really a UFS filesystem.  */
+  grub_uint32_t magic;
+};
+
+/* UFS inode.  */
+struct grub_ufs_inode
+{
+  grub_uint16_t mode;
+  grub_uint16_t nlinks;
+  grub_uint16_t uid;
+  grub_uint16_t gid;
+  grub_int64_t size;
+  grub_uint64_t atime;
+  grub_uint64_t mtime;
+  grub_uint64_t ctime;
+  union
+  {
+    struct
+    {
+      grub_uint32_t dir_blocks[GRUB_UFS_DIRBLKS];
+      grub_uint32_t indir_blocks[GRUB_UFS_INDIRBLKS];
+    } blocks;
+    grub_uint8_t symlink[(GRUB_UFS_DIRBLKS + GRUB_UFS_INDIRBLKS) * 4];
+  };
+  grub_uint32_t flags;
+  grub_uint32_t nblocks;
+  grub_uint32_t gen;
+  grub_uint32_t unused;
+  grub_uint8_t pad[12];
+};
+
+/* UFS inode.  */
+struct grub_ufs2_inode
+{
+  grub_uint16_t mode;
+  grub_uint16_t nlinks;
+  grub_uint32_t uid;
+  grub_uint32_t gid;
+  grub_uint32_t blocksize;
+  grub_int64_t size;
+  grub_int64_t nblocks;
+  grub_uint64_t atime;
+  grub_uint64_t mtime;
+  grub_uint64_t ctime;
+  grub_uint64_t create_time;
+  grub_uint32_t atime_sec;
+  grub_uint32_t mtime_sec;
+  grub_uint32_t ctime_sec;
+  grub_uint32_t create_time_sec;
+  grub_uint32_t gen;
+  grub_uint32_t kernel_flags;
+  grub_uint32_t flags;
+  grub_uint32_t extsz;
+  grub_uint64_t ext[2];
+  union
+  {
+    struct
+    {
+      grub_uint64_t dir_blocks[GRUB_UFS_DIRBLKS];
+      grub_uint64_t indir_blocks[GRUB_UFS_INDIRBLKS];
+    } blocks;
+    grub_uint8_t symlink[(GRUB_UFS_DIRBLKS + GRUB_UFS_INDIRBLKS) * 8];
+  };
+
+  grub_uint8_t unused[24];
+};
+
+/* Directory entry.  */
+struct grub_ufs_dirent
+{
+  grub_uint32_t ino;
+  grub_uint16_t direntlen;
+  grub_uint8_t filetype;
+  grub_uint8_t namelen;
+};
+
+/* Information about a "mounted" ufs filesystem.  */
+struct grub_ufs_data
+{
+  struct grub_ufs_sblock sblock;
+  grub_disk_t disk;
+  union
+  {
+    struct grub_ufs_inode inode;
+    struct grub_ufs2_inode inode2;
+  };
+  enum
+    {
+      UFS1,
+      UFS2,
+      UNKNOWN
+    } ufs_type;
+  int ino;
+  int linknest;
+};
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+\f
+/* Forward declaration.  */
+static grub_err_t grub_ufs_find_file (struct grub_ufs_data *data,
+                                     const char *path);
+
+
+static int
+grub_ufs_get_file_block (struct grub_ufs_data *data, unsigned int blk)
+{
+  struct grub_ufs_sblock *sblock = &data->sblock;
+  unsigned int indirsz;
+  int log2_blksz; 
+  
+  /* Direct.  */
+  if (blk < GRUB_UFS_DIRBLKS)
+    return INODE_DIRBLOCKS (data, blk);
+  
+  log2_blksz = grub_le_to_cpu32 (data->sblock.log2_blksz);
+  
+  blk -= GRUB_UFS_DIRBLKS;
+  
+  indirsz = UFS_BLKSZ (sblock) / INODE_BLKSZ (data);
+  /* Single indirect block.  */
+  if (blk < indirsz)
+    {
+      grub_uint32_t indir[UFS_BLKSZ (sblock) >> 2];
+      grub_disk_read (data->disk, INODE_INDIRBLOCKS (data, 0) << log2_blksz,
+                     0, sizeof (indir), (char *) indir);
+      return (data->ufs_type == UFS1) ? indir[blk] : indir[blk << 1];
+    }
+  blk -= indirsz;
+  
+  /* Double indirect block.  */
+  if (blk < UFS_BLKSZ (sblock) / indirsz)
+    {
+      grub_uint32_t indir[UFS_BLKSZ (sblock) >> 2];
+      
+      grub_disk_read (data->disk, INODE_INDIRBLOCKS (data, 1) << log2_blksz,
+                     0, sizeof (indir), (char *) indir);
+      grub_disk_read (data->disk,
+                     (data->ufs_type == UFS1) ?
+                     indir[blk / indirsz] : indir [(blk / indirsz) << 1],
+                     0, sizeof (indir), (char *) indir);
+      
+      return (data->ufs_type == UFS1) ?
+            indir[blk % indirsz] : indir[(blk % indirsz) << 1];
+    }
+
+
+  grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+             "ufs does not support triple indirect blocks");
+  return 0;
+}
+
+
+/* Read LEN bytes from the file described by DATA starting with byte
+   POS.  Return the amount of read bytes in READ.  */
+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)
+{
+  struct grub_ufs_sblock *sblock = &data->sblock;
+  int i;
+  int blockcnt;
+
+  /* Adjust len so it we can't read past the end of the file.  */
+  if (len > INODE_SIZE (data))
+    len = INODE_SIZE (data);
+
+  blockcnt = (len + pos + UFS_BLKSZ (sblock) - 1) / UFS_BLKSZ (sblock);
+  
+  for (i = pos / UFS_BLKSZ (sblock); i < blockcnt; i++)
+    {
+      int blknr;
+      int blockoff = pos % UFS_BLKSZ (sblock);
+      int blockend = UFS_BLKSZ (sblock);
+      
+      int skipfirst = 0;
+      
+      blknr = grub_ufs_get_file_block (data, i);
+      if (grub_errno)
+       return -1;
+      
+      /* Last block.  */
+      if (i == blockcnt - 1)
+       {
+         blockend = (len + pos) % UFS_BLKSZ (sblock);
+         
+         if (!blockend)
+           blockend = UFS_BLKSZ (sblock);
+       }
+      
+      /* First block.  */
+      if (i == (pos / (int) UFS_BLKSZ (sblock)))
+       {
+         skipfirst = blockoff;
+         blockend -= skipfirst;
+       }
+      
+      /* XXX: If the block number is 0 this block is not stored on
+        disk but is zero filled instead.  */
+      if (blknr)
+       {
+         data->disk->read_hook = read_hook;
+         grub_disk_read (data->disk,
+                         blknr << grub_le_to_cpu32 (data->sblock.log2_blksz),
+                         skipfirst, blockend, buf);
+         data->disk->read_hook = 0;
+         if (grub_errno)
+           return -1;
+       }
+      else
+       grub_memset (buf, UFS_BLKSZ (sblock) - skipfirst, 0);
+
+      buf += UFS_BLKSZ (sblock) - skipfirst;
+    }
+  
+  return len;
+}
+
+
+/* Read inode INO from the mounted filesystem described by DATA.  This
+   inode is used by default now.  */
+static grub_err_t
+grub_ufs_read_inode (struct grub_ufs_data *data, int ino)
+{
+  struct grub_ufs_sblock *sblock = &data->sblock;
+  
+  /* Determine the group the inode is in.  */
+  int group = ino / grub_le_to_cpu32 (sblock->ino_per_group);
+  
+  /* Determine the inode within the group.  */
+  int grpino = ino % grub_le_to_cpu32 (sblock->ino_per_group);
+  
+  /* The first block of the group.  */
+  int grpblk = group * (grub_le_to_cpu32 (sblock->frags_per_group));
+  
+  if (data->ufs_type == UFS1)
+    {
+      struct grub_ufs_inode *inode = &data->inode;
+      
+      grub_disk_read (data->disk,
+                     (((grub_le_to_cpu32 (sblock->inoblk_offs) + grpblk)
+                       << grub_le_to_cpu32 (data->sblock.log2_blksz)))
+                     + grpino / 4,
+                     (grpino % 4) * sizeof (struct grub_ufs_inode),
+                     sizeof (struct grub_ufs_inode),
+                     (char *) inode);
+    }
+  else
+    {
+      struct grub_ufs2_inode *inode = &data->inode2;
+      
+      grub_disk_read (data->disk,
+                     (((grub_le_to_cpu32 (sblock->inoblk_offs) + grpblk)
+                       << grub_le_to_cpu32 (data->sblock.log2_blksz)))
+                     + grpino / 2,
+                     (grpino % 2) * sizeof (struct grub_ufs2_inode),
+                     sizeof (struct grub_ufs2_inode),
+                     (char *) inode);
+    }
+  
+  data->ino = ino;
+  return grub_errno;
+}
+
+
+/* Lookup the symlink the current inode points to.  INO is the inode
+   number of the directory the symlink is relative to.  */
+static grub_err_t
+grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino)
+{
+  char symlink[INODE_SIZE (data)];
+  
+  if (++data->linknest > GRUB_UFS_MAX_SYMLNK_CNT)
+    return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks");
+  
+  if (INODE_SIZE (data) < (GRUB_UFS_DIRBLKS + GRUB_UFS_INDIRBLKS
+                         * INODE_BLKSZ (data)))
+    grub_strcpy (symlink, (char *) INODE (data, symlink));
+  else
+    {
+      grub_disk_read (data->disk, 
+                     (INODE_DIRBLOCKS (data, 0) 
+                      << grub_le_to_cpu32 (data->sblock.log2_blksz)),
+                     0, INODE_SIZE (data), symlink);
+      symlink[INODE_SIZE (data)] = '\0';
+    }
+
+  /* The symlink is an absolute path, go back to the root inode.  */
+  if (symlink[0] == '/')
+    ino = GRUB_UFS_INODE;
+  
+  /* Now load in the old inode.  */
+  if (grub_ufs_read_inode (data, ino))
+    return grub_errno;
+  
+  grub_ufs_find_file (data, symlink);
+  if (grub_errno)
+    grub_error (grub_errno, "Can not follow symlink `%s'.", symlink);
+  
+  return grub_errno;
+}
+
+
+/* Find the file with the pathname PATH on the filesystem described by
+   DATA.  */
+static grub_err_t
+grub_ufs_find_file (struct grub_ufs_data *data, const char *path)
+{
+  char fpath[grub_strlen (path) + 1];
+  char *name = fpath;
+  char *next;
+  unsigned int pos = 0;
+  int dirino;
+  
+  grub_strcpy (fpath, path);
+  
+  /* Skip the first slash.  */
+  if (name[0] == '/')
+    {
+      name++;
+      if (!*name)
+       return 0;
+    }
+
+  /* Extract the actual part from the pathname.  */
+  next = grub_strchr (name, '/');
+  if (next)
+    {
+      next[0] = '\0';
+      next++;
+    }
+  
+  do
+    {
+      struct grub_ufs_dirent dirent;
+      
+      if (grub_strlen (name) == 0)
+       return GRUB_ERR_NONE;
+      
+      if (grub_ufs_read_file (data, 0, pos, sizeof (dirent),
+                             (char *) &dirent) < 0)
+       return grub_errno;
+      
+      {
+       char filename[dirent.namelen + 1];
+
+       if (grub_ufs_read_file (data, 0, pos + sizeof (dirent),
+                               dirent.namelen, filename) < 0)
+         return grub_errno;
+       
+       filename[dirent.namelen] = '\0';
+       
+       if (!grub_strcmp (name, filename))
+         {
+           dirino = data->ino;
+           grub_ufs_read_inode (data, grub_le_to_cpu32 (dirent.ino));
+           
+           if (dirent.filetype == GRUB_UFS_FILETYPE_LNK)
+             {
+               grub_ufs_lookup_symlink (data, dirino);
+               if (grub_errno)
+                 return grub_errno;
+             }
+
+           if (!next)
+             return 0;
+
+           pos = 0;
+
+           name = next;
+           next = grub_strchr (name, '/');
+           if (next)
+             {
+               next[0] = '\0';
+               next++;
+             }
+           
+           if (!(dirent.filetype & GRUB_UFS_FILETYPE_DIR))
+             return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+           
+           continue;
+         }
+      }
+      
+      pos += grub_le_to_cpu16 (dirent.direntlen);
+    } while (pos < INODE_SIZE (data));
+  
+  grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+  return grub_errno;
+}
+
+
+/* Mount the filesystem on the disk DISK.  */
+static struct grub_ufs_data *
+grub_ufs_mount (grub_disk_t disk)
+{
+  struct grub_ufs_data *data;
+  int *sblklist = sblocklist;
+  
+  data = grub_malloc (sizeof (struct grub_ufs_data));
+  if (!data)
+    return 0;
+  
+  /* Find a UFS1 or UFS2 sblock.  */
+  data->ufs_type = UNKNOWN;
+  while (*sblklist != -1)
+    {
+      grub_disk_read (disk, *sblklist, 0, sizeof (struct grub_ufs_sblock),
+                     (char *) &data->sblock);
+      if (grub_errno)
+       goto fail;
+      
+      if (grub_le_to_cpu32 (data->sblock.magic) == GRUB_UFS_MAGIC)
+       {
+         data->ufs_type = UFS1;
+         break;
+       }
+      else if (grub_le_to_cpu32 (data->sblock.magic) == GRUB_UFS2_MAGIC)
+       {
+         data->ufs_type = UFS2;
+         break;
+       }
+      sblklist++;
+    }
+  if (data->ufs_type == UNKNOWN)
+    {
+      grub_error (GRUB_ERR_BAD_FS, "not an ufs filesystem");
+      goto fail;
+    }
+
+  data->disk = disk;
+  data->linknest = 0;
+  return data;
+
+ fail:
+  grub_free (data);
+  
+  if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+    grub_error (GRUB_ERR_BAD_FS, "not a ufs filesystem");
+  
+  return 0;
+}
+
+
+static grub_err_t
+grub_ufs_dir (grub_device_t device, const char *path, 
+              int (*hook) (const char *filename, int dir))
+{
+  struct grub_ufs_data *data;
+  struct grub_ufs_sblock *sblock;
+  unsigned int pos = 0;
+
+  data = grub_ufs_mount (device->disk);
+  if (!data)
+    return grub_errno;
+  
+  grub_ufs_read_inode (data, GRUB_UFS_INODE);
+  if (grub_errno)
+    return grub_errno;
+  
+  sblock = &data->sblock;
+  
+  if (!path || path[0] != '/')
+    {
+      grub_error (GRUB_ERR_BAD_FILENAME, "bad filename");
+      return grub_errno;
+    }
+  
+  grub_ufs_find_file (data, path);
+  if (grub_errno)
+    goto fail;  
+  
+  if (!(INODE_MODE (data) & GRUB_UFS_ATTR_DIR))
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
+      goto fail;
+    }
+  
+  while (pos < INODE_SIZE (data))
+    {
+      struct grub_ufs_dirent dirent;
+      
+      if (grub_ufs_read_file (data, 0, pos, sizeof (dirent),
+                             (char *) &dirent) < 0)
+       break;
+      
+      {
+       char filename[dirent.namelen + 1];
+       
+       if (grub_ufs_read_file (data, 0, pos + sizeof (dirent),
+                               dirent.namelen, filename) < 0)
+         break;
+       
+       filename[dirent.namelen] = '\0';
+       if (hook (filename, dirent.filetype == GRUB_UFS_FILETYPE_DIR))
+         break;
+      }
+      
+      pos += grub_le_to_cpu16 (dirent.direntlen);
+    }
+
+ fail:
+  grub_free (data);
+
+  return grub_errno;
+}
+
+
+/* Open a file named NAME and initialize FILE.  */
+static grub_err_t
+grub_ufs_open (struct grub_file *file, const char *name)
+{
+  struct grub_ufs_data *data;
+  data = grub_ufs_mount (file->device->disk);
+  if (!data)
+    return grub_errno;
+  
+  grub_ufs_read_inode (data, 2);
+  if (grub_errno)
+    {
+      grub_free (data);
+      return grub_errno;
+    }
+    
+  if (!name || name[0] != '/')
+    {
+      grub_error (GRUB_ERR_BAD_FILENAME, "bad filename");
+      return grub_errno;
+    }
+  
+  grub_ufs_find_file (data, name);
+  if (grub_errno)
+    {
+      grub_free (data);
+      return grub_errno;
+    }
+  
+  file->data = data;
+  file->size = INODE_SIZE (data);
+
+  return GRUB_ERR_NONE;
+}
+
+
+static grub_ssize_t
+grub_ufs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_ufs_data *data = 
+    (struct grub_ufs_data *) file->data;
+  
+  return grub_ufs_read_file (data, file->read_hook, file->offset, len, buf);
+}
+
+
+static grub_err_t
+grub_ufs_close (grub_file_t file)
+{
+  grub_free (file->data);
+  
+  return GRUB_ERR_NONE;
+}
+
+
+static grub_err_t
+grub_ufs_label (grub_device_t device, char **label)
+{
+  struct grub_ufs_data *data = 0;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  *label = 0;
+
+  data = grub_ufs_mount (device->disk);
+  if (data)
+    {
+      if (data->ufs_type == UFS2)
+        *label = grub_strdup ((char *) data->sblock.volume_name);
+    }
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+}
+
+\f
+static struct grub_fs grub_ufs_fs =
+  {
+    .name = "ufs",
+    .dir = grub_ufs_dir,
+    .open = grub_ufs_open,
+    .read = grub_ufs_read,
+    .close = grub_ufs_close,
+    .label = grub_ufs_label,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(ufs)
+{
+  grub_fs_register (&grub_ufs_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(ufs)
+{
+  grub_fs_unregister (&grub_ufs_fs);
+}
+
diff --git a/fs/xfs.c b/fs/xfs.c
new file mode 100644 (file)
index 0000000..81a2771
--- /dev/null
+++ b/fs/xfs.c
@@ -0,0 +1,833 @@
+/* xfs.c - XFS.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2006,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/>.
+ */
+
+#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>
+
+#define        XFS_INODE_EXTENTS       9
+
+#define XFS_INODE_FORMAT_INO   1
+#define XFS_INODE_FORMAT_EXT   2
+#define XFS_INODE_FORMAT_BTREE 3
+
+
+struct grub_xfs_sblock
+{
+  grub_uint8_t magic[4];
+  grub_uint32_t bsize;
+  grub_uint8_t unused1[24];
+  grub_uint16_t uuid[8];
+  grub_uint8_t unused2[8];
+  grub_uint64_t rootino;
+  grub_uint8_t unused3[20];
+  grub_uint32_t agsize; 
+  grub_uint8_t unused4[20];
+  grub_uint8_t label[12];
+  grub_uint8_t log2_bsize;
+  grub_uint8_t unused5[2];
+  grub_uint8_t log2_inop;
+  grub_uint8_t log2_agblk;
+  grub_uint8_t unused6[67];
+  grub_uint8_t log2_dirblk;
+} __attribute__ ((packed));
+
+struct grub_xfs_dir_header
+{
+  grub_uint8_t count;
+  grub_uint8_t smallino;
+  union
+  {
+    grub_uint32_t i4;
+    grub_uint64_t i8;
+  } parent __attribute__ ((packed));
+} __attribute__ ((packed));
+
+struct grub_xfs_dir_entry
+{
+  grub_uint8_t len;
+  grub_uint16_t offset;
+  char name[1];
+  /* Inode number follows, 32 bits.  */
+} __attribute__ ((packed));
+
+struct grub_xfs_dir2_entry
+{
+  grub_uint64_t inode;
+  grub_uint8_t len;
+} __attribute__ ((packed));
+
+typedef grub_uint32_t grub_xfs_extent[4];
+
+struct grub_xfs_btree_node
+{
+  grub_uint8_t magic[4];
+  grub_uint16_t level;
+  grub_uint16_t numrecs;
+  grub_uint64_t left;
+  grub_uint64_t right;
+  grub_uint64_t keys[1];
+}  __attribute__ ((packed));
+
+struct grub_xfs_btree_root
+{
+  grub_uint16_t level;
+  grub_uint16_t numrecs;
+  grub_uint64_t keys[1];
+}  __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_uint64_t size;
+  grub_uint64_t nblocks;
+  grub_uint32_t extsize;
+  grub_uint32_t nextents;
+  grub_uint8_t unused3[20];
+  union
+  {
+    char raw[156];
+    struct dir
+    {
+      struct grub_xfs_dir_header dirhead;
+      struct grub_xfs_dir_entry direntry[1];
+    } dir;
+    grub_xfs_extent extents[XFS_INODE_EXTENTS];
+    struct grub_xfs_btree_root btree;
+  } data __attribute__ ((packed));
+} __attribute__ ((packed));
+
+struct grub_xfs_dirblock_tail
+{
+  grub_uint32_t leaf_count;
+  grub_uint32_t leaf_stale;
+} __attribute__ ((packed));
+
+struct grub_fshelp_node
+{
+  struct grub_xfs_data *data;
+  struct grub_xfs_inode inode;
+  grub_uint64_t ino;
+  int inode_read;
+};
+
+struct grub_xfs_data
+{
+  struct grub_xfs_sblock sblock;
+  struct grub_xfs_inode *inode;
+  grub_disk_t disk;
+  int pos;
+  int bsize;
+  int agsize;
+  struct grub_fshelp_node diropen;
+
+};
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+\f
+
+/* Filetype information as used in inodes.  */
+#define FILETYPE_INO_MASK      0170000
+#define FILETYPE_INO_REG       0100000
+#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) & ((1 << 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) & ((1 << (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)
+\f
+static inline int
+grub_xfs_inode_block (struct grub_xfs_data *data,
+                     grub_uint64_t ino)
+{
+  long long int inoinag = GRUB_XFS_INO_INOINAG (data, ino);
+  long long ag = GRUB_XFS_INO_AG (data, ino);
+  long long block;
+
+  block = (inoinag >> 4) + ag * data->agsize;
+  block <<= (data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS);
+  return block;
+}
+
+
+static inline int
+grub_xfs_inode_offset (struct grub_xfs_data *data,
+                      grub_uint64_t ino)
+{
+  int inoag = GRUB_XFS_INO_INOINAG (data, ino);
+  return (inoag & ((1 << 4) - 1)) << 8;
+}
+
+
+static grub_err_t
+grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
+                    struct grub_xfs_inode *inode)
+{
+  int block = grub_xfs_inode_block (data, ino);
+  int offset = grub_xfs_inode_offset (data, ino);
+
+  /* Read the inode.  */
+  if (grub_disk_read (data->disk, block, offset,
+                     sizeof (struct grub_xfs_inode), (char *) inode))
+    return grub_errno;
+
+  if (grub_strncmp ((char *) inode->magic, "IN", 2))
+    return grub_error (GRUB_ERR_BAD_FS, "not a correct XFS inode.\n");
+
+  return 0;
+}
+
+
+static grub_disk_addr_t
+grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
+{
+  struct grub_xfs_btree_node *leaf = 0;
+  int ex, nrec;
+  grub_xfs_extent *exts;
+  grub_uint64_t ret = 0;
+
+  if (node->inode.format == XFS_INODE_FORMAT_BTREE)
+    {
+      grub_uint64_t *keys;
+
+      leaf = grub_malloc (node->data->sblock.bsize);
+      if (leaf == 0)
+        return 0;
+
+      nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs);
+      keys = &node->inode.data.btree.keys[0];
+      do
+        {
+          int i;
+
+          for (i = 0; i < nrec; i++)
+            {
+              if (fileblock < grub_be_to_cpu64 (keys[i]))
+                break;
+            }
+
+          /* Sparse block.  */
+          if (i == 0)
+            {
+              grub_free (leaf);
+              return 0;
+            }
+
+          if (grub_disk_read (node->data->disk,
+                              grub_be_to_cpu64 (keys[i - 1 + XFS_INODE_EXTENTS])
+                              << (node->data->sblock.log2_bsize
+                                  - GRUB_DISK_SECTOR_BITS),
+                              0, node->data->sblock.bsize, (char *) leaf))
+            return 0;
+
+          if (grub_strncmp ((char *) leaf->magic, "BMAP", 4))
+            {
+              grub_free (leaf);
+              grub_error (GRUB_ERR_BAD_FS, "not a correct XFS BMAP node.\n");
+              return 0;
+            }
+
+          nrec = grub_be_to_cpu16 (leaf->numrecs);
+          keys = &leaf->keys[0];
+        } while (leaf->level);
+      exts = (grub_xfs_extent *) keys;
+    }
+  else if (node->inode.format == XFS_INODE_FORMAT_EXT)
+    {
+      nrec = grub_be_to_cpu32 (node->inode.nextents);
+      exts = &node->inode.data.extents[0];
+    }
+  else
+    {
+      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                 "xfs does not support inode format %d yet",
+                 node->inode.format);
+      return 0;
+    }
+
+  /* Iterate over each extent to figure out which extent has
+     the block we are looking for.  */
+  for (ex = 0; ex < nrec; ex++)
+    {
+      grub_uint64_t start = GRUB_XFS_EXTENT_BLOCK (exts, ex);
+      grub_uint64_t offset = GRUB_XFS_EXTENT_OFFSET (exts, ex);
+      grub_uint64_t size = GRUB_XFS_EXTENT_SIZE (exts, ex);
+
+      /* Sparse block.  */
+      if (fileblock < offset)
+        break;
+      else if (fileblock < offset + size)
+        {
+          ret = (fileblock - offset + start);
+          break;
+        }
+    }
+
+  if (leaf)
+    grub_free (leaf);
+
+  return GRUB_XFS_FSB_TO_BLOCK(node->data, ret);
+}
+
+
+/* Read LEN bytes from the file described by DATA starting with byte
+   POS.  Return the amount of read bytes in READ.  */
+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)
+{
+  return grub_fshelp_read_file (node->data->disk, node, read_hook,
+                               pos, len, buf, grub_xfs_read_block,
+                               grub_be_to_cpu64 (node->inode.size),
+                               node->data->sblock.log2_bsize
+                               - GRUB_DISK_SECTOR_BITS);
+}
+
+
+static char *
+grub_xfs_read_symlink (grub_fshelp_node_t node)
+{
+  int size = grub_be_to_cpu64 (node->inode.size);
+
+  switch (node->inode.format)
+    {
+    case XFS_INODE_FORMAT_INO:
+      return grub_strndup (node->inode.data.raw, size);
+
+    case XFS_INODE_FORMAT_EXT:
+      {
+       char *symlink;
+       grub_ssize_t numread;
+
+       symlink = grub_malloc (size + 1);
+       if (!symlink)
+         return 0;
+
+       numread = grub_xfs_read_file (node, 0, 0, size, symlink);
+       if (numread != size)
+         {
+           grub_free (symlink);
+           return 0;
+         }
+       symlink[size] = '\0';
+       return symlink;
+      }
+    }
+
+  return 0;
+}
+
+
+static enum grub_fshelp_filetype
+grub_xfs_mode_to_filetype (grub_uint16_t mode)
+{
+  if ((grub_be_to_cpu16 (mode)
+       & FILETYPE_INO_MASK) == FILETYPE_INO_DIRECTORY)
+    return GRUB_FSHELP_DIR;
+  else if ((grub_be_to_cpu16 (mode)
+           & FILETYPE_INO_MASK) == FILETYPE_INO_SYMLINK)
+    return GRUB_FSHELP_SYMLINK;
+  else if ((grub_be_to_cpu16 (mode)
+           & FILETYPE_INO_MASK) == FILETYPE_INO_REG)
+    return GRUB_FSHELP_REG;
+  return GRUB_FSHELP_UNKNOWN;
+}
+
+
+static int
+grub_xfs_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))
+{
+  struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
+  auto int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, char *filename);
+    
+  int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, char *filename)
+    {
+      struct grub_fshelp_node *fdiro;
+
+      fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
+      if (!fdiro)
+       return 0;
+             
+      /* The inode should be read, otherwise the filetype can
+        not be determined.  */
+      fdiro->ino = ino;
+      fdiro->inode_read = 1;
+      fdiro->data = diro->data;
+      grub_xfs_read_inode (diro->data, ino, &fdiro->inode);
+
+      return hook (filename,
+                  grub_xfs_mode_to_filetype (fdiro->inode.mode),
+                  fdiro);
+    }
+  
+  switch (diro->inode.format)
+    {
+    case XFS_INODE_FORMAT_INO:
+      {
+       struct grub_xfs_dir_entry *de = &diro->inode.data.dir.direntry[0];
+       int smallino = !diro->inode.data.dir.dirhead.smallino;
+       int i;
+       grub_uint64_t parent;
+
+       /* If small inode numbers are used to pack the direntry, the
+          parent inode number is small too.  */
+       if (smallino)
+         {
+           parent = grub_be_to_cpu32 (diro->inode.data.dir.dirhead.parent.i4);
+           parent = grub_cpu_to_be64 (parent);
+           /* The header is a bit smaller than usual.  */
+           de = (struct grub_xfs_dir_entry *) ((char *) de - 4);
+         }
+       else
+         {
+           parent = diro->inode.data.dir.dirhead.parent.i8;
+         }
+
+       /* Synthesize the direntries for `.' and `..'.  */
+       if (call_hook (diro->ino, "."))
+         return 1;
+
+       if (call_hook (parent, ".."))
+         return 1;
+
+       for (i = 0; i < diro->inode.data.dir.dirhead.count; i++)
+         {
+           grub_uint64_t ino;
+           void *inopos = (((char *) de)
+                           + sizeof (struct grub_xfs_dir_entry)
+                           + de->len - 1);
+           char name[de->len + 1];
+           
+           if (smallino)
+             {
+               ino = grub_be_to_cpu32 (*(grub_uint32_t *) inopos);
+               ino = grub_cpu_to_be64 (ino);
+             }
+           else
+             ino = *(grub_uint64_t *) inopos;
+
+           grub_memcpy (name, de->name, de->len);
+           name[de->len] = '\0';
+           if (call_hook (ino, name))
+             return 1;
+
+           de = ((struct grub_xfs_dir_entry *) 
+                 (((char *) de)+ sizeof (struct grub_xfs_dir_entry) + de->len
+                  + ((smallino ? sizeof (grub_uint32_t)
+                      : sizeof (grub_uint64_t))) - 1));
+         }
+       break;
+      }
+
+    case XFS_INODE_FORMAT_BTREE:
+    case XFS_INODE_FORMAT_EXT:
+      {
+       grub_ssize_t numread;
+       char *dirblock;
+       grub_uint64_t blk;
+        int dirblk_size, dirblk_log2;
+
+        dirblk_log2 = (dir->data->sblock.log2_bsize
+                       + dir->data->sblock.log2_dirblk);
+        dirblk_size = 1 << dirblk_log2;
+
+       dirblock = grub_malloc (dirblk_size);
+       if (! dirblock)
+         return 0;
+
+       /* Iterate over every block the directory has.  */
+       for (blk = 0;
+            blk < (grub_be_to_cpu64 (dir->inode.size) 
+                   >> dirblk_log2);
+            blk++)
+         {
+           /* The header is skipped, the first direntry is stored
+              from byte 16.  */
+           int pos = 16;
+           int entries;
+           int tail_start = (dirblk_size
+                             - sizeof (struct grub_xfs_dirblock_tail));
+
+           struct grub_xfs_dirblock_tail *tail;
+           tail = (struct grub_xfs_dirblock_tail *) &dirblock[tail_start];
+
+           numread = grub_xfs_read_file (dir, 0,
+                                         blk << dirblk_log2,
+                                         dirblk_size, dirblock);
+           if (numread != dirblk_size)
+             return 0;
+
+           entries = (grub_be_to_cpu32 (tail->leaf_count)
+                      - grub_be_to_cpu32 (tail->leaf_stale));
+
+           /* Iterate over all entries within this block.  */
+           while (pos < (dirblk_size
+                         - (int) sizeof (struct grub_xfs_dir2_entry)))
+             {
+               struct grub_xfs_dir2_entry *direntry;
+               grub_uint16_t *freetag;
+               char *filename;
+
+               direntry = (struct grub_xfs_dir2_entry *) &dirblock[pos];
+               freetag = (grub_uint16_t *) direntry;
+
+               if (*freetag == 0XFFFF)
+                 {
+                   grub_uint16_t *skip = (grub_uint16_t *) (freetag + 1);
+
+                   /* This entry is not used, go to the next one.  */
+                   pos += grub_be_to_cpu16 (*skip);
+
+                   continue;
+                 }
+
+               filename = &dirblock[pos + sizeof (*direntry)];
+               /* The byte after the filename is for the tag, which
+                  is not used by GRUB.  So it can be overwritten.  */
+               filename[direntry->len] = '\0';
+
+               if (call_hook (direntry->inode, filename))
+                 {
+                   grub_free (dirblock);
+                   return 1;
+                 }
+
+               /* Check if last direntry in this block is
+                  reached.  */
+               entries--;
+               if (!entries)
+                 break;
+
+               /* Select the next directory entry.  */
+               pos = GRUB_XFS_NEXT_DIRENT (pos, direntry->len);
+               pos = GRUB_XFS_ROUND_TO_DIRENT (pos);
+             }
+         }
+       grub_free (dirblock);
+       break;
+      }
+
+    default:
+      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                 "xfs does not support inode format %d yet",
+                 diro->inode.format);
+    }
+  return 0;
+}
+
+
+static struct grub_xfs_data *
+grub_xfs_mount (grub_disk_t disk)
+{
+  struct grub_xfs_data *data = 0;
+
+  data = grub_malloc (sizeof (struct grub_xfs_data));
+  if (!data)
+    return 0;
+
+  /* Read the superblock.  */
+  if (grub_disk_read (disk, 0, 0,
+                     sizeof (struct grub_xfs_sblock), (char *) &data->sblock))
+    goto fail;
+  
+  if (grub_strncmp ((char *) (data->sblock.magic), "XFSB", 4))
+    {
+      grub_error (GRUB_ERR_BAD_FS, "not a xfs filesystem");
+      goto fail;
+    }
+
+  data->diropen.data = data;
+  data->diropen.ino = data->sblock.rootino;
+  data->diropen.inode_read = 1;
+  data->bsize = grub_be_to_cpu32 (data->sblock.bsize);
+  data->agsize = grub_be_to_cpu32 (data->sblock.agsize);
+
+  data->disk = disk;
+  data->inode = &data->diropen.inode;
+  data->pos = 0;
+
+  grub_xfs_read_inode (data, data->diropen.ino, data->inode);
+
+  return data;
+ fail:
+  
+  if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+    grub_error (GRUB_ERR_BAD_FS, "not an xfs filesystem");
+
+  grub_free (data);
+  
+  return 0;
+}
+
+\f
+static grub_err_t
+grub_xfs_dir (grub_device_t device, const char *path, 
+             int (*hook) (const char *filename, int dir))
+{
+  struct grub_xfs_data *data = 0;;
+  struct grub_fshelp_node *fdiro = 0;
+  
+  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)
+    {
+      grub_free (node);
+      
+      if (filetype == GRUB_FSHELP_DIR)
+       return hook (filename, 1);
+      else 
+       return hook (filename, 0);
+      
+      return 0;
+    }
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  
+  data = grub_xfs_mount (device->disk);
+  if (!data)
+    goto fail;
+  
+  grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_xfs_iterate_dir,
+                        grub_xfs_read_symlink, GRUB_FSHELP_DIR);
+  if (grub_errno)
+    goto fail;
+
+  grub_xfs_iterate_dir (fdiro, iterate);
+  
+ fail:
+  if (fdiro != &data->diropen)
+    grub_free (fdiro);
+  grub_free (data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+
+  return 0;
+}
+
+
+/* Open a file named NAME and initialize FILE.  */
+static grub_err_t
+grub_xfs_open (struct grub_file *file, const char *name)
+{
+  struct grub_xfs_data *data;
+  struct grub_fshelp_node *fdiro = 0;
+  
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  
+  data = grub_xfs_mount (file->device->disk);
+  if (!data)
+    goto fail;
+  
+  grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_xfs_iterate_dir,
+                        grub_xfs_read_symlink, GRUB_FSHELP_REG);
+  if (grub_errno)
+    goto fail;
+  
+  if (!fdiro->inode_read)
+    {
+      grub_xfs_read_inode (data, fdiro->ino, &fdiro->inode);
+      if (grub_errno)
+       goto fail;
+    }
+  
+  grub_memcpy (data->inode,
+              &fdiro->inode,
+              sizeof (struct grub_xfs_inode));
+  grub_free (fdiro);
+
+  file->size = grub_be_to_cpu64 (data->inode->size);
+  file->data = data;
+  file->offset = 0;
+
+  return 0;
+
+ fail:
+  if (fdiro != &data->diropen)
+    grub_free (fdiro);
+  grub_free (data);
+  
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return grub_errno;
+}
+
+
+static grub_ssize_t
+grub_xfs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_xfs_data *data = 
+    (struct grub_xfs_data *) file->data;
+
+  return grub_xfs_read_file (&data->diropen, file->read_hook,
+                             file->offset, len, buf);
+}
+
+
+static grub_err_t
+grub_xfs_close (grub_file_t file)
+{
+  grub_free (file->data);
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
+
+static grub_err_t
+grub_xfs_label (grub_device_t device, char **label)
+{
+  struct grub_xfs_data *data;
+  grub_disk_t disk = device->disk;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_xfs_mount (disk);
+  if (data)
+    *label = grub_strndup ((char *) (data->sblock.label), 12);
+  else
+    *label = 0;
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_xfs_uuid (grub_device_t device, char **uuid)
+{
+  struct grub_xfs_data *data;
+  grub_disk_t disk = device->disk;
+
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+
+  data = grub_xfs_mount (disk);
+  if (data)
+    {
+      *uuid = grub_malloc (sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"));
+      grub_sprintf (*uuid, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
+                   grub_be_to_cpu16 (data->sblock.uuid[0]), grub_be_to_cpu16 (data->sblock.uuid[1]),
+                   grub_be_to_cpu16 (data->sblock.uuid[2]), grub_be_to_cpu16 (data->sblock.uuid[3]),
+                   grub_be_to_cpu16 (data->sblock.uuid[4]), grub_be_to_cpu16 (data->sblock.uuid[5]),
+                   grub_be_to_cpu16 (data->sblock.uuid[6]), grub_be_to_cpu16 (data->sblock.uuid[7]));
+    }
+  else
+    *uuid = NULL;
+
+#ifndef GRUB_UTIL
+  grub_dl_unref (my_mod);
+#endif
+
+  grub_free (data);
+
+  return grub_errno;
+}
+
+\f
+
+static struct grub_fs grub_xfs_fs =
+  {
+    .name = "xfs",
+    .dir = grub_xfs_dir,
+    .open = grub_xfs_open,
+    .read = grub_xfs_read,
+    .close = grub_xfs_close,
+    .label = grub_xfs_label,
+    .uuid = grub_xfs_uuid,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(xfs)
+{
+  grub_fs_register (&grub_xfs_fs);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(xfs)
+{
+  grub_fs_unregister (&grub_xfs_fs);
+}
diff --git a/gencmdlist.sh b/gencmdlist.sh
new file mode 100644 (file)
index 0000000..5955066
--- /dev/null
@@ -0,0 +1,18 @@
+#! /bin/sh
+#
+# Copyright (C) 2005  Free Software Foundation, Inc.
+#
+# This gensymlist.sh is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# Read source code from stdin and detect command names.
+
+module=$1
+
+grep -v "^#" | sed -ne "/grub_register_command *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $module/;p;}"
diff --git a/gendistlist.sh b/gendistlist.sh
new file mode 100755 (executable)
index 0000000..011554d
--- /dev/null
@@ -0,0 +1,43 @@
+#! /bin/sh
+#
+# Copyright (C) 2005, 2008, 2009  Free Software Foundation, Inc.
+#
+# This gendistlist.sh is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# Generate a list of distributed files.
+
+EXTRA_DISTFILES="AUTHORS COPYING ChangeLog DISTLIST INSTALL NEWS README \
+       THANKS TODO Makefile.in aclocal.m4 autogen.sh config.guess \
+       config.h.in config.sub configure configure.ac gencmdlist.sh \
+       gendistlist.sh genfslist.sh geninit.sh geninitheader.sh genkernsyms.sh.in \
+       genmk.rb genmoddep.awk genmodsrc.sh genpartmaplist.sh gensymlist.sh.in
+       install-sh mkinstalldirs stamp-h.in"
+
+DISTDIRS="boot bus commands conf disk docs font fs hello hook include io kern lib \
+       loader normal partmap term util video"
+
+LC_COLLATE=C
+export LC_COLLATE
+
+for f in $EXTRA_DISTFILES; do
+    echo $f
+done
+
+dir=`dirname $0`
+cd $dir
+
+for dir in $DISTDIRS; do
+  for d in `find $dir -type d | sed '/\/\.svn$/d;\/\.svn\//d' | sort`; do
+    find $d -maxdepth 1 -name '*.[chSy]' -o -name '*.mk' -o -name '*.rmk' \
+      -o -name '*.rb' -o -name '*.in' -o -name '*.tex' -o -name '*.texi' \
+      -o -name 'grub.cfg' -o -name 'README' -o -name '*.sc' -o -name 'mdate.sh' \
+      | sort
+  done
+done
diff --git a/genfslist.sh b/genfslist.sh
new file mode 100644 (file)
index 0000000..6fa7e92
--- /dev/null
@@ -0,0 +1,26 @@
+#! /bin/sh
+#
+# Copyright (C) 2005,2008  Free Software Foundation, Inc.
+#
+# This gensymlist.sh is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# Read source code from stdin and detect fs names.
+
+module=$1
+
+# Ignore kernel.mod.
+if test $module = kernel; then
+    exit
+fi
+
+# For now, this emits only a module name, if the module registers a filesystem.
+if grep -v "^#" | grep '^ *grub_fs_register' >/dev/null 2>&1; then
+    echo $module
+fi
diff --git a/geninit.sh b/geninit.sh
new file mode 100644 (file)
index 0000000..43d2d16
--- /dev/null
@@ -0,0 +1,75 @@
+#! /bin/sh
+#
+# Copyright (C) 2002,2005,2007  Free Software Foundation, Inc.
+#
+# This gensymlist.sh is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+lst="$1"
+shift
+
+header=`echo "${lst}" | sed -e "s/\.lst$/.h/g"`
+
+cat <<EOF
+/* This file is automatically generated by geninit.sh. DO NOT EDIT! */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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/>.
+ */
+
+#include <$header>
+
+EOF
+
+cat <<EOF
+void
+grub_init_all (void)
+{
+EOF
+
+while read line; do
+  file=`echo $line | cut -f1 -d:`
+  if echo $@ | grep $file >/dev/null; then
+    echo $line | sed -e 's/.*GRUB_MOD_INIT *(\([a-zA-Z0-9_]*\)).*/  grub_\1_init ();/'
+  fi
+done < ${lst}
+
+cat <<EOF
+}
+EOF
+
+cat <<EOF
+void
+grub_fini_all (void)
+{
+EOF
+
+while read line; do
+  file=`echo $line | cut -f1 -d:`
+  if echo $@ | grep $file >/dev/null; then
+    echo $line | sed -e 's/.*GRUB_MOD_INIT *(\([a-zA-Z0-9_]*\)).*/  grub_\1_fini ();/'
+  fi
+done < ${lst}
+
+cat <<EOF
+}
+EOF
diff --git a/geninitheader.sh b/geninitheader.sh
new file mode 100644 (file)
index 0000000..5ad1428
--- /dev/null
@@ -0,0 +1,45 @@
+#! /bin/sh
+#
+# Copyright (C) 2005,2007  Free Software Foundation, Inc.
+#
+# This gensymlist.sh is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+lst="$1"
+shift
+
+cat <<EOF
+/* This file is automatically generated by gensymlist.sh. DO NOT EDIT! */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+EOF
+
+cat <<EOF
+void grub_init_all (void);
+void grub_fini_all (void);
+EOF
+
+grep -v '^#' "${lst}" | sed -n '/GRUB_MOD_INIT *([a-zA-Z0-9_]*)/{s/.*GRUB_MOD_INIT *(\([a-zA-Z0-9_]*\)).*/void grub_\1_init (void);/;p;}'
+grep -v '^#' "${lst}" | sed -n '/GRUB_MOD_INIT *([a-zA-Z0-9_]*)/{s/.*GRUB_MOD_INIT *(\([a-zA-Z0-9_]*\)).*/void grub_\1_fini (void);/;p;}'
diff --git a/genkernsyms.sh.in b/genkernsyms.sh.in
new file mode 100644 (file)
index 0000000..3dec582
--- /dev/null
@@ -0,0 +1,27 @@
+#! /bin/sh
+#
+# Copyright (C) 2002,2006,2008  Free Software Foundation, Inc.
+#
+# This gensymlist.sh is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+### The configure script will replace these variables.
+
+: ${srcdir=@srcdir@}
+: ${CC=@CC@}
+
+u=
+grep "^#define HAVE_ASM_USCORE" config.h >/dev/null 2>&1 && u="_"
+
+$CC -DGRUB_SYMBOL_GENERATOR=1 -E -I. -Iinclude -I"$srcdir/include" $* \
+  | grep -v '^#' \
+  | sed -n \
+        -e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/'"$u"'\1 kernel/;p;}' \
+        -e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/'"$u"'\1 kernel/;p;}' \
+  | sort -u
diff --git a/genmk.rb b/genmk.rb
new file mode 100644 (file)
index 0000000..c41872c
--- /dev/null
+++ b/genmk.rb
@@ -0,0 +1,359 @@
+#! /usr/bin/ruby -w
+#
+# Copyright (C) 2002,2003,2004,2005,2006,2007,2008  Free Software Foundation, Inc.
+#
+# This genmk.rb is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+module Enumerable
+  def collect_with_index
+    ret = []
+    self.each_with_index do |item, index|
+      ret.push(yield(item, index))
+    end
+    ret
+  end
+end
+
+class String
+  def to_var
+    self.gsub(/[^a-zA-Z0-9_@]/, '_')
+  end
+
+  def suffix(str)
+    self.sub(/\.[^\.]*$/, '') + '.' + str
+  end
+
+  def to_obj
+    self.sub(/\.[^\.]*$/, '').to_var + '.o'
+  end
+end
+
+class Image
+  def initialize(dir, name)
+    @dir = dir
+    @name = name
+  end
+  attr_reader :dir, :name
+
+  def rule(sources)
+    prefix = @name.to_var
+    exe = @name.suffix('exec')
+    objs = sources.collect do |src|
+      raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src
+      prefix + '-' + src.to_obj
+    end
+    objs_str = objs.join(' ')
+    deps = objs.collect {|obj| obj.suffix('d')}
+    deps_str = deps.join(' ')
+    
+    "CLEANFILES += #{@name} #{exe} #{objs_str}
+MOSTLYCLEANFILES += #{deps_str}
+
+#{@name}: #{exe}
+       $(OBJCOPY) -O binary -R .note -R .comment -R .note.gnu.build-id $< $@
+
+#{exe}: #{objs_str}
+       $(TARGET_CC) -o $@ $^ $(TARGET_LDFLAGS) $(#{prefix}_LDFLAGS)
+
+" + objs.collect_with_index do |obj, i|
+      src = sources[i]
+      fake_obj = File.basename(src).suffix('o')
+      dep = deps[i]
+      flag = if /\.c$/ =~ src then 'CFLAGS' else 'ASFLAGS' end
+      extra_flags = if /\.S$/ =~ src then '-DASM_FILE=1' else '' end
+      dir = File.dirname(src)
+      
+      "#{obj}: #{src} $(#{src}_DEPENDENCIES)
+       $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -MD -c -o $@ $<
+-include #{dep}
+
+"
+    end.join('')
+  end
+end
+
+# Use PModule instead Module, to avoid name conflicting.
+class PModule
+  def initialize(dir, name)
+    @dir = dir
+    @name = name
+  end
+  attr_reader :dir, :name
+
+  def rule(sources)
+    prefix = @name.to_var
+    objs = sources.collect do |src|
+      raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src
+      prefix + '-' + src.to_obj
+    end
+    objs_str = objs.join(' ')
+    deps = objs.collect {|obj| obj.suffix('d')}
+    deps_str = deps.join(' ')
+    pre_obj = 'pre-' + @name.suffix('o')
+    mod_src = 'mod-' + @name.suffix('c')
+    mod_obj = mod_src.suffix('o')
+    defsym = 'def-' + @name.suffix('lst')
+    undsym = 'und-' + @name.suffix('lst')
+    mod_name = File.basename(@name, '.mod')
+    symbolic_name = mod_name.sub(/\.[^\.]*$/, '')
+    
+    "CLEANFILES += #{@name} #{mod_obj} #{mod_src} #{pre_obj} #{objs_str} #{undsym}
+ifneq ($(#{prefix}_EXPORTS),no)
+CLEANFILES += #{defsym}
+DEFSYMFILES += #{defsym}
+endif
+MOSTLYCLEANFILES += #{deps_str}
+UNDSYMFILES += #{undsym}
+
+#{@name}: #{pre_obj} #{mod_obj} $(TARGET_OBJ2ELF)
+       -rm -f $@
+       $(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ #{pre_obj} #{mod_obj}
+       if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+#{pre_obj}: $(#{prefix}_DEPENDENCIES) #{objs_str}
+       -rm -f $@
+       $(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ #{objs_str}
+
+#{mod_obj}: #{mod_src}
+       $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(#{prefix}_CFLAGS) -c -o $@ $<
+
+#{mod_src}: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '#{mod_name}' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(#{prefix}_EXPORTS),no)
+#{defsym}: #{pre_obj}
+       $(NM) -g --defined-only -P -p $< | sed 's/^\\([^ ]*\\).*/\\1 #{mod_name}/' > $@
+endif
+
+#{undsym}: #{pre_obj}
+       echo '#{mod_name}' > $@
+       $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+" + objs.collect_with_index do |obj, i|
+      src = sources[i]
+      fake_obj = File.basename(src).suffix('o')
+      command = 'cmd-' + obj.suffix('lst')
+      fs = 'fs-' + obj.suffix('lst')
+      partmap = 'partmap-' + obj.suffix('lst')
+      dep = deps[i]
+      flag = if /\.c$/ =~ src then 'CFLAGS' else 'ASFLAGS' end
+      extra_flags = if /\.S$/ =~ src then '-DASM_FILE=1' else '' end
+      dir = File.dirname(src)
+
+      "#{obj}: #{src} $(#{src}_DEPENDENCIES)
+       $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -MD -c -o $@ $<
+-include #{dep}
+
+CLEANFILES += #{command} #{fs} #{partmap}
+COMMANDFILES += #{command}
+FSFILES += #{fs}
+PARTMAPFILES += #{partmap}
+
+#{command}: #{src} $(#{src}_DEPENDENCIES) gencmdlist.sh
+       set -e; \
+         $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \
+         | sh $(srcdir)/gencmdlist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1)
+
+#{fs}: #{src} $(#{src}_DEPENDENCIES) genfslist.sh
+       set -e; \
+         $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \
+         | sh $(srcdir)/genfslist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1)
+
+#{partmap}: #{src} $(#{src}_DEPENDENCIES) genpartmaplist.sh
+       set -e; \
+         $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \
+         | sh $(srcdir)/genpartmaplist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1)
+
+
+"
+    end.join('')
+  end
+end
+
+class Utility
+  def initialize(dir, name)
+    @dir = dir
+    @name = name
+  end
+  attr_reader :dir, :name
+
+  def rule(sources)
+    prefix = @name.to_var
+    objs = sources.collect do |src|
+      raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src
+      prefix + '-' + src.to_obj
+    end
+    objs_str = objs.join(' ');
+    deps = objs.collect {|obj| obj.suffix('d')}
+    deps_str = deps.join(' ');
+
+    "CLEANFILES += #{@name}$(EXEEXT) #{objs_str}
+MOSTLYCLEANFILES += #{deps_str}
+
+#{@name}: $(#{prefix}_DEPENDENCIES) #{objs_str}
+       $(CC) -o $@ #{objs_str} $(LDFLAGS) $(#{prefix}_LDFLAGS)
+
+" + objs.collect_with_index do |obj, i|
+      src = sources[i]
+      fake_obj = File.basename(src).suffix('o')
+      dep = deps[i]
+      dir = File.dirname(src)
+
+      "#{obj}: #{src} $(#{src}_DEPENDENCIES)
+       $(CC) -I#{dir} -I$(srcdir)/#{dir} $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(#{prefix}_CFLAGS) -MD -c -o $@ $<
+-include #{dep}
+
+"
+    end.join('')
+  end
+end
+
+class Program
+  def initialize(dir, name)
+    @dir = dir
+    @name = name
+  end
+  attr_reader :dir, :name
+
+  def rule(sources)
+    prefix = @name.to_var
+    objs = sources.collect do |src|
+      raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src
+      prefix + '-' + src.to_obj
+    end
+    objs_str = objs.join(' ');
+    deps = objs.collect {|obj| obj.suffix('d')}
+    deps_str = deps.join(' ');
+
+    "CLEANFILES += #{@name} #{objs_str}
+MOSTLYCLEANFILES += #{deps_str}
+
+#{@name}: $(#{prefix}_DEPENDENCIES) #{objs_str}
+       $(TARGET_CC) -o $@ #{objs_str} $(TARGET_LDFLAGS) $(#{prefix}_LDFLAGS)
+
+" + objs.collect_with_index do |obj, i|
+      src = sources[i]
+      fake_obj = File.basename(src).suffix('o')
+      dep = deps[i]
+      dir = File.dirname(src)
+
+      "#{obj}: #{src} $(#{src}_DEPENDENCIES)
+       $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(#{prefix}_CFLAGS) -MD -c -o $@ $<
+-include #{dep}
+
+"
+    end.join('')
+  end
+end
+
+class Script
+  def initialize(dir, name)
+    @dir = dir
+    @name = name
+  end
+  attr_reader :dir, :name
+
+  def rule(sources)
+    if sources.length != 1
+      raise "only a single source file must be specified for a script"
+    end
+    src = sources[0]
+    if /\.in$/ !~ src
+      raise "unknown source file `#{src}'" 
+    end
+
+    "CLEANFILES += #{@name}
+
+#{@name}: #{src} $(#{src}_DEPENDENCIES) config.status
+       ./config.status --file=#{name}:#{src}
+       chmod +x $@
+
+"
+  end
+end
+
+images = []
+utils = []
+pmodules = []
+programs = []
+scripts = []
+
+l = gets
+print l
+print "# Generated by genmk.rb, please don't edit!\n"
+
+cont = false
+s = nil
+while l = gets
+  if cont
+    s += l
+  else
+    s = l
+  end
+
+  print l
+  cont = (/\\$/ =~ l)
+  unless cont
+    s.gsub!(/\\\n/, ' ')
+    
+    if /^([a-zA-Z0-9_]+)\s*\+?=\s*(.*?)\s*$/ =~ s
+      var, args = $1, $2
+
+      if var =~ /^([a-zA-Z0-9_]+)_([A-Z]+)$/
+       prefix, type = $1, $2
+
+       case type
+       when 'IMAGES'
+         images += args.split(/\s+/).collect do |img|
+           Image.new(prefix, img)
+         end
+
+       when 'MODULES'
+         pmodules += args.split(/\s+/).collect do |pmod|
+           PModule.new(prefix, pmod)
+         end
+         
+       when 'UTILITIES'
+         utils += args.split(/\s+/).collect do |util|
+           Utility.new(prefix, util)
+         end
+
+       when 'PROGRAMS'
+         programs += args.split(/\s+/).collect do |prog|
+           Program.new(prefix, prog)
+         end
+
+       when 'SCRIPTS'
+         scripts += args.split(/\s+/).collect do |script|
+           Script.new(prefix, script)
+         end
+
+       when 'SOURCES'
+         if img = images.detect() {|i| i.name.to_var == prefix}
+           print img.rule(args.split(/\s+/))
+         elsif pmod = pmodules.detect() {|m| m.name.to_var == prefix}
+           print pmod.rule(args.split(/\s+/))
+         elsif util = utils.detect() {|u| u.name.to_var == prefix}
+           print util.rule(args.split(/\s+/))
+         elsif program = programs.detect() {|u| u.name.to_var == prefix}
+           print program.rule(args.split(/\s+/))
+         elsif script = scripts.detect() {|s| s.name.to_var == prefix}
+           print script.rule(args.split(/\s+/))
+         end
+       end
+      end
+      
+    end
+    
+  end
+  
+end
+
diff --git a/genmoddep.awk b/genmoddep.awk
new file mode 100644 (file)
index 0000000..c079b36
--- /dev/null
@@ -0,0 +1,62 @@
+#! /usr/bin/awk -f
+#
+# Copyright (C) 2006  Free Software Foundation, Inc.
+#
+# This genmoddep.awk is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# Read defined symbols from stdin.
+BEGIN {
+  while (getline <"/dev/stdin") {
+    symtab[$1] = $2
+  }
+}
+
+# The first line contains a module name.
+FNR == 1 {
+  module = $1
+  next
+};
+
+# The rest is undefined symbols.
+{
+  if ($1 in symtab) {
+    modtab[module] = modtab[module] " " symtab[$1];
+  }
+  else {
+    printf "%s in %s is not defined\n", $1, module >"/dev/stderr";
+    error++;
+    exit;
+  }
+}
+
+# Output the result.
+END {
+  if (error == 1)
+    exit 1;
+  
+  for (mod in modtab) {
+    # Remove duplications.
+    split(modtab[mod], depmods, " ");
+    for (depmod in uniqmods) {
+      delete uniqmods[depmod];
+    }
+    for (i in depmods) {
+      depmod = depmods[i];
+      # Ignore kernel, as always loaded.
+      if (depmod != "kernel")
+       uniqmods[depmod] = 1;
+    }
+    modlist = ""
+    for (depmod in uniqmods) {
+      modlist = modlist " " depmod;
+    }
+    printf "%s:%s\n", mod, modlist;
+  }
+}
diff --git a/genmodsrc.sh b/genmodsrc.sh
new file mode 100644 (file)
index 0000000..2d42055
--- /dev/null
@@ -0,0 +1,47 @@
+#! /bin/sh
+#
+# Copyright (C) 2002,2007  Free Software Foundation, Inc.
+#
+# This genmodsrc.sh is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+set -e
+
+mod_name="$1"
+deps="$2"
+
+cat <<EOF
+/* This file is automatically generated by genmodsrc.sh. DO NOT EDIT! */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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/>.
+ */
+
+#include <grub/dl.h>
+
+EOF
+
+echo "GRUB_MOD_NAME(${mod_name});"
+
+for mod in `grep "^${mod_name}:" ${deps} | sed 's/^[^:]*://'`; do
+  echo "GRUB_MOD_DEP(${mod});"
+done
diff --git a/genpartmaplist.sh b/genpartmaplist.sh
new file mode 100644 (file)
index 0000000..fceb0f8
--- /dev/null
@@ -0,0 +1,26 @@
+#! /bin/sh
+#
+# Copyright (C) 2005, 2008  Free Software Foundation, Inc.
+#
+# This script is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# Read source code from stdin and detect partmap names.
+
+module=$1
+
+# Ignore kernel.mod.
+if test $module = kernel; then
+    exit
+fi
+
+# For now, this emits only a module name, if the module registers a partition map.
+if grep -v "^#" | grep '^ *grub_partition_map_register' >/dev/null 2>&1; then
+    echo $module
+fi
diff --git a/gensymlist.sh.in b/gensymlist.sh.in
new file mode 100644 (file)
index 0000000..8f50b99
--- /dev/null
@@ -0,0 +1,77 @@
+#! /bin/sh
+#
+# Copyright (C) 2002,2006,2007,2008  Free Software Foundation, Inc.
+#
+# This gensymlist.sh.in is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+### The configure script will replace these variables.
+
+: ${srcdir=@srcdir@}
+: ${CC=@CC@}
+
+
+cat <<EOF
+/* This file is automatically generated by gensymlist.sh. DO NOT EDIT! */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2006,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/>.
+ */
+
+EOF
+
+for i in $*; do
+  echo "#include <$i>"
+done
+
+cat <<EOF
+
+#define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; }
+
+void
+grub_register_exported_symbols (void)
+{
+EOF
+
+cat <<EOF
+  struct symtab { const char *name; void *addr; };
+  struct symtab *p;
+  static struct symtab tab[] =
+    {
+EOF
+
+$CC -DGRUB_SYMBOL_GENERATOR=1 -E -I. -Iinclude -I"$srcdir/include" $* \
+  | 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;}' \
+  | sort -u
+
+cat <<EOF
+      {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);
+}
+EOF
diff --git a/hello/hello.c b/hello/hello.c
new file mode 100644 (file)
index 0000000..70cbf60
--- /dev/null
@@ -0,0 +1,47 @@
+/* hello.c - test module for dynamic loading */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2007  Free Software Foundation, Inc.
+ *  Copyright (C) 2003  NIIBE Yutaka <gniibe@m17n.org>
+ *
+ *  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/normal.h>
+
+static grub_err_t
+grub_cmd_hello (struct grub_arg_list *state __attribute__ ((unused)),
+               int argc __attribute__ ((unused)),
+               char **args __attribute__ ((unused)))
+{
+  grub_printf ("Hello World\n");
+  return 0;
+}
+
+GRUB_MOD_INIT(hello)
+{
+  (void)mod;                   /* To stop warning. */
+  grub_register_command ("hello", grub_cmd_hello, GRUB_COMMAND_FLAG_BOTH,
+                        "hello", "Say hello", 0);
+}
+
+GRUB_MOD_FINI(hello)
+{
+  grub_unregister_command ("hello");
+}
diff --git a/hook/datehook.c b/hook/datehook.c
new file mode 100644 (file)
index 0000000..9419d48
--- /dev/null
@@ -0,0 +1,106 @@
+/* datehook.c - Module to install datetime hooks.  */
+/*
+ *  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/dl.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/lib/datetime.h>
+
+static char *grub_datetime_names[] =
+{
+  "YEAR",
+  "MONTH",
+  "DAY",
+  "HOUR",
+  "MINUTE",
+  "SECOND",
+  "WEEKDAY",
+};
+
+static char *
+grub_read_hook_datetime (struct grub_env_var *var,
+                         const char *val __attribute__ ((unused)))
+{
+  struct grub_datetime datetime;
+  static char buf[6];
+
+  buf[0] = 0;
+  if (! grub_get_datetime (&datetime))
+    {
+      int i;
+
+      for (i = 0; i < 7; i++)
+        if (! grub_strcmp (var->name, grub_datetime_names[i]))
+          {
+            int n;
+
+            switch (i)
+              {
+              case 0:
+                n = datetime.year;
+                break;
+              case 1:
+                n = datetime.month;
+                break;
+              case 2:
+                n = datetime.day;
+                break;
+              case 3:
+                n = datetime.hour;
+                break;
+              case 4:
+                n = datetime.minute;
+                break;
+              case 5:
+                n = datetime.second;
+                break;
+              default:
+                return grub_get_weekday_name (&datetime);
+              }
+
+            grub_sprintf (buf, "%d", n);
+            break;
+          }
+    }
+
+  return buf;
+}
+
+GRUB_MOD_INIT(datetime)
+{
+  (void)mod;                   /* To stop warning. */
+  int i;
+
+  for (i = 0; i < 7; i++)
+    grub_register_variable_hook (grub_datetime_names[i],
+                                 grub_read_hook_datetime, 0);
+}
+
+GRUB_MOD_FINI(datetime)
+{
+  int i;
+
+  for (i = 0; i < 7; i++)
+    {
+      grub_register_variable_hook (grub_datetime_names[i], 0, 0);
+      grub_env_unset (grub_datetime_names[i]);
+    }
+}
diff --git a/include/grub/acorn_filecore.h b/include/grub/acorn_filecore.h
new file mode 100644 (file)
index 0000000..6cda6cf
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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 GRUB_ACORN_FILECORE_HEADER
+#define GRUB_ACORN_FILECORE_HEADER     1
+
+#include <grub/types.h>
+
+struct grub_filecore_disc_record
+{
+  grub_uint8_t log2secsize;
+  grub_uint8_t secspertrack;
+  grub_uint8_t heads;
+  grub_uint8_t density;
+  grub_uint8_t idlen;
+  grub_uint8_t log2bpmb;
+  grub_uint8_t skew;
+  grub_uint8_t bootoption;
+  /* In bits 0-5, flags in bits 6 and 7.  */
+  grub_uint8_t lowsector;
+  grub_uint8_t nzones;
+  grub_uint16_t zone_spare;
+  grub_uint32_t root_address;
+  /* Disc size in bytes.  */
+  grub_uint32_t disc_size;
+  grub_uint16_t cycle_id;
+  char disc_name[10];
+  /* Yes, it is 32 bits!  */
+  grub_uint32_t disctype;
+  /* Most significant part of the disc size.  */
+  grub_uint32_t disc_size2;
+  grub_uint8_t share_size;
+  grub_uint8_t big_flag;
+  grub_uint8_t reserved[18];
+};
+
+
+#endif /* ! GRUB_ACORN_FILECORE_HEADER */
diff --git a/include/grub/aout.h b/include/grub/aout.h
new file mode 100644 (file)
index 0000000..c5650dd
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ *  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_AOUT_HEADER
+#define GRUB_AOUT_HEADER 1
+
+#include <grub/types.h>
+
+struct grub_aout32_header
+{
+  grub_uint32_t a_midmag;      /* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint32_t a_text;                /* text segment size */
+  grub_uint32_t a_data;                /* initialized data size */
+  grub_uint32_t a_bss;         /* uninitialized data size */
+  grub_uint32_t a_syms;                /* symbol table size */
+  grub_uint32_t a_entry;       /* entry point */
+  grub_uint32_t a_trsize;      /* text relocation size */
+  grub_uint32_t a_drsize;      /* data relocation size */
+};
+
+struct grub_aout64_header
+{
+  grub_uint32_t a_midmag;      /* htonl(flags<<26 | mid<<16 | magic) */
+  grub_uint64_t a_text;                /* text segment size */
+  grub_uint64_t a_data;                /* initialized data size */
+  grub_uint64_t a_bss;         /* uninitialized data size */
+  grub_uint64_t a_syms;                /* symbol table size */
+  grub_uint64_t a_entry;       /* entry point */
+  grub_uint64_t a_trsize;      /* text relocation size */
+  grub_uint64_t a_drsize;      /* data relocation size */
+};
+
+union grub_aout_header
+{
+  struct grub_aout32_header aout32;
+  struct grub_aout64_header aout64;
+};
+
+#define AOUT_TYPE_NONE         0
+#define AOUT_TYPE_AOUT32       1
+#define AOUT_TYPE_AOUT64       6
+
+#define        AOUT32_OMAGIC           0x107   /* 0407 old impure format */
+#define        AOUT32_NMAGIC           0x108   /* 0410 read-only text */
+#define        AOUT32_ZMAGIC           0x10b   /* 0413 demand load format */
+#define AOUT32_QMAGIC          0xcc    /* 0314 "compact" demand load format */
+
+#define AOUT64_OMAGIC          0x1001
+#define AOUT64_ZMAGIC          0x1002
+#define AOUT64_NMAGIC          0x1003
+
+#define        AOUT_MID_ZERO           0       /* unknown - implementation dependent */
+#define        AOUT_MID_SUN010         1       /* sun 68010/68020 binary */
+#define        AOUT_MID_SUN020         2       /* sun 68020-only binary */
+#define AOUT_MID_I386          134     /* i386 BSD binary */
+#define AOUT_MID_SPARC         138     /* sparc */
+#define        AOUT_MID_HP200          200     /* hp200 (68010) BSD binary */
+#define        AOUT_MID_HP300          300     /* hp300 (68020+68881) BSD binary */
+#define        AOUT_MID_HPUX           0x20C   /* hp200/300 HP-UX binary */
+#define        AOUT_MID_HPUX800        0x20B   /* hp800 HP-UX binary */
+
+#define AOUT_FLAG_PIC          0x10    /* contains position independent code */
+#define AOUT_FLAG_DYNAMIC      0x20    /* contains run-time link-edit info */
+#define AOUT_FLAG_DPMASK       0x30    /* mask for the above */
+
+#define AOUT_GETMAGIC(header) ((header).a_midmag & 0xffff)
+#define AOUT_GETMID(header) ((header).a_midmag >> 16) & 0x03ff)
+#define AOUT_GETFLAG(header) ((header).a_midmag >> 26) & 0x3f)
+
+int EXPORT_FUNC(grub_aout_get_type) (union grub_aout_header *header);
+
+grub_err_t EXPORT_FUNC(grub_aout_load) (grub_file_t file, int offset,
+                                        grub_addr_t load_addr, int load_size,
+                                        grub_addr_t bss_end_addr);
+
+#endif /* ! GRUB_AOUT_HEADER */
diff --git a/include/grub/arg.h b/include/grub/arg.h
new file mode 100644 (file)
index 0000000..bb9ce7b
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,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 GRUB_ARG_HEADER
+#define GRUB_ARG_HEADER        1
+
+#include <grub/symbol.h>
+#include <grub/err.h>
+#include <grub/types.h>
+
+enum grub_arg_type
+  {
+    ARG_TYPE_NONE,
+    ARG_TYPE_STRING,
+    ARG_TYPE_INT,
+    ARG_TYPE_DEVICE,
+    ARG_TYPE_FILE,
+    ARG_TYPE_DIR,
+    ARG_TYPE_PATHNAME
+  };
+
+typedef enum grub_arg_type grub_arg_type_t;
+
+/* Flags for the option field op grub_arg_option.  */
+#define GRUB_ARG_OPTION_OPTIONAL       (1 << 1)
+
+enum grub_key_type
+  {
+    GRUB_KEY_ARG = -1,
+    GRUB_KEY_END = -2
+  };
+typedef enum grub_key_type grub_arg_key_type_t;
+
+struct grub_arg_option
+{
+  const char *longarg;
+  int shortarg;
+  int flags;
+  char *doc;
+  char *arg;
+  grub_arg_type_t type;
+};
+
+struct grub_arg_list
+{
+  int set;
+  char *arg;
+};
+
+#endif /* ! GRUB_ARG_HEADER */
diff --git a/include/grub/ata.h b/include/grub/ata.h
new file mode 100644 (file)
index 0000000..aaa2e14
--- /dev/null
@@ -0,0 +1,168 @@
+/* ata.h - ATA disk access.  */
+/*
+ *  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_ATA_HEADER
+#define GRUB_ATA_HEADER 1
+
+#include <grub/misc.h>
+#include <grub/symbol.h>
+/* XXX: For now this only works on i386.  */
+#include <grub/cpu/io.h>
+
+typedef enum
+  {
+    GRUB_ATA_CHS,
+    GRUB_ATA_LBA,
+    GRUB_ATA_LBA48
+  } grub_ata_addressing_t;
+
+#define GRUB_ATA_REG_DATA      0
+#define GRUB_ATA_REG_ERROR     1
+#define GRUB_ATA_REG_FEATURES  1
+#define GRUB_ATA_REG_SECTORS   2
+#define GRUB_ATAPI_REG_IREASON 2
+#define GRUB_ATA_REG_SECTNUM   3
+#define GRUB_ATA_REG_CYLLSB    4
+#define GRUB_ATA_REG_CYLMSB    5
+#define GRUB_ATA_REG_LBALOW    3
+#define GRUB_ATA_REG_LBAMID    4
+#define GRUB_ATAPI_REG_CNTLOW  4
+#define GRUB_ATA_REG_LBAHIGH   5
+#define GRUB_ATAPI_REG_CNTHIGH 5
+#define GRUB_ATA_REG_DISK      6
+#define GRUB_ATA_REG_CMD       7
+#define GRUB_ATA_REG_STATUS    7
+
+#define GRUB_ATA_REG2_CONTROL  0
+
+#define GRUB_ATA_STATUS_ERR    0x01
+#define GRUB_ATA_STATUS_INDEX  0x02
+#define GRUB_ATA_STATUS_ECC    0x04
+#define GRUB_ATA_STATUS_DRQ    0x08
+#define GRUB_ATA_STATUS_SEEK   0x10
+#define GRUB_ATA_STATUS_WRERR  0x20
+#define GRUB_ATA_STATUS_READY  0x40
+#define GRUB_ATA_STATUS_BUSY   0x80
+
+/* ATAPI interrupt reason values (I/O, D/C bits).  */
+#define GRUB_ATAPI_IREASON_MASK     0x3
+#define GRUB_ATAPI_IREASON_DATA_OUT 0x0
+#define GRUB_ATAPI_IREASON_CMD_OUT  0x1
+#define GRUB_ATAPI_IREASON_DATA_IN  0x2
+#define GRUB_ATAPI_IREASON_ERROR    0x3
+
+enum grub_ata_commands
+  {
+    GRUB_ATA_CMD_CHECK_POWER_MODE      = 0xe5,
+    GRUB_ATA_CMD_IDENTIFY_DEVICE       = 0xec,
+    GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE        = 0xa1,
+    GRUB_ATA_CMD_IDLE                  = 0xe3,
+    GRUB_ATA_CMD_PACKET                        = 0xa0,
+    GRUB_ATA_CMD_READ_SECTORS          = 0x20,
+    GRUB_ATA_CMD_READ_SECTORS_EXT      = 0x24,
+    GRUB_ATA_CMD_SECURITY_FREEZE_LOCK  = 0xf5,
+    GRUB_ATA_CMD_SET_FEATURES          = 0xef,
+    GRUB_ATA_CMD_SLEEP                 = 0xe6,
+    GRUB_ATA_CMD_SMART                 = 0xb0,
+    GRUB_ATA_CMD_STANDBY_IMMEDIATE     = 0xe0,
+    GRUB_ATA_CMD_WRITE_SECTORS         = 0x30,
+    GRUB_ATA_CMD_WRITE_SECTORS_EXT     = 0x34,
+  };
+
+enum grub_ata_timeout_milliseconds
+  {
+    GRUB_ATA_TOUT_STD  =  1000,  /* 1s standard timeout.  */
+    GRUB_ATA_TOUT_DATA = 10000   /* 10s DATA I/O timeout.  */
+  };
+
+struct grub_ata_device
+{
+  /* IDE port to use.  */
+  int port;
+
+  /* IO addresses on which the registers for this device can be
+     found.  */
+  int ioaddress;
+  int ioaddress2;
+
+  /* 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;
+
+  /* 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.  */
+  grub_ata_addressing_t addr;
+
+  /* Sector count.  */
+  grub_uint64_t size;
+
+  /* CHS maximums.  */
+  grub_uint16_t cylinders;
+  grub_uint16_t heads;
+  grub_uint16_t sectors_per_track;
+
+  /* Set to 0 for ATA, set to 1 for ATAPI.  */
+  int atapi;
+
+  struct grub_ata_device *next;
+};
+
+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);
+
+static inline void
+grub_ata_regset (struct grub_ata_device *dev, int reg, int val)
+{
+  grub_outb (val, dev->ioaddress + reg);
+}
+
+static inline grub_uint8_t
+grub_ata_regget (struct grub_ata_device *dev, int reg)
+{
+  return grub_inb (dev->ioaddress + reg);
+}
+
+static inline void
+grub_ata_regset2 (struct grub_ata_device *dev, int reg, int val)
+{
+  grub_outb (val, dev->ioaddress2 + reg);
+}
+
+static inline grub_uint8_t
+grub_ata_regget2 (struct grub_ata_device *dev, int reg)
+{
+  return grub_inb (dev->ioaddress2 + reg);
+}
+
+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);
+
+  return GRUB_ERR_NONE;
+}
+
+#endif /* ! GRUB_ATA_HEADER */
diff --git a/include/grub/bitmap.h b/include/grub/bitmap.h
new file mode 100644 (file)
index 0000000..42c439d
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  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_BITMAP_HEADER
+#define GRUB_BITMAP_HEADER     1
+
+#include <grub/err.h>
+#include <grub/symbol.h>
+#include <grub/types.h>
+#include <grub/video.h>
+
+struct grub_video_bitmap
+{
+  /* Bitmap format description.  */
+  struct grub_video_mode_info mode_info;
+
+  /* Pointer to bitmap data formatted according to mode_info.  */
+  void *data;
+};
+
+struct grub_video_bitmap_reader
+{
+  /* File extension for this bitmap type (including dot).  */
+  const char *extension;
+
+  /* Reader function to load bitmap.  */
+  grub_err_t (*reader) (struct grub_video_bitmap **bitmap,
+                        const char *filename);
+
+  /* Next reader.  */
+  struct grub_video_bitmap_reader *next;
+};
+typedef struct grub_video_bitmap_reader *grub_video_bitmap_reader_t;
+
+void grub_video_bitmap_reader_register (grub_video_bitmap_reader_t reader);
+void grub_video_bitmap_reader_unregister (grub_video_bitmap_reader_t reader);
+
+grub_err_t grub_video_bitmap_create (struct grub_video_bitmap **bitmap,
+                                     unsigned int width, unsigned int height,
+                                     enum grub_video_blit_format blit_format);
+
+grub_err_t grub_video_bitmap_destroy (struct grub_video_bitmap *bitmap);
+
+grub_err_t grub_video_bitmap_load (struct grub_video_bitmap **bitmap,
+                                   const char *filename);
+
+unsigned int grub_video_bitmap_get_width (struct grub_video_bitmap *bitmap);
+unsigned int grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap);
+
+void grub_video_bitmap_get_mode_info (struct grub_video_bitmap *bitmap,
+                                      struct grub_video_mode_info *mode_info);
+
+void *grub_video_bitmap_get_data (struct grub_video_bitmap *bitmap);
+
+#endif /* ! GRUB_BITMAP_HEADER */
diff --git a/include/grub/boot.h b/include/grub/boot.h
new file mode 100644 (file)
index 0000000..2357748
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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_BOOT_HEADER
+#define GRUB_BOOT_HEADER       1
+
+#define GRUB_BOOT_VERSION_MAJOR        4
+#define GRUB_BOOT_VERSION_MINOR        0
+#define GRUB_BOOT_VERSION      ((GRUB_BOOT_VERSION_MINOR << 8) \
+                                       | GRUB_BOOT_VERSION_MAJOR)
+
+#endif /* ! GRUB_BOOT_HEADER */
diff --git a/include/grub/bufio.h b/include/grub/bufio.h
new file mode 100644 (file)
index 0000000..9a2294c
--- /dev/null
@@ -0,0 +1,28 @@
+/* bufio.h - prototypes for bufio */
+/*
+ *  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_BUFIO_H
+#define GRUB_BUFIO_H   1
+
+#include <grub/file.h>
+
+grub_file_t grub_bufio_open (grub_file_t io, int size);
+grub_file_t grub_buffile_open (const char *name, int size);
+
+#endif /* ! GRUB_BUFIO_H */
diff --git a/include/grub/cache.h b/include/grub/cache.h
new file mode 100644 (file)
index 0000000..745af43
--- /dev/null
@@ -0,0 +1,28 @@
+/* cache.h - Flush the processor's cache.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,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_CACHE_H
+#define GRUB_CACHE_H   1
+
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+void EXPORT_FUNC(grub_arch_sync_caches) (void *address, grub_size_t len);
+
+#endif /* ! GRUB_CACHE_HEADER */
diff --git a/include/grub/device.h b/include/grub/device.h
new file mode 100644 (file)
index 0000000..f0e8a8c
--- /dev/null
@@ -0,0 +1,41 @@
+/* device.h - device manager */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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 GRUB_DEVICE_HEADER
+#define GRUB_DEVICE_HEADER     1
+
+#include <grub/symbol.h>
+#include <grub/err.h>
+
+struct grub_disk;
+struct grub_net;
+struct grub_fs;
+
+struct grub_device
+{
+  struct grub_disk *disk;
+  struct grub_net *net;
+};
+typedef struct grub_device *grub_device_t;
+
+grub_device_t EXPORT_FUNC(grub_device_open) (const char *name);
+grub_err_t EXPORT_FUNC(grub_device_close) (grub_device_t device);
+int EXPORT_FUNC(grub_device_iterate) (int (*hook) (const char *name));
+
+#endif /* ! GRUB_DEVICE_HEADER */
diff --git a/include/grub/disk.h b/include/grub/disk.h
new file mode 100644 (file)
index 0000000..1e8046a
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,2005,2006,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_DISK_HEADER
+#define GRUB_DISK_HEADER       1
+
+#include <grub/symbol.h>
+#include <grub/err.h>
+#include <grub/types.h>
+#include <grub/device.h>
+
+/* These are used to set a device id. When you add a new disk device,
+   you must define a new id for it here.  */
+enum grub_disk_dev_id
+  {
+    GRUB_DISK_DEVICE_BIOSDISK_ID,
+    GRUB_DISK_DEVICE_OFDISK_ID,
+    GRUB_DISK_DEVICE_LOOPBACK_ID,
+    GRUB_DISK_DEVICE_EFIDISK_ID,
+    GRUB_DISK_DEVICE_RAID_ID,
+    GRUB_DISK_DEVICE_LVM_ID,
+    GRUB_DISK_DEVICE_HOST_ID,
+    GRUB_DISK_DEVICE_ATA_ID,
+    GRUB_DISK_DEVICE_MEMDISK_ID,
+    GRUB_DISK_DEVICE_NAND_ID,
+    GRUB_DISK_DEVICE_UUID_ID,
+    GRUB_DISK_DEVICE_PXE_ID,
+    GRUB_DISK_DEVICE_SCSI_ID,
+  };
+
+struct grub_disk;
+#ifdef GRUB_UTIL
+struct grub_disk_memberlist;
+#endif
+
+/* Disk device.  */
+struct grub_disk_dev
+{
+  /* The device name.  */
+  const char *name;
+
+  /* The device id used by the cache manager.  */
+  unsigned long id;
+  
+  /* Call HOOK with each device name, until HOOK returns non-zero.  */
+  int (*iterate) (int (*hook) (const char *name));
+
+  /* Open the device named NAME, and set up DISK.  */
+  grub_err_t (*open) (const char *name, struct grub_disk *disk);
+
+  /* Close the disk DISK.  */
+  void (*close) (struct grub_disk *disk);
+
+  /* Read SIZE sectors from the sector SECTOR of the disk DISK into BUF.  */
+  grub_err_t (*read) (struct grub_disk *disk, grub_disk_addr_t sector,
+                     grub_size_t size, char *buf);
+
+  /* Write SIZE sectors from BUF into the sector SECTOR of the disk DISK.  */
+  grub_err_t (*write) (struct grub_disk *disk, grub_disk_addr_t sector,
+                      grub_size_t size, const char *buf);
+
+#ifdef GRUB_UTIL
+  struct grub_disk_memberlist *(*memberlist) (struct grub_disk *disk);
+#endif
+
+  /* The next disk device.  */
+  struct grub_disk_dev *next;
+};
+typedef struct grub_disk_dev *grub_disk_dev_t;
+
+struct grub_partition;
+
+/* Disk.  */
+struct grub_disk
+{
+  /* The disk name.  */
+  const char *name;
+
+  /* The underlying disk device.  */
+  grub_disk_dev_t dev;
+
+  /* The total number of sectors.  */
+  grub_uint64_t total_sectors;
+
+  /* If partitions can be stored.  */
+  int has_partitions;
+
+  /* The id used by the disk cache manager.  */
+  unsigned long id;
+  
+  /* The partition information. This is machine-specific.  */
+  struct grub_partition *partition;
+
+  /* Called when a sector was read. OFFSET is between 0 and
+     the sector size minus 1, and LENGTH is between 0 and the sector size.  */
+  void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
+                    unsigned offset, unsigned length);
+
+  /* Device-specific data.  */
+  void *data;
+};
+typedef struct grub_disk *grub_disk_t;
+
+#ifdef GRUB_UTIL
+struct grub_disk_memberlist
+{
+  grub_disk_t disk;
+  struct grub_disk_memberlist *next;
+};
+typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
+#endif
+
+/* The sector size.  */
+#define GRUB_DISK_SECTOR_SIZE  0x200
+#define GRUB_DISK_SECTOR_BITS  9
+
+/* 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
+
+/* This is called from the memory manager.  */
+void grub_disk_cache_invalidate_all (void);
+
+void EXPORT_FUNC(grub_disk_dev_register) (grub_disk_dev_t dev);
+void EXPORT_FUNC(grub_disk_dev_unregister) (grub_disk_dev_t dev);
+int EXPORT_FUNC(grub_disk_dev_iterate) (int (*hook) (const char *name));
+
+grub_disk_t EXPORT_FUNC(grub_disk_open) (const char *name);
+void EXPORT_FUNC(grub_disk_close) (grub_disk_t disk);
+grub_err_t EXPORT_FUNC(grub_disk_read) (grub_disk_t disk,
+                                       grub_disk_addr_t sector,
+                                       grub_off_t offset,
+                                       grub_size_t size,
+                                       char *buf);
+grub_err_t EXPORT_FUNC(grub_disk_write) (grub_disk_t disk,
+                                        grub_disk_addr_t sector,
+                                        grub_off_t offset,
+                                        grub_size_t size,
+                                        const char *buf);
+
+grub_uint64_t EXPORT_FUNC(grub_disk_get_size) (grub_disk_t disk);
+
+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 *);
+
+#ifdef GRUB_UTIL
+void grub_raid_init (void);
+void grub_raid_fini (void);
+void grub_lvm_init (void);
+void grub_lvm_fini (void);
+#endif
+
+#endif /* ! GRUB_DISK_HEADER */
diff --git a/include/grub/dl.h b/include/grub/dl.h
new file mode 100644 (file)
index 0000000..5e46374
--- /dev/null
@@ -0,0 +1,96 @@
+/* dl.h - types and prototypes for loadable module support */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2004,2005,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_DL_H
+#define GRUB_DL_H      1
+
+#include <grub/symbol.h>
+#include <grub/err.h>
+#include <grub/types.h>
+
+#define GRUB_MOD_INIT(name)    \
+static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \
+void grub_##name##_init (void); \
+void \
+grub_##name##_init (void) { grub_mod_init (0); } \
+static void \
+grub_mod_init (grub_dl_t mod __attribute__ ((unused)))
+
+#define GRUB_MOD_FINI(name)    \
+static void grub_mod_fini (void) __attribute__ ((used)); \
+void grub_##name##_fini (void); \
+void \
+grub_##name##_fini (void) { grub_mod_fini (); } \
+static void \
+grub_mod_fini (void)
+
+#define GRUB_MOD_NAME(name)    \
+__asm__ (".section .modname\n.string \"" #name "\"\n")
+
+#define GRUB_MOD_DEP(name)     \
+__asm__ (".section .moddeps\n.string \"" #name "\"\n")
+
+struct grub_dl_segment
+{
+  struct grub_dl_segment *next;
+  void *addr;
+  grub_size_t size;
+  unsigned section;
+};
+typedef struct grub_dl_segment *grub_dl_segment_t;
+
+struct grub_dl;
+
+struct grub_dl_dep
+{
+  struct grub_dl_dep *next;
+  struct grub_dl *mod;
+};
+typedef struct grub_dl_dep *grub_dl_dep_t;
+
+struct grub_dl
+{
+  char *name;
+  int ref_count;
+  grub_dl_dep_t dep;
+  grub_dl_segment_t segment;
+  void (*init) (struct grub_dl *mod);
+  void (*fini) (void);
+};
+typedef struct grub_dl *grub_dl_t;
+
+grub_err_t EXPORT_FUNC(grub_dl_check_header) (void *ehdr, grub_size_t size);
+grub_dl_t EXPORT_FUNC(grub_dl_load_file) (const char *filename);
+grub_dl_t EXPORT_FUNC(grub_dl_load) (const char *name);
+grub_dl_t grub_dl_load_core (void *addr, grub_size_t size);
+int EXPORT_FUNC(grub_dl_unload) (grub_dl_t mod);
+void grub_dl_unload_unneeded (void);
+void grub_dl_unload_all (void);
+int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod);
+int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod);
+void EXPORT_FUNC(grub_dl_iterate) (int (*hook) (grub_dl_t mod));
+grub_dl_t EXPORT_FUNC(grub_dl_get) (const char *name);
+grub_err_t EXPORT_FUNC(grub_dl_register_symbol) (const char *name, void *addr,
+                                           grub_dl_t mod);
+void *EXPORT_FUNC(grub_dl_resolve_symbol) (const char *name);
+
+grub_err_t grub_arch_dl_check_header (void *ehdr);
+grub_err_t grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr);
+
+#endif /* ! GRUB_DL_H */
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
new file mode 100644 (file)
index 0000000..44b7d27
--- /dev/null
@@ -0,0 +1,1136 @@
+/* efi.h - declare EFI types and functions */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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_EFI_API_HEADER
+#define GRUB_EFI_API_HEADER    1
+
+#include <grub/types.h>
+
+/* For consistency and safety, we name the EFI-defined types differently.
+   All names are transformed into lower case, _t appended, and
+   grub_efi_ prepended.  */
+
+/* Constants.  */
+#define GRUB_EFI_EVT_TIMER                             0x80000000
+#define GRUB_EFI_EVT_RUNTIME                           0x40000000
+#define GRUB_EFI_EVT_RUNTIME_CONTEXT                   0x20000000
+#define GRUB_EFI_EVT_NOTIFY_WAIT                       0x00000100
+#define GRUB_EFI_EVT_NOTIFY_SIGNAL                     0x00000200
+#define GRUB_EFI_EVT_SIGNAL_EXIT_BOOT_SERVICES         0x00000201
+#define GRUB_EFI_EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE     0x60000202
+
+#define GRUB_EFI_TPL_APPLICATION       4
+#define GRUB_EFI_TPL_CALLBACK          8
+#define GRUB_EFI_TPL_NOTIFY            16
+#define GRUB_EFI_TPL_HIGH_LEVEL                31
+
+#define GRUB_EFI_MEMORY_UC     0x0000000000000001
+#define GRUB_EFI_MEMORY_WC     0x0000000000000002
+#define GRUB_EFI_MEMORY_WT     0x0000000000000004
+#define GRUB_EFI_MEMORY_WB     0x0000000000000008
+#define GRUB_EFI_MEMORY_UCE    0x0000000000000010
+#define GRUB_EFI_MEMORY_WP     0x0000000000001000
+#define GRUB_EFI_MEMORY_RP     0x0000000000002000
+#define GRUB_EFI_MEMORY_XP     0x0000000000004000
+#define GRUB_EFI_MEMORY_RUNTIME        0x8000000000000000
+
+#define GRUB_EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL      0x00000001
+#define GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL            0x00000002
+#define GRUB_EFI_OPEN_PROTOCOL_TEST_PROTOCOL           0x00000004
+#define GRUB_EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER     0x00000008
+#define GRUB_EFI_OPEN_PROTOCOL_BY_DRIVER               0x00000010
+#define GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE            0x00000020
+
+#define GRUB_EFI_VARIABLE_NON_VOLATILE         0x0000000000000001
+#define GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS   0x0000000000000002
+#define GRUB_EFI_VARIABLE_RUNTIME_ACCESS       0x0000000000000004
+
+#define GRUB_EFI_TIME_ADJUST_DAYLIGHT  0x01
+#define GRUB_EFI_TIME_IN_DAYLIGHT      0x02
+
+#define GRUB_EFI_UNSPECIFIED_TIMEZONE  0x07FF
+
+#define GRUB_EFI_OPTIONAL_PTR  0x00000001
+
+#define GRUB_EFI_LOADED_IMAGE_GUID     \
+  { 0x5b1b31a1, 0x9562, 0x11d2, \
+    { 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+  }
+
+#define GRUB_EFI_DISK_IO_GUID  \
+  { 0xce345171, 0xba0b, 0x11d2, \
+    { 0x8e, 0x4f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+  }
+
+#define GRUB_EFI_BLOCK_IO_GUID \
+  { 0x964e5b21, 0x6459, 0x11d2, \
+    { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+  }
+
+#define GRUB_EFI_DEVICE_PATH_GUID      \
+  { 0x09576e91, 0x6d3f, 0x11d2, \
+    { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+  }
+
+/* Enumerations.  */
+enum grub_efi_timer_delay
+  {
+    GRUB_EFI_TIMER_CANCEL,
+    GRUB_EFI_TIMER_PERIODIC,
+    GRUB_EFI_TIMER_RELATIVE
+  };
+typedef enum grub_efi_timer_delay grub_efi_timer_delay_t;
+
+enum grub_efi_allocate_type
+  {
+    GRUB_EFI_ALLOCATE_ANY_PAGES,
+    GRUB_EFI_ALLOCATE_MAX_ADDRESS,
+    GRUB_EFI_ALLOCATE_ADDRESS,
+    GRUB_EFI_MAX_ALLOCATION_TYPE
+  };
+typedef enum grub_efi_allocate_type grub_efi_allocate_type_t;
+
+enum grub_efi_memory_type
+  {
+    GRUB_EFI_RESERVED_MEMORY_TYPE,
+    GRUB_EFI_LOADER_CODE,
+    GRUB_EFI_LOADER_DATA,
+    GRUB_EFI_BOOT_SERVICES_CODE,
+    GRUB_EFI_BOOT_SERVICES_DATA,
+    GRUB_EFI_RUNTIME_SERVICES_CODE,
+    GRUB_EFI_RUNTIME_SERVICES_DATA,
+    GRUB_EFI_CONVENTIONAL_MEMORY,
+    GRUB_EFI_UNUSABLE_MEMORY,
+    GRUB_EFI_ACPI_RECLAIM_MEMORY,
+    GRUB_EFI_ACPI_MEMORY_NVS,
+    GRUB_EFI_MEMORY_MAPPED_IO,
+    GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE,
+    GRUB_EFI_PAL_CODE,
+    GRUB_EFI_MAX_MEMORY_TYPE
+  };
+typedef enum grub_efi_memory_type grub_efi_memory_type_t;
+
+enum grub_efi_interface_type
+  {
+    GRUB_EFI_NATIVE_INTERFACE
+  };
+typedef enum grub_efi_interface_type grub_efi_interface_type_t;
+
+enum grub_efi_locate_search_type
+  {
+    GRUB_EFI_ALL_HANDLES,
+    GRUB_EFI_BY_REGISTER_NOTIFY,
+    GRUB_EFI_BY_PROTOCOL
+  };
+typedef enum grub_efi_locate_search_type grub_efi_locate_search_type_t;
+
+enum grub_efi_reset_type
+  {
+    GRUB_EFI_RESET_COLD,
+    GRUB_EFI_RESET_WARM,
+    GRUB_EFI_RESET_SHUTDOWN
+  };
+typedef enum grub_efi_reset_type grub_efi_reset_type_t;
+
+/* Types.  */
+typedef char grub_efi_boolean_t;
+typedef long grub_efi_intn_t;
+typedef unsigned long grub_efi_uintn_t;
+typedef grub_int8_t grub_efi_int8_t;
+typedef grub_uint8_t grub_efi_uint8_t;
+typedef grub_int16_t grub_efi_int16_t;
+typedef grub_uint16_t grub_efi_uint16_t;
+typedef grub_int32_t grub_efi_int32_t;
+typedef grub_uint32_t grub_efi_uint32_t;
+typedef grub_int64_t grub_efi_int64_t;
+typedef grub_uint64_t grub_efi_uint64_t;
+typedef grub_uint8_t grub_efi_char8_t;
+typedef grub_uint16_t grub_efi_char16_t;
+
+typedef grub_efi_intn_t grub_efi_status_t;
+
+#define GRUB_EFI_ERROR_CODE(value)     \
+  ((1L << (sizeof (grub_efi_status_t) * 8 - 1)) | (value))
+
+#define GRUB_EFI_WARNING_CODE(value)   (value)
+
+#define GRUB_EFI_SUCCESS               0
+
+#define GRUB_EFI_LOAD_ERROR            GRUB_EFI_ERROR_CODE (1)
+#define GRUB_EFI_INVALID_PARAMETER     GRUB_EFI_ERROR_CODE (2)
+#define GRUB_EFI_UNSUPPORTED           GRUB_EFI_ERROR_CODE (3)
+#define GRUB_EFI_BAD_BUFFER_SIZE       GRUB_EFI_ERROR_CODE (4)
+#define GRUB_EFI_BUFFER_TOO_SMALL      GRUB_EFI_ERROR_CODE (5)
+#define GRUB_EFI_NOT_READY             GRUB_EFI_ERROR_CODE (6)
+#define GRUB_EFI_DEVICE_ERROR          GRUB_EFI_ERROR_CODE (7)
+#define GRUB_EFI_WRITE_PROTECTED       GRUB_EFI_ERROR_CODE (8)
+#define GRUB_EFI_OUT_OF_RESOURCES      GRUB_EFI_ERROR_CODE (9)
+#define GRUB_EFI_VOLUME_CORRUPTED      GRUB_EFI_ERROR_CODE (10)
+#define GRUB_EFI_VOLUME_FULL           GRUB_EFI_ERROR_CODE (11)
+#define GRUB_EFI_NO_MEDIA              GRUB_EFI_ERROR_CODE (12)
+#define GRUB_EFI_MEDIA_CHANGED         GRUB_EFI_ERROR_CODE (13)
+#define GRUB_EFI_NOT_FOUND             GRUB_EFI_ERROR_CODE (14)
+#define GRUB_EFI_ACCESS_DENIED         GRUB_EFI_ERROR_CODE (15)
+#define GRUB_EFI_NO_RESPONSE           GRUB_EFI_ERROR_CODE (16)
+#define GRUB_EFI_NO_MAPPING            GRUB_EFI_ERROR_CODE (17)
+#define GRUB_EFI_TIMEOUT               GRUB_EFI_ERROR_CODE (18)
+#define GRUB_EFI_NOT_STARTED           GRUB_EFI_ERROR_CODE (19)
+#define GRUB_EFI_ALREADY_STARTED       GRUB_EFI_ERROR_CODE (20)
+#define GRUB_EFI_ABORTED               GRUB_EFI_ERROR_CODE (21)
+#define GRUB_EFI_ICMP_ERROR            GRUB_EFI_ERROR_CODE (22)
+#define GRUB_EFI_TFTP_ERROR            GRUB_EFI_ERROR_CODE (23)
+#define GRUB_EFI_PROTOCOL_ERROR                GRUB_EFI_ERROR_CODE (24)
+#define GRUB_EFI_INCOMPATIBLE_VERSION  GRUB_EFI_ERROR_CODE (25)
+#define GRUB_EFI_SECURITY_VIOLATION    GRUB_EFI_ERROR_CODE (26)
+#define GRUB_EFI_CRC_ERROR             GRUB_EFI_ERROR_CODE (27)
+
+#define GRUB_EFI_WARN_UNKNOWN_GLYPH    GRUB_EFI_WARNING_CODE (1)
+#define GRUB_EFI_WARN_DELETE_FAILURE   GRUB_EFI_WARNING_CODE (2)
+#define GRUB_EFI_WARN_WRITE_FAILURE    GRUB_EFI_WARNING_CODE (3)
+#define GRUB_EFI_WARN_BUFFER_TOO_SMALL GRUB_EFI_WARNING_CODE (4)
+
+typedef void *grub_efi_handle_t;
+typedef void *grub_efi_event_t;
+typedef grub_efi_uint64_t grub_efi_lba_t;
+typedef grub_efi_uintn_t grub_efi_tpl_t;
+typedef grub_uint8_t grub_efi_mac_address_t[32];
+typedef grub_uint8_t grub_efi_ipv4_address_t[4];
+typedef grub_uint16_t grub_efi_ipv6_address_t[8];
+typedef grub_uint8_t grub_efi_ip_address_t[8] __attribute__ ((aligned(4)));
+typedef grub_efi_uint64_t grub_efi_physical_address_t;
+typedef grub_efi_uint64_t grub_efi_virtual_address_t;
+
+struct grub_efi_guid
+{
+  grub_uint32_t data1;
+  grub_uint16_t data2;
+  grub_uint16_t data3;
+  grub_uint8_t data4[8];
+} __attribute__ ((aligned(8)));
+typedef struct grub_efi_guid grub_efi_guid_t;
+
+/* XXX although the spec does not specify the padding, this actually
+   must have the padding!  */
+struct grub_efi_memory_descriptor
+{
+  grub_efi_uint32_t type;
+  grub_efi_uint32_t padding;
+  grub_efi_physical_address_t physical_start;
+  grub_efi_virtual_address_t virtual_start;
+  grub_efi_uint64_t num_pages;
+  grub_efi_uint64_t attribute;
+};
+typedef struct grub_efi_memory_descriptor grub_efi_memory_descriptor_t;
+
+/* Device Path definitions.  */
+struct grub_efi_device_path
+{
+  grub_efi_uint8_t type;
+  grub_efi_uint8_t subtype;
+  grub_efi_uint8_t length[2];
+};
+typedef struct grub_efi_device_path grub_efi_device_path_t;
+/* XXX EFI does not define EFI_DEVICE_PATH_PROTOCOL but uses it.
+   It seems to be identical to EFI_DEVICE_PATH.  */
+typedef struct grub_efi_device_path grub_efi_device_path_protocol_t;
+
+#define GRUB_EFI_DEVICE_PATH_TYPE(dp)          ((dp)->type & 0x7f)
+#define GRUB_EFI_DEVICE_PATH_SUBTYPE(dp)       ((dp)->subtype)
+#define GRUB_EFI_DEVICE_PATH_LENGTH(dp)                \
+  ((dp)->length[0] | ((grub_efi_uint16_t) ((dp)->length[1]) << 8))
+
+/* The End of Device Path nodes.  */
+#define GRUB_EFI_END_DEVICE_PATH_TYPE                  (0xff & 0x7f)
+
+#define GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE                0xff
+#define GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE          0x01
+
+#define GRUB_EFI_END_ENTIRE_DEVICE_PATH(dp)    \
+  (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_END_DEVICE_PATH_TYPE \
+   && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) \
+       == GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE))
+
+#define GRUB_EFI_NEXT_DEVICE_PATH(dp)  \
+  ((grub_efi_device_path_t *) ((char *) (dp) \
+                               + GRUB_EFI_DEVICE_PATH_LENGTH (dp)))
+
+/* Hardware Device Path.  */
+#define GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE             1
+
+#define GRUB_EFI_PCI_DEVICE_PATH_SUBTYPE               1
+
+struct grub_efi_pci_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint8_t function;
+  grub_efi_uint8_t device;
+};
+typedef struct grub_efi_pci_device_path grub_efi_pci_device_path_t;
+
+#define GRUB_EFI_PCCARD_DEVICE_PATH_SUBTYPE            2
+
+struct grub_efi_pccard_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint8_t function;
+};
+typedef struct grub_efi_pccard_device_path grub_efi_pccard_device_path_t;
+
+#define GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE     3
+
+struct grub_efi_memory_mapped_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_memory_type_t memory_type;
+  grub_efi_physical_address_t start_address;
+  grub_efi_physical_address_t end_address;
+};
+typedef struct grub_efi_memory_mapped_device_path grub_efi_memory_mapped_device_path_t;
+
+#define GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE            4
+
+struct grub_efi_vendor_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_guid_t vendor_guid;
+  grub_efi_uint8_t vendor_defined_data[0];
+};
+typedef struct grub_efi_vendor_device_path grub_efi_vendor_device_path_t;
+
+#define GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE                5
+
+struct grub_efi_controller_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint32_t controller_number;
+};
+typedef struct grub_efi_controller_device_path grub_efi_controller_device_path_t;
+
+/* ACPI Device Path.  */
+#define GRUB_EFI_ACPI_DEVICE_PATH_TYPE                 2
+
+#define GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE              1
+
+struct grub_efi_acpi_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint32_t hid;
+  grub_efi_uint32_t uid;
+};
+typedef struct grub_efi_acpi_device_path grub_efi_acpi_device_path_t;
+
+#define GRUB_EFI_EXPANDED_ACPI_DEVICE_PATH_SUBTYPE     2
+
+struct grub_efi_expanded_acpi_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint32_t hid;
+  grub_efi_uint32_t uid;
+  grub_efi_uint32_t cid;
+  char hidstr[1];
+};
+typedef struct grub_efi_expanded_acpi_device_path grub_efi_expanded_acpi_device_path_t;
+
+#define GRUB_EFI_EXPANDED_ACPI_HIDSTR(dp)      \
+  (((grub_efi_expanded_acpi_device_path_t *) dp)->hidstr)
+#define GRUB_EFI_EXPANDED_ACPI_UIDSTR(dp)      \
+  (GRUB_EFI_EXPANDED_ACPI_HIDSTR(dp) \
+   + grub_strlen (GRUB_EFI_EXPANDED_ACPI_HIDSTR(dp)) + 1)
+#define GRUB_EFI_EXPANDED_ACPI_CIDSTR(dp)      \
+  (GRUB_EFI_EXPANDED_ACPI_UIDSTR(dp) \
+   + grub_strlen (GRUB_EFI_EXPANDED_ACPI_UIDSTR(dp)) + 1)
+
+/* Messaging Device Path.  */
+#define GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE            3
+
+#define GRUB_EFI_ATAPI_DEVICE_PATH_SUBTYPE             1
+
+struct grub_efi_atapi_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint8_t primary_secondary;
+  grub_efi_uint8_t slave_master;
+  grub_efi_uint16_t lun;
+};
+typedef struct grub_efi_atapi_device_path grub_efi_atapi_device_path_t;
+
+#define GRUB_EFI_SCSI_DEVICE_PATH_SUBTYPE              2
+
+struct grub_efi_scsi_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint16_t pun;
+  grub_efi_uint16_t lun;
+};
+typedef struct grub_efi_scsi_device_path grub_efi_scsi_device_path_t;
+
+#define GRUB_EFI_FIBRE_CHANNEL_DEVICE_PATH_SUBTYPE     3
+
+struct grub_efi_fibre_channel_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint32_t reserved;
+  grub_efi_uint64_t wwn;
+  grub_efi_uint64_t lun;
+};
+typedef struct grub_efi_fibre_channel_device_path grub_efi_fibre_channel_device_path_t;
+
+#define GRUB_EFI_1394_DEVICE_PATH_SUBTYPE              4
+
+struct grub_efi_1394_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint32_t reserved;
+  grub_efi_uint64_t guid;
+};
+typedef struct grub_efi_1394_device_path grub_efi_1394_device_path_t;
+
+#define GRUB_EFI_USB_DEVICE_PATH_SUBTYPE               5
+
+struct grub_efi_usb_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint8_t parent_port_number;
+  grub_efi_uint8_t interface;
+};
+typedef struct grub_efi_usb_device_path grub_efi_usb_device_path_t;
+
+#define GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE         15
+
+struct grub_efi_usb_class_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint16_t vendor_id;
+  grub_efi_uint16_t product_id;
+  grub_efi_uint8_t device_class;
+  grub_efi_uint8_t device_subclass;
+  grub_efi_uint8_t device_protocol;
+};
+typedef struct grub_efi_usb_class_device_path grub_efi_usb_class_device_path_t;
+
+#define GRUB_EFI_I2O_DEVICE_PATH_SUBTYPE               6
+
+struct grub_efi_i2o_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint32_t tid;
+};
+typedef struct grub_efi_i2o_device_path grub_efi_i2o_device_path_t;
+
+#define GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE       11
+
+struct grub_efi_mac_address_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_mac_address_t mac_address;
+  grub_efi_uint8_t if_type;
+};
+typedef struct grub_efi_mac_address_device_path grub_efi_mac_address_device_path_t;
+
+#define GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE              12
+
+struct grub_efi_ipv4_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_ipv4_address_t local_ip_address;
+  grub_efi_ipv4_address_t remote_ip_address;
+  grub_efi_uint16_t local_port;
+  grub_efi_uint16_t remote_port;
+  grub_efi_uint16_t protocol;
+  grub_efi_uint8_t static_ip_address;
+};
+typedef struct grub_efi_ipv4_device_path grub_efi_ipv4_device_path_t;
+
+#define GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE              13
+
+struct grub_efi_ipv6_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_ipv6_address_t local_ip_address;
+  grub_efi_ipv6_address_t remote_ip_address;
+  grub_efi_uint16_t local_port;
+  grub_efi_uint16_t remote_port;
+  grub_efi_uint16_t protocol;
+  grub_efi_uint8_t static_ip_address;
+};
+typedef struct grub_efi_ipv6_device_path grub_efi_ipv6_device_path_t;
+
+#define GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE                9
+
+struct grub_efi_infiniband_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint32_t resource_flags;
+  grub_efi_uint8_t port_gid[16];
+  grub_efi_uint64_t remote_id;
+  grub_efi_uint64_t target_port_id;
+  grub_efi_uint64_t device_id;
+};
+typedef struct grub_efi_infiniband_device_path grub_efi_infiniband_device_path_t;
+
+#define GRUB_EFI_UART_DEVICE_PATH_SUBTYPE              14
+
+struct grub_efi_uart_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint32_t reserved;
+  grub_efi_uint64_t baud_rate;
+  grub_efi_uint8_t data_bits;
+  grub_efi_uint8_t parity;
+  grub_efi_uint8_t stop_bits;
+};
+typedef struct grub_efi_uart_device_path grub_efi_uart_device_path_t;
+
+#define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE  10
+
+struct grub_efi_vendor_messaging_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_guid_t vendor_guid;
+  grub_efi_uint8_t vendor_defined_data[0];
+};
+typedef struct grub_efi_vendor_messaging_device_path grub_efi_vendor_messaging_device_path_t;
+
+/* Media Device Path.  */
+#define GRUB_EFI_MEDIA_DEVICE_PATH_TYPE                        4
+
+#define GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE                1
+
+struct grub_efi_hard_drive_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint32_t partition_number;
+  grub_efi_lba_t partition_start;
+  grub_efi_lba_t partition_size;
+  grub_efi_uint8_t partition_signature[8];
+  grub_efi_uint8_t mbr_type;
+  grub_efi_uint8_t signature_type;
+};
+typedef struct grub_efi_hard_drive_device_path grub_efi_hard_drive_device_path_t;
+
+#define GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE             2
+
+struct grub_efi_cdrom_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint32_t boot_entry;
+  grub_efi_lba_t partition_start;
+  grub_efi_lba_t partition_size;
+};
+typedef struct grub_efi_cdrom_device_path grub_efi_cdrom_device_path_t;
+
+#define GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE      3
+
+struct grub_efi_vendor_media_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_guid_t vendor_guid;
+  grub_efi_uint8_t vendor_defined_data[0];
+};
+typedef struct grub_efi_vendor_media_device_path grub_efi_vendor_media_device_path_t;
+
+#define GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE         4
+
+struct grub_efi_file_path_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_char16_t path_name[0];
+};
+typedef struct grub_efi_file_path_device_path grub_efi_file_path_device_path_t;
+
+#define GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE          5
+
+struct grub_efi_protocol_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_guid_t guid;
+};
+typedef struct grub_efi_protocol_device_path grub_efi_protocol_device_path_t;
+
+/* BIOS Boot Specification Device Path.  */
+#define GRUB_EFI_BIOS_DEVICE_PATH_TYPE                 5
+
+#define GRUB_EFI_BIOS_DEVICE_PATH_SUBTYPE              1
+
+struct grub_efi_bios_device_path
+{
+  grub_efi_device_path_t header;
+  grub_efi_uint16_t device_type;
+  grub_efi_uint16_t status_flags;
+  char description[0];
+};
+typedef struct grub_efi_bios_device_path grub_efi_bios_device_path_t;
+
+struct grub_efi_open_protocol_information_entry
+{
+  grub_efi_handle_t agent_handle;
+  grub_efi_handle_t controller_handle;
+  grub_efi_uint32_t attributes;
+  grub_efi_uint32_t open_count;
+};
+typedef struct grub_efi_open_protocol_information_entry grub_efi_open_protocol_information_entry_t;
+
+struct grub_efi_time
+{
+  grub_efi_uint16_t year;
+  grub_efi_uint8_t month;
+  grub_efi_uint8_t day;
+  grub_efi_uint8_t hour;
+  grub_efi_uint8_t minute;
+  grub_efi_uint8_t second;
+  grub_efi_uint8_t pad1;
+  grub_efi_uint32_t nanosecond;
+  grub_efi_int16_t time_zone;
+  grub_efi_uint8_t daylight;
+  grub_efi_uint8_t pad2;
+};
+typedef struct grub_efi_time grub_efi_time_t;
+
+struct grub_efi_time_capabilities
+{
+  grub_efi_uint32_t resolution;
+  grub_efi_uint32_t accuracy;
+  grub_efi_boolean_t sets_to_zero;
+};
+typedef struct grub_efi_time_capabilities grub_efi_time_capabilities_t;
+
+struct grub_efi_input_key
+{
+  grub_efi_uint16_t scan_code;
+  grub_efi_char16_t unicode_char;
+};
+typedef struct grub_efi_input_key grub_efi_input_key_t;
+
+struct grub_efi_simple_text_output_mode
+{
+  grub_efi_int32_t max_mode;
+  grub_efi_int32_t mode;
+  grub_efi_int32_t attribute;
+  grub_efi_int32_t cursor_column;
+  grub_efi_int32_t cursor_row;
+  grub_efi_boolean_t cursor_visible;
+};
+typedef struct grub_efi_simple_text_output_mode grub_efi_simple_text_output_mode_t;
+
+/* Tables.  */
+struct grub_efi_table_header
+{
+  grub_efi_uint64_t signature;
+  grub_efi_uint32_t revision;
+  grub_efi_uint32_t header_size;
+  grub_efi_uint32_t crc32;
+  grub_efi_uint32_t reserved;
+};
+typedef struct grub_efi_table_header grub_efi_table_header_t;
+
+struct grub_efi_boot_services
+{
+  grub_efi_table_header_t hdr;
+  
+  grub_efi_tpl_t
+  (*raise_tpl) (grub_efi_tpl_t new_tpl);
+  
+  void
+  (*restore_tpl) (grub_efi_tpl_t old_tpl);
+  
+  grub_efi_status_t
+  (*allocate_pages) (grub_efi_allocate_type_t type,
+                    grub_efi_memory_type_t memory_type,
+                    grub_efi_uintn_t pages,
+                    grub_efi_physical_address_t *memory);
+  
+  grub_efi_status_t
+  (*free_pages) (grub_efi_physical_address_t memory,
+                grub_efi_uintn_t pages);
+  
+  grub_efi_status_t
+  (*get_memory_map) (grub_efi_uintn_t *memory_map_size,
+                    grub_efi_memory_descriptor_t *memory_map,
+                    grub_efi_uintn_t *map_key,
+                    grub_efi_uintn_t *descriptor_size,
+                    grub_efi_uint32_t *descriptor_version);
+  
+  grub_efi_status_t
+  (*allocate_pool) (grub_efi_memory_type_t pool_type,
+                   grub_efi_uintn_t size,
+                   void **buffer);
+  
+  grub_efi_status_t
+  (*free_pool) (void *buffer);
+  
+  grub_efi_status_t
+  (*create_event) (grub_efi_uint32_t type,
+                  grub_efi_tpl_t notify_tpl,
+                  void (*notify_function) (grub_efi_event_t event,
+                                           void *context),
+                  void *notify_context,
+                  grub_efi_event_t *event);
+
+  grub_efi_status_t
+  (*set_timer) (grub_efi_event_t event,
+               grub_efi_timer_delay_t type,
+               grub_efi_uint64_t trigger_time);
+  
+   grub_efi_status_t
+   (*wait_for_event) (grub_efi_uintn_t num_events,
+                     grub_efi_event_t *event,
+                     grub_efi_uintn_t *index);
+
+  grub_efi_status_t
+  (*signal_event) (grub_efi_event_t event);
+  
+  grub_efi_status_t
+  (*close_event) (grub_efi_event_t event);
+  
+  grub_efi_status_t
+  (*check_event) (grub_efi_event_t event);
+
+   grub_efi_status_t
+   (*install_protocol_interface) (grub_efi_handle_t *handle,
+                                 grub_efi_guid_t *protocol,
+                                 grub_efi_interface_type_t interface_type,
+                                 void *interface);
+  
+  grub_efi_status_t
+  (*reinstall_protocol_interface) (grub_efi_handle_t handle,
+                                  grub_efi_guid_t *protocol,
+                                  void *old_interface,
+                                  void *new_interface);
+  
+  grub_efi_status_t
+  (*uninstall_protocol_interface) (grub_efi_handle_t handle,
+                                  grub_efi_guid_t *protocol,
+                                  void *interface);
+
+  grub_efi_status_t
+  (*handle_protocol) (grub_efi_handle_t handle,
+                     grub_efi_guid_t *protocol,
+                     void **interface);
+  
+  void *reserved;
+  
+  grub_efi_status_t
+  (*register_protocol_notify) (grub_efi_guid_t *protocol,
+                              grub_efi_event_t event,
+                              void **registration);
+
+  grub_efi_status_t
+  (*locate_handle) (grub_efi_locate_search_type_t search_type,
+                   grub_efi_guid_t *protocol,
+                   void *search_key,
+                   grub_efi_uintn_t *buffer_size,
+                   grub_efi_handle_t *buffer);
+
+  grub_efi_status_t
+  (*locate_device_path) (grub_efi_guid_t *protocol,
+                        grub_efi_device_path_t **device_path,
+                        grub_efi_handle_t *device);
+
+  grub_efi_status_t
+  (*install_configuration_table) (grub_efi_guid_t *guid, void *table);
+
+  grub_efi_status_t
+  (*load_image) (grub_efi_boolean_t boot_policy,
+                grub_efi_handle_t parent_image_handle,
+                grub_efi_device_path_t *file_path,
+                void *source_buffer,
+                grub_efi_uintn_t source_size,
+                grub_efi_handle_t *image_handle);
+
+  grub_efi_status_t
+  (*start_image) (grub_efi_handle_t image_handle,
+                 grub_efi_uintn_t *exit_data_size,
+                 grub_efi_char16_t **exit_data);
+
+  grub_efi_status_t
+  (*exit) (grub_efi_handle_t image_handle,
+          grub_efi_status_t exit_status,
+          grub_efi_uintn_t exit_data_size,
+          grub_efi_char16_t *exit_data) __attribute__((noreturn));
+
+  grub_efi_status_t
+  (*unload_image) (grub_efi_handle_t image_handle);
+
+  grub_efi_status_t
+  (*exit_boot_services) (grub_efi_handle_t image_handle,
+                        grub_efi_uintn_t map_key);
+
+  grub_efi_status_t
+  (*get_next_monotonic_count) (grub_efi_uint64_t *count);
+
+  grub_efi_status_t
+  (*stall) (grub_efi_uintn_t microseconds);
+
+  grub_efi_status_t
+  (*set_watchdog_timer) (grub_efi_uintn_t timeout,
+                        grub_efi_uint64_t watchdog_code,
+                        grub_efi_uintn_t data_size,
+                        grub_efi_char16_t *watchdog_data);
+
+  grub_efi_status_t
+  (*connect_controller) (grub_efi_handle_t controller_handle,
+                        grub_efi_handle_t *driver_image_handle,
+                        grub_efi_device_path_protocol_t *remaining_device_path,
+                        grub_efi_boolean_t recursive);
+
+  grub_efi_status_t
+  (*disconnect_controller) (grub_efi_handle_t controller_handle,
+                           grub_efi_handle_t driver_image_handle,
+                           grub_efi_handle_t child_handle);
+
+  grub_efi_status_t
+  (*open_protocol) (grub_efi_handle_t handle,
+                   grub_efi_guid_t *protocol,
+                   void **interface,
+                   grub_efi_handle_t agent_handle,
+                   grub_efi_handle_t controller_handle,
+                   grub_efi_uint32_t attributes);
+
+  grub_efi_status_t
+  (*close_protocol) (grub_efi_handle_t handle,
+                    grub_efi_guid_t *protocol,
+                    grub_efi_handle_t agent_handle,
+                    grub_efi_handle_t controller_handle);
+
+  grub_efi_status_t
+  (*open_protocol_information) (grub_efi_handle_t handle,
+                               grub_efi_guid_t *protocol,
+                               grub_efi_open_protocol_information_entry_t **entry_buffer,
+                               grub_efi_uintn_t *entry_count);
+
+  grub_efi_status_t
+  (*protocols_per_handle) (grub_efi_handle_t handle,
+                          grub_efi_guid_t ***protocol_buffer,
+                          grub_efi_uintn_t *protocol_buffer_count);
+
+  grub_efi_status_t
+  (*locate_handle_buffer) (grub_efi_locate_search_type_t search_type,
+                          grub_efi_guid_t *protocol,
+                          void *search_key,
+                          grub_efi_uintn_t *no_handles,
+                          grub_efi_handle_t **buffer);
+
+  grub_efi_status_t
+  (*locate_protocol) (grub_efi_guid_t *protocol,
+                     void *registration,
+                     void **interface);
+
+  grub_efi_status_t
+  (*install_multiple_protocol_interfaces) (grub_efi_handle_t *handle, ...);
+
+  grub_efi_status_t
+  (*uninstall_multiple_protocol_interfaces) (grub_efi_handle_t handle, ...);
+
+  grub_efi_status_t
+  (*calculate_crc32) (void *data,
+                     grub_efi_uintn_t data_size,
+                     grub_efi_uint32_t *crc32);
+
+  void
+  (*copy_mem) (void *destination, void *source, grub_efi_uintn_t length);
+
+  void
+  (*set_mem) (void *buffer, grub_efi_uintn_t size, grub_efi_uint8_t value);
+};
+typedef struct grub_efi_boot_services grub_efi_boot_services_t;
+
+struct grub_efi_runtime_services
+{
+  grub_efi_table_header_t hdr;
+
+  grub_efi_status_t 
+  (*get_time) (grub_efi_time_t *time,
+              grub_efi_time_capabilities_t *capabilities);
+
+  grub_efi_status_t
+  (*set_time) (grub_efi_time_t *time);
+
+  grub_efi_status_t
+  (*get_wakeup_time) (grub_efi_boolean_t *enabled,
+                     grub_efi_boolean_t *pending,
+                     grub_efi_time_t *time);
+
+  grub_efi_status_t
+  (*set_wakeup_time) (grub_efi_boolean_t enabled,
+                     grub_efi_time_t *time);
+
+  grub_efi_status_t
+  (*set_virtual_address_map) (grub_efi_uintn_t memory_map_size,
+                             grub_efi_uintn_t descriptor_size,
+                             grub_efi_uint32_t descriptor_version,
+                             grub_efi_memory_descriptor_t *virtual_map);
+
+  grub_efi_status_t
+  (*convert_pointer) (grub_efi_uintn_t debug_disposition, void **address);
+
+  grub_efi_status_t
+  (*get_variable) (grub_efi_char16_t *variable_name,
+                  grub_efi_guid_t *vendor_guid,
+                  grub_efi_uint32_t *attributes,
+                  grub_efi_uintn_t *data_size,
+                  void *data);
+
+  grub_efi_status_t
+  (*get_next_variable_name) (grub_efi_uintn_t *variable_name_size,
+                            grub_efi_char16_t *variable_name,
+                            grub_efi_guid_t *vendor_guid);
+
+  grub_efi_status_t
+  (*set_variable) (grub_efi_char16_t *variable_name,
+                  grub_efi_guid_t *vendor_guid,
+                  grub_efi_uint32_t attributes,
+                  grub_efi_uintn_t data_size,
+                  void *data);
+
+  grub_efi_status_t
+  (*get_next_high_monotonic_count) (grub_efi_uint32_t *high_count);
+
+  void
+  (*reset_system) (grub_efi_reset_type_t reset_type,
+                  grub_efi_status_t reset_status,
+                  grub_efi_uintn_t data_size,
+                  grub_efi_char16_t *reset_data);
+};
+typedef struct grub_efi_runtime_services grub_efi_runtime_services_t;
+
+struct grub_efi_configuration_table
+{
+  grub_efi_guid_t vendor_guid;
+  void *vendor_table;
+};
+typedef struct grub_efi_configuration_table grub_efi_configuration_table_t;
+
+struct grub_efi_simple_input_interface
+{
+  grub_efi_status_t
+  (*reset) (struct grub_efi_simple_input_interface *this,
+           grub_efi_boolean_t extended_verification);
+  
+  grub_efi_status_t
+  (*read_key_stroke) (struct grub_efi_simple_input_interface *this,
+                     grub_efi_input_key_t *key);
+  
+  grub_efi_event_t wait_for_key;
+};
+typedef struct grub_efi_simple_input_interface grub_efi_simple_input_interface_t;
+
+struct grub_efi_simple_text_output_interface
+{
+  grub_efi_status_t
+  (*reset) (struct grub_efi_simple_text_output_interface *this,
+           grub_efi_boolean_t extended_verification);
+
+  grub_efi_status_t
+  (*output_string) (struct grub_efi_simple_text_output_interface *this,
+                   grub_efi_char16_t *string);
+
+  grub_efi_status_t
+  (*test_string) (struct grub_efi_simple_text_output_interface *this,
+                 grub_efi_char16_t *string);
+
+  grub_efi_status_t
+  (*query_mode) (struct grub_efi_simple_text_output_interface *this,
+                grub_efi_uintn_t mode_number,
+                grub_efi_uintn_t *columns,
+                grub_efi_uintn_t *rows);
+
+  grub_efi_status_t 
+  (*set_mode) (struct grub_efi_simple_text_output_interface *this,
+              grub_efi_uintn_t mode_number);
+
+  grub_efi_status_t
+  (*set_attributes) (struct grub_efi_simple_text_output_interface *this,
+                    grub_efi_uintn_t attribute);
+
+  grub_efi_status_t
+  (*clear_screen) (struct grub_efi_simple_text_output_interface *this);
+
+  grub_efi_status_t
+  (*set_cursor_position) (struct grub_efi_simple_text_output_interface *this,
+                         grub_efi_uintn_t column,
+                         grub_efi_uintn_t row);
+
+  grub_efi_status_t
+  (*enable_cursor) (struct grub_efi_simple_text_output_interface *this,
+                   grub_efi_boolean_t visible);
+  
+  grub_efi_simple_text_output_mode_t *mode;
+};
+typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output_interface_t;
+
+#define GRUB_EFI_BLACK         0x00
+#define GRUB_EFI_BLUE          0x01
+#define GRUB_EFI_GREEN         0x02
+#define GRUB_EFI_CYAN          0x03
+#define GRUB_EFI_RED           0x04
+#define GRUB_EFI_MAGENTA       0x05
+#define GRUB_EFI_BROWN         0x06
+#define GRUB_EFI_LIGHTGRAY     0x07
+#define GRUB_EFI_BRIGHT                0x08
+#define GRUB_EFI_DARKGRAY      0x08
+#define GRUB_EFI_LIGHTBLUE     0x09
+#define GRUB_EFI_LIGHTGREEN    0x0A
+#define GRUB_EFI_LIGHTCYAN     0x0B
+#define GRUB_EFI_LIGHTRED      0x0C
+#define GRUB_EFI_LIGHTMAGENTA  0x0D
+#define GRUB_EFI_YELLOW                0x0E
+#define GRUB_EFI_WHITE         0x0F
+
+#define GRUB_EFI_BACKGROUND_BLACK      0x00
+#define GRUB_EFI_BACKGROUND_BLUE       0x10
+#define GRUB_EFI_BACKGROUND_GREEN      0x20
+#define GRUB_EFI_BACKGROUND_CYAN       0x30
+#define GRUB_EFI_BACKGROUND_RED                0x40
+#define GRUB_EFI_BACKGROUND_MAGENTA    0x50
+#define GRUB_EFI_BACKGROUND_BROWN      0x60
+#define GRUB_EFI_BACKGROUND_LIGHTGRAY  0x70
+
+#define GRUB_EFI_TEXT_ATTR(fg, bg)     ((fg) | ((bg)))
+
+struct grub_efi_system_table
+{
+  grub_efi_table_header_t hdr;
+  grub_efi_char16_t *firmware_vendor;
+  grub_efi_uint32_t firmware_revision;
+  grub_efi_handle_t console_in_handler;
+  grub_efi_simple_input_interface_t *con_in;
+  grub_efi_handle_t console_out_handler;
+  grub_efi_simple_text_output_interface_t *con_out;
+  grub_efi_handle_t standard_error_handle;
+  grub_efi_simple_text_output_interface_t *std_err;
+  grub_efi_runtime_services_t *runtime_services;
+  grub_efi_boot_services_t *boot_services;
+  grub_efi_uintn_t num_table_entries;
+  grub_efi_configuration_table_t *configuration_table;
+};
+typedef struct grub_efi_system_table  grub_efi_system_table_t;
+
+struct grub_efi_loaded_image
+{
+  grub_efi_uint32_t revision;
+  grub_efi_handle_t parent_handle;
+  grub_efi_system_table_t *system_table;
+
+  grub_efi_handle_t device_handle;
+  grub_efi_device_path_t *file_path;
+  void *reserved;
+
+  grub_efi_uint32_t load_options_size;
+  void *load_options;
+
+  void *image_base;
+  grub_efi_uint64_t image_size;
+  grub_efi_memory_type_t image_code_type;
+  grub_efi_memory_type_t image_data_type;
+
+  grub_efi_status_t (*unload) (grub_efi_handle_t image_handle);
+};
+typedef struct grub_efi_loaded_image grub_efi_loaded_image_t;
+
+struct grub_efi_disk_io
+{
+  grub_efi_uint64_t revision;
+  grub_efi_status_t (*read) (struct grub_efi_disk_io *this,
+                            grub_efi_uint32_t media_id,
+                            grub_efi_uint64_t offset,
+                            grub_efi_uintn_t buffer_size,
+                            void *buffer);
+  grub_efi_status_t (*write) (struct grub_efi_disk_io *this,
+                            grub_efi_uint32_t media_id,
+                            grub_efi_uint64_t offset,
+                            grub_efi_uintn_t buffer_size,
+                            void *buffer);
+};
+typedef struct grub_efi_disk_io grub_efi_disk_io_t;
+
+struct grub_efi_block_io_media
+{
+  grub_efi_uint32_t media_id;
+  grub_efi_boolean_t removable_media;
+  grub_efi_boolean_t media_present;
+  grub_efi_boolean_t logical_partition;
+  grub_efi_boolean_t read_only;
+  grub_efi_boolean_t write_caching;
+  grub_efi_uint8_t pad[3];
+  grub_efi_uint32_t block_size;
+  grub_efi_uint32_t io_align;
+  grub_efi_uint8_t pad2[4];
+  grub_efi_lba_t last_block;
+};
+typedef struct grub_efi_block_io_media grub_efi_block_io_media_t;
+
+struct grub_efi_block_io
+{
+  grub_efi_uint64_t revision;
+  grub_efi_block_io_media_t *media;
+  grub_efi_status_t (*reset) (struct grub_efi_block_io *this,
+                             grub_efi_boolean_t extended_verification);
+  grub_efi_status_t (*read_blocks) (struct grub_efi_block_io *this,
+                                   grub_efi_uint32_t media_id,
+                                   grub_efi_lba_t lba,
+                                   grub_efi_uintn_t buffer_size,
+                                   void *buffer);
+  grub_efi_status_t (*write_blocks) (struct grub_efi_block_io *this,
+                                    grub_efi_uint32_t media_id,
+                                    grub_efi_lba_t lba,
+                                    grub_efi_uintn_t buffer_size,
+                                    void *buffer);
+  grub_efi_status_t (*flush_blocks) (struct grub_efi_block_io *this);
+};
+typedef struct grub_efi_block_io grub_efi_block_io_t;
+
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+
+#define efi_call_0(func)               func()
+#define efi_call_1(func, a)            func(a)
+#define efi_call_2(func, a, b)         func(a, b)
+#define efi_call_3(func, a, b, c)      func(a, b, c)
+#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)
+
+#else
+
+#define efi_call_0(func)               efi_wrap_0(func)
+#define efi_call_1(func, 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)
+#define efi_call_3(func, a, b, 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)
+#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)
+#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)
+
+grub_uint64_t EXPORT_FUNC(efi_wrap_0) (void *func);
+grub_uint64_t EXPORT_FUNC(efi_wrap_1) (void *func, grub_uint64_t arg1);
+grub_uint64_t EXPORT_FUNC(efi_wrap_2) (void *func, grub_uint64_t arg1,
+                                       grub_uint64_t arg2);
+grub_uint64_t EXPORT_FUNC(efi_wrap_3) (void *func, grub_uint64_t arg1,
+                                       grub_uint64_t arg2, grub_uint64_t arg3);
+grub_uint64_t EXPORT_FUNC(efi_wrap_4) (void *func, grub_uint64_t arg1,
+                                       grub_uint64_t arg2, grub_uint64_t arg3,
+                                       grub_uint64_t arg4);
+grub_uint64_t EXPORT_FUNC(efi_wrap_5) (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 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);
+#endif
+
+#endif /* ! GRUB_EFI_API_HEADER */
diff --git a/include/grub/efi/chainloader.h b/include/grub/efi/chainloader.h
new file mode 100644 (file)
index 0000000..d5c11e3
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  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_EFI_CHAINLOADER_HEADER
+#define GRUB_EFI_CHAINLOADER_HEADER    1
+
+void grub_rescue_cmd_chainloader (int argc, char *argv[]);
+
+#endif /* ! GRUB_EFI_CHAINLOADER_HEADER */
diff --git a/include/grub/efi/console.h b/include/grub/efi/console.h
new file mode 100644 (file)
index 0000000..f90b5b7
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,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_EFI_CONSOLE_HEADER
+#define GRUB_EFI_CONSOLE_HEADER        1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+
+/* Initialize the console system.  */
+void grub_console_init (void);
+
+/* Finish the console system.  */
+void grub_console_fini (void);
+
+#endif /* ! GRUB_EFI_CONSOLE_HEADER */
diff --git a/include/grub/efi/console_control.h b/include/grub/efi/console_control.h
new file mode 100644 (file)
index 0000000..7c358fc
--- /dev/null
@@ -0,0 +1,57 @@
+/* console_control.h - definitions of the console control protocol */
+/*
+ *  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/>.
+ */
+
+/* The console control protocol is not a part of the EFI spec,
+   but defined in Intel's Sample Implementation.  */
+
+#ifndef GRUB_EFI_CONSOLE_CONTROL_HEADER
+#define GRUB_EFI_CONSOLE_CONTROL_HEADER        1
+
+#define GRUB_EFI_CONSOLE_CONTROL_GUID  \
+  { 0xf42f7782, 0x12e, 0x4c12, \
+    { 0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21 } \
+  }
+
+enum grub_efi_screen_mode
+  {
+    GRUB_EFI_SCREEN_TEXT,
+    GRUB_EFI_SCREEN_GRAPHICS,
+    GRUB_EFI_SCREEN_TEXT_MAX_VALUE
+  };
+typedef enum grub_efi_screen_mode grub_efi_screen_mode_t;
+
+struct grub_efi_console_control_protocol
+{
+  grub_efi_status_t
+  (*get_mode) (struct grub_efi_console_control_protocol *this,
+              grub_efi_screen_mode_t *mode,
+              grub_efi_boolean_t *uga_exists,
+              grub_efi_boolean_t *std_in_locked);
+
+  grub_efi_status_t
+  (*set_mode) (struct grub_efi_console_control_protocol *this,
+              grub_efi_screen_mode_t mode);
+
+  grub_efi_status_t
+  (*lock_std_in) (struct grub_efi_console_control_protocol *this,
+                 grub_efi_char16_t *password);
+};
+typedef struct grub_efi_console_control_protocol grub_efi_console_control_protocol_t;
+
+#endif /* ! GRUB_EFI_CONSOLE_CONTROL_HEADER */
diff --git a/include/grub/efi/disk.h b/include/grub/efi/disk.h
new file mode 100644 (file)
index 0000000..254475c
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  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_EFI_DISK_HEADER
+#define GRUB_EFI_DISK_HEADER   1
+
+#include <grub/efi/api.h>
+#include <grub/symbol.h>
+#include <grub/disk.h>
+
+grub_efi_handle_t
+EXPORT_FUNC(grub_efidisk_get_device_handle) (grub_disk_t disk);
+char *EXPORT_FUNC(grub_efidisk_get_device_name) (grub_efi_handle_t *handle);
+
+void grub_efidisk_init (void);
+void grub_efidisk_fini (void);
+
+#endif /* ! GRUB_EFI_DISK_HEADER */
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
new file mode 100644 (file)
index 0000000..8c277c0
--- /dev/null
@@ -0,0 +1,70 @@
+/* efi.h - declare variables and functions for EFI support */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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_EFI_EFI_HEADER
+#define GRUB_EFI_EFI_HEADER    1
+
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/efi/api.h>
+
+/* Functions.  */
+void *EXPORT_FUNC(grub_efi_locate_protocol) (grub_efi_guid_t *protocol,
+                                            void *registration);
+grub_efi_handle_t *
+EXPORT_FUNC(grub_efi_locate_handle) (grub_efi_locate_search_type_t search_type,
+                                    grub_efi_guid_t *protocol,
+                                    void *search_key,
+                                    grub_efi_uintn_t *num_handles);
+void *EXPORT_FUNC(grub_efi_open_protocol) (grub_efi_handle_t handle,
+                                          grub_efi_guid_t *protocol,
+                                          grub_efi_uint32_t attributes);
+int EXPORT_FUNC(grub_efi_set_text_mode) (int on);
+void EXPORT_FUNC(grub_efi_stall) (grub_efi_uintn_t microseconds);
+void *
+EXPORT_FUNC(grub_efi_allocate_pages) (grub_efi_physical_address_t address,
+                                     grub_efi_uintn_t pages);
+void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address,
+                                      grub_efi_uintn_t pages);
+int
+EXPORT_FUNC(grub_efi_get_memory_map) (grub_efi_uintn_t *memory_map_size,
+                                     grub_efi_memory_descriptor_t *memory_map,
+                                     grub_efi_uintn_t *map_key,
+                                     grub_efi_uintn_t *descriptor_size,
+                                     grub_efi_uint32_t *descriptor_version);
+grub_efi_loaded_image_t *EXPORT_FUNC(grub_efi_get_loaded_image) (grub_efi_handle_t image_handle);
+void EXPORT_FUNC(grub_efi_print_device_path) (grub_efi_device_path_t *dp);
+char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp);
+grub_efi_device_path_t *
+EXPORT_FUNC(grub_efi_get_device_path) (grub_efi_handle_t handle);
+int EXPORT_FUNC(grub_efi_exit_boot_services) (grub_efi_uintn_t map_key);
+void EXPORT_FUNC (grub_reboot) (void);
+void EXPORT_FUNC (grub_halt) (void);
+
+void grub_efi_mm_init (void);
+void grub_efi_mm_fini (void);
+void grub_efi_init (void);
+void grub_efi_fini (void);
+void grub_efi_set_prefix (void);
+
+/* Variables.  */
+extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table);
+extern grub_efi_handle_t EXPORT_VAR(grub_efi_image_handle);
+
+#endif /* ! GRUB_EFI_EFI_HEADER */
diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
new file mode 100644 (file)
index 0000000..50b4102
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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_EFI_PE32_HEADER
+#define GRUB_EFI_PE32_HEADER   1
+
+#include <grub/types.h>
+
+/* The MSDOS compatibility stub. This was copied from the output of
+   objcopy, and it is not necessary to care about what this means.  */
+#define GRUB_PE32_MSDOS_STUB \
+  { \
+    0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, \
+    0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, \
+    0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+    0x40, 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, 0x80, 0x00, 0x00, 0x00, \
+    0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, \
+    0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68, \
+    0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, \
+    0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, \
+    0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, \
+    0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20, \
+    0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, \
+    0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  \
+  }
+
+#define GRUB_PE32_MSDOS_STUB_SIZE      0x80
+
+/* According to the spec, the minimal alignment is 512 bytes...
+   But some examples (such as EFI drivers in the Intel
+   Sample Implementation) use 32 bytes (0x20) instead, and it seems
+   to be working. For now, GRUB uses 512 bytes for safety.  */
+#define GRUB_PE32_SECTION_ALIGNMENT    0x200
+#define GRUB_PE32_FILE_ALIGNMENT       GRUB_PE32_SECTION_ALIGNMENT
+
+struct grub_pe32_coff_header
+{
+  grub_uint16_t machine;
+  grub_uint16_t num_sections;
+  grub_uint32_t time;
+  grub_uint32_t symtab_offset;
+  grub_uint32_t num_symbols;
+  grub_uint16_t optional_header_size;
+  grub_uint16_t characteristics;
+};
+
+#define GRUB_PE32_MACHINE_I386         0x14c
+#define GRUB_PE32_MACHINE_X86_64       0x8664
+
+#define GRUB_PE32_RELOCS_STRIPPED              0x0001
+#define GRUB_PE32_EXECUTABLE_IMAGE             0x0002
+#define GRUB_PE32_LINE_NUMS_STRIPPED           0x0004
+#define GRUB_PE32_LOCAL_SYMS_STRIPPED          0x0008
+#define GRUB_PE32_AGGRESSIVE_WS_TRIM           0x0010
+#define GRUB_PE32_LARGE_ADDRESS_AWARE          0x0020
+#define GRUB_PE32_16BIT_MACHINE                        0x0040
+#define GRUB_PE32_BYTES_REVERSED_LO            0x0080
+#define GRUB_PE32_32BIT_MACHINE                        0x0100
+#define GRUB_PE32_DEBUG_STRIPPED               0x0200
+#define GRUB_PE32_REMOVABLE_RUN_FROM_SWAP      0x0400
+#define GRUB_PE32_SYSTEM                       0x1000
+#define GRUB_PE32_DLL                          0x2000
+#define GRUB_PE32_UP_SYSTEM_ONLY               0x4000
+#define GRUB_PE32_BYTES_REVERSED_HI            0x8000
+
+struct grub_pe32_data_directory
+{
+  grub_uint32_t rva;
+  grub_uint32_t size;
+};
+
+struct grub_pe32_optional_header
+{
+  grub_uint16_t magic;
+  grub_uint8_t major_linker_version;
+  grub_uint8_t minor_linker_version;
+  grub_uint32_t code_size;
+  grub_uint32_t data_size;
+  grub_uint32_t bss_size;
+  grub_uint32_t entry_addr;
+  grub_uint32_t code_base;
+  
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+  grub_uint32_t data_base;
+  grub_uint32_t image_base;
+#else
+  grub_uint64_t image_base;
+#endif
+
+  grub_uint32_t section_alignment;
+  grub_uint32_t file_alignment;
+  grub_uint16_t major_os_version;
+  grub_uint16_t minor_os_version;
+  grub_uint16_t major_image_version;
+  grub_uint16_t minor_image_version;
+  grub_uint16_t major_subsystem_version;
+  grub_uint16_t minor_subsystem_version;
+  grub_uint32_t reserved;
+  grub_uint32_t image_size;
+  grub_uint32_t header_size;
+  grub_uint32_t checksum;
+  grub_uint16_t subsystem;
+  grub_uint16_t dll_characteristics;
+
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+
+  grub_uint32_t stack_reserve_size;
+  grub_uint32_t stack_commit_size;
+  grub_uint32_t heap_reserve_size;
+  grub_uint32_t heap_commit_size;
+
+#else
+
+  grub_uint64_t stack_reserve_size;
+  grub_uint64_t stack_commit_size;
+  grub_uint64_t heap_reserve_size;
+  grub_uint64_t heap_commit_size;
+
+#endif
+
+  grub_uint32_t loader_flags;
+  grub_uint32_t num_data_directories;
+  
+  /* Data directories.  */
+  struct grub_pe32_data_directory export_table;
+  struct grub_pe32_data_directory import_table;
+  struct grub_pe32_data_directory resource_table;
+  struct grub_pe32_data_directory exception_table;
+  struct grub_pe32_data_directory certificate_table;
+  struct grub_pe32_data_directory base_relocation_table;
+  struct grub_pe32_data_directory debug;
+  struct grub_pe32_data_directory architecture;
+  struct grub_pe32_data_directory global_ptr;
+  struct grub_pe32_data_directory tls_table;
+  struct grub_pe32_data_directory load_config_table;
+  struct grub_pe32_data_directory bound_import;
+  struct grub_pe32_data_directory iat;
+  struct grub_pe32_data_directory delay_import_descriptor;
+  struct grub_pe32_data_directory com_runtime_header;
+  struct grub_pe32_data_directory reserved_entry;
+};
+
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+
+#define GRUB_PE32_PE32_MAGIC   0x10b
+
+#else
+
+#define GRUB_PE32_PE32_MAGIC   0x20b
+
+#endif
+
+#define GRUB_PE32_SUBSYSTEM_EFI_APPLICATION    10
+
+#define GRUB_PE32_NUM_DATA_DIRECTORIES 16
+
+struct grub_pe32_section_table
+{
+  char name[8];
+  grub_uint32_t virtual_size;
+  grub_uint32_t virtual_address;
+  grub_uint32_t raw_data_size;
+  grub_uint32_t raw_data_offset;
+  grub_uint32_t relocations_offset;
+  grub_uint32_t line_numbers_offset;
+  grub_uint16_t num_relocations;
+  grub_uint16_t num_line_numbers;
+  grub_uint32_t characteristics;
+};
+
+#define GRUB_PE32_SCN_CNT_CODE                 0x00000020
+#define GRUB_PE32_SCN_CNT_INITIALIZED_DATA     0x00000040
+#define GRUB_PE32_SCN_MEM_DISCARDABLE          0x02000000
+#define GRUB_PE32_SCN_MEM_EXECUTE              0x20000000
+#define GRUB_PE32_SCN_MEM_READ                 0x40000000
+#define GRUB_PE32_SCN_MEM_WRITE                        0x80000000
+
+#define GRUB_PE32_SCN_ALIGN_1BYTES             0x00100000
+#define GRUB_PE32_SCN_ALIGN_2BYTES             0x00200000
+#define GRUB_PE32_SCN_ALIGN_4BYTES             0x00300000
+#define GRUB_PE32_SCN_ALIGN_8BYTES             0x00400000
+#define GRUB_PE32_SCN_ALIGN_16BYTES            0x00500000
+#define GRUB_PE32_SCN_ALIGN_32BYTES            0x00600000
+#define GRUB_PE32_SCN_ALIGN_64BYTES            0x00700000
+
+#define GRUB_PE32_SCN_ALIGN_SHIFT              20
+#define GRUB_PE32_SCN_ALIGN_MASK               7
+
+
+struct grub_pe32_header
+{
+  /* This should be filled in with GRUB_PE32_MSDOS_STUB.  */
+  grub_uint8_t msdos_stub[GRUB_PE32_MSDOS_STUB_SIZE];
+  
+  /* This is always PE\0\0.  */
+  char signature[4];
+
+  /* The COFF file header.  */
+  struct grub_pe32_coff_header coff_header;
+
+  /* The Optional header.  */
+  struct grub_pe32_optional_header optional_header;
+};
+
+struct grub_pe32_fixup_block
+{
+  grub_uint32_t page_rva;
+  grub_uint32_t block_size;
+  grub_uint16_t entries[0];
+};
+
+#define GRUB_PE32_FIXUP_ENTRY(type, offset)    (((type) << 12) | (offset))
+
+#define GRUB_PE32_REL_BASED_ABSOLUTE   0
+#define GRUB_PE32_REL_BASED_HIGHLOW    3
+
+struct grub_pe32_symbol
+{
+  union
+  {
+    char short_name[8];
+    grub_uint32_t long_name[2];
+  };
+
+  grub_uint32_t value;
+  grub_uint16_t section;
+  grub_uint16_t type;
+  grub_uint8_t storage_class;
+  grub_uint8_t num_aux;
+} __attribute__ ((packed));
+
+#define GRUB_PE32_SYM_CLASS_EXTERNAL   2
+#define GRUB_PE32_SYM_CLASS_STATIC     3
+#define GRUB_PE32_SYM_CLASS_FILE       0x67
+
+#define GRUB_PE32_DT_FUNCTION          0x20
+
+struct grub_pe32_reloc
+{
+  grub_uint32_t offset;
+  grub_uint32_t symtab_index;
+  grub_uint16_t type;
+} __attribute__ ((packed));
+
+#define GRUB_PE32_REL_I386_DIR32       0x6
+#define GRUB_PE32_REL_I386_REL32       0x14
+
+#endif /* ! GRUB_EFI_PE32_HEADER */
diff --git a/include/grub/efi/time.h b/include/grub/efi/time.h
new file mode 100644 (file)
index 0000000..540f6fc
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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_EFI_TIME_HEADER
+#define GRUB_EFI_TIME_HEADER   1
+
+#include <grub/symbol.h>
+
+/* This is destined to overflow when one hour passes by.  */
+#define GRUB_TICKS_PER_SECOND  ((1UL << 31) / 60 / 60 * 2)
+
+/* Return the real time in ticks.  */
+grub_uint32_t EXPORT_FUNC (grub_get_rtc) (void);
+
+#endif /* ! GRUB_EFI_TIME_HEADER */
diff --git a/include/grub/efi/uga_draw.h b/include/grub/efi/uga_draw.h
new file mode 100644 (file)
index 0000000..9350430
--- /dev/null
@@ -0,0 +1,76 @@
+/* uga_draw.h - definitions of the uga draw protocol */
+/*
+ *  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/>.
+ */
+
+/* The console control protocol is not a part of the EFI spec,
+   but defined in Intel's Sample Implementation.  */
+
+#ifndef GRUB_EFI_UGA_DRAW_HEADER
+#define GRUB_EFI_UGA_DRAW_HEADER       1
+
+#define GRUB_EFI_UGA_DRAW_GUID \
+  { 0x982c298b, 0xf4fa, 0x41cb, { 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 }}
+
+enum grub_efi_uga_blt_operation
+{
+  GRUB_EFI_UGA_VIDEO_FILL,
+  GRUB_EFI_UGA_VIDEO_TO_BLT,
+  GRUB_EFI_UGA_BLT_TO_VIDEO,
+  GRUB_EFI_UGA_VIDEO_TO_VIDEO,
+  GRUB_EFI_UGA_GLT_MAX
+};
+
+struct grub_efi_uga_pixel
+{
+  grub_uint8_t Blue;
+  grub_uint8_t Green;
+  grub_uint8_t Red;
+  grub_uint8_t Reserved;
+};
+
+struct grub_efi_uga_draw_protocol
+{
+  grub_efi_status_t
+  (*get_mode) (struct grub_efi_uga_draw_protocol *this,
+              grub_uint32_t *width,
+              grub_uint32_t *height,
+              grub_uint32_t *depth,
+              grub_uint32_t *refresh_rate);
+
+  grub_efi_status_t
+  (*set_mode) (struct grub_efi_uga_draw_protocol *this,
+              grub_uint32_t width,
+              grub_uint32_t height,
+              grub_uint32_t depth,
+              grub_uint32_t refresh_rate);
+
+  grub_efi_status_t
+  (*blt) (struct grub_efi_uga_draw_protocol *this,
+         struct grub_efi_uga_pixel *blt_buffer,
+         enum grub_efi_uga_blt_operation blt_operation,
+         grub_efi_uintn_t src_x,
+         grub_efi_uintn_t src_y,
+         grub_efi_uintn_t dest_x,
+         grub_efi_uintn_t dest_y,
+         grub_efi_uintn_t width,
+         grub_efi_uintn_t height,
+         grub_efi_uintn_t delta);
+};
+typedef struct grub_efi_uga_draw_protocol grub_efi_uga_draw_protocol_t;
+
+#endif /* ! GRUB_EFI_UGA_DRAW_HEADER */
diff --git a/include/grub/elf.h b/include/grub/elf.h
new file mode 100644 (file)
index 0000000..5d46daa
--- /dev/null
@@ -0,0 +1,2333 @@
+/* This file defines standard ELF types, structures, and macros.
+   Copyright (C) 1995-1999, 2000, 2001, 2002,2008 Free Software Foundation, Inc.
+   This file was part of the GNU C Library.
+
+   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.  */
+
+#ifndef GRUB_ELF_H
+#define        GRUB_ELF_H 1
+
+/* Standard ELF types.  */
+
+#include <grub/types.h>
+
+/* Type for a 16-bit quantity.  */
+typedef grub_uint16_t Elf32_Half;
+typedef grub_uint16_t Elf64_Half;
+
+/* Types for signed and unsigned 32-bit quantities.  */
+typedef grub_uint32_t Elf32_Word;
+typedef        grub_int32_t  Elf32_Sword;
+typedef grub_uint32_t Elf64_Word;
+typedef        grub_int32_t  Elf64_Sword;
+
+/* Types for signed and unsigned 64-bit quantities.  */
+typedef grub_uint64_t Elf32_Xword;
+typedef        grub_int64_t  Elf32_Sxword;
+typedef grub_uint64_t Elf64_Xword;
+typedef        grub_int64_t  Elf64_Sxword;
+
+/* Type of addresses.  */
+typedef grub_uint32_t Elf32_Addr;
+typedef grub_uint64_t Elf64_Addr;
+
+/* Type of file offsets.  */
+typedef grub_uint32_t Elf32_Off;
+typedef grub_uint64_t Elf64_Off;
+
+/* Type for section indices, which are 16-bit quantities.  */
+typedef grub_uint16_t Elf32_Section;
+typedef grub_uint16_t Elf64_Section;
+
+/* Type for version symbol information.  */
+typedef Elf32_Half Elf32_Versym;
+typedef Elf64_Half Elf64_Versym;
+
+
+/* The ELF file header.  This appears at the start of every ELF file.  */
+
+#define EI_NIDENT (16)
+
+typedef struct
+{
+  unsigned char        e_ident[EI_NIDENT];     /* Magic number and other info */
+  Elf32_Half   e_type;                 /* Object file type */
+  Elf32_Half   e_machine;              /* Architecture */
+  Elf32_Word   e_version;              /* Object file version */
+  Elf32_Addr   e_entry;                /* Entry point virtual address */
+  Elf32_Off    e_phoff;                /* Program header table file offset */
+  Elf32_Off    e_shoff;                /* Section header table file offset */
+  Elf32_Word   e_flags;                /* Processor-specific flags */
+  Elf32_Half   e_ehsize;               /* ELF header size in bytes */
+  Elf32_Half   e_phentsize;            /* Program header table entry size */
+  Elf32_Half   e_phnum;                /* Program header table entry count */
+  Elf32_Half   e_shentsize;            /* Section header table entry size */
+  Elf32_Half   e_shnum;                /* Section header table entry count */
+  Elf32_Half   e_shstrndx;             /* Section header string table index */
+} Elf32_Ehdr;
+
+typedef struct
+{
+  unsigned char        e_ident[EI_NIDENT];     /* Magic number and other info */
+  Elf64_Half   e_type;                 /* Object file type */
+  Elf64_Half   e_machine;              /* Architecture */
+  Elf64_Word   e_version;              /* Object file version */
+  Elf64_Addr   e_entry;                /* Entry point virtual address */
+  Elf64_Off    e_phoff;                /* Program header table file offset */
+  Elf64_Off    e_shoff;                /* Section header table file offset */
+  Elf64_Word   e_flags;                /* Processor-specific flags */
+  Elf64_Half   e_ehsize;               /* ELF header size in bytes */
+  Elf64_Half   e_phentsize;            /* Program header table entry size */
+  Elf64_Half   e_phnum;                /* Program header table entry count */
+  Elf64_Half   e_shentsize;            /* Section header table entry size */
+  Elf64_Half   e_shnum;                /* Section header table entry count */
+  Elf64_Half   e_shstrndx;             /* Section header string table index */
+} Elf64_Ehdr;
+
+/* Fields in the e_ident array.  The EI_* macros are indices into the
+   array.  The macros under each EI_* macro are the values the byte
+   may have.  */
+
+#define EI_MAG0                0               /* File identification byte 0 index */
+#define ELFMAG0                0x7f            /* Magic number byte 0 */
+
+#define EI_MAG1                1               /* File identification byte 1 index */
+#define ELFMAG1                'E'             /* Magic number byte 1 */
+
+#define EI_MAG2                2               /* File identification byte 2 index */
+#define ELFMAG2                'L'             /* Magic number byte 2 */
+
+#define EI_MAG3                3               /* File identification byte 3 index */
+#define ELFMAG3                'F'             /* Magic number byte 3 */
+
+/* Conglomeration of the identification bytes, for easy testing as a word.  */
+#define        ELFMAG          "\177ELF"
+#define        SELFMAG         4
+
+#define EI_CLASS       4               /* File class byte index */
+#define ELFCLASSNONE   0               /* Invalid class */
+#define ELFCLASS32     1               /* 32-bit objects */
+#define ELFCLASS64     2               /* 64-bit objects */
+#define ELFCLASSNUM    3
+
+#define EI_DATA                5               /* Data encoding byte index */
+#define ELFDATANONE    0               /* Invalid data encoding */
+#define ELFDATA2LSB    1               /* 2's complement, little endian */
+#define ELFDATA2MSB    2               /* 2's complement, big endian */
+#define ELFDATANUM     3
+
+#define EI_VERSION     6               /* File version byte index */
+                                       /* Value must be EV_CURRENT */
+
+#define EI_OSABI       7               /* OS ABI identification */
+#define ELFOSABI_NONE          0       /* UNIX System V ABI */
+#define ELFOSABI_SYSV          0       /* Alias.  */
+#define ELFOSABI_HPUX          1       /* HP-UX */
+#define ELFOSABI_NETBSD                2       /* NetBSD.  */
+#define ELFOSABI_LINUX         3       /* Linux.  */
+#define ELFOSABI_SOLARIS       6       /* Sun Solaris.  */
+#define ELFOSABI_AIX           7       /* IBM AIX.  */
+#define ELFOSABI_IRIX          8       /* SGI Irix.  */
+#define ELFOSABI_FREEBSD       9       /* FreeBSD.  */
+#define ELFOSABI_TRU64         10      /* Compaq TRU64 UNIX.  */
+#define ELFOSABI_MODESTO       11      /* Novell Modesto.  */
+#define ELFOSABI_OPENBSD       12      /* OpenBSD.  */
+#define ELFOSABI_ARM           97      /* ARM */
+#define ELFOSABI_STANDALONE    255     /* Standalone (embedded) application */
+
+#define EI_ABIVERSION  8               /* ABI version */
+
+#define EI_PAD         9               /* Byte index of padding bytes */
+
+/* Legal values for e_type (object file type).  */
+
+#define ET_NONE                0               /* No file type */
+#define ET_REL         1               /* Relocatable file */
+#define ET_EXEC                2               /* Executable file */
+#define ET_DYN         3               /* Shared object file */
+#define ET_CORE                4               /* Core file */
+#define        ET_NUM          5               /* Number of defined types */
+#define ET_LOOS                0xfe00          /* OS-specific range start */
+#define ET_HIOS                0xfeff          /* OS-specific range end */
+#define ET_LOPROC      0xff00          /* Processor-specific range start */
+#define ET_HIPROC      0xffff          /* Processor-specific range end */
+
+/* Legal values for e_machine (architecture).  */
+
+#define EM_NONE                 0              /* No machine */
+#define EM_M32          1              /* AT&T WE 32100 */
+#define EM_SPARC        2              /* SUN SPARC */
+#define EM_386          3              /* Intel 80386 */
+#define EM_68K          4              /* Motorola m68k family */
+#define EM_88K          5              /* Motorola m88k family */
+#define EM_860          7              /* Intel 80860 */
+#define EM_MIPS                 8              /* MIPS R3000 big-endian */
+#define EM_S370                 9              /* IBM System/370 */
+#define EM_MIPS_RS3_LE 10              /* MIPS R3000 little-endian */
+
+#define EM_PARISC      15              /* HPPA */
+#define EM_VPP500      17              /* Fujitsu VPP500 */
+#define EM_SPARC32PLUS 18              /* Sun's "v8plus" */
+#define EM_960         19              /* Intel 80960 */
+#define EM_PPC         20              /* PowerPC */
+#define EM_PPC64       21              /* PowerPC 64-bit */
+#define EM_S390                22              /* IBM S390 */
+
+#define EM_V800                36              /* NEC V800 series */
+#define EM_FR20                37              /* Fujitsu FR20 */
+#define EM_RH32                38              /* TRW RH-32 */
+#define EM_RCE         39              /* Motorola RCE */
+#define EM_ARM         40              /* ARM */
+#define EM_FAKE_ALPHA  41              /* Digital Alpha */
+#define EM_SH          42              /* Hitachi SH */
+#define EM_SPARCV9     43              /* SPARC v9 64-bit */
+#define EM_TRICORE     44              /* Siemens Tricore */
+#define EM_ARC         45              /* Argonaut RISC Core */
+#define EM_H8_300      46              /* Hitachi H8/300 */
+#define EM_H8_300H     47              /* Hitachi H8/300H */
+#define EM_H8S         48              /* Hitachi H8S */
+#define EM_H8_500      49              /* Hitachi H8/500 */
+#define EM_IA_64       50              /* Intel Merced */
+#define EM_MIPS_X      51              /* Stanford MIPS-X */
+#define EM_COLDFIRE    52              /* Motorola Coldfire */
+#define EM_68HC12      53              /* Motorola M68HC12 */
+#define EM_MMA         54              /* Fujitsu MMA Multimedia Accelerator*/
+#define EM_PCP         55              /* Siemens PCP */
+#define EM_NCPU                56              /* Sony nCPU embeeded RISC */
+#define EM_NDR1                57              /* Denso NDR1 microprocessor */
+#define EM_STARCORE    58              /* Motorola Start*Core processor */
+#define EM_ME16                59              /* Toyota ME16 processor */
+#define EM_ST100       60              /* STMicroelectronic ST100 processor */
+#define EM_TINYJ       61              /* Advanced Logic Corp. Tinyj emb.fam*/
+#define EM_X86_64      62              /* AMD x86-64 architecture */
+#define EM_PDSP                63              /* Sony DSP Processor */
+
+#define EM_FX66                66              /* Siemens FX66 microcontroller */
+#define EM_ST9PLUS     67              /* STMicroelectronics ST9+ 8/16 mc */
+#define EM_ST7         68              /* STmicroelectronics ST7 8 bit mc */
+#define EM_68HC16      69              /* Motorola MC68HC16 microcontroller */
+#define EM_68HC11      70              /* Motorola MC68HC11 microcontroller */
+#define EM_68HC08      71              /* Motorola MC68HC08 microcontroller */
+#define EM_68HC05      72              /* Motorola MC68HC05 microcontroller */
+#define EM_SVX         73              /* Silicon Graphics SVx */
+#define EM_AT19                74              /* STMicroelectronics ST19 8 bit mc */
+#define EM_VAX         75              /* Digital VAX */
+#define EM_CRIS                76              /* Axis Communications 32-bit embedded processor */
+#define EM_JAVELIN     77              /* Infineon Technologies 32-bit embedded processor */
+#define EM_FIREPATH    78              /* Element 14 64-bit DSP Processor */
+#define EM_ZSP         79              /* LSI Logic 16-bit DSP Processor */
+#define EM_MMIX                80              /* Donald Knuth's educational 64-bit processor */
+#define EM_HUANY       81              /* Harvard University machine-independent object files */
+#define EM_PRISM       82              /* SiTera Prism */
+#define EM_AVR         83              /* Atmel AVR 8-bit microcontroller */
+#define EM_FR30                84              /* Fujitsu FR30 */
+#define EM_D10V                85              /* Mitsubishi D10V */
+#define EM_D30V                86              /* Mitsubishi D30V */
+#define EM_V850                87              /* NEC v850 */
+#define EM_M32R                88              /* Mitsubishi M32R */
+#define EM_MN10300     89              /* Matsushita MN10300 */
+#define EM_MN10200     90              /* Matsushita MN10200 */
+#define EM_PJ          91              /* picoJava */
+#define EM_OPENRISC    92              /* OpenRISC 32-bit embedded processor */
+#define EM_ARC_A5      93              /* ARC Cores Tangent-A5 */
+#define EM_XTENSA      94              /* Tensilica Xtensa Architecture */
+#define EM_NUM         95
+
+/* If it is necessary to assign new unofficial EM_* values, please
+   pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
+   chances of collision with official or non-GNU unofficial values.  */
+
+#define EM_ALPHA       0x9026
+
+/* Legal values for e_version (version).  */
+
+#define EV_NONE                0               /* Invalid ELF version */
+#define EV_CURRENT     1               /* Current version */
+#define EV_NUM         2
+
+/* Section header.  */
+
+typedef struct
+{
+  Elf32_Word   sh_name;                /* Section name (string tbl index) */
+  Elf32_Word   sh_type;                /* Section type */
+  Elf32_Word   sh_flags;               /* Section flags */
+  Elf32_Addr   sh_addr;                /* Section virtual addr at execution */
+  Elf32_Off    sh_offset;              /* Section file offset */
+  Elf32_Word   sh_size;                /* Section size in bytes */
+  Elf32_Word   sh_link;                /* Link to another section */
+  Elf32_Word   sh_info;                /* Additional section information */
+  Elf32_Word   sh_addralign;           /* Section alignment */
+  Elf32_Word   sh_entsize;             /* Entry size if section holds table */
+} Elf32_Shdr;
+
+typedef struct
+{
+  Elf64_Word   sh_name;                /* Section name (string tbl index) */
+  Elf64_Word   sh_type;                /* Section type */
+  Elf64_Xword  sh_flags;               /* Section flags */
+  Elf64_Addr   sh_addr;                /* Section virtual addr at execution */
+  Elf64_Off    sh_offset;              /* Section file offset */
+  Elf64_Xword  sh_size;                /* Section size in bytes */
+  Elf64_Word   sh_link;                /* Link to another section */
+  Elf64_Word   sh_info;                /* Additional section information */
+  Elf64_Xword  sh_addralign;           /* Section alignment */
+  Elf64_Xword  sh_entsize;             /* Entry size if section holds table */
+} Elf64_Shdr;
+
+/* Special section indices.  */
+
+#define SHN_UNDEF      0               /* Undefined section */
+#define SHN_LORESERVE  0xff00          /* Start of reserved indices */
+#define SHN_LOPROC     0xff00          /* Start of processor-specific */
+#define SHN_HIPROC     0xff1f          /* End of processor-specific */
+#define SHN_LOOS       0xff20          /* Start of OS-specific */
+#define SHN_HIOS       0xff3f          /* End of OS-specific */
+#define SHN_ABS                0xfff1          /* Associated symbol is absolute */
+#define SHN_COMMON     0xfff2          /* Associated symbol is common */
+#define SHN_XINDEX     0xffff          /* Index is in extra table.  */
+#define SHN_HIRESERVE  0xffff          /* End of reserved indices */
+
+/* Legal values for sh_type (section type).  */
+
+#define SHT_NULL         0             /* Section header table entry unused */
+#define SHT_PROGBITS     1             /* Program data */
+#define SHT_SYMTAB       2             /* Symbol table */
+#define SHT_STRTAB       3             /* String table */
+#define SHT_RELA         4             /* Relocation entries with addends */
+#define SHT_HASH         5             /* Symbol hash table */
+#define SHT_DYNAMIC      6             /* Dynamic linking information */
+#define SHT_NOTE         7             /* Notes */
+#define SHT_NOBITS       8             /* Program space with no data (bss) */
+#define SHT_REL                  9             /* Relocation entries, no addends */
+#define SHT_SHLIB        10            /* Reserved */
+#define SHT_DYNSYM       11            /* Dynamic linker symbol table */
+#define SHT_INIT_ARRAY   14            /* Array of constructors */
+#define SHT_FINI_ARRAY   15            /* Array of destructors */
+#define SHT_PREINIT_ARRAY 16           /* Array of pre-constructors */
+#define SHT_GROUP        17            /* Section group */
+#define SHT_SYMTAB_SHNDX  18           /* Extended section indeces */
+#define        SHT_NUM           19            /* Number of defined types.  */
+#define SHT_LOOS         0x60000000    /* Start OS-specific */
+#define SHT_GNU_LIBLIST          0x6ffffff7    /* Prelink library list */
+#define SHT_CHECKSUM     0x6ffffff8    /* Checksum for DSO content.  */
+#define SHT_LOSUNW       0x6ffffffa    /* Sun-specific low bound.  */
+#define SHT_SUNW_move    0x6ffffffa
+#define SHT_SUNW_COMDAT   0x6ffffffb
+#define SHT_SUNW_syminfo  0x6ffffffc
+#define SHT_GNU_verdef   0x6ffffffd    /* Version definition section.  */
+#define SHT_GNU_verneed          0x6ffffffe    /* Version needs section.  */
+#define SHT_GNU_versym   0x6fffffff    /* Version symbol table.  */
+#define SHT_HISUNW       0x6fffffff    /* Sun-specific high bound.  */
+#define SHT_HIOS         0x6fffffff    /* End OS-specific type */
+#define SHT_LOPROC       0x70000000    /* Start of processor-specific */
+#define SHT_HIPROC       0x7fffffff    /* End of processor-specific */
+#define SHT_LOUSER       0x80000000    /* Start of application-specific */
+#define SHT_HIUSER       0x8fffffff    /* End of application-specific */
+
+/* Legal values for sh_flags (section flags).  */
+
+#define SHF_WRITE           (1 << 0)   /* Writable */
+#define SHF_ALLOC           (1 << 1)   /* Occupies memory during execution */
+#define SHF_EXECINSTR       (1 << 2)   /* Executable */
+#define SHF_MERGE           (1 << 4)   /* Might be merged */
+#define SHF_STRINGS         (1 << 5)   /* Contains nul-terminated strings */
+#define SHF_INFO_LINK       (1 << 6)   /* `sh_info' contains SHT index */
+#define SHF_LINK_ORDER      (1 << 7)   /* Preserve order after combining */
+#define SHF_OS_NONCONFORMING (1 << 8)  /* Non-standard OS specific handling
+                                          required */
+#define SHF_GROUP           (1 << 9)   /* Section is member of a group.  */
+#define SHF_TLS                     (1 << 10)  /* Section hold thread-local data.  */
+#define SHF_MASKOS          0x0ff00000 /* OS-specific.  */
+#define SHF_MASKPROC        0xf0000000 /* Processor-specific */
+
+/* Section group handling.  */
+#define GRP_COMDAT     0x1             /* Mark group as COMDAT.  */
+
+/* Symbol table entry.  */
+
+typedef struct
+{
+  Elf32_Word   st_name;                /* Symbol name (string tbl index) */
+  Elf32_Addr   st_value;               /* Symbol value */
+  Elf32_Word   st_size;                /* Symbol size */
+  unsigned char        st_info;                /* Symbol type and binding */
+  unsigned char        st_other;               /* Symbol visibility */
+  Elf32_Section        st_shndx;               /* Section index */
+} Elf32_Sym;
+
+typedef struct
+{
+  Elf64_Word   st_name;                /* Symbol name (string tbl index) */
+  unsigned char        st_info;                /* Symbol type and binding */
+  unsigned char st_other;              /* Symbol visibility */
+  Elf64_Section        st_shndx;               /* Section index */
+  Elf64_Addr   st_value;               /* Symbol value */
+  Elf64_Xword  st_size;                /* Symbol size */
+} Elf64_Sym;
+
+/* The syminfo section if available contains additional information about
+   every dynamic symbol.  */
+
+typedef struct
+{
+  Elf32_Half si_boundto;               /* Direct bindings, symbol bound to */
+  Elf32_Half si_flags;                 /* Per symbol flags */
+} Elf32_Syminfo;
+
+typedef struct
+{
+  Elf64_Half si_boundto;               /* Direct bindings, symbol bound to */
+  Elf64_Half si_flags;                 /* Per symbol flags */
+} Elf64_Syminfo;
+
+/* Possible values for si_boundto.  */
+#define SYMINFO_BT_SELF                0xffff  /* Symbol bound to self */
+#define SYMINFO_BT_PARENT      0xfffe  /* Symbol bound to parent */
+#define SYMINFO_BT_LOWRESERVE  0xff00  /* Beginning of reserved entries */
+
+/* Possible bitmasks for si_flags.  */
+#define SYMINFO_FLG_DIRECT     0x0001  /* Direct bound symbol */
+#define SYMINFO_FLG_PASSTHRU   0x0002  /* Pass-thru symbol for translator */
+#define SYMINFO_FLG_COPY       0x0004  /* Symbol is a copy-reloc */
+#define SYMINFO_FLG_LAZYLOAD   0x0008  /* Symbol bound to object to be lazy
+                                          loaded */
+/* Syminfo version values.  */
+#define SYMINFO_NONE           0
+#define SYMINFO_CURRENT                1
+#define SYMINFO_NUM            2
+
+
+/* How to extract and insert information held in the st_info field.  */
+
+#define ELF32_ST_BIND(val)             (((unsigned char) (val)) >> 4)
+#define ELF32_ST_TYPE(val)             ((val) & 0xf)
+#define ELF32_ST_INFO(bind, type)      (((bind) << 4) + ((type) & 0xf))
+
+/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field.  */
+#define ELF64_ST_BIND(val)             ELF32_ST_BIND (val)
+#define ELF64_ST_TYPE(val)             ELF32_ST_TYPE (val)
+#define ELF64_ST_INFO(bind, type)      ELF32_ST_INFO ((bind), (type))
+
+/* Legal values for ST_BIND subfield of st_info (symbol binding).  */
+
+#define STB_LOCAL      0               /* Local symbol */
+#define STB_GLOBAL     1               /* Global symbol */
+#define STB_WEAK       2               /* Weak symbol */
+#define        STB_NUM         3               /* Number of defined types.  */
+#define STB_LOOS       10              /* Start of OS-specific */
+#define STB_HIOS       12              /* End of OS-specific */
+#define STB_LOPROC     13              /* Start of processor-specific */
+#define STB_HIPROC     15              /* End of processor-specific */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_NOTYPE     0               /* Symbol type is unspecified */
+#define STT_OBJECT     1               /* Symbol is a data object */
+#define STT_FUNC       2               /* Symbol is a code object */
+#define STT_SECTION    3               /* Symbol associated with a section */
+#define STT_FILE       4               /* Symbol's name is file name */
+#define STT_COMMON     5               /* Symbol is a common data object */
+#define STT_TLS                6               /* Symbol is thread-local data object*/
+#define        STT_NUM         7               /* Number of defined types.  */
+#define STT_LOOS       10              /* Start of OS-specific */
+#define STT_HIOS       12              /* End of OS-specific */
+#define STT_LOPROC     13              /* Start of processor-specific */
+#define STT_HIPROC     15              /* End of processor-specific */
+
+
+/* Symbol table indices are found in the hash buckets and chain table
+   of a symbol hash table section.  This special index value indicates
+   the end of a chain, meaning no further symbols are found in that bucket.  */
+
+#define STN_UNDEF      0               /* End of a chain.  */
+#define STN_ABS                65521
+
+
+/* How to extract and insert information held in the st_other field.  */
+
+#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
+
+/* For ELF64 the definitions are the same.  */
+#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
+
+/* Symbol visibility specification encoded in the st_other field.  */
+#define STV_DEFAULT    0               /* Default symbol visibility rules */
+#define STV_INTERNAL   1               /* Processor specific hidden class */
+#define STV_HIDDEN     2               /* Sym unavailable in other modules */
+#define STV_PROTECTED  3               /* Not preemptible, not exported */
+
+
+/* Relocation table entry without addend (in section of type SHT_REL).  */
+
+typedef struct
+{
+  Elf32_Addr   r_offset;               /* Address */
+  Elf32_Word   r_info;                 /* Relocation type and symbol index */
+} Elf32_Rel;
+
+/* I have seen two different definitions of the Elf64_Rel and
+   Elf64_Rela structures, so we'll leave them out until Novell (or
+   whoever) gets their act together.  */
+/* The following, at least, is used on Sparc v9, MIPS, and Alpha.  */
+
+typedef struct
+{
+  Elf64_Addr   r_offset;               /* Address */
+  Elf64_Xword  r_info;                 /* Relocation type and symbol index */
+} Elf64_Rel;
+
+/* Relocation table entry with addend (in section of type SHT_RELA).  */
+
+typedef struct
+{
+  Elf32_Addr   r_offset;               /* Address */
+  Elf32_Word   r_info;                 /* Relocation type and symbol index */
+  Elf32_Sword  r_addend;               /* Addend */
+} Elf32_Rela;
+
+typedef struct
+{
+  Elf64_Addr   r_offset;               /* Address */
+  Elf64_Xword  r_info;                 /* Relocation type and symbol index */
+  Elf64_Sxword r_addend;               /* Addend */
+} Elf64_Rela;
+
+/* How to extract and insert information held in the r_info field.  */
+
+#define ELF32_R_SYM(val)               ((val) >> 8)
+#define ELF32_R_TYPE(val)              ((val) & 0xff)
+#define ELF32_R_INFO(sym, type)                (((sym) << 8) + ((type) & 0xff))
+
+#define ELF64_R_SYM(i)                 ((i) >> 32)
+#define ELF64_R_TYPE(i)                        ((i) & 0xffffffff)
+#define ELF64_R_INFO(sym,type)         ((((Elf64_Xword) (sym)) << 32) + (type))
+
+/* Program segment header.  */
+
+typedef struct
+{
+  Elf32_Word   p_type;                 /* Segment type */
+  Elf32_Off    p_offset;               /* Segment file offset */
+  Elf32_Addr   p_vaddr;                /* Segment virtual address */
+  Elf32_Addr   p_paddr;                /* Segment physical address */
+  Elf32_Word   p_filesz;               /* Segment size in file */
+  Elf32_Word   p_memsz;                /* Segment size in memory */
+  Elf32_Word   p_flags;                /* Segment flags */
+  Elf32_Word   p_align;                /* Segment alignment */
+} Elf32_Phdr;
+
+typedef struct
+{
+  Elf64_Word   p_type;                 /* Segment type */
+  Elf64_Word   p_flags;                /* Segment flags */
+  Elf64_Off    p_offset;               /* Segment file offset */
+  Elf64_Addr   p_vaddr;                /* Segment virtual address */
+  Elf64_Addr   p_paddr;                /* Segment physical address */
+  Elf64_Xword  p_filesz;               /* Segment size in file */
+  Elf64_Xword  p_memsz;                /* Segment size in memory */
+  Elf64_Xword  p_align;                /* Segment alignment */
+} Elf64_Phdr;
+
+/* Legal values for p_type (segment type).  */
+
+#define        PT_NULL         0               /* Program header table entry unused */
+#define PT_LOAD                1               /* Loadable program segment */
+#define PT_DYNAMIC     2               /* Dynamic linking information */
+#define PT_INTERP      3               /* Program interpreter */
+#define PT_NOTE                4               /* Auxiliary information */
+#define PT_SHLIB       5               /* Reserved */
+#define PT_PHDR                6               /* Entry for header table itself */
+#define PT_TLS         7               /* Thread-local storage segment */
+#define        PT_NUM          8               /* Number of defined types */
+#define PT_LOOS                0x60000000      /* Start of OS-specific */
+#define PT_GNU_EH_FRAME        0x6474e550      /* GCC .eh_frame_hdr segment */
+#define PT_LOSUNW      0x6ffffffa
+#define PT_SUNWBSS     0x6ffffffa      /* Sun Specific segment */
+#define PT_SUNWSTACK   0x6ffffffb      /* Stack segment */
+#define PT_HISUNW      0x6fffffff
+#define PT_HIOS                0x6fffffff      /* End of OS-specific */
+#define PT_LOPROC      0x70000000      /* Start of processor-specific */
+#define PT_HIPROC      0x7fffffff      /* End of processor-specific */
+
+/* Legal values for p_flags (segment flags).  */
+
+#define PF_X           (1 << 0)        /* Segment is executable */
+#define PF_W           (1 << 1)        /* Segment is writable */
+#define PF_R           (1 << 2)        /* Segment is readable */
+#define PF_MASKOS      0x0ff00000      /* OS-specific */
+#define PF_MASKPROC    0xf0000000      /* Processor-specific */
+
+/* Legal values for note segment descriptor types for core files. */
+
+#define NT_PRSTATUS    1               /* Contains copy of prstatus struct */
+#define NT_FPREGSET    2               /* Contains copy of fpregset struct */
+#define NT_PRPSINFO    3               /* Contains copy of prpsinfo struct */
+#define NT_PRXREG      4               /* Contains copy of prxregset struct */
+#define NT_PLATFORM    5               /* String from sysinfo(SI_PLATFORM) */
+#define NT_AUXV                6               /* Contains copy of auxv array */
+#define NT_GWINDOWS    7               /* Contains copy of gwindows struct */
+#define NT_ASRS                8               /* Contains copy of asrset struct */
+#define NT_PSTATUS     10              /* Contains copy of pstatus struct */
+#define NT_PSINFO      13              /* Contains copy of psinfo struct */
+#define NT_PRCRED      14              /* Contains copy of prcred struct */
+#define NT_UTSNAME     15              /* Contains copy of utsname struct */
+#define NT_LWPSTATUS   16              /* Contains copy of lwpstatus struct */
+#define NT_LWPSINFO    17              /* Contains copy of lwpinfo struct */
+#define NT_PRFPXREG    20              /* Contains copy of fprxregset struct*/
+
+/* Legal values for the note segment descriptor types for object files.  */
+
+#define NT_VERSION     1               /* Contains a version string.  */
+
+
+/* Dynamic section entry.  */
+
+typedef struct
+{
+  Elf32_Sword  d_tag;                  /* Dynamic entry type */
+  union
+    {
+      Elf32_Word d_val;                        /* Integer value */
+      Elf32_Addr d_ptr;                        /* Address value */
+    } d_un;
+} Elf32_Dyn;
+
+typedef struct
+{
+  Elf64_Sxword d_tag;                  /* Dynamic entry type */
+  union
+    {
+      Elf64_Xword d_val;               /* Integer value */
+      Elf64_Addr d_ptr;                        /* Address value */
+    } d_un;
+} Elf64_Dyn;
+
+/* Legal values for d_tag (dynamic entry type).  */
+
+#define DT_NULL                0               /* Marks end of dynamic section */
+#define DT_NEEDED      1               /* Name of needed library */
+#define DT_PLTRELSZ    2               /* Size in bytes of PLT relocs */
+#define DT_PLTGOT      3               /* Processor defined value */
+#define DT_HASH                4               /* Address of symbol hash table */
+#define DT_STRTAB      5               /* Address of string table */
+#define DT_SYMTAB      6               /* Address of symbol table */
+#define DT_RELA                7               /* Address of Rela relocs */
+#define DT_RELASZ      8               /* Total size of Rela relocs */
+#define DT_RELAENT     9               /* Size of one Rela reloc */
+#define DT_STRSZ       10              /* Size of string table */
+#define DT_SYMENT      11              /* Size of one symbol table entry */
+#define DT_INIT                12              /* Address of init function */
+#define DT_FINI                13              /* Address of termination function */
+#define DT_SONAME      14              /* Name of shared object */
+#define DT_RPATH       15              /* Library search path (deprecated) */
+#define DT_SYMBOLIC    16              /* Start symbol search here */
+#define DT_REL         17              /* Address of Rel relocs */
+#define DT_RELSZ       18              /* Total size of Rel relocs */
+#define DT_RELENT      19              /* Size of one Rel reloc */
+#define DT_PLTREL      20              /* Type of reloc in PLT */
+#define DT_DEBUG       21              /* For debugging; unspecified */
+#define DT_TEXTREL     22              /* Reloc might modify .text */
+#define DT_JMPREL      23              /* Address of PLT relocs */
+#define        DT_BIND_NOW     24              /* Process relocations of object */
+#define        DT_INIT_ARRAY   25              /* Array with addresses of init fct */
+#define        DT_FINI_ARRAY   26              /* Array with addresses of fini fct */
+#define        DT_INIT_ARRAYSZ 27              /* Size in bytes of DT_INIT_ARRAY */
+#define        DT_FINI_ARRAYSZ 28              /* Size in bytes of DT_FINI_ARRAY */
+#define DT_RUNPATH     29              /* Library search path */
+#define DT_FLAGS       30              /* Flags for the object being loaded */
+#define DT_ENCODING    32              /* Start of encoded range */
+#define DT_PREINIT_ARRAY 32            /* Array with addresses of preinit fct*/
+#define DT_PREINIT_ARRAYSZ 33          /* size in bytes of DT_PREINIT_ARRAY */
+#define        DT_NUM          34              /* Number used */
+#define DT_LOOS                0x6000000d      /* Start of OS-specific */
+#define DT_HIOS                0x6ffff000      /* End of OS-specific */
+#define DT_LOPROC      0x70000000      /* Start of processor-specific */
+#define DT_HIPROC      0x7fffffff      /* End of processor-specific */
+#define        DT_PROCNUM      DT_MIPS_NUM     /* Most used by any processor */
+
+/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
+   Dyn.d_un.d_val field of the Elf*_Dyn structure.  This follows Sun's
+   approach.  */
+#define DT_VALRNGLO    0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5    /* Prelinking timestamp */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6   /* Size of conflict section */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7    /* Size of library list */
+#define DT_CHECKSUM    0x6ffffdf8
+#define DT_PLTPADSZ    0x6ffffdf9
+#define DT_MOVEENT     0x6ffffdfa
+#define DT_MOVESZ      0x6ffffdfb
+#define DT_FEATURE_1   0x6ffffdfc      /* Feature selection (DTF_*).  */
+#define DT_POSFLAG_1   0x6ffffdfd      /* Flags for DT_* entries, effecting
+                                          the following DT_* entry.  */
+#define DT_SYMINSZ     0x6ffffdfe      /* Size of syminfo table (in bytes) */
+#define DT_SYMINENT    0x6ffffdff      /* Entry size of syminfo */
+#define DT_VALRNGHI    0x6ffffdff
+#define DT_VALTAGIDX(tag)      (DT_VALRNGHI - (tag))   /* Reverse order! */
+#define DT_VALNUM 12
+
+/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
+   Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+
+   If any adjustment is made to the ELF object after it has been
+   built these entries will need to be adjusted.  */
+#define DT_ADDRRNGLO   0x6ffffe00
+#define DT_GNU_CONFLICT        0x6ffffef8      /* Start of conflict section */
+#define DT_GNU_LIBLIST 0x6ffffef9      /* Library list */
+#define DT_CONFIG      0x6ffffefa      /* Configuration information.  */
+#define DT_DEPAUDIT    0x6ffffefb      /* Dependency auditing.  */
+#define DT_AUDIT       0x6ffffefc      /* Object auditing.  */
+#define        DT_PLTPAD       0x6ffffefd      /* PLT padding.  */
+#define        DT_MOVETAB      0x6ffffefe      /* Move table.  */
+#define DT_SYMINFO     0x6ffffeff      /* Syminfo table.  */
+#define DT_ADDRRNGHI   0x6ffffeff
+#define DT_ADDRTAGIDX(tag)     (DT_ADDRRNGHI - (tag))  /* Reverse order! */
+#define DT_ADDRNUM 10
+
+/* The versioning entry types.  The next are defined as part of the
+   GNU extension.  */
+#define DT_VERSYM      0x6ffffff0
+
+#define DT_RELACOUNT   0x6ffffff9
+#define DT_RELCOUNT    0x6ffffffa
+
+/* These were chosen by Sun.  */
+#define DT_FLAGS_1     0x6ffffffb      /* State flags, see DF_1_* below.  */
+#define        DT_VERDEF       0x6ffffffc      /* Address of version definition
+                                          table */
+#define        DT_VERDEFNUM    0x6ffffffd      /* Number of version definitions */
+#define        DT_VERNEED      0x6ffffffe      /* Address of table with needed
+                                          versions */
+#define        DT_VERNEEDNUM   0x6fffffff      /* Number of needed versions */
+#define DT_VERSIONTAGIDX(tag)  (DT_VERNEEDNUM - (tag)) /* Reverse order! */
+#define DT_VERSIONTAGNUM 16
+
+/* Sun added these machine-independent extensions in the "processor-specific"
+   range.  Be compatible.  */
+#define DT_AUXILIARY    0x7ffffffd      /* Shared object to load before self */
+#define DT_FILTER       0x7fffffff      /* Shared object to get values from */
+#define DT_EXTRATAGIDX(tag)    ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
+#define DT_EXTRANUM    3
+
+/* Values of `d_un.d_val' in the DT_FLAGS entry.  */
+#define DF_ORIGIN      0x00000001      /* Object may use DF_ORIGIN */
+#define DF_SYMBOLIC    0x00000002      /* Symbol resolutions starts here */
+#define DF_TEXTREL     0x00000004      /* Object contains text relocations */
+#define DF_BIND_NOW    0x00000008      /* No lazy binding for this object */
+#define DF_STATIC_TLS  0x00000010      /* Module uses the static TLS model */
+
+/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
+   entry in the dynamic section.  */
+#define DF_1_NOW       0x00000001      /* Set RTLD_NOW for this object.  */
+#define DF_1_GLOBAL    0x00000002      /* Set RTLD_GLOBAL for this object.  */
+#define DF_1_GROUP     0x00000004      /* Set RTLD_GROUP for this object.  */
+#define DF_1_NODELETE  0x00000008      /* Set RTLD_NODELETE for this object.*/
+#define DF_1_LOADFLTR  0x00000010      /* Trigger filtee loading at runtime.*/
+#define DF_1_INITFIRST 0x00000020      /* Set RTLD_INITFIRST for this object*/
+#define DF_1_NOOPEN    0x00000040      /* Set RTLD_NOOPEN for this object.  */
+#define DF_1_ORIGIN    0x00000080      /* $ORIGIN must be handled.  */
+#define DF_1_DIRECT    0x00000100      /* Direct binding enabled.  */
+#define DF_1_TRANS     0x00000200
+#define DF_1_INTERPOSE 0x00000400      /* Object is used to interpose.  */
+#define DF_1_NODEFLIB  0x00000800      /* Ignore default lib search path.  */
+#define DF_1_NODUMP    0x00001000      /* Object can't be dldump'ed.  */
+#define DF_1_CONFALT   0x00002000      /* Configuration alternative created.*/
+#define DF_1_ENDFILTEE 0x00004000      /* Filtee terminates filters search. */
+#define        DF_1_DISPRELDNE 0x00008000      /* Disp reloc applied at build time. */
+#define        DF_1_DISPRELPND 0x00010000      /* Disp reloc applied at run-time.  */
+
+/* Flags for the feature selection in DT_FEATURE_1.  */
+#define DTF_1_PARINIT  0x00000001
+#define DTF_1_CONFEXP  0x00000002
+
+/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry.  */
+#define DF_P1_LAZYLOAD 0x00000001      /* Lazyload following object.  */
+#define DF_P1_GROUPPERM        0x00000002      /* Symbols from next object are not
+                                          generally available.  */
+
+/* Version definition sections.  */
+
+typedef struct
+{
+  Elf32_Half   vd_version;             /* Version revision */
+  Elf32_Half   vd_flags;               /* Version information */
+  Elf32_Half   vd_ndx;                 /* Version Index */
+  Elf32_Half   vd_cnt;                 /* Number of associated aux entries */
+  Elf32_Word   vd_hash;                /* Version name hash value */
+  Elf32_Word   vd_aux;                 /* Offset in bytes to verdaux array */
+  Elf32_Word   vd_next;                /* Offset in bytes to next verdef
+                                          entry */
+} Elf32_Verdef;
+
+typedef struct
+{
+  Elf64_Half   vd_version;             /* Version revision */
+  Elf64_Half   vd_flags;               /* Version information */
+  Elf64_Half   vd_ndx;                 /* Version Index */
+  Elf64_Half   vd_cnt;                 /* Number of associated aux entries */
+  Elf64_Word   vd_hash;                /* Version name hash value */
+  Elf64_Word   vd_aux;                 /* Offset in bytes to verdaux array */
+  Elf64_Word   vd_next;                /* Offset in bytes to next verdef
+                                          entry */
+} Elf64_Verdef;
+
+
+/* Legal values for vd_version (version revision).  */
+#define VER_DEF_NONE   0               /* No version */
+#define VER_DEF_CURRENT        1               /* Current version */
+#define VER_DEF_NUM    2               /* Given version number */
+
+/* Legal values for vd_flags (version information flags).  */
+#define VER_FLG_BASE   0x1             /* Version definition of file itself */
+#define VER_FLG_WEAK   0x2             /* Weak version identifier */
+
+/* Versym symbol index values.  */
+#define        VER_NDX_LOCAL           0       /* Symbol is local.  */
+#define        VER_NDX_GLOBAL          1       /* Symbol is global.  */
+#define        VER_NDX_LORESERVE       0xff00  /* Beginning of reserved entries.  */
+#define        VER_NDX_ELIMINATE       0xff01  /* Symbol is to be eliminated.  */
+
+/* Auxiliary version information.  */
+
+typedef struct
+{
+  Elf32_Word   vda_name;               /* Version or dependency names */
+  Elf32_Word   vda_next;               /* Offset in bytes to next verdaux
+                                          entry */
+} Elf32_Verdaux;
+
+typedef struct
+{
+  Elf64_Word   vda_name;               /* Version or dependency names */
+  Elf64_Word   vda_next;               /* Offset in bytes to next verdaux
+                                          entry */
+} Elf64_Verdaux;
+
+
+/* Version dependency section.  */
+
+typedef struct
+{
+  Elf32_Half   vn_version;             /* Version of structure */
+  Elf32_Half   vn_cnt;                 /* Number of associated aux entries */
+  Elf32_Word   vn_file;                /* Offset of filename for this
+                                          dependency */
+  Elf32_Word   vn_aux;                 /* Offset in bytes to vernaux array */
+  Elf32_Word   vn_next;                /* Offset in bytes to next verneed
+                                          entry */
+} Elf32_Verneed;
+
+typedef struct
+{
+  Elf64_Half   vn_version;             /* Version of structure */
+  Elf64_Half   vn_cnt;                 /* Number of associated aux entries */
+  Elf64_Word   vn_file;                /* Offset of filename for this
+                                          dependency */
+  Elf64_Word   vn_aux;                 /* Offset in bytes to vernaux array */
+  Elf64_Word   vn_next;                /* Offset in bytes to next verneed
+                                          entry */
+} Elf64_Verneed;
+
+
+/* Legal values for vn_version (version revision).  */
+#define VER_NEED_NONE   0              /* No version */
+#define VER_NEED_CURRENT 1             /* Current version */
+#define VER_NEED_NUM    2              /* Given version number */
+
+/* Auxiliary needed version information.  */
+
+typedef struct
+{
+  Elf32_Word   vna_hash;               /* Hash value of dependency name */
+  Elf32_Half   vna_flags;              /* Dependency specific information */
+  Elf32_Half   vna_other;              /* Unused */
+  Elf32_Word   vna_name;               /* Dependency name string offset */
+  Elf32_Word   vna_next;               /* Offset in bytes to next vernaux
+                                          entry */
+} Elf32_Vernaux;
+
+typedef struct
+{
+  Elf64_Word   vna_hash;               /* Hash value of dependency name */
+  Elf64_Half   vna_flags;              /* Dependency specific information */
+  Elf64_Half   vna_other;              /* Unused */
+  Elf64_Word   vna_name;               /* Dependency name string offset */
+  Elf64_Word   vna_next;               /* Offset in bytes to next vernaux
+                                          entry */
+} Elf64_Vernaux;
+
+
+/* Legal values for vna_flags.  */
+#define VER_FLG_WEAK   0x2             /* Weak version identifier */
+
+
+/* Auxiliary vector.  */
+
+/* This vector is normally only used by the program interpreter.  The
+   usual definition in an ABI supplement uses the name auxv_t.  The
+   vector is not usually defined in a standard <elf.h> file, but it
+   can't hurt.  We rename it to avoid conflicts.  The sizes of these
+   types are an arrangement between the exec server and the program
+   interpreter, so we don't fully specify them here.  */
+
+typedef struct
+{
+  int a_type;                  /* Entry type */
+  union
+    {
+      long int a_val;          /* Integer value */
+      void *a_ptr;             /* Pointer value */
+      void (*a_fcn) (void);    /* Function pointer value */
+    } a_un;
+} Elf32_auxv_t;
+
+typedef struct
+{
+  long int a_type;             /* Entry type */
+  union
+    {
+      long int a_val;          /* Integer value */
+      void *a_ptr;             /* Pointer value */
+      void (*a_fcn) (void);    /* Function pointer value */
+    } a_un;
+} Elf64_auxv_t;
+
+/* Legal values for a_type (entry type).  */
+
+#define AT_NULL                0               /* End of vector */
+#define AT_IGNORE      1               /* Entry should be ignored */
+#define AT_EXECFD      2               /* File descriptor of program */
+#define AT_PHDR                3               /* Program headers for program */
+#define AT_PHENT       4               /* Size of program header entry */
+#define AT_PHNUM       5               /* Number of program headers */
+#define AT_PAGESZ      6               /* System page size */
+#define AT_BASE                7               /* Base address of interpreter */
+#define AT_FLAGS       8               /* Flags */
+#define AT_ENTRY       9               /* Entry point of program */
+#define AT_NOTELF      10              /* Program is not ELF */
+#define AT_UID         11              /* Real uid */
+#define AT_EUID                12              /* Effective uid */
+#define AT_GID         13              /* Real gid */
+#define AT_EGID                14              /* Effective gid */
+#define AT_CLKTCK      17              /* Frequency of times() */
+
+/* Some more special a_type values describing the hardware.  */
+#define AT_PLATFORM    15              /* String identifying platform.  */
+#define AT_HWCAP       16              /* Machine dependent hints about
+                                          processor capabilities.  */
+
+/* This entry gives some information about the FPU initialization
+   performed by the kernel.  */
+#define AT_FPUCW       18              /* Used FPU control word.  */
+
+/* Cache block sizes.  */
+#define AT_DCACHEBSIZE 19              /* Data cache block size.  */
+#define AT_ICACHEBSIZE 20              /* Instruction cache block size.  */
+#define AT_UCACHEBSIZE 21              /* Unified cache block size.  */
+
+/* A special ignored value for PPC, used by the kernel to control the
+   interpretation of the AUXV. Must be > 16.  */
+#define AT_IGNOREPPC   22              /* Entry should be ignored */
+
+
+/* Note section contents.  Each entry in the note section begins with
+   a header of a fixed form.  */
+
+typedef struct
+{
+  Elf32_Word n_namesz;                 /* Length of the note's name.  */
+  Elf32_Word n_descsz;                 /* Length of the note's descriptor.  */
+  Elf32_Word n_type;                   /* Type of the note.  */
+} Elf32_Nhdr;
+
+typedef struct
+{
+  Elf64_Word n_namesz;                 /* Length of the note's name.  */
+  Elf64_Word n_descsz;                 /* Length of the note's descriptor.  */
+  Elf64_Word n_type;                   /* Type of the note.  */
+} Elf64_Nhdr;
+
+/* Known names of notes.  */
+
+/* Solaris entries in the note section have this name.  */
+#define ELF_NOTE_SOLARIS       "SUNW Solaris"
+
+/* Note entries for GNU systems have this name.  */
+#define ELF_NOTE_GNU           "GNU"
+
+
+/* Defined types of notes for Solaris.  */
+
+/* Value of descriptor (one word) is desired pagesize for the binary.  */
+#define ELF_NOTE_PAGESIZE_HINT 1
+
+
+/* Defined note types for GNU systems.  */
+
+/* ABI information.  The descriptor consists of words:
+   word 0: OS descriptor
+   word 1: major version of the ABI
+   word 2: minor version of the ABI
+   word 3: subminor version of the ABI
+*/
+#define ELF_NOTE_ABI           1
+
+/* Known OSes.  These value can appear in word 0 of an ELF_NOTE_ABI
+   note section entry.  */
+#define ELF_NOTE_OS_LINUX      0
+#define ELF_NOTE_OS_GNU                1
+#define ELF_NOTE_OS_SOLARIS2   2
+
+
+/* Move records.  */
+typedef struct
+{
+  Elf32_Xword m_value;         /* Symbol value.  */
+  Elf32_Word m_info;           /* Size and index.  */
+  Elf32_Word m_poffset;                /* Symbol offset.  */
+  Elf32_Half m_repeat;         /* Repeat count.  */
+  Elf32_Half m_stride;         /* Stride info.  */
+} Elf32_Move;
+
+typedef struct
+{
+  Elf64_Xword m_value;         /* Symbol value.  */
+  Elf64_Xword m_info;          /* Size and index.  */
+  Elf64_Xword m_poffset;       /* Symbol offset.  */
+  Elf64_Half m_repeat;         /* Repeat count.  */
+  Elf64_Half m_stride;         /* Stride info.  */
+} Elf64_Move;
+
+/* Macro to construct move records.  */
+#define ELF32_M_SYM(info)      ((info) >> 8)
+#define ELF32_M_SIZE(info)     ((unsigned char) (info))
+#define ELF32_M_INFO(sym, size)        (((sym) << 8) + (unsigned char) (size))
+
+#define ELF64_M_SYM(info)      ELF32_M_SYM (info)
+#define ELF64_M_SIZE(info)     ELF32_M_SIZE (info)
+#define ELF64_M_INFO(sym, size)        ELF32_M_INFO (sym, size)
+
+
+/* Motorola 68k specific definitions.  */
+
+/* Values for Elf32_Ehdr.e_flags.  */
+#define EF_CPU32       0x00810000
+
+/* m68k relocs.  */
+
+#define R_68K_NONE     0               /* No reloc */
+#define R_68K_32       1               /* Direct 32 bit  */
+#define R_68K_16       2               /* Direct 16 bit  */
+#define R_68K_8                3               /* Direct 8 bit  */
+#define R_68K_PC32     4               /* PC relative 32 bit */
+#define R_68K_PC16     5               /* PC relative 16 bit */
+#define R_68K_PC8      6               /* PC relative 8 bit */
+#define R_68K_GOT32    7               /* 32 bit PC relative GOT entry */
+#define R_68K_GOT16    8               /* 16 bit PC relative GOT entry */
+#define R_68K_GOT8     9               /* 8 bit PC relative GOT entry */
+#define R_68K_GOT32O   10              /* 32 bit GOT offset */
+#define R_68K_GOT16O   11              /* 16 bit GOT offset */
+#define R_68K_GOT8O    12              /* 8 bit GOT offset */
+#define R_68K_PLT32    13              /* 32 bit PC relative PLT address */
+#define R_68K_PLT16    14              /* 16 bit PC relative PLT address */
+#define R_68K_PLT8     15              /* 8 bit PC relative PLT address */
+#define R_68K_PLT32O   16              /* 32 bit PLT offset */
+#define R_68K_PLT16O   17              /* 16 bit PLT offset */
+#define R_68K_PLT8O    18              /* 8 bit PLT offset */
+#define R_68K_COPY     19              /* Copy symbol at runtime */
+#define R_68K_GLOB_DAT 20              /* Create GOT entry */
+#define R_68K_JMP_SLOT 21              /* Create PLT entry */
+#define R_68K_RELATIVE 22              /* Adjust by program base */
+/* Keep this the last entry.  */
+#define R_68K_NUM      23
+
+/* Intel 80386 specific definitions.  */
+
+/* i386 relocs.  */
+
+#define R_386_NONE        0            /* No reloc */
+#define R_386_32          1            /* Direct 32 bit  */
+#define R_386_PC32        2            /* PC relative 32 bit */
+#define R_386_GOT32       3            /* 32 bit GOT entry */
+#define R_386_PLT32       4            /* 32 bit PLT address */
+#define R_386_COPY        5            /* Copy symbol at runtime */
+#define R_386_GLOB_DAT    6            /* Create GOT entry */
+#define R_386_JMP_SLOT    7            /* Create PLT entry */
+#define R_386_RELATIVE    8            /* Adjust by program base */
+#define R_386_GOTOFF      9            /* 32 bit offset to GOT */
+#define R_386_GOTPC       10           /* 32 bit PC relative offset to GOT */
+#define R_386_32PLT       11
+#define R_386_TLS_TPOFF           14           /* Offset in static TLS block */
+#define R_386_TLS_IE      15           /* Address of GOT entry for static TLS
+                                          block offset */
+#define R_386_TLS_GOTIE           16           /* GOT entry for static TLS block
+                                          offset */
+#define R_386_TLS_LE      17           /* Offset relative to static TLS
+                                          block */
+#define R_386_TLS_GD      18           /* Direct 32 bit for GNU version of
+                                          general dynamic thread local data */
+#define R_386_TLS_LDM     19           /* Direct 32 bit for GNU version of
+                                          local dynamic thread local data
+                                          in LE code */
+#define R_386_16          20
+#define R_386_PC16        21
+#define R_386_8                   22
+#define R_386_PC8         23
+#define R_386_TLS_GD_32           24           /* Direct 32 bit for general dynamic
+                                          thread local data */
+#define R_386_TLS_GD_PUSH  25          /* Tag for pushl in GD TLS code */
+#define R_386_TLS_GD_CALL  26          /* Relocation for call to
+                                          __tls_get_addr() */
+#define R_386_TLS_GD_POP   27          /* Tag for popl in GD TLS code */
+#define R_386_TLS_LDM_32   28          /* Direct 32 bit for local dynamic
+                                          thread local data in LE code */
+#define R_386_TLS_LDM_PUSH 29          /* Tag for pushl in LDM TLS code */
+#define R_386_TLS_LDM_CALL 30          /* Relocation for call to
+                                          __tls_get_addr() in LDM code */
+#define R_386_TLS_LDM_POP  31          /* Tag for popl in LDM TLS code */
+#define R_386_TLS_LDO_32   32          /* Offset relative to TLS block */
+#define R_386_TLS_IE_32           33           /* GOT entry for negated static TLS
+                                          block offset */
+#define R_386_TLS_LE_32           34           /* Negated offset relative to static
+                                          TLS block */
+#define R_386_TLS_DTPMOD32 35          /* ID of module containing symbol */
+#define R_386_TLS_DTPOFF32 36          /* Offset in TLS block */
+#define R_386_TLS_TPOFF32  37          /* Negated offset in static TLS block */
+/* Keep this the last entry.  */
+#define R_386_NUM         38
+
+
+/* SUN SPARC specific definitions.  */
+
+/* x86_64 specific definitions.  */
+#define R_X86_64_NONE          0
+#define R_X86_64_64            1
+#define R_X86_64_PC32          2
+#define R_X86_64_GOT32         3
+#define R_X86_64_PLT32         4
+#define R_X86_64_COPY          5
+#define R_X86_64_GLOB_DAT      6
+#define R_X86_64_JUMP_SLOT     7
+#define R_X86_64_RELATIVE      8
+#define R_X86_64_GOTPCREL      9
+#define R_X86_64_32            10
+#define R_X86_64_32S           11
+#define R_X86_64_16            12
+#define R_X86_64_PC16          13
+#define R_X86_64_8             14
+#define R_X86_64_PC8           15
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_REGISTER   13              /* Global register reserved to app. */
+
+/* Values for Elf64_Ehdr.e_flags.  */
+
+#define EF_SPARCV9_MM          3
+#define EF_SPARCV9_TSO         0
+#define EF_SPARCV9_PSO         1
+#define EF_SPARCV9_RMO         2
+#define EF_SPARC_LEDATA                0x800000 /* little endian data */
+#define EF_SPARC_EXT_MASK      0xFFFF00
+#define EF_SPARC_32PLUS                0x000100 /* generic V8+ features */
+#define EF_SPARC_SUN_US1       0x000200 /* Sun UltraSPARC1 extensions */
+#define EF_SPARC_HAL_R1                0x000400 /* HAL R1 extensions */
+#define EF_SPARC_SUN_US3       0x000800 /* Sun UltraSPARCIII extensions */
+
+/* SPARC relocs.  */
+
+#define R_SPARC_NONE           0       /* No reloc */
+#define R_SPARC_8              1       /* Direct 8 bit */
+#define R_SPARC_16             2       /* Direct 16 bit */
+#define R_SPARC_32             3       /* Direct 32 bit */
+#define R_SPARC_DISP8          4       /* PC relative 8 bit */
+#define R_SPARC_DISP16         5       /* PC relative 16 bit */
+#define R_SPARC_DISP32         6       /* PC relative 32 bit */
+#define R_SPARC_WDISP30                7       /* PC relative 30 bit shifted */
+#define R_SPARC_WDISP22                8       /* PC relative 22 bit shifted */
+#define R_SPARC_HI22           9       /* High 22 bit */
+#define R_SPARC_22             10      /* Direct 22 bit */
+#define R_SPARC_13             11      /* Direct 13 bit */
+#define R_SPARC_LO10           12      /* Truncated 10 bit */
+#define R_SPARC_GOT10          13      /* Truncated 10 bit GOT entry */
+#define R_SPARC_GOT13          14      /* 13 bit GOT entry */
+#define R_SPARC_GOT22          15      /* 22 bit GOT entry shifted */
+#define R_SPARC_PC10           16      /* PC relative 10 bit truncated */
+#define R_SPARC_PC22           17      /* PC relative 22 bit shifted */
+#define R_SPARC_WPLT30         18      /* 30 bit PC relative PLT address */
+#define R_SPARC_COPY           19      /* Copy symbol at runtime */
+#define R_SPARC_GLOB_DAT       20      /* Create GOT entry */
+#define R_SPARC_JMP_SLOT       21      /* Create PLT entry */
+#define R_SPARC_RELATIVE       22      /* Adjust by program base */
+#define R_SPARC_UA32           23      /* Direct 32 bit unaligned */
+
+/* Additional Sparc64 relocs.  */
+
+#define R_SPARC_PLT32          24      /* Direct 32 bit ref to PLT entry */
+#define R_SPARC_HIPLT22                25      /* High 22 bit PLT entry */
+#define R_SPARC_LOPLT10                26      /* Truncated 10 bit PLT entry */
+#define R_SPARC_PCPLT32                27      /* PC rel 32 bit ref to PLT entry */
+#define R_SPARC_PCPLT22                28      /* PC rel high 22 bit PLT entry */
+#define R_SPARC_PCPLT10                29      /* PC rel trunc 10 bit PLT entry */
+#define R_SPARC_10             30      /* Direct 10 bit */
+#define R_SPARC_11             31      /* Direct 11 bit */
+#define R_SPARC_64             32      /* Direct 64 bit */
+#define R_SPARC_OLO10          33      /* 10bit with secondary 13bit addend */
+#define R_SPARC_HH22           34      /* Top 22 bits of direct 64 bit */
+#define R_SPARC_HM10           35      /* High middle 10 bits of ... */
+#define R_SPARC_LM22           36      /* Low middle 22 bits of ... */
+#define R_SPARC_PC_HH22                37      /* Top 22 bits of pc rel 64 bit */
+#define R_SPARC_PC_HM10                38      /* High middle 10 bit of ... */
+#define R_SPARC_PC_LM22                39      /* Low miggle 22 bits of ... */
+#define R_SPARC_WDISP16                40      /* PC relative 16 bit shifted */
+#define R_SPARC_WDISP19                41      /* PC relative 19 bit shifted */
+#define R_SPARC_7              43      /* Direct 7 bit */
+#define R_SPARC_5              44      /* Direct 5 bit */
+#define R_SPARC_6              45      /* Direct 6 bit */
+#define R_SPARC_DISP64         46      /* PC relative 64 bit */
+#define R_SPARC_PLT64          47      /* Direct 64 bit ref to PLT entry */
+#define R_SPARC_HIX22          48      /* High 22 bit complemented */
+#define R_SPARC_LOX10          49      /* Truncated 11 bit complemented */
+#define R_SPARC_H44            50      /* Direct high 12 of 44 bit */
+#define R_SPARC_M44            51      /* Direct mid 22 of 44 bit */
+#define R_SPARC_L44            52      /* Direct low 10 of 44 bit */
+#define R_SPARC_REGISTER       53      /* Global register usage */
+#define R_SPARC_UA64           54      /* Direct 64 bit unaligned */
+#define R_SPARC_UA16           55      /* Direct 16 bit unaligned */
+#define R_SPARC_TLS_GD_HI22    56
+#define R_SPARC_TLS_GD_LO10    57
+#define R_SPARC_TLS_GD_ADD     58
+#define R_SPARC_TLS_GD_CALL    59
+#define R_SPARC_TLS_LDM_HI22   60
+#define R_SPARC_TLS_LDM_LO10   61
+#define R_SPARC_TLS_LDM_ADD    62
+#define R_SPARC_TLS_LDM_CALL   63
+#define R_SPARC_TLS_LDO_HIX22  64
+#define R_SPARC_TLS_LDO_LOX10  65
+#define R_SPARC_TLS_LDO_ADD    66
+#define R_SPARC_TLS_IE_HI22    67
+#define R_SPARC_TLS_IE_LO10    68
+#define R_SPARC_TLS_IE_LD      69
+#define R_SPARC_TLS_IE_LDX     70
+#define R_SPARC_TLS_IE_ADD     71
+#define R_SPARC_TLS_LE_HIX22   72
+#define R_SPARC_TLS_LE_LOX10   73
+#define R_SPARC_TLS_DTPMOD32   74
+#define R_SPARC_TLS_DTPMOD64   75
+#define R_SPARC_TLS_DTPOFF32   76
+#define R_SPARC_TLS_DTPOFF64   77
+#define R_SPARC_TLS_TPOFF32    78
+#define R_SPARC_TLS_TPOFF64    79
+/* Keep this the last entry.  */
+#define R_SPARC_NUM            80
+
+/* For Sparc64, legal values for d_tag of Elf64_Dyn.  */
+
+#define DT_SPARC_REGISTER 0x70000001
+#define DT_SPARC_NUM   2
+
+/* Bits present in AT_HWCAP, primarily for Sparc32.  */
+
+#define HWCAP_SPARC_FLUSH      1       /* The cpu supports flush insn.  */
+#define HWCAP_SPARC_STBAR      2
+#define HWCAP_SPARC_SWAP       4
+#define HWCAP_SPARC_MULDIV     8
+#define HWCAP_SPARC_V9         16      /* The cpu is v9, so v8plus is ok.  */
+#define HWCAP_SPARC_ULTRA3     32
+
+/* MIPS R3000 specific definitions.  */
+
+/* Legal values for e_flags field of Elf32_Ehdr.  */
+
+#define EF_MIPS_NOREORDER   1          /* A .noreorder directive was used */
+#define EF_MIPS_PIC        2           /* Contains PIC code */
+#define EF_MIPS_CPIC       4           /* Uses PIC calling sequence */
+#define EF_MIPS_XGOT       8
+#define EF_MIPS_64BIT_WHIRL 16
+#define EF_MIPS_ABI2       32
+#define EF_MIPS_ABI_ON32    64
+#define EF_MIPS_ARCH       0xf0000000  /* MIPS architecture level */
+
+/* Legal values for MIPS architecture level.  */
+
+#define EF_MIPS_ARCH_1     0x00000000  /* -mips1 code.  */
+#define EF_MIPS_ARCH_2     0x10000000  /* -mips2 code.  */
+#define EF_MIPS_ARCH_3     0x20000000  /* -mips3 code.  */
+#define EF_MIPS_ARCH_4     0x30000000  /* -mips4 code.  */
+#define EF_MIPS_ARCH_5     0x40000000  /* -mips5 code.  */
+#define EF_MIPS_ARCH_32            0x60000000  /* MIPS32 code.  */
+#define EF_MIPS_ARCH_64            0x70000000  /* MIPS64 code.  */
+
+/* The following are non-official names and should not be used.  */
+
+#define E_MIPS_ARCH_1    0x00000000    /* -mips1 code.  */
+#define E_MIPS_ARCH_2    0x10000000    /* -mips2 code.  */
+#define E_MIPS_ARCH_3    0x20000000    /* -mips3 code.  */
+#define E_MIPS_ARCH_4    0x30000000    /* -mips4 code.  */
+#define E_MIPS_ARCH_5    0x40000000    /* -mips5 code.  */
+#define E_MIPS_ARCH_32   0x60000000    /* MIPS32 code.  */
+#define E_MIPS_ARCH_64   0x70000000    /* MIPS64 code.  */
+
+/* Special section indices.  */
+
+#define SHN_MIPS_ACOMMON    0xff00     /* Allocated common symbols */
+#define SHN_MIPS_TEXT      0xff01      /* Allocated test symbols.  */
+#define SHN_MIPS_DATA      0xff02      /* Allocated data symbols.  */
+#define SHN_MIPS_SCOMMON    0xff03     /* Small common symbols */
+#define SHN_MIPS_SUNDEFINED 0xff04     /* Small undefined symbols */
+
+/* Legal values for sh_type field of Elf32_Shdr.  */
+
+#define SHT_MIPS_LIBLIST       0x70000000 /* Shared objects used in link */
+#define SHT_MIPS_MSYM         0x70000001
+#define SHT_MIPS_CONFLICT      0x70000002 /* Conflicting symbols */
+#define SHT_MIPS_GPTAB        0x70000003 /* Global data area sizes */
+#define SHT_MIPS_UCODE        0x70000004 /* Reserved for SGI/MIPS compilers */
+#define SHT_MIPS_DEBUG        0x70000005 /* MIPS ECOFF debugging information*/
+#define SHT_MIPS_REGINFO       0x70000006 /* Register usage information */
+#define SHT_MIPS_PACKAGE       0x70000007
+#define SHT_MIPS_PACKSYM       0x70000008
+#define SHT_MIPS_RELD         0x70000009
+#define SHT_MIPS_IFACE         0x7000000b
+#define SHT_MIPS_CONTENT       0x7000000c
+#define SHT_MIPS_OPTIONS       0x7000000d /* Miscellaneous options.  */
+#define SHT_MIPS_SHDR         0x70000010
+#define SHT_MIPS_FDESC        0x70000011
+#define SHT_MIPS_EXTSYM               0x70000012
+#define SHT_MIPS_DENSE        0x70000013
+#define SHT_MIPS_PDESC        0x70000014
+#define SHT_MIPS_LOCSYM               0x70000015
+#define SHT_MIPS_AUXSYM               0x70000016
+#define SHT_MIPS_OPTSYM               0x70000017
+#define SHT_MIPS_LOCSTR               0x70000018
+#define SHT_MIPS_LINE         0x70000019
+#define SHT_MIPS_RFDESC               0x7000001a
+#define SHT_MIPS_DELTASYM      0x7000001b
+#define SHT_MIPS_DELTAINST     0x7000001c
+#define SHT_MIPS_DELTACLASS    0x7000001d
+#define SHT_MIPS_DWARF         0x7000001e /* DWARF debugging information.  */
+#define SHT_MIPS_DELTADECL     0x7000001f
+#define SHT_MIPS_SYMBOL_LIB    0x70000020
+#define SHT_MIPS_EVENTS               0x70000021 /* Event section.  */
+#define SHT_MIPS_TRANSLATE     0x70000022
+#define SHT_MIPS_PIXIE        0x70000023
+#define SHT_MIPS_XLATE        0x70000024
+#define SHT_MIPS_XLATE_DEBUG   0x70000025
+#define SHT_MIPS_WHIRL        0x70000026
+#define SHT_MIPS_EH_REGION     0x70000027
+#define SHT_MIPS_XLATE_OLD     0x70000028
+#define SHT_MIPS_PDR_EXCEPTION 0x70000029
+
+/* Legal values for sh_flags field of Elf32_Shdr.  */
+
+#define SHF_MIPS_GPREL  0x10000000     /* Must be part of global data area */
+#define SHF_MIPS_MERGE  0x20000000
+#define SHF_MIPS_ADDR   0x40000000
+#define SHF_MIPS_STRINGS 0x80000000
+#define SHF_MIPS_NOSTRIP 0x08000000
+#define SHF_MIPS_LOCAL  0x04000000
+#define SHF_MIPS_NAMES  0x02000000
+#define SHF_MIPS_NODUPE         0x01000000
+
+
+/* Symbol tables.  */
+
+/* MIPS specific values for `st_other'.  */
+#define STO_MIPS_DEFAULT               0x0
+#define STO_MIPS_INTERNAL              0x1
+#define STO_MIPS_HIDDEN                        0x2
+#define STO_MIPS_PROTECTED             0x3
+#define STO_MIPS_SC_ALIGN_UNUSED       0xff
+
+/* MIPS specific values for `st_info'.  */
+#define STB_MIPS_SPLIT_COMMON          13
+
+/* Entries found in sections of type SHT_MIPS_GPTAB.  */
+
+typedef union
+{
+  struct
+    {
+      Elf32_Word gt_current_g_value;   /* -G value used for compilation */
+      Elf32_Word gt_unused;            /* Not used */
+    } gt_header;                       /* First entry in section */
+  struct
+    {
+      Elf32_Word gt_g_value;           /* If this value were used for -G */
+      Elf32_Word gt_bytes;             /* This many bytes would be used */
+    } gt_entry;                                /* Subsequent entries in section */
+} Elf32_gptab;
+
+/* Entry found in sections of type SHT_MIPS_REGINFO.  */
+
+typedef struct
+{
+  Elf32_Word   ri_gprmask;             /* General registers used */
+  Elf32_Word   ri_cprmask[4];          /* Coprocessor registers used */
+  Elf32_Sword  ri_gp_value;            /* $gp register value */
+} Elf32_RegInfo;
+
+/* Entries found in sections of type SHT_MIPS_OPTIONS.  */
+
+typedef struct
+{
+  unsigned char kind;          /* Determines interpretation of the
+                                  variable part of descriptor.  */
+  unsigned char size;          /* Size of descriptor, including header.  */
+  Elf32_Section section;       /* Section header index of section affected,
+                                  0 for global options.  */
+  Elf32_Word info;             /* Kind-specific information.  */
+} Elf_Options;
+
+/* Values for `kind' field in Elf_Options.  */
+
+#define ODK_NULL       0       /* Undefined.  */
+#define ODK_REGINFO    1       /* Register usage information.  */
+#define ODK_EXCEPTIONS 2       /* Exception processing options.  */
+#define ODK_PAD                3       /* Section padding options.  */
+#define ODK_HWPATCH    4       /* Hardware workarounds performed */
+#define ODK_FILL       5       /* record the fill value used by the linker. */
+#define ODK_TAGS       6       /* reserve space for desktop tools to write. */
+#define ODK_HWAND      7       /* HW workarounds.  'AND' bits when merging. */
+#define ODK_HWOR       8       /* HW workarounds.  'OR' bits when merging.  */
+
+/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries.  */
+
+#define OEX_FPU_MIN    0x1f    /* FPE's which MUST be enabled.  */
+#define OEX_FPU_MAX    0x1f00  /* FPE's which MAY be enabled.  */
+#define OEX_PAGE0      0x10000 /* page zero must be mapped.  */
+#define OEX_SMM                0x20000 /* Force sequential memory mode?  */
+#define OEX_FPDBUG     0x40000 /* Force floating point debug mode?  */
+#define OEX_PRECISEFP  OEX_FPDBUG
+#define OEX_DISMISS    0x80000 /* Dismiss invalid address faults?  */
+
+#define OEX_FPU_INVAL  0x10
+#define OEX_FPU_DIV0   0x08
+#define OEX_FPU_OFLO   0x04
+#define OEX_FPU_UFLO   0x02
+#define OEX_FPU_INEX   0x01
+
+/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry.  */
+
+#define OHW_R4KEOP     0x1     /* R4000 end-of-page patch.  */
+#define OHW_R8KPFETCH  0x2     /* may need R8000 prefetch patch.  */
+#define OHW_R5KEOP     0x4     /* R5000 end-of-page patch.  */
+#define OHW_R5KCVTL    0x8     /* R5000 cvt.[ds].l bug.  clean=1.  */
+
+#define OPAD_PREFIX    0x1
+#define OPAD_POSTFIX   0x2
+#define OPAD_SYMBOL    0x4
+
+/* Entry found in `.options' section.  */
+
+typedef struct
+{
+  Elf32_Word hwp_flags1;       /* Extra flags.  */
+  Elf32_Word hwp_flags2;       /* Extra flags.  */
+} Elf_Options_Hw;
+
+/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries.  */
+
+#define OHWA0_R4KEOP_CHECKED   0x00000001
+#define OHWA1_R4KEOP_CLEAN     0x00000002
+
+/* MIPS relocs.  */
+
+#define R_MIPS_NONE            0       /* No reloc */
+#define R_MIPS_16              1       /* Direct 16 bit */
+#define R_MIPS_32              2       /* Direct 32 bit */
+#define R_MIPS_REL32           3       /* PC relative 32 bit */
+#define R_MIPS_26              4       /* Direct 26 bit shifted */
+#define R_MIPS_HI16            5       /* High 16 bit */
+#define R_MIPS_LO16            6       /* Low 16 bit */
+#define R_MIPS_GPREL16         7       /* GP relative 16 bit */
+#define R_MIPS_LITERAL         8       /* 16 bit literal entry */
+#define R_MIPS_GOT16           9       /* 16 bit GOT entry */
+#define R_MIPS_PC16            10      /* PC relative 16 bit */
+#define R_MIPS_CALL16          11      /* 16 bit GOT entry for function */
+#define R_MIPS_GPREL32         12      /* GP relative 32 bit */
+
+#define R_MIPS_SHIFT5          16
+#define R_MIPS_SHIFT6          17
+#define R_MIPS_64              18
+#define R_MIPS_GOT_DISP                19
+#define R_MIPS_GOT_PAGE                20
+#define R_MIPS_GOT_OFST                21
+#define R_MIPS_GOT_HI16                22
+#define R_MIPS_GOT_LO16                23
+#define R_MIPS_SUB             24
+#define R_MIPS_INSERT_A                25
+#define R_MIPS_INSERT_B                26
+#define R_MIPS_DELETE          27
+#define R_MIPS_HIGHER          28
+#define R_MIPS_HIGHEST         29
+#define R_MIPS_CALL_HI16       30
+#define R_MIPS_CALL_LO16       31
+#define R_MIPS_SCN_DISP                32
+#define R_MIPS_REL16           33
+#define R_MIPS_ADD_IMMEDIATE   34
+#define R_MIPS_PJUMP           35
+#define R_MIPS_RELGOT          36
+#define R_MIPS_JALR            37
+/* Keep this the last entry.  */
+#define R_MIPS_NUM             38
+
+/* Legal values for p_type field of Elf32_Phdr.  */
+
+#define PT_MIPS_REGINFO        0x70000000      /* Register usage information */
+#define PT_MIPS_RTPROC  0x70000001     /* Runtime procedure table. */
+#define PT_MIPS_OPTIONS 0x70000002
+
+/* Special program header types.  */
+
+#define PF_MIPS_LOCAL  0x10000000
+
+/* Legal values for d_tag field of Elf32_Dyn.  */
+
+#define DT_MIPS_RLD_VERSION  0x70000001        /* Runtime linker interface version */
+#define DT_MIPS_TIME_STAMP   0x70000002        /* Timestamp */
+#define DT_MIPS_ICHECKSUM    0x70000003        /* Checksum */
+#define DT_MIPS_IVERSION     0x70000004        /* Version string (string tbl index) */
+#define DT_MIPS_FLAGS       0x70000005 /* Flags */
+#define DT_MIPS_BASE_ADDRESS 0x70000006        /* Base address */
+#define DT_MIPS_MSYM        0x70000007
+#define DT_MIPS_CONFLICT     0x70000008        /* Address of CONFLICT section */
+#define DT_MIPS_LIBLIST             0x70000009 /* Address of LIBLIST section */
+#define DT_MIPS_LOCAL_GOTNO  0x7000000a        /* Number of local GOT entries */
+#define DT_MIPS_CONFLICTNO   0x7000000b        /* Number of CONFLICT entries */
+#define DT_MIPS_LIBLISTNO    0x70000010        /* Number of LIBLIST entries */
+#define DT_MIPS_SYMTABNO     0x70000011        /* Number of DYNSYM entries */
+#define DT_MIPS_UNREFEXTNO   0x70000012        /* First external DYNSYM */
+#define DT_MIPS_GOTSYM      0x70000013 /* First GOT entry in DYNSYM */
+#define DT_MIPS_HIPAGENO     0x70000014        /* Number of GOT page table entries */
+#define DT_MIPS_RLD_MAP             0x70000016 /* Address of run time loader map.  */
+#define DT_MIPS_DELTA_CLASS  0x70000017        /* Delta C++ class definition.  */
+#define DT_MIPS_DELTA_CLASS_NO    0x70000018 /* Number of entries in
+                                               DT_MIPS_DELTA_CLASS.  */
+#define DT_MIPS_DELTA_INSTANCE    0x70000019 /* Delta C++ class instances.  */
+#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in
+                                               DT_MIPS_DELTA_INSTANCE.  */
+#define DT_MIPS_DELTA_RELOC  0x7000001b /* Delta relocations.  */
+#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in
+                                            DT_MIPS_DELTA_RELOC.  */
+#define DT_MIPS_DELTA_SYM    0x7000001d /* Delta symbols that Delta
+                                          relocations refer to.  */
+#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in
+                                          DT_MIPS_DELTA_SYM.  */
+#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the
+                                            class declaration.  */
+#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in
+                                               DT_MIPS_DELTA_CLASSSYM.  */
+#define DT_MIPS_CXX_FLAGS    0x70000022 /* Flags indicating for C++ flavor.  */
+#define DT_MIPS_PIXIE_INIT   0x70000023
+#define DT_MIPS_SYMBOL_LIB   0x70000024
+#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
+#define DT_MIPS_LOCAL_GOTIDX 0x70000026
+#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
+#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
+#define DT_MIPS_OPTIONS             0x70000029 /* Address of .options.  */
+#define DT_MIPS_INTERFACE    0x7000002a /* Address of .interface.  */
+#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
+#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */
+#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve
+                                                   function stored in GOT.  */
+#define DT_MIPS_PERF_SUFFIX  0x7000002e /* Default suffix of dso to be added
+                                          by rld on dlopen() calls.  */
+#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */
+#define DT_MIPS_GP_VALUE     0x70000030 /* GP value for aux GOTs.  */
+#define DT_MIPS_AUX_DYNAMIC  0x70000031 /* Address of aux .dynamic.  */
+#define DT_MIPS_NUM         0x32
+
+/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry.  */
+
+#define RHF_NONE                  0            /* No flags */
+#define RHF_QUICKSTART            (1 << 0)     /* Use quickstart */
+#define RHF_NOTPOT                (1 << 1)     /* Hash size not power of 2 */
+#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2)    /* Ignore LD_LIBRARY_PATH */
+#define RHF_NO_MOVE               (1 << 3)
+#define RHF_SGI_ONLY              (1 << 4)
+#define RHF_GUARANTEE_INIT        (1 << 5)
+#define RHF_DELTA_C_PLUS_PLUS     (1 << 6)
+#define RHF_GUARANTEE_START_INIT   (1 << 7)
+#define RHF_PIXIE                 (1 << 8)
+#define RHF_DEFAULT_DELAY_LOAD    (1 << 9)
+#define RHF_REQUICKSTART          (1 << 10)
+#define RHF_REQUICKSTARTED        (1 << 11)
+#define RHF_CORD                  (1 << 12)
+#define RHF_NO_UNRES_UNDEF        (1 << 13)
+#define RHF_RLD_ORDER_SAFE        (1 << 14)
+
+/* Entries found in sections of type SHT_MIPS_LIBLIST.  */
+
+typedef struct
+{
+  Elf32_Word l_name;           /* Name (string table index) */
+  Elf32_Word l_time_stamp;     /* Timestamp */
+  Elf32_Word l_checksum;       /* Checksum */
+  Elf32_Word l_version;                /* Interface version */
+  Elf32_Word l_flags;          /* Flags */
+} Elf32_Lib;
+
+typedef struct
+{
+  Elf64_Word l_name;           /* Name (string table index) */
+  Elf64_Word l_time_stamp;     /* Timestamp */
+  Elf64_Word l_checksum;       /* Checksum */
+  Elf64_Word l_version;                /* Interface version */
+  Elf64_Word l_flags;          /* Flags */
+} Elf64_Lib;
+
+
+/* Legal values for l_flags.  */
+
+#define LL_NONE                  0
+#define LL_EXACT_MATCH   (1 << 0)      /* Require exact match */
+#define LL_IGNORE_INT_VER (1 << 1)     /* Ignore interface version */
+#define LL_REQUIRE_MINOR  (1 << 2)
+#define LL_EXPORTS       (1 << 3)
+#define LL_DELAY_LOAD    (1 << 4)
+#define LL_DELTA         (1 << 5)
+
+/* Entries found in sections of type SHT_MIPS_CONFLICT.  */
+
+typedef Elf32_Addr Elf32_Conflict;
+
+
+/* HPPA specific definitions.  */
+
+/* Legal values for e_flags field of Elf32_Ehdr.  */
+
+#define EF_PARISC_TRAPNIL      0x00010000 /* Trap nil pointer dereference.  */
+#define EF_PARISC_EXT          0x00020000 /* Program uses arch. extensions. */
+#define EF_PARISC_LSB          0x00040000 /* Program expects little endian. */
+#define EF_PARISC_WIDE         0x00080000 /* Program expects wide mode.  */
+#define EF_PARISC_NO_KABP      0x00100000 /* No kernel assisted branch
+                                             prediction.  */
+#define EF_PARISC_LAZYSWAP     0x00400000 /* Allow lazy swapping.  */
+#define EF_PARISC_ARCH         0x0000ffff /* Architecture version.  */
+
+/* Defined values for `e_flags & EF_PARISC_ARCH' are:  */
+
+#define EFA_PARISC_1_0             0x020b /* PA-RISC 1.0 big-endian.  */
+#define EFA_PARISC_1_1             0x0210 /* PA-RISC 1.1 big-endian.  */
+#define EFA_PARISC_2_0             0x0214 /* PA-RISC 2.0 big-endian.  */
+
+/* Additional section indeces.  */
+
+#define SHN_PARISC_ANSI_COMMON 0xff00     /* Section for tenatively declared
+                                             symbols in ANSI C.  */
+#define SHN_PARISC_HUGE_COMMON 0xff01     /* Common blocks in huge model.  */
+
+/* Legal values for sh_type field of Elf32_Shdr.  */
+
+#define SHT_PARISC_EXT         0x70000000 /* Contains product specific ext. */
+#define SHT_PARISC_UNWIND      0x70000001 /* Unwind information.  */
+#define SHT_PARISC_DOC         0x70000002 /* Debug info for optimized code. */
+
+/* Legal values for sh_flags field of Elf32_Shdr.  */
+
+#define SHF_PARISC_SHORT       0x20000000 /* Section with short addressing. */
+#define SHF_PARISC_HUGE                0x40000000 /* Section far from gp.  */
+#define SHF_PARISC_SBP         0x80000000 /* Static branch prediction code. */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_PARISC_MILLICODE   13      /* Millicode function entry point.  */
+
+#define STT_HP_OPAQUE          (STT_LOOS + 0x1)
+#define STT_HP_STUB            (STT_LOOS + 0x2)
+
+/* HPPA relocs.  */
+
+#define R_PARISC_NONE          0       /* No reloc.  */
+#define R_PARISC_DIR32         1       /* Direct 32-bit reference.  */
+#define R_PARISC_DIR21L                2       /* Left 21 bits of eff. address.  */
+#define R_PARISC_DIR17R                3       /* Right 17 bits of eff. address.  */
+#define R_PARISC_DIR17F                4       /* 17 bits of eff. address.  */
+#define R_PARISC_DIR14R                6       /* Right 14 bits of eff. address.  */
+#define R_PARISC_PCREL32       9       /* 32-bit rel. address.  */
+#define R_PARISC_PCREL21L      10      /* Left 21 bits of rel. address.  */
+#define R_PARISC_PCREL17R      11      /* Right 17 bits of rel. address.  */
+#define R_PARISC_PCREL17F      12      /* 17 bits of rel. address.  */
+#define R_PARISC_PCREL14R      14      /* Right 14 bits of rel. address.  */
+#define R_PARISC_DPREL21L      18      /* Left 21 bits of rel. address.  */
+#define R_PARISC_DPREL14R      22      /* Right 14 bits of rel. address.  */
+#define R_PARISC_GPREL21L      26      /* GP-relative, left 21 bits.  */
+#define R_PARISC_GPREL14R      30      /* GP-relative, right 14 bits.  */
+#define R_PARISC_LTOFF21L      34      /* LT-relative, left 21 bits.  */
+#define R_PARISC_LTOFF14R      38      /* LT-relative, right 14 bits.  */
+#define R_PARISC_SECREL32      41      /* 32 bits section rel. address.  */
+#define R_PARISC_SEGBASE       48      /* No relocation, set segment base.  */
+#define R_PARISC_SEGREL32      49      /* 32 bits segment rel. address.  */
+#define R_PARISC_PLTOFF21L     50      /* PLT rel. address, left 21 bits.  */
+#define R_PARISC_PLTOFF14R     54      /* PLT rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF_FPTR32  57      /* 32 bits LT-rel. function pointer. */
+#define R_PARISC_LTOFF_FPTR21L 58      /* LT-rel. fct ptr, left 21 bits. */
+#define R_PARISC_LTOFF_FPTR14R 62      /* LT-rel. fct ptr, right 14 bits. */
+#define R_PARISC_FPTR64                64      /* 64 bits function address.  */
+#define R_PARISC_PLABEL32      65      /* 32 bits function address.  */
+#define R_PARISC_PCREL64       72      /* 64 bits PC-rel. address.  */
+#define R_PARISC_PCREL22F      74      /* 22 bits PC-rel. address.  */
+#define R_PARISC_PCREL14WR     75      /* PC-rel. address, right 14 bits.  */
+#define R_PARISC_PCREL14DR     76      /* PC rel. address, right 14 bits.  */
+#define R_PARISC_PCREL16F      77      /* 16 bits PC-rel. address.  */
+#define R_PARISC_PCREL16WF     78      /* 16 bits PC-rel. address.  */
+#define R_PARISC_PCREL16DF     79      /* 16 bits PC-rel. address.  */
+#define R_PARISC_DIR64         80      /* 64 bits of eff. address.  */
+#define R_PARISC_DIR14WR       83      /* 14 bits of eff. address.  */
+#define R_PARISC_DIR14DR       84      /* 14 bits of eff. address.  */
+#define R_PARISC_DIR16F                85      /* 16 bits of eff. address.  */
+#define R_PARISC_DIR16WF       86      /* 16 bits of eff. address.  */
+#define R_PARISC_DIR16DF       87      /* 16 bits of eff. address.  */
+#define R_PARISC_GPREL64       88      /* 64 bits of GP-rel. address.  */
+#define R_PARISC_GPREL14WR     91      /* GP-rel. address, right 14 bits.  */
+#define R_PARISC_GPREL14DR     92      /* GP-rel. address, right 14 bits.  */
+#define R_PARISC_GPREL16F      93      /* 16 bits GP-rel. address.  */
+#define R_PARISC_GPREL16WF     94      /* 16 bits GP-rel. address.  */
+#define R_PARISC_GPREL16DF     95      /* 16 bits GP-rel. address.  */
+#define R_PARISC_LTOFF64       96      /* 64 bits LT-rel. address.  */
+#define R_PARISC_LTOFF14WR     99      /* LT-rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF14DR     100     /* LT-rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF16F      101     /* 16 bits LT-rel. address.  */
+#define R_PARISC_LTOFF16WF     102     /* 16 bits LT-rel. address.  */
+#define R_PARISC_LTOFF16DF     103     /* 16 bits LT-rel. address.  */
+#define R_PARISC_SECREL64      104     /* 64 bits section rel. address.  */
+#define R_PARISC_SEGREL64      112     /* 64 bits segment rel. address.  */
+#define R_PARISC_PLTOFF14WR    115     /* PLT-rel. address, right 14 bits.  */
+#define R_PARISC_PLTOFF14DR    116     /* PLT-rel. address, right 14 bits.  */
+#define R_PARISC_PLTOFF16F     117     /* 16 bits LT-rel. address.  */
+#define R_PARISC_PLTOFF16WF    118     /* 16 bits PLT-rel. address.  */
+#define R_PARISC_PLTOFF16DF    119     /* 16 bits PLT-rel. address.  */
+#define R_PARISC_LTOFF_FPTR64  120     /* 64 bits LT-rel. function ptr.  */
+#define R_PARISC_LTOFF_FPTR14WR        123     /* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR14DR        124     /* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR16F 125     /* 16 bits LT-rel. function ptr.  */
+#define R_PARISC_LTOFF_FPTR16WF        126     /* 16 bits LT-rel. function ptr.  */
+#define R_PARISC_LTOFF_FPTR16DF        127     /* 16 bits LT-rel. function ptr.  */
+#define R_PARISC_LORESERVE     128
+#define R_PARISC_COPY          128     /* Copy relocation.  */
+#define R_PARISC_IPLT          129     /* Dynamic reloc, imported PLT */
+#define R_PARISC_EPLT          130     /* Dynamic reloc, exported PLT */
+#define R_PARISC_TPREL32       153     /* 32 bits TP-rel. address.  */
+#define R_PARISC_TPREL21L      154     /* TP-rel. address, left 21 bits.  */
+#define R_PARISC_TPREL14R      158     /* TP-rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF_TP21L   162     /* LT-TP-rel. address, left 21 bits. */
+#define R_PARISC_LTOFF_TP14R   166     /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14F   167     /* 14 bits LT-TP-rel. address.  */
+#define R_PARISC_TPREL64       216     /* 64 bits TP-rel. address.  */
+#define R_PARISC_TPREL14WR     219     /* TP-rel. address, right 14 bits.  */
+#define R_PARISC_TPREL14DR     220     /* TP-rel. address, right 14 bits.  */
+#define R_PARISC_TPREL16F      221     /* 16 bits TP-rel. address.  */
+#define R_PARISC_TPREL16WF     222     /* 16 bits TP-rel. address.  */
+#define R_PARISC_TPREL16DF     223     /* 16 bits TP-rel. address.  */
+#define R_PARISC_LTOFF_TP64    224     /* 64 bits LT-TP-rel. address.  */
+#define R_PARISC_LTOFF_TP14WR  227     /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14DR  228     /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP16F   229     /* 16 bits LT-TP-rel. address.  */
+#define R_PARISC_LTOFF_TP16WF  230     /* 16 bits LT-TP-rel. address.  */
+#define R_PARISC_LTOFF_TP16DF  231     /* 16 bits LT-TP-rel. address.  */
+#define R_PARISC_HIRESERVE     255
+
+/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr.  */
+
+#define PT_HP_TLS              (PT_LOOS + 0x0)
+#define PT_HP_CORE_NONE                (PT_LOOS + 0x1)
+#define PT_HP_CORE_VERSION     (PT_LOOS + 0x2)
+#define PT_HP_CORE_KERNEL      (PT_LOOS + 0x3)
+#define PT_HP_CORE_COMM                (PT_LOOS + 0x4)
+#define PT_HP_CORE_PROC                (PT_LOOS + 0x5)
+#define PT_HP_CORE_LOADABLE    (PT_LOOS + 0x6)
+#define PT_HP_CORE_STACK       (PT_LOOS + 0x7)
+#define PT_HP_CORE_SHM         (PT_LOOS + 0x8)
+#define PT_HP_CORE_MMF         (PT_LOOS + 0x9)
+#define PT_HP_PARALLEL         (PT_LOOS + 0x10)
+#define PT_HP_FASTBIND         (PT_LOOS + 0x11)
+#define PT_HP_OPT_ANNOT                (PT_LOOS + 0x12)
+#define PT_HP_HSL_ANNOT                (PT_LOOS + 0x13)
+#define PT_HP_STACK            (PT_LOOS + 0x14)
+
+#define PT_PARISC_ARCHEXT      0x70000000
+#define PT_PARISC_UNWIND       0x70000001
+
+/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr.  */
+
+#define PF_PARISC_SBP          0x08000000
+
+#define PF_HP_PAGE_SIZE                0x00100000
+#define PF_HP_FAR_SHARED       0x00200000
+#define PF_HP_NEAR_SHARED      0x00400000
+#define PF_HP_CODE             0x01000000
+#define PF_HP_MODIFY           0x02000000
+#define PF_HP_LAZYSWAP         0x04000000
+#define PF_HP_SBP              0x08000000
+
+
+/* Alpha specific definitions.  */
+
+/* Legal values for e_flags field of Elf64_Ehdr.  */
+
+#define EF_ALPHA_32BIT         1       /* All addresses must be < 2GB.  */
+#define EF_ALPHA_CANRELAX      2       /* Relocations for relaxing exist.  */
+
+/* Legal values for sh_type field of Elf64_Shdr.  */
+
+/* These two are primerily concerned with ECOFF debugging info.  */
+#define SHT_ALPHA_DEBUG                0x70000001
+#define SHT_ALPHA_REGINFO      0x70000002
+
+/* Legal values for sh_flags field of Elf64_Shdr.  */
+
+#define SHF_ALPHA_GPREL                0x10000000
+
+/* Legal values for st_other field of Elf64_Sym.  */
+#define STO_ALPHA_NOPV         0x80    /* No PV required.  */
+#define STO_ALPHA_STD_GPLOAD   0x88    /* PV only used for initial ldgp.  */
+
+/* Alpha relocs.  */
+
+#define R_ALPHA_NONE           0       /* No reloc */
+#define R_ALPHA_REFLONG                1       /* Direct 32 bit */
+#define R_ALPHA_REFQUAD                2       /* Direct 64 bit */
+#define R_ALPHA_GPREL32                3       /* GP relative 32 bit */
+#define R_ALPHA_LITERAL                4       /* GP relative 16 bit w/optimization */
+#define R_ALPHA_LITUSE         5       /* Optimization hint for LITERAL */
+#define R_ALPHA_GPDISP         6       /* Add displacement to GP */
+#define R_ALPHA_BRADDR         7       /* PC+4 relative 23 bit shifted */
+#define R_ALPHA_HINT           8       /* PC+4 relative 16 bit shifted */
+#define R_ALPHA_SREL16         9       /* PC relative 16 bit */
+#define R_ALPHA_SREL32         10      /* PC relative 32 bit */
+#define R_ALPHA_SREL64         11      /* PC relative 64 bit */
+#define R_ALPHA_GPRELHIGH      17      /* GP relative 32 bit, high 16 bits */
+#define R_ALPHA_GPRELLOW       18      /* GP relative 32 bit, low 16 bits */
+#define R_ALPHA_GPREL16                19      /* GP relative 16 bit */
+#define R_ALPHA_COPY           24      /* Copy symbol at runtime */
+#define R_ALPHA_GLOB_DAT       25      /* Create GOT entry */
+#define R_ALPHA_JMP_SLOT       26      /* Create PLT entry */
+#define R_ALPHA_RELATIVE       27      /* Adjust by program base */
+#define R_ALPHA_TLS_GD_HI      28
+#define R_ALPHA_TLSGD          29
+#define R_ALPHA_TLS_LDM                30
+#define R_ALPHA_DTPMOD64       31
+#define R_ALPHA_GOTDTPREL      32
+#define R_ALPHA_DTPREL64       33
+#define R_ALPHA_DTPRELHI       34
+#define R_ALPHA_DTPRELLO       35
+#define R_ALPHA_DTPREL16       36
+#define R_ALPHA_GOTTPREL       37
+#define R_ALPHA_TPREL64                38
+#define R_ALPHA_TPRELHI                39
+#define R_ALPHA_TPRELLO                40
+#define R_ALPHA_TPREL16                41
+/* Keep this the last entry.  */
+#define R_ALPHA_NUM            46
+
+/* Magic values of the LITUSE relocation addend.  */
+#define LITUSE_ALPHA_ADDR      0
+#define LITUSE_ALPHA_BASE      1
+#define LITUSE_ALPHA_BYTOFF    2
+#define LITUSE_ALPHA_JSR       3
+#define LITUSE_ALPHA_TLS_GD    4
+#define LITUSE_ALPHA_TLS_LDM   5
+
+
+/* PowerPC specific declarations */
+
+/* Values for Elf32/64_Ehdr.e_flags.  */
+#define EF_PPC_EMB             0x80000000      /* PowerPC embedded flag */
+
+/* Cygnus local bits below */
+#define EF_PPC_RELOCATABLE     0x00010000      /* PowerPC -mrelocatable flag*/
+#define EF_PPC_RELOCATABLE_LIB 0x00008000      /* PowerPC -mrelocatable-lib
+                                                  flag */
+
+/* PowerPC relocations defined by the ABIs */
+#define R_PPC_NONE             0
+#define R_PPC_ADDR32           1       /* 32bit absolute address */
+#define R_PPC_ADDR24           2       /* 26bit address, 2 bits ignored.  */
+#define R_PPC_ADDR16           3       /* 16bit absolute address */
+#define R_PPC_ADDR16_LO                4       /* lower 16bit of absolute address */
+#define R_PPC_ADDR16_HI                5       /* high 16bit of absolute address */
+#define R_PPC_ADDR16_HA                6       /* adjusted high 16bit */
+#define R_PPC_ADDR14           7       /* 16bit address, 2 bits ignored */
+#define R_PPC_ADDR14_BRTAKEN   8
+#define R_PPC_ADDR14_BRNTAKEN  9
+#define R_PPC_REL24            10      /* PC relative 26 bit */
+#define R_PPC_REL14            11      /* PC relative 16 bit */
+#define R_PPC_REL14_BRTAKEN    12
+#define R_PPC_REL14_BRNTAKEN   13
+#define R_PPC_GOT16            14
+#define R_PPC_GOT16_LO         15
+#define R_PPC_GOT16_HI         16
+#define R_PPC_GOT16_HA         17
+#define R_PPC_PLTREL24         18
+#define R_PPC_COPY             19
+#define R_PPC_GLOB_DAT         20
+#define R_PPC_JMP_SLOT         21
+#define R_PPC_RELATIVE         22
+#define R_PPC_LOCAL24PC                23
+#define R_PPC_UADDR32          24
+#define R_PPC_UADDR16          25
+#define R_PPC_REL32            26
+#define R_PPC_PLT32            27
+#define R_PPC_PLTREL32         28
+#define R_PPC_PLT16_LO         29
+#define R_PPC_PLT16_HI         30
+#define R_PPC_PLT16_HA         31
+#define R_PPC_SDAREL16         32
+#define R_PPC_SECTOFF          33
+#define R_PPC_SECTOFF_LO       34
+#define R_PPC_SECTOFF_HI       35
+#define R_PPC_SECTOFF_HA       36
+/* Keep this the last entry.  */
+#define R_PPC_NUM              37
+
+/* PowerPC64 relocations defined by the ABIs */
+#define R_PPC64_NONE    R_PPC_NONE
+#define R_PPC64_ADDR32  R_PPC_ADDR32  /* 32bit absolute address.  */
+#define R_PPC64_ADDR24  R_PPC_ADDR24  /* 26bit address, word aligned.  */
+#define R_PPC64_ADDR16  R_PPC_ADDR16  /* 16bit absolute address. */
+#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of abs. address.  */
+#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of abs. address. */
+#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits.  */
+#define R_PPC64_ADDR14 R_PPC_ADDR14   /* 16bit address, word aligned.  */
+#define R_PPC64_ADDR14_BRTAKEN  R_PPC_ADDR14_BRTAKEN
+#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN
+#define R_PPC64_REL24   R_PPC_REL24 /* PC relative 26 bit, word aligned.  */
+#define R_PPC64_REL14   R_PPC_REL14 /* PC relative 16 bit. */
+#define R_PPC64_REL14_BRTAKEN   R_PPC_REL14_BRTAKEN
+#define R_PPC64_REL14_BRNTAKEN  R_PPC_REL14_BRNTAKEN
+#define R_PPC64_GOT16     R_PPC_GOT16
+#define R_PPC64_GOT16_LO  R_PPC_GOT16_LO
+#define R_PPC64_GOT16_HI  R_PPC_GOT16_HI
+#define R_PPC64_GOT16_HA  R_PPC_GOT16_HA
+
+#define R_PPC64_COPY      R_PPC_COPY
+#define R_PPC64_GLOB_DAT  R_PPC_GLOB_DAT
+#define R_PPC64_JMP_SLOT  R_PPC_JMP_SLOT
+#define R_PPC64_RELATIVE  R_PPC_RELATIVE
+
+#define R_PPC64_UADDR32   R_PPC_UADDR32
+#define R_PPC64_UADDR16   R_PPC_UADDR16
+#define R_PPC64_REL32     R_PPC_REL32
+#define R_PPC64_PLT32     R_PPC_PLT32
+#define R_PPC64_PLTREL32  R_PPC_PLTREL32
+#define R_PPC64_PLT16_LO  R_PPC_PLT16_LO
+#define R_PPC64_PLT16_HI  R_PPC_PLT16_HI
+#define R_PPC64_PLT16_HA  R_PPC_PLT16_HA
+
+#define R_PPC64_SECTOFF     R_PPC_SECTOFF
+#define R_PPC64_SECTOFF_LO  R_PPC_SECTOFF_LO
+#define R_PPC64_SECTOFF_HI  R_PPC_SECTOFF_HI
+#define R_PPC64_SECTOFF_HA  R_PPC_SECTOFF_HA
+#define R_PPC64_ADDR30          37  /* word30 (S + A - P) >> 2.  */
+#define R_PPC64_ADDR64          38  /* doubleword64 S + A.  */
+#define R_PPC64_ADDR16_HIGHER   39  /* half16 #higher(S + A).  */
+#define R_PPC64_ADDR16_HIGHERA  40  /* half16 #highera(S + A).  */
+#define R_PPC64_ADDR16_HIGHEST  41  /* half16 #highest(S + A).  */
+#define R_PPC64_ADDR16_HIGHESTA 42  /* half16 #highesta(S + A). */
+#define R_PPC64_UADDR64     43  /* doubleword64 S + A.  */
+#define R_PPC64_REL64       44  /* doubleword64 S + A - P.  */
+#define R_PPC64_PLT64       45  /* doubleword64 L + A.  */
+#define R_PPC64_PLTREL64    46  /* doubleword64 L + A - P.  */
+#define R_PPC64_TOC16       47  /* half16* S + A - .TOC.  */
+#define R_PPC64_TOC16_LO    48  /* half16 #lo(S + A - .TOC.).  */
+#define R_PPC64_TOC16_HI    49  /* half16 #hi(S + A - .TOC.).  */
+#define R_PPC64_TOC16_HA    50  /* half16 #ha(S + A - .TOC.).  */
+#define R_PPC64_TOC         51  /* doubleword64 .TOC. */
+#define R_PPC64_PLTGOT16    52  /* half16* M + A.  */
+#define R_PPC64_PLTGOT16_LO 53  /* half16 #lo(M + A).  */
+#define R_PPC64_PLTGOT16_HI 54  /* half16 #hi(M + A).  */
+#define R_PPC64_PLTGOT16_HA 55  /* half16 #ha(M + A).  */
+
+#define R_PPC64_ADDR16_DS      56 /* half16ds* (S + A) >> 2.  */
+#define R_PPC64_ADDR16_LO_DS   57 /* half16ds  #lo(S + A) >> 2.  */
+#define R_PPC64_GOT16_DS       58 /* half16ds* (G + A) >> 2.  */
+#define R_PPC64_GOT16_LO_DS    59 /* half16ds  #lo(G + A) >> 2.  */
+#define R_PPC64_PLT16_LO_DS    60 /* half16ds  #lo(L + A) >> 2.  */
+#define R_PPC64_SECTOFF_DS     61 /* half16ds* (R + A) >> 2.  */
+#define R_PPC64_SECTOFF_LO_DS  62 /* half16ds  #lo(R + A) >> 2.  */
+#define R_PPC64_TOC16_DS       63 /* half16ds* (S + A - .TOC.) >> 2.  */
+#define R_PPC64_TOC16_LO_DS    64 /* half16ds  #lo(S + A - .TOC.) >> 2.  */
+#define R_PPC64_PLTGOT16_DS    65 /* half16ds* (M + A) >> 2.  */
+#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds  #lo(M + A) >> 2.  */
+/* Keep this the last entry.  */
+#define R_PPC64_NUM            67
+
+/* The remaining relocs are from the Embedded ELF ABI, and are not
+   in the SVR4 ELF ABI.  */
+#define R_PPC_EMB_NADDR32      101
+#define R_PPC_EMB_NADDR16      102
+#define R_PPC_EMB_NADDR16_LO   103
+#define R_PPC_EMB_NADDR16_HI   104
+#define R_PPC_EMB_NADDR16_HA   105
+#define R_PPC_EMB_SDAI16       106
+#define R_PPC_EMB_SDA2I16      107
+#define R_PPC_EMB_SDA2REL      108
+#define R_PPC_EMB_SDA21                109     /* 16 bit offset in SDA */
+#define R_PPC_EMB_MRKREF       110
+#define R_PPC_EMB_RELSEC16     111
+#define R_PPC_EMB_RELST_LO     112
+#define R_PPC_EMB_RELST_HI     113
+#define R_PPC_EMB_RELST_HA     114
+#define R_PPC_EMB_BIT_FLD      115
+#define R_PPC_EMB_RELSDA       116     /* 16 bit relative offset in SDA */
+
+/* Diab tool relocations.  */
+#define R_PPC_DIAB_SDA21_LO    180     /* like EMB_SDA21, but lower 16 bit */
+#define R_PPC_DIAB_SDA21_HI    181     /* like EMB_SDA21, but high 16 bit */
+#define R_PPC_DIAB_SDA21_HA    182     /* like EMB_SDA21, adjusted high 16 */
+#define R_PPC_DIAB_RELSDA_LO   183     /* like EMB_RELSDA, but lower 16 bit */
+#define R_PPC_DIAB_RELSDA_HI   184     /* like EMB_RELSDA, but high 16 bit */
+#define R_PPC_DIAB_RELSDA_HA   185     /* like EMB_RELSDA, adjusted high 16 */
+
+/* This is a phony reloc to handle any old fashioned TOC16 references
+   that may still be in object files.  */
+#define R_PPC_TOC16            255
+
+/* PowerPC64 specific values for the Dyn d_tag field.  */
+#define DT_PPC64_GLINK  (DT_LOPROC + 0)
+#define DT_PPC64_NUM    1
+
+/* ARM specific declarations */
+
+/* Processor specific flags for the ELF header e_flags field.  */
+#define EF_ARM_RELEXEC     0x01
+#define EF_ARM_HASENTRY    0x02
+#define EF_ARM_INTERWORK   0x04
+#define EF_ARM_APCS_26     0x08
+#define EF_ARM_APCS_FLOAT  0x10
+#define EF_ARM_PIC         0x20
+#define EF_ARM_ALIGN8      0x40                /* 8-bit structure alignment is in use */
+#define EF_ARM_NEW_ABI     0x80
+#define EF_ARM_OLD_ABI     0x100
+
+/* Other constants defined in the ARM ELF spec. version B-01.  */
+/* NB. These conflict with values defined above.  */
+#define EF_ARM_SYMSARESORTED   0x04
+#define EF_ARM_DYNSYMSUSESEGIDX 0x08
+#define EF_ARM_MAPSYMSFIRST    0x10
+#define EF_ARM_EABIMASK                0XFF000000
+
+#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK)
+#define EF_ARM_EABI_UNKNOWN  0x00000000
+#define EF_ARM_EABI_VER1     0x01000000
+#define EF_ARM_EABI_VER2     0x02000000
+
+/* Additional symbol types for Thumb */
+#define STT_ARM_TFUNC      0xd
+
+/* ARM-specific values for sh_flags */
+#define SHF_ARM_ENTRYSECT  0x10000000   /* Section contains an entry point */
+#define SHF_ARM_COMDEF     0x80000000   /* Section may be multiply defined
+                                          in the input to a link step */
+
+/* ARM-specific program header flags */
+#define PF_ARM_SB          0x10000000   /* Segment contains the location
+                                          addressed by the static base */
+
+/* ARM relocs.  */
+#define R_ARM_NONE             0       /* No reloc */
+#define R_ARM_PC24             1       /* PC relative 26 bit branch */
+#define R_ARM_ABS32            2       /* Direct 32 bit  */
+#define R_ARM_REL32            3       /* PC relative 32 bit */
+#define R_ARM_PC13             4
+#define R_ARM_ABS16            5       /* Direct 16 bit */
+#define R_ARM_ABS12            6       /* Direct 12 bit */
+#define R_ARM_THM_ABS5         7
+#define R_ARM_ABS8             8       /* Direct 8 bit */
+#define R_ARM_SBREL32          9
+#define R_ARM_THM_PC22         10
+#define R_ARM_THM_PC8          11
+#define R_ARM_AMP_VCALL9       12
+#define R_ARM_SWI24            13
+#define R_ARM_THM_SWI8         14
+#define R_ARM_XPC25            15
+#define R_ARM_THM_XPC22                16
+#define R_ARM_COPY             20      /* Copy symbol at runtime */
+#define R_ARM_GLOB_DAT         21      /* Create GOT entry */
+#define R_ARM_JUMP_SLOT                22      /* Create PLT entry */
+#define R_ARM_RELATIVE         23      /* Adjust by program base */
+#define R_ARM_GOTOFF           24      /* 32 bit offset to GOT */
+#define R_ARM_GOTPC            25      /* 32 bit PC relative offset to GOT */
+#define R_ARM_GOT32            26      /* 32 bit GOT entry */
+#define R_ARM_PLT32            27      /* 32 bit PLT address */
+#define R_ARM_ALU_PCREL_7_0    32
+#define R_ARM_ALU_PCREL_15_8   33
+#define R_ARM_ALU_PCREL_23_15  34
+#define R_ARM_LDR_SBREL_11_0   35
+#define R_ARM_ALU_SBREL_19_12  36
+#define R_ARM_ALU_SBREL_27_20  37
+#define R_ARM_GNU_VTENTRY      100
+#define R_ARM_GNU_VTINHERIT    101
+#define R_ARM_THM_PC11         102     /* thumb unconditional branch */
+#define R_ARM_THM_PC9          103     /* thumb conditional branch */
+#define R_ARM_RXPC25           249
+#define R_ARM_RSBREL32         250
+#define R_ARM_THM_RPC22                251
+#define R_ARM_RREL32           252
+#define R_ARM_RABS22           253
+#define R_ARM_RPC24            254
+#define R_ARM_RBASE            255
+/* Keep this the last entry.  */
+#define R_ARM_NUM              256
+
+/* IA-64 specific declarations.  */
+
+/* Processor specific flags for the Ehdr e_flags field.  */
+#define EF_IA_64_MASKOS                0x0000000f      /* os-specific flags */
+#define EF_IA_64_ABI64         0x00000010      /* 64-bit ABI */
+#define EF_IA_64_ARCH          0xff000000      /* arch. version mask */
+
+/* Processor specific values for the Phdr p_type field.  */
+#define PT_IA_64_ARCHEXT       (PT_LOPROC + 0) /* arch extension bits */
+#define PT_IA_64_UNWIND                (PT_LOPROC + 1) /* ia64 unwind bits */
+
+/* Processor specific flags for the Phdr p_flags field.  */
+#define PF_IA_64_NORECOV       0x80000000      /* spec insns w/o recovery */
+
+/* Processor specific values for the Shdr sh_type field.  */
+#define SHT_IA_64_EXT          (SHT_LOPROC + 0) /* extension bits */
+#define SHT_IA_64_UNWIND       (SHT_LOPROC + 1) /* unwind bits */
+
+/* Processor specific flags for the Shdr sh_flags field.  */
+#define SHF_IA_64_SHORT                0x10000000      /* section near gp */
+#define SHF_IA_64_NORECOV      0x20000000      /* spec insns w/o recovery */
+
+/* Processor specific values for the Dyn d_tag field.  */
+#define DT_IA_64_PLT_RESERVE   (DT_LOPROC + 0)
+#define DT_IA_64_NUM           1
+
+/* IA-64 relocations.  */
+#define R_IA64_NONE            0x00    /* none */
+#define R_IA64_IMM14           0x21    /* symbol + addend, add imm14 */
+#define R_IA64_IMM22           0x22    /* symbol + addend, add imm22 */
+#define R_IA64_IMM64           0x23    /* symbol + addend, mov imm64 */
+#define R_IA64_DIR32MSB                0x24    /* symbol + addend, data4 MSB */
+#define R_IA64_DIR32LSB                0x25    /* symbol + addend, data4 LSB */
+#define R_IA64_DIR64MSB                0x26    /* symbol + addend, data8 MSB */
+#define R_IA64_DIR64LSB                0x27    /* symbol + addend, data8 LSB */
+#define R_IA64_GPREL22         0x2a    /* @gprel(sym + add), add imm22 */
+#define R_IA64_GPREL64I                0x2b    /* @gprel(sym + add), mov imm64 */
+#define R_IA64_GPREL32MSB      0x2c    /* @gprel(sym + add), data4 MSB */
+#define R_IA64_GPREL32LSB      0x2d    /* @gprel(sym + add), data4 LSB */
+#define R_IA64_GPREL64MSB      0x2e    /* @gprel(sym + add), data8 MSB */
+#define R_IA64_GPREL64LSB      0x2f    /* @gprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF22         0x32    /* @ltoff(sym + add), add imm22 */
+#define R_IA64_LTOFF64I                0x33    /* @ltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF22                0x3a    /* @pltoff(sym + add), add imm22 */
+#define R_IA64_PLTOFF64I       0x3b    /* @pltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF64MSB     0x3e    /* @pltoff(sym + add), data8 MSB */
+#define R_IA64_PLTOFF64LSB     0x3f    /* @pltoff(sym + add), data8 LSB */
+#define R_IA64_FPTR64I         0x43    /* @fptr(sym + add), mov imm64 */
+#define R_IA64_FPTR32MSB       0x44    /* @fptr(sym + add), data4 MSB */
+#define R_IA64_FPTR32LSB       0x45    /* @fptr(sym + add), data4 LSB */
+#define R_IA64_FPTR64MSB       0x46    /* @fptr(sym + add), data8 MSB */
+#define R_IA64_FPTR64LSB       0x47    /* @fptr(sym + add), data8 LSB */
+#define R_IA64_PCREL60B                0x48    /* @pcrel(sym + add), brl */
+#define R_IA64_PCREL21B                0x49    /* @pcrel(sym + add), ptb, call */
+#define R_IA64_PCREL21M                0x4a    /* @pcrel(sym + add), chk.s */
+#define R_IA64_PCREL21F                0x4b    /* @pcrel(sym + add), fchkf */
+#define R_IA64_PCREL32MSB      0x4c    /* @pcrel(sym + add), data4 MSB */
+#define R_IA64_PCREL32LSB      0x4d    /* @pcrel(sym + add), data4 LSB */
+#define R_IA64_PCREL64MSB      0x4e    /* @pcrel(sym + add), data8 MSB */
+#define R_IA64_PCREL64LSB      0x4f    /* @pcrel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_FPTR22    0x52    /* @ltoff(@fptr(s+a)), imm22 */
+#define R_IA64_LTOFF_FPTR64I   0x53    /* @ltoff(@fptr(s+a)), imm64 */
+#define R_IA64_LTOFF_FPTR32MSB 0x54    /* @ltoff(@fptr(s+a)), data4 MSB */
+#define R_IA64_LTOFF_FPTR32LSB 0x55    /* @ltoff(@fptr(s+a)), data4 LSB */
+#define R_IA64_LTOFF_FPTR64MSB 0x56    /* @ltoff(@fptr(s+a)), data8 MSB */
+#define R_IA64_LTOFF_FPTR64LSB 0x57    /* @ltoff(@fptr(s+a)), data8 LSB */
+#define R_IA64_SEGREL32MSB     0x5c    /* @segrel(sym + add), data4 MSB */
+#define R_IA64_SEGREL32LSB     0x5d    /* @segrel(sym + add), data4 LSB */
+#define R_IA64_SEGREL64MSB     0x5e    /* @segrel(sym + add), data8 MSB */
+#define R_IA64_SEGREL64LSB     0x5f    /* @segrel(sym + add), data8 LSB */
+#define R_IA64_SECREL32MSB     0x64    /* @secrel(sym + add), data4 MSB */
+#define R_IA64_SECREL32LSB     0x65    /* @secrel(sym + add), data4 LSB */
+#define R_IA64_SECREL64MSB     0x66    /* @secrel(sym + add), data8 MSB */
+#define R_IA64_SECREL64LSB     0x67    /* @secrel(sym + add), data8 LSB */
+#define R_IA64_REL32MSB                0x6c    /* data 4 + REL */
+#define R_IA64_REL32LSB                0x6d    /* data 4 + REL */
+#define R_IA64_REL64MSB                0x6e    /* data 8 + REL */
+#define R_IA64_REL64LSB                0x6f    /* data 8 + REL */
+#define R_IA64_LTV32MSB                0x74    /* symbol + addend, data4 MSB */
+#define R_IA64_LTV32LSB                0x75    /* symbol + addend, data4 LSB */
+#define R_IA64_LTV64MSB                0x76    /* symbol + addend, data8 MSB */
+#define R_IA64_LTV64LSB                0x77    /* symbol + addend, data8 LSB */
+#define R_IA64_PCREL21BI       0x79    /* @pcrel(sym + add), 21bit inst */
+#define R_IA64_PCREL22         0x7a    /* @pcrel(sym + add), 22bit inst */
+#define R_IA64_PCREL64I                0x7b    /* @pcrel(sym + add), 64bit inst */
+#define R_IA64_IPLTMSB         0x80    /* dynamic reloc, imported PLT, MSB */
+#define R_IA64_IPLTLSB         0x81    /* dynamic reloc, imported PLT, LSB */
+#define R_IA64_COPY            0x84    /* copy relocation */
+#define R_IA64_SUB             0x85    /* Addend and symbol difference */
+#define R_IA64_LTOFF22X                0x86    /* LTOFF22, relaxable.  */
+#define R_IA64_LDXMOV          0x87    /* Use of LTOFF22X.  */
+#define R_IA64_TPREL14         0x91    /* @tprel(sym + add), imm14 */
+#define R_IA64_TPREL22         0x92    /* @tprel(sym + add), imm22 */
+#define R_IA64_TPREL64I                0x93    /* @tprel(sym + add), imm64 */
+#define R_IA64_TPREL64MSB      0x96    /* @tprel(sym + add), data8 MSB */
+#define R_IA64_TPREL64LSB      0x97    /* @tprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_TPREL22   0x9a    /* @ltoff(@tprel(s+a)), imm2 */
+#define R_IA64_DTPMOD64MSB     0xa6    /* @dtpmod(sym + add), data8 MSB */
+#define R_IA64_DTPMOD64LSB     0xa7    /* @dtpmod(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPMOD22  0xaa    /* @ltoff(@dtpmod(sym + add)), imm22 */
+#define R_IA64_DTPREL14                0xb1    /* @dtprel(sym + add), imm14 */
+#define R_IA64_DTPREL22                0xb2    /* @dtprel(sym + add), imm22 */
+#define R_IA64_DTPREL64I       0xb3    /* @dtprel(sym + add), imm64 */
+#define R_IA64_DTPREL32MSB     0xb4    /* @dtprel(sym + add), data4 MSB */
+#define R_IA64_DTPREL32LSB     0xb5    /* @dtprel(sym + add), data4 LSB */
+#define R_IA64_DTPREL64MSB     0xb6    /* @dtprel(sym + add), data8 MSB */
+#define R_IA64_DTPREL64LSB     0xb7    /* @dtprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPREL22  0xba    /* @ltoff(@dtprel(s+a)), imm22 */
+
+/* SH specific declarations */
+
+/* SH relocs.  */
+#define        R_SH_NONE               0
+#define        R_SH_DIR32              1
+#define        R_SH_REL32              2
+#define        R_SH_DIR8WPN            3
+#define        R_SH_IND12W             4
+#define        R_SH_DIR8WPL            5
+#define        R_SH_DIR8WPZ            6
+#define        R_SH_DIR8BP             7
+#define        R_SH_DIR8W              8
+#define        R_SH_DIR8L              9
+#define        R_SH_SWITCH16           25
+#define        R_SH_SWITCH32           26
+#define        R_SH_USES               27
+#define        R_SH_COUNT              28
+#define        R_SH_ALIGN              29
+#define        R_SH_CODE               30
+#define        R_SH_DATA               31
+#define        R_SH_LABEL              32
+#define        R_SH_SWITCH8            33
+#define        R_SH_GNU_VTINHERIT      34
+#define        R_SH_GNU_VTENTRY        35
+#define        R_SH_TLS_GD_32          144
+#define        R_SH_TLS_LD_32          145
+#define        R_SH_TLS_LDO_32         146
+#define        R_SH_TLS_IE_32          147
+#define        R_SH_TLS_LE_32          148
+#define        R_SH_TLS_DTPMOD32       149
+#define        R_SH_TLS_DTPOFF32       150
+#define        R_SH_TLS_TPOFF32        151
+#define        R_SH_TLS_GD_MOV         152
+#define        R_SH_TLS_LDM_MOV        153
+#define        R_SH_TLS_LDO_MOV        154
+#define        R_SH_TLS_IE_MOV         155
+#define        R_SH_TLS_LE_MOV         156
+#define        R_SH_GOT32              160
+#define        R_SH_PLT32              161
+#define        R_SH_COPY               162
+#define        R_SH_GLOB_DAT           163
+#define        R_SH_JMP_SLOT           164
+#define        R_SH_RELATIVE           165
+#define        R_SH_GOTOFF             166
+#define        R_SH_GOTPC              167
+/* Keep this the last entry.  */
+#define        R_SH_NUM                256
+
+/* Additional s390 relocs */
+
+#define R_390_NONE     0              /* No reloc.  */
+#define R_390_8                1              /* Direct 8 bit.  */
+#define R_390_12       2              /* Direct 12 bit.  */
+#define R_390_16       3              /* Direct 16 bit.  */
+#define R_390_32       4              /* Direct 32 bit.  */
+#define R_390_PC32     5              /* PC relative 32 bit.  */
+#define R_390_GOT12    6              /* 12 bit GOT offset.  */
+#define R_390_GOT32    7              /* 32 bit GOT offset.  */
+#define R_390_PLT32    8              /* 32 bit PC relative PLT address.  */
+#define R_390_COPY     9              /* Copy symbol at runtime.  */
+#define R_390_GLOB_DAT 10             /* Create GOT entry.  */
+#define R_390_JMP_SLOT 11             /* Create PLT entry.  */
+#define R_390_RELATIVE 12             /* Adjust by program base.  */
+#define R_390_GOTOFF   13             /* 32 bit offset to GOT.  */
+#define R_390_GOTPC    14             /* 32 bit PC relative offset to GOT.  */
+#define R_390_GOT16    15             /* 16 bit GOT offset.  */
+#define R_390_PC16     16             /* PC relative 16 bit.  */
+#define R_390_PC16DBL  17             /* PC relative 16 bit shifted by 1.  */
+#define R_390_PLT16DBL 18             /* 16 bit PC rel. PLT shifted by 1.  */
+#define R_390_PC32DBL  19             /* PC relative 32 bit shifted by 1.  */
+#define R_390_PLT32DBL 20             /* 32 bit PC rel. PLT shifted by 1.  */
+#define R_390_GOTPCDBL 21             /* 32 bit PC rel. GOT shifted by 1.  */
+#define R_390_64       22             /* Direct 64 bit.  */
+#define R_390_PC64     23             /* PC relative 64 bit.  */
+#define R_390_GOT64    24             /* 64 bit GOT offset.  */
+#define R_390_PLT64    25             /* 64 bit PC relative PLT address.  */
+#define R_390_GOTENT   26             /* 32 bit PC rel. to GOT entry >> 1. */
+
+/* Keep this the last entry.  */
+#define R_390_NUM      27
+
+/* CRIS relocations.  */
+#define R_CRIS_NONE            0
+#define R_CRIS_8               1
+#define R_CRIS_16              2
+#define R_CRIS_32              3
+#define R_CRIS_8_PCREL         4
+#define R_CRIS_16_PCREL                5
+#define R_CRIS_32_PCREL                6
+#define R_CRIS_GNU_VTINHERIT   7
+#define R_CRIS_GNU_VTENTRY     8
+#define R_CRIS_COPY            9
+#define R_CRIS_GLOB_DAT                10
+#define R_CRIS_JUMP_SLOT       11
+#define R_CRIS_RELATIVE                12
+#define R_CRIS_16_GOT          13
+#define R_CRIS_32_GOT          14
+#define R_CRIS_16_GOTPLT       15
+#define R_CRIS_32_GOTPLT       16
+#define R_CRIS_32_GOTREL       17
+#define R_CRIS_32_PLT_GOTREL   18
+#define R_CRIS_32_PLT_PCREL    19
+
+#define R_CRIS_NUM             20
+
+/* AMD x86-64 relocations.  */
+#define R_X86_64_NONE          0       /* No reloc */
+#define R_X86_64_64            1       /* Direct 64 bit  */
+#define R_X86_64_PC32          2       /* PC relative 32 bit signed */
+#define R_X86_64_GOT32         3       /* 32 bit GOT entry */
+#define R_X86_64_PLT32         4       /* 32 bit PLT address */
+#define R_X86_64_COPY          5       /* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT      6       /* Create GOT entry */
+#define R_X86_64_JUMP_SLOT     7       /* Create PLT entry */
+#define R_X86_64_RELATIVE      8       /* Adjust by program base */
+#define R_X86_64_GOTPCREL      9       /* 32 bit signed PC relative
+                                          offset to GOT */
+#define R_X86_64_32            10      /* Direct 32 bit zero extended */
+#define R_X86_64_32S           11      /* Direct 32 bit sign extended */
+#define R_X86_64_16            12      /* Direct 16 bit zero extended */
+#define R_X86_64_PC16          13      /* 16 bit sign extended pc relative */
+#define R_X86_64_8             14      /* Direct 8 bit sign extended  */
+#define R_X86_64_PC8           15      /* 8 bit sign extended pc relative */
+#define R_X86_64_DTPMOD64      16      /* ID of module containing symbol */
+#define R_X86_64_DTPOFF64      17      /* Offset in module's TLS block */
+#define R_X86_64_TPOFF64       18      /* Offset in initial TLS block */
+#define R_X86_64_TLSGD         19      /* 32 bit signed PC relative offset
+                                          to two GOT entries for GD symbol */
+#define R_X86_64_TLSLD         20      /* 32 bit signed PC relative offset
+                                          to two GOT entries for LD symbol */
+#define R_X86_64_DTPOFF32      21      /* Offset in TLS block */
+#define r_x86_64_GOTTPOFF      22      /* 32 bit signed PC relative offset
+                                          to GOT entry for IE symbol */
+#define R_X86_64_TPOFF32       23      /* Offset in initial TLS block */
+
+#define R_X86_64_NUM           24
+
+#endif /* ! GRUB_ELF_H */
diff --git a/include/grub/elfload.h b/include/grub/elfload.h
new file mode 100644 (file)
index 0000000..5d611da
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003, 2004, 2005, 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_ELFLOAD_HEADER
+#define GRUB_ELFLOAD_HEADER    1
+
+#include <grub/err.h>
+#include <grub/elf.h>
+#include <grub/file.h>
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+struct grub_elf_file
+{
+  grub_file_t file;
+  union {
+    Elf64_Ehdr ehdr64;
+    Elf32_Ehdr ehdr32;
+  } ehdr;
+  void *phdrs;
+};
+typedef struct grub_elf_file *grub_elf_t;
+
+typedef grub_err_t (*grub_elf32_load_hook_t)
+  (Elf32_Phdr *phdr, grub_addr_t *addr);
+typedef grub_err_t (*grub_elf64_load_hook_t)
+  (Elf64_Phdr *phdr, grub_addr_t *addr);
+
+grub_elf_t grub_elf_open (const char *);
+grub_elf_t grub_elf_file (grub_file_t);
+grub_err_t grub_elf_close (grub_elf_t);
+
+int grub_elf_is_elf32 (grub_elf_t);
+grub_size_t grub_elf32_size (grub_elf_t);
+grub_err_t grub_elf32_load (grub_elf_t, grub_elf32_load_hook_t, grub_addr_t *,
+                           grub_size_t *);
+
+int grub_elf_is_elf64 (grub_elf_t);
+grub_size_t grub_elf64_size (grub_elf_t);
+grub_err_t grub_elf64_load (grub_elf_t, grub_elf64_load_hook_t, grub_addr_t *,
+                           grub_size_t *);
+
+#endif /* ! GRUB_ELFLOAD_HEADER */
diff --git a/include/grub/env.h b/include/grub/env.h
new file mode 100644 (file)
index 0000000..36c1e87
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2005,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_ENV_HEADER
+#define GRUB_ENV_HEADER        1
+
+#include <grub/symbol.h>
+#include <grub/err.h>
+#include <grub/types.h>
+
+struct grub_env_var;
+
+typedef char *(*grub_env_read_hook_t) (struct grub_env_var *var,
+                                      const char *val);
+typedef char *(*grub_env_write_hook_t) (struct grub_env_var *var,
+                                       const char *val);
+
+enum grub_env_var_type
+  {
+    /* The default variable type which is local in current context.  */
+    GRUB_ENV_VAR_LOCAL,
+
+    /* The exported type, which is passed to new contexts.  */
+    GRUB_ENV_VAR_GLOBAL,
+
+    /* The data slot type, which is used to store arbitrary data.  */
+    GRUB_ENV_VAR_DATA
+  };
+
+struct grub_env_var
+{
+  char *name;
+  char *value;
+  grub_env_read_hook_t read_hook;
+  grub_env_write_hook_t write_hook;
+  struct grub_env_var *next;
+  struct grub_env_var **prevp;
+  enum grub_env_var_type type;
+};
+
+grub_err_t EXPORT_FUNC(grub_env_set) (const char *name, const char *val);
+char *EXPORT_FUNC(grub_env_get) (const char *name);
+void EXPORT_FUNC(grub_env_unset) (const char *name);
+void EXPORT_FUNC(grub_env_iterate) (int (*func) (struct grub_env_var *var));
+grub_err_t EXPORT_FUNC(grub_register_variable_hook) (const char *name,
+                                                    grub_env_read_hook_t read_hook,
+                                                    grub_env_write_hook_t write_hook);
+grub_err_t EXPORT_FUNC(grub_env_context_open) (void);
+grub_err_t EXPORT_FUNC(grub_env_context_close) (void);
+grub_err_t EXPORT_FUNC(grub_env_export) (const char *name);
+
+grub_err_t EXPORT_FUNC(grub_env_set_data_slot) (const char *name,
+                                               const void *ptr);
+void *EXPORT_FUNC(grub_env_get_data_slot) (const char *name);
+void EXPORT_FUNC(grub_env_unset_data_slot) (const char *name);
+
+#endif /* ! GRUB_ENV_HEADER */
diff --git a/include/grub/err.h b/include/grub/err.h
new file mode 100644 (file)
index 0000000..3435fb7
--- /dev/null
@@ -0,0 +1,71 @@
+/* err.h - error numbers and prototypes */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,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_ERR_HEADER
+#define GRUB_ERR_HEADER        1
+
+#include <grub/symbol.h>
+
+typedef enum
+  {
+    GRUB_ERR_NONE = 0,
+    GRUB_ERR_TEST_FAILURE,
+    GRUB_ERR_BAD_MODULE,
+    GRUB_ERR_OUT_OF_MEMORY,
+    GRUB_ERR_BAD_FILE_TYPE,
+    GRUB_ERR_FILE_NOT_FOUND,
+    GRUB_ERR_FILE_READ_ERROR,
+    GRUB_ERR_BAD_FILENAME,
+    GRUB_ERR_UNKNOWN_FS,
+    GRUB_ERR_BAD_FS,
+    GRUB_ERR_BAD_NUMBER,
+    GRUB_ERR_OUT_OF_RANGE,
+    GRUB_ERR_UNKNOWN_DEVICE,
+    GRUB_ERR_BAD_DEVICE,
+    GRUB_ERR_READ_ERROR,
+    GRUB_ERR_WRITE_ERROR,
+    GRUB_ERR_UNKNOWN_COMMAND,
+    GRUB_ERR_INVALID_COMMAND,
+    GRUB_ERR_BAD_ARGUMENT,
+    GRUB_ERR_BAD_PART_TABLE,
+    GRUB_ERR_UNKNOWN_OS,
+    GRUB_ERR_BAD_OS,
+    GRUB_ERR_NO_KERNEL,
+    GRUB_ERR_BAD_FONT,
+    GRUB_ERR_NOT_IMPLEMENTED_YET,
+    GRUB_ERR_SYMLINK_LOOP,
+    GRUB_ERR_BAD_GZIP_DATA,
+    GRUB_ERR_MENU,
+    GRUB_ERR_TIMEOUT,
+    GRUB_ERR_IO
+  }
+grub_err_t;
+
+extern grub_err_t EXPORT_VAR(grub_errno);
+extern char EXPORT_VAR(grub_errmsg)[];
+
+grub_err_t EXPORT_FUNC(grub_error) (grub_err_t n, const char *fmt, ...);
+void EXPORT_FUNC(grub_fatal) (const char *fmt, ...) __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_error_push) (void);
+int EXPORT_FUNC(grub_error_pop) (void);
+void EXPORT_FUNC(grub_print_error) (void);
+int EXPORT_FUNC(grub_err_printf) (const char *fmt, ...)
+__attribute__ ((format (printf, 1, 2)));
+
+#endif /* ! GRUB_ERR_HEADER */
diff --git a/include/grub/file.h b/include/grub/file.h
new file mode 100644 (file)
index 0000000..df2e9e4
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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_FILE_HEADER
+#define GRUB_FILE_HEADER       1
+
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/device.h>
+#include <grub/fs.h>
+
+/* File description.  */
+struct grub_file
+{
+  /* The underlying device.  */
+  grub_device_t device;
+
+  /* The underlying filesystem.  */
+  grub_fs_t fs;
+
+  /* The current offset.  */
+  grub_off_t offset;
+
+  /* The file size.  */
+  grub_off_t size;
+
+  /* Filesystem-specific data.  */
+  void *data;
+
+  /* This is called when a sector is read. Used only for a disk device.  */
+  void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
+                    unsigned offset, unsigned length);
+};
+typedef struct grub_file *grub_file_t;
+
+/* Get a device name from NAME.  */
+char *EXPORT_FUNC(grub_file_get_device_name) (const char *name);
+
+grub_file_t EXPORT_FUNC(grub_file_open) (const char *name);
+grub_ssize_t EXPORT_FUNC(grub_file_read) (grub_file_t file, char *buf,
+                                         grub_size_t len);
+grub_off_t EXPORT_FUNC(grub_file_seek) (grub_file_t file, grub_off_t offset);
+grub_err_t EXPORT_FUNC(grub_file_close) (grub_file_t file);
+
+static inline grub_off_t
+grub_file_size (const grub_file_t file)
+{
+  return file->size;
+}
+
+static inline grub_off_t
+grub_file_tell (const grub_file_t file)
+{
+  return file->offset;
+}
+
+#endif /* ! GRUB_FILE_HEADER */
diff --git a/include/grub/font.h b/include/grub/font.h
new file mode 100644 (file)
index 0000000..8a5f3ac
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,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_FONT_HEADER
+#define GRUB_FONT_HEADER       1
+
+#include <grub/types.h>
+#include <grub/video.h>
+
+/* Forward declaration of opaque structure grub_font.
+   Users only pass struct grub_font pointers to the font module functions,
+   and do not have knowledge of the structure contents.  */
+struct grub_font;
+
+/* Font type used to access font functions.  */
+typedef struct grub_font *grub_font_t;
+
+struct grub_font_node
+{
+  struct grub_font_node *next;
+  grub_font_t value;
+};
+
+/* Global font registry.  */
+extern struct grub_font_node *grub_font_list;
+
+struct grub_font_glyph
+{
+  /* Reference to the font this glyph belongs to.  */
+  grub_font_t font;
+
+  /* Glyph bitmap width in pixels.  */
+  grub_uint16_t width;
+
+  /* Glyph bitmap height in pixels.  */
+  grub_uint16_t height;
+
+  /* Glyph bitmap x offset in pixels.  Add to screen coordinate.  */
+  grub_int16_t offset_x;
+
+  /* Glyph bitmap y offset in pixels.  Subtract from screen coordinate.  */
+  grub_int16_t offset_y;
+
+  /* Number of pixels to advance to start the next character.  */
+  grub_uint16_t device_width;
+
+  /* Row-major order, packed bits (no padding; rows can break within a byte).
+     The length of the array is (width * height + 7) / 8.  Within a
+     byte, the most significant bit is the first (leftmost/uppermost) pixel.
+     Pixels are coded as bits, value 1 meaning of opaque pixel and 0 is
+     transparent.  If the length of the array does not fit byte boundary, it
+     will be padded with 0 bits to make it fit.  */
+  grub_uint8_t bitmap[0];
+};
+
+/* Initialize the font loader.
+   Must be called before any fonts are loaded or used.  */
+void grub_font_loader_init (void);
+
+/* Load a font and add it to the beginning of the global font list.
+   Returns: 0 upon success; nonzero upon failure.  */
+int grub_font_load (const char *filename);
+
+/* Get the font that has the specified name.  Font names are in the form
+   "Family Name Bold Italic 14", where Bold and Italic are optional.
+   If no font matches the name specified, the most recently loaded font
+   is returned as a fallback.  */
+grub_font_t grub_font_get (const char *font_name);
+
+const char *grub_font_get_name (grub_font_t font);
+
+int grub_font_get_max_char_width (grub_font_t font);
+
+int grub_font_get_max_char_height (grub_font_t font);
+
+int grub_font_get_ascent (grub_font_t font);
+
+int grub_font_get_descent (grub_font_t font);
+
+int grub_font_get_leading (grub_font_t font);
+
+int grub_font_get_height (grub_font_t font);
+
+int grub_font_get_string_width (grub_font_t font, const char *str);
+
+struct grub_font_glyph *grub_font_get_glyph (grub_font_t font,
+                                             grub_uint32_t code);
+
+struct grub_font_glyph *grub_font_get_glyph_with_fallback (grub_font_t font,
+                                                           grub_uint32_t code);
+
+grub_err_t grub_font_draw_glyph (struct grub_font_glyph *glyph,
+                                        grub_video_color_t color,
+                                        int left_x, int baseline_y);
+
+grub_err_t grub_font_draw_string (const char *str, grub_font_t font,
+                                  grub_video_color_t color,
+                                  int left_x, int baseline_y);
+
+#endif /* ! GRUB_FONT_HEADER */
diff --git a/include/grub/fs.h b/include/grub/fs.h
new file mode 100644 (file)
index 0000000..46c7492
--- /dev/null
@@ -0,0 +1,79 @@
+/* fs.h - filesystem manager */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,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_FS_HEADER
+#define GRUB_FS_HEADER 1
+
+#include <grub/device.h>
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+/* Forward declaration is required, because of mutual reference.  */
+struct grub_file;
+
+/* Filesystem descriptor.  */
+struct grub_fs
+{
+  /* My name.  */
+  const char *name;
+
+  /* Call HOOK with each file under DIR.  */
+  grub_err_t (*dir) (grub_device_t device, const char *path,
+                    int (*hook) (const char *filename, int dir));
+  
+  /* Open a file named NAME and initialize FILE.  */
+  grub_err_t (*open) (struct grub_file *file, const char *name);
+  
+  /* Read LEN bytes data from FILE into BUF.  */
+  grub_ssize_t (*read) (struct grub_file *file, char *buf, grub_size_t len);
+  
+  /* Close the file FILE.  */
+  grub_err_t (*close) (struct grub_file *file);
+  
+  /* Return the label of the device DEVICE in LABEL.  The label is
+     returned in a grub_malloc'ed buffer and should be freed by the
+     caller.  */
+  grub_err_t (*label) (grub_device_t device, char **label);
+
+  /* Return the uuid of the device DEVICE in UUID.  The uuid is
+     returned in a grub_malloc'ed buffer and should be freed by the
+     caller.  */
+  grub_err_t (*uuid) (grub_device_t device, char **uuid);
+
+  /* The next filesystem.  */
+  struct grub_fs *next;
+};
+typedef struct grub_fs *grub_fs_t;
+
+/* This is special, because block lists are not files in usual sense.  */
+extern struct grub_fs grub_fs_blocklist;
+
+/* This hook is used to automatically load filesystem modules.
+   If this hook loads a module, return non-zero. Otherwise return zero.
+   The newly loaded filesystem is assumed to be inserted into the head of
+   the linked list GRUB_FS_LIST through the function grub_fs_register.  */
+typedef int (*grub_fs_autoload_hook_t) (void);
+extern grub_fs_autoload_hook_t EXPORT_VAR(grub_fs_autoload_hook);
+
+void EXPORT_FUNC(grub_fs_register) (grub_fs_t fs);
+void EXPORT_FUNC(grub_fs_unregister) (grub_fs_t fs);
+void EXPORT_FUNC(grub_fs_iterate) (int (*hook) (const grub_fs_t fs));
+grub_fs_t EXPORT_FUNC(grub_fs_probe) (grub_device_t device);
+
+#endif /* ! GRUB_FS_HEADER */
diff --git a/include/grub/fshelp.h b/include/grub/fshelp.h
new file mode 100644 (file)
index 0000000..7092cac
--- /dev/null
@@ -0,0 +1,80 @@
+/* fshelp.h -- Filesystem helper functions */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,2005,2006,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_FSHELP_HEADER
+#define GRUB_FSHELP_HEADER     1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/err.h>
+
+typedef struct grub_fshelp_node *grub_fshelp_node_t;
+
+#define GRUB_FSHELP_CASE_INSENSITIVE   0x100
+
+enum grub_fshelp_filetype
+  {
+    GRUB_FSHELP_UNKNOWN,
+    GRUB_FSHELP_REG,
+    GRUB_FSHELP_DIR,
+    GRUB_FSHELP_SYMLINK
+  };
+
+/* Lookup the node PATH.  The node ROOTNODE describes the root of the
+   directory tree.  The node found is returned in FOUNDNODE, which is
+   either a ROOTNODE or a new malloc'ed node.  ITERATE_DIR is used to
+   iterate over all directory entries in the current node.
+   READ_SYMLINK is used to read the symlink if a node is a symlink.
+   EXPECTTYPE is the type node that is expected by the called, an
+   error is generated if the node is not of the expected type.  Make
+   sure you use the NESTED_FUNC_ATTR macro for HOOK, this is required
+   because GCC has a nasty bug when using regparm=3.  */
+grub_err_t
+EXPORT_FUNC(grub_fshelp_find_file) (const char *path,
+                                   grub_fshelp_node_t rootnode,
+                                   grub_fshelp_node_t *foundnode,
+                                   int (*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)),
+                                   char *(*read_symlink) (grub_fshelp_node_t node),
+                                   enum grub_fshelp_filetype expect);
+
+
+/* Read LEN bytes from the file NODE on disk DISK into the buffer BUF,
+   beginning with the block POS.  READ_HOOK should be set before
+   reading a block from the file.  GET_BLOCK is used to translate file
+   blocks to disk blocks.  The file is FILESIZE bytes big and the
+   blocks have a size of LOG2BLOCKSIZE (in log2).  */
+grub_ssize_t
+EXPORT_FUNC(grub_fshelp_read_file) (grub_disk_t disk, grub_fshelp_node_t node,
+                                   void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
+                                                                        unsigned offset,
+                                                                        unsigned length),
+                                   grub_off_t pos, grub_size_t len, char *buf,
+                                   grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
+                                                                   grub_disk_addr_t block),
+                                   grub_off_t filesize, int log2blocksize);
+
+unsigned int
+EXPORT_FUNC(grub_fshelp_log2blksize) (unsigned int blksize,
+                                     unsigned int *pow);
+
+#endif /* ! GRUB_FSHELP_HEADER */
diff --git a/include/grub/gpt_partition.h b/include/grub/gpt_partition.h
new file mode 100644 (file)
index 0000000..0244530
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,2006,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_GPT_PARTITION_HEADER
+#define GRUB_GPT_PARTITION_HEADER      1
+
+#include <grub/types.h>
+
+struct grub_gpt_part_type
+{
+  grub_uint32_t data1;
+  grub_uint16_t data2;
+  grub_uint16_t data3;
+  grub_uint8_t data4[8];
+} __attribute__ ((aligned(8)));
+typedef struct grub_gpt_part_type grub_gpt_part_type_t;
+
+#define GRUB_GPT_PARTITION_TYPE_EMPTY \
+  { 0x0, 0x0, 0x0, \
+    { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } \
+  }
+
+#define GRUB_GPT_PARTITION_TYPE_BIOS_BOOT \
+  { grub_cpu_to_le32 (0x21686148), grub_cpu_to_le16 (0x6449), grub_cpu_to_le16 (0x6e6f), \
+    { 0x74, 0x4e, 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 } \
+  }
+
+struct grub_gpt_header
+{
+  grub_uint8_t magic[8];
+  grub_uint32_t version;
+  grub_uint32_t headersize;
+  grub_uint32_t crc32;
+  grub_uint32_t unused1;
+  grub_uint64_t primary;
+  grub_uint64_t backup;
+  grub_uint64_t start;
+  grub_uint64_t end;
+  grub_uint8_t guid[16];
+  grub_uint64_t partitions;
+  grub_uint32_t maxpart;
+  grub_uint32_t partentry_size;
+  grub_uint32_t partentry_crc32;
+} __attribute__ ((packed));
+
+struct grub_gpt_partentry
+{
+  grub_gpt_part_type_t type;
+  grub_uint8_t guid[16];
+  grub_uint64_t start;
+  grub_uint64_t end;
+  grub_uint8_t attrib;
+  char name[72];
+} __attribute__ ((packed));
+
+#endif /* ! GRUB_GPT_PARTITION_HEADER */
diff --git a/include/grub/gzio.h b/include/grub/gzio.h
new file mode 100644 (file)
index 0000000..cd7f397
--- /dev/null
@@ -0,0 +1,28 @@
+/* gzio.h - prototypes for gzio */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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 GRUB_GZIO_H
+#define GRUB_GZIO_H    1
+
+#include <grub/file.h>
+
+grub_file_t grub_gzio_open (grub_file_t io, int transparent);
+grub_file_t grub_gzfile_open (const char *name, int transparent);
+
+#endif /* ! GRUB_GZIO_H */
diff --git a/include/grub/hfs.h b/include/grub/hfs.h
new file mode 100644 (file)
index 0000000..311b998
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,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_HFS_HEADER
+#define GRUB_HFS_HEADER        1
+
+#include <grub/types.h>
+
+#define GRUB_HFS_MAGIC         0x4244
+
+/* A single extent.  A file consists of one or more extents.  */
+struct grub_hfs_extent
+{
+  /* The first physical block.  */
+  grub_uint16_t first_block;
+  grub_uint16_t count;
+};
+
+/* HFS stores extents in groups of 3.  */
+typedef struct grub_hfs_extent grub_hfs_datarecord_t[3];
+
+/* The HFS superblock (The official name is `Master Directory
+   Block').  */
+struct grub_hfs_sblock
+{
+  grub_uint16_t magic;
+  grub_uint8_t unused[18];
+  grub_uint32_t blksz;
+  grub_uint8_t unused2[4];
+  grub_uint16_t first_block;
+  grub_uint8_t unused4[6];
+
+  /* A pascal style string that holds the volumename.  */
+  grub_uint8_t volname[28];
+  
+  grub_uint8_t unused5[60];
+  grub_uint16_t embed_sig;
+  struct grub_hfs_extent embed_extent;
+  grub_uint8_t unused6[4];
+  grub_hfs_datarecord_t extent_recs;
+  grub_uint32_t catalog_size;
+  grub_hfs_datarecord_t catalog_recs;
+} __attribute__ ((packed));
+
+#endif /* ! GRUB_HFS_HEADER */
diff --git a/include/grub/i386/at_keyboard.h b/include/grub/i386/at_keyboard.h
new file mode 100644 (file)
index 0000000..5c15ef3
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  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 GRUB_CPU_AT_KEYBOARD_HEADER
+#define GRUB_CPU_AT_KEYBOARD_HEADER    1
+
+#include <grub/machine/machine.h>
+
+#define SHIFT_L                0x2a
+#define SHIFT_R                0x36
+#define CTRL           0x1d
+#define ALT            0x38
+#define CAPS_LOCK      0x3a
+
+#define KEYBOARD_REG_DATA      0x60
+#define KEYBOARD_REG_STATUS    0x64
+
+/* Used for sending commands to the controller.  */
+#define KEYBOARD_COMMAND_ISREADY(x)    !((x) & 0x02)
+#define KEYBOARD_COMMAND_READ          0x20
+#define KEYBOARD_COMMAND_WRITE         0x60
+#define KEYBOARD_COMMAND_REBOOT                0xfe
+
+#define KEYBOARD_SCANCODE_SET1         0x40
+
+#define KEYBOARD_ISMAKE(x)     !((x) & 0x80)
+#define KEYBOARD_ISREADY(x)    (((x) & 0x01) == 0)
+#define KEYBOARD_SCANCODE(x)   ((x) & 0x7f)
+
+#ifdef GRUB_MACHINE_IEEE1275
+#define OLPC_UP                GRUB_TERM_UP
+#define OLPC_DOWN      GRUB_TERM_DOWN
+#define OLPC_LEFT      GRUB_TERM_LEFT
+#define OLPC_RIGHT     GRUB_TERM_RIGHT
+#else
+#define OLPC_UP                '\0'
+#define OLPC_DOWN      '\0'
+#define OLPC_LEFT      '\0'
+#define OLPC_RIGHT     '\0'
+#endif
+
+#endif
diff --git a/include/grub/i386/bsd.h b/include/grub/i386/bsd.h
new file mode 100644 (file)
index 0000000..00296c9
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ *  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_BSD_CPU_HEADER
+#define GRUB_BSD_CPU_HEADER    1
+
+#include <grub/types.h>
+
+#define KERNEL_TYPE_NONE       0
+#define KERNEL_TYPE_FREEBSD    1
+#define KERNEL_TYPE_OPENBSD    2
+#define KERNEL_TYPE_NETBSD     3
+
+#define GRUB_BSD_TEMP_BUFFER   0x68000
+
+#define FREEBSD_RB_ASKNAME     (1 << 0)  /* ask for file name to reboot from */
+#define FREEBSD_RB_SINGLE       (1 << 1)  /* reboot to single user only */
+#define FREEBSD_RB_NOSYNC       (1 << 2)  /* dont sync before reboot */
+#define FREEBSD_RB_HALT         (1 << 3)  /* don't reboot, just halt */
+#define FREEBSD_RB_INITNAME     (1 << 4)  /* name given for /etc/init (unused) */
+#define FREEBSD_RB_DFLTROOT     (1 << 5)  /* use compiled-in rootdev */
+#define FREEBSD_RB_KDB          (1 << 6)  /* give control to kernel debugger */
+#define FREEBSD_RB_RDONLY       (1 << 7)  /* mount root fs read-only */
+#define FREEBSD_RB_DUMP         (1 << 8)  /* dump kernel memory before reboot */
+#define FREEBSD_RB_MINIROOT     (1 << 9)  /* mini-root present in memory at boot time */
+#define FREEBSD_RB_CONFIG       (1 << 10) /* invoke user configuration routing */
+#define FREEBSD_RB_VERBOSE      (1 << 11) /* print all potentially useful info */
+#define FREEBSD_RB_SERIAL       (1 << 12) /* user serial port as console */
+#define FREEBSD_RB_CDROM        (1 << 13) /* use cdrom as root */
+#define FREEBSD_RB_GDB         (1 << 15) /* use GDB remote debugger instead of DDB */
+#define FREEBSD_RB_MUTE                (1 << 16) /* Come up with the console muted */
+#define FREEBSD_RB_PAUSE       (1 << 20)
+#define FREEBSD_RB_QUIET       (1 << 21)
+#define FREEBSD_RB_NOINTR      (1 << 28)
+#define FREENSD_RB_MULTIPLE    (1 << 29)  /* Use multiple consoles */
+#define FREEBSD_RB_DUAL                FREENSD_RB_MULTIPLE
+#define FREEBSD_RB_BOOTINFO     (1 << 31) /* have `struct bootinfo *' arg */
+
+#define FREEBSD_B_DEVMAGIC     0xa0000000
+#define FREEBSD_B_SLICESHIFT   20
+#define FREEBSD_B_UNITSHIFT    16
+#define FREEBSD_B_PARTSHIFT    8
+#define FREEBSD_B_TYPESHIFT    0
+
+#define FREEBSD_BOOTINFO_VERSION 1
+#define FREEBSD_N_BIOS_GEOM    8
+
+#define FREEBSD_MODINFO_END            0x0000  /* End of list */
+#define FREEBSD_MODINFO_NAME           0x0001  /* Name of module (string) */
+#define FREEBSD_MODINFO_TYPE           0x0002  /* Type of module (string) */
+#define FREEBSD_MODINFO_ADDR           0x0003  /* Loaded address */
+#define FREEBSD_MODINFO_SIZE           0x0004  /* Size of module */
+#define FREEBSD_MODINFO_EMPTY          0x0005  /* Has been deleted */
+#define FREEBSD_MODINFO_ARGS           0x0006  /* Parameters string */
+#define FREEBSD_MODINFO_METADATA       0x8000  /* Module-specfic */
+
+#define FREEBSD_MODINFOMD_AOUTEXEC     0x0001  /* a.out exec header */
+#define FREEBSD_MODINFOMD_ELFHDR       0x0002  /* ELF header */
+#define FREEBSD_MODINFOMD_SSYM         0x0003  /* start of symbols */
+#define FREEBSD_MODINFOMD_ESYM         0x0004  /* end of symbols */
+#define FREEBSD_MODINFOMD_DYNAMIC      0x0005  /* _DYNAMIC pointer */
+#define FREEBSD_MODINFOMD_ENVP         0x0006  /* envp[] */
+#define FREEBSD_MODINFOMD_HOWTO                0x0007  /* boothowto */
+#define FREEBSD_MODINFOMD_KERNEND      0x0008  /* kernend */
+#define FREEBSD_MODINFOMD_SHDR         0x0009  /* section header table */
+#define FREEBSD_MODINFOMD_NOCOPY       0x8000  /* don't copy this metadata to the kernel */
+
+#define FREEBSD_MODINFOMD_DEPLIST      (0x4001 | FREEBSD_MODINFOMD_NOCOPY)  /* depends on */
+
+#define FREEBSD_MODTYPE_KERNEL         "elf kernel"
+#define FREEBSD_MODTYPE_MODULE         "elf module"
+#define FREEBSD_MODTYPE_RAW            "raw"
+
+struct grub_freebsd_bootinfo
+{
+  grub_uint32_t bi_version;
+  grub_uint8_t *bi_kernelname;
+  struct nfs_diskless *bi_nfs_diskless;
+  grub_uint32_t bi_n_bios_used;
+  grub_uint32_t bi_bios_geom[FREEBSD_N_BIOS_GEOM];
+  grub_uint32_t bi_size;
+  grub_uint8_t bi_memsizes_valid;
+  grub_uint8_t bi_bios_dev;
+  grub_uint8_t bi_pad[2];
+  grub_uint32_t bi_basemem;
+  grub_uint32_t bi_extmem;
+  grub_uint32_t bi_symtab;
+  grub_uint32_t bi_esymtab;
+  grub_uint32_t bi_kernend;
+  grub_uint32_t bi_envp;
+  grub_uint32_t bi_modulep;
+} __attribute__ ((packed));
+
+#define OPENBSD_RB_ASKNAME     (1 << 0)  /* ask for file name to reboot from */
+#define OPENBSD_RB_SINGLE      (1 << 1)  /* reboot to single user only */
+#define OPENBSD_RB_NOSYNC      (1 << 2)  /* dont sync before reboot */
+#define OPENBSD_RB_HALT                (1 << 3)  /* don't reboot, just halt */
+#define OPENBSD_RB_INITNAME    (1 << 4)  /* name given for /etc/init (unused) */
+#define OPENBSD_RB_DFLTROOT    (1 << 5)  /* use compiled-in rootdev */
+#define OPENBSD_RB_KDB         (1 << 6)  /* give control to kernel debugger */
+#define OPENBSD_RB_RDONLY      (1 << 7)  /* mount root fs read-only */
+#define OPENBSD_RB_DUMP                (1 << 8)  /* dump kernel memory before reboot */
+#define OPENBSD_RB_MINIROOT    (1 << 9)  /* mini-root present in memory at boot time */
+#define OPENBSD_RB_CONFIG      (1 << 10) /* change configured devices */
+#define OPENBSD_RB_TIMEBAD     (1 << 11) /* don't call resettodr() in boot() */
+#define OPENBSD_RB_POWERDOWN   (1 << 12) /* attempt to power down machine */
+#define OPENBSD_RB_SERCONS     (1 << 13) /* use serial console if available */
+#define OPENBSD_RB_USERREQ     (1 << 14) /* boot() called at user request (e.g. ddb) */
+
+#define OPENBSD_B_DEVMAGIC     0xa0000000
+#define OPENBSD_B_ADAPTORSHIFT 24
+#define OPENBSD_B_CTRLSHIFT    20
+#define OPENBSD_B_UNITSHIFT    16
+#define OPENBSD_B_PARTSHIFT    8
+#define OPENBSD_B_TYPESHIFT    0
+
+#define OPENBSD_BOOTARG_APIVER (OPENBSD_BAPIV_VECTOR | \
+                                 OPENBSD_BAPIV_ENV | \
+                                 OPENBSD_BAPIV_BMEMMAP)
+
+#define OPENBSD_BAPIV_ANCIENT  0x0  /* MD old i386 bootblocks */
+#define OPENBSD_BAPIV_VARS     0x1  /* MD structure w/ add info passed */
+#define OPENBSD_BAPIV_VECTOR   0x2  /* MI vector of MD structures passed */
+#define OPENBSD_BAPIV_ENV      0x4  /* MI environment vars vector */
+#define OPENBSD_BAPIV_BMEMMAP  0x8  /* MI memory map passed is in bytes */
+
+#define OPENBSD_BOOTARG_ENV    0x1000
+#define OPENBSD_BOOTARG_END    -1
+
+#define        OPENBSD_BOOTARG_MMAP    0
+
+struct grub_openbsd_bios_mmap
+{
+  grub_uint64_t addr;
+  grub_uint64_t len;
+  grub_uint32_t type;
+};
+
+struct grub_openbsd_bootargs
+{
+  int ba_type;
+  int ba_size;
+  struct grub_openbsd_bootargs *ba_next;
+} __attribute__ ((packed));
+
+#define NETBSD_RB_AUTOBOOT     0  /* flags for system auto-booting itself */
+
+#define NETBSD_RB_ASKNAME      (1 << 0)  /* ask for file name to reboot from */
+#define NETBSD_RB_SINGLE       (1 << 1)  /* reboot to single user only */
+#define NETBSD_RB_NOSYNC       (1 << 2)  /* dont sync before reboot */
+#define NETBSD_RB_HALT         (1 << 3)  /* don't reboot, just halt */
+#define NETBSD_RB_INITNAME     (1 << 4)  /* name given for /etc/init (unused) */
+#define NETBSD_RB_UNUSED1      (1 << 5)  /* was RB_DFLTROOT, obsolete */
+#define NETBSD_RB_KDB          (1 << 6)  /* give control to kernel debugger */
+#define NETBSD_RB_RDONLY       (1 << 7)  /* mount root fs read-only */
+#define NETBSD_RB_DUMP         (1 << 8)  /* dump kernel memory before reboot */
+#define NETBSD_RB_MINIROOT     (1 << 9)  /* mini-root present in memory at boot time */
+#define NETBSD_RB_STRING       (1 << 10) /* use provided bootstr */
+#define NETBSD_RB_POWERDOWN     ((1 << 11) | RB_HALT) /* turn power off (or at least halt) */
+#define NETBSD_RB_USERCONFIG   (1 << 12) /* change configured devices */
+
+#define NETBSD_AB_NORMAL       0  /* boot normally (default) */
+
+#define NETBSD_AB_QUIET                (1 << 16) /* boot quietly */
+#define NETBSD_AB_VERBOSE      (1 << 17) /* boot verbosely */
+#define NETBSD_AB_SILENT       (1 << 18) /* boot silently */
+#define NETBSD_AB_DEBUG                (1 << 19) /* boot with debug messages */
+
+struct grub_netbsd_bootinfo
+{
+  grub_uint32_t bi_count;
+  void *bi_data[1];
+};
+
+#define NETBSD_BTINFO_BOOTPATH         0
+#define NETBSD_BTINFO_ROOTDEVICE       1
+#define NETBSD_BTINFO_BOOTDISK         3
+
+struct grub_netbsd_btinfo_common
+{
+  int len;
+  int type;
+};
+
+struct grub_netbsd_btinfo_bootpath
+{
+  struct grub_netbsd_btinfo_common common;
+  char bootpath[80];
+};
+
+struct grub_netbsd_btinfo_rootdevice
+{
+  struct grub_netbsd_btinfo_common common;
+  char devname[16];
+};
+
+struct grub_netbsd_btinfo_bootdisk
+{
+  struct grub_netbsd_btinfo_common common;
+  int labelsector;  /* label valid if != -1 */
+  struct
+    {
+      grub_uint16_t type, checksum;
+      char packname[16];
+    } label;
+  int biosdev;
+  int partition;
+};
+
+void grub_rescue_cmd_freebsd (int argc, char *argv[]);
+void grub_rescue_cmd_openbsd (int argc, char *argv[]);
+void grub_rescue_cmd_netbsd (int argc, char *argv[]);
+
+void grub_rescue_cmd_freebsd_loadenv (int argc, char *argv[]);
+void grub_rescue_cmd_freebsd_module (int argc, char *argv[]);
+
+#endif /* ! GRUB_BSD_CPU_HEADER */
diff --git a/include/grub/i386/cmos.h b/include/grub/i386/cmos.h
new file mode 100644 (file)
index 0000000..1c0530d
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ *  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/i386/io.h>
+
+#define GRUB_CMOS_ADDR_REG     0x70
+#define GRUB_CMOS_DATA_REG     0x71
+
+#define GRUB_CMOS_INDEX_SECOND         0
+#define GRUB_CMOS_INDEX_SECOND_ALARM   1
+#define GRUB_CMOS_INDEX_MINUTE         2
+#define GRUB_CMOS_INDEX_MINUTE_ALARM   3
+#define GRUB_CMOS_INDEX_HOUR           4
+#define GRUB_CMOS_INDEX_HOUR_ALARM     5
+#define GRUB_CMOS_INDEX_DAY_OF_WEEK    6
+#define GRUB_CMOS_INDEX_DAY_OF_MONTH   7
+#define GRUB_CMOS_INDEX_MONTH          8
+#define GRUB_CMOS_INDEX_YEAR           9
+
+#define GRUB_CMOS_INDEX_STATUS_A       0xA
+#define GRUB_CMOS_INDEX_STATUS_B       0xB
+#define GRUB_CMOS_INDEX_STATUS_C       0xC
+#define GRUB_CMOS_INDEX_STATUS_D       0xD
+
+#define GRUB_CMOS_STATUS_B_DAYLIGHT    1
+#define GRUB_CMOS_STATUS_B_24HOUR      2
+#define GRUB_CMOS_STATUS_B_BINARY      4
+
+static inline grub_uint8_t
+grub_bcd_to_num (grub_uint8_t a)
+{
+  return ((a >> 4) * 10 + (a & 0xF));
+}
+
+static inline grub_uint8_t
+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)
+{
+  grub_outb (index, GRUB_CMOS_ADDR_REG);
+  return grub_inb (GRUB_CMOS_DATA_REG);
+}
+
+static inline void
+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);
+}
+
+#endif /* GRUB_CPU_CMOS_H */
diff --git a/include/grub/i386/coreboot/boot.h b/include/grub/i386/coreboot/boot.h
new file mode 100644 (file)
index 0000000..6cd23aa
--- /dev/null
@@ -0,0 +1 @@
+#include <grub/i386/pc/boot.h>
diff --git a/include/grub/i386/coreboot/console.h b/include/grub/i386/coreboot/console.h
new file mode 100644 (file)
index 0000000..305a46d
--- /dev/null
@@ -0,0 +1 @@
+#include <grub/i386/pc/console.h>
diff --git a/include/grub/i386/coreboot/init.h b/include/grub/i386/coreboot/init.h
new file mode 100644 (file)
index 0000000..e670074
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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_INIT_I386_LINUXBIOS_HEADER
+#define GRUB_INIT_I386_LINUXBIOS_HEADER                1
+
+#include <grub/symbol.h>
+#include <grub/i386/pc/memory.h>
+
+void EXPORT_FUNC(grub_stop) (void) __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_stop_floppy) (void);
+
+#endif
diff --git a/include/grub/i386/coreboot/kernel.h b/include/grub/i386/coreboot/kernel.h
new file mode 100644 (file)
index 0000000..fb60668
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2006,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_KERNEL_MACHINE_HEADER
+#define GRUB_KERNEL_MACHINE_HEADER     1
+
+#include <grub/symbol.h>
+
+#ifndef ASM_FILE
+extern char grub_prefix[];
+#endif
+
+#endif /* ! GRUB_KERNEL_MACHINE_HEADER */
diff --git a/include/grub/i386/coreboot/loader.h b/include/grub/i386/coreboot/loader.h
new file mode 100644 (file)
index 0000000..d3f36bb
--- /dev/null
@@ -0,0 +1 @@
+#include <grub/cpu/loader.h>
diff --git a/include/grub/i386/coreboot/machine.h b/include/grub/i386/coreboot/machine.h
new file mode 100644 (file)
index 0000000..3f278ed
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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_MACHINE_MACHINE_HEADER
+#define GRUB_MACHINE_MACHINE_HEADER    1
+
+#define GRUB_MACHINE_LINUXBIOS 1
+
+#endif /* ! GRUB_MACHINE_MACHINE_HEADER */
diff --git a/include/grub/i386/coreboot/memory.h b/include/grub/i386/coreboot/memory.h
new file mode 100644 (file)
index 0000000..434ae62
--- /dev/null
@@ -0,0 +1,70 @@
+/* memory.h - describe the memory map */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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_MEMORY_MACHINE_LB_HEADER
+#define _GRUB_MEMORY_MACHINE_LB_HEADER      1
+
+#include <grub/symbol.h>
+#include <grub/i386/pc/memory.h>
+
+#ifndef ASM_FILE
+#include <grub/err.h>
+#include <grub/types.h>
+#endif
+
+#define GRUB_MEMORY_MACHINE_LOWER_USABLE               0x9fc00         /* 640 kiB - 1 kiB */
+
+#define GRUB_MEMORY_MACHINE_UPPER_START                        0x100000        /* 1 MiB */
+#define GRUB_MEMORY_MACHINE_LOWER_SIZE                 GRUB_MEMORY_MACHINE_UPPER_START
+
+#ifndef ASM_FILE
+
+struct grub_linuxbios_table_header
+{
+  char signature[4];
+  grub_uint32_t size;
+};
+typedef struct grub_linuxbios_table_header *grub_linuxbios_table_header_t;
+
+struct grub_linuxbios_table_item
+{
+#define GRUB_LINUXBIOS_MEMBER_UNUSED           0
+#define GRUB_LINUXBIOS_MEMBER_MEMORY           1
+  grub_uint32_t tag;
+  grub_uint32_t size;
+};
+typedef struct grub_linuxbios_table_item *grub_linuxbios_table_item_t;
+
+struct grub_linuxbios_mem_region
+{
+  grub_uint64_t addr;
+  grub_uint64_t size;
+#define GRUB_MACHINE_MEMORY_AVAILABLE          1
+  grub_uint32_t type;
+};
+typedef struct grub_linuxbios_mem_region *mem_region_t;
+
+void grub_machine_mmap_init (void);
+
+grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate)
+     (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
+
+#endif
+
+#endif /* ! _GRUB_MEMORY_MACHINE_HEADER */
diff --git a/include/grub/i386/coreboot/serial.h b/include/grub/i386/coreboot/serial.h
new file mode 100644 (file)
index 0000000..2c527f6
--- /dev/null
@@ -0,0 +1 @@
+#include <grub/i386/pc/serial.h>
diff --git a/include/grub/i386/coreboot/time.h b/include/grub/i386/coreboot/time.h
new file mode 100644 (file)
index 0000000..2298ee8
--- /dev/null
@@ -0,0 +1 @@
+#include <grub/i386/pc/time.h>
diff --git a/include/grub/i386/efi/kernel.h b/include/grub/i386/efi/kernel.h
new file mode 100644 (file)
index 0000000..c0549f4
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,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_MACHINE_KERNEL_HEADER
+#define GRUB_MACHINE_KERNEL_HEADER   1
+
+/* The prefix which points to the directory where GRUB modules and its
+   configuration file are located.  */
+extern char grub_prefix[];
+
+/* The offset of GRUB_PREFIX.  */
+#define GRUB_KERNEL_MACHINE_PREFIX             0x8
+
+/* End of the data section. */
+#define GRUB_KERNEL_MACHINE_DATA_END           0x50
+
+#endif /* ! GRUB_MACHINE_KERNEL_HEADER */
+
diff --git a/include/grub/i386/efi/loader.h b/include/grub/i386/efi/loader.h
new file mode 100644 (file)
index 0000000..3308be0
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,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_LOADER_MACHINE_HEADER
+#define GRUB_LOADER_MACHINE_HEADER     1
+
+/* It is necessary to export these functions, because normal mode commands
+   reuse rescue mode commands.  */
+void grub_rescue_cmd_linux (int argc, char *argv[]);
+void grub_rescue_cmd_initrd (int argc, char *argv[]);
+
+#endif /* ! GRUB_LOADER_MACHINE_HEADER */
diff --git a/include/grub/i386/efi/machine.h b/include/grub/i386/efi/machine.h
new file mode 100644 (file)
index 0000000..1600768
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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_MACHINE_MACHINE_HEADER
+#define GRUB_MACHINE_MACHINE_HEADER    1
+
+#define GRUB_MACHINE_EFI       1
+
+#endif /* ! GRUB_MACHINE_MACHINE_HEADER */
diff --git a/include/grub/i386/efi/time.h b/include/grub/i386/efi/time.h
new file mode 100644 (file)
index 0000000..7a9241f
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  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_MACHINE_TIME_HEADER
+#define GRUB_MACHINE_TIME_HEADER       1
+
+#include <grub/efi/time.h>
+
+#endif /* ! GRUB_MACHINE_TIME_HEADER */
diff --git a/include/grub/i386/halt.h b/include/grub/i386/halt.h
new file mode 100644 (file)
index 0000000..1c403a7
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  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/>.
+ */
+
+extern void grub_halt (void);
diff --git a/include/grub/i386/ieee1275/console.h b/include/grub/i386/ieee1275/console.h
new file mode 100644 (file)
index 0000000..854724a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  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 (void);
+
+/* Finish the console system.  */
+void grub_console_fini (void);
+
+#endif /* ! GRUB_CONSOLE_MACHINE_HEADER */
diff --git a/include/grub/i386/ieee1275/ieee1275.h b/include/grub/i386/ieee1275/ieee1275.h
new file mode 100644 (file)
index 0000000..2625f02
--- /dev/null
@@ -0,0 +1 @@
+#include <grub/powerpc/ieee1275/ieee1275.h>
diff --git a/include/grub/i386/ieee1275/kernel.h b/include/grub/i386/ieee1275/kernel.h
new file mode 100644 (file)
index 0000000..dccf8cb
--- /dev/null
@@ -0,0 +1 @@
+#include <grub/powerpc/ieee1275/kernel.h>
diff --git a/include/grub/i386/ieee1275/loader.h b/include/grub/i386/ieee1275/loader.h
new file mode 100644 (file)
index 0000000..942242b
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,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_LOADER_MACHINE_HEADER
+#define GRUB_LOADER_MACHINE_HEADER     1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/multiboot.h>
+
+void EXPORT_FUNC(grub_multiboot2_real_boot) (grub_addr_t entry,
+                                             struct grub_multiboot_info *mbi)
+     __attribute__ ((noreturn));
+
+void grub_rescue_cmd_linux (int argc, char *argv[]);
+void grub_rescue_cmd_initrd (int argc, char *argv[]);
+
+#endif /* ! GRUB_LOADER_MACHINE_HEADER */
diff --git a/include/grub/i386/ieee1275/machine.h b/include/grub/i386/ieee1275/machine.h
new file mode 100644 (file)
index 0000000..755eb33
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  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_MACHINE_HEADER
+#define GRUB_MACHINE_MACHINE_HEADER    1
+
+#define GRUB_MACHINE_IEEE1275  1
+
+#endif /* ! GRUB_MACHINE_MACHINE_HEADER */
diff --git a/include/grub/i386/ieee1275/memory.h b/include/grub/i386/ieee1275/memory.h
new file mode 100644 (file)
index 0000000..386ee4a
--- /dev/null
@@ -0,0 +1 @@
+#include <grub/i386/pc/memory.h>
diff --git a/include/grub/i386/ieee1275/serial.h b/include/grub/i386/ieee1275/serial.h
new file mode 100644 (file)
index 0000000..2c527f6
--- /dev/null
@@ -0,0 +1 @@
+#include <grub/i386/pc/serial.h>
diff --git a/include/grub/i386/ieee1275/time.h b/include/grub/i386/ieee1275/time.h
new file mode 100644 (file)
index 0000000..6f474ba
--- /dev/null
@@ -0,0 +1 @@
+#include <grub/powerpc/ieee1275/time.h>
diff --git a/include/grub/i386/io.h b/include/grub/i386/io.h
new file mode 100644 (file)
index 0000000..0e56776
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1996,2000,2002,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/>.
+ */
+
+/* Based on sys/io.h from GNU libc. */
+
+#ifndef        GRUB_IO_H
+#define        GRUB_IO_H       1
+
+static __inline unsigned char
+grub_inb (unsigned short int port)
+{
+  unsigned char _v;
+
+  __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (port));
+  return _v;
+}
+
+static __inline unsigned short int
+grub_inw (unsigned short int port)
+{
+  unsigned short _v;
+
+  __asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (port));
+  return _v;
+}
+
+static __inline unsigned int
+grub_inl (unsigned short int port)
+{
+  unsigned int _v;
+
+  __asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (port));
+  return _v;
+}
+
+static __inline void
+grub_outb (unsigned char value, unsigned short int port)
+{
+  __asm__ __volatile__ ("outb %b0,%w1": :"a" (value), "Nd" (port));
+}
+
+static __inline void
+grub_outw (unsigned short int value, unsigned short int port)
+{
+  __asm__ __volatile__ ("outw %w0,%w1": :"a" (value), "Nd" (port));
+
+}
+
+static __inline void
+grub_outl (unsigned int value, unsigned short int port)
+{
+  __asm__ __volatile__ ("outl %0,%w1": :"a" (value), "Nd" (port));
+}
+
+#endif /* _SYS_IO_H */
diff --git a/include/grub/i386/kernel.h b/include/grub/i386/kernel.h
new file mode 100644 (file)
index 0000000..0dfab05
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2006,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_KERNEL_CPU_HEADER
+#define GRUB_KERNEL_CPU_HEADER 1
+
+#define GRUB_MOD_ALIGN 0x1000
+
+/* Non-zero value is only needed for PowerMacs.  */
+#define GRUB_MOD_GAP 0x0
+
+#define GRUB_KERNEL_CPU_PREFIX 0x2
+#define GRUB_KERNEL_CPU_DATA_END       0x42
+
+#endif
diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
new file mode 100644 (file)
index 0000000..d5b5207
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,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_LINUX_MACHINE_HEADER
+#define GRUB_LINUX_MACHINE_HEADER      1
+
+#define GRUB_LINUX_MAGIC_SIGNATURE     0x53726448      /* "HdrS" */
+#define GRUB_LINUX_DEFAULT_SETUP_SECTS 4
+#define GRUB_LINUX_FLAG_CAN_USE_HEAP   0x80
+#define GRUB_LINUX_INITRD_MAX_ADDRESS  0x37FFFFFF
+#define GRUB_LINUX_MAX_SETUP_SECTS     64
+#define GRUB_LINUX_BOOT_LOADER_TYPE    0x72
+#define GRUB_LINUX_HEAP_END_OFFSET     (0x9000 - 0x200)
+
+#define GRUB_LINUX_BZIMAGE_ADDR                0x100000
+#define GRUB_LINUX_ZIMAGE_ADDR         0x10000
+#define GRUB_LINUX_OLD_REAL_MODE_ADDR  0x90000
+#define GRUB_LINUX_SETUP_STACK         0x9000
+
+#define GRUB_LINUX_FLAG_BIG_KERNEL     0x1
+
+/* Linux's video mode selection support. Actually I hate it!  */
+#define GRUB_LINUX_VID_MODE_NORMAL     0xFFFF
+#define GRUB_LINUX_VID_MODE_EXTENDED   0xFFFE
+#define GRUB_LINUX_VID_MODE_ASK                0xFFFD
+
+#define GRUB_LINUX_SETUP_MOVE_SIZE     0x9100
+#define GRUB_LINUX_CL_MAGIC            0xA33F
+
+#ifdef __x86_64__
+
+#define GRUB_LINUX_EFI_SIGNATURE       \
+  ('4' << 24 | '6' << 16 | 'L' << 8 | 'E')
+
+#else
+
+#define GRUB_LINUX_EFI_SIGNATURE       \
+  ('2' << 24 | '3' << 16 | 'L' << 8 | 'E')
+
+#endif
+
+#define GRUB_LINUX_EFI_SIGNATURE_0204  \
+  ('L' << 24 | 'I' << 16 | 'F' << 8 | 'E')
+
+#define GRUB_LINUX_OFW_SIGNATURE       \
+  (' ' << 24 | 'W' << 16 | 'F' << 8 | 'O')
+
+#ifndef ASM_FILE
+
+#define GRUB_E820_RAM        1
+#define GRUB_E820_RESERVED   2
+#define GRUB_E820_ACPI       3
+#define GRUB_E820_NVS        4
+#define GRUB_E820_EXEC_CODE  5
+
+#define GRUB_E820_MAX_ENTRY  128
+
+struct grub_e820_mmap
+{
+  grub_uint64_t addr;
+  grub_uint64_t size;
+  grub_uint32_t type;
+} __attribute__((packed));
+
+#define GRUB_VIDEO_TYPE_VLFB   0x23    /* VESA VGA in graphic mode     */
+#define GRUB_VIDEO_TYPE_EFI    0x70
+
+/* For the Linux/i386 boot protocol version 2.03.  */
+struct linux_kernel_header
+{ 
+  grub_uint8_t code1[0x0020];
+  grub_uint16_t cl_magic;              /* Magic number 0xA33F */
+  grub_uint16_t cl_offset;             /* The offset of command line */
+  grub_uint8_t code2[0x01F1 - 0x0020 - 2 - 2];
+  grub_uint8_t setup_sects;            /* The size of the setup in sectors */
+  grub_uint16_t root_flags;            /* If the root is mounted readonly */
+  grub_uint16_t syssize;               /* obsolete */
+  grub_uint16_t swap_dev;              /* obsolete */
+  grub_uint16_t ram_size;              /* obsolete */
+  grub_uint16_t vid_mode;              /* Video mode control */
+  grub_uint16_t root_dev;              /* Default root device number */
+  grub_uint16_t boot_flag;             /* 0xAA55 magic number */
+  grub_uint16_t jump;                  /* Jump instruction */
+  grub_uint32_t header;                        /* Magic signature "HdrS" */
+  grub_uint16_t version;               /* Boot protocol version supported */
+  grub_uint32_t realmode_swtch;                /* Boot loader hook */
+  grub_uint16_t start_sys;             /* The load-low segment (obsolete) */
+  grub_uint16_t kernel_version;                /* Points to kernel version string */
+  grub_uint8_t type_of_loader;         /* Boot loader identifier */
+#define LINUX_LOADER_ID_LILO           0x0
+#define LINUX_LOADER_ID_LOADLIN                0x1
+#define LINUX_LOADER_ID_BOOTSECT       0x2
+#define LINUX_LOADER_ID_SYSLINUX       0x3
+#define LINUX_LOADER_ID_ETHERBOOT      0x4
+#define LINUX_LOADER_ID_ELILO          0x5
+#define LINUX_LOADER_ID_GRUB           0x7
+#define LINUX_LOADER_ID_UBOOT          0x8
+#define LINUX_LOADER_ID_XEN            0x9
+#define LINUX_LOADER_ID_GUJIN          0xa
+#define LINUX_LOADER_ID_QEMU           0xb
+  grub_uint8_t loadflags;              /* Boot protocol option flags */
+  grub_uint16_t setup_move_size;       /* Move to high memory size */
+  grub_uint32_t code32_start;          /* Boot loader hook */
+  grub_uint32_t ramdisk_image;         /* initrd load address */
+  grub_uint32_t ramdisk_size;          /* initrd size */
+  grub_uint32_t bootsect_kludge;       /* obsolete */
+  grub_uint16_t heap_end_ptr;          /* Free memory after setup end */
+  grub_uint16_t pad1;                  /* Unused */
+  char *cmd_line_ptr;                  /* Points to the kernel command line */
+  grub_uint32_t initrd_addr_max;        /* Highest address for initrd */
+} __attribute__ ((packed));
+
+/* Boot parameters for Linux based on 2.6.12. This is used by the setup
+   sectors of Linux, and must be simulated by GRUB on EFI, because
+   the setup sectors depend on BIOS.  */
+struct linux_kernel_params
+{
+  grub_uint8_t video_cursor_x;         /* 0 */
+  grub_uint8_t video_cursor_y;
+
+  grub_uint16_t ext_mem;               /* 2 */
+  
+  grub_uint16_t video_page;            /* 4 */
+  grub_uint8_t video_mode;             /* 6 */
+  grub_uint8_t video_width;            /* 7 */
+  
+  grub_uint8_t padding1[0xa - 0x8];
+  
+  grub_uint16_t video_ega_bx;          /* a */
+  
+  grub_uint8_t padding2[0xe - 0xc];
+  
+  grub_uint8_t video_height;           /* e */
+  grub_uint8_t have_vga;               /* f */
+  grub_uint16_t font_size;             /* 10 */
+  
+  grub_uint16_t lfb_width;             /* 12 */
+  grub_uint16_t lfb_height;            /* 14 */
+  grub_uint16_t lfb_depth;             /* 16 */
+  grub_uint32_t lfb_base;              /* 18 */
+  grub_uint32_t lfb_size;              /* 1c */
+
+  grub_uint16_t cl_magic;              /* 20 */
+  grub_uint16_t cl_offset;
+
+  grub_uint16_t lfb_line_len;          /* 24 */
+  grub_uint8_t red_mask_size;          /* 26 */
+  grub_uint8_t red_field_pos;
+  grub_uint8_t green_mask_size;
+  grub_uint8_t green_field_pos;
+  grub_uint8_t blue_mask_size;
+  grub_uint8_t blue_field_pos;
+  grub_uint8_t reserved_mask_size;
+  grub_uint8_t reserved_field_pos;
+  grub_uint16_t vesapm_segment;                /* 2e */
+  grub_uint16_t vesapm_offset;         /* 30 */
+  grub_uint16_t lfb_pages;             /* 32 */
+  grub_uint16_t vesa_attrib;           /* 34 */
+
+  grub_uint8_t padding3[0x40 - 0x36];
+
+  grub_uint16_t apm_version;           /* 40 */
+  grub_uint16_t apm_code_segment;      /* 42 */
+  grub_uint32_t apm_entry;             /* 44 */
+  grub_uint16_t apm_16bit_code_segment;        /* 48 */
+  grub_uint16_t apm_data_segment;      /* 4a */
+  grub_uint16_t apm_flags;             /* 4c */
+  grub_uint32_t apm_code_len;          /* 4e */
+  grub_uint16_t apm_data_len;          /* 52 */
+  
+  grub_uint8_t padding4[0x60 - 0x54];
+  
+  grub_uint32_t ist_signature;         /* 60 */
+  grub_uint32_t ist_command;           /* 64 */
+  grub_uint32_t ist_event;             /* 68 */
+  grub_uint32_t ist_perf_level;                /* 6c */
+
+  grub_uint8_t padding5[0x80 - 0x70];
+  
+  grub_uint8_t hd0_drive_info[0x10];   /* 80 */
+  grub_uint8_t hd1_drive_info[0x10];   /* 90 */
+  grub_uint16_t rom_config_len;                /* a0 */
+
+  grub_uint8_t padding6[0xb0 - 0xa2];
+
+  grub_uint32_t ofw_signature;         /* b0 */
+  grub_uint32_t ofw_num_items;         /* b4 */
+  grub_uint32_t ofw_cif_handler;       /* b8 */
+  grub_uint32_t ofw_idt;               /* bc */
+
+  grub_uint8_t padding7[0x1b8 - 0xc0];
+
+  union
+    {
+      struct
+        {
+          grub_uint32_t efi_system_table;      /* 1b8 */
+          grub_uint32_t padding7_1;            /* 1bc */
+          grub_uint32_t efi_signature;         /* 1c0 */
+          grub_uint32_t efi_mem_desc_size;     /* 1c4 */
+          grub_uint32_t efi_mem_desc_version;  /* 1c8 */
+          grub_uint32_t efi_mmap_size;         /* 1cc */
+          grub_uint32_t efi_mmap;              /* 1d0 */
+        } v0204;
+      struct
+        {
+          grub_uint32_t padding7_1;            /* 1b8 */
+          grub_uint32_t padding7_2;            /* 1bc */
+          grub_uint32_t efi_signature;         /* 1c0 */
+          grub_uint32_t efi_system_table;      /* 1c4 */
+          grub_uint32_t efi_mem_desc_size;     /* 1c8 */
+          grub_uint32_t efi_mem_desc_version;  /* 1cc */
+          grub_uint32_t efi_mmap;              /* 1d0 */
+          grub_uint32_t efi_mmap_size;         /* 1d4 */
+          grub_uint32_t efi_system_table_hi;   /* 1d8 */
+          grub_uint32_t efi_mmap_hi;           /* 1dc */
+        } v0206;
+    };
+  
+  grub_uint32_t alt_mem;               /* 1e0 */
+  
+  grub_uint8_t padding8[0x1e8 - 0x1e4];
+  
+  grub_uint32_t mmap_size;             /* 1e8 */
+
+  grub_uint8_t padding9[0x1f1 - 0x1ec];
+  
+  grub_uint8_t setup_sects;            /* The size of the setup in sectors */
+  grub_uint16_t root_flags;            /* If the root is mounted readonly */
+  grub_uint16_t syssize;               /* obsolete */
+  grub_uint16_t swap_dev;              /* obsolete */
+  grub_uint16_t ram_size;              /* obsolete */
+  grub_uint16_t vid_mode;              /* Video mode control */
+  grub_uint16_t root_dev;              /* Default root device number */
+
+  grub_uint8_t padding10;              /* 1fe */
+  grub_uint8_t ps_mouse;               /* 1ff */
+
+  grub_uint16_t jump;                  /* Jump instruction */
+  grub_uint32_t header;                        /* Magic signature "HdrS" */
+  grub_uint16_t version;               /* Boot protocol version supported */
+  grub_uint32_t realmode_swtch;                /* Boot loader hook */
+  grub_uint16_t start_sys;             /* The load-low segment (obsolete) */
+  grub_uint16_t kernel_version;                /* Points to kernel version string */
+  grub_uint8_t type_of_loader;         /* Boot loader identifier */
+  grub_uint8_t loadflags;              /* Boot protocol option flags */
+  grub_uint16_t setup_move_size;       /* Move to high memory size */
+  grub_uint32_t code32_start;          /* Boot loader hook */
+  grub_uint32_t ramdisk_image;         /* initrd load address */
+  grub_uint32_t ramdisk_size;          /* initrd size */
+  grub_uint32_t bootsect_kludge;       /* obsolete */
+  grub_uint16_t heap_end_ptr;          /* Free memory after setup end */
+  grub_uint16_t pad1;                  /* Unused */
+  grub_uint32_t cmd_line_ptr;          /* Points to the kernel command line */
+
+  grub_uint8_t pad2[164];              /* 22c */
+  struct grub_e820_mmap e820_map[GRUB_E820_MAX_ENTRY]; /* 2d0 */
+
+} __attribute__ ((packed));
+#endif /* ! ASM_FILE */
+
+#endif /* ! GRUB_LINUX_MACHINE_HEADER */
diff --git a/include/grub/i386/loader.h b/include/grub/i386/loader.h
new file mode 100644 (file)
index 0000000..9673e82
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,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_LOADER_CPU_HEADER
+#define GRUB_LOADER_CPU_HEADER 1
+
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/symbol.h>
+#include <grub/multiboot.h>
+
+extern grub_uint32_t EXPORT_VAR(grub_linux_prot_size);
+extern char *EXPORT_VAR(grub_linux_tmp_addr);
+extern char *EXPORT_VAR(grub_linux_real_addr);
+extern grub_int32_t EXPORT_VAR(grub_linux_is_bzimage);
+extern grub_addr_t EXPORT_VAR(grub_os_area_addr);
+extern grub_size_t EXPORT_VAR(grub_os_area_size);
+
+grub_err_t EXPORT_FUNC(grub_linux_boot) (void);
+
+/* The asm part of the multiboot loader.  */
+void EXPORT_FUNC(grub_multiboot_real_boot) (grub_addr_t entry,
+                                           struct grub_multiboot_info *mbi)
+     __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_multiboot2_real_boot) (grub_addr_t entry,
+                                             struct grub_multiboot_info *mbi)
+     __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_unix_real_boot) (grub_addr_t entry, ...)
+     __attribute__ ((cdecl,noreturn));
+
+extern grub_addr_t EXPORT_VAR(grub_multiboot_payload_orig);
+extern grub_addr_t EXPORT_VAR(grub_multiboot_payload_dest);
+extern grub_size_t EXPORT_VAR(grub_multiboot_payload_size);
+extern grub_uint32_t EXPORT_VAR(grub_multiboot_payload_entry_offset);
+
+/* It is necessary to export these functions, because normal mode commands
+   reuse rescue mode commands.  */
+void grub_rescue_cmd_linux (int argc, char *argv[]);
+void grub_rescue_cmd_initrd (int argc, char *argv[]);
+
+extern grub_uint8_t EXPORT_VAR(grub_multiboot_forward_relocator);
+extern grub_uint8_t EXPORT_VAR(grub_multiboot_forward_relocator_end);
+extern grub_uint8_t EXPORT_VAR(grub_multiboot_backward_relocator);
+extern grub_uint8_t EXPORT_VAR(grub_multiboot_backward_relocator_end);
+
+#define RELOCATOR_SIZEOF(x)    (&grub_multiboot_##x##_relocator_end - &grub_multiboot_##x##_relocator)
+
+#endif /* ! GRUB_LOADER_CPU_HEADER */
diff --git a/include/grub/i386/pc/biosdisk.h b/include/grub/i386/pc/biosdisk.h
new file mode 100644 (file)
index 0000000..64d4f21
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,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_BIOSDISK_MACHINE_HEADER
+#define GRUB_BIOSDISK_MACHINE_HEADER   1
+
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+#define GRUB_BIOSDISK_FLAG_LBA 1
+#define GRUB_BIOSDISK_FLAG_CDROM 2
+
+#define GRUB_BIOSDISK_CDTYPE_NO_EMUL   0
+#define GRUB_BIOSDISK_CDTYPE_1_2_M     1
+#define GRUB_BIOSDISK_CDTYPE_1_44_M    2
+#define GRUB_BIOSDISK_CDTYPE_2_88_M    3
+#define GRUB_BIOSDISK_CDTYPE_HARDDISK  4
+
+#define GRUB_BIOSDISK_CDTYPE_MASK      0xF
+
+struct grub_biosdisk_data
+{
+  int drive;
+  unsigned long cylinders;
+  unsigned long heads;
+  unsigned long sectors;
+  unsigned long flags;
+};
+
+/* Drive Parameters.  */
+struct grub_biosdisk_drp
+{
+  grub_uint16_t size;
+  grub_uint16_t flags;
+  grub_uint32_t cylinders;
+  grub_uint32_t heads;
+  grub_uint32_t sectors;
+  grub_uint64_t total_sectors;
+  grub_uint16_t bytes_per_sector;
+  /* ver 2.0 or higher */
+
+  union
+  {
+    grub_uint32_t EDD_configuration_parameters;
+
+    /* Pointer to the Device Parameter Table Extension (ver 3.0+).  */
+    grub_uint32_t dpte_pointer;
+  };
+
+  /* ver 3.0 or higher */
+  grub_uint16_t signature_dpi;
+  grub_uint8_t length_dpi;
+  grub_uint8_t reserved[3];
+  grub_uint8_t name_of_host_bus[4];
+  grub_uint8_t name_of_interface_type[8];
+  grub_uint8_t interface_path[8];
+  grub_uint8_t device_path[8];
+  grub_uint8_t reserved2;
+  grub_uint8_t checksum;
+  
+  /* XXX: This is necessary, because the BIOS of Thinkpad X20
+     writes a garbage to the tail of drive parameters,
+     regardless of a size specified in a caller.  */
+  grub_uint8_t dummy[16];
+} __attribute__ ((packed));
+
+struct grub_biosdisk_cdrp
+{
+  grub_uint8_t size;
+  grub_uint8_t media_type;
+  grub_uint8_t drive_no;
+  grub_uint8_t controller_no;
+  grub_uint32_t image_lba;
+  grub_uint16_t device_spec;
+  grub_uint16_t cache_seg;
+  grub_uint16_t load_seg;
+  grub_uint16_t length_sec512;
+  grub_uint8_t cylinders;
+  grub_uint8_t sectors;
+  grub_uint8_t heads;
+  grub_uint8_t dummy[16];
+} __attribute__ ((packed));
+
+/* Disk Address Packet.  */
+struct grub_biosdisk_dap
+{
+  grub_uint8_t length;
+  grub_uint8_t reserved;
+  grub_uint16_t blocks;
+  grub_uint32_t buffer;
+  grub_uint64_t block;
+} __attribute__ ((packed));
+
+int EXPORT_FUNC(grub_biosdisk_rw_int13_extensions) (int ah, int drive, void *dap);
+int EXPORT_FUNC(grub_biosdisk_rw_standard) (int ah, int drive, int coff, int hoff,
+                              int soff, int nsec, int segment);
+int EXPORT_FUNC(grub_biosdisk_check_int13_extensions) (int drive);
+int EXPORT_FUNC(grub_biosdisk_get_diskinfo_int13_extensions) (int drive,
+           void *drp);
+int EXPORT_FUNC(grub_biosdisk_get_cdinfo_int13_extensions) (int drive,
+           void *cdrp);
+int EXPORT_FUNC(grub_biosdisk_get_diskinfo_standard) (int drive,
+                                        unsigned long *cylinders,
+                                        unsigned long *heads,
+                                        unsigned long *sectors);
+int EXPORT_FUNC(grub_biosdisk_get_num_floppies) (void);
+
+void grub_biosdisk_init (void);
+void grub_biosdisk_fini (void);
+
+#endif /* ! GRUB_BIOSDISK_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/boot.h b/include/grub/i386/pc/boot.h
new file mode 100644 (file)
index 0000000..3862214
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2002,2005,2006,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_BOOT_MACHINE_HEADER
+#define GRUB_BOOT_MACHINE_HEADER       1
+
+/* The signature for bootloader.  */
+#define GRUB_BOOT_MACHINE_SIGNATURE    0xaa55
+
+/* The offset of the start of BPB (BIOS Parameter Block).  */
+#define GRUB_BOOT_MACHINE_BPB_START    0x3
+
+/* The offset of the end of BPB (BIOS Parameter Block).  */
+#define GRUB_BOOT_MACHINE_BPB_END      0x3e
+
+/* The offset of the major version.  */
+#define GRUB_BOOT_MACHINE_VER_MAJ      0x3e
+
+/* The offset of BOOT_DRIVE.  */
+#define GRUB_BOOT_MACHINE_BOOT_DRIVE   0x4c
+
+/* The offset of ROOT_DRIVE.  */
+#define GRUB_BOOT_MACHINE_ROOT_DRIVE   0x4d
+
+/* The offset of KERNEL_ADDRESS.  */
+#define GRUB_BOOT_MACHINE_KERNEL_ADDRESS       0x40
+
+/* The offset of KERNEL_SECTOR.  */
+#define GRUB_BOOT_MACHINE_KERNEL_SECTOR        0x44
+
+/* The offset of KERNEL_SEGMENT.  */
+#define GRUB_BOOT_MACHINE_KERNEL_SEGMENT       0x42
+
+/* The offset of BOOT_DRIVE_CHECK.  */
+#define GRUB_BOOT_MACHINE_DRIVE_CHECK  0x4f
+
+/* The offset of a magic number used by Windows NT.  */
+#define GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC     0x1b8
+
+/* The offset of the start of the partition table.  */
+#define GRUB_BOOT_MACHINE_PART_START   0x1be
+
+/* The offset of the end of the partition table.  */
+#define GRUB_BOOT_MACHINE_PART_END     0x1fe
+
+/* The stack segment.  */
+#define GRUB_BOOT_MACHINE_STACK_SEG    0x2000
+
+/* The segment of disk buffer. The disk buffer MUST be 32K long and
+   cannot straddle a 64K boundary.  */
+#define GRUB_BOOT_MACHINE_BUFFER_SEG   0x7000
+
+/* The flag for BIOS drive number to designate a hard disk vs. a
+   floppy.  */
+#define GRUB_BOOT_MACHINE_BIOS_HD_FLAG 0x80
+
+/* The segment where the kernel is loaded.  */
+#define GRUB_BOOT_MACHINE_KERNEL_SEG   0x800
+
+/* The address where the kernel is loaded.  */
+#define GRUB_BOOT_MACHINE_KERNEL_ADDR  (GRUB_BOOT_MACHINE_KERNEL_SEG << 4)
+
+/* The size of a block list used in the kernel startup code.  */
+#define GRUB_BOOT_MACHINE_LIST_SIZE    12
+
+#endif /* ! BOOT_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/chainloader.h b/include/grub/i386/pc/chainloader.h
new file mode 100644 (file)
index 0000000..c28a42d
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,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_CHAINLOADER_MACHINE_HEADER
+#define GRUB_CHAINLOADER_MACHINE_HEADER        1
+
+#include <grub/dl.h>
+
+/* Common function for normal and rescue mode commands. */
+typedef enum
+  {
+    GRUB_CHAINLOADER_FORCE = 0x1
+  } grub_chainloader_flags_t;
+
+void EXPORT_FUNC(grub_chainloader_cmd) (const char * file,
+                                       grub_chainloader_flags_t flags);
+
+#endif /* GRUB_CHAINLOADER_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/console.h b/include/grub/i386/pc/console.h
new file mode 100644 (file)
index 0000000..2a74d15
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,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_CONSOLE_MACHINE_HEADER
+#define GRUB_CONSOLE_MACHINE_HEADER    1
+
+/* Define scan codes.  */
+#define GRUB_CONSOLE_KEY_LEFT          0x4B00
+#define GRUB_CONSOLE_KEY_RIGHT         0x4D00
+#define GRUB_CONSOLE_KEY_UP            0x4800
+#define GRUB_CONSOLE_KEY_DOWN          0x5000
+#define GRUB_CONSOLE_KEY_IC            0x5200
+#define GRUB_CONSOLE_KEY_DC            0x5300
+#define GRUB_CONSOLE_KEY_BACKSPACE     0x0008
+#define GRUB_CONSOLE_KEY_HOME          0x4700
+#define GRUB_CONSOLE_KEY_END           0x4F00
+#define GRUB_CONSOLE_KEY_NPAGE         0x5100
+#define GRUB_CONSOLE_KEY_PPAGE         0x4900
+
+#ifndef ASM_FILE
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/term.h>
+#include <grub/i386/vga_common.h>
+
+/* These are global to share code between C and asm.  */
+int grub_console_checkkey (void);
+int grub_console_getkey (void);
+grub_uint16_t grub_console_getxy (void);
+void grub_console_gotoxy (grub_uint8_t x, grub_uint8_t y);
+void grub_console_cls (void);
+void grub_console_setcursor (int on);
+
+/* Initialize the console system.  */
+void grub_console_init (void);
+
+/* Finish the console system.  */
+void grub_console_fini (void);
+
+#endif
+
+#endif /* ! GRUB_CONSOLE_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/init.h b/include/grub/i386/pc/init.h
new file mode 100644 (file)
index 0000000..f18a0da
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2004,2005,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_INIT_MACHINE_HEADER
+#define GRUB_INIT_MACHINE_HEADER       1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/machine/memory.h>
+
+/* Get the memory size in KB. If EXTENDED is zero, return conventional
+   memory, otherwise return extended memory.  */
+grub_uint16_t grub_get_memsize (int extended);
+
+/* Get a packed EISA memory map. Lower 16 bits are between 1MB and 16MB
+   in 1KB parts, and upper 16 bits are above 16MB in 64KB parts.  */
+grub_uint32_t grub_get_eisa_mmap (void);
+
+/* Get a memory map entry. Return next continuation value. Zero means
+   the end.  */
+grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_machine_mmap_entry *entry,
+                                  grub_uint32_t cont);
+
+/* Turn on/off Gate A20.  */
+void grub_gate_a20 (int on);
+
+/* Reboot the machine.  */
+void EXPORT_FUNC (grub_reboot) (void);
+
+/* Halt the system, using APM if possible. If NO_APM is true, don't
+ * use APM even if it is available.  */
+void EXPORT_FUNC (grub_halt) (int no_apm);
+
+
+#endif /* ! GRUB_INIT_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h
new file mode 100644 (file)
index 0000000..b6650bc
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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 KERNEL_MACHINE_HEADER
+#define KERNEL_MACHINE_HEADER  1
+
+/* The offset of GRUB_TOTAL_MODULE_SIZE.  */
+#define GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE  0x8
+
+/* The offset of GRUB_KERNEL_IMAGE_SIZE.  */
+#define GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE  0xc
+
+/* The offset of GRUB_COMPRESSED_SIZE.  */
+#define GRUB_KERNEL_MACHINE_COMPRESSED_SIZE    0x10
+
+/* The offset of GRUB_INSTALL_DOS_PART.  */
+#define GRUB_KERNEL_MACHINE_INSTALL_DOS_PART   0x14
+
+/* The offset of GRUB_INSTALL_BSD_PART.  */
+#define GRUB_KERNEL_MACHINE_INSTALL_BSD_PART   0x18
+
+/* The offset of GRUB_PREFIX.  */
+#define GRUB_KERNEL_MACHINE_PREFIX             0x1c
+
+/* End of the data section. */
+#define GRUB_KERNEL_MACHINE_DATA_END           0x5c
+
+/* The size of the first region which won't be compressed.  */
+#if defined(ENABLE_LZO)
+#define GRUB_KERNEL_MACHINE_RAW_SIZE           (GRUB_KERNEL_MACHINE_DATA_END + 0x450)
+#elif defined(ENABLE_LZMA)
+#define GRUB_KERNEL_MACHINE_RAW_SIZE           (GRUB_KERNEL_MACHINE_DATA_END + 0x5F0)
+#endif
+
+#ifndef ASM_FILE
+
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+/* The size of kernel image.  */
+extern grub_int32_t grub_kernel_image_size;
+
+/* The total size of module images following the kernel.  */
+extern grub_int32_t grub_total_module_size;
+
+/* The DOS partition number of the installed partition.  */
+extern grub_int32_t grub_install_dos_part;
+
+/* The BSD partition number of the installed partition.  */
+extern grub_int32_t grub_install_bsd_part;
+
+/* The prefix which points to the directory where GRUB modules and its
+   configuration file are located.  */
+extern char grub_prefix[];
+
+/* The boot BIOS drive number.  */
+extern grub_int32_t EXPORT_VAR(grub_boot_drive);
+
+/* The root BIOS drive number.  */
+extern grub_int32_t grub_root_drive;
+
+/* The end address of the kernel.  */
+extern grub_addr_t grub_end_addr;
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! KERNEL_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/loader.h b/include/grub/i386/pc/loader.h
new file mode 100644 (file)
index 0000000..3e03141
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,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_LOADER_MACHINE_HEADER
+#define GRUB_LOADER_MACHINE_HEADER     1
+
+#include <grub/symbol.h>
+#include <grub/cpu/loader.h>
+
+/* This is an asm part of the chainloader.  */
+void EXPORT_FUNC(grub_chainloader_real_boot) (int drive, void *part_addr) __attribute__ ((noreturn));
+
+#endif /* ! GRUB_LOADER_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/machine.h b/include/grub/i386/pc/machine.h
new file mode 100644 (file)
index 0000000..e6de728
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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_MACHINE_MACHINE_HEADER
+#define GRUB_MACHINE_MACHINE_HEADER    1
+
+#define GRUB_MACHINE_PCBIOS    1
+
+#endif /* ! GRUB_MACHINE_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/memory.h b/include/grub/i386/pc/memory.h
new file mode 100644 (file)
index 0000000..08e92a9
--- /dev/null
@@ -0,0 +1,103 @@
+/* memory.h - describe the memory map */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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_MEMORY_MACHINE_HEADER
+#define GRUB_MEMORY_MACHINE_HEADER     1
+
+#include <grub/symbol.h>
+#include <grub/machine/machine.h>
+#ifndef ASM_FILE
+#include <grub/types.h>
+#include <grub/err.h>
+#endif
+
+/* The scratch buffer used in real mode code.  */
+#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
+
+/* The real mode stack.  */
+#define GRUB_MEMORY_MACHINE_REAL_STACK (0x2000 - 0x10)
+
+/* The size of the protect mode stack.  */
+#define GRUB_MEMORY_MACHINE_PROT_STACK_SIZE    0x8000
+
+/* The upper memory area (starting at 640 kiB).  */
+#define GRUB_MEMORY_MACHINE_UPPER              0xa0000
+
+/* The protected mode stack.  */
+#define GRUB_MEMORY_MACHINE_PROT_STACK \
+       (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + GRUB_MEMORY_MACHINE_SCRATCH_SIZE \
+        + GRUB_MEMORY_MACHINE_PROT_STACK_SIZE - 0x10)
+
+/* The memory area where GRUB uses its own purpose. This part is not added
+   into free memory for dynamic allocations.  */
+#define GRUB_MEMORY_MACHINE_RESERVED_START     \
+       GRUB_MEMORY_MACHINE_SCRATCH_ADDR
+#define GRUB_MEMORY_MACHINE_RESERVED_END       \
+       (GRUB_MEMORY_MACHINE_PROT_STACK + 0x10)
+
+/* The area where GRUB is decompressed at early startup.  */
+#define GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR 0x100000
+
+/* The address of a partition table passed to another boot loader.  */
+#define GRUB_MEMORY_MACHINE_PART_TABLE_ADDR    0x7be
+
+/* The address where another boot loader is loaded.  */
+#define GRUB_MEMORY_MACHINE_BOOT_LOADER_ADDR   0x7c00
+
+/* The flag for protected mode.  */
+#define GRUB_MEMORY_MACHINE_CR0_PE_ON          0x1
+
+/* The code segment of the protected mode.  */
+#define GRUB_MEMORY_MACHINE_PROT_MODE_CSEG     0x8
+
+/* The data segment of the protected mode.  */
+#define GRUB_MEMORY_MACHINE_PROT_MODE_DSEG     0x10
+
+/* The code segment of the pseudo real mode.  */
+#define GRUB_MEMORY_MACHINE_PSEUDO_REAL_CSEG   0x18
+
+/* The data segment of the pseudo real mode.  */
+#define GRUB_MEMORY_MACHINE_PSEUDO_REAL_DSEG   0x20
+
+#ifndef ASM_FILE
+
+#ifndef GRUB_MACHINE_IEEE1275
+extern grub_size_t EXPORT_VAR(grub_lower_mem);
+#endif
+
+extern grub_size_t EXPORT_VAR(grub_upper_mem);
+
+struct grub_machine_mmap_entry
+{
+  grub_uint32_t size;
+  grub_uint64_t addr;
+  grub_uint64_t len;
+#define GRUB_MACHINE_MEMORY_AVAILABLE  1
+#define GRUB_MACHINE_MEMORY_RESERVED   2
+  grub_uint32_t type;
+} __attribute__((packed));
+
+grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate)
+     (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
+
+#endif
+
+#endif /* ! GRUB_MEMORY_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/pxe.h b/include/grub/i386/pc/pxe.h
new file mode 100644 (file)
index 0000000..4821328
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ *  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_PXE_H
+#define GRUB_CPU_PXE_H
+
+#include <grub/types.h>
+
+#define GRUB_PXENV_TFTP_OPEN                   0x0020
+#define GRUB_PXENV_TFTP_CLOSE                  0x0021
+#define GRUB_PXENV_TFTP_READ                   0x0022
+#define GRUB_PXENV_TFTP_READ_FILE              0x0023
+#define GRUB_PXENV_TFTP_READ_FILE_PMODE                0x0024
+#define GRUB_PXENV_TFTP_GET_FSIZE              0x0025
+
+#define GRUB_PXENV_UDP_OPEN                    0x0030
+#define GRUB_PXENV_UDP_CLOSE                   0x0031
+#define GRUB_PXENV_UDP_READ                    0x0032
+#define GRUB_PXENV_UDP_WRITE                   0x0033
+
+#define GRUB_PXENV_START_UNDI                  0x0000
+#define GRUB_PXENV_UNDI_STARTUP                        0x0001
+#define GRUB_PXENV_UNDI_CLEANUP                        0x0002
+#define GRUB_PXENV_UNDI_INITIALIZE             0x0003
+#define GRUB_PXENV_UNDI_RESET_NIC              0x0004
+#define GRUB_PXENV_UNDI_SHUTDOWN               0x0005
+#define GRUB_PXENV_UNDI_OPEN                   0x0006
+#define GRUB_PXENV_UNDI_CLOSE                  0x0007
+#define GRUB_PXENV_UNDI_TRANSMIT               0x0008
+#define GRUB_PXENV_UNDI_SET_MCAST_ADDR         0x0009
+#define GRUB_PXENV_UNDI_SET_STATION_ADDR       0x000A
+#define GRUB_PXENV_UNDI_SET_PACKET_FILTER      0x000B
+#define GRUB_PXENV_UNDI_GET_INFORMATION                0x000C
+#define GRUB_PXENV_UNDI_GET_STATISTICS         0x000D
+#define GRUB_PXENV_UNDI_CLEAR_STATISTICS       0x000E
+#define GRUB_PXENV_UNDI_INITIATE_DIAGS         0x000F
+#define GRUB_PXENV_UNDI_FORCE_INTERRUPT                0x0010
+#define GRUB_PXENV_UNDI_GET_MCAST_ADDR         0x0011
+#define GRUB_PXENV_UNDI_GET_NIC_TYPE           0x0012
+#define GRUB_PXENV_UNDI_GET_IFACE_INFO         0x0013
+#define GRUB_PXENV_UNDI_ISR                    0x0014
+#define        GRUB_PXENV_STOP_UNDI                    0x0015
+#define GRUB_PXENV_UNDI_GET_STATE              0x0015
+
+#define GRUB_PXENV_UNLOAD_STACK                        0x0070
+#define GRUB_PXENV_GET_CACHED_INFO             0x0071
+#define GRUB_PXENV_RESTART_DHCP                        0x0072
+#define GRUB_PXENV_RESTART_TFTP                        0x0073
+#define GRUB_PXENV_MODE_SWITCH                 0x0074
+#define GRUB_PXENV_START_BASE                  0x0075
+#define GRUB_PXENV_STOP_BASE                   0x0076
+
+#define GRUB_PXENV_EXIT_SUCCESS                        0x0000
+#define GRUB_PXENV_EXIT_FAILURE                        0x0001
+
+#define GRUB_PXENV_STATUS_SUCCESS                              0x00
+#define GRUB_PXENV_STATUS_FAILURE                              0x01
+#define GRUB_PXENV_STATUS_BAD_FUNC                             0x02
+#define GRUB_PXENV_STATUS_UNSUPPORTED                          0x03
+#define GRUB_PXENV_STATUS_KEEP_UNDI                            0x04
+#define GRUB_PXENV_STATUS_KEEP_ALL                             0x05
+#define GRUB_PXENV_STATUS_OUT_OF_RESOURCES                     0x06
+#define GRUB_PXENV_STATUS_ARP_TIMEOUT                          0x11
+#define GRUB_PXENV_STATUS_UDP_CLOSED                           0x18
+#define GRUB_PXENV_STATUS_UDP_OPEN                             0x19
+#define GRUB_PXENV_STATUS_TFTP_CLOSED                          0x1A
+#define GRUB_PXENV_STATUS_TFTP_OPEN                            0x1B
+#define GRUB_PXENV_STATUS_MCOPY_PROBLEM                                0x20
+#define GRUB_PXENV_STATUS_BIS_INTEGRITY_FAILURE                        0x21
+#define GRUB_PXENV_STATUS_BIS_VALIDATE_FAILURE                 0x22
+#define GRUB_PXENV_STATUS_BIS_INIT_FAILURE                     0x23
+#define GRUB_PXENV_STATUS_BIS_SHUTDOWN_FAILURE                 0x24
+#define GRUB_PXENV_STATUS_BIS_GBOA_FAILURE                     0x25
+#define GRUB_PXENV_STATUS_BIS_FREE_FAILURE                     0x26
+#define GRUB_PXENV_STATUS_BIS_GSI_FAILURE                      0x27
+#define GRUB_PXENV_STATUS_BIS_BAD_CKSUM                                0x28
+#define GRUB_PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS              0x30
+#define GRUB_PXENV_STATUS_TFTP_OPEN_TIMEOUT                    0x32
+
+#define GRUB_PXENV_STATUS_TFTP_UNKNOWN_OPCODE                  0x33
+#define GRUB_PXENV_STATUS_TFTP_READ_TIMEOUT                    0x35
+#define GRUB_PXENV_STATUS_TFTP_ERROR_OPCODE                    0x36
+#define GRUB_PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION          0x38
+#define GRUB_PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION     0x39
+#define GRUB_PXENV_STATUS_TFTP_TOO_MANY_PACKAGES               0x3A
+#define GRUB_PXENV_STATUS_TFTP_FILE_NOT_FOUND                  0x3B
+#define GRUB_PXENV_STATUS_TFTP_ACCESS_VIOLATION                        0x3C
+#define GRUB_PXENV_STATUS_TFTP_NO_MCAST_ADDRESS                        0x3D
+#define GRUB_PXENV_STATUS_TFTP_NO_FILESIZE                     0x3E
+#define GRUB_PXENV_STATUS_TFTP_INVALID_PACKET_SIZE             0x3F
+#define GRUB_PXENV_STATUS_DHCP_TIMEOUT                         0x51
+#define GRUB_PXENV_STATUS_DHCP_NO_IP_ADDRESS                   0x52
+#define GRUB_PXENV_STATUS_DHCP_NO_BOOTFILE_NAME                        0x53
+#define GRUB_PXENV_STATUS_DHCP_BAD_IP_ADDRESS                  0x54
+#define GRUB_PXENV_STATUS_UNDI_INVALID_FUNCTION                        0x60
+#define GRUB_PXENV_STATUS_UNDI_MEDIATEST_FAILED                        0x61
+#define GRUB_PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST       0x62
+#define GRUB_PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC           0x63
+#define GRUB_PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY           0x64
+#define GRUB_PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA         0x65
+#define GRUB_PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA           0x66
+#define GRUB_PXENV_STATUS_UNDI_BAD_MAC_ADDRESS                 0x67
+#define GRUB_PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM             0x68
+#define GRUB_PXENV_STATUS_UNDI_ERROR_SETTING_ISR               0x69
+#define GRUB_PXENV_STATUS_UNDI_INVALID_STATE                   0x6A
+#define GRUB_PXENV_STATUS_UNDI_TRANSMIT_ERROR                  0x6B
+#define GRUB_PXENV_STATUS_UNDI_INVALID_PARAMETER               0x6C
+#define GRUB_PXENV_STATUS_BSTRAP_PROMPT_MENU                   0x74
+#define GRUB_PXENV_STATUS_BSTRAP_MCAST_ADDR                    0x76
+#define GRUB_PXENV_STATUS_BSTRAP_MISSING_LIST                  0x77
+#define GRUB_PXENV_STATUS_BSTRAP_NO_RESPONSE                   0x78
+#define GRUB_PXENV_STATUS_BSTRAP_FILE_TOO_BIG                  0x79
+#define GRUB_PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE           0xA0
+#define GRUB_PXENV_STATUS_BINL_NO_PXE_SERVER                   0xA1
+#define GRUB_PXENV_STATUS_NOT_AVAILABLE_IN_PMODE               0xA2
+#define GRUB_PXENV_STATUS_NOT_AVAILABLE_IN_RMODE               0xA3
+#define GRUB_PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED            0xB0
+#define GRUB_PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY           0xC0
+#define GRUB_PXENV_STATUS_LOADER_NO_BC_ROMID                   0xC1
+#define GRUB_PXENV_STATUS_LOADER_BAD_BC_ROMID                  0xC2
+#define GRUB_PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE          0xC3
+#define GRUB_PXENV_STATUS_LOADER_NO_UNDI_ROMID                 0xC4
+#define GRUB_PXENV_STATUS_LOADER_BAD_UNDI_ROMID                        0xC5
+#define GRUB_PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE         0xC6
+#define GRUB_PXENV_STATUS_LOADER_NO_PXE_STRUCT                 0xC8
+#define GRUB_PXENV_STATUS_LOADER_NO_PXENV_STRUCT               0xC9
+#define GRUB_PXENV_STATUS_LOADER_UNDI_START                    0xCA
+#define GRUB_PXENV_STATUS_LOADER_BC_START                      0xCB
+
+#define GRUB_PXENV_PACKET_TYPE_DHCP_DISCOVER   1
+#define GRUB_PXENV_PACKET_TYPE_DHCP_ACK                2
+#define GRUB_PXENV_PACKET_TYPE_CACHED_REPLY    3
+
+#define GRUB_PXE_BOOTP_REQ     1
+#define GRUB_PXE_BOOTP_REP     2
+
+#define GRUB_PXE_BOOTP_BCAST   0x8000
+
+#if 1
+#define GRUB_PXE_BOOTP_DHCPVEND        1024    /* DHCP extended vendor field size.  */
+#else
+#define GRUB_PXE_BOOTP_DHCPVEND        312     /* DHCP standard vendor field size.  */
+#endif
+
+#define GRUB_PXE_MIN_BLKSIZE   512
+#define GRUB_PXE_MAX_BLKSIZE   1432
+
+#define GRUB_PXE_TFTP_PORT     69
+
+#define        GRUB_PXE_VM_RFC1048     0x63825363L
+
+#define GRUB_PXE_ERR_LEN       0xFFFFFFFF
+
+#ifndef ASM_FILE
+
+struct grub_pxenv
+{
+  grub_uint8_t signature[6];   /* 'PXENV+'.  */
+  grub_uint16_t version;       /* MSB = major, LSB = minor.  */
+  grub_uint8_t length;         /* structure length.  */
+  grub_uint8_t checksum;       /* checksum pad.  */
+  grub_uint32_t rm_entry;      /* SEG:OFF to PXE entry point.  */
+  grub_uint32_t        pm_offset;      /* Protected mode entry.  */
+  grub_uint16_t pm_selector;   /* Protected mode selector.  */
+  grub_uint16_t stack_seg;     /* Stack segment address.  */
+  grub_uint16_t        stack_size;     /* Stack segment size (bytes).  */
+  grub_uint16_t bc_code_seg;   /* BC Code segment address.  */
+  grub_uint16_t        bc_code_size;   /* BC Code segment size (bytes).  */
+  grub_uint16_t        bc_data_seg;    /* BC Data segment address.  */
+  grub_uint16_t        bc_data_size;   /* BC Data segment size (bytes).  */
+  grub_uint16_t        undi_data_seg;  /* UNDI Data segment address.  */
+  grub_uint16_t        undi_data_size; /* UNDI Data segment size (bytes).  */
+  grub_uint16_t        undi_code_seg;  /* UNDI Code segment address.  */
+  grub_uint16_t        undi_code_size; /* UNDI Code segment size (bytes).  */
+  grub_uint32_t pxe_ptr;       /* SEG:OFF to !PXE struct.  */
+} __attribute__ ((packed));
+
+struct grub_pxenv_get_cached_info
+{
+  grub_uint16_t status;
+  grub_uint16_t packet_type;
+  grub_uint16_t buffer_size;
+  grub_uint32_t buffer;
+  grub_uint16_t buffer_limit;
+} __attribute__ ((packed));
+
+#define GRUB_PXE_MAC_ADDR_LEN  16
+
+typedef grub_uint8_t grub_pxe_mac_addr[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 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;
+  grub_uint32_t server_ip;
+  grub_uint32_t gateway_ip;
+  grub_uint8_t filename[128];
+  grub_uint16_t tftp_port;
+  grub_uint16_t packet_size;
+} __attribute__ ((packed));
+
+struct grub_pxenv_tftp_close
+{
+  grub_uint16_t status;
+} __attribute__ ((packed));
+
+struct grub_pxenv_tftp_read
+{
+  grub_uint16_t status;
+  grub_uint16_t packet_number;
+  grub_uint16_t buffer_size;
+  grub_uint32_t buffer;
+} __attribute__ ((packed));
+
+struct grub_pxenv_tftp_get_fsize
+{
+  grub_uint16_t status;
+  grub_uint32_t server_ip;
+  grub_uint32_t gateway_ip;
+  grub_uint8_t filename[128];
+  grub_uint32_t file_size;
+} __attribute__ ((packed));
+
+struct grub_pxenv_udp_open
+{
+  grub_uint16_t status;
+  grub_uint32_t src_ip;
+} __attribute__ ((packed));
+
+struct grub_pxenv_udp_close
+{
+  grub_uint16_t status;
+} __attribute__ ((packed));
+
+struct grub_pxenv_udp_write
+{
+  grub_uint16_t status;
+  grub_uint32_t ip;
+  grub_uint32_t gateway;
+  grub_uint16_t src_port;
+  grub_uint16_t dst_port;
+  grub_uint16_t buffer_size;
+  grub_uint32_t buffer;
+} __attribute__ ((packed));
+
+struct grub_pxenv_udp_read
+{
+  grub_uint16_t status;
+  grub_uint32_t src_ip;
+  grub_uint32_t dst_ip;
+  grub_uint16_t src_port;
+  grub_uint16_t dst_port;
+  grub_uint16_t buffer_size;
+  grub_uint32_t buffer;
+} __attribute__ ((packed));
+
+struct grub_pxenv_unload_stack
+{
+  grub_uint16_t status;
+  grub_uint8_t reserved[10];
+} __attribute__ ((packed));
+
+struct grub_pxenv * EXPORT_FUNC(grub_pxe_scan) (void);
+int EXPORT_FUNC(grub_pxe_call) (int func, void * data);
+
+extern struct grub_pxenv *grub_pxe_pxenv;
+extern grub_uint32_t grub_pxe_your_ip;
+extern grub_uint32_t grub_pxe_server_ip;
+extern grub_uint32_t grub_pxe_gateway_ip;
+extern int grub_pxe_blksize;
+
+void grub_pxe_unload (void);
+
+#endif
+
+#endif /* GRUB_CPU_PXE_H */
diff --git a/include/grub/i386/pc/serial.h b/include/grub/i386/pc/serial.h
new file mode 100644 (file)
index 0000000..0632ff7
--- /dev/null
@@ -0,0 +1,67 @@
+/* serial.h - serial device interface */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2000,2001,2002,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 GRUB_SERIAL_MACHINE_HEADER
+#define GRUB_SERIAL_MACHINE_HEADER     1
+
+/* Macros.  */
+
+/* The offsets of UART registers.  */
+#define UART_TX                0
+#define UART_RX                0
+#define UART_DLL       0
+#define UART_IER       1
+#define UART_DLH       1
+#define UART_IIR       2
+#define UART_FCR       2
+#define UART_LCR       3
+#define UART_MCR       4
+#define UART_LSR       5
+#define UART_MSR       6
+#define UART_SR                7
+
+/* For LSR bits.  */
+#define UART_DATA_READY                0x01
+#define UART_EMPTY_TRANSMITTER 0x20
+
+/* The type of parity.  */
+#define UART_NO_PARITY         0x00
+#define UART_ODD_PARITY                0x08
+#define UART_EVEN_PARITY       0x18
+
+/* The type of word length.  */
+#define UART_5BITS_WORD        0x00
+#define UART_6BITS_WORD        0x01
+#define UART_7BITS_WORD        0x02
+#define UART_8BITS_WORD        0x03
+
+/* The type of the length of stop bit.  */
+#define UART_1_STOP_BIT                0x00
+#define UART_2_STOP_BITS       0x04
+
+/* the switch of DLAB.  */
+#define UART_DLAB      0x80
+
+/* Enable the FIFO.  */
+#define UART_ENABLE_FIFO       0xC7
+
+/* Turn on DTR, RTS, and OUT2.  */
+#define UART_ENABLE_MODEM      0x0B
+
+#endif /* ! GRUB_SERIAL_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/time.h b/include/grub/i386/pc/time.h
new file mode 100644 (file)
index 0000000..98399b6
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *  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  18
+
+/* Return the real time in ticks.  */
+grub_uint32_t EXPORT_FUNC (grub_get_rtc) (void);
+
+#endif /* ! KERNEL_MACHINE_TIME_HEADER */
diff --git a/include/grub/i386/pc/vbe.h b/include/grub/i386/pc/vbe.h
new file mode 100644 (file)
index 0000000..9a8cb95
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2006,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_VBE_MACHINE_HEADER
+#define GRUB_VBE_MACHINE_HEADER        1
+
+#include <grub/symbol.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/video.h>
+
+/* Default video mode to be used.  */
+#define GRUB_VBE_DEFAULT_VIDEO_MODE     0x101
+
+/* VBE status codes.  */
+#define GRUB_VBE_STATUS_OK             0x004f
+
+/* Bits from the GRUB_VBE "mode_attributes" field in the mode info struct.  */
+#define GRUB_VBE_MODEATTR_SUPPORTED                 (1 << 0)
+#define GRUB_VBE_MODEATTR_RESERVED_1                (1 << 1)
+#define GRUB_VBE_MODEATTR_BIOS_TTY_OUTPUT_SUPPORT   (1 << 2)
+#define GRUB_VBE_MODEATTR_COLOR                     (1 << 3)
+#define GRUB_VBE_MODEATTR_GRAPHICS                  (1 << 4)
+#define GRUB_VBE_MODEATTR_VGA_COMPATIBLE            (1 << 5)
+#define GRUB_VBE_MODEATTR_VGA_WINDOWED_AVAIL        (1 << 6)
+#define GRUB_VBE_MODEATTR_LFB_AVAIL                 (1 << 7)
+#define GRUB_VBE_MODEATTR_DOUBLE_SCAN_AVAIL         (1 << 8)
+#define GRUB_VBE_MODEATTR_INTERLACED_AVAIL          (1 << 9)
+#define GRUB_VBE_MODEATTR_TRIPLE_BUF_AVAIL          (1 << 10)
+#define GRUB_VBE_MODEATTR_STEREO_AVAIL              (1 << 11)
+#define GRUB_VBE_MODEATTR_DUAL_DISPLAY_START        (1 << 12)
+
+/* Values for the GRUB_VBE memory_model field in the mode info struct.  */
+#define GRUB_VBE_MEMORY_MODEL_TEXT           0x00
+#define GRUB_VBE_MEMORY_MODEL_CGA            0x01
+#define GRUB_VBE_MEMORY_MODEL_HERCULES       0x02
+#define GRUB_VBE_MEMORY_MODEL_PLANAR         0x03
+#define GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL   0x04
+#define GRUB_VBE_MEMORY_MODEL_NONCHAIN4_256  0x05
+#define GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR   0x06
+#define GRUB_VBE_MEMORY_MODEL_YUV            0x07
+
+/* Note:
+
+   Please refer to VESA BIOS Extension 3.0 Specification for more descriptive
+   meanings of following structures and how they should be used.
+
+   I have tried to maintain field name compatibility against specification
+   while following naming conventions used in GRUB.  */
+
+typedef grub_uint32_t grub_vbe_farptr_t;
+typedef grub_uint32_t grub_vbe_physptr_t;
+typedef grub_uint32_t grub_vbe_status_t;
+
+struct grub_vbe_info_block
+{
+  grub_uint8_t signature[4];
+  grub_uint16_t version;
+
+  grub_vbe_farptr_t oem_string_ptr;
+  grub_uint32_t capabilities;
+  grub_vbe_farptr_t video_mode_ptr;
+  grub_uint16_t total_memory;
+
+  grub_uint16_t oem_software_rev;
+  grub_vbe_farptr_t oem_vendor_name_ptr;
+  grub_vbe_farptr_t oem_product_name_ptr;
+  grub_vbe_farptr_t oem_product_rev_ptr;
+
+  grub_uint8_t reserved[222];
+
+  grub_uint8_t oem_data[256];
+} __attribute__ ((packed));
+
+struct grub_vbe_mode_info_block
+{
+  /* Mandatory information for all VBE revisions.  */
+  grub_uint16_t mode_attributes;
+  grub_uint8_t win_a_attributes;
+  grub_uint8_t win_b_attributes;
+  grub_uint16_t win_granularity;
+  grub_uint16_t win_size;
+  grub_uint16_t win_a_segment;
+  grub_uint16_t win_b_segment;
+  grub_vbe_farptr_t win_func_ptr;
+  grub_uint16_t bytes_per_scan_line;
+
+  /* Mandatory information for VBE 1.2 and above.  */
+  grub_uint16_t x_resolution;
+  grub_uint16_t y_resolution;
+  grub_uint8_t x_char_size;
+  grub_uint8_t y_char_size;
+  grub_uint8_t number_of_planes;
+  grub_uint8_t bits_per_pixel;
+  grub_uint8_t number_of_banks;
+  grub_uint8_t memory_model;
+  grub_uint8_t bank_size;
+  grub_uint8_t number_of_image_pages;
+  grub_uint8_t reserved;
+
+  /* Direct Color fields (required for direct/6 and YUV/7 memory models).  */
+  grub_uint8_t red_mask_size;
+  grub_uint8_t red_field_position;
+  grub_uint8_t green_mask_size;
+  grub_uint8_t green_field_position;
+  grub_uint8_t blue_mask_size;
+  grub_uint8_t blue_field_position;
+  grub_uint8_t rsvd_mask_size;
+  grub_uint8_t rsvd_field_position;
+  grub_uint8_t direct_color_mode_info;
+
+  /* Mandatory information for VBE 2.0 and above.  */
+  grub_vbe_physptr_t phys_base_addr;
+  grub_uint32_t reserved2;
+  grub_uint16_t reserved3;
+
+  /* Mandatory information for VBE 3.0 and above.  */
+  grub_uint16_t lin_bytes_per_scan_line;
+  grub_uint8_t bnk_number_of_image_pages;
+  grub_uint8_t lin_number_of_image_pages;
+  grub_uint8_t lin_red_mask_size;
+  grub_uint8_t lin_red_field_position;
+  grub_uint8_t lin_green_mask_size;
+  grub_uint8_t lin_green_field_position;
+  grub_uint8_t lin_blue_mask_size;
+  grub_uint8_t lin_blue_field_position;
+  grub_uint8_t lin_rsvd_mask_size;
+  grub_uint8_t lin_rsvd_field_position;
+  grub_uint32_t max_pixel_clock;
+
+  /* Reserved field to make structure to be 256 bytes long, VESA BIOS 
+     Extension 3.0 Specification says to reserve 189 bytes here but 
+     that doesn't make structure to be 256 bytes.  So additional one is 
+     added here.  */
+  grub_uint8_t reserved4[189 + 1];
+} __attribute__ ((packed));
+
+struct grub_vbe_crtc_info_block
+{
+  grub_uint16_t horizontal_total;
+  grub_uint16_t horizontal_sync_start;
+  grub_uint16_t horizontal_sync_end;
+  grub_uint16_t vertical_total;
+  grub_uint16_t vertical_sync_start;
+  grub_uint16_t vertical_sync_end;
+  grub_uint8_t flags;
+  grub_uint32_t pixel_clock;
+  grub_uint16_t refresh_rate;
+  grub_uint8_t reserved[40];
+} __attribute__ ((packed));
+
+struct grub_vbe_palette_data
+{
+  grub_uint8_t blue;
+  grub_uint8_t green;
+  grub_uint8_t red;
+  grub_uint8_t alignment;
+} __attribute__ ((packed));
+
+/* Prototypes for kernel real mode thunks.  */
+
+/* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status.  */
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_controller_info) (struct grub_vbe_info_block *controller_info);
+
+/* Call VESA BIOS 0x4f01 to get VBE Mode Information, return status.  */
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_mode_info) (grub_uint32_t mode,
+                                                            struct grub_vbe_mode_info_block *mode_info);
+
+/* Call VESA BIOS 0x4f02 to set video mode, return status.  */
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_mode) (grub_uint32_t mode,
+                                                       struct grub_vbe_crtc_info_block *crtc_info);
+
+/* Call VESA BIOS 0x4f03 to return current VBE Mode, return status.  */
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_mode) (grub_uint32_t *mode);
+
+/* Call VESA BIOS 0x4f05 to set memory window, return status.  */
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_memory_window) (grub_uint32_t window,
+                                                                grub_uint32_t position);
+
+/* Call VESA BIOS 0x4f05 to return memory window, return status.  */
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_memory_window) (grub_uint32_t window,
+                                                                grub_uint32_t *position);
+
+/* Call VESA BIOS 0x4f06 to set scanline length (in bytes), return status.  */
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_scanline_length) (grub_uint32_t length);
+
+/* Call VESA BIOS 0x4f06 to return scanline length (in bytes), return status.  */
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_scanline_length) (grub_uint32_t *length);
+
+/* Call VESA BIOS 0x4f07 to set display start, return status.  */
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_display_start) (grub_uint32_t x,
+                                                                grub_uint32_t y);
+
+/* Call VESA BIOS 0x4f07 to get display start, return status.  */
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_get_display_start) (grub_uint32_t *x,
+                                                                grub_uint32_t *y);
+
+/* Call VESA BIOS 0x4f09 to set palette data, return status.  */
+grub_vbe_status_t EXPORT_FUNC(grub_vbe_bios_set_palette_data) (grub_uint32_t color_count,
+                                                               grub_uint32_t start_index,
+                                                               struct grub_vbe_palette_data *palette_data);
+
+/* Prototypes for helper functions.  */
+
+grub_err_t grub_vbe_probe (struct grub_vbe_info_block *info_block);
+grub_err_t grub_vbe_set_video_mode (grub_uint32_t mode,
+                                    struct grub_vbe_mode_info_block *mode_info);
+grub_err_t grub_vbe_get_video_mode (grub_uint32_t *mode);
+grub_err_t grub_vbe_get_video_mode_info (grub_uint32_t mode,
+                                         struct grub_vbe_mode_info_block *mode_info);
+
+/* VBE module internal prototypes (should not be used from elsewhere).  */
+struct grub_video_i386_vbeblit_info;
+
+struct grub_video_render_target
+{
+  /* Copy of the screen's mode info structure, except that width, height and
+     mode_type has been re-adjusted to requested render target settings.  */
+  struct grub_video_mode_info mode_info;
+
+  struct
+  {
+    unsigned int x;
+    unsigned int y;
+    unsigned int width;
+    unsigned int height;
+  } viewport;
+
+  /* Indicates whether the data has been allocated by us and must be freed
+     when render target is destroyed.  */
+  int is_allocated;
+
+  /* Pointer to data.  Can either be in video card memory or in local host's
+     memory.  */
+  void *data;
+};
+
+grub_uint8_t * grub_video_vbe_get_video_ptr (struct grub_video_i386_vbeblit_info *source,
+                                             grub_uint32_t x, grub_uint32_t y);
+
+grub_video_color_t grub_video_vbe_map_rgb (grub_uint8_t red, grub_uint8_t green,
+                                           grub_uint8_t blue);
+
+grub_video_color_t grub_video_vbe_map_rgba (grub_uint8_t red,
+                                            grub_uint8_t green,
+                                            grub_uint8_t blue,
+                                            grub_uint8_t alpha);
+
+grub_err_t grub_video_vbe_unmap_color (grub_video_color_t color,
+                                       grub_uint8_t *red,
+                                       grub_uint8_t *green,
+                                       grub_uint8_t *blue,
+                                       grub_uint8_t *alpha);
+
+void grub_video_vbe_unmap_color_int (struct grub_video_i386_vbeblit_info *source,
+                                     grub_video_color_t color,
+                                     grub_uint8_t *red,
+                                     grub_uint8_t *green,
+                                     grub_uint8_t *blue,
+                                     grub_uint8_t *alpha);
+
+#endif /* ! GRUB_VBE_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/vbeblit.h b/include/grub/i386/pc/vbeblit.h
new file mode 100644 (file)
index 0000000..5a2aa7a
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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_VBEBLIT_MACHINE_HEADER
+#define GRUB_VBEBLIT_MACHINE_HEADER    1
+
+/* NOTE: This header is private header for vbe driver and should not be used
+   in other parts of the code.  */
+
+struct grub_video_i386_vbeblit_info;
+
+void
+grub_video_i386_vbeblit_replace (struct grub_video_i386_vbeblit_info *dst,
+                                 struct grub_video_i386_vbeblit_info *src,
+                                 int x, int y, int width, int height,
+                                 int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_replace_directN (struct grub_video_i386_vbeblit_info *dst,
+                                        struct grub_video_i386_vbeblit_info *src,
+                                        int x, int y, int width, int height,
+                                        int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_replace_BGRX8888_RGBX8888 (struct grub_video_i386_vbeblit_info *dst,
+                                                  struct grub_video_i386_vbeblit_info *src,
+                                                  int x, int y, int width, int height,
+                                                  int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_replace_BGRX8888_RGB888 (struct grub_video_i386_vbeblit_info *dst,
+                                                struct grub_video_i386_vbeblit_info *src,
+                                                int x, int y,
+                                                int width, int height,
+                                                int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_replace_BGR888_RGBX8888 (struct grub_video_i386_vbeblit_info *dst,
+                                                struct grub_video_i386_vbeblit_info *src,
+                                                int x, int y,
+                                                int width, int height,
+                                                int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_replace_BGR888_RGB888 (struct grub_video_i386_vbeblit_info *dst,
+                                              struct grub_video_i386_vbeblit_info *src,
+                                              int x, int y,
+                                              int width, int height,
+                                              int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_replace_RGBX8888_RGB888 (struct grub_video_i386_vbeblit_info *dst,
+                                                struct grub_video_i386_vbeblit_info *src,
+                                                int x, int y,
+                                                int width, int height,
+                                                int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_replace_RGB888_RGBX8888 (struct grub_video_i386_vbeblit_info *dst,
+                                                struct grub_video_i386_vbeblit_info *src,
+                                                int x, int y,
+                                                int width, int height,
+                                                int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_replace_index_RGBX8888 (struct grub_video_i386_vbeblit_info *dst,
+                                               struct grub_video_i386_vbeblit_info *src,
+                                               int x, int y,
+                                               int width, int height,
+                                               int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_replace_index_RGB888 (struct grub_video_i386_vbeblit_info *dst,
+                                             struct grub_video_i386_vbeblit_info *src,
+                                             int x, int y, int width, int height,
+                                             int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_blend (struct grub_video_i386_vbeblit_info *dst,
+                               struct grub_video_i386_vbeblit_info *src,
+                               int x, int y, int width, int height,
+                               int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_blend_BGRA8888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst,
+                                                struct grub_video_i386_vbeblit_info *src,
+                                                int x, int y,
+                                                int width, int height,
+                                                int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_blend_BGR888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst,
+                                              struct grub_video_i386_vbeblit_info *src,
+                                              int x, int y,
+                                              int width, int height,
+                                              int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_blend_RGBA8888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst,
+                                                struct grub_video_i386_vbeblit_info *src,
+                                                int x, int y,
+                                                int width, int height,
+                                                int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_blend_RGB888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst,
+                                              struct grub_video_i386_vbeblit_info *src,
+                                              int x, int y,
+                                              int width, int height,
+                                              int offset_x, int offset_y);
+
+void
+grub_video_i386_vbeblit_blend_index_RGBA8888 (struct grub_video_i386_vbeblit_info *dst,
+                                             struct grub_video_i386_vbeblit_info *src,
+                                             int x, int y,
+                                             int width, int height,
+                                             int offset_x, int offset_y);
+
+#endif /* ! GRUB_VBEBLIT_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/vbefill.h b/include/grub/i386/pc/vbefill.h
new file mode 100644 (file)
index 0000000..efc6378
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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_VBEFILL_MACHINE_HEADER
+#define GRUB_VBEFILL_MACHINE_HEADER    1
+
+/* NOTE: This header is private header for vbe driver and should not be used
+   in other parts of the code.  */
+
+struct grub_video_i386_vbeblit_info;
+
+void
+grub_video_i386_vbefill (struct grub_video_i386_vbeblit_info *dst,
+                         grub_video_color_t color, int x, int y,
+                         int width, int height);
+
+void
+grub_video_i386_vbefill_direct32 (struct grub_video_i386_vbeblit_info *dst,
+                                  grub_video_color_t color,  int x, int y,
+                                  int width, int height);
+
+void
+grub_video_i386_vbefill_direct24 (struct grub_video_i386_vbeblit_info *dst,
+                                  grub_video_color_t color, int x, int y,
+                                  int width, int height);
+
+void
+grub_video_i386_vbefill_direct16 (struct grub_video_i386_vbeblit_info *dst,
+                                  grub_video_color_t color, int x, int y,
+                                  int width, int height);
+
+void
+grub_video_i386_vbefill_direct8 (struct grub_video_i386_vbeblit_info *dst,
+                                grub_video_color_t color, int x, int y,
+                                int width, int height);
+
+#endif /* ! GRUB_VBEFILL_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/vbeutil.h b/include/grub/i386/pc/vbeutil.h
new file mode 100644 (file)
index 0000000..9b5be21
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *  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/>.
+ */
+
+/* NOTE: This header is private header for vbe driver and should not be used
+   in other parts of the code.  */
+
+#ifndef GRUB_VBEUTIL_MACHINE_HEADER
+#define GRUB_VBEUTIL_MACHINE_HEADER    1
+
+#include <grub/types.h>
+#include <grub/video.h>
+
+struct grub_video_i386_vbeblit_info
+{
+  struct grub_video_mode_info *mode_info;
+  void *data;
+};
+
+grub_uint8_t *get_data_ptr (struct grub_video_i386_vbeblit_info *source,
+                            unsigned int x, unsigned int y);
+
+grub_video_color_t get_pixel (struct grub_video_i386_vbeblit_info *source,
+                              unsigned int x, unsigned int y);
+
+void set_pixel (struct grub_video_i386_vbeblit_info *source,
+                unsigned int x, unsigned int y, grub_video_color_t color);
+
+#endif /* ! GRUB_VBEUTIL_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/vga.h b/include/grub/i386/pc/vga.h
new file mode 100644 (file)
index 0000000..b982239
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  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
+
+/* Set the video mode to MODE and return the previous mode.  */
+unsigned char EXPORT_FUNC(grub_vga_set_mode) (unsigned char mode);
+
+/* Return a pointer to the ROM font table.  */
+unsigned char *EXPORT_FUNC(grub_vga_get_font) (void);
+
+#endif /* ! GRUB_VGA_MACHINE_HEADER */
diff --git a/include/grub/i386/pci.h b/include/grub/i386/pci.h
new file mode 100644 (file)
index 0000000..f4f08ab
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  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_PCI_H
+#define        GRUB_CPU_PCI_H  1
+
+#include <grub/types.h>
+#include <grub/i386/io.h>
+
+#define GRUB_PCI_ADDR_REG      0xcf8
+#define GRUB_PCI_DATA_REG      0xcfc
+
+static inline grub_uint32_t
+grub_pci_read (grub_pci_address_t addr)
+{
+  grub_outl (addr, GRUB_PCI_ADDR_REG);
+  return grub_inl (GRUB_PCI_DATA_REG);
+}
+
+#endif /* GRUB_CPU_PCI_H */
diff --git a/include/grub/i386/pit.h b/include/grub/i386/pit.h
new file mode 100644 (file)
index 0000000..0da271d
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *  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 KERNEL_CPU_PIT_HEADER
+#define KERNEL_CPU_PIT_HEADER   1
+
+#include <grub/types.h>
+
+extern void grub_pit_wait (grub_uint16_t tics);
+
+#endif /* ! KERNEL_CPU_PIT_HEADER */
diff --git a/include/grub/i386/reboot.h b/include/grub/i386/reboot.h
new file mode 100644 (file)
index 0000000..5bcbb5d
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  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/>.
+ */
+
+extern void grub_reboot (void);
diff --git a/include/grub/i386/setjmp.h b/include/grub/i386/setjmp.h
new file mode 100644 (file)
index 0000000..02b0d8f
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,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_SETJMP_CPU_HEADER
+#define GRUB_SETJMP_CPU_HEADER 1
+
+typedef unsigned long grub_jmp_buf[6];
+
+int grub_setjmp (grub_jmp_buf env) __attribute__ ((cdecl, regparm (3)));
+void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn, cdecl,
+                                                             regparm (3)));
+
+#endif /* ! GRUB_SETJMP_CPU_HEADER */
diff --git a/include/grub/i386/time.h b/include/grub/i386/time.h
new file mode 100644 (file)
index 0000000..842882c
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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
+
+static __inline void
+grub_cpu_idle (void)
+{
+  /* FIXME: this can't work until we handle interrupts.  */
+/*  __asm__ __volatile__ ("hlt"); */
+}
+
+#endif /* ! KERNEL_CPU_TIME_HEADER */
diff --git a/include/grub/i386/tsc.h b/include/grub/i386/tsc.h
new file mode 100644 (file)
index 0000000..9633701
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ *  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 KERNEL_CPU_TSC_HEADER
+#define KERNEL_CPU_TSC_HEADER   1
+
+#include <grub/types.h>
+
+/* Read the TSC value, which increments with each CPU clock cycle. */
+static __inline grub_uint64_t
+grub_get_tsc (void)
+{
+  grub_uint32_t lo, hi;
+
+  /* The CPUID instruction is a 'serializing' instruction, and
+     avoids out-of-order execution of the RDTSC instruction. */
+  __asm__ __volatile__ ("xorl %%eax, %%eax\n\t"
+                        "cpuid":::"%rax", "%rbx", "%rcx", "%rdx");
+  /* Read TSC value.  We cannot use "=A", since this would use
+     %rax on x86_64. */
+  __asm__ __volatile__ ("rdtsc":"=a" (lo), "=d" (hi));
+
+  return (((grub_uint64_t) hi) << 32) | lo;
+}
+
+#ifdef __x86_64__
+
+static __inline int
+grub_cpu_is_cpuid_supported (void)
+{
+  grub_uint64_t id_supported;
+
+  __asm__ ("pushfq\n\t"
+           "popq %%rax             /* Get EFLAGS into EAX */\n\t"
+           "movq %%rax, %%rcx      /* Save original flags in ECX */\n\t"
+           "xorq $0x200000, %%rax  /* Flip ID bit in EFLAGS */\n\t"
+           "pushq %%rax            /* Store modified EFLAGS on stack */\n\t"
+           "popfq                  /* Replace current EFLAGS */\n\t"
+           "pushfq                 /* Read back the EFLAGS */\n\t"
+           "popq %%rax             /* Get EFLAGS into EAX */\n\t"
+           "xorq %%rcx, %%rax      /* Check if flag could be modified */\n\t"
+           : "=a" (id_supported)
+           : /* No inputs.  */
+           : /* Clobbered:  */ "%rcx");
+
+  return id_supported != 0;
+}
+
+#else
+
+static __inline int
+grub_cpu_is_cpuid_supported (void)
+{
+  grub_uint32_t id_supported;
+
+  __asm__ ("pushfl\n\t"
+           "popl %%eax             /* Get EFLAGS into EAX */\n\t"
+           "movl %%eax, %%ecx      /* Save original flags in ECX */\n\t"
+           "xorl $0x200000, %%eax  /* Flip ID bit in EFLAGS */\n\t"
+           "pushl %%eax            /* Store modified EFLAGS on stack */\n\t"
+           "popfl                  /* Replace current EFLAGS */\n\t"
+           "pushfl                 /* Read back the EFLAGS */\n\t"
+           "popl %%eax             /* Get EFLAGS into EAX */\n\t"
+           "xorl %%ecx, %%eax      /* Check if flag could be modified */\n\t"
+           : "=a" (id_supported)
+           : /* No inputs.  */
+           : /* Clobbered:  */ "%rcx");
+
+  return id_supported != 0;
+}
+
+#endif
+
+static __inline int
+grub_cpu_is_tsc_supported (void)
+{
+  if (! grub_cpu_is_cpuid_supported ())
+    return 0;
+
+  grub_uint32_t features;
+  __asm__ ("movl $1, %%eax\n\t"
+           "cpuid"
+           : "=d" (features)
+           : /* No inputs.  */
+           : /* Clobbered:  */ "%rax", "%rbx", "%rcx");
+  return (features & (1 << 4)) != 0;
+}
+
+void grub_tsc_init (void);
+grub_uint64_t grub_tsc_get_time_ms (void);
+
+#endif /* ! KERNEL_CPU_TSC_HEADER */
diff --git a/include/grub/i386/types.h b/include/grub/i386/types.h
new file mode 100644 (file)
index 0000000..0ac6473
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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_TYPES_CPU_HEADER
+#define GRUB_TYPES_CPU_HEADER  1
+
+/* The size of void *.  */
+#define GRUB_TARGET_SIZEOF_VOID_P      4
+
+/* The size of long.  */
+#define GRUB_TARGET_SIZEOF_LONG                4
+
+/* i386 is little-endian.  */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
diff --git a/include/grub/i386/vga_common.h b/include/grub/i386/vga_common.h
new file mode 100644 (file)
index 0000000..f17fc01
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,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_COMMON_CPU_HEADER
+#define GRUB_VGA_COMMON_CPU_HEADER     1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/term.h>
+
+extern grub_uint8_t grub_console_cur_color;
+
+void grub_console_putchar (grub_uint32_t c);
+grub_ssize_t grub_console_getcharwidth (grub_uint32_t c);
+grub_uint16_t grub_console_getwh (void);
+void grub_console_setcolorstate (grub_term_color_state state);
+void grub_console_setcolor (grub_uint8_t normal_color, grub_uint8_t highlight_color);
+void grub_console_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_color);
+
+/* Implemented in both kern/i386/pc/startup.S and vga_text.c;  this symbol
+   is not exported, so there's no collision, but vga_common.c expects this
+   prototype to be the same.  */
+void grub_console_real_putchar (int c);
+
+#endif /* ! GRUB_VGA_COMMON_CPU_HEADER */
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
new file mode 100644 (file)
index 0000000..628d888
--- /dev/null
@@ -0,0 +1,177 @@
+/* ieee1275.h - Access the Open Firmware client interface.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,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_IEEE1275_HEADER
+#define GRUB_IEEE1275_HEADER   1
+
+#include <stdint.h>
+#include <grub/err.h>
+#include <grub/types.h>
+#include <grub/machine/ieee1275.h>
+
+/* Maps a device alias to a pathname.  */
+struct grub_ieee1275_devalias
+{
+  char *name;
+  char *path;
+  char *type;
+};
+
+struct grub_ieee1275_mem_region 
+{
+  unsigned int start;
+  unsigned int size;
+};
+
+#ifndef IEEE1275_CALL_ENTRY_FN
+#define IEEE1275_CALL_ENTRY_FN(args) (*grub_ieee1275_entry_fn) (args)
+#endif
+
+/* All backcalls to the firmware is done by calling an entry function 
+   which was passed to us from the bootloader.  When doing the backcall, 
+   a structure is passed which specifies what the firmware should do.  
+   NAME is the requested service.  NR_INS and NR_OUTS is the number of
+   passed arguments and the expected number of return values, resp. */
+struct grub_ieee1275_common_hdr
+{
+  grub_ieee1275_cell_t name;
+  grub_ieee1275_cell_t nr_ins;
+  grub_ieee1275_cell_t nr_outs;
+};
+
+#define INIT_IEEE1275_COMMON(p, xname, xins, xouts) \
+  (p)->name = (grub_ieee1275_cell_t) xname; \
+  (p)->nr_ins = (grub_ieee1275_cell_t) xins; \
+  (p)->nr_outs = (grub_ieee1275_cell_t) xouts
+
+typedef grub_ieee1275_cell_t grub_ieee1275_ihandle_t;
+typedef grub_ieee1275_cell_t grub_ieee1275_phandle_t;
+
+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 *);
+
+enum grub_ieee1275_flag
+{
+  /* Old World Macintosh firmware fails seek when "dev:0" is opened.  */
+  GRUB_IEEE1275_FLAG_NO_PARTITION_0,
+
+  /* Apple firmware runs in translated mode and requires use of the "map"
+     method.  Other firmware runs in untranslated mode and doesn't like "map"
+     calls.  */
+  GRUB_IEEE1275_FLAG_REAL_MODE,
+
+  /* CHRP specifies partitions are numbered from 1 (partition 0 refers to the
+     whole disk). However, CodeGen firmware numbers partitions from 0.  */
+  GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS,
+
+  /* CodeGen firmware does not correctly implement "output-device output" */
+  GRUB_IEEE1275_FLAG_BROKEN_OUTPUT,
+
+  /* OLPC / XO firmware hangs when accessing USB devices.  */
+  GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY,
+
+  /* Open Hack'Ware stops when trying to set colors */
+  GRUB_IEEE1275_FLAG_CANNOT_SET_COLORS,
+
+  /* Open Hack'Ware stops when grub_ieee1275_interpret is used.  */
+  GRUB_IEEE1275_FLAG_CANNOT_INTERPRET,
+
+  /* Open Hack'Ware has no memory map, just claim what we need.  */
+  GRUB_IEEE1275_FLAG_FORCE_CLAIM,
+
+  /* Open Hack'Ware don't support the ANSI sequence.  */
+  GRUB_IEEE1275_FLAG_NO_ANSI,
+};
+
+extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag);
+extern void EXPORT_FUNC(grub_ieee1275_set_flag) (enum grub_ieee1275_flag flag);
+
+\f
+
+
+void EXPORT_FUNC(grub_ieee1275_init) (void);
+int EXPORT_FUNC(grub_ieee1275_finddevice) (char *name,
+                                          grub_ieee1275_phandle_t *phandlep);
+int EXPORT_FUNC(grub_ieee1275_get_property) (grub_ieee1275_phandle_t phandle,
+                                            const char *property, void *buf,
+                                            grub_size_t size,
+                                            grub_ssize_t *actual);
+int EXPORT_FUNC(grub_ieee1275_get_integer_property) (grub_ieee1275_phandle_t phandle,
+                                                    const char *property, grub_uint32_t *buf,
+                                                    grub_size_t size,
+                                                    grub_ssize_t *actual);
+int EXPORT_FUNC(grub_ieee1275_next_property) (grub_ieee1275_phandle_t phandle,
+                                             char *prev_prop, char *prop);
+int EXPORT_FUNC(grub_ieee1275_get_property_length) 
+     (grub_ieee1275_phandle_t phandle, const char *prop, grub_ssize_t *length);
+int EXPORT_FUNC(grub_ieee1275_instance_to_package) 
+     (grub_ieee1275_ihandle_t ihandle, grub_ieee1275_phandle_t *phandlep);
+int EXPORT_FUNC(grub_ieee1275_package_to_path) (grub_ieee1275_phandle_t phandle,
+                                               char *path, grub_size_t len,
+                                               grub_ssize_t *actual);
+int EXPORT_FUNC(grub_ieee1275_instance_to_path) 
+     (grub_ieee1275_ihandle_t ihandle, char *path, grub_size_t len,
+      grub_ssize_t *actual);
+int EXPORT_FUNC(grub_ieee1275_write) (grub_ieee1275_ihandle_t ihandle,
+                                     void *buffer, grub_size_t len,
+                                     grub_ssize_t *actualp);
+int EXPORT_FUNC(grub_ieee1275_read) (grub_ieee1275_ihandle_t ihandle,
+                                    void *buffer, grub_size_t len,
+                                    grub_ssize_t *actualp);
+int EXPORT_FUNC(grub_ieee1275_seek) (grub_ieee1275_ihandle_t ihandle,
+                                    int pos_hi, int pos_lo,
+                                    grub_ssize_t *result);
+int EXPORT_FUNC(grub_ieee1275_peer) (grub_ieee1275_phandle_t node,
+                                    grub_ieee1275_phandle_t *result);
+int EXPORT_FUNC(grub_ieee1275_child) (grub_ieee1275_phandle_t node,
+                                     grub_ieee1275_phandle_t *result);
+int EXPORT_FUNC(grub_ieee1275_parent) (grub_ieee1275_phandle_t node,
+                                      grub_ieee1275_phandle_t *result);
+int EXPORT_FUNC(grub_ieee1275_interpret) (const char *command,
+                                         grub_ieee1275_cell_t *catch);
+int EXPORT_FUNC(grub_ieee1275_enter) (void);
+void EXPORT_FUNC(grub_ieee1275_exit) (void) __attribute__ ((noreturn));
+int EXPORT_FUNC(grub_ieee1275_open) (const char *node,
+                                    grub_ieee1275_ihandle_t *result);
+int EXPORT_FUNC(grub_ieee1275_close) (grub_ieee1275_ihandle_t ihandle);
+int EXPORT_FUNC(grub_ieee1275_claim) (grub_addr_t addr, grub_size_t size,
+                                     unsigned int align, grub_addr_t *result);
+int EXPORT_FUNC(grub_ieee1275_release) (grub_addr_t addr, grub_size_t size);
+int EXPORT_FUNC(grub_ieee1275_set_property) (grub_ieee1275_phandle_t phandle,
+                                            const char *propname, void *buf,
+                                            grub_size_t size,
+                                            grub_ssize_t *actual);
+int EXPORT_FUNC(grub_ieee1275_set_color) (grub_ieee1275_ihandle_t ihandle,
+                                         int index, int r, int g, int b);
+int EXPORT_FUNC(grub_ieee1275_milliseconds) (grub_uint32_t *msecs);
+
+
+grub_err_t EXPORT_FUNC(grub_devalias_iterate)
+     (int (*hook) (struct grub_ieee1275_devalias *alias));
+grub_err_t EXPORT_FUNC(grub_children_iterate) (char *devpath,
+     int (*hook) (struct grub_ieee1275_devalias *alias));
+grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate)
+     (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
+int EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size);
+
+char *EXPORT_FUNC(grub_ieee1275_encode_devname) (const char *path);
+char *EXPORT_FUNC(grub_ieee1275_get_filename) (const char *path);
+
+#endif /* ! GRUB_IEEE1275_HEADER */
diff --git a/include/grub/ieee1275/ofdisk.h b/include/grub/ieee1275/ofdisk.h
new file mode 100644 (file)
index 0000000..2f69e3f
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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 GRUB_OFDISK_HEADER
+#define GRUB_OFDISK_HEADER     1
+
+extern void grub_ofdisk_init (void);
+extern void grub_ofdisk_fini (void);
+
+#endif /* ! GRUB_INIT_HEADER */
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
new file mode 100644 (file)
index 0000000..adaee58
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,2006,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_KERNEL_HEADER
+#define GRUB_KERNEL_HEADER     1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+
+/* The module header.  */
+struct grub_module_header
+{
+  /* The type of object.  */
+  grub_int8_t type;
+  enum
+  {
+    OBJ_TYPE_ELF,
+    OBJ_TYPE_MEMDISK,
+  }  grub_module_header_types;
+
+  /* The size of object (including this header).  */
+  grub_target_size_t size;
+};
+
+/* "gmim" (GRUB Module Info Magic).  */
+#define GRUB_MODULE_MAGIC 0x676d696d
+
+struct grub_module_info
+{
+  /* Magic number so we know we have modules present.  */
+  grub_uint32_t magic;
+#if GRUB_TARGET_SIZEOF_VOID_P == 8
+  grub_uint32_t padding;
+#endif
+  /* The offset of the modules.  */
+  grub_target_off_t offset;
+  /* The size of all modules plus this header.  */
+  grub_target_size_t size;
+};
+
+extern grub_addr_t grub_arch_modules_addr (void);
+
+extern void EXPORT_FUNC(grub_module_iterate) (int (*hook) (struct grub_module_header *));
+
+/* The start point of the C code.  */
+void grub_main (void);
+
+/* The machine-specific initialization. This must initialize memory.  */
+void grub_machine_init (void);
+
+/* The machine-specific finalization.  */
+void grub_machine_fini (void);
+
+/* The machine-specific prefix initialization.  */
+void grub_machine_set_prefix (void);
+
+/* Register all the exported symbols. This is automatically generated.  */
+void grub_register_exported_symbols (void);
+
+#endif /* ! GRUB_KERNEL_HEADER */
diff --git a/include/grub/lib/LzFind.h b/include/grub/lib/LzFind.h
new file mode 100644 (file)
index 0000000..69447b6
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (c) 1999-2008 Igor Pavlov
+ *  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/>.
+ */
+
+/*
+ * This code was taken from LZMA SDK 4.58 beta, and was slightly modified
+ * to adapt it to GRUB's requirement.
+ *
+ * See <http://www.7-zip.org>, for more information about LZMA.
+ */
+
+#ifndef __LZFIND_H
+#define __LZFIND_H
+
+#include <grub/lib/LzmaTypes.h>
+
+typedef UInt32 CLzRef;
+
+typedef struct _CMatchFinder
+{
+  Byte *buffer;
+  UInt32 pos;
+  UInt32 posLimit;
+  UInt32 streamPos;
+  UInt32 lenLimit;
+
+  UInt32 cyclicBufferPos;
+  UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
+
+  UInt32 matchMaxLen;
+  CLzRef *hash;
+  CLzRef *son;
+  UInt32 hashMask;
+  UInt32 cutValue;
+
+  Byte *bufferBase;
+  ISeqInStream *stream;
+  int streamEndWasReached;
+
+  UInt32 blockSize;
+  UInt32 keepSizeBefore;
+  UInt32 keepSizeAfter;
+
+  UInt32 numHashBytes;
+  int directInput;
+  int btMode;
+  /* int skipModeBits; */
+  int bigHash;
+  UInt32 historySize;
+  UInt32 fixedHashSize;
+  UInt32 hashSizeSum;
+  UInt32 numSons;
+  SRes result;
+  UInt32 crc[256];
+} CMatchFinder;
+
+#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
+#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
+
+#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
+
+int MatchFinder_NeedMove(CMatchFinder *p);
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
+void MatchFinder_MoveBlock(CMatchFinder *p);
+void MatchFinder_ReadIfRequired(CMatchFinder *p);
+
+void MatchFinder_Construct(CMatchFinder *p);
+
+/* Conditions:
+     historySize <= 3 GB
+     keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
+*/
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
+    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+    ISzAlloc *alloc);
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
+
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
+    UInt32 *distances, UInt32 maxLen);
+
+/*
+Conditions:
+  Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
+  Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
+*/
+
+typedef void (*Mf_Init_Func)(void *object);
+typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
+typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
+typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
+typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
+typedef void (*Mf_Skip_Func)(void *object, UInt32);
+
+typedef struct _IMatchFinder
+{
+  Mf_Init_Func Init;
+  Mf_GetIndexByte_Func GetIndexByte;
+  Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
+  Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
+  Mf_GetMatches_Func GetMatches;
+  Mf_Skip_Func Skip;
+} IMatchFinder;
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
+
+void MatchFinder_Init(CMatchFinder *p);
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
+
+#endif
diff --git a/include/grub/lib/LzHash.h b/include/grub/lib/LzHash.h
new file mode 100644 (file)
index 0000000..c3d5586
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (c) 1999-2008 Igor Pavlov
+ *  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/>.
+ */
+
+/*
+ * This code was taken from LZMA SDK 4.58 beta, and was slightly modified
+ * to adapt it to GRUB's requirement.
+ *
+ * See <http://www.7-zip.org>, for more information about LZMA.
+ */
+
+#ifndef __LZHASH_H
+#define __LZHASH_H
+
+#define kHash2Size (1 << 10)
+#define kHash3Size (1 << 16)
+#define kHash4Size (1 << 20)
+
+#define kFix3HashSize (kHash2Size)
+#define kFix4HashSize (kHash2Size + kHash3Size)
+#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
+
+#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
+
+#define HASH3_CALC { \
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+  hash2Value = temp & (kHash2Size - 1); \
+  hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
+
+#define HASH4_CALC { \
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+  hash2Value = temp & (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+  hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
+
+#define HASH5_CALC { \
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+  hash2Value = temp & (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
+  hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
+  hash4Value &= (kHash4Size - 1); }
+
+/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
+#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
+
+
+#define MT_HASH2_CALC \
+  hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
+
+#define MT_HASH3_CALC { \
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+  hash2Value = temp & (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
+
+#define MT_HASH4_CALC { \
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+  hash2Value = temp & (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
+
+#endif
diff --git a/include/grub/lib/LzmaDec.h b/include/grub/lib/LzmaDec.h
new file mode 100644 (file)
index 0000000..1e66b74
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (c) 1999-2008 Igor Pavlov
+ *  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/>.
+ */
+
+/*
+ * This code was taken from LZMA SDK 4.58 beta, and was slightly modified
+ * to adapt it to GRUB's requirement.
+ *
+ * See <http://www.7-zip.org>, for more information about LZMA.
+ */
+
+#ifndef __LZMADEC_H
+#define __LZMADEC_H
+
+#include "Types.h"
+
+/* #define _LZMA_PROB32 */
+/* _LZMA_PROB32 can increase the speed on some CPUs,
+   but memory usage for CLzmaDec::probs will be doubled in that case */
+
+#ifdef _LZMA_PROB32
+#define CLzmaProb UInt32
+#else
+#define CLzmaProb UInt16
+#endif
+
+
+/* ---------- LZMA Properties ---------- */
+
+#define LZMA_PROPS_SIZE 5
+
+typedef struct _CLzmaProps
+{
+  unsigned lc, lp, pb;
+  UInt32 dicSize;
+} CLzmaProps;
+
+/* LzmaProps_Decode - decodes properties
+Returns:
+  SZ_OK
+  SZ_ERROR_UNSUPPORTED - Unsupported properties
+*/
+
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
+
+
+/* ---------- LZMA Decoder state ---------- */
+
+/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
+   Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
+
+#define LZMA_REQUIRED_INPUT_MAX 20
+
+typedef struct
+{
+  CLzmaProps prop;
+  CLzmaProb *probs;
+  Byte *dic;
+  const Byte *buf;
+  UInt32 range, code;
+  SizeT dicPos;
+  SizeT dicBufSize;
+  UInt32 processedPos;
+  UInt32 checkDicSize;
+  unsigned state;
+  UInt32 reps[4];
+  unsigned remainLen;
+  int needFlush;
+  int needInitState;
+  UInt32 numProbs;
+  unsigned tempBufSize;
+  Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
+} CLzmaDec;
+
+#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
+
+void LzmaDec_Init(CLzmaDec *p);
+
+/* There are two types of LZMA streams:
+     0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
+     1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
+
+typedef enum
+{
+  LZMA_FINISH_ANY,   /* finish at any point */
+  LZMA_FINISH_END    /* block must be finished at the end */
+} ELzmaFinishMode;
+
+/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
+
+   You must use LZMA_FINISH_END, when you know that current output buffer
+   covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
+
+   If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
+   and output value of destLen will be less than output buffer size limit.
+   You can check status result also.
+
+   You can use multiple checks to test data integrity after full decompression:
+     1) Check Result and "status" variable.
+     2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
+     3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
+        You must use correct finish mode in that case. */
+
+typedef enum
+{
+  LZMA_STATUS_NOT_SPECIFIED,               /* use main error code instead */
+  LZMA_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */
+  LZMA_STATUS_NOT_FINISHED,                /* stream was not finished */
+  LZMA_STATUS_NEEDS_MORE_INPUT,            /* you must provide more input bytes */
+  LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK  /* there is probability that stream was finished without end mark */
+} ELzmaStatus;
+
+/* ELzmaStatus is used only as output value for function call */
+
+
+/* ---------- Interfaces ---------- */
+
+/* There are 3 levels of interfaces:
+     1) Dictionary Interface
+     2) Buffer Interface
+     3) One Call Interface
+   You can select any of these interfaces, but don't mix functions from different
+   groups for same object. */
+
+
+/* There are two variants to allocate state for Dictionary Interface:
+     1) LzmaDec_Allocate / LzmaDec_Free
+     2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
+   You can use variant 2, if you set dictionary buffer manually.
+   For Buffer Interface you must always use variant 1.
+
+LzmaDec_Allocate* can return:
+  SZ_OK
+  SZ_ERROR_MEM         - Memory allocation error
+  SZ_ERROR_UNSUPPORTED - Unsupported properties
+*/
+
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
+
+SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
+void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
+
+/* ---------- Dictionary Interface ---------- */
+
+/* You can use it, if you want to eliminate the overhead for data copying from
+   dictionary to some other external buffer.
+   You must work with CLzmaDec variables directly in this interface.
+
+   STEPS:
+     LzmaDec_Constr()
+     LzmaDec_Allocate()
+     for (each new stream)
+     {
+       LzmaDec_Init()
+       while (it needs more decompression)
+       {
+         LzmaDec_DecodeToDic()
+         use data from CLzmaDec::dic and update CLzmaDec::dicPos
+       }
+     }
+     LzmaDec_Free()
+*/
+
+/* LzmaDec_DecodeToDic
+
+   The decoding to internal dictionary buffer (CLzmaDec::dic).
+   You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
+
+finishMode:
+  It has meaning only if the decoding reaches output limit (dicLimit).
+  LZMA_FINISH_ANY - Decode just dicLimit bytes.
+  LZMA_FINISH_END - Stream must be finished after dicLimit.
+
+Returns:
+  SZ_OK
+    status:
+      LZMA_STATUS_FINISHED_WITH_MARK
+      LZMA_STATUS_NOT_FINISHED
+      LZMA_STATUS_NEEDS_MORE_INPUT
+      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+  SZ_ERROR_DATA - Data error
+*/
+
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
+
+
+/* ---------- Buffer Interface ---------- */
+
+/* It's zlib-like interface.
+   See LzmaDec_DecodeToDic description for information about STEPS and return results,
+   but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
+   to work with CLzmaDec variables manually.
+
+finishMode:
+  It has meaning only if the decoding reaches output limit (*destLen).
+  LZMA_FINISH_ANY - Decode just destLen bytes.
+  LZMA_FINISH_END - Stream must be finished after (*destLen).
+*/
+
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
+
+
+/* ---------- One Call Interface ---------- */
+
+/* LzmaDecode
+
+finishMode:
+  It has meaning only if the decoding reaches output limit (*destLen).
+  LZMA_FINISH_ANY - Decode just destLen bytes.
+  LZMA_FINISH_END - Stream must be finished after (*destLen).
+
+Returns:
+  SZ_OK
+    status:
+      LZMA_STATUS_FINISHED_WITH_MARK
+      LZMA_STATUS_NOT_FINISHED
+      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+  SZ_ERROR_DATA - Data error
+  SZ_ERROR_MEM  - Memory allocation error
+  SZ_ERROR_UNSUPPORTED - Unsupported properties
+  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
+*/
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+    ELzmaStatus *status, ISzAlloc *alloc);
+
+#endif
diff --git a/include/grub/lib/LzmaEnc.h b/include/grub/lib/LzmaEnc.h
new file mode 100644 (file)
index 0000000..c625cd0
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (c) 1999-2008 Igor Pavlov
+ *  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/>.
+ */
+
+/*
+ * This code was taken from LZMA SDK 4.58 beta, and was slightly modified
+ * to adapt it to GRUB's requirement.
+ *
+ * See <http://www.7-zip.org>, for more information about LZMA.
+ */
+
+#ifndef __LZMAENC_H
+#define __LZMAENC_H
+
+#include "LzmaTypes.h"
+
+#define LZMA_PROPS_SIZE 5
+
+typedef struct _CLzmaEncProps
+{
+  int level;       /*  0 <= level <= 9 */
+  UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
+                      (1 << 12) <= dictSize <= (1 << 30) for 64-bit version
+                       default = (1 << 24) */
+  int lc;          /* 0 <= lc <= 8, default = 3 */
+  int lp;          /* 0 <= lp <= 4, default = 0 */
+  int pb;          /* 0 <= pb <= 4, default = 2 */
+  int algo;        /* 0 - fast, 1 - normal, default = 1 */
+  int fb;          /* 5 <= fb <= 273, default = 32 */
+  int btMode;      /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
+  int numHashBytes; /* 2, 3 or 4, default = 4 */
+  UInt32 mc;        /* 1 <= mc <= (1 << 30), default = 32 */
+  unsigned writeEndMark;  /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
+  int numThreads;  /* 1 or 2, default = 2 */
+} CLzmaEncProps;
+
+void LzmaEncProps_Init(CLzmaEncProps *p);
+void LzmaEncProps_Normalize(CLzmaEncProps *p);
+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
+
+
+/* ---------- CLzmaEncHandle Interface ---------- */
+
+/* LzmaEnc_* functions can return the following exit codes:
+Returns:
+  SZ_OK           - OK
+  SZ_ERROR_MEM    - Memory allocation error
+  SZ_ERROR_PARAM  - Incorrect paramater in props
+  SZ_ERROR_WRITE  - Write callback error.
+  SZ_ERROR_PROGRESS - some break from progress callback
+  SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
+*/
+
+typedef void * CLzmaEncHandle;
+
+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
+SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
+SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
+SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+
+/* ---------- One Call Interface ---------- */
+
+/* LzmaEncode
+Return code:
+  SZ_OK               - OK
+  SZ_ERROR_MEM        - Memory allocation error
+  SZ_ERROR_PARAM      - Incorrect paramater
+  SZ_ERROR_OUTPUT_EOF - output buffer overflow
+  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)
+*/
+
+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+
+#endif
diff --git a/include/grub/lib/LzmaTypes.h b/include/grub/lib/LzmaTypes.h
new file mode 100644 (file)
index 0000000..1e783a2
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (c) 1999-2008 Igor Pavlov
+ *  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/>.
+ */
+
+/*
+ * This code was taken from LZMA SDK 4.58 beta, and was slightly modified
+ * to adapt it to GRUB's requirement.
+ *
+ * See <http://www.7-zip.org>, for more information about LZMA.
+ */
+
+#ifndef __7Z_TYPES_H
+#define __7Z_TYPES_H
+
+#define SZ_OK 0
+
+#define SZ_ERROR_DATA 1
+#define SZ_ERROR_MEM 2
+#define SZ_ERROR_CRC 3
+#define SZ_ERROR_UNSUPPORTED 4
+#define SZ_ERROR_PARAM 5
+#define SZ_ERROR_INPUT_EOF 6
+#define SZ_ERROR_OUTPUT_EOF 7
+#define SZ_ERROR_READ 8
+#define SZ_ERROR_WRITE 9
+#define SZ_ERROR_PROGRESS 10
+#define SZ_ERROR_FAIL 11
+#define SZ_ERROR_THREAD 12
+
+#define SZ_ERROR_ARCHIVE 16
+#define SZ_ERROR_NO_ARCHIVE 17
+
+typedef int SRes;
+
+#ifndef RINOK
+#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
+#endif
+
+typedef unsigned char Byte;
+typedef short Int16;
+typedef unsigned short UInt16;
+
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef long Int32;
+typedef unsigned long UInt32;
+#else
+typedef int Int32;
+typedef unsigned int UInt32;
+#endif
+
+/* #define _SZ_NO_INT_64 */
+/* define it if your compiler doesn't support 64-bit integers */
+
+#ifdef _SZ_NO_INT_64
+
+typedef long Int64;
+typedef unsigned long UInt64;
+
+#else
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#else
+typedef long long int Int64;
+typedef unsigned long long int UInt64;
+#endif
+
+#endif
+
+#ifdef _LZMA_NO_SYSTEM_SIZE_T
+typedef UInt32 SizeT;
+#else
+#include <stddef.h>
+typedef size_t SizeT;
+#endif
+
+typedef int Bool;
+#define True 1
+#define False 0
+
+
+#ifdef _MSC_VER
+
+#if _MSC_VER >= 1300
+#define MY_NO_INLINE __declspec(noinline)
+#else
+#define MY_NO_INLINE
+#endif
+
+#define MY_CDECL __cdecl
+#define MY_STD_CALL __stdcall
+#define MY_FAST_CALL MY_NO_INLINE __fastcall
+
+#else
+
+#define MY_CDECL
+#define MY_STD_CALL
+#define MY_FAST_CALL
+
+#endif
+
+
+/* The following interfaces use first parameter as pointer to structure */
+
+typedef struct
+{
+  SRes (*Read)(void *p, void *buf, size_t *size);
+    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
+       (output(*size) < input(*size)) is allowed */
+} ISeqInStream;
+
+typedef struct
+{
+  size_t (*Write)(void *p, const void *buf, size_t size);
+    /* Returns: result - the number of actually written bytes.
+      (result < size) means error */
+} ISeqOutStream;
+
+typedef struct
+{
+  SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
+    /* Returns: result. (result != SZ_OK) means break.
+       Value (UInt64)(Int64)-1 for size means unknown value. */
+} ICompressProgress;
+
+typedef struct
+{
+  void *(*Alloc)(void *p, size_t size);
+  void (*Free)(void *p, void *address); /* address can be 0 */
+} ISzAlloc;
+
+#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
+#define IAlloc_Free(p, a) (p)->Free((p), a)
+
+#endif
diff --git a/include/grub/lib/crc.h b/include/grub/lib/crc.h
new file mode 100644 (file)
index 0000000..ff7284d
--- /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_getcrc32 (grub_uint32_t crc, void *buf, int size);
+
+#endif /* ! GRUB_CRC_H */
diff --git a/include/grub/lib/datetime.h b/include/grub/lib/datetime.h
new file mode 100644 (file)
index 0000000..7b140cc
--- /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/>.
+ */
+
+#ifndef KERNEL_DATETIME_HEADER
+#define KERNEL_DATETIME_HEADER 1
+
+#include <grub/types.h>
+#include <grub/err.h>
+
+struct grub_datetime
+{
+  grub_uint16_t year;
+  grub_uint8_t month;
+  grub_uint8_t day;
+  grub_uint8_t hour;
+  grub_uint8_t minute;
+  grub_uint8_t second;
+};
+
+/* Return date and time.  */
+grub_err_t grub_get_datetime (struct grub_datetime *datetime);
+
+/* Set date and time.  */
+grub_err_t grub_set_datetime (struct grub_datetime *datetime);
+
+int grub_get_weekday (struct grub_datetime *datetime);
+char *grub_get_weekday_name (struct grub_datetime *datetime);
+
+#endif /* ! KERNEL_DATETIME_HEADER */
diff --git a/include/grub/lib/envblk.h b/include/grub/lib/envblk.h
new file mode 100644 (file)
index 0000000..5c1157e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  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_ENVBLK_HEADER
+#define GRUB_ENVBLK_HEADER     1
+
+#define GRUB_ENVBLK_SIGNATURE  0x764e6547      /* GeNv  */
+
+#define GRUB_ENVBLK_MAXLEN     8192
+
+#define GRUB_ENVBLK_DEFCFG     "grubenv"
+
+#ifndef ASM_FILE
+
+struct grub_envblk
+{
+  grub_uint32_t signature;
+  grub_uint16_t length;
+  char data[0];
+} __attribute__ ((packed));
+typedef struct grub_envblk *grub_envblk_t;
+
+grub_envblk_t grub_envblk_find (char *buf);
+int grub_envblk_insert (grub_envblk_t envblk, char *name, char *value);
+void grub_envblk_delete (grub_envblk_t envblk, char *name);
+void grub_envblk_iterate (grub_envblk_t envblk, int hook (char *name, char *value));
+
+#endif
+
+#endif /* ! GRUB_ENVBLK_HEADER */
diff --git a/include/grub/lib/hexdump.h b/include/grub/lib/hexdump.h
new file mode 100644 (file)
index 0000000..23c6fa6
--- /dev/null
@@ -0,0 +1,25 @@
+/* hexdump.h - prototypes for dump */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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_HEXDUMP_H
+#define GRUB_HEXDUMP_H 1
+
+void hexdump (unsigned long bse,char* buf,int len);
+
+#endif /* ! GRUB_HEXDUMP_H */
diff --git a/include/grub/loader.h b/include/grub/loader.h
new file mode 100644 (file)
index 0000000..1ae5fdd
--- /dev/null
@@ -0,0 +1,44 @@
+/* loader.h - OS loaders */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,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_LOADER_HEADER
+#define GRUB_LOADER_HEADER     1
+
+#include <grub/file.h>
+#include <grub/symbol.h>
+#include <grub/err.h>
+#include <grub/types.h>
+
+/* Check if a loader is loaded.  */
+int EXPORT_FUNC(grub_loader_is_loaded) (void);
+
+/* Set loader functions. NORETURN must be set to true, if BOOT won't return
+   to the original state.  */
+void EXPORT_FUNC(grub_loader_set) (grub_err_t (*boot) (void),
+                                  grub_err_t (*unload) (void),
+                                  int noreturn);
+
+/* Unset current loader, if any.  */
+void EXPORT_FUNC(grub_loader_unset) (void);
+
+/* Call the boot hook in current loader. This may or may not return,
+   depending on the setting by grub_loader_set.  */
+grub_err_t EXPORT_FUNC(grub_loader_boot) (void);
+
+#endif /* ! GRUB_LOADER_HEADER */
diff --git a/include/grub/lvm.h b/include/grub/lvm.h
new file mode 100644 (file)
index 0000000..dd91cc6
--- /dev/null
@@ -0,0 +1,129 @@
+/* lvm.h - On disk structures for LVM. */
+/*
+ *  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_LVM_H
+#define GRUB_LVM_H     1
+
+#include <grub/types.h>
+
+/* Length of ID string, excluding terminating zero. */
+#define GRUB_LVM_ID_STRLEN 38
+
+struct grub_lvm_vg {
+  char id[GRUB_LVM_ID_STRLEN+1];
+  char *name;
+  int extent_size;
+  struct grub_lvm_pv *pvs;
+  struct grub_lvm_lv *lvs;
+  struct grub_lvm_vg *next;
+};
+
+struct grub_lvm_pv {
+  char id[GRUB_LVM_ID_STRLEN+1];
+  char *name;
+  grub_disk_t disk;
+  int start; /* Sector number where the data area starts. */
+  struct grub_lvm_pv *next;
+};
+
+struct grub_lvm_lv {
+  char *name;
+  unsigned int number;
+  unsigned int segment_count;
+  grub_uint64_t size;
+  struct grub_lvm_segment *segments; /* Pointer to segment_count segments. */
+  struct grub_lvm_vg *vg;
+  struct grub_lvm_lv *next;
+};
+
+struct grub_lvm_segment {
+  unsigned int start_extent;
+  unsigned int extent_count;
+  unsigned int stripe_count;
+  unsigned int stripe_size;
+  struct grub_lvm_stripe *stripes; /* Pointer to stripe_count stripes. */
+};
+
+struct grub_lvm_stripe {
+  int start;
+  struct grub_lvm_pv *pv;
+};
+
+#define GRUB_LVM_LABEL_SIZE GRUB_DISK_SECTOR_SIZE
+#define GRUB_LVM_LABEL_SCAN_SECTORS 4L
+
+#define GRUB_LVM_LABEL_ID "LABELONE"
+#define GRUB_LVM_LVM2_LABEL "LVM2 001"
+
+#define GRUB_LVM_ID_LEN 32
+
+/* On disk - 32 bytes */
+struct grub_lvm_label_header {
+  grub_int8_t id[8];           /* LABELONE */
+  grub_uint64_t sector_xl;     /* Sector number of this label */
+  grub_uint32_t crc_xl;                /* From next field to end of sector */
+  grub_uint32_t offset_xl;     /* Offset from start of struct to contents */
+  grub_int8_t type[8];         /* LVM2 001 */
+} __attribute__ ((packed));
+
+/* On disk */
+struct grub_lvm_disk_locn {
+  grub_uint64_t offset;                /* Offset in bytes to start sector */
+  grub_uint64_t size;          /* Bytes */
+} __attribute__ ((packed));
+
+/* Fields with the suffix _xl should be xlate'd wherever they appear */
+/* On disk */
+struct grub_lvm_pv_header {
+  grub_int8_t pv_uuid[GRUB_LVM_ID_LEN];
+
+  /* This size can be overridden if PV belongs to a VG */
+  grub_uint64_t device_size_xl;        /* Bytes */
+
+  /* NULL-terminated list of data areas followed by */
+  /* NULL-terminated list of metadata area headers */
+  struct grub_lvm_disk_locn disk_areas_xl[0];  /* Two lists */
+} __attribute__ ((packed));
+
+#define GRUB_LVM_FMTT_MAGIC "\040\114\126\115\062\040\170\133\065\101\045\162\060\116\052\076"
+#define GRUB_LVM_FMTT_VERSION 1
+#define GRUB_LVM_MDA_HEADER_SIZE 512
+
+/* On disk */
+struct grub_lvm_raw_locn {
+  grub_uint64_t offset;                /* Offset in bytes to start sector */
+  grub_uint64_t size;          /* Bytes */
+  grub_uint32_t checksum;
+  grub_uint32_t filler;
+} __attribute__ ((packed));
+
+/* On disk */
+/* Structure size limited to one sector */
+struct grub_lvm_mda_header {
+  grub_uint32_t checksum_xl;   /* Checksum of rest of mda_header */
+  grub_int8_t magic[16];       /* To aid scans for metadata */
+  grub_uint32_t version;
+  grub_uint64_t start;         /* Absolute start byte of mda_header */
+  grub_uint64_t size;          /* Size of metadata area */
+  
+  struct grub_lvm_raw_locn raw_locns[0];       /* NULL-terminated list */
+} __attribute__ ((packed));
+
+
+#endif /* ! GRUB_LVM_H */
diff --git a/include/grub/menu.h b/include/grub/menu.h
new file mode 100644 (file)
index 0000000..6850846
--- /dev/null
@@ -0,0 +1,63 @@
+/* menu.h - Menu and menu entry model declarations. */
+/*
+ *  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_MENU_HEADER
+#define GRUB_MENU_HEADER 1
+
+struct grub_menu_entry_class
+{
+  char *name;
+  struct grub_menu_entry_class *next;
+};
+
+/* The menu entry.  */
+struct grub_menu_entry
+{
+  /* The title name.  */
+  const char *title;
+
+  /* The classes associated with the menu entry:
+     used to choose an icon or other style attributes.
+     This is a dummy head node for the linked list, so for an entry E,
+     E.classes->next is the first class if it is not NULL.  */
+  struct grub_menu_entry_class *classes;
+
+  /* The commands associated with this menu entry.  */
+  struct grub_script *commands;
+
+  /* The sourcecode of the menu entry, used by the editor.  */
+  const char *sourcecode;
+
+  /* The next element.  */
+  struct grub_menu_entry *next;
+};
+typedef struct grub_menu_entry *grub_menu_entry_t;
+
+/* The menu.  */
+struct grub_menu
+{
+  /* The size of a menu.  */
+  int size;
+
+  /* The list of menu entries.  */
+  grub_menu_entry_t entry_list;
+};
+typedef struct grub_menu *grub_menu_t;
+
+#endif /* GRUB_MENU_HEADER */
diff --git a/include/grub/menu_viewer.h b/include/grub/menu_viewer.h
new file mode 100644 (file)
index 0000000..725c975
--- /dev/null
@@ -0,0 +1,43 @@
+/* menu_viewer.h - Interface to menu viewer implementations. */
+/*
+ *  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_MENU_VIEWER_HEADER
+#define GRUB_MENU_VIEWER_HEADER 1
+
+#include <grub/err.h>
+#include <grub/symbol.h>
+#include <grub/types.h>
+#include <grub/menu.h>
+
+struct grub_menu_viewer
+{
+  /* The menu viewer name.  */
+  const char *name;
+
+  grub_err_t (*show_menu) (grub_menu_t menu, int nested);
+
+  struct grub_menu_viewer *next;
+};
+typedef struct grub_menu_viewer *grub_menu_viewer_t;
+
+void grub_menu_viewer_register (grub_menu_viewer_t viewer);
+
+grub_err_t grub_menu_viewer_show_menu (grub_menu_t menu, int nested);
+
+#endif /* GRUB_MENU_VIEWER_HEADER */
diff --git a/include/grub/misc.h b/include/grub/misc.h
new file mode 100644 (file)
index 0000000..c377c20
--- /dev/null
@@ -0,0 +1,119 @@
+/* misc.h - prototypes for misc functions */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2005,2006,2007,2008,2009,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_MISC_HEADER
+#define GRUB_MISC_HEADER       1
+
+#include <stdarg.h>
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/err.h>
+
+#define ALIGN_UP(addr, align) (((grub_uint64_t)addr + align - 1) & ~(align - 1))
+
+#define grub_dprintf(condition, fmt, args...) grub_real_dprintf(__FILE__, __LINE__, condition, fmt, ## args);
+/* XXX: If grub_memmove is too slow, we must implement grub_memcpy.  */
+#define grub_memcpy(d,s,n)     grub_memmove ((d), (s), (n))
+
+void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n);
+char *EXPORT_FUNC(grub_strcpy) (char *dest, const char *src);
+char *EXPORT_FUNC(grub_strncpy) (char *dest, const char *src, int c);
+char *EXPORT_FUNC(grub_stpcpy) (char *dest, const char *src);
+char *EXPORT_FUNC(grub_strcat) (char *dest, const char *src);
+char *EXPORT_FUNC(grub_strncat) (char *dest, const char *src, int c);
+
+/* Prototypes for aliases.  */
+void *EXPORT_FUNC(memmove) (void *dest, const void *src, grub_size_t n);
+void *EXPORT_FUNC(memcpy) (void *dest, const void *src, grub_size_t n);
+
+int EXPORT_FUNC(grub_memcmp) (const void *s1, const void *s2, grub_size_t n);
+int EXPORT_FUNC(grub_strcmp) (const char *s1, const char *s2);
+int EXPORT_FUNC(grub_strncmp) (const char *s1, const char *s2, grub_size_t n);
+int EXPORT_FUNC(grub_strcasecmp) (const char *s1, const char *s2);
+int EXPORT_FUNC(grub_strncasecmp) (const char *s1, const char *s2, grub_size_t n);
+char *EXPORT_FUNC(grub_strchr) (const char *s, int c);
+char *EXPORT_FUNC(grub_strrchr) (const char *s, int c);
+int EXPORT_FUNC(grub_strword) (const char *s, const char *w);
+char *EXPORT_FUNC(grub_strstr) (const char *haystack, const char *needle);
+int EXPORT_FUNC(grub_iswordseparator) (int c);
+int EXPORT_FUNC(grub_isspace) (int c);
+int EXPORT_FUNC(grub_isprint) (int c);
+int EXPORT_FUNC(grub_isalpha) (int c);
+int EXPORT_FUNC(grub_isgraph) (int c);
+int EXPORT_FUNC(grub_isdigit) (int c);
+int EXPORT_FUNC(grub_tolower) (int c);
+unsigned long EXPORT_FUNC(grub_strtoul) (const char *str, char **end, int base);
+unsigned long long EXPORT_FUNC(grub_strtoull) (const char *str, char **end, int base);
+char *EXPORT_FUNC(grub_strdup) (const char *s);
+char *EXPORT_FUNC(grub_strndup) (const char *s, grub_size_t n);
+void *EXPORT_FUNC(grub_memset) (void *s, int c, grub_size_t n);
+grub_size_t EXPORT_FUNC(grub_strlen) (const char *s);
+int EXPORT_FUNC(grub_printf) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+void EXPORT_FUNC(grub_real_dprintf) (const char *file,
+                                     const int line,
+                                     const char *condition,
+                                     const char *fmt, ...) __attribute__ ((format (printf, 4, 5)));
+int EXPORT_FUNC(grub_vprintf) (const char *fmt, va_list args);
+int EXPORT_FUNC(grub_sprintf) (char *str, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+int EXPORT_FUNC(grub_vsprintf) (char *str, const char *fmt, va_list args);
+void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn));
+grub_uint8_t *EXPORT_FUNC(grub_utf16_to_utf8) (grub_uint8_t *dest,
+                                              grub_uint16_t *src,
+                                              grub_size_t size);
+grub_ssize_t EXPORT_FUNC(grub_utf8_to_ucs4) (grub_uint32_t *dest,
+                                            grub_size_t destsize,
+                                            const grub_uint8_t *src,
+                                            grub_size_t srcsize,
+                                            const grub_uint8_t **srcend);
+grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
+                                         grub_uint32_t d, grub_uint32_t *r);
+
+#ifdef NEED_ENABLE_EXECUTE_STACK
+void EXPORT_FUNC(__enable_execute_stack) (void *addr);
+#endif
+
+/* Inline functions.  */
+
+static inline unsigned int
+grub_abs (int x)
+{
+  if (x < 0)
+    return (unsigned int) (-x);
+  else
+    return (unsigned int) x;
+}
+
+static inline long
+grub_max (long x, long y)
+{
+  if (x > y)
+    return x;
+  else
+    return y;
+}
+
+/* Rounded-up division */
+static inline unsigned int
+grub_div_roundup (unsigned int x, unsigned int y)
+{
+  return (x + y - 1) / y;
+}
+
+#endif /* ! GRUB_MISC_HEADER */
diff --git a/include/grub/mm.h b/include/grub/mm.h
new file mode 100644 (file)
index 0000000..4dd1363
--- /dev/null
@@ -0,0 +1,66 @@
+/* mm.h - prototypes and declarations for memory manager */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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_MM_H
+#define GRUB_MM_H      1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <config.h>
+
+#ifndef NULL
+# define NULL  ((void *) 0)
+#endif
+
+void grub_mm_init_region (void *addr, grub_size_t size);
+void *EXPORT_FUNC(grub_malloc) (grub_size_t size);
+void EXPORT_FUNC(grub_free) (void *ptr);
+void *EXPORT_FUNC(grub_realloc) (void *ptr, grub_size_t size);
+void *EXPORT_FUNC(grub_memalign) (grub_size_t align, grub_size_t size);
+
+/* For debugging.  */
+#if defined(MM_DEBUG) && !defined(GRUB_UTIL)
+/* Set this variable to 1 when you want to trace all memory function calls.  */
+extern int EXPORT_VAR(grub_mm_debug);
+
+void grub_mm_dump_free (void);
+void grub_mm_dump (unsigned lineno);
+
+#define grub_malloc(size)      \
+  grub_debug_malloc (__FILE__, __LINE__, size)
+
+#define grub_realloc(ptr,size) \
+  grub_debug_realloc (__FILE__, __LINE__, ptr, size)
+
+#define grub_memalign(align,size)      \
+  grub_debug_memalign (__FILE__, __LINE__, align, size)
+
+#define grub_free(ptr) \
+  grub_debug_free (__FILE__, __LINE__, ptr)
+
+void *EXPORT_FUNC(grub_debug_malloc) (const char *file, int line,
+                                     grub_size_t size);
+void EXPORT_FUNC(grub_debug_free) (const char *file, int line, void *ptr);
+void *EXPORT_FUNC(grub_debug_realloc) (const char *file, int line, void *ptr,
+                                      grub_size_t size);
+void *EXPORT_FUNC(grub_debug_memalign) (const char *file, int line,
+                                       grub_size_t align, grub_size_t size);
+#endif /* MM_DEBUG && ! GRUB_UTIL */
+
+#endif /* ! GRUB_MM_H */
diff --git a/include/grub/multiboot.h b/include/grub/multiboot.h
new file mode 100644 (file)
index 0000000..5285ea2
--- /dev/null
@@ -0,0 +1,129 @@
+/* multiboot.h - multiboot header file with grub definitions. */
+/*
+ *  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_MULTIBOOT_HEADER
+#define GRUB_MULTIBOOT_HEADER 1
+
+#include <multiboot.h>
+
+void grub_multiboot (int argc, char *argv[]);
+void grub_module (int argc, char *argv[]);
+
+#ifndef ASM_FILE
+
+#include <grub/types.h>
+
+struct grub_multiboot_header
+{ 
+  /* Must be MULTIBOOT_MAGIC - see above.  */
+  grub_uint32_t magic;
+
+  /* Feature flags.  */
+  grub_uint32_t flags;
+
+  /* The above fields plus this one must equal 0 mod 2^32. */
+  grub_uint32_t checksum;
+  
+  /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set.  */
+  grub_uint32_t header_addr;
+  grub_uint32_t load_addr;
+  grub_uint32_t load_end_addr;
+  grub_uint32_t bss_end_addr;
+  grub_uint32_t entry_addr;
+
+  /* These are only valid if MULTIBOOT_VIDEO_MODE is set.  */
+  grub_uint32_t mode_type;
+  grub_uint32_t width;
+  grub_uint32_t height;
+  grub_uint32_t depth;
+};
+
+struct grub_multiboot_info
+{
+  /* Multiboot info version number */
+  grub_uint32_t flags;
+  
+  /* Available memory from BIOS */
+  grub_uint32_t mem_lower;
+  grub_uint32_t mem_upper;
+  
+  /* "root" partition */
+  grub_uint32_t boot_device;
+  
+  /* Kernel command line */
+  grub_uint32_t cmdline;
+  
+  /* Boot-Module list */
+  grub_uint32_t mods_count;
+  grub_uint32_t mods_addr;
+  
+  grub_uint32_t syms[4];
+  
+  /* Memory Mapping buffer */
+  grub_uint32_t mmap_length;
+  grub_uint32_t mmap_addr;
+  
+  /* Drive Info buffer */
+  grub_uint32_t drives_length;
+  grub_uint32_t drives_addr;
+  
+  /* ROM configuration table */
+  grub_uint32_t config_table;
+  
+  /* Boot Loader Name */
+  grub_uint32_t boot_loader_name;
+
+  /* APM table */
+  grub_uint32_t apm_table;
+
+  /* Video */
+  grub_uint32_t vbe_control_info;
+  grub_uint32_t vbe_mode_info;
+  grub_uint16_t vbe_mode;
+  grub_uint16_t vbe_interface_seg;
+  grub_uint16_t vbe_interface_off;
+  grub_uint16_t vbe_interface_len;
+};
+
+struct grub_multiboot_mmap_entry
+{
+  grub_uint32_t size;
+  grub_uint64_t addr;
+  grub_uint64_t len;
+#define GRUB_MULTIBOOT_MEMORY_AVAILABLE                1
+#define GRUB_MULTIBOOT_MEMORY_RESERVED         2
+  grub_uint32_t type;
+} __attribute__((packed));
+
+struct grub_mod_list
+{
+  /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
+  grub_uint32_t mod_start;
+  grub_uint32_t mod_end;
+  
+  /* Module command line */
+  grub_uint32_t cmdline;
+  
+  /* padding to take it to 16 bytes (must be zero) */
+  grub_uint32_t pad;
+};
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! GRUB_MULTIBOOT_HEADER */
diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h
new file mode 100644 (file)
index 0000000..bfbffcc
--- /dev/null
@@ -0,0 +1,64 @@
+/* multiboot2.h - multiboot2 header file with grub definitions. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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 GRUB_MULTIBOOT2_HEADER
+#define GRUB_MULTIBOOT2_HEADER 1
+
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/elf.h>
+
+struct multiboot_tag_header;
+
+grub_err_t
+grub_mb2_tag_alloc (grub_addr_t *addr, int key, grub_size_t len);
+
+grub_err_t 
+grub_mb2_tags_arch_create (void);
+
+void 
+grub_mb2_arch_boot (grub_addr_t entry, void *tags);
+
+void 
+grub_mb2_arch_unload (struct multiboot_tag_header *tags);
+
+grub_err_t
+grub_mb2_arch_elf32_hook (Elf32_Phdr *phdr, grub_addr_t *addr);
+
+grub_err_t 
+grub_mb2_arch_elf64_hook (Elf64_Phdr *phdr, grub_addr_t *addr);
+
+grub_err_t
+grub_mb2_arch_module_alloc (grub_size_t size, grub_addr_t *addr);
+
+grub_err_t
+grub_mb2_arch_module_free (grub_addr_t addr, grub_size_t size);
+
+void 
+grub_multiboot2 (int argc, char *argv[]);
+
+void 
+grub_module2 (int argc, char *argv[]);
+
+#define for_each_tag(tag, tags) \
+  for (tag = tags; \
+       tag && tag->key != MULTIBOOT2_TAG_END; \
+       tag = (struct multiboot_tag_header *)((char *)tag + tag->len))
+
+#endif /* ! GRUB_MULTIBOOT2_HEADER */
diff --git a/include/grub/multiboot_loader.h b/include/grub/multiboot_loader.h
new file mode 100644 (file)
index 0000000..bf1c130
--- /dev/null
@@ -0,0 +1,28 @@
+/* multiboot_loader.h - multiboot loader header file. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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 GRUB_MULTIBOOT_LOADER_HEADER
+#define GRUB_MULTIBOOT_LOADER_HEADER 1
+
+/* Provided by the core ("rescue mode").  */
+void grub_rescue_cmd_multiboot_loader (int argc, char *argv[]);
+void grub_rescue_cmd_module_loader (int argc, char *argv[]);
+
+#endif /* ! GRUB_MULTIBOOT_LOADER_HEADER */
diff --git a/include/grub/net.h b/include/grub/net.h
new file mode 100644 (file)
index 0000000..2eac431
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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_NET_HEADER
+#define GRUB_NET_HEADER        1
+
+#include <grub/symbol.h>
+#include <grub/err.h>
+#include <grub/types.h>
+
+struct grub_net;
+
+struct grub_net_dev
+{
+  /* The device name.  */
+  const char *name;
+
+  /* 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);
+
+  /* The next net device.  */
+  struct grub_net_dev *next;
+};
+typedef struct grub_net_dev *grub_net_dev_t;
+
+struct grub_fs;
+
+struct grub_net
+{
+  /* The net name.  */
+  const char *name;
+  
+  /* The underlying disk device.  */
+  grub_net_dev_t dev;
+
+  /* The binding filesystem.  */
+  struct grub_fs *fs;
+
+  /* FIXME: More data would be required, such as an IP address, a mask,
+     a gateway, etc.  */
+  
+  /* Device-specific data.  */
+  void *data;
+};
+typedef struct grub_net *grub_net_t;
+
+/* FIXME: How to abstract networks? More consideration is necessary.  */
+
+/* Note: Networks are very different from disks, because networks must
+   be initialized before used, and the status is persistent.  */
+
+#endif /* ! GRUB_NET_HEADER */
diff --git a/include/grub/normal.h b/include/grub/normal.h
new file mode 100644 (file)
index 0000000..216ae0d
--- /dev/null
@@ -0,0 +1,198 @@
+/* normal.h - prototypes for the normal mode */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,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_NORMAL_HEADER
+#define GRUB_NORMAL_HEADER     1
+
+#include <grub/setjmp.h>
+#include <grub/symbol.h>
+#include <grub/err.h>
+#include <grub/arg.h>
+#include <grub/env.h>
+#include <grub/menu.h>
+
+/* The maximum size of a command-line.  */
+#define GRUB_MAX_CMDLINE       1600
+
+/* Can be run in the command-line.  */
+#define GRUB_COMMAND_FLAG_CMDLINE      0x1
+/* Can be run in the menu.  */
+#define GRUB_COMMAND_FLAG_MENU         0x2
+/* Can be run in both interfaces.  */
+#define GRUB_COMMAND_FLAG_BOTH         0x3
+/* Only for the command title.  */
+#define GRUB_COMMAND_FLAG_TITLE                0x4
+/* Don't print the command on booting.  */
+#define GRUB_COMMAND_FLAG_NO_ECHO      0x8
+/* Pass arguments to the command without parsing options.  */
+#define GRUB_COMMAND_FLAG_NO_ARG_PARSE 0x10
+/* Not loaded yet. Used for auto-loading.  */
+#define GRUB_COMMAND_FLAG_NOT_LOADED   0x20
+
+/* The type of a completion item.  */
+enum grub_completion_type
+  {
+    GRUB_COMPLETION_TYPE_COMMAND,
+    GRUB_COMPLETION_TYPE_DEVICE,
+    GRUB_COMPLETION_TYPE_PARTITION,
+    GRUB_COMPLETION_TYPE_FILE,
+    GRUB_COMPLETION_TYPE_ARGUMENT
+  };
+typedef enum grub_completion_type grub_completion_type_t;
+
+/* The command description.  */
+struct grub_command
+{
+  /* The name.  */
+  char *name;
+
+  /* The callback function.  */
+  grub_err_t (*func) (struct grub_arg_list *state, int argc, char **args);
+
+  /* The flags.  */
+  unsigned flags;
+
+  /* The summary of the command usage.  */
+  const char *summary;
+
+  /* The description of the command.  */
+  const char *description;
+
+  /* The argument parser optionlist.  */
+  const struct grub_arg_option *options;
+
+  /* The name of a module. Used for auto-loading.  */
+  char *module_name;
+
+  /* The next element.  */
+  struct grub_command *next;
+};
+typedef struct grub_command *grub_command_t;
+
+/* This is used to store the names of filesystem modules for auto-loading.  */
+struct grub_fs_module_list
+{
+  char *name;
+  struct grub_fs_module_list *next;
+};
+typedef struct grub_fs_module_list *grub_fs_module_list_t;
+
+/* To exit from the normal mode.  */
+extern grub_jmp_buf grub_exit_env;
+
+extern struct grub_menu_viewer grub_normal_text_menu_viewer;
+
+/* Callback structure menu viewers can use to provide user feedback when
+   default entries are executed, possibly including fallback entries.  */
+typedef struct grub_menu_execute_callback
+{
+  /* Called immediately before ENTRY is booted.  */
+  void (*notify_booting) (grub_menu_entry_t entry, void *userdata);
+
+  /* Called when executing one entry has failed, and another entry, ENTRY, will
+     be executed as a fallback.  The implementation of this function should
+     delay for a period of at least 2 seconds before returning in order to
+     allow the user time to read the information before it can be lost by
+     executing ENTRY.  */
+  void (*notify_fallback) (grub_menu_entry_t entry, void *userdata);
+
+  /* Called when an entry has failed to execute and there is no remaining
+     fallback entry to attempt.  */
+  void (*notify_failure) (void *userdata);
+}
+*grub_menu_execute_callback_t;
+
+void grub_enter_normal_mode (const char *config);
+void grub_normal_execute (const char *config, int nested);
+void grub_menu_execute_with_fallback (grub_menu_t menu,
+                                     grub_menu_entry_t entry,
+                                     grub_menu_execute_callback_t callback,
+                                     void *callback_data);
+void grub_menu_entry_run (grub_menu_entry_t entry);
+void grub_menu_execute_entry(grub_menu_entry_t entry);
+grub_menu_entry_t grub_menu_get_entry (grub_menu_t menu, int no);
+int grub_menu_get_timeout (void);
+void grub_menu_set_timeout (int timeout);
+void grub_cmdline_run (int nested);
+int grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
+                     int echo_char, int readline);
+grub_command_t grub_register_command (const char *name,
+                                     grub_err_t (*func) (struct grub_arg_list *state,
+                                                         int argc,
+                                                         char **args),
+                                     unsigned flags,
+                                     const char *summary,
+                                     const char *description,
+                                     const struct grub_arg_option *parser);
+void grub_unregister_command (const char *name);
+grub_command_t grub_command_find (char *cmdline);
+grub_err_t grub_set_history (int newsize);
+int grub_iterate_commands (int (*iterate) (grub_command_t));
+int grub_command_execute (char *cmdline, int interactive);
+void grub_command_init (void);
+void grub_normal_init_page (void);
+void grub_menu_init_page (int nested, int edit);
+int grub_arg_parse (grub_command_t parser, int argc, char **argv,
+                   struct grub_arg_list *usr, char ***args, int *argnum);
+void grub_arg_show_help (grub_command_t cmd);
+char *grub_normal_do_completion (char *buf, int *restore,
+                                void (*hook) (const char *item, grub_completion_type_t type, int count));
+grub_err_t grub_normal_print_device_info (const char *name);
+grub_err_t grub_normal_menu_addentry (int argc, const char **args,
+                                     struct grub_script *script,
+                                     const char *sourcecode);
+char *grub_env_write_color_normal (struct grub_env_var *var, const char *val);
+char *grub_env_write_color_highlight (struct grub_env_var *var, const char *val);
+void grub_parse_color_name_pair (grub_uint8_t *ret, const char *name);
+void grub_wait_after_message (void);
+
+#ifdef GRUB_UTIL
+void grub_normal_init (void);
+void grub_normal_fini (void);
+void grub_hello_init (void);
+void grub_hello_fini (void);
+void grub_ls_init (void);
+void grub_ls_fini (void);
+void grub_cat_init (void);
+void grub_cat_fini (void);
+void grub_boot_init (void);
+void grub_boot_fini (void);
+void grub_cmp_init (void);
+void grub_cmp_fini (void);
+void grub_terminal_init (void);
+void grub_terminal_fini (void);
+void grub_loop_init (void);
+void grub_loop_fini (void);
+void grub_help_init (void);
+void grub_help_fini (void);
+void grub_halt_init (void);
+void grub_halt_fini (void);
+void grub_reboot_init (void);
+void grub_reboot_fini (void);
+void grub_configfile_init (void);
+void grub_configfile_fini (void);
+void grub_search_init (void);
+void grub_search_fini (void);
+void grub_test_init (void);
+void grub_test_fini (void);
+void grub_blocklist_init (void);
+void grub_blocklist_fini (void);
+#endif
+
+#endif /* ! GRUB_NORMAL_HEADER */
diff --git a/include/grub/ntfs.h b/include/grub/ntfs.h
new file mode 100644 (file)
index 0000000..9b2ae0a
--- /dev/null
@@ -0,0 +1,182 @@
+/* ntfs.h - header for the NTFS filesystem */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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_NTFS_H
+#define GRUB_NTFS_H    1
+
+#define FILE_MFT      0
+#define FILE_MFTMIRR  1
+#define FILE_LOGFILE  2
+#define FILE_VOLUME   3
+#define FILE_ATTRDEF  4
+#define FILE_ROOT     5
+#define FILE_BITMAP   6
+#define FILE_BOOT     7
+#define FILE_BADCLUS  8
+#define FILE_QUOTA    9
+#define FILE_UPCASE  10
+
+#define AT_STANDARD_INFORMATION        0x10
+#define AT_ATTRIBUTE_LIST      0x20
+#define AT_FILENAME            0x30
+#define AT_OBJECT_ID           0x40
+#define AT_SECURITY_DESCRIPTOR 0x50
+#define AT_VOLUME_NAME         0x60
+#define AT_VOLUME_INFORMATION  0x70
+#define AT_DATA                        0x80
+#define AT_INDEX_ROOT          0x90
+#define AT_INDEX_ALLOCATION    0xA0
+#define AT_BITMAP              0xB0
+#define AT_SYMLINK             0xC0
+#define AT_EA_INFORMATION      0xD0
+#define AT_EA                  0xE0
+
+#define ATTR_READ_ONLY         0x1
+#define ATTR_HIDDEN            0x2
+#define ATTR_SYSTEM            0x4
+#define ATTR_ARCHIVE           0x20
+#define ATTR_DEVICE            0x40
+#define ATTR_NORMAL            0x80
+#define ATTR_TEMPORARY         0x100
+#define ATTR_SPARSE            0x200
+#define ATTR_REPARSE           0x400
+#define ATTR_COMPRESSED                0x800
+#define ATTR_OFFLINE           0x1000
+#define ATTR_NOT_INDEXED       0x2000
+#define ATTR_ENCRYPTED         0x4000
+#define ATTR_DIRECTORY         0x10000000
+#define ATTR_INDEX_VIEW                0x20000000
+
+#define FLAG_COMPRESSED                1
+#define FLAG_ENCRYPTED         0x4000
+#define FLAG_SPARSE            0x8000
+
+#define BLK_SHR                GRUB_DISK_SECTOR_BITS
+
+#define MAX_MFT                (1024 >> BLK_SHR)
+#define MAX_IDX                (16384 >> BLK_SHR)
+
+#define COM_LEN                4096
+#define COM_SEC                (COM_LEN >> BLK_SHR)
+
+#define AF_ALST                1
+#define AF_MMFT                2
+#define AF_GPOS                4
+
+#define RF_COMP                1
+#define RF_CBLK                2
+#define RF_BLNK                4
+
+#define valueat(buf,ofs,type)  *((type*)(((char*)buf)+ofs))
+
+#define u16at(buf,ofs) grub_le_to_cpu16(valueat(buf,ofs,grub_uint16_t))
+#define u32at(buf,ofs) grub_le_to_cpu32(valueat(buf,ofs,grub_uint32_t))
+#define u64at(buf,ofs) grub_le_to_cpu64(valueat(buf,ofs,grub_uint64_t))
+
+#define v16at(buf,ofs) valueat(buf,ofs,grub_uint16_t)
+#define v32at(buf,ofs) valueat(buf,ofs,grub_uint32_t)
+#define v64at(buf,ofs) valueat(buf,ofs,grub_uint64_t)
+
+struct grub_ntfs_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_uint8_t reserved_1[7];
+  grub_uint8_t media;
+  grub_uint16_t reserved_2;
+  grub_uint16_t sectors_per_track;
+  grub_uint16_t num_heads;
+  grub_uint32_t num_hidden_sectors;
+  grub_uint32_t reserved_3[2];
+  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_uint64_t num_serial;
+  grub_uint32_t checksum;
+} __attribute__ ((packed));
+
+#define grub_ntfs_file grub_fshelp_node
+
+struct grub_ntfs_attr
+{
+  int flags;
+  char *emft_buf, *edat_buf;
+  char *attr_cur, *attr_nxt, *attr_end;
+  grub_uint32_t save_pos;
+  char *sbuf;
+  struct grub_ntfs_file *mft;
+};
+
+struct grub_fshelp_node
+{
+  struct grub_ntfs_data *data;
+  char *buf;
+  grub_uint32_t size;
+  grub_uint32_t ino;
+  int inode_read;
+  struct grub_ntfs_attr attr;
+};
+
+struct grub_ntfs_data
+{
+  struct grub_ntfs_file cmft;
+  struct grub_ntfs_file mmft;
+  grub_disk_t disk;
+  grub_uint32_t mft_size;
+  grub_uint32_t idx_size;
+  grub_uint32_t spc;
+  grub_uint32_t blocksize;
+  grub_uint32_t mft_start;
+  grub_uint64_t uuid;
+};
+
+struct grub_ntfs_comp
+{
+  grub_disk_t disk;
+  int comp_head, comp_tail;
+  grub_uint32_t comp_table[16][2];
+  grub_uint32_t cbuf_ofs, cbuf_vcn, spc;
+  char *cbuf;
+};
+
+struct grub_ntfs_rlst
+{
+  int flags;
+  grub_uint32_t target_vcn, curr_vcn, next_vcn, curr_lcn;
+  char *cur_run;
+  struct grub_ntfs_attr *attr;
+  struct grub_ntfs_comp comp;
+};
+
+typedef grub_err_t (*ntfscomp_func_t) (struct grub_ntfs_attr * at, char *dest,
+                                      grub_uint32_t ofs, grub_uint32_t len,
+                                      struct grub_ntfs_rlst * ctx,
+                                      grub_uint32_t vcn);
+
+extern ntfscomp_func_t EXPORT_VAR (grub_ntfscomp_func);
+
+grub_err_t EXPORT_FUNC(grub_ntfs_read_run_list) (struct grub_ntfs_rlst *ctx);
+
+#endif /* ! GRUB_NTFS_H */
diff --git a/include/grub/parser.h b/include/grub/parser.h
new file mode 100644 (file)
index 0000000..1a7f0a3
--- /dev/null
@@ -0,0 +1,67 @@
+/* parser.h - prototypes for the command line parser.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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 GRUB_PARSER_HEADER
+#define GRUB_PARSER_HEADER     1
+
+#include <grub/types.h>
+#include <grub/err.h>
+
+/* All the states for the command line.  */
+typedef enum
+  {
+    GRUB_PARSER_STATE_TEXT = 1,
+    GRUB_PARSER_STATE_ESC,
+    GRUB_PARSER_STATE_QUOTE,
+    GRUB_PARSER_STATE_DQUOTE,
+    GRUB_PARSER_STATE_VAR,
+    GRUB_PARSER_STATE_VARNAME,
+    GRUB_PARSER_STATE_VARNAME2,
+    GRUB_PARSER_STATE_QVAR,
+    GRUB_PARSER_STATE_QVARNAME,
+    GRUB_PARSER_STATE_QVARNAME2
+  } grub_parser_state_t;
+
+/* A single state transition.  */
+struct grub_parser_state_transition
+{
+  /* The state that is looked up.  */
+  grub_parser_state_t from_state;
+
+  /* The next state, determined by FROM_STATE and INPUT.  */
+  grub_parser_state_t to_state;
+
+  /* The input that will determine the next state from FROM_STATE.  */
+  char input;
+
+  /* If set to 1, the input is valid and should be used.  */
+  int keep_value;
+};
+
+/* Determines the state following STATE, determined by C.  */
+grub_parser_state_t
+EXPORT_FUNC (grub_parser_cmdline_state) (grub_parser_state_t state,
+                                        char c, char *result);
+
+grub_err_t
+EXPORT_FUNC (grub_parser_split_cmdline) (const char *cmdline,
+                                        grub_err_t (*getline) (char **),
+                                        int *argc, char ***argv);
+
+#endif /* ! GRUB_PARSER_HEADER */
diff --git a/include/grub/partition.h b/include/grub/partition.h
new file mode 100644 (file)
index 0000000..6e74cd5
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2004,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_PART_HEADER
+#define GRUB_PART_HEADER       1
+
+#include <grub/dl.h>
+
+struct grub_disk;
+
+typedef struct grub_partition *grub_partition_t;
+
+/* Partition map type.  */
+struct grub_partition_map
+{
+  /* The name of the partition map type.  */
+  const char *name;
+  
+  /* Call HOOK with each partition, until HOOK returns non-zero.  */
+  grub_err_t (*iterate) (struct grub_disk *disk,
+                        int (*hook) (struct grub_disk *disk,
+                                     const grub_partition_t partition));
+  
+  /* Return the partition named STR on the disk DISK.  */
+  grub_partition_t (*probe) (struct grub_disk *disk,
+                            const char *str);
+  
+  /* Return the name of the partition PARTITION.  */
+  char *(*get_name) (const grub_partition_t partition);
+  
+  /* The next partition map type.  */
+  struct grub_partition_map *next;
+};
+typedef struct grub_partition_map *grub_partition_map_t;
+
+/* Partition description.  */
+struct grub_partition
+{
+  /* The start sector.  */
+  grub_disk_addr_t start;
+
+  /* The length in sector units.  */
+  grub_uint64_t len;
+
+  /* The offset of the partition table.  */
+  grub_disk_addr_t offset;
+
+  /* The index of this partition in the partition table.  */
+  int index;
+  
+  /* Partition map type specific data.  */
+  void *data;
+  
+  /* The type partition map.  */
+  grub_partition_map_t partmap;
+};
+
+grub_partition_t EXPORT_FUNC(grub_partition_probe) (struct grub_disk *disk,
+                                                   const char *str);
+int EXPORT_FUNC(grub_partition_iterate) (struct grub_disk *disk,
+                                        int (*hook) (struct grub_disk *disk,
+                                                     const grub_partition_t partition));
+char *EXPORT_FUNC(grub_partition_get_name) (const grub_partition_t partition);
+
+int EXPORT_FUNC(grub_partition_map_iterate) (int (*hook) (const grub_partition_map_t partmap));
+                                             
+void EXPORT_FUNC(grub_partition_map_register) (grub_partition_map_t partmap);
+
+void EXPORT_FUNC(grub_partition_map_unregister) (grub_partition_map_t partmap);
+
+#ifdef GRUB_UTIL
+void grub_pc_partition_map_init (void);
+void grub_pc_partition_map_fini (void);
+void grub_amiga_partition_map_init (void);
+void grub_amiga_partition_map_fini (void);
+void grub_apple_partition_map_init (void);
+void grub_apple_partition_map_fini (void);
+void grub_sun_partition_map_init (void);
+void grub_sun_partition_map_fini (void);
+void grub_gpt_partition_map_init (void);
+void grub_gpt_partition_map_fini (void);
+void grub_apple_partition_map_init (void);
+void grub_apple_partition_map_fini (void);
+#endif
+\f
+static inline grub_disk_addr_t
+grub_partition_get_start (const grub_partition_t p)
+{
+  return p->start;
+}
+
+static inline grub_uint64_t
+grub_partition_get_len (const grub_partition_t p)
+{
+  return p->len;
+}
+
+#endif /* ! GRUB_PART_HEADER */
diff --git a/include/grub/pc_partition.h b/include/grub/pc_partition.h
new file mode 100644 (file)
index 0000000..6a815c3
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2004,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_PC_PARTITION_HEADER
+#define GRUB_PC_PARTITION_HEADER       1
+
+#include <grub/symbol.h>
+#include <grub/types.h>
+#include <grub/err.h>
+
+/* The signature.  */
+#define GRUB_PC_PARTITION_SIGNATURE            0xaa55
+
+/* This is not a flag actually, but used as if it were a flag.  */
+#define GRUB_PC_PARTITION_TYPE_HIDDEN_FLAG     0x10
+
+/* DOS partition types.  */
+#define GRUB_PC_PARTITION_TYPE_NONE            0
+#define GRUB_PC_PARTITION_TYPE_FAT12           1
+#define GRUB_PC_PARTITION_TYPE_FAT16_LT32M     4
+#define GRUB_PC_PARTITION_TYPE_EXTENDED                5
+#define GRUB_PC_PARTITION_TYPE_FAT16_GT32M     6
+#define GRUB_PC_PARTITION_TYPE_FAT32           0xb
+#define GRUB_PC_PARTITION_TYPE_FAT32_LBA       0xc
+#define GRUB_PC_PARTITION_TYPE_FAT16_LBA       0xe
+#define GRUB_PC_PARTITION_TYPE_WIN95_EXTENDED  0xf
+#define GRUB_PC_PARTITION_TYPE_EZD             0x55
+#define GRUB_PC_PARTITION_TYPE_MINIX           0x80
+#define GRUB_PC_PARTITION_TYPE_LINUX_MINIX     0x81
+#define GRUB_PC_PARTITION_TYPE_EXT2FS          0x83
+#define GRUB_PC_PARTITION_TYPE_LINUX_EXTENDED  0x85
+#define GRUB_PC_PARTITION_TYPE_VSTAFS          0x9e
+#define GRUB_PC_PARTITION_TYPE_FREEBSD         0xa5
+#define GRUB_PC_PARTITION_TYPE_OPENBSD         0xa6
+#define GRUB_PC_PARTITION_TYPE_NETBSD          0xa9
+#define GRUB_PC_PARTITION_TYPE_GPT_DISK                0xee
+#define GRUB_PC_PARTITION_TYPE_LINUX_RAID      0xfd
+
+/* Constants for BSD disk label.  */
+#define GRUB_PC_PARTITION_BSD_LABEL_SECTOR     1
+#define GRUB_PC_PARTITION_BSD_LABEL_MAGIC      0x82564557
+#define GRUB_PC_PARTITION_BSD_MAX_ENTRIES      8
+
+/* BSD partition types.  */
+#define GRUB_PC_PARTITION_BSD_TYPE_UNUSED      0
+#define GRUB_PC_PARTITION_BSD_TYPE_SWAP                1
+#define GRUB_PC_PARTITION_BSD_TYPE_V6          2
+#define GRUB_PC_PARTITION_BSD_TYPE_V7          3
+#define GRUB_PC_PARTITION_BSD_TYPE_SYSV                4
+#define GRUB_PC_PARTITION_BSD_TYPE_V71K                5
+#define GRUB_PC_PARTITION_BSD_TYPE_V8          6
+#define GRUB_PC_PARTITION_BSD_TYPE_BSDFFS      7
+#define GRUB_PC_PARTITION_BSD_TYPE_MSDOS       8
+#define GRUB_PC_PARTITION_BSD_TYPE_BSDLFS      9
+#define GRUB_PC_PARTITION_BSD_TYPE_OTHER       10
+#define GRUB_PC_PARTITION_BSD_TYPE_HPFS                11
+#define GRUB_PC_PARTITION_BSD_TYPE_ISO9660     12
+#define GRUB_PC_PARTITION_BSD_TYPE_BOOT                13
+
+/* FreeBSD-specific types.  */
+#define GRUB_PC_PARTITION_FREEBSD_TYPE_VINUM   14
+#define GRUB_PC_PARTITION_FREEBSD_TYPE_RAID    15
+#define GRUB_PC_PARTITION_FREEBSD_TYPE_JFS2    21
+
+/* NetBSD-specific types.  */
+#define        GRUB_PC_PARTITION_NETBSD_TYPE_ADOS      14
+#define        GRUB_PC_PARTITION_NETBSD_TYPE_HFS       15
+#define        GRUB_PC_PARTITION_NETBSD_TYPE_FILECORE  16
+#define        GRUB_PC_PARTITION_NETBSD_TYPE_EXT2FS    17
+#define        GRUB_PC_PARTITION_NETBSD_TYPE_NTFS      18
+#define        GRUB_PC_PARTITION_NETBSD_TYPE_RAID      19
+#define        GRUB_PC_PARTITION_NETBSD_TYPE_CCD       20
+#define        GRUB_PC_PARTITION_NETBSD_TYPE_JFS2      21
+#define        GRUB_PC_PARTITION_NETBSD_TYPE_APPLEUFS  22
+
+/* OpenBSD-specific types.  */
+#define        GRUB_PC_PARTITION_OPENBSD_TYPE_ADOS     14
+#define        GRUB_PC_PARTITION_OPENBSD_TYPE_HFS      15
+#define        GRUB_PC_PARTITION_OPENBSD_TYPE_FILECORE 16
+#define        GRUB_PC_PARTITION_OPENBSD_TYPE_EXT2FS   17
+#define        GRUB_PC_PARTITION_OPENBSD_TYPE_NTFS     18
+#define        GRUB_PC_PARTITION_OPENBSD_TYPE_RAID     19
+
+/* The BSD partition entry.  */
+struct grub_pc_partition_bsd_entry
+{
+  grub_uint32_t size;
+  grub_uint32_t offset;
+  grub_uint32_t fragment_size;
+  grub_uint8_t fs_type;
+  grub_uint8_t fs_fragments;
+  grub_uint16_t fs_cylinders;
+} __attribute__ ((packed));
+
+/* The BSD disk label. Only define members useful for GRUB.  */
+struct grub_pc_partition_disk_label
+{
+  grub_uint32_t magic;
+  grub_uint8_t padding[128];
+  grub_uint32_t magic2;
+  grub_uint16_t checksum;
+  grub_uint16_t num_partitions;
+  grub_uint32_t boot_size;
+  grub_uint32_t superblock_size;
+  struct grub_pc_partition_bsd_entry entries[GRUB_PC_PARTITION_BSD_MAX_ENTRIES];
+} __attribute__ ((packed));
+
+/* The partition entry.  */
+struct grub_pc_partition_entry
+{
+  /* If active, 0x80, otherwise, 0x00.  */
+  grub_uint8_t flag;
+
+  /* The head of the start.  */
+  grub_uint8_t start_head;
+
+  /* (S | ((C >> 2) & 0xC0)) where S is the sector of the start and C
+     is the cylinder of the start. Note that S is counted from one.  */
+  grub_uint8_t start_sector;
+
+  /* (C & 0xFF) where C is the cylinder of the start.  */
+  grub_uint8_t start_cylinder;
+
+  /* The partition type.  */
+  grub_uint8_t type;
+
+  /* The end versions of start_head, start_sector and start_cylinder,
+     respectively.  */
+  grub_uint8_t end_head;
+  grub_uint8_t end_sector;
+  grub_uint8_t end_cylinder;
+
+  /* The start sector. Note that this is counted from zero.  */
+  grub_uint32_t start;
+
+  /* The length in sector units.  */
+  grub_uint32_t length;
+} __attribute__ ((packed));
+
+/* The structure of MBR.  */
+struct grub_pc_partition_mbr
+{
+  /* The code area (actually, including BPB).  */
+  grub_uint8_t code[446];
+
+  /* Four partition entries.  */
+  struct grub_pc_partition_entry entries[4];
+
+  /* The signature 0xaa55.  */
+  grub_uint16_t signature;
+} __attribute__ ((packed));
+
+\f
+struct grub_pc_partition
+{
+    /* The DOS partition number.  */
+  int dos_part;
+
+  /* The BSD partition number (a == 0).  */
+  int bsd_part;
+
+  /* The DOS partition type.  */
+  int dos_type;
+
+  /* The BSD partition type.  */
+  int bsd_type;
+
+  /* The offset of the extended partition.  */
+  unsigned long ext_offset;
+};
+
+static inline int
+grub_pc_partition_is_empty (int type)
+{
+  return (type == GRUB_PC_PARTITION_TYPE_NONE);
+}
+
+static inline int
+grub_pc_partition_is_extended (int type)
+{
+  return (type == GRUB_PC_PARTITION_TYPE_EXTENDED
+         || type == GRUB_PC_PARTITION_TYPE_WIN95_EXTENDED
+         || type == GRUB_PC_PARTITION_TYPE_LINUX_EXTENDED);
+}
+
+static inline int
+grub_pc_partition_is_bsd (int type)
+{
+  return (type == GRUB_PC_PARTITION_TYPE_FREEBSD
+         || type == GRUB_PC_PARTITION_TYPE_OPENBSD
+         || type == GRUB_PC_PARTITION_TYPE_NETBSD);
+}
+
+#endif /* ! GRUB_PC_PARTITION_HEADER */
diff --git a/include/grub/pci.h b/include/grub/pci.h
new file mode 100644 (file)
index 0000000..aceee49
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  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_PCI_H
+#define        GRUB_PCI_H      1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+
+#define  GRUB_PCI_ADDR_SPACE_MASK      0x01
+#define  GRUB_PCI_ADDR_SPACE_MEMORY    0x00
+#define  GRUB_PCI_ADDR_SPACE_IO                0x01
+
+#define  GRUB_PCI_ADDR_MEM_TYPE_MASK   0x06
+#define  GRUB_PCI_ADDR_MEM_TYPE_32     0x00    /* 32 bit address */
+#define  GRUB_PCI_ADDR_MEM_TYPE_1M     0x02    /* Below 1M [obsolete] */
+#define  GRUB_PCI_ADDR_MEM_TYPE_64     0x04    /* 64 bit address */
+#define  GRUB_PCI_ADDR_MEM_PREFETCH    0x08    /* prefetchable */
+
+#define  GRUB_PCI_ADDR_MEM_MASK                ~0xf
+#define  GRUB_PCI_ADDR_IO_MASK         ~0x03
+
+typedef grub_uint32_t grub_pci_id_t;
+typedef int (*grub_pci_iteratefunc_t) (int bus, int device, int func,
+                                      grub_pci_id_t pciid);
+typedef grub_uint32_t grub_pci_address_t;
+
+grub_pci_address_t EXPORT_FUNC(grub_pci_make_address) (int bus, int device,
+                                                      int function, int reg);
+
+void EXPORT_FUNC(grub_pci_iterate) (grub_pci_iteratefunc_t hook);
+
+#include <grub/cpu/pci.h>
+
+#endif /* GRUB_PCI_H */
diff --git a/include/grub/powerpc/ieee1275/biosdisk.h b/include/grub/powerpc/ieee1275/biosdisk.h
new file mode 100644 (file)
index 0000000..30584d6
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2004,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_BIOSDISK_MACHINE_HEADER
+#define GRUB_BIOSDISK_MACHINE_HEADER   1
+
+#define GRUB_BIOSDISK_FLAG_LBA 1
+
+struct grub_biosdisk_data
+{
+  int drive;
+  unsigned long cylinders;
+  unsigned long heads;
+  unsigned long sectors;
+  unsigned long flags;
+};
+
+int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap);
+int grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff,
+                              int soff, int nsec, int segment);
+int grub_biosdisk_check_int13_extensions (int drive);
+int grub_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp);
+int grub_biosdisk_get_diskinfo_standard (int drive,
+                                        unsigned long *cylinders,
+                                        unsigned long *heads,
+                                        unsigned long *sectors);
+int grub_biosdisk_get_num_floppies (void);
+
+void grub_biosdisk_init (void);
+
+#endif /* ! GRUB_BIOSDISK_MACHINE_HEADER */
diff --git a/include/grub/powerpc/ieee1275/console.h b/include/grub/powerpc/ieee1275/console.h
new file mode 100644 (file)
index 0000000..ed2b720
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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 GRUB_CONSOLE_MACHINE_HEADER
+#define GRUB_CONSOLE_MACHINE_HEADER    1
+
+/* Initialize the console system.  */
+void grub_console_init (void);
+
+/* Finish the console system.  */
+void grub_console_fini (void);
+
+#endif /* ! GRUB_CONSOLE_MACHINE_HEADER */
diff --git a/include/grub/powerpc/ieee1275/ieee1275.h b/include/grub/powerpc/ieee1275/ieee1275.h
new file mode 100644 (file)
index 0000000..7e93055
--- /dev/null
@@ -0,0 +1,27 @@
+/* ieee1275.h - Access the Open Firmware client interface.  */
+/*
+ *  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 GRUB_IEEE1275_MACHINE_HEADER
+#define GRUB_IEEE1275_MACHINE_HEADER   1
+
+#include <grub/types.h>
+
+typedef grub_uint32_t grub_ieee1275_cell_t;
+
+#endif /* ! GRUB_IEEE1275_MACHINE_HEADER */
diff --git a/include/grub/powerpc/ieee1275/kernel.h b/include/grub/powerpc/ieee1275/kernel.h
new file mode 100644 (file)
index 0000000..917e154
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2006,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_KERNEL_MACHINE_HEADER
+#define GRUB_KERNEL_MACHINE_HEADER     1
+
+#include <grub/symbol.h>
+
+#ifndef ASM_FILE
+
+void EXPORT_FUNC (grub_reboot) (void);
+void EXPORT_FUNC (grub_halt) (void);
+
+/* The prefix which points to the directory where GRUB modules and its
+   configuration file are located.  */
+extern char grub_prefix[];
+
+#endif
+
+#endif /* ! GRUB_KERNEL_MACHINE_HEADER */
diff --git a/include/grub/powerpc/ieee1275/loader.h b/include/grub/powerpc/ieee1275/loader.h
new file mode 100644 (file)
index 0000000..606bfcd
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,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_LOADER_MACHINE_HEADER
+#define GRUB_LOADER_MACHINE_HEADER     1
+
+/* The symbol shared between the normal mode and rescue mode
+   loader.  */
+void grub_rescue_cmd_linux (int argc, char *argv[]);
+void grub_rescue_cmd_initrd (int argc, char *argv[]);
+
+void grub_linux_init (void);
+void grub_linux_fini (void);
+void grub_linux_normal_init (void);
+void grub_linux_normal_fini (void);
+
+#endif /* ! GRUB_LOADER_MACHINE_HEADER */
diff --git a/include/grub/powerpc/ieee1275/machine.h b/include/grub/powerpc/ieee1275/machine.h
new file mode 100644 (file)
index 0000000..66da1d9
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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_MACHINE_MACHINE_HEADER
+#define GRUB_MACHINE_MACHINE_HEADER    1
+
+#define GRUB_MACHINE_IEEE1275  1
+
+#endif /* ! GRUB_MACHINE_MACHINE_HEADER */
diff --git a/include/grub/powerpc/ieee1275/memory.h b/include/grub/powerpc/ieee1275/memory.h
new file mode 100644 (file)
index 0000000..23e282f
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  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_MEMORY_MACHINE_HEADER
+#define GRUB_MEMORY_MACHINE_HEADER     1
+
+#define GRUB_MACHINE_MEMORY_AVAILABLE          1
+
+#endif
diff --git a/include/grub/powerpc/ieee1275/time.h b/include/grub/powerpc/ieee1275/time.h
new file mode 100644 (file)
index 0000000..3f8ad26
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *  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);
+
+#endif /* ! KERNEL_MACHINE_TIME_HEADER */
diff --git a/include/grub/powerpc/ieee1275/util/biosdisk.h b/include/grub/powerpc/ieee1275/util/biosdisk.h
new file mode 100644 (file)
index 0000000..f4262a0
--- /dev/null
@@ -0,0 +1,27 @@
+/* biosdisk.h - emulate biosdisk */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2004,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_BIOSDISK_MACHINE_UTIL_HEADER
+#define GRUB_BIOSDISK_MACHINE_UTIL_HEADER      1
+
+void grub_util_biosdisk_init (const char *dev_map);
+void grub_util_biosdisk_fini (void);
+char *grub_util_biosdisk_get_grub_dev (const char *os_dev);
+
+#endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */
diff --git a/include/grub/powerpc/kernel.h b/include/grub/powerpc/kernel.h
new file mode 100644 (file)
index 0000000..b468733
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2006,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_KERNEL_CPU_HEADER
+#define GRUB_KERNEL_CPU_HEADER 1
+
+#define GRUB_MOD_ALIGN 0x1000
+
+/* 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
+   rewrite grub-mkimage to generate valid ELF files.  */
+#define GRUB_MOD_GAP 0x8000
+
+#define GRUB_KERNEL_CPU_PREFIX         0x4
+#define GRUB_KERNEL_CPU_DATA_END       0x44
+
+#endif
diff --git a/include/grub/powerpc/libgcc.h b/include/grub/powerpc/libgcc.h
new file mode 100644 (file)
index 0000000..acdd146
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,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/>.
+ */
+
+void EXPORT_FUNC (memset) (void);
+void EXPORT_FUNC (__ashldi3) (void);
+void EXPORT_FUNC (__lshrdi3) (void);
+void EXPORT_FUNC (__trampoline_setup) (void);
+void EXPORT_FUNC (__ucmpdi2) (void);
diff --git a/include/grub/powerpc/setjmp.h b/include/grub/powerpc/setjmp.h
new file mode 100644 (file)
index 0000000..441e538
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2004,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_SETJMP_CPU_HEADER
+#define GRUB_SETJMP_CPU_HEADER 1
+
+typedef unsigned long grub_jmp_buf[20];
+
+int grub_setjmp (grub_jmp_buf env);
+void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn));
+
+#endif /* ! GRUB_SETJMP_CPU_HEADER */
diff --git a/include/grub/powerpc/time.h b/include/grub/powerpc/time.h
new file mode 100644 (file)
index 0000000..5db7ff4
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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
+
+static __inline void
+grub_cpu_idle (void)
+{
+  /* FIXME: not implemented */
+}
+
+#endif /* ! KERNEL_CPU_TIME_HEADER */
diff --git a/include/grub/powerpc/types.h b/include/grub/powerpc/types.h
new file mode 100644 (file)
index 0000000..a098ae6
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2004,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_TYPES_CPU_HEADER
+#define GRUB_TYPES_CPU_HEADER  1
+
+/* The size of void *.  */
+#define GRUB_TARGET_SIZEOF_VOID_P      4
+
+/* The size of long.  */
+#define GRUB_TARGET_SIZEOF_LONG                4
+
+/* powerpc is big-endian.  */
+#define GRUB_TARGET_WORDS_BIGENDIAN    1
+
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
diff --git a/include/grub/raid.h b/include/grub/raid.h
new file mode 100644 (file)
index 0000000..a36be6d
--- /dev/null
@@ -0,0 +1,86 @@
+/* raid.h - On disk structures for RAID. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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_RAID_H
+#define GRUB_RAID_H    1
+
+#include <grub/types.h>
+
+#define GRUB_RAID_MAX_DEVICES  32
+
+#define GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC       0
+#define GRUB_RAID_LAYOUT_RIGHT_ASYMMETRIC      1
+#define GRUB_RAID_LAYOUT_LEFT_SYMMETRIC                2
+#define GRUB_RAID_LAYOUT_RIGHT_SYMMETRIC       3
+
+#define GRUB_RAID_LAYOUT_RIGHT_MASK            1
+#define GRUB_RAID_LAYOUT_SYMMETRIC_MASK                2
+
+struct grub_raid_array
+{
+  int number;              /* The device number, taken from md_minor so we
+                             are consistent with the device name in
+                             Linux. */
+  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. */
+  grub_size_t chunk_size;  /* The size of a chunk, in 512 byte sectors. */
+  grub_uint64_t disk_size; /* Size of an individual disk, in 512 byte
+                             sectors. */
+  int index;               /* Index of current device.  */
+  int uuid_len;            /* The length of uuid.  */
+  char *uuid;              /* The UUID of the device. */
+
+  /* The following field is setup by the caller.  */
+  char *name;              /* That will be "md<number>". */
+  unsigned int nr_devs;    /* The number of devices we've found so far. */
+  grub_disk_t device[GRUB_RAID_MAX_DEVICES];  /* Array of total_devs devices. */
+  struct grub_raid_array *next;
+};
+
+struct grub_raid
+{
+  const char *name;
+
+  grub_err_t (*detect) (grub_disk_t disk, struct grub_raid_array *array);
+
+  struct grub_raid *next;
+};
+typedef struct grub_raid *grub_raid_t;
+
+void grub_raid_register (grub_raid_t raid);
+void grub_raid_unregister (grub_raid_t raid);
+
+void grub_raid_rescan (void);
+void grub_raid_block_xor (char *buf1, char *buf2, int size);
+
+typedef grub_err_t (*grub_raid5_recover_func_t) (struct grub_raid_array *array,
+                                                 int disknr, char *buf,
+                                                 grub_disk_addr_t sector,
+                                                 int size);
+
+typedef grub_err_t (*grub_raid6_recover_func_t) (struct grub_raid_array *array,
+                                                 int disknr, int p, char *buf,
+                                                 grub_disk_addr_t sector,
+                                                 int size);
+
+extern grub_raid5_recover_func_t grub_raid5_recover_func;
+extern grub_raid6_recover_func_t grub_raid6_recover_func;
+
+#endif /* ! GRUB_RAID_H */
diff --git a/include/grub/rescue.h b/include/grub/rescue.h
new file mode 100644 (file)
index 0000000..4d8d167
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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_RESCUE_HEADER
+#define GRUB_RESCUE_HEADER     1
+
+#include <grub/symbol.h>
+
+/* Enter rescue mode.  */
+void grub_enter_rescue_mode (void);
+
+/* Register a rescue mode command.  */
+void EXPORT_FUNC(grub_rescue_register_command) (const char *name,
+                                               void (*func) (int argc,
+                                                             char *argv[]),
+                                               const char *message);
+
+/* Unregister a rescue mode command.  */
+void EXPORT_FUNC(grub_rescue_unregister_command) (const char *name);
+
+#endif /* ! GRUB_RESCUE_HEADER */
diff --git a/include/grub/script.h b/include/grub/script.h
new file mode 100644 (file)
index 0000000..4d18b92
--- /dev/null
@@ -0,0 +1,287 @@
+/* script.h  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#ifndef GRUB_SCRIPT_HEADER
+#define GRUB_SCRIPT_HEADER     1
+
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/parser.h>
+
+struct grub_script_mem;
+
+/* The generic header for each scripting command or structure.  */
+struct grub_script_cmd
+{
+  /* This function is called to execute the command.  */
+  grub_err_t (*exec) (struct grub_script_cmd *cmd);
+
+  /* The next command.  This can be used by the parent to form a chain
+     of commands.  */
+  struct grub_script_cmd *next;
+};
+
+struct grub_script
+{
+  struct grub_script_mem *mem;
+  struct grub_script_cmd *cmd;
+};
+\f
+typedef enum
+{
+  GRUB_SCRIPT_ARG_TYPE_STR,
+  GRUB_SCRIPT_ARG_TYPE_VAR
+} grub_script_arg_type_t;
+
+/* A part of an argument.  */
+struct grub_script_arg
+{
+  grub_script_arg_type_t type;
+
+  char *str;
+
+  /* Next argument part.  */
+  struct grub_script_arg *next;
+};
+
+/* A complete argument.  It consists of a list of one or more `struct
+   grub_script_arg's.  */
+struct grub_script_arglist
+{
+  struct grub_script_arglist *next;
+  struct grub_script_arg *arg;
+  /* Only stored in the first link.  */
+  int argcount;
+};
+
+/* A single command line.  */
+struct grub_script_cmdline
+{
+  struct grub_script_cmd cmd;
+
+  /* The arguments for this command.  */
+  struct grub_script_arglist *arglist;
+
+  /* The command name of this command.  XXX: Perhaps an argument
+     should be used for this so we can use variables as command
+     name.  */
+  char *cmdname;
+};
+
+/* A block of commands, this can be used to group commands.  */
+struct grub_script_cmdblock
+{
+  struct grub_script_cmd cmd;
+
+  /* A chain of commands.  */
+  struct grub_script_cmd *cmdlist;
+};
+
+/* An if statement.  */
+struct grub_script_cmdif
+{
+  struct grub_script_cmd cmd;
+
+  /* The command used to check if the 'if' is true or false.  */
+  struct grub_script_cmd *exec_to_evaluate;
+
+  /* The code executed in case the result of 'if' was true.  */
+  struct grub_script_cmd *exec_on_true;
+
+  /* The code executed in case the result of 'if' was false.  */
+  struct grub_script_cmd *exec_on_false;
+};
+
+/* A menu entry generate statement.  */
+struct grub_script_cmd_menuentry
+{
+  struct grub_script_cmd cmd;
+
+  /* The arguments for this menu entry.  */
+  struct grub_script_arglist *arglist;
+
+  /* The sourcecode the entry will be generated from.  */
+  const char *sourcecode;
+
+  /* Options.  XXX: Not used yet.  */
+  int options;
+};
+
+/* State of the lexer as passed to the lexer.  */
+struct grub_lexer_param
+{
+  /* Set to 0 when the lexer is done.  */
+  int done;
+
+  /* State of the state machine.  */
+  grub_parser_state_t state;
+
+  /* Function used by the lexer to get a new line when more input is
+     expected, but not available.  */
+  grub_err_t (*getline) (char **);
+
+  /* A reference counter.  If this is >0 it means that the parser
+     expects more tokens and `getline' should be called to fetch more.
+     Otherwise the lexer can stop processing if the current buffer is
+     depleted.  */
+  int refs;
+
+  /* The character stream that has to be parsed.  */
+  char *script;
+  char *newscript; /* XXX */
+
+  /* While walking through the databuffer, `record' the characters to
+     this other buffer.  It can be used to edit the menu entry at a
+     later moment.  */
+
+  /* If true, recording is enabled.  */
+  int record;
+
+  /* Points to the recording.  */
+  char *recording;
+
+  /* index in the RECORDING.  */ 
+  int recordpos;
+
+  /* Size of RECORDING.  */
+  int recordlen;
+};
+
+/* State of the parser as passes to the parser.  */
+struct grub_parser_param
+{
+  /* Keep track of the memory allocated for this specific
+     function.  */
+  struct grub_script_mem *func_mem;
+
+  /* When set to 0, no errors have occured during parsing.  */
+  int err;
+
+  /* The memory that was used while parsing and scanning.  */
+  struct grub_script_mem *memused;
+
+  /* The result of the parser.  */
+  struct grub_script_cmd *parsed;
+
+  struct grub_lexer_param *lexerstate;
+};
+
+struct grub_script_arglist *
+grub_script_create_arglist (struct grub_parser_param *state);
+
+struct grub_script_arglist *
+grub_script_add_arglist (struct grub_parser_param *state,
+                        struct grub_script_arglist *list,
+                        struct grub_script_arg *arg);
+struct grub_script_cmd *
+grub_script_create_cmdline (struct grub_parser_param *state,
+                           char *cmdname,
+                           struct grub_script_arglist *arglist);
+struct grub_script_cmd *
+grub_script_create_cmdblock (struct grub_parser_param *state);
+
+struct grub_script_cmd *
+grub_script_create_cmdif (struct grub_parser_param *state,
+                         struct grub_script_cmd *exec_to_evaluate,
+                         struct grub_script_cmd *exec_on_true,
+                         struct grub_script_cmd *exec_on_false);
+
+struct grub_script_cmd *
+grub_script_create_cmdmenu (struct grub_parser_param *state,
+                           struct grub_script_arglist *arglist,
+                           char *sourcecode,
+                           int options);
+
+struct grub_script_cmd *
+grub_script_add_cmd (struct grub_parser_param *state,
+                    struct grub_script_cmdblock *cmdblock,
+                    struct grub_script_cmd *cmd);
+struct grub_script_arg *
+grub_script_arg_add (struct grub_parser_param *state,
+                    struct grub_script_arg *arg,
+                    grub_script_arg_type_t type, char *str);
+
+struct grub_script *grub_script_parse (char *script,
+                                      grub_err_t (*getline) (char **));
+void grub_script_free (struct grub_script *script);
+struct grub_script *grub_script_create (struct grub_script_cmd *cmd,
+                                       struct grub_script_mem *mem);
+
+struct grub_lexer_param *grub_script_lexer_init (char *s,
+                                                grub_err_t (*getline) (char **));
+void grub_script_lexer_ref (struct grub_lexer_param *);
+void grub_script_lexer_deref (struct grub_lexer_param *);
+void grub_script_lexer_record_start (struct grub_lexer_param *);
+char *grub_script_lexer_record_stop (struct grub_lexer_param *);
+
+/* Functions to track allocated memory.  */
+struct grub_script_mem *grub_script_mem_record (struct grub_parser_param *state);
+struct grub_script_mem *grub_script_mem_record_stop (struct grub_parser_param *state, 
+                                                    struct grub_script_mem *restore);
+void *grub_script_malloc (struct grub_parser_param *state, grub_size_t size);
+
+/* Functions used by bison.  */
+union YYSTYPE;
+int grub_script_yylex (union YYSTYPE *, struct grub_parser_param *);
+int grub_script_yyparse (struct grub_parser_param *);
+void grub_script_yyerror (struct grub_parser_param *, char const *);
+
+/* Commands to execute, don't use these directly.  */
+grub_err_t grub_script_execute_cmdline (struct grub_script_cmd *cmd);
+grub_err_t grub_script_execute_cmdblock (struct grub_script_cmd *cmd);
+grub_err_t grub_script_execute_cmdif (struct grub_script_cmd *cmd);
+grub_err_t grub_script_execute_menuentry (struct grub_script_cmd *cmd);
+
+/* Execute any GRUB pre-parsed command or script.  */
+grub_err_t grub_script_execute (struct grub_script *script);
+
+/* This variable points to the parsed command.  This is used to
+   communicate with the bison code.  */
+extern struct grub_script_cmd *grub_script_parsed;
+
+\f
+
+/* The function description.  */
+struct grub_script_function
+{
+  /* The name.  */
+  char *name;
+
+  /* The script function.  */
+  struct grub_script *func;
+
+  /* The flags.  */
+  unsigned flags;
+
+  /* The next element.  */
+  struct grub_script_function *next;
+
+  int references;
+};
+typedef struct grub_script_function *grub_script_function_t;
+
+grub_script_function_t grub_script_function_create (char *functionname,
+                                                   struct grub_script *cmd);
+void grub_script_function_remove (const char *name);
+grub_script_function_t grub_script_function_find (char *functionname);
+int grub_script_function_iterate (int (*iterate) (grub_script_function_t));
+int grub_script_function_call (grub_script_function_t func,
+                              int argc, char **args);
+
+#endif /* ! GRUB_SCRIPT_HEADER */
diff --git a/include/grub/scsi.h b/include/grub/scsi.h
new file mode 100644 (file)
index 0000000..fbe4582
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *  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_SCSI_H
+#define        GRUB_SCSI_H     1
+
+typedef struct grub_scsi_dev *grub_scsi_dev_t;
+
+void grub_scsi_dev_register (grub_scsi_dev_t dev);
+void grub_scsi_dev_unregister (grub_scsi_dev_t dev);
+
+struct grub_scsi;
+
+struct grub_scsi_dev
+{
+  /* The device name.  */
+  const char *name;
+
+  /* Call HOOK with each device name, until HOOK returns non-zero.  */
+  int (*iterate) (int (*hook) (const char *name, int luns));
+
+  /* Open the device named NAME, and set up SCSI.  */
+  grub_err_t (*open) (const char *name, struct grub_scsi *scsi);
+
+  /* Close the scsi device SCSI.  */
+  void (*close) (struct grub_scsi *scsi);
+
+  /* Read SIZE bytes from the device SCSI into BUF after sending the
+     command CMD of size CMDSIZE.  */
+  grub_err_t (*read) (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
+                     grub_size_t size, char *buf);
+
+  /* Write SIZE  bytes from BUF to  the device SCSI  after sending the
+     command CMD of size CMDSIZE.  */
+  grub_err_t (*write) (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
+                      grub_size_t size, char *buf);
+
+  /* The next scsi device.  */
+  struct grub_scsi_dev *next;
+};
+
+struct grub_scsi
+{
+  /* The scsi device name.  */
+  char *name;
+
+  /* The underlying scsi device.  */
+  grub_scsi_dev_t dev;
+
+  /* Type of SCSI device.  XXX: Make enum.  */
+  grub_uint8_t devtype;
+
+  /* Number of LUNs.  */
+  int luns;
+
+  /* LUN for this `struct grub_scsi'.  */
+  int lun;
+
+  /* Set to 0 when not removable, 1 when removable.  */
+  int removable;
+
+  /* Size of the device in blocks.  */
+  int size;
+
+  /* Size of one block.  */
+  int blocksize;
+
+  /* Device-specific data.  */
+  void *data;
+};
+typedef struct grub_scsi *grub_scsi_t;
+
+#endif /* GRUB_SCSI_H */
diff --git a/include/grub/scsicmd.h b/include/grub/scsicmd.h
new file mode 100644 (file)
index 0000000..40f237a
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *  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_SCSICMD_H
+#define        GRUB_SCSICMD_H  1
+
+#include <grub/types.h>
+
+#define GRUB_SCSI_DEVTYPE_MASK 31
+#define GRUB_SCSI_REMOVABLE_BIT        7
+#define GRUB_SCSI_LUN_SHIFT    5
+
+struct grub_scsi_inquiry
+{
+  grub_uint8_t opcode;
+  grub_uint8_t lun;
+  grub_uint16_t reserved;
+  grub_uint16_t alloc_length;
+  grub_uint8_t reserved2;
+  grub_uint8_t pad[5];
+} __attribute__((packed));
+
+struct grub_scsi_inquiry_data
+{
+  grub_uint8_t devtype;
+  grub_uint8_t rmb;
+  grub_uint16_t reserved;
+  grub_uint8_t length;
+  grub_uint8_t reserved2[3];
+  char vendor[8];
+  char prodid[16];
+  char prodrev[4];
+} __attribute__((packed));
+
+struct grub_scsi_read_capacity
+{
+  grub_uint8_t opcode;
+  grub_uint8_t lun;
+  grub_uint8_t reserved[8];
+  grub_uint8_t pad[2];
+} __attribute__((packed));
+
+struct grub_scsi_read_capacity_data
+{
+  grub_uint32_t size;
+  grub_uint32_t blocksize;
+} __attribute__((packed));
+
+struct grub_scsi_read10
+{
+  grub_uint8_t opcode;
+  grub_uint8_t lun;
+  grub_uint32_t lba;
+  grub_uint8_t reserved;
+  grub_uint16_t size;
+  grub_uint8_t reserved2;
+  grub_uint16_t pad;
+} __attribute__((packed));
+
+struct grub_scsi_read12
+{
+  grub_uint8_t opcode;
+  grub_uint8_t lun;
+  grub_uint32_t lba;
+  grub_uint32_t size;
+  grub_uint8_t reserved;
+  grub_uint8_t control;
+} __attribute__((packed));
+
+struct grub_scsi_write10
+{
+  grub_uint8_t opcode;
+  grub_uint8_t lun;
+  grub_uint32_t lba;
+  grub_uint8_t reserved;
+  grub_uint16_t size;
+  grub_uint8_t reserved2;
+  grub_uint16_t pad;
+} __attribute__((packed));
+
+struct grub_scsi_write12
+{
+  grub_uint8_t opcode;
+  grub_uint8_t lun;
+  grub_uint32_t lba;
+  grub_uint32_t size;
+  grub_uint8_t reserved;
+  grub_uint8_t control;
+} __attribute__((packed));
+
+typedef enum
+  {
+    grub_scsi_cmd_inquiry = 0x12,
+    grub_scsi_cmd_read_capacity = 0x25,
+    grub_scsi_cmd_read10 = 0x28,
+    grub_scsi_cmd_write10 = 0x2a,
+    grub_scsi_cmd_read12 = 0xa8,
+    grub_scsi_cmd_write12 = 0xaa
+  } grub_scsi_cmd_t;
+
+typedef enum
+  {
+    grub_scsi_devtype_direct = 0x00,
+    grub_scsi_devtype_cdrom = 0x05
+  } grub_scsi_devtype_t;
+
+#endif /* GRUB_SCSICMD_H */
diff --git a/include/grub/setjmp.h b/include/grub/setjmp.h
new file mode 100644 (file)
index 0000000..70147a7
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,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_SETJMP_HEADER
+#define GRUB_SETJMP_HEADER     1
+
+#if defined(GRUB_UTIL) && !defined(GRUBOF)
+#include <setjmp.h>
+typedef jmp_buf grub_jmp_buf;
+#define grub_setjmp setjmp
+#define grub_longjmp longjmp
+#else
+/* This must define grub_jmp_buf, and declare grub_setjmp and
+   grub_longjmp.  */
+# include <grub/cpu/setjmp.h>
+#endif
+
+#endif /* ! GRUB_SETJMP_HEADER */
diff --git a/include/grub/sparc64/ieee1275/console.h b/include/grub/sparc64/ieee1275/console.h
new file mode 100644 (file)
index 0000000..ed2b720
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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 GRUB_CONSOLE_MACHINE_HEADER
+#define GRUB_CONSOLE_MACHINE_HEADER    1
+
+/* Initialize the console system.  */
+void grub_console_init (void);
+
+/* Finish the console system.  */
+void grub_console_fini (void);
+
+#endif /* ! GRUB_CONSOLE_MACHINE_HEADER */
diff --git a/include/grub/sparc64/ieee1275/ieee1275.h b/include/grub/sparc64/ieee1275/ieee1275.h
new file mode 100644 (file)
index 0000000..1ef95f9
--- /dev/null
@@ -0,0 +1,27 @@
+/* ieee1275.h - Access the Open Firmware client interface.  */
+/*
+ *  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 GRUB_IEEE1275_MACHINE_HEADER
+#define GRUB_IEEE1275_MACHINE_HEADER   1
+
+#include <grub/types.h>
+
+typedef grub_uint64_t grub_ieee1275_cell_t;
+
+#endif /* ! GRUB_IEEE1275_MACHINE_HEADER */
diff --git a/include/grub/sparc64/ieee1275/kernel.h b/include/grub/sparc64/ieee1275/kernel.h
new file mode 100644 (file)
index 0000000..0b6bce2
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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 GRUB_KERNEL_MACHINE_HEADER
+#define GRUB_KERNEL_MACHINE_HEADER     1
+
+#include <grub/symbol.h>
+
+void EXPORT_FUNC (grub_reboot) (void);
+void EXPORT_FUNC (grub_halt) (void);
+
+/* Where grub-mkimage places the core modules in memory.  */
+#define GRUB_IEEE1275_MODULE_BASE 0x00300000
+
+#endif /* ! GRUB_KERNEL_MACHINE_HEADER */
diff --git a/include/grub/sparc64/ieee1275/machine.h b/include/grub/sparc64/ieee1275/machine.h
new file mode 100644 (file)
index 0000000..66da1d9
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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_MACHINE_MACHINE_HEADER
+#define GRUB_MACHINE_MACHINE_HEADER    1
+
+#define GRUB_MACHINE_IEEE1275  1
+
+#endif /* ! GRUB_MACHINE_MACHINE_HEADER */
diff --git a/include/grub/sparc64/ieee1275/time.h b/include/grub/sparc64/ieee1275/time.h
new file mode 100644 (file)
index 0000000..3f8ad26
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *  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);
+
+#endif /* ! KERNEL_MACHINE_TIME_HEADER */
diff --git a/include/grub/sparc64/libgcc.h b/include/grub/sparc64/libgcc.h
new file mode 100644 (file)
index 0000000..e30c717
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,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/>.
+ */
+
+void EXPORT_FUNC (memset) (void);
diff --git a/include/grub/sparc64/setjmp.h b/include/grub/sparc64/setjmp.h
new file mode 100644 (file)
index 0000000..12d8e01
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2004,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_SETJMP_CPU_HEADER
+#define GRUB_SETJMP_CPU_HEADER 1
+
+/* FIXME (sparc64).  */
+typedef unsigned long grub_jmp_buf[20];
+
+int grub_setjmp (grub_jmp_buf env);
+void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn));
+
+#endif /* ! GRUB_SETJMP_CPU_HEADER */
diff --git a/include/grub/sparc64/time.h b/include/grub/sparc64/time.h
new file mode 100644 (file)
index 0000000..5db7ff4
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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
+
+static __inline void
+grub_cpu_idle (void)
+{
+  /* FIXME: not implemented */
+}
+
+#endif /* ! KERNEL_CPU_TIME_HEADER */
diff --git a/include/grub/sparc64/types.h b/include/grub/sparc64/types.h
new file mode 100644 (file)
index 0000000..b9b0cf9
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2004,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_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
+
+/* sparc64 is big-endian.  */
+#define GRUB_TARGET_WORDS_BIGENDIAN    1
+
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
diff --git a/include/grub/symbol.h b/include/grub/symbol.h
new file mode 100644 (file)
index 0000000..ef19a73
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2006,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_SYMBOL_HEADER
+#define GRUB_SYMBOL_HEADER     1
+
+#include <config.h>
+
+/* Add an underscore to a C symbol in assembler code if needed. */
+#ifdef HAVE_ASM_USCORE
+# define EXT_C(sym)    _ ## sym
+#else
+# define EXT_C(sym)    sym
+#endif
+
+#if ! defined (__CYGWIN__) && ! defined (__MINGW32__)
+#define FUNCTION(x)    .globl EXT_C(x) ; .type EXT_C(x), "function" ; EXT_C(x):
+#define VARIABLE(x)    .globl EXT_C(x) ; .type EXT_C(x), "object" ; EXT_C(x):
+#else
+/* .type not supported for non-ELF targets.  XXX: Check this in configure? */
+#define FUNCTION(x)    .globl EXT_C(x) ; .def EXT_C(x); .scl 2; .type 32; .endef; EXT_C(x):
+#define VARIABLE(x)    .globl EXT_C(x) ; .def EXT_C(x); .scl 2; .type 0; .endef; EXT_C(x):
+#endif
+
+/* Mark an exported symbol.  */
+#ifndef GRUB_SYMBOL_GENERATOR
+# define EXPORT_FUNC(x)        x
+# define EXPORT_VAR(x) x
+#endif /* ! GRUB_SYMBOL_GENERATOR */
+
+#endif /* ! GRUB_SYMBOL_HEADER */
diff --git a/include/grub/term.h b/include/grub/term.h
new file mode 100644 (file)
index 0000000..13835bb
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2005,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_TERM_HEADER
+#define GRUB_TERM_HEADER       1
+
+/* Internal codes used by GRUB to represent terminal input.  */
+#define GRUB_TERM_LEFT         2
+#define GRUB_TERM_RIGHT                6
+#define GRUB_TERM_UP           16
+#define GRUB_TERM_DOWN         14
+#define GRUB_TERM_HOME         1
+#define GRUB_TERM_END          5
+#define GRUB_TERM_DC           4
+#define GRUB_TERM_PPAGE                7
+#define GRUB_TERM_NPAGE                3
+#define GRUB_TERM_ESC          '\e'
+#define GRUB_TERM_TAB          '\t'
+#define GRUB_TERM_BACKSPACE    '\b'
+
+#ifndef ASM_FILE
+
+#include <grub/err.h>
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+/* These are used to represent the various color states we use.  */
+typedef enum
+  {
+    /* The color used to display all text that does not use the
+       user defined colors below.  */
+    GRUB_TERM_COLOR_STANDARD,
+    /* The user defined colors for normal text.  */
+    GRUB_TERM_COLOR_NORMAL,
+    /* The user defined colors for highlighted text.  */
+    GRUB_TERM_COLOR_HIGHLIGHT
+  }
+grub_term_color_state;
+
+/* Flags for representing the capabilities of a terminal.  */
+/* Some notes about the flags:
+   - These flags are used by higher-level functions but not terminals
+   themselves.
+   - If a terminal is dumb, you may assume that only putchar, getkey and
+   checkkey are called.
+   - Some fancy features (setcolorstate, setcolor and setcursor) can be set
+   to NULL.  */
+
+/* Set when input characters shouldn't be echoed back.  */
+#define GRUB_TERM_NO_ECHO      (1 << 0)
+/* Set when the editing feature should be disabled.  */
+#define GRUB_TERM_NO_EDIT      (1 << 1)
+/* Set when the terminal cannot do fancy things.  */
+#define GRUB_TERM_DUMB         (1 << 2)
+/* Set when the terminal needs to be initialized.  */
+#define GRUB_TERM_NEED_INIT    (1 << 16)
+
+
+/* Unicode characters for fancy graphics.  */
+#define GRUB_TERM_DISP_LEFT    0x2190
+#define GRUB_TERM_DISP_UP      0x2191
+#define GRUB_TERM_DISP_RIGHT   0x2192
+#define GRUB_TERM_DISP_DOWN    0x2193
+#define GRUB_TERM_DISP_HLINE   0x2501
+#define GRUB_TERM_DISP_VLINE   0x2503
+#define GRUB_TERM_DISP_UL      0x250F
+#define GRUB_TERM_DISP_UR      0x2513
+#define GRUB_TERM_DISP_LL      0x2517
+#define GRUB_TERM_DISP_LR      0x251B
+
+
+/* Menu-related geometrical constants.  */
+
+/* FIXME: Ugly way to get them form terminal.  */
+#define GRUB_TERM_WIDTH         ((grub_getwh()&0xFF00)>>8)
+#define GRUB_TERM_HEIGHT        (grub_getwh()&0xFF)
+
+/* The number of lines of "GRUB version..." at the top.  */
+#define GRUB_TERM_INFO_HEIGHT  1
+
+/* The number of columns/lines between messages/borders/etc.  */
+#define GRUB_TERM_MARGIN       1
+
+/* The number of columns of scroll information.  */
+#define GRUB_TERM_SCROLL_WIDTH 1
+
+/* The Y position of the top border.  */
+#define GRUB_TERM_TOP_BORDER_Y (GRUB_TERM_MARGIN + GRUB_TERM_INFO_HEIGHT \
+                                 + GRUB_TERM_MARGIN)
+
+/* The X position of the left border.  */
+#define GRUB_TERM_LEFT_BORDER_X        GRUB_TERM_MARGIN
+
+/* The width of the border.  */
+#define GRUB_TERM_BORDER_WIDTH (GRUB_TERM_WIDTH \
+                                 - GRUB_TERM_MARGIN * 3 \
+                                - GRUB_TERM_SCROLL_WIDTH)
+
+/* The number of lines of messages at the bottom.  */
+#define GRUB_TERM_MESSAGE_HEIGHT       8
+
+/* The height of the border.  */
+#define GRUB_TERM_BORDER_HEIGHT        (GRUB_TERM_HEIGHT \
+                                 - GRUB_TERM_TOP_BORDER_Y \
+                                 - GRUB_TERM_MESSAGE_HEIGHT)
+
+/* The number of entries shown at a time.  */
+#define GRUB_TERM_NUM_ENTRIES  (GRUB_TERM_BORDER_HEIGHT - 2)
+
+/* The Y position of the first entry.  */
+#define GRUB_TERM_FIRST_ENTRY_Y        (GRUB_TERM_TOP_BORDER_Y + 1)
+
+/* The max column number of an entry. The last "-1" is for a
+   continuation marker.  */
+#define GRUB_TERM_ENTRY_WIDTH  (GRUB_TERM_BORDER_WIDTH - 2 \
+                                 - GRUB_TERM_MARGIN * 2 - 1)
+
+/* The standard X position of the cursor.  */
+#define GRUB_TERM_CURSOR_X     (GRUB_TERM_LEFT_BORDER_X \
+                                 + GRUB_TERM_BORDER_WIDTH \
+                                 - GRUB_TERM_MARGIN \
+                                 - 1)
+
+
+struct grub_term_input
+{
+  /* The terminal name.  */
+  const char *name;
+
+  /* Initialize the terminal.  */
+  grub_err_t (*init) (void);
+
+  /* Clean up the terminal.  */
+  grub_err_t (*fini) (void);
+  
+  /* Check if any input character is available.  */
+  int (*checkkey) (void);
+  
+  /* Get a character.  */
+  int (*getkey) (void);
+
+  /* The next terminal.  */
+  struct grub_term_input *next;
+};
+typedef struct grub_term_input *grub_term_input_t;
+
+struct grub_term_output
+{
+  /* The terminal name.  */
+  const char *name;
+
+  /* Initialize the terminal.  */
+  grub_err_t (*init) (void);
+
+  /* Clean up the terminal.  */
+  grub_err_t (*fini) (void);
+  
+  /* Put a character. C is encoded in Unicode.  */
+  void (*putchar) (grub_uint32_t c);
+
+  /* Get the number of columns occupied by a given character C. C is
+     encoded in Unicode.  */
+  grub_ssize_t (*getcharwidth) (grub_uint32_t c);
+  
+  /* Get the screen size. The return value is ((Width << 8) | Height).  */
+  grub_uint16_t (*getwh) (void);
+
+  /* Get the cursor position. The return value is ((X << 8) | Y).  */
+  grub_uint16_t (*getxy) (void);
+  
+  /* Go to the position (X, Y).  */
+  void (*gotoxy) (grub_uint8_t x, grub_uint8_t y);
+  
+  /* Clear the screen.  */
+  void (*cls) (void);
+  
+  /* Set the current color to be used */
+  void (*setcolorstate) (grub_term_color_state state);
+  
+  /* Set the normal color and the highlight color. The format of each
+     color is VGA's.  */
+  void (*setcolor) (grub_uint8_t normal_color, grub_uint8_t highlight_color);
+  
+  /* Get the normal color and the highlight color. The format of each
+     color is VGA's.  */
+  void (*getcolor) (grub_uint8_t *normal_color, grub_uint8_t *highlight_color);
+  
+  /* Turn on/off the cursor.  */
+  void (*setcursor) (int on);
+
+  /* Update the screen.  */
+  void (*refresh) (void);
+
+  /* The feature flags defined above.  */
+  grub_uint32_t flags;
+  
+  /* The next terminal.  */
+  struct grub_term_output *next;
+};
+typedef struct grub_term_output *grub_term_output_t;
+
+void EXPORT_FUNC(grub_term_register_input) (grub_term_input_t term);
+void EXPORT_FUNC(grub_term_register_output) (grub_term_output_t term);
+void EXPORT_FUNC(grub_term_unregister_input) (grub_term_input_t term);
+void EXPORT_FUNC(grub_term_unregister_output) (grub_term_output_t term);
+void EXPORT_FUNC(grub_term_iterate_input) (int (*hook) (grub_term_input_t term));
+void EXPORT_FUNC(grub_term_iterate_output) (int (*hook) (grub_term_output_t term));
+
+grub_err_t EXPORT_FUNC(grub_term_set_current_input) (grub_term_input_t term);
+grub_err_t EXPORT_FUNC(grub_term_set_current_output) (grub_term_output_t term);
+grub_term_input_t EXPORT_FUNC(grub_term_get_current_input) (void);
+grub_term_output_t EXPORT_FUNC(grub_term_get_current_output) (void);
+
+void EXPORT_FUNC(grub_putchar) (int c);
+void EXPORT_FUNC(grub_putcode) (grub_uint32_t code);
+grub_ssize_t EXPORT_FUNC(grub_getcharwidth) (grub_uint32_t code);
+int EXPORT_FUNC(grub_getkey) (void);
+int EXPORT_FUNC(grub_checkkey) (void);
+grub_uint16_t EXPORT_FUNC(grub_getwh) (void);
+grub_uint16_t EXPORT_FUNC(grub_getxy) (void);
+void EXPORT_FUNC(grub_gotoxy) (grub_uint8_t x, grub_uint8_t y);
+void EXPORT_FUNC(grub_cls) (void);
+void EXPORT_FUNC(grub_setcolorstate) (grub_term_color_state state);
+void EXPORT_FUNC(grub_setcolor) (grub_uint8_t normal_color,
+                                grub_uint8_t highlight_color);
+void EXPORT_FUNC(grub_getcolor) (grub_uint8_t *normal_color,
+                                grub_uint8_t *highlight_color);
+int EXPORT_FUNC(grub_setcursor) (int on);
+int EXPORT_FUNC(grub_getcursor) (void);
+void EXPORT_FUNC(grub_refresh) (void);
+void EXPORT_FUNC(grub_set_more) (int onoff);
+
+/* For convenience.  */
+#define GRUB_TERM_ASCII_CHAR(c)        ((c) & 0xff)
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! GRUB_TERM_HEADER */
diff --git a/include/grub/terminfo.h b/include/grub/terminfo.h
new file mode 100644 (file)
index 0000000..1ea741e
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,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 GRUB_TERMINFO_HEADER
+#define GRUB_TERMINFO_HEADER   1
+
+#include <grub/err.h>
+#include <grub/types.h>
+
+char *grub_terminfo_get_current (void);
+grub_err_t grub_terminfo_set_current (const char *);
+
+void grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y);
+void grub_terminfo_cls (void);
+void grub_terminfo_reverse_video_on (void);
+void grub_terminfo_reverse_video_off (void);
+void grub_terminfo_cursor_on (void);
+void grub_terminfo_cursor_off (void);
+
+#endif /* ! GRUB_TERMINFO_HEADER */
diff --git a/include/grub/time.h b/include/grub/time.h
new file mode 100644 (file)
index 0000000..4dcd843
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  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_TIME_HEADER
+#define KERNEL_TIME_HEADER     1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/machine/time.h>
+#include <grub/cpu/time.h>
+
+void EXPORT_FUNC(grub_millisleep) (grub_uint32_t ms);
+grub_uint64_t EXPORT_FUNC(grub_get_time_ms) (void);
+
+grub_uint64_t grub_rtc_get_time_ms (void);
+
+static __inline void
+grub_sleep (grub_uint32_t s)
+{
+  grub_millisleep (1000 * s);
+}
+
+void grub_install_get_time_ms (grub_uint64_t (*get_time_ms_func) (void));
+
+#endif /* ! KERNEL_TIME_HEADER */
diff --git a/include/grub/tparm.h b/include/grub/tparm.h
new file mode 100644 (file)
index 0000000..642a22f
--- /dev/null
@@ -0,0 +1,26 @@
+/* tparm.h - parameter formatting of terminfo */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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 GRUB_TPARM_HEADER
+#define GRUB_TPARM_HEADER      1
+
+/* Function prototypes.  */
+char *grub_terminfo_tparm (const char *string, ...);
+
+#endif /* ! GRUB_TPARM_HEADER */
diff --git a/include/grub/types.h b/include/grub/types.h
new file mode 100644 (file)
index 0000000..8d51b66
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,2006,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_TYPES_HEADER
+#define GRUB_TYPES_HEADER      1
+
+#include <config.h>
+#include <grub/cpu/types.h>
+
+#define UNUSED __attribute__ ((unused))
+
+#ifdef GRUB_UTIL
+# define GRUB_CPU_SIZEOF_VOID_P        SIZEOF_VOID_P
+# define GRUB_CPU_SIZEOF_LONG  SIZEOF_LONG
+# ifdef WORDS_BIGENDIAN
+#  define GRUB_CPU_WORDS_BIGENDIAN     1
+# else
+#  undef GRUB_CPU_WORDS_BIGENDIAN
+# endif
+#else /* ! GRUB_UTIL */
+# define GRUB_CPU_SIZEOF_VOID_P        GRUB_TARGET_SIZEOF_VOID_P
+# define GRUB_CPU_SIZEOF_LONG  GRUB_TARGET_SIZEOF_LONG
+# ifdef GRUB_TARGET_WORDS_BIGENDIAN
+#  define GRUB_CPU_WORDS_BIGENDIAN     1
+# else
+#  undef GRUB_CPU_WORDS_BIGENDIAN
+# endif
+#endif /* ! GRUB_UTIL */
+
+#if GRUB_CPU_SIZEOF_VOID_P != GRUB_CPU_SIZEOF_LONG
+# error "This architecture is not supported because sizeof(void *) != sizeof(long)"
+#endif
+
+#if GRUB_CPU_SIZEOF_VOID_P != 4 && GRUB_CPU_SIZEOF_VOID_P != 8
+# error "This architecture is not supported because sizeof(void *) != 4 and sizeof(void *) != 8"
+#endif
+
+/* Define various wide integers.  */
+typedef signed char            grub_int8_t;
+typedef short                  grub_int16_t;
+typedef int                    grub_int32_t;
+#if GRUB_CPU_SIZEOF_VOID_P == 8
+typedef long                   grub_int64_t;
+#else
+typedef long long              grub_int64_t;
+#endif
+
+typedef unsigned char          grub_uint8_t;
+typedef unsigned short         grub_uint16_t;
+typedef unsigned               grub_uint32_t;
+#if GRUB_CPU_SIZEOF_VOID_P == 8
+typedef unsigned long          grub_uint64_t;
+#else
+typedef unsigned long long     grub_uint64_t;
+#endif
+
+/* Misc types.  */
+#if GRUB_TARGET_SIZEOF_VOID_P == 8
+typedef grub_uint64_t  grub_target_addr_t;
+typedef grub_uint64_t  grub_target_off_t;
+typedef grub_uint64_t  grub_target_size_t;
+typedef grub_int64_t   grub_target_ssize_t;
+#else
+typedef grub_uint32_t  grub_target_addr_t;
+typedef grub_uint32_t  grub_target_off_t;
+typedef grub_uint32_t  grub_target_size_t;
+typedef grub_int32_t   grub_target_ssize_t;
+#endif
+
+#if GRUB_CPU_SIZEOF_VOID_P == 8
+typedef grub_uint64_t  grub_addr_t;
+typedef grub_uint64_t  grub_size_t;
+typedef grub_int64_t   grub_ssize_t;
+#else
+typedef grub_uint32_t  grub_addr_t;
+typedef grub_uint32_t  grub_size_t;
+typedef grub_int32_t   grub_ssize_t;
+#endif
+
+#if GRUB_CPU_SIZEOF_VOID_P == 8
+# define ULONG_MAX 18446744073709551615UL
+# define LONG_MAX 9223372036854775807UL
+#else
+# define ULONG_MAX 4294967295UL
+# define LONG_MAX 2147483647UL
+#endif
+
+/* The type for representing a file offset.  */
+typedef grub_uint64_t  grub_off_t;
+
+/* The type for representing a disk block address.  */
+typedef grub_uint64_t  grub_disk_addr_t;
+
+/* Byte-orders.  */
+#define grub_swap_bytes16(x)   \
+({ \
+   grub_uint16_t _x = (x); \
+   (grub_uint16_t) ((_x << 8) | (_x >> 8)); \
+})
+
+#if defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)
+static inline grub_uint32_t grub_swap_bytes32(grub_uint32_t x)
+{
+       return __builtin_bswap32(x);
+}
+
+static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x)
+{
+       return __builtin_bswap64(x);
+}
+#else                                  /* not gcc 4.3 or newer */
+#define grub_swap_bytes32(x)   \
+({ \
+   grub_uint32_t _x = (x); \
+   (grub_uint32_t) ((_x << 24) \
+                    | ((_x & (grub_uint32_t) 0xFF00UL) << 8) \
+                    | ((_x & (grub_uint32_t) 0xFF0000UL) >> 8) \
+                    | (_x >> 24)); \
+})
+
+#define grub_swap_bytes64(x)   \
+({ \
+   grub_uint64_t _x = (x); \
+   (grub_uint64_t) ((_x << 56) \
+                    | ((_x & (grub_uint64_t) 0xFF00ULL) << 40) \
+                    | ((_x & (grub_uint64_t) 0xFF0000ULL) << 24) \
+                    | ((_x & (grub_uint64_t) 0xFF000000ULL) << 8) \
+                    | ((_x & (grub_uint64_t) 0xFF00000000ULL) >> 8) \
+                    | ((_x & (grub_uint64_t) 0xFF0000000000ULL) >> 24) \
+                    | ((_x & (grub_uint64_t) 0xFF000000000000ULL) >> 40) \
+                    | (_x >> 56)); \
+})
+#endif                                 /* not gcc 4.3 or newer */
+
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+# define grub_cpu_to_le16(x)   grub_swap_bytes16(x)
+# define grub_cpu_to_le32(x)   grub_swap_bytes32(x)
+# define grub_cpu_to_le64(x)   grub_swap_bytes64(x)
+# define grub_le_to_cpu16(x)   grub_swap_bytes16(x)
+# define grub_le_to_cpu32(x)   grub_swap_bytes32(x)
+# define grub_le_to_cpu64(x)   grub_swap_bytes64(x)
+# define grub_cpu_to_be16(x)   ((grub_uint16_t) (x))
+# define grub_cpu_to_be32(x)   ((grub_uint32_t) (x))
+# define grub_cpu_to_be64(x)   ((grub_uint64_t) (x))
+# define grub_be_to_cpu16(x)   ((grub_uint16_t) (x))
+# define grub_be_to_cpu32(x)   ((grub_uint32_t) (x))
+# define grub_be_to_cpu64(x)   ((grub_uint64_t) (x))
+# ifdef GRUB_TARGET_WORDS_BIGENDIAN
+#  define grub_target_to_host16(x)     ((grub_uint16_t) (x))
+#  define grub_target_to_host32(x)     ((grub_uint32_t) (x))
+#  define grub_target_to_host64(x)     ((grub_uint64_t) (x))
+#  define grub_host_to_target16(x)     ((grub_uint16_t) (x))
+#  define grub_host_to_target32(x)     ((grub_uint32_t) (x))
+#  define grub_host_to_target64(x)     ((grub_uint64_t) (x))
+# else /* ! GRUB_TARGET_WORDS_BIGENDIAN */
+#  define grub_target_to_host16(x)     grub_swap_bytes16(x)
+#  define grub_target_to_host32(x)     grub_swap_bytes32(x)
+#  define grub_target_to_host64(x)     grub_swap_bytes64(x)
+#  define grub_host_to_target16(x)     grub_swap_bytes16(x)
+#  define grub_host_to_target32(x)     grub_swap_bytes32(x)
+#  define grub_host_to_target64(x)     grub_swap_bytes64(x)
+# endif
+#else /* ! WORDS_BIGENDIAN */
+# define grub_cpu_to_le16(x)   ((grub_uint16_t) (x))
+# define grub_cpu_to_le32(x)   ((grub_uint32_t) (x))
+# define grub_cpu_to_le64(x)   ((grub_uint64_t) (x))
+# define grub_le_to_cpu16(x)   ((grub_uint16_t) (x))
+# define grub_le_to_cpu32(x)   ((grub_uint32_t) (x))
+# define grub_le_to_cpu64(x)   ((grub_uint64_t) (x))
+# define grub_cpu_to_be16(x)   grub_swap_bytes16(x)
+# define grub_cpu_to_be32(x)   grub_swap_bytes32(x)
+# define grub_cpu_to_be64(x)   grub_swap_bytes64(x)
+# define grub_be_to_cpu16(x)   grub_swap_bytes16(x)
+# define grub_be_to_cpu32(x)   grub_swap_bytes32(x)
+# define grub_be_to_cpu64(x)   grub_swap_bytes64(x)
+# ifdef GRUB_TARGET_WORDS_BIGENDIAN
+#  define grub_target_to_host16(x)     grub_swap_bytes16(x)
+#  define grub_target_to_host32(x)     grub_swap_bytes32(x)
+#  define grub_target_to_host64(x)     grub_swap_bytes64(x)
+#  define grub_host_to_target16(x)     grub_swap_bytes16(x)
+#  define grub_host_to_target32(x)     grub_swap_bytes32(x)
+#  define grub_host_to_target64(x)     grub_swap_bytes64(x)
+# else /* ! GRUB_TARGET_WORDS_BIGENDIAN */
+#  define grub_target_to_host16(x)     ((grub_uint16_t) (x))
+#  define grub_target_to_host32(x)     ((grub_uint32_t) (x))
+#  define grub_target_to_host64(x)     ((grub_uint64_t) (x))
+#  define grub_host_to_target16(x)     ((grub_uint16_t) (x))
+#  define grub_host_to_target32(x)     ((grub_uint32_t) (x))
+#  define grub_host_to_target64(x)     ((grub_uint64_t) (x))
+# endif
+#endif /* ! WORDS_BIGENDIAN */
+
+#endif /* ! GRUB_TYPES_HEADER */
diff --git a/include/grub/usb.h b/include/grub/usb.h
new file mode 100644 (file)
index 0000000..9c9e58b
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ *  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_USB_H
+#define        GRUB_USB_H      1
+
+#include <grub/usbdesc.h>
+#include <grub/usbtrans.h>
+
+typedef struct grub_usb_device *grub_usb_device_t;
+typedef struct grub_usb_controller *grub_usb_controller_t;
+typedef struct grub_usb_controller_dev *grub_usb_controller_dev_t;
+
+typedef enum
+  {
+    GRUB_USB_ERR_NONE,
+    GRUB_USB_ERR_INTERNAL,
+    GRUB_USB_ERR_STALL,
+    GRUB_USB_ERR_DATA,
+    GRUB_USB_ERR_NAK,
+    GRUB_USB_ERR_BABBLE,
+    GRUB_USB_ERR_TIMEOUT,
+    GRUB_USB_ERR_BITSTUFF
+  } grub_usb_err_t;
+
+typedef enum
+  {
+    GRUB_USB_SPEED_NONE,
+    GRUB_USB_SPEED_LOW,
+    GRUB_USB_SPEED_FULL,
+    GRUB_USB_SPEED_HIGH
+  } grub_usb_speed_t;
+
+/* Call HOOK with each device, until HOOK returns non-zero.  */
+int grub_usb_iterate (int (*hook) (grub_usb_device_t dev));
+
+grub_usb_err_t grub_usb_device_initialize (grub_usb_device_t dev);
+
+grub_usb_err_t grub_usb_get_descriptor (grub_usb_device_t dev,
+                                       grub_uint8_t type, grub_uint8_t index,
+                                       grub_size_t size, char *data);
+
+struct grub_usb_desc_endp *
+grub_usb_get_endpdescriptor (grub_usb_device_t usbdev, int addr);
+
+grub_usb_err_t grub_usb_clear_halt (grub_usb_device_t dev, int endpoint);
+
+
+grub_usb_err_t grub_usb_set_configuration (grub_usb_device_t dev,
+                                          int configuration);
+
+grub_usb_err_t grub_usb_get_string (grub_usb_device_t dev, grub_uint8_t index,
+                                   int langid, char **string);
+
+void grub_usb_controller_dev_register (grub_usb_controller_dev_t usb);
+
+void grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb);
+
+int grub_usb_controller_iterate (int (*hook) (grub_usb_controller_t dev));
+
+
+grub_usb_err_t grub_usb_control_msg (grub_usb_device_t dev, grub_uint8_t reqtype,
+                                    grub_uint8_t request, grub_uint16_t value,
+                                    grub_uint16_t index, grub_size_t size,
+                                    char *data);
+
+grub_usb_err_t
+grub_usb_bulk_read (grub_usb_device_t dev,
+                   int endpoint, grub_size_t size, char *data);
+grub_usb_err_t
+grub_usb_bulk_write (grub_usb_device_t dev,
+                    int endpoint, grub_size_t size, char *data);
+
+grub_usb_err_t
+grub_usb_root_hub (grub_usb_controller_t controller);
+
+\f
+/* XXX: All handled by libusb for now.  */
+struct grub_usb_controller_dev
+{
+  /* The device name.  */
+  const char *name;
+
+  int (*iterate) (int (*hook) (grub_usb_controller_t dev));
+
+  grub_usb_err_t (*transfer) (grub_usb_controller_t dev,
+                             grub_usb_transfer_t transfer);
+
+  int (*hubports) (grub_usb_controller_t dev);
+
+  grub_err_t (*portstatus) (grub_usb_controller_t dev, unsigned int port,
+                           unsigned int enable);
+
+  grub_usb_speed_t (*detect_dev) (grub_usb_controller_t dev, int port);
+
+  /* The next host controller.  */
+  struct grub_usb_controller_dev *next;
+};
+
+struct grub_usb_controller
+{
+  /* The underlying USB Host Controller device.  */
+  grub_usb_controller_dev_t dev;
+
+  /* Data used by the USB Host Controller Driver.  */
+  void *data;
+};
+\f
+
+struct grub_usb_interface
+{
+  struct grub_usb_desc_if *descif;
+
+  struct grub_usb_desc_endp *descendp;
+};
+
+struct grub_usb_configuration
+{
+  /* Configuration descriptors .  */
+  struct grub_usb_desc_config *descconf;
+
+  /* Interfaces associated to this configuration.  */
+  struct grub_usb_interface interf[32];
+};
+
+struct grub_usb_device
+{
+  /* The device descriptor of this device.  */
+  struct grub_usb_desc_device descdev;
+
+  /* The controller the device is connected to.  */
+  struct grub_usb_controller controller;
+
+  /* Device configurations (after opening the device).  */
+  struct grub_usb_configuration config[8];
+
+  /* Device address.  */
+  int addr;
+
+  /* Device speed.  */
+  grub_usb_speed_t speed;
+
+  /* All desciptors are read if this is set to 1.  */
+  int initialized;
+
+  /* Data toggle values (used for bulk transfers only).  */
+  int toggle[16];
+
+  /* Device-specific data.  */
+  void *data;
+};
+
+\f
+
+typedef enum
+  {
+    GRUB_USB_CLASS_NOTHERE,
+    GRUB_USB_CLASS_AUDIO,
+    GRUB_USB_CLASS_COMMUNICATION,
+    GRUB_USB_CLASS_HID,
+    GRUB_USB_CLASS_XXX,
+    GRUB_USB_CLASS_PHYSICAL,
+    GRUB_USB_CLASS_IMAGE,
+    GRUB_USB_CLASS_PRINTER,
+    GRUB_USB_CLASS_MASS_STORAGE,
+    GRUB_USB_CLASS_HUB,
+    GRUB_USB_CLASS_DATA_INTERFACE,
+    GRUB_USB_CLASS_SMART_CARD,
+    GRUB_USB_CLASS_CONTENT_SECURITY,
+    GRUB_USB_CLASS_VIDEO
+  } grub_usb_classes_t;
+
+typedef enum
+  {
+    GRUB_USBMS_SUBCLASS_BULK = 0x06
+  } grub_usbms_subclass_t;
+
+typedef enum
+  {
+    GRUB_USBMS_PROTOCOL_BULK = 0x50
+  } grub_usbms_protocol_t;
+
+static inline struct grub_usb_desc_if *
+grub_usb_get_config_interface (struct grub_usb_desc_config *config)
+{
+  struct grub_usb_desc_if *interf;
+
+  interf = (struct grub_usb_desc_if *) (sizeof (*config) + (char *) config);
+  return interf;
+}
+
+#endif /* GRUB_USB_H */
diff --git a/include/grub/usbdesc.h b/include/grub/usbdesc.h
new file mode 100644 (file)
index 0000000..97947dc
--- /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_USBDESC_H
+#define        GRUB_USBDESC_H  1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+
+typedef enum {
+  GRUB_USB_DESCRIPTOR_DEVICE = 1,
+  GRUB_USB_DESCRIPTOR_CONFIG,
+  GRUB_USB_DESCRIPTOR_STRING,
+  GRUB_USB_DESCRIPTOR_INTERFACE,
+  GRUB_USB_DESCRIPTOR_ENDPOINT,
+  GRUB_USB_DESCRIPTOR_HUB = 0x29
+} grub_usb_descriptor_t;
+
+struct grub_usb_desc_device
+{
+  grub_uint8_t length;
+  grub_uint8_t type;
+  grub_uint16_t usbrel;
+  grub_uint8_t class;
+  grub_uint8_t subclass;
+  grub_uint8_t protocol;
+  grub_uint8_t maxsize0;
+  grub_uint16_t vendorid;
+  grub_uint16_t prodid;
+  grub_uint16_t devrel;
+  grub_uint8_t strvendor;
+  grub_uint8_t strprod;
+  grub_uint8_t strserial;
+  grub_uint8_t configcnt;  
+} __attribute__ ((packed));
+
+struct grub_usb_desc_config
+{
+  grub_uint8_t length;
+  grub_uint8_t type;
+  grub_uint16_t totallen;
+  grub_uint8_t numif;
+  grub_uint8_t config;
+  grub_uint8_t strconfig;
+  grub_uint8_t attrib;
+  grub_uint8_t maxpower;
+} __attribute__ ((packed));
+
+#if 0
+struct grub_usb_desc_ifassosiation
+{
+  grub_uint8_t length;
+  grub_uint8_t type;
+  grub_uint8_t firstif;
+  grub_uint8_t ifcnt;
+  grub_uint8_t class;
+  grub_uint8_t subclass;
+  grub_uint8_t protocol;
+  grub_uint8_t function;
+} __attribute__ ((packed));
+#endif
+
+struct grub_usb_desc_if
+{
+  grub_uint8_t length;
+  grub_uint8_t type;
+  grub_uint8_t ifnum;
+  grub_uint8_t altsetting;
+  grub_uint8_t endpointcnt;
+  grub_uint8_t class;
+  grub_uint8_t subclass;
+  grub_uint8_t protocol;
+  grub_uint8_t strif;
+} __attribute__ ((packed));
+
+struct grub_usb_desc_endp
+{
+  grub_uint8_t length;
+  grub_uint8_t type;
+  grub_uint8_t endp_addr;
+  grub_uint8_t attrib;
+  grub_uint16_t maxpacket;
+  grub_uint8_t interval;
+} __attribute__ ((packed));
+
+struct grub_usb_desc_str
+{
+  grub_uint8_t length;
+  grub_uint8_t type;
+  grub_uint16_t str[0];
+} __attribute__ ((packed));
+
+struct grub_usb_usb_hubdesc
+{
+  grub_uint8_t length;
+  grub_uint8_t type;
+  grub_uint8_t portcnt;
+  grub_uint16_t characteristics;
+  grub_uint8_t pwdgood;
+  grub_uint8_t current;
+  /* Removable and power control bits follow.  */
+} __attribute__ ((packed));
+
+#endif /* GRUB_USBDESC_H */
diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h
new file mode 100644 (file)
index 0000000..7e4a9d7
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ *  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_USBTRANS_H
+#define        GRUB_USBTRANS_H 1
+
+typedef enum
+  {
+    GRUB_USB_TRANSFER_TYPE_IN,
+    GRUB_USB_TRANSFER_TYPE_OUT,
+    GRUB_USB_TRANSFER_TYPE_SETUP
+  } grub_transfer_type_t;
+
+typedef enum
+  {
+    GRUB_USB_TRANSACTION_TYPE_CONTROL,
+    GRUB_USB_TRANSACTION_TYPE_BULK
+  } grub_transaction_type_t;
+
+struct grub_usb_transaction
+{
+  int size;
+  int toggle;
+  grub_transfer_type_t pid;
+  char *data;
+};
+typedef struct grub_usb_transaction *grub_usb_transaction_t;
+
+struct grub_usb_transfer
+{
+  int devaddr;
+
+  int endpoint;
+
+  int size;
+
+  int transcnt;
+
+  int max;
+
+  grub_transaction_type_t type;
+
+  struct grub_usb_device *dev;
+
+  struct grub_usb_transaction *transactions;
+};
+typedef struct grub_usb_transfer *grub_usb_transfer_t;
+
+\f
+#define GRUB_USB_REQTYPE_IN            (1 << 7)
+#define GRUB_USB_REQTYPE_OUT           (0 << 7)
+#define GRUB_USB_REQTYPE_STANDARD      (0 << 5)
+#define GRUB_USB_REQTYPE_CLASS         (1 << 5)
+#define GRUB_USB_REQTYPE_VENDOR                (2 << 5)
+#define GRUB_USB_REQTYPE_TARGET_DEV    (0 << 0)
+#define GRUB_USB_REQTYPE_TARGET_INTERF (1 << 0)
+#define GRUB_USB_REQTYPE_TARGET_ENDP   (2 << 0)
+#define GRUB_USB_REQTYPE_TARGET_OTHER  (3 << 0)
+
+#define GRUB_USB_REQ_GET_STATUS                0x00
+#define GRUB_USB_REQ_CLEAR_FEATURE     0x01
+#define GRUB_USB_REQ_SET_FEATURE       0x03
+#define GRUB_USB_REQ_SET_ADDRESS       0x05
+#define GRUB_USB_REQ_GET_DESCRIPTOR    0x06
+#define GRUB_USB_REQ_SET_DESCRIPTOR    0x07
+#define GRUB_USB_REQ_GET_CONFIGURATION 0x08
+#define GRUB_USB_REQ_SET_CONFIGURATION 0x09
+#define GRUB_USB_REQ_GET_INTERFACE     0x0A
+#define GRUB_USB_REQ_SET_INTERFACE     0x0B
+#define GRUB_USB_REQ_SYNC_FRAME                0x0C
+
+#define GRUB_USB_REQ_HUB_GET_PORT_STATUS 0x00
+
+#define GRUB_USB_FEATURE_ENDP_HALT     0x01
+#define GRUB_USB_FEATURE_DEV_REMOTE_WU 0x02
+#define GRUB_USB_FEATURE_TEST_MODE     0x04
+
+#define GRUB_USB_HUB_STATUS_CONNECTED  (1 << 0)
+#define GRUB_USB_HUB_STATUS_LOWSPEED   (1 << 9)
+#define GRUB_USB_HUB_STATUS_HIGHSPEED  (1 << 10)
+
+struct grub_usb_packet_setup
+{
+  grub_uint8_t reqtype;
+  grub_uint8_t request;
+  grub_uint16_t value;
+  grub_uint16_t index;
+  grub_uint16_t length;
+} __attribute__((packed));
+
+
+#endif /* GRUB_USBTRANS_H */
diff --git a/include/grub/util/getroot.h b/include/grub/util/getroot.h
new file mode 100644 (file)
index 0000000..bf0c55c
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  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_UTIL_GETROOT_HEADER
+#define GRUB_UTIL_GETROOT_HEADER       1
+
+enum grub_dev_abstraction_types {
+  GRUB_DEV_ABSTRACTION_NONE,
+  GRUB_DEV_ABSTRACTION_LVM,
+  GRUB_DEV_ABSTRACTION_RAID,
+};
+
+char *grub_guess_root_device (const char *dir);
+char *grub_get_prefix (const char *dir);
+int grub_util_get_dev_abstraction (const char *os_dev);
+char *grub_util_get_grub_dev (const char *os_dev);
+const char *grub_util_check_block_device (const char *blk_dev);
+
+#endif /* ! GRUB_UTIL_GETROOT_HEADER */
diff --git a/include/grub/util/hostdisk.h b/include/grub/util/hostdisk.h
new file mode 100644 (file)
index 0000000..21efb0d
--- /dev/null
@@ -0,0 +1,27 @@
+/* biosdisk.h - emulate biosdisk */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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_BIOSDISK_MACHINE_UTIL_HEADER
+#define GRUB_BIOSDISK_MACHINE_UTIL_HEADER      1
+
+void grub_util_biosdisk_init (const char *dev_map);
+void grub_util_biosdisk_fini (void);
+char *grub_util_biosdisk_get_grub_dev (const char *os_dev);
+
+#endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */
diff --git a/include/grub/util/lvm.h b/include/grub/util/lvm.h
new file mode 100644 (file)
index 0000000..7a4c76c
--- /dev/null
@@ -0,0 +1,27 @@
+/* lvm.h - LVM 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_LVM_UTIL_HEADER
+#define GRUB_LVM_UTIL_HEADER   1
+
+#ifdef __linux__
+int grub_util_lvm_isvolume (char *name);
+#endif
+
+#endif /* ! GRUB_RAID_UTIL_HEADER */
diff --git a/include/grub/util/misc.h b/include/grub/util/misc.h
new file mode 100644 (file)
index 0000000..2e920c1
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2005,2006,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_UTIL_MISC_HEADER
+#define GRUB_UTIL_MISC_HEADER  1
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <unistd.h>
+
+#include <config.h>
+#include <grub/types.h>
+
+#ifdef __NetBSD__
+/* NetBSD uses /boot for its boot block.  */
+# define DEFAULT_DIRECTORY     "/grub"
+#else
+# define DEFAULT_DIRECTORY     "/boot/grub"
+#endif
+
+#define DEFAULT_DEVICE_MAP     DEFAULT_DIRECTORY "/device.map"
+
+extern char *progname;
+extern int verbosity;
+extern jmp_buf main_env;
+
+void grub_util_info (const char *fmt, ...);
+void grub_util_error (const char *fmt, ...) __attribute__ ((noreturn));
+
+void *xmalloc (size_t size);
+void *xrealloc (void *ptr, size_t size);
+char *xstrdup (const char *str);
+
+char *grub_util_get_path (const char *dir, const char *file);
+size_t grub_util_get_fp_size (FILE *fp);
+size_t grub_util_get_image_size (const char *path);
+void grub_util_read_at (void *img, size_t len, off_t offset, FILE *fp);
+char *grub_util_read_image (const char *path);
+void grub_util_load_image (const char *path, char *buf);
+void grub_util_write_image (const char *img, size_t size, FILE *out);
+void grub_util_write_image_at (const void *img, size_t size, off_t offset,
+                              FILE *out);
+
+#ifndef  HAVE_ASPRINTF
+
+int asprintf (char **buf, const char *fmt, ...);
+
+#endif
+
+#ifdef __MINGW32__
+
+#define fseeko fseeko64
+#define ftello ftello64
+
+void sync (void);
+void sleep(int s);
+
+grub_int64_t grub_util_get_disk_size (char *name);
+
+#endif
+
+#endif /* ! GRUB_UTIL_MISC_HEADER */
diff --git a/include/grub/util/raid.h b/include/grub/util/raid.h
new file mode 100644 (file)
index 0000000..67020bb
--- /dev/null
@@ -0,0 +1,27 @@
+/* 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 (char *name);
+#endif
+
+#endif /* ! GRUB_RAID_UTIL_HEADER */
diff --git a/include/grub/util/resolve.h b/include/grub/util/resolve.h
new file mode 100644 (file)
index 0000000..f42df32
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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_UTIL_RESOLVE_HEADER
+#define GRUB_UTIL_RESOLVE_HEADER       1
+
+struct grub_util_path_list
+{
+  const char *name;
+  struct grub_util_path_list *next;
+};
+
+/* Resolve the dependencies of the modules MODULES using the information
+   in the file DEP_LIST_FILE. The directory PREFIX is used to find files.  */
+struct grub_util_path_list *
+grub_util_resolve_dependencies (const char *prefix,
+                               const char *dep_list_file,
+                               char *modules[]);
+
+#endif /* ! GRUB_UTIL_RESOLVE_HEADER */
diff --git a/include/grub/video.h b/include/grub/video.h
new file mode 100644 (file)
index 0000000..cb73dae
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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_VIDEO_HEADER
+#define GRUB_VIDEO_HEADER      1
+
+#include <grub/err.h>
+#include <grub/types.h>
+
+/* Video color in hardware dependent format.  Users should not assume any
+   specific coding format.  */
+typedef grub_uint32_t grub_video_color_t;
+
+/* This structure is driver specific and should not be accessed directly by
+   outside code.  */
+struct grub_video_render_target;
+
+/* Forward declarations for used data structures.  */
+struct grub_video_bitmap;
+
+/* Defines used to describe video mode or rendering target.  */
+#define GRUB_VIDEO_MODE_TYPE_ALPHA             0x00000020
+#define GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED   0x00000010
+#define GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP       0x00000004
+#define GRUB_VIDEO_MODE_TYPE_INDEX_COLOR       0x00000002
+#define GRUB_VIDEO_MODE_TYPE_RGB               0x00000001
+
+/* Defines used to mask flags.  */
+#define GRUB_VIDEO_MODE_TYPE_COLOR_MASK                0x0000000F
+
+/* Defines used to specify requested bit depth.  */
+#define GRUB_VIDEO_MODE_TYPE_DEPTH_MASK                0x0000ff00
+#define GRUB_VIDEO_MODE_TYPE_DEPTH_POS         8
+
+/* Defined predefined render targets.  */
+#define GRUB_VIDEO_RENDER_TARGET_DISPLAY       ((struct grub_video_render_target *) 0)
+#define GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER  ((struct grub_video_render_target *) 0)
+#define GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER   ((struct grub_video_render_target *) 1)
+
+/* Defined blitting formats.  */
+enum grub_video_blit_format
+  {
+    /* Generic RGBA, use fields & masks.  */
+    GRUB_VIDEO_BLIT_FORMAT_RGBA,
+
+    /* Optimized RGBA's.  */
+    GRUB_VIDEO_BLIT_FORMAT_RGBA_8888,
+    GRUB_VIDEO_BLIT_FORMAT_BGRA_8888,
+
+    /* Generic RGB, use fields & masks.  */
+    GRUB_VIDEO_BLIT_FORMAT_RGB,
+
+    /* Optimized RGB's.  */
+    GRUB_VIDEO_BLIT_FORMAT_RGB_888,
+    GRUB_VIDEO_BLIT_FORMAT_BGR_888,
+    GRUB_VIDEO_BLIT_FORMAT_RGB_565,
+    GRUB_VIDEO_BLIT_FORMAT_BGR_565,
+
+    /* When needed, decode color or just use value as is.  */
+    GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR,
+    
+    /* Two color bitmap; bits packed: rows are not padded to byte boundary.  */
+    GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED
+  };
+
+/* Define blitting operators.  */
+enum grub_video_blit_operators
+  {
+    /* Replace target bitmap data with source.  */
+    GRUB_VIDEO_BLIT_REPLACE,
+    /* Blend target and source based on source's alpha value.  */
+    GRUB_VIDEO_BLIT_BLEND
+  };
+
+struct grub_video_mode_info
+{
+  /* Width of the screen.  */
+  unsigned int width;
+
+  /* Height of the screen.  */
+  unsigned int height;
+
+  /* Mode type bitmask.  Contains information like is it Index color or
+     RGB mode.  */
+  unsigned int mode_type;
+
+  /* Bits per pixel.  */
+  unsigned int bpp;
+
+  /* Bytes per pixel.  */
+  unsigned int bytes_per_pixel;
+
+  /* Pitch of one scanline.  How many bytes there are for scanline.  */
+  unsigned int pitch;
+
+  /* In index color mode, number of colors.  In RGB mode this is 256.  */
+  unsigned int number_of_colors;
+
+  /* Optimization hint how binary data is coded.  */
+  enum grub_video_blit_format blit_format;
+
+  /* How many bits are reserved for red color.  */
+  unsigned int red_mask_size;
+
+  /* What is location of red color bits.  In Index Color mode, this is 0.  */
+  unsigned int red_field_pos;
+
+  /* How many bits are reserved for green color.  */
+  unsigned int green_mask_size;
+
+  /* What is location of green color bits.  In Index Color mode, this is 0.  */
+  unsigned int green_field_pos;
+
+  /* How many bits are reserved for blue color.  */
+  unsigned int blue_mask_size;
+
+  /* What is location of blue color bits.  In Index Color mode, this is 0.  */
+  unsigned int blue_field_pos;
+
+  /* How many bits are reserved in color.  */
+  unsigned int reserved_mask_size;
+
+  /* What is location of reserved color bits.  In Index Color mode,
+     this is 0.  */
+  unsigned int reserved_field_pos;
+
+  /* For 1-bit bitmaps, the background color.  Used for bits = 0.  */
+  grub_uint8_t bg_red;
+  grub_uint8_t bg_green;
+  grub_uint8_t bg_blue;
+  grub_uint8_t bg_alpha;
+
+  /* For 1-bit bitmaps, the foreground color.  Used for bits = 1.  */
+  grub_uint8_t fg_red;
+  grub_uint8_t fg_green;
+  grub_uint8_t fg_blue;
+  grub_uint8_t fg_alpha;
+};
+
+struct grub_video_palette_data
+{
+  grub_uint8_t r; /* Red color value (0-255).  */
+  grub_uint8_t g; /* Green color value (0-255).  */
+  grub_uint8_t b; /* Blue color value (0-255).  */
+  grub_uint8_t a; /* Reserved bits value (0-255).  */
+};
+
+struct grub_video_adapter
+{
+  /* The video adapter name.  */
+  const char *name;
+
+  /* Initialize the video adapter.  */
+  grub_err_t (*init) (void);
+
+  /* Clean up the video adapter.  */
+  grub_err_t (*fini) (void);
+
+  grub_err_t (*setup) (unsigned int width,  unsigned int height,
+                       unsigned int mode_type);
+
+  grub_err_t (*get_info) (struct grub_video_mode_info *mode_info);
+
+  grub_err_t (*set_palette) (unsigned int start, unsigned int count,
+                             struct grub_video_palette_data *palette_data);
+
+  grub_err_t (*get_palette) (unsigned int start, unsigned int count,
+                             struct grub_video_palette_data *palette_data);
+
+  grub_err_t (*set_viewport) (unsigned int x, unsigned int y,
+                              unsigned int width, unsigned int height);
+
+  grub_err_t (*get_viewport) (unsigned int *x, unsigned int *y,
+                              unsigned int *width, unsigned int *height);
+
+  grub_video_color_t (*map_color) (grub_uint32_t color_name);
+
+  grub_video_color_t (*map_rgb) (grub_uint8_t red, grub_uint8_t green,
+                                 grub_uint8_t blue);
+
+  grub_video_color_t (*map_rgba) (grub_uint8_t red, grub_uint8_t green,
+                                  grub_uint8_t blue, grub_uint8_t alpha);
+
+  grub_err_t (*unmap_color) (grub_video_color_t color,
+                             grub_uint8_t *red, grub_uint8_t *green,
+                             grub_uint8_t *blue, grub_uint8_t *alpha);
+
+  grub_err_t (*fill_rect) (grub_video_color_t color, int x, int y,
+                           unsigned int width, unsigned int height);
+
+  grub_err_t (*blit_bitmap) (struct grub_video_bitmap *bitmap,
+                             enum grub_video_blit_operators oper,
+                             int x, int y, int offset_x, int offset_y,
+                             unsigned int width, unsigned int height);
+
+  grub_err_t (*blit_render_target) (struct grub_video_render_target *source,
+                                    enum grub_video_blit_operators oper,
+                                    int x, int y, int offset_x, int offset_y,
+                                    unsigned int width, unsigned int height);
+
+  grub_err_t (*scroll) (grub_video_color_t color, int dx, int dy);
+
+  grub_err_t (*swap_buffers) (void);
+
+  grub_err_t (*create_render_target) (struct grub_video_render_target **result,
+                                      unsigned int width, unsigned int height,
+                                      unsigned int mode_type);
+
+  grub_err_t (*delete_render_target) (struct grub_video_render_target *target);
+
+  grub_err_t (*set_active_render_target) (struct grub_video_render_target *target);
+
+  grub_err_t (*get_active_render_target) (struct grub_video_render_target **target);
+
+  /* The next video adapter.  */
+  struct grub_video_adapter *next;
+};
+typedef struct grub_video_adapter *grub_video_adapter_t;
+
+void grub_video_register (grub_video_adapter_t adapter);
+void grub_video_unregister (grub_video_adapter_t adapter);
+void grub_video_iterate (int (*hook) (grub_video_adapter_t adapter));
+
+grub_err_t grub_video_setup (unsigned int width, unsigned int height,
+                             unsigned int mode_type);
+
+grub_err_t grub_video_restore (void);
+
+grub_err_t grub_video_get_info (struct grub_video_mode_info *mode_info);
+
+enum grub_video_blit_format grub_video_get_blit_format (struct grub_video_mode_info *mode_info);
+
+grub_err_t grub_video_set_palette (unsigned int start, unsigned int count,
+                                   struct grub_video_palette_data *palette_data);
+
+grub_err_t grub_video_get_palette (unsigned int start, unsigned int count,
+                                   struct grub_video_palette_data *palette_data);
+
+grub_err_t grub_video_set_viewport (unsigned int x, unsigned int y,
+                                    unsigned int width, unsigned int height);
+
+grub_err_t grub_video_get_viewport (unsigned int *x, unsigned int *y,
+                                    unsigned int *width, unsigned int *height);
+
+grub_video_color_t grub_video_map_color (grub_uint32_t color_name);
+
+grub_video_color_t grub_video_map_rgb (grub_uint8_t red, grub_uint8_t green,
+                                       grub_uint8_t blue);
+
+grub_video_color_t grub_video_map_rgba (grub_uint8_t red, grub_uint8_t green,
+                                        grub_uint8_t blue, grub_uint8_t alpha);
+
+grub_err_t grub_video_unmap_color (grub_video_color_t color,
+                                   grub_uint8_t *red, grub_uint8_t *green,
+                                   grub_uint8_t *blue, grub_uint8_t *alpha);
+
+grub_err_t grub_video_fill_rect (grub_video_color_t color, int x, int y,
+                                 unsigned int width, unsigned int height);
+
+grub_err_t grub_video_blit_bitmap (struct grub_video_bitmap *bitmap,
+                                   enum grub_video_blit_operators oper,
+                                   int x, int y, int offset_x, int offset_y,
+                                   unsigned int width, unsigned int height);
+
+grub_err_t grub_video_blit_render_target (struct grub_video_render_target *source,
+                                          enum grub_video_blit_operators oper,
+                                          int x, int y,
+                                          int offset_x, int offset_y,
+                                          unsigned int width,
+                                          unsigned int height);
+
+grub_err_t grub_video_scroll (grub_video_color_t color, int dx, int dy);
+
+grub_err_t grub_video_swap_buffers (void);
+
+grub_err_t grub_video_create_render_target (struct grub_video_render_target **result,
+                                            unsigned int width,
+                                            unsigned int height,
+                                            unsigned int mode_type);
+
+grub_err_t grub_video_delete_render_target (struct grub_video_render_target *target);
+
+grub_err_t grub_video_set_active_render_target (struct grub_video_render_target *target);
+
+grub_err_t grub_video_get_active_render_target (struct grub_video_render_target **target);
+
+#endif /* ! GRUB_VIDEO_HEADER */
diff --git a/include/grub/x86_64/efi/kernel.h b/include/grub/x86_64/efi/kernel.h
new file mode 100644 (file)
index 0000000..c0549f4
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,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_MACHINE_KERNEL_HEADER
+#define GRUB_MACHINE_KERNEL_HEADER   1
+
+/* The prefix which points to the directory where GRUB modules and its
+   configuration file are located.  */
+extern char grub_prefix[];
+
+/* The offset of GRUB_PREFIX.  */
+#define GRUB_KERNEL_MACHINE_PREFIX             0x8
+
+/* End of the data section. */
+#define GRUB_KERNEL_MACHINE_DATA_END           0x50
+
+#endif /* ! GRUB_MACHINE_KERNEL_HEADER */
+
diff --git a/include/grub/x86_64/efi/loader.h b/include/grub/x86_64/efi/loader.h
new file mode 100644 (file)
index 0000000..4368a82
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,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_LOADER_MACHINE_HEADER
+#define GRUB_LOADER_MACHINE_HEADER     1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+
+/* It is necessary to export these functions, because normal mode commands
+   reuse rescue mode commands.  */
+void grub_rescue_cmd_linux (int argc, char *argv[]);
+void grub_rescue_cmd_initrd (int argc, char *argv[]);
+
+void EXPORT_FUNC(grub_linux_real_boot) (void);
+
+#endif /* ! GRUB_LOADER_MACHINE_HEADER */
diff --git a/include/grub/x86_64/efi/machine.h b/include/grub/x86_64/efi/machine.h
new file mode 100644 (file)
index 0000000..1600768
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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_MACHINE_MACHINE_HEADER
+#define GRUB_MACHINE_MACHINE_HEADER    1
+
+#define GRUB_MACHINE_EFI       1
+
+#endif /* ! GRUB_MACHINE_MACHINE_HEADER */
diff --git a/include/grub/x86_64/efi/time.h b/include/grub/x86_64/efi/time.h
new file mode 100644 (file)
index 0000000..7a9241f
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  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_MACHINE_TIME_HEADER
+#define GRUB_MACHINE_TIME_HEADER       1
+
+#include <grub/efi/time.h>
+
+#endif /* ! GRUB_MACHINE_TIME_HEADER */
diff --git a/include/grub/x86_64/kernel.h b/include/grub/x86_64/kernel.h
new file mode 100644 (file)
index 0000000..25ac57e
--- /dev/null
@@ -0,0 +1 @@
+#include <grub/i386/kernel.h>
diff --git a/include/grub/x86_64/linux.h b/include/grub/x86_64/linux.h
new file mode 100644 (file)
index 0000000..19ea936
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  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/i386/linux.h>
diff --git a/include/grub/x86_64/pci.h b/include/grub/x86_64/pci.h
new file mode 100644 (file)
index 0000000..91a9924
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  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/i386/pci.h>
diff --git a/include/grub/x86_64/setjmp.h b/include/grub/x86_64/setjmp.h
new file mode 100644 (file)
index 0000000..e417f65
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,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_SETJMP_CPU_HEADER
+#define GRUB_SETJMP_CPU_HEADER 1
+
+typedef unsigned long grub_jmp_buf[8];
+
+int grub_setjmp (grub_jmp_buf env);
+void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn));
+
+#endif /* ! GRUB_SETJMP_CPU_HEADER */
diff --git a/include/grub/x86_64/time.h b/include/grub/x86_64/time.h
new file mode 100644 (file)
index 0000000..842882c
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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
+
+static __inline void
+grub_cpu_idle (void)
+{
+  /* FIXME: this can't work until we handle interrupts.  */
+/*  __asm__ __volatile__ ("hlt"); */
+}
+
+#endif /* ! KERNEL_CPU_TIME_HEADER */
diff --git a/include/grub/x86_64/types.h b/include/grub/x86_64/types.h
new file mode 100644 (file)
index 0000000..bdee5a1
--- /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_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
+
+/* x86_64 is little-endian.  */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
diff --git a/include/multiboot.h b/include/multiboot.h
new file mode 100644 (file)
index 0000000..9adc873
--- /dev/null
@@ -0,0 +1,92 @@
+/* multiboot.h - multiboot header file. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,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 MULTIBOOT_HEADER
+#define MULTIBOOT_HEADER 1
+
+/* How many bytes from the start of the file we search for the header.  */
+#define MULTIBOOT_SEARCH                 8192
+
+/* The magic field should contain this.  */
+#define MULTIBOOT_MAGIC                  0x1BADB002
+
+/* This should be in %eax.  */
+#define MULTIBOOT_MAGIC2                 0x2BADB002
+
+/* The bits in the required part of flags field we don't support.  */
+#define MULTIBOOT_UNSUPPORTED            0x0000fffc
+
+/* Alignment of multiboot modules.  */
+#define MULTIBOOT_MOD_ALIGN              0x00001000
+
+/* 
+ * Flags set in the 'flags' member of the multiboot header.
+ */
+
+/* Align all boot modules on i386 page (4KB) boundaries.  */
+#define MULTIBOOT_PAGE_ALIGN           0x00000001
+
+/* Must pass memory information to OS.  */
+#define MULTIBOOT_MEMORY_INFO          0x00000002
+
+/* Must pass video information to OS.  */
+#define MULTIBOOT_VIDEO_MODE           0x00000004
+
+/* This flag indicates the use of the address fields in the header.  */
+#define MULTIBOOT_AOUT_KLUDGE          0x00010000
+
+/*
+ *  Flags to be set in the 'flags' member of the multiboot info structure.
+ */
+
+/* is there basic lower/upper memory information? */
+#define MULTIBOOT_INFO_MEMORY          0x00000001
+/* is there a boot device set? */
+#define MULTIBOOT_INFO_BOOTDEV         0x00000002
+/* is the command-line defined? */
+#define MULTIBOOT_INFO_CMDLINE         0x00000004
+/* are there modules to do something with? */
+#define MULTIBOOT_INFO_MODS            0x00000008
+
+/* These next two are mutually exclusive */
+
+/* is there a symbol table loaded? */
+#define MULTIBOOT_INFO_AOUT_SYMS               0x00000010
+/* is there an ELF section header table? */
+#define MULTIBOOT_INFO_ELF_SHDR                0x00000020
+
+/* is there a full memory map? */
+#define MULTIBOOT_INFO_MEM_MAP         0x00000040
+
+/* Is there drive info?  */
+#define MULTIBOOT_INFO_DRIVE_INFO              0x00000080
+
+/* Is there a config table?  */
+#define MULTIBOOT_INFO_CONFIG_TABLE    0x00000100
+
+/* Is there a boot loader name?  */
+#define MULTIBOOT_INFO_BOOT_LOADER_NAME        0x00000200
+
+/* Is there a APM table?  */
+#define MULTIBOOT_INFO_APM_TABLE               0x00000400
+
+/* Is there video information?  */
+#define MULTIBOOT_INFO_VIDEO_INFO              0x00000800
+
+#endif /* ! MULTIBOOT_HEADER */
diff --git a/include/multiboot2.h b/include/multiboot2.h
new file mode 100644 (file)
index 0000000..0f2b0cf
--- /dev/null
@@ -0,0 +1,108 @@
+/* multiboot2.h - multiboot 2 header file. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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 MULTIBOOT2_HEADER
+#define MULTIBOOT2_HEADER 1
+
+/* How many bytes from the start of the file we search for the header.  */
+#define MULTIBOOT2_HEADER_SEARCH           8192
+
+/* The magic field should contain this.  */
+#define MULTIBOOT2_HEADER_MAGIC            0xe85250d6
+
+/* Passed from the bootloader to the kernel.  */
+#define MULTIBOOT2_BOOTLOADER_MAGIC        0x36d76289
+
+/* Alignment of multiboot modules.  */
+#define MULTIBOOT2_MOD_ALIGN               0x00001000
+
+#ifndef ASM_FILE
+
+#include "stdint.h"
+
+/* XXX not portable? */
+#if __WORDSIZE == 64
+typedef uint64_t multiboot_word;
+#else
+typedef uint32_t multiboot_word;
+#endif
+
+struct multiboot_header
+{
+  uint32_t magic;
+  uint32_t flags;
+};
+
+struct multiboot_tag_header
+{
+  uint32_t key;
+  uint32_t len;
+};
+
+#define MULTIBOOT2_TAG_RESERVED1 0
+#define MULTIBOOT2_TAG_RESERVED2 (~0)
+
+#define MULTIBOOT2_TAG_START     1
+struct multiboot_tag_start
+{
+  struct multiboot_tag_header header;
+  multiboot_word size; /* Total size of all multiboot tags. */
+};
+
+#define MULTIBOOT2_TAG_NAME      2
+struct multiboot_tag_name
+{
+  struct multiboot_tag_header header;
+  char name[1];
+};
+
+#define MULTIBOOT2_TAG_MODULE    3
+struct multiboot_tag_module
+{
+  struct multiboot_tag_header header;
+  multiboot_word addr;
+  multiboot_word size;
+  char type[36];
+  char cmdline[1];
+};
+
+#define MULTIBOOT2_TAG_MEMORY    4
+struct multiboot_tag_memory
+{
+  struct multiboot_tag_header header;
+  multiboot_word addr;
+  multiboot_word size;
+  multiboot_word type;
+};
+
+#define MULTIBOOT2_TAG_UNUSED    5
+struct multiboot_tag_unused
+{
+  struct multiboot_tag_header header;
+};
+
+#define MULTIBOOT2_TAG_END       0xffff
+struct multiboot_tag_end
+{
+  struct multiboot_tag_header header;
+};
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! MULTIBOOT2_HEADER */
diff --git a/install-sh b/install-sh
new file mode 100755 (executable)
index 0000000..a5897de
--- /dev/null
@@ -0,0 +1,519 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2006-12-25.00
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" ""       $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+  test "$posix_glob" != "?" || {
+    if (set -f) 2>/dev/null; then
+      posix_glob=
+    else
+      posix_glob=:
+    fi
+  }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+     --help     display this help and exit.
+     --version  display version info and exit.
+
+  -c            (ignored)
+  -C            install only if different (preserve the last data modification time)
+  -d            create directories instead of installing files.
+  -g GROUP      $chgrpprog installed files to GROUP.
+  -m MODE       $chmodprog installed files to MODE.
+  -o USER       $chownprog installed files to USER.
+  -s            $stripprog installed files.
+  -t DIRECTORY  install into DIRECTORY.
+  -T            report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) ;;
+
+    -C) copy_on_change=true;;
+
+    -d) dir_arg=true;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+       shift;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+       case $mode in
+         *' '* | *'    '* | *'
+'*       | *'*'* | *'?'* | *'['*)
+           echo "$0: invalid mode: $mode" >&2
+           exit 1;;
+       esac
+       shift;;
+
+    -o) chowncmd="$chownprog $2"
+       shift;;
+
+    -s) stripcmd=$stripprog;;
+
+    -t) dst_arg=$2
+       shift;;
+
+    -T) no_target_directory=true;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)        shift
+       break;;
+
+    -*)        echo "$0: invalid option: $1" >&2
+       exit 1;;
+
+    *)  break;;
+  esac
+  shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dst_arg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dst_arg"
+      shift # fnord
+    fi
+    shift # arg
+    dst_arg=$arg
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call `install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  trap '(exit $?); exit' 1 2 13 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+       u_plus_rw=
+      else
+       u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+       u_plus_rw=
+      else
+       u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names starting with `-'.
+  case $src in
+    -*) src=./$src;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dst_arg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+
+    dst=$dst_arg
+    # Protect names starting with `-'.
+    case $dst in
+      -*) dst=./$dst;;
+    esac
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+       echo "$0: $dst_arg: Is a directory" >&2
+       exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+       (dirname "$dst") 2>/dev/null ||
+       expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+            X"$dst" : 'X\(//\)[^/]' \| \
+            X"$dst" : 'X\(//\)$' \| \
+            X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+       echo X"$dst" |
+           sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\/\)[^/].*/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\/\)$/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\).*/{
+                  s//\1/
+                  q
+                }
+                s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+       # Create intermediate dirs using mode 755 as modified by the umask.
+       # This is like FreeBSD 'install' as of 1997-10-28.
+       umask=`umask`
+       case $stripcmd.$umask in
+         # Optimize common cases.
+         *[2367][2367]) mkdir_umask=$umask;;
+         .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+         *[0-7])
+           mkdir_umask=`expr $umask + 22 \
+             - $umask % 100 % 40 + $umask % 20 \
+             - $umask % 10 % 4 + $umask % 2
+           `;;
+         *) mkdir_umask=$umask,go-w;;
+       esac
+
+       # With -d, create the new directory with the user-specified mode.
+       # Otherwise, rely on $mkdir_umask.
+       if test -n "$dir_arg"; then
+         mkdir_mode=-m$mode
+       else
+         mkdir_mode=
+       fi
+
+       posix_mkdir=false
+       case $umask in
+         *[123567][0-7][0-7])
+           # POSIX mkdir -p sets u+wx bits regardless of umask, which
+           # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+           ;;
+         *)
+           tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+           trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+           if (umask $mkdir_umask &&
+               exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+           then
+             if test -z "$dir_arg" || {
+                  # Check for POSIX incompatibilities with -m.
+                  # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+                  # other-writeable bit of parent directory when it shouldn't.
+                  # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+                  ls_ld_tmpdir=`ls -ld "$tmpdir"`
+                  case $ls_ld_tmpdir in
+                    d????-?r-*) different_mode=700;;
+                    d????-?--*) different_mode=755;;
+                    *) false;;
+                  esac &&
+                  $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+                    ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+                    test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+                  }
+                }
+             then posix_mkdir=:
+             fi
+             rmdir "$tmpdir/d" "$tmpdir"
+           else
+             # Remove any dirs left behind by ancient mkdir implementations.
+             rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+           fi
+           trap '' 0;;
+       esac;;
+    esac
+
+    if
+      $posix_mkdir && (
+       umask $mkdir_umask &&
+       $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+       /*) prefix='/';;
+       -*) prefix='./';;
+       *)  prefix='';;
+      esac
+
+      eval "$initialize_posix_glob"
+
+      oIFS=$IFS
+      IFS=/
+      $posix_glob set -f
+      set fnord $dstdir
+      shift
+      $posix_glob set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+       test -z "$d" && continue
+
+       prefix=$prefix$d
+       if test -d "$prefix"; then
+         prefixes=
+       else
+         if $posix_mkdir; then
+           (umask=$mkdir_umask &&
+            $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+           # Don't fail if two instances are running concurrently.
+           test -d "$prefix" || exit 1
+         else
+           case $prefix in
+             *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+             *) qprefix=$prefix;;
+           esac
+           prefixes="$prefixes '$qprefix'"
+         fi
+       fi
+       prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+       # Don't fail if two instances are running concurrently.
+       (umask $mkdir_umask &&
+        eval "\$doit_exec \$mkdirprog $prefixes") ||
+         test -d "$dstdir" || exit 1
+       obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"    2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+       eval "$initialize_posix_glob" &&
+       $posix_glob set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       $posix_glob set +f &&
+
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+       # Now remove or move aside any old file at destination location.
+       # We try this two ways since rm can't unlink itself on some
+       # systems and the destination file might be busy for other
+       # reasons.  In this case, the final cleanup might fail but the new
+       # file should still install successfully.
+       {
+         test ! -f "$dst" ||
+         $doit $rmcmd -f "$dst" 2>/dev/null ||
+         { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+           { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+         } ||
+         { echo "$0: cannot unlink or rename $dst" >&2
+           (exit 1); exit 1
+         }
+       } &&
+
+       # Now rename the file to the real destination.
+       $doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/io/bufio.c b/io/bufio.c
new file mode 100644 (file)
index 0000000..92f2927
--- /dev/null
@@ -0,0 +1,205 @@
+/* bufio.c - buffered io access */
+/*
+ *  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/err.h>
+#include <grub/types.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/fs.h>
+#include <grub/bufio.h>
+
+#define GRUB_BUFIO_DEF_SIZE    8192
+#define GRUB_BUFIO_MAX_SIZE    1048576
+
+struct grub_bufio
+{
+  grub_file_t file;
+  grub_size_t block_size;
+  grub_size_t buffer_len;
+  char buffer[0];
+};
+typedef struct grub_bufio *grub_bufio_t;
+
+static struct grub_fs grub_bufio_fs;
+
+grub_file_t
+grub_bufio_open (grub_file_t io, int size)
+{
+  grub_file_t file;
+  grub_bufio_t bufio = 0;
+
+  file = (grub_file_t) grub_malloc (sizeof (*file));
+  if (! file)
+    return 0;
+
+  if (size == 0)
+    size = GRUB_BUFIO_DEF_SIZE;
+  else if (size > GRUB_BUFIO_MAX_SIZE)
+    size = GRUB_BUFIO_MAX_SIZE;
+
+  if ((size < 0) || ((unsigned) size > io->size))
+    size = ((io->size > GRUB_BUFIO_MAX_SIZE) ? GRUB_BUFIO_MAX_SIZE :
+            io->size);
+
+  bufio = grub_malloc (sizeof (struct grub_bufio) + size);
+  if (! bufio)
+    {
+      grub_free (file);
+      return 0;
+    }
+
+  bufio->file = io;
+  bufio->block_size = size;
+  bufio->buffer_len = 0;
+
+  file->device = io->device;
+  file->offset = 0;
+  file->size = io->size;
+  file->data = bufio;
+  file->read_hook = 0;
+  file->fs = &grub_bufio_fs;
+
+  return file;
+}
+
+grub_file_t
+grub_buffile_open (const char *name, int size)
+{
+  grub_file_t io, file;
+
+  io = grub_file_open (name);
+  if (! io)
+    return 0;
+
+  file = grub_bufio_open (io, size);
+  if (! file)
+    {
+      grub_file_close (io);
+      return 0;
+    }
+
+  return file;
+}
+
+static grub_ssize_t
+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;
+
+  if ((file->offset >= bufio->file->offset) &&
+      (file->offset < bufio->file->offset + bufio->buffer_len))
+    {
+      grub_size_t n;
+
+      pos = file->offset - bufio->file->offset;
+      n = bufio->buffer_len - pos;
+      if (n > len)
+        n = len;
+
+      grub_memcpy (buf, &bufio->buffer[pos], n);
+      len -= n;
+      if (! len)
+        return res;
+
+      buf += n;
+      bufio->file->offset += bufio->buffer_len;
+      pos = 0;
+    }
+  else
+    {
+      bufio->file->offset = grub_divmod64 (file->offset, bufio->block_size,
+                                           &pos);
+      bufio->file->offset *= bufio->block_size;
+    }
+
+  if (pos + len >= bufio->block_size)
+    {
+      if (pos)
+        {
+          grub_size_t n;
+
+          bufio->file->fs->read (bufio->file, bufio->buffer,
+                                 bufio->block_size);
+          if (grub_errno)
+            return -1;
+
+          n = bufio->block_size - pos;
+          grub_memcpy (buf, &bufio->buffer[pos], n);
+          len -= n;
+          buf += n;
+          bufio->file->offset += bufio->block_size;
+          pos = 0;
+        }
+
+      while (len >= bufio->block_size)
+        {
+          bufio->file->fs->read (bufio->file, buf, bufio->block_size);
+          if (grub_errno)
+            return -1;
+
+          len -= bufio->block_size;
+          buf += bufio->block_size;
+          bufio->file->offset += bufio->block_size;
+        }
+
+      if (! len)
+        {
+          bufio->buffer_len = 0;
+          return res;
+        }
+    }
+
+  bufio->buffer_len = bufio->file->size - bufio->file->offset;
+  if (bufio->buffer_len > bufio->block_size)
+    bufio->buffer_len = bufio->block_size;
+
+  bufio->file->fs->read (bufio->file, bufio->buffer, bufio->buffer_len);
+  if (grub_errno)
+    return -1;
+
+  grub_memcpy (buf, &bufio->buffer[pos], len);
+
+  return res;
+}
+
+static grub_err_t
+grub_bufio_close (grub_file_t file)
+{
+  grub_bufio_t bufio = file->data;
+
+  grub_file_close (bufio->file);
+  grub_free (bufio);
+
+  file->device = 0;
+
+  return grub_errno;
+}
+
+static struct grub_fs grub_bufio_fs =
+  {
+    .name = "bufio",
+    .dir = 0,
+    .open = 0,
+    .read = grub_bufio_read,
+    .close = grub_bufio_close,
+    .label = 0,
+    .next = 0
+  };
diff --git a/io/gzio.c b/io/gzio.c
new file mode 100644 (file)
index 0000000..0fada6c
--- /dev/null
+++ b/io/gzio.c
@@ -0,0 +1,1243 @@
+/* gzio.c - decompression support for gzip */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2005,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/>.
+ */
+
+/*
+ * Most of this file was originally the source file "inflate.c", written
+ * by Mark Adler.  It has been very heavily modified.  In particular, the
+ * original would run through the whole file at once, and this version can
+ * be stopped and restarted on any boundary during the decompression process.
+ *
+ * The license and header comments that file are included here.
+ */
+
+/* inflate.c -- Not copyrighted 1992 by Mark Adler
+   version c10p1, 10 January 1993 */
+
+/* You can do whatever you like with this source file, though I would
+   prefer that if you modify it and redistribute it that you include
+   comments to that effect with your name and the date.  Thank you.
+ */
+
+#include <grub/err.h>
+#include <grub/types.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/fs.h>
+#include <grub/file.h>
+#include <grub/gzio.h>
+
+/*
+ *  Window Size
+ *
+ *  This must be a power of two, and at least 32K for zip's deflate method
+ */
+
+#define WSIZE  0x8000
+
+
+#define INBUFSIZ  0x2000
+
+/* The state stored in filesystem-specific data.  */
+struct grub_gzio
+{
+  /* The underlying file object.  */
+  grub_file_t file;
+  /* The offset at which the data starts in the underlying file.  */
+  grub_off_t data_offset;
+  /* The type of current block.  */
+  int block_type;
+  /* The length of current block.  */
+  int block_len;
+  /* The flag of the last block.  */
+  int last_block;
+  /* The flag of codes.  */
+  int code_state;
+  /* The length of a copy.  */
+  unsigned inflate_n;
+  /* The index of a copy.  */
+  unsigned inflate_d;
+  /* The input buffer.  */
+  grub_uint8_t inbuf[INBUFSIZ];
+  int inbuf_d;
+  /* The bit buffer.  */
+  unsigned long bb;
+  /* The bits in the bit buffer.  */
+  unsigned bk;
+  /* The sliding window in uncompressed data.  */
+  grub_uint8_t slide[WSIZE];
+  /* Current position in the slide.  */
+  unsigned wp;
+  /* The literal/length code table.  */
+  struct huft *tl;
+  /* The distance code table.  */
+  struct huft *td;
+  /* The lookup bits for the literal/length code table. */
+  int bl;
+  /* The lookup bits for the distance code table.  */
+  int bd;
+  /* The original offset value.  */
+  grub_off_t saved_offset;
+};
+typedef struct grub_gzio *grub_gzio_t;
+
+/* Declare the filesystem structure for grub_gzio_open.  */
+static struct grub_fs grub_gzio_fs;
+
+/* Function prototypes */
+static void initialize_tables (grub_file_t file);
+
+/* Eat variable-length header fields.  */
+static int
+eat_field (grub_file_t file, int len)
+{
+  char ch = 1;
+  int not_retval = 1;
+
+  do
+    {
+      if (len >= 0)
+       {
+         if (! (len--))
+           break;
+       }
+      else
+       {
+         if (! ch)
+           break;
+       }
+    }
+  while ((not_retval = grub_file_read (file, &ch, 1)) == 1);
+
+  return ! not_retval;
+}
+
+
+/* Little-Endian defines for the 2-byte magic numbers for gzip files.  */
+#define GZIP_MAGIC     grub_le_to_cpu16 (0x8B1F)
+#define OLD_GZIP_MAGIC grub_le_to_cpu16 (0x9E1F)
+
+/* Compression methods (see algorithm.doc) */
+#define STORED      0
+#define COMPRESSED  1
+#define PACKED      2
+#define LZHED       3
+/* methods 4 to 7 reserved */
+#define DEFLATED    8
+#define MAX_METHODS 9
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01      /* bit 0 set: file probably ascii text */
+#define CONTINUATION 0x02      /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04      /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08      /* bit 3 set: original file name present */
+#define COMMENT      0x10      /* bit 4 set: file comment present */
+#define ENCRYPTED    0x20      /* bit 5 set: file is encrypted */
+#define RESERVED     0xC0      /* bit 6,7:   reserved */
+
+#define UNSUPPORTED_FLAGS      (CONTINUATION | ENCRYPTED | RESERVED)
+
+/* inflate block codes */
+#define INFLATE_STORED 0
+#define INFLATE_FIXED  1
+#define INFLATE_DYNAMIC        2
+
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+static int
+test_header (grub_file_t file)
+{
+  unsigned char buf[10] __attribute__ ((aligned));
+  grub_gzio_t gzio = file->data;
+
+  if (grub_file_tell (gzio->file) != 0)
+    grub_file_seek (gzio->file, 0);
+  
+  /*
+   *  This checks if the file is gzipped.  If a problem occurs here
+   *  (other than a real error with the disk) then we don't think it
+   *  is a compressed file, and simply mark it as such.
+   */
+  if (grub_file_read (gzio->file, (char *) buf, 10) != 10
+      || ((*((grub_uint16_t *) buf) != GZIP_MAGIC)
+         && (*((grub_uint16_t *) buf) != OLD_GZIP_MAGIC)))
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "no gzip magic found");
+      return 0;
+    }
+
+  /*
+   *  This does consistency checking on the header data.  If a
+   *  problem occurs from here on, then we have corrupt or otherwise
+   *  bad data, and the error should be reported to the user.
+   */
+  if (buf[2] != DEFLATED
+      || (buf[3] & UNSUPPORTED_FLAGS)
+      || ((buf[3] & EXTRA_FIELD)
+         && (grub_file_read (gzio->file, (char *) buf, 2) != 2
+             || eat_field (gzio->file,
+                           grub_le_to_cpu16 (*((grub_uint16_t *) buf)))))
+      || ((buf[3] & ORIG_NAME) && eat_field (gzio->file, -1))
+      || ((buf[3] & COMMENT) && eat_field (gzio->file, -1)))
+    {
+      grub_error (GRUB_ERR_BAD_GZIP_DATA, "unsupported gzip format");
+      return 0;
+    }
+
+  gzio->data_offset = grub_file_tell (gzio->file);
+  
+  grub_file_seek (gzio->file, grub_file_size (gzio->file) - 8);
+  
+  if (grub_file_read (gzio->file, (char *) buf, 8) != 8)
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported gzip format");
+      return 0;
+    }
+
+  /* FIXME: this does not handle files whose original size is over 4GB.
+     But how can we know the real original size?  */
+  file->size = grub_le_to_cpu32 (*((grub_uint32_t *) (buf + 4)));
+
+  initialize_tables (file);
+
+  return 1;
+}
+
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+   that have 16-bit pointers (e.g. PC's in the small or medium model).
+   Valid extra bits are 0..13.  e == 15 is EOB (end of block), e == 16
+   means that v is a literal, 16 < e < 32 means that v is a pointer to
+   the next table, which codes e - 16 bits, and lastly e == 99 indicates
+   an unused code.  If a code with e == 99 is looked up, this implies an
+   error in the data. */
+struct huft
+{
+  uch e;                       /* number of extra bits or operation */
+  uch b;                       /* number of bits in this code or subcode */
+  union
+    {
+      ush n;                   /* literal, length base, or distance base */
+      struct huft *t;          /* pointer to next level of table */
+    }
+  v;
+};
+
+
+/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
+   stream to find repeated byte strings.  This is implemented here as a
+   circular buffer.  The index is updated simply by incrementing and then
+   and'ing with 0x7fff (32K-1). */
+/* It is left to other modules to supply the 32K area.  It is assumed
+   to be usable as if it were declared "uch slide[32768];" or as just
+   "uch *slide;" and then malloc'ed in the latter case.  The definition
+   must be in unzip.h, included above. */
+
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+static unsigned bitorder[] =
+{                              /* Order of the bit length code lengths */
+  16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+static ush cplens[] =
+{                              /* Copy lengths for literal codes 257..285 */
+  3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+  35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+       /* note: see note #13 above about the 258 in this list. */
+static ush cplext[] =
+{                              /* Extra bits for literal codes 257..285 */
+  0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+  3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99};      /* 99==invalid */
+static ush cpdist[] =
+{                              /* Copy offsets for distance codes 0..29 */
+  1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+  257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+  8193, 12289, 16385, 24577};
+static ush cpdext[] =
+{                              /* Extra bits for distance codes */
+  0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+  7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+  12, 12, 13, 13};
+
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   is not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+
+static int lbits = 9;          /* bits in base literal/length lookup table */
+static int dbits = 6;          /* bits in base distance lookup table */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16                        /* maximum bit length of any code (16 for explode) */
+#define N_MAX 288              /* maximum number of codes in any set */
+
+
+/* Macros for inflate() bit peeking and grabbing.
+   The usage is:
+
+        NEEDBITS(j)
+        x = b & mask_bits[j];
+        DUMPBITS(j)
+
+   where NEEDBITS makes sure that b has at least j bits in it, and
+   DUMPBITS removes the bits from b.  The macros use the variable k
+   for the number of bits in b.  Normally, b and k are register
+   variables for speed, and are initialized at the beginning of a
+   routine that uses these macros from a global bit buffer and count.
+
+   If we assume that EOB will be the longest code, then we will never
+   ask for bits with NEEDBITS that are beyond the end of the stream.
+   So, NEEDBITS should not read any more bytes than are needed to
+   meet the request.  Then no bytes need to be "returned" to the buffer
+   at the end of the last block.
+
+   However, this assumption is not true for fixed blocks--the EOB code
+   is 7 bits, but the other literal/length codes can be 8 or 9 bits.
+   (The EOB code is shorter than other codes because fixed blocks are
+   generally short.  So, while a block always has an EOB, many other
+   literal/length codes have a significantly lower probability of
+   showing up at all.)  However, by making the first table have a
+   lookup of seven bits, the EOB code will be found in that first
+   lookup, and so will not require that too many bits be pulled from
+   the stream.
+ */
+
+static ush mask_bits[] =
+{
+  0x0000,
+  0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+  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 DUMPBITS(n) do {b>>=(n);k-=(n);} while (0)
+
+static int
+get_byte (grub_file_t file)
+{
+  grub_gzio_t gzio = file->data;
+  
+  if (grub_file_tell (gzio->file) == (grub_off_t) gzio->data_offset
+      || gzio->inbuf_d == INBUFSIZ)
+    {
+      gzio->inbuf_d = 0;
+      grub_file_read (gzio->file, (char *) gzio->inbuf, INBUFSIZ);
+    }
+
+  return gzio->inbuf[gzio->inbuf_d++];
+}
+
+/* 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);
+
+
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return zero on success, one if
+   the given code set is incomplete (the tables are still built in this
+   case), two if the input is invalid (all zero length codes or an
+   oversubscribed set of lengths), and three if not enough memory. */
+
+static int
+huft_build (unsigned *b,       /* code lengths in bits (all assumed <= BMAX) */
+           unsigned n,         /* number of codes (assumed <= N_MAX) */
+           unsigned s,         /* number of simple-valued codes (0..s-1) */
+           ush * d,            /* list of base values for non-simple codes */
+           ush * e,            /* list of extra bits for non-simple codes */
+           struct huft **t,    /* result: starting table */
+           int *m)             /* maximum lookup bits, returns actual */
+{
+  unsigned a;                  /* counter for codes of length k */
+  unsigned c[BMAX + 1];                /* bit length count table */
+  unsigned f;                  /* i repeats in table every f entries */
+  int g;                       /* maximum code length */
+  int h;                       /* table level */
+  register unsigned i;         /* counter, current code */
+  register unsigned j;         /* counter */
+  register int k;              /* number of bits in current code */
+  int l;                       /* bits per table (returned in m) */
+  register unsigned *p;                /* pointer into c[], b[], or v[] */
+  register struct huft *q;     /* points to current table */
+  struct huft r;               /* table entry for structure assignment */
+  struct huft *u[BMAX];                /* table stack */
+  unsigned v[N_MAX];           /* values in order of bit length */
+  register int w;              /* bits before this table == (l * h) */
+  unsigned x[BMAX + 1];                /* bit offsets, then code stack */
+  unsigned *xp;                        /* pointer into x */
+  int y;                       /* number of dummy codes added */
+  unsigned z;                  /* number of entries in current table */
+
+  /* Generate counts for each bit length */
+  grub_memset ((char *) c, 0, sizeof (c));
+  p = b;
+  i = n;
+  do
+    {
+      c[*p]++;                 /* assume all entries <= BMAX */
+      p++;                     /* Can't combine with above line (Solaris bug) */
+    }
+  while (--i);
+  if (c[0] == n)               /* null input--all zero length codes */
+    {
+      *t = (struct huft *) NULL;
+      *m = 0;
+      return 0;
+    }
+
+  /* Find minimum and maximum length, bound *m by those */
+  l = *m;
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                       /* minimum code length */
+  if ((unsigned) l < j)
+    l = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                       /* maximum code length */
+  if ((unsigned) l > i)
+    l = i;
+  *m = l;
+
+  /* Adjust last length count to fill out codes, if needed */
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return 2;                        /* bad input: more codes than bits */
+  if ((y -= c[i]) < 0)
+    return 2;
+  c[i] += y;
+
+  /* Generate starting offsets into the value table for each length */
+  x[1] = j = 0;
+  p = c + 1;
+  xp = x + 2;
+  while (--i)
+    {                          /* note that i == g from above */
+      *xp++ = (j += *p++);
+    }
+
+  /* Make a table of values in order of bit lengths */
+  p = b;
+  i = 0;
+  do
+    {
+      if ((j = *p++) != 0)
+       v[x[j]++] = i;
+    }
+  while (++i < n);
+
+  /* Generate the Huffman codes and for each, make the table entries */
+  x[0] = i = 0;                        /* first Huffman code is zero */
+  p = v;                       /* grab values in bit order */
+  h = -1;                      /* no tables yet--level -1 */
+  w = -l;                      /* bits decoded == (l * h) */
+  u[0] = (struct huft *) NULL; /* just to keep compilers happy */
+  q = (struct huft *) NULL;    /* ditto */
+  z = 0;                       /* ditto */
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+    {
+      a = c[k];
+      while (a--)
+       {
+         /* here i is the Huffman code of length k bits for value *p */
+         /* make tables up to required level */
+         while (k > w + l)
+           {
+             h++;
+             w += l;           /* previous table always l bits */
+
+             /* compute minimum size table less than or equal to l bits */
+             z = (z = (unsigned) (g - w)) > (unsigned) l ? (unsigned) l : z;   /* upper limit on table size */
+             if ((f = 1 << (j = k - w)) > a + 1)       /* try a k-w bit table */
+               {               /* too few codes for k-w bit table */
+                 f -= a + 1;   /* deduct codes from patterns left */
+                 xp = c + k;
+                 while (++j < z)       /* try smaller tables up to z bits */
+                   {
+                     if ((f <<= 1) <= *++xp)
+                       break;  /* enough codes to use up j bits */
+                     f -= *xp; /* else deduct codes from patterns */
+                   }
+               }
+             z = 1 << j;       /* table entries for j-bit table */
+
+             /* allocate and link in new table */
+             q = (struct huft *) grub_malloc ((z + 1) * sizeof (struct huft));
+             if (! q)
+               {
+                 if (h)
+                   huft_free (u[0]);
+                 return 3;
+               }
+
+             *t = q + 1;       /* link to list for huft_free() */
+             *(t = &(q->v.t)) = (struct huft *) NULL;
+             u[h] = ++q;       /* table starts after link */
+
+             /* connect to last table, if there is one */
+             if (h)
+               {
+                 x[h] = i;     /* save pattern for backing up */
+                 r.b = (uch) l;        /* bits to dump before this table */
+                 r.e = (uch) (16 + j);         /* bits in this table */
+                 r.v.t = q;    /* pointer to this table */
+                 j = i >> (w - l);     /* (get around Turbo C bug) */
+                 u[h - 1][j] = r;      /* connect to last table */
+               }
+           }
+
+         /* set up table entry in r */
+         r.b = (uch) (k - w);
+         if (p >= v + n)
+           r.e = 99;           /* out of values--invalid code */
+         else if (*p < s)
+           {
+             r.e = (uch) (*p < 256 ? 16 : 15);         /* 256 is end-of-block code */
+             r.v.n = (ush) (*p);       /* simple code is just the value */
+             p++;              /* one compiler does not like *p++ */
+           }
+         else
+           {
+             r.e = (uch) e[*p - s];    /* non-simple--look up in lists */
+             r.v.n = d[*p++ - s];
+           }
+
+         /* fill code-like entries with r */
+         f = 1 << (k - w);
+         for (j = i >> w; j < z; j += f)
+           q[j] = r;
+
+         /* backwards increment the k-bit code i */
+         for (j = 1 << (k - 1); i & j; j >>= 1)
+           i ^= j;
+         i ^= j;
+
+         /* backup over finished tables */
+         while ((i & ((1 << w) - 1)) != x[h])
+           {
+             h--;              /* don't need to update q */
+             w -= l;
+           }
+       }
+    }
+
+  /* Return true (1) if we were given an incomplete table */
+  return y != 0 && g != 1;
+}
+
+
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+   list of the tables it made, with the links in a dummy first entry of
+   each table.  */
+static int
+huft_free (struct huft *t)
+{
+  register struct huft *p, *q;
+
+
+  /* Go through linked list, freeing from the malloced (t[-1]) address. */
+  p = t;
+  while (p != (struct huft *) NULL)
+    {
+      q = (--p)->v.t;
+      grub_free ((char *) p);
+      p = q;
+    }
+  return 0;
+}
+
+
+/*
+ *  inflate (decompress) the codes in a deflated (compressed) block.
+ *  Return an error code or zero if it all goes ok.
+ */
+
+static int
+inflate_codes_in_window (grub_file_t file)
+{
+  register unsigned e;         /* table entry flag/number of extra bits */
+  unsigned n, d;               /* length and index for copy */
+  unsigned w;                  /* current window position */
+  struct huft *t;              /* pointer to table entry */
+  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;
+  n = gzio->inflate_n;
+  b = gzio->bb;                        /* initialize bit buffer */
+  k = gzio->bk;
+  w = gzio->wp;                        /* initialize window position */
+
+  /* inflate the coded data */
+  ml = mask_bits[gzio->bl];            /* precompute masks for speed */
+  md = mask_bits[gzio->bd];
+  for (;;)                     /* do until end of block */
+    {
+      if (! gzio->code_state)
+       {
+         NEEDBITS ((unsigned) gzio->bl);
+         if ((e = (t = gzio->tl + ((unsigned) b & ml))->e) > 16)
+           do
+             {
+               if (e == 99)
+                 {
+                   grub_error (GRUB_ERR_BAD_GZIP_DATA,
+                               "an unused code found");
+                   return 1;
+                 }
+               DUMPBITS (t->b);
+               e -= 16;
+               NEEDBITS (e);
+             }
+           while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
+         DUMPBITS (t->b);
+
+         if (e == 16)          /* then it's a literal */
+           {
+             gzio->slide[w++] = (uch) t->v.n;
+             if (w == WSIZE)
+               break;
+           }
+         else
+           /* it's an EOB or a length */
+           {
+             /* exit if end of block */
+             if (e == 15)
+               {
+                 gzio->block_len = 0;
+                 break;
+               }
+
+             /* get length of block to copy */
+             NEEDBITS (e);
+             n = t->v.n + ((unsigned) b & mask_bits[e]);
+             DUMPBITS (e);
+
+             /* decode distance of block to copy */
+             NEEDBITS ((unsigned) gzio->bd);
+             if ((e = (t = gzio->td + ((unsigned) b & md))->e) > 16)
+               do
+                 {
+                   if (e == 99)
+                     {
+                       grub_error (GRUB_ERR_BAD_GZIP_DATA,
+                                   "an unused code found");
+                       return 1;
+                     }
+                   DUMPBITS (t->b);
+                   e -= 16;
+                   NEEDBITS (e);
+                 }
+               while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e)
+                      > 16);
+             DUMPBITS (t->b);
+             NEEDBITS (e);
+             d = w - t->v.n - ((unsigned) b & mask_bits[e]);
+             DUMPBITS (e);
+             gzio->code_state++;
+           }
+       }
+
+      if (gzio->code_state)
+       {
+         /* do the copy */
+         do
+           {
+             n -= (e = (e = WSIZE - ((d &= WSIZE - 1) > w ? d : w)) > n ? n
+                   : e);
+
+             if (w - d >= e)
+               {
+                 grub_memmove (gzio->slide + w, gzio->slide + d, e);
+                 w += e;
+                 d += e;
+               }
+             else
+               /* purposefully use the overlap for extra copies here!! */
+               {
+                 while (e--)
+                   gzio->slide[w++] = gzio->slide[d++];
+               }
+
+             if (w == WSIZE)
+               break;
+           }
+         while (n);
+
+         if (! n)
+           gzio->code_state--;
+
+         /* did we break from the loop too soon? */
+         if (w == WSIZE)
+           break;
+       }
+    }
+
+  /* restore the globals from the locals */
+  gzio->inflate_d = d;
+  gzio->inflate_n = n;
+  gzio->wp = w;                        /* restore global window pointer */
+  gzio->bb = b;                        /* restore global bit buffer */
+  gzio->bk = k;
+
+  return ! gzio->block_len;
+}
+
+
+/* get header for an inflated type 0 (stored) block. */
+
+static void
+init_stored_block (grub_file_t file)
+{
+  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 */
+  k = gzio->bk;
+
+  /* go to byte boundary */
+  DUMPBITS (k & 7);
+
+  /* get the length and its complement */
+  NEEDBITS (16);
+  gzio->block_len = ((unsigned) b & 0xffff);
+  DUMPBITS (16);
+  NEEDBITS (16);
+  if (gzio->block_len != (int) ((~b) & 0xffff))
+    grub_error (GRUB_ERR_BAD_GZIP_DATA,
+               "the length of a stored block does not match");
+  DUMPBITS (16);
+
+  /* restore global variables */
+  gzio->bb = b;
+  gzio->bk = k;
+}
+
+
+/* get header for an inflated type 1 (fixed Huffman codes) block.  We should
+   either replace this with a custom decoder, or at least precompute the
+   Huffman tables. */
+
+static void
+init_fixed_block (grub_file_t file)
+{
+  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++)
+    l[i] = 8;
+  for (; i < 256; i++)
+    l[i] = 9;
+  for (; i < 280; i++)
+    l[i] = 7;
+  for (; i < 288; i++)         /* make a complete, but wrong code set */
+    l[i] = 8;
+  gzio->bl = 7;
+  if (huft_build (l, 288, 257, cplens, cplext, &gzio->tl, &gzio->bl) != 0)
+    {
+      if (grub_errno == GRUB_ERR_NONE)
+       grub_error (GRUB_ERR_BAD_GZIP_DATA,
+                   "failed in building a Huffman code table");
+      return;
+    }
+
+  /* set up distance table */
+  for (i = 0; i < 30; i++)     /* make an incomplete code set */
+    l[i] = 5;
+  gzio->bd = 5;
+  if (huft_build (l, 30, 0, cpdist, cpdext, &gzio->td, &gzio->bd) > 1)
+    {
+      if (grub_errno == GRUB_ERR_NONE)
+       grub_error (GRUB_ERR_BAD_GZIP_DATA,
+                   "failed in building a Huffman code table");
+      huft_free (gzio->tl);
+      gzio->tl = 0;
+      return;
+    }
+
+  /* indicate we're now working on a block */
+  gzio->code_state = 0;
+  gzio->block_len++;
+}
+
+
+/* get header for an inflated type 2 (dynamic Huffman codes) block. */
+
+static void
+init_dynamic_block (grub_file_t file)
+{
+  int i;                       /* temporary variables */
+  unsigned j;
+  unsigned l;                  /* last length */
+  unsigned m;                  /* mask for bit lengths table */
+  unsigned n;                  /* number of lengths to get */
+  unsigned nb;                 /* number of bit length codes */
+  unsigned nl;                 /* number of literal/length codes */
+  unsigned nd;                 /* number of distance codes */
+  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;
+  k = gzio->bk;
+
+  /* read in table lengths */
+  NEEDBITS (5);
+  nl = 257 + ((unsigned) b & 0x1f);    /* number of literal/length codes */
+  DUMPBITS (5);
+  NEEDBITS (5);
+  nd = 1 + ((unsigned) b & 0x1f);      /* number of distance codes */
+  DUMPBITS (5);
+  NEEDBITS (4);
+  nb = 4 + ((unsigned) b & 0xf);       /* number of bit length codes */
+  DUMPBITS (4);
+  if (nl > 286 || nd > 30)
+    {
+      grub_error (GRUB_ERR_BAD_GZIP_DATA, "too much data");
+      return;
+    }
+
+  /* read in bit-length-code lengths */
+  for (j = 0; j < nb; j++)
+    {
+      NEEDBITS (3);
+      ll[bitorder[j]] = (unsigned) b & 7;
+      DUMPBITS (3);
+    }
+  for (; j < 19; j++)
+    ll[bitorder[j]] = 0;
+
+  /* build decoding table for trees--single level, 7 bit lookup */
+  gzio->bl = 7;
+  if (huft_build (ll, 19, 19, NULL, NULL, &gzio->tl, &gzio->bl) != 0)
+    {
+      grub_error (GRUB_ERR_BAD_GZIP_DATA,
+                 "failed in building a Huffman code table");
+      return;
+    }
+
+  /* read in literal and distance code lengths */
+  n = nl + nd;
+  m = mask_bits[gzio->bl];
+  i = l = 0;
+  while ((unsigned) i < n)
+    {
+      NEEDBITS ((unsigned) gzio->bl);
+      j = (gzio->td = gzio->tl + ((unsigned) b & m))->b;
+      DUMPBITS (j);
+      j = gzio->td->v.n;
+      if (j < 16)              /* length of code in bits (0..15) */
+       ll[i++] = l = j;        /* save last length in l */
+      else if (j == 16)                /* repeat last length 3 to 6 times */
+       {
+         NEEDBITS (2);
+         j = 3 + ((unsigned) b & 3);
+         DUMPBITS (2);
+         if ((unsigned) i + j > n)
+           {
+             grub_error (GRUB_ERR_BAD_GZIP_DATA, "too many codes found");
+             return;
+           }
+         while (j--)
+           ll[i++] = l;
+       }
+      else if (j == 17)                /* 3 to 10 zero length codes */
+       {
+         NEEDBITS (3);
+         j = 3 + ((unsigned) b & 7);
+         DUMPBITS (3);
+         if ((unsigned) i + j > n)
+           {
+             grub_error (GRUB_ERR_BAD_GZIP_DATA, "too many codes found");
+             return;
+           }
+         while (j--)
+           ll[i++] = 0;
+         l = 0;
+       }
+      else
+       /* j == 18: 11 to 138 zero length codes */
+       {
+         NEEDBITS (7);
+         j = 11 + ((unsigned) b & 0x7f);
+         DUMPBITS (7);
+         if ((unsigned) i + j > n)
+           {
+             grub_error (GRUB_ERR_BAD_GZIP_DATA, "too many codes found");
+             return;
+           }
+         while (j--)
+           ll[i++] = 0;
+         l = 0;
+       }
+    }
+
+  /* free decoding table for trees */
+  huft_free (gzio->tl);
+  gzio->td = 0;
+  gzio->tl = 0;
+
+  /* restore the global bit buffer */
+  gzio->bb = b;
+  gzio->bk = k;
+
+  /* build the decoding tables for literal/length and distance codes */
+  gzio->bl = lbits;
+  if (huft_build (ll, nl, 257, cplens, cplext, &gzio->tl, &gzio->bl) != 0)
+    {
+      grub_error (GRUB_ERR_BAD_GZIP_DATA,
+                 "failed in building a Huffman code table");
+      return;
+    }
+  gzio->bd = dbits;
+  if (huft_build (ll + nl, nd, 0, cpdist, cpdext, &gzio->td, &gzio->bd) != 0)
+    {
+      huft_free (gzio->tl);
+      gzio->tl = 0;
+      grub_error (GRUB_ERR_BAD_GZIP_DATA,
+                 "failed in building a Huffman code table");
+      return;
+    }
+
+  /* indicate we're now working on a block */
+  gzio->code_state = 0;
+  gzio->block_len++;
+}
+
+
+static void
+get_new_block (grub_file_t file)
+{
+  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;
+  k = gzio->bk;
+
+  /* read in last block bit */
+  NEEDBITS (1);
+  gzio->last_block = (int) b & 1;
+  DUMPBITS (1);
+
+  /* read in block type */
+  NEEDBITS (2);
+  gzio->block_type = (unsigned) b & 3;
+  DUMPBITS (2);
+
+  /* restore the global bit buffer */
+  gzio->bb = b;
+  gzio->bk = k;
+
+  switch (gzio->block_type)
+    {
+    case INFLATE_STORED:
+      init_stored_block (file);
+      break;
+    case INFLATE_FIXED:
+      init_fixed_block (file);
+      break;
+    case INFLATE_DYNAMIC:
+      init_dynamic_block (file);
+      break;
+    default:
+      break;
+    }
+}
+
+
+static void
+inflate_window (grub_file_t file)
+{
+  grub_gzio_t gzio = file->data;
+  
+  /* initialize window */
+  gzio->wp = 0;
+
+  /*
+   *  Main decompression loop.
+   */
+
+  while (gzio->wp < WSIZE && grub_errno == GRUB_ERR_NONE)
+    {
+      if (! gzio->block_len)
+       {
+         if (gzio->last_block)
+           break;
+
+         get_new_block (file);
+       }
+
+      if (gzio->block_type > INFLATE_DYNAMIC)
+       grub_error (GRUB_ERR_BAD_GZIP_DATA,
+                   "unknown block type %d", gzio->block_type);
+
+      if (grub_errno != GRUB_ERR_NONE)
+       return;
+
+      /*
+       *  Expand stored block here.
+       */
+      if (gzio->block_type == INFLATE_STORED)
+       {
+         int w = gzio->wp;
+
+         /*
+          *  This is basically a glorified pass-through
+          */
+
+         while (gzio->block_len && w < WSIZE && grub_errno == GRUB_ERR_NONE)
+           {
+             gzio->slide[w++] = get_byte (file);
+             gzio->block_len--;
+           }
+
+         gzio->wp = w;
+
+         continue;
+       }
+
+      /*
+       *  Expand other kind of block.
+       */
+
+      if (inflate_codes_in_window (file))
+       {
+         huft_free (gzio->tl);
+         huft_free (gzio->td);
+         gzio->tl = 0;
+         gzio->td = 0;
+       }
+    }
+
+  gzio->saved_offset += WSIZE;
+
+  /* XXX do CRC calculation here! */
+}
+
+
+static void
+initialize_tables (grub_file_t file)
+{
+  grub_gzio_t gzio = file->data;
+  
+  gzio->saved_offset = 0;
+  grub_file_seek (gzio->file, gzio->data_offset);
+
+  /* Initialize the bit buffer.  */
+  gzio->bk = 0;
+  gzio->bb = 0;
+
+  /* Reset partial decompression code.  */
+  gzio->last_block = 0;
+  gzio->block_len = 0;
+
+  /* Reset memory allocation stuff.  */
+  huft_free (gzio->tl);
+  huft_free (gzio->td);
+}
+
+
+/* Open a new decompressing object on the top of IO. If TRANSPARENT is true,
+   even if IO does not contain data compressed by gzip, return a valid file
+   object. Note that this function won't close IO, even if an error occurs.  */
+grub_file_t
+grub_gzio_open (grub_file_t io, int transparent)
+{
+  grub_file_t file;
+  grub_gzio_t gzio = 0;
+  
+  file = (grub_file_t) grub_malloc (sizeof (*file));
+  if (! file)
+    return 0;
+
+  gzio = grub_malloc (sizeof (*gzio));
+  if (! gzio)
+    {
+      grub_free (file);
+      return 0;
+    }
+  
+  grub_memset (gzio, 0, sizeof (*gzio));
+  gzio->file = io;
+  
+  file->device = io->device;
+  file->offset = 0;
+  file->data = gzio;
+  file->read_hook = 0;
+  file->fs = &grub_gzio_fs;
+
+  if (! test_header (file))
+    {
+      grub_free (gzio);
+      grub_free (file);
+      grub_file_seek (io, 0);
+
+      if (grub_errno == GRUB_ERR_BAD_FILE_TYPE && transparent)
+       {
+         grub_errno = GRUB_ERR_NONE;
+         return io;
+       }
+      else
+       return 0;
+    }
+  
+  return file;
+}
+
+/* This is similar to grub_gzio_open, but takes a file name as an argument.  */
+grub_file_t
+grub_gzfile_open (const char *name, int transparent)
+{
+  grub_file_t io, file;
+  
+  io = grub_file_open (name);
+  if (! io)
+    return 0;
+
+  file = grub_gzio_open (io, transparent);
+  if (! file)
+    {
+      grub_file_close (io);
+      return 0;
+    }
+
+  return file;
+}
+
+static grub_ssize_t
+grub_gzio_read (grub_file_t file, 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);
+
+  /*
+   *  This loop operates upon uncompressed data only.  The only
+   *  special thing it does is to make sure the decompression
+   *  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);
+
+      srcaddr = (char *) ((offset & (WSIZE - 1)) + gzio->slide);
+      size = gzio->saved_offset - offset;
+      if (size > len)
+       size = len;
+
+      grub_memmove (buf, srcaddr, size);
+
+      buf += size;
+      len -= size;
+      ret += size;
+      offset += size;
+    }
+
+  if (grub_errno != GRUB_ERR_NONE)
+    ret = -1;
+
+  return ret;
+}
+
+/* Release everything, including the underlying file object.  */
+static grub_err_t
+grub_gzio_close (grub_file_t file)
+{
+  grub_gzio_t gzio = file->data;
+  
+  grub_file_close (gzio->file);
+  huft_free (gzio->tl);
+  huft_free (gzio->td);
+  grub_free (gzio);
+
+  /* No need to close the same device twice.  */
+  file->device = 0;
+
+  return grub_errno;
+}
+
+\f
+
+static struct grub_fs grub_gzio_fs =
+  {
+    .name = "gzio",
+    .dir = 0,
+    .open = 0,
+    .read = grub_gzio_read,
+    .close = grub_gzio_close,
+    .label = 0,
+    .next = 0
+  };
diff --git a/kern/device.c b/kern/device.c
new file mode 100644 (file)
index 0000000..60f25c1
--- /dev/null
@@ -0,0 +1,136 @@
+/* device.c - device manager */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,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/>.
+ */
+
+#include <grub/device.h>
+#include <grub/disk.h>
+#include <grub/net.h>
+#include <grub/fs.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/partition.h>
+
+grub_device_t
+grub_device_open (const char *name)
+{
+  grub_disk_t disk = 0;
+  grub_device_t dev = 0;
+
+  if (! name)
+    {
+      name = grub_env_get ("root");
+      if (*name == '\0')
+       {
+         grub_error (GRUB_ERR_BAD_DEVICE, "no device is set");
+         goto fail;
+       }
+    }
+    
+  dev = grub_malloc (sizeof (*dev));
+  if (! dev)
+    goto fail;
+  
+  /* Try to open a disk.  */
+  disk = grub_disk_open (name);
+  if (! disk)
+    goto fail;
+
+  dev->disk = disk;
+  dev->net = 0;        /* FIXME */
+
+  return dev;
+
+ fail:
+  if (disk)
+    grub_disk_close (disk);
+  
+  grub_free (dev);
+
+  return 0;
+}
+
+grub_err_t
+grub_device_close (grub_device_t device)
+{
+  if (device->disk)
+    grub_disk_close (device->disk);
+
+  grub_free (device);
+
+  return grub_errno;
+}
+
+int
+grub_device_iterate (int (*hook) (const char *name))
+{
+  auto int iterate_disk (const char *disk_name);
+  auto int iterate_partition (grub_disk_t disk,
+                             const grub_partition_t partition);
+  
+  int iterate_disk (const char *disk_name)
+    {
+      grub_device_t dev;
+
+      if (hook (disk_name))
+       return 1;
+      
+      dev = grub_device_open (disk_name);
+      if (! dev)
+       return 0;
+      
+      if (dev->disk && dev->disk->has_partitions)
+       if (grub_partition_iterate (dev->disk, iterate_partition))
+         {
+           grub_device_close (dev);
+           return 1;
+         }
+
+      grub_device_close (dev);
+      return 0;
+    }
+  
+  int iterate_partition (grub_disk_t disk, const grub_partition_t partition)
+    {
+      char *partition_name;
+      char *device_name;
+      int ret;
+      
+      partition_name = grub_partition_get_name (partition);
+      if (! partition_name)
+       return 1;
+      
+      device_name = grub_malloc (grub_strlen (disk->name) + 1
+                                + grub_strlen (partition_name) + 1);
+      if (! device_name)
+       {
+         grub_free (partition_name);
+         return 1;
+       }
+
+      grub_sprintf (device_name, "%s,%s", disk->name, partition_name);
+      grub_free (partition_name);
+
+      ret = hook (device_name);
+      grub_free (device_name);
+      return ret;
+    }
+
+  /* Only disk devices are supported at the moment.  */
+  return grub_disk_dev_iterate (iterate_disk);
+}
diff --git a/kern/disk.c b/kern/disk.c
new file mode 100644 (file)
index 0000000..4ee03e0
--- /dev/null
@@ -0,0 +1,576 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,2006,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/>.
+ */
+
+#include <grub/disk.h>
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/partition.h>
+#include <grub/misc.h>
+#include <grub/time.h>
+#include <grub/file.h>
+
+#define        GRUB_CACHE_TIMEOUT      2
+
+/* The last time the disk was used.  */
+static grub_uint64_t grub_last_time = 0;
+
+
+/* Disk cache.  */
+struct grub_disk_cache
+{
+  unsigned long dev_id;
+  unsigned long disk_id;
+  grub_disk_addr_t sector;
+  char *data;
+  int lock;
+};
+
+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
+static unsigned long grub_disk_cache_hits;
+static unsigned long grub_disk_cache_misses;
+
+void
+grub_disk_cache_get_performance (unsigned long *hits, unsigned long *misses)
+{
+  *hits = grub_disk_cache_hits;
+  *misses = grub_disk_cache_misses;
+}
+#endif
+
+static unsigned
+grub_disk_cache_get_index (unsigned long dev_id, unsigned long disk_id,
+                          grub_disk_addr_t sector)
+{
+  return ((dev_id * 524287UL + disk_id * 2606459UL
+          + ((unsigned) (sector >> GRUB_DISK_CACHE_BITS)))
+         % GRUB_DISK_CACHE_NUM);
+}
+
+static void
+grub_disk_cache_invalidate (unsigned long dev_id, unsigned long disk_id,
+                           grub_disk_addr_t sector)
+{
+  unsigned index;
+  struct grub_disk_cache *cache;
+
+  sector &= ~(GRUB_DISK_CACHE_SIZE - 1);
+  index = grub_disk_cache_get_index (dev_id, disk_id, sector);
+  cache = grub_disk_cache_table + index;
+
+  if (cache->dev_id == dev_id && cache->disk_id == disk_id
+      && cache->sector == sector && cache->data)
+    {
+      cache->lock = 1;
+      grub_free (cache->data);
+      cache->data = 0;
+      cache->lock = 0;
+    }
+}
+
+void
+grub_disk_cache_invalidate_all (void)
+{
+  unsigned i;
+
+  for (i = 0; i < GRUB_DISK_CACHE_NUM; i++)
+    {
+      struct grub_disk_cache *cache = grub_disk_cache_table + i;
+
+      if (cache->data && ! cache->lock)
+       {
+         grub_free (cache->data);
+         cache->data = 0;
+       }
+    }
+}
+
+static char *
+grub_disk_cache_fetch (unsigned long dev_id, unsigned long disk_id,
+                      grub_disk_addr_t sector)
+{
+  struct grub_disk_cache *cache;
+  unsigned index;
+
+  index = grub_disk_cache_get_index (dev_id, disk_id, sector);
+  cache = grub_disk_cache_table + index;
+
+  if (cache->dev_id == dev_id && cache->disk_id == disk_id
+      && cache->sector == sector)
+    {
+      cache->lock = 1;
+#if 0
+      grub_disk_cache_hits++;
+#endif
+      return cache->data;
+    }
+
+#if 0
+  grub_disk_cache_misses++;
+#endif
+  
+  return 0;
+}
+
+static void
+grub_disk_cache_unlock (unsigned long dev_id, unsigned long disk_id,
+                       grub_disk_addr_t sector)
+{
+  struct grub_disk_cache *cache;
+  unsigned index;
+
+  index = grub_disk_cache_get_index (dev_id, disk_id, sector);
+  cache = grub_disk_cache_table + index;
+
+  if (cache->dev_id == dev_id && cache->disk_id == disk_id
+      && cache->sector == sector)
+    cache->lock = 0;
+}
+
+static grub_err_t
+grub_disk_cache_store (unsigned long dev_id, unsigned long disk_id,
+                      grub_disk_addr_t sector, const char *data)
+{
+  unsigned index;
+  struct grub_disk_cache *cache;
+  
+  grub_disk_cache_invalidate (dev_id, disk_id, sector);
+  
+  index = grub_disk_cache_get_index (dev_id, disk_id, sector);
+  cache = grub_disk_cache_table + index;
+  
+  cache->data = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS);
+  if (! cache->data)
+    return grub_errno;
+  
+  grub_memcpy (cache->data, data,
+              GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS);
+  cache->dev_id = dev_id;
+  cache->disk_id = disk_id;
+  cache->sector = sector;
+
+  return GRUB_ERR_NONE;
+}
+
+\f
+
+static grub_disk_dev_t grub_disk_dev_list;
+
+void
+grub_disk_dev_register (grub_disk_dev_t dev)
+{
+  dev->next = grub_disk_dev_list;
+  grub_disk_dev_list = dev;
+}
+
+void
+grub_disk_dev_unregister (grub_disk_dev_t dev)
+{
+  grub_disk_dev_t *p, q;
+  
+  for (p = &grub_disk_dev_list, q = *p; q; p = &(q->next), q = q->next)
+    if (q == dev)
+      {
+        *p = q->next;
+       break;
+      }
+}
+
+int
+grub_disk_dev_iterate (int (*hook) (const char *name))
+{
+  grub_disk_dev_t p;
+
+  for (p = grub_disk_dev_list; p; p = p->next)
+    if (p->iterate && (p->iterate) (hook))
+      return 1;
+
+  return 0;
+}
+
+grub_disk_t
+grub_disk_open (const char *name)
+{
+  char *p;
+  grub_disk_t disk;
+  grub_disk_dev_t dev;
+  char *raw = (char *) name;
+  grub_uint64_t current_time;
+
+  grub_dprintf ("disk", "Opening `%s'...\n", name);
+
+  disk = (grub_disk_t) grub_malloc (sizeof (*disk));
+  if (! disk)
+    return 0;
+
+  disk->dev = 0;
+  disk->read_hook = 0;
+  disk->partition = 0;
+  disk->data = 0;
+  disk->name = grub_strdup (name);
+  if (! disk->name)
+    goto fail;
+  
+  p = grub_strchr (name, ',');
+  if (p)
+    {
+      grub_size_t len = p - name;
+      
+      raw = grub_malloc (len + 1);
+      if (! raw)
+       goto fail;
+
+      grub_memcpy (raw, name, len);
+      raw[len] = '\0';
+    }
+
+  for (dev = grub_disk_dev_list; dev; dev = dev->next)
+    {
+      if ((dev->open) (raw, disk) == GRUB_ERR_NONE)
+       break;
+      else if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE)
+       grub_errno = GRUB_ERR_NONE;
+      else
+       goto fail;
+    }
+
+  if (! dev)
+    {
+      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such disk");
+      goto fail;
+    }
+
+  if (p && ! disk->has_partitions)
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, "no partition on this disk");
+      goto fail;
+    }
+  
+  disk->dev = dev;
+
+  if (p)
+    {
+      disk->partition = grub_partition_probe (disk, p + 1);
+      if (! disk->partition)
+       {
+         grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such partition");
+         goto fail;
+       }
+    }
+
+  /* The cache will be invalidated about 2 seconds after a device was
+     closed.  */
+  current_time = grub_get_time_ms ();
+
+  if (current_time > (grub_last_time
+                     + GRUB_CACHE_TIMEOUT * 1000))
+    grub_disk_cache_invalidate_all ();
+  
+  grub_last_time = current_time;
+  
+ fail:
+  
+  if (raw && raw != name)
+    grub_free (raw);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_error_push ();
+      grub_dprintf ("disk", "Opening `%s' failed.\n", name);
+      grub_error_pop ();
+
+      grub_disk_close (disk);
+      return 0;
+    }
+
+  return disk;
+}
+
+void
+grub_disk_close (grub_disk_t disk)
+{
+  grub_dprintf ("disk", "Closing `%s'.\n", disk->name);
+
+  if (disk->dev && disk->dev->close)
+    (disk->dev->close) (disk);
+
+  /* Reset the timer.  */
+  grub_last_time = grub_get_time_ms ();
+
+  grub_free (disk->partition);
+  grub_free ((void *) disk->name);
+  grub_free (disk);
+}
+
+/* This function performs three tasks:
+   - Make sectors disk relative from partition relative.
+   - Normalize offset to be less than the sector size.
+   - Verify that the range is inside the partition.  */
+static grub_err_t
+grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector,
+                      grub_off_t *offset, grub_size_t size)
+{
+  *sector += *offset >> GRUB_DISK_SECTOR_BITS;
+  *offset &= GRUB_DISK_SECTOR_SIZE - 1;
+  
+  if (disk->partition)
+    {
+      grub_disk_addr_t start;
+      grub_uint64_t len;
+
+      start = grub_partition_get_start (disk->partition);
+      len = grub_partition_get_len (disk->partition);
+
+      if (*sector >= len
+         || len - *sector < ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)
+                             >> GRUB_DISK_SECTOR_BITS))
+       return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of partition");
+
+      *sector += start;
+    }
+
+  if (disk->total_sectors <= *sector
+      || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)
+         >> GRUB_DISK_SECTOR_BITS) > disk->total_sectors - *sector)
+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of disk");
+
+  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, char *buf)
+{
+  char *tmp_buf;
+  unsigned real_offset;
+
+  grub_dprintf ("disk", "Reading `%s'...\n", disk->name);
+  
+  /* First of all, check if the region is within the disk.  */
+  if (grub_disk_adjust_range (disk, &sector, &offset, size) != GRUB_ERR_NONE)
+    {
+      grub_error_push ();
+      grub_dprintf ("disk", "Read out of range: sector 0x%llx (%s).\n",
+                   (unsigned long long) sector, grub_errmsg);
+      grub_error_pop ();
+      return grub_errno;
+    }
+
+  real_offset = offset;
+  
+  /* 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)
+    {
+      char *data;
+      grub_disk_addr_t start_sector;
+      grub_size_t len;
+      grub_size_t pos;
+
+      /* 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);
+      if (len > size)
+       len = size;
+
+      /* Fetch the cache.  */
+      data = grub_disk_cache_fetch (disk->dev->id, disk->id, start_sector);
+      if (data)
+       {
+         /* Just copy it!  */
+         grub_memcpy (buf, data + pos + real_offset, len);
+         grub_disk_cache_unlock (disk->dev->id, disk->id, start_sector);
+       }
+      else
+       {
+         /* Otherwise read data from the disk actually.  */
+         if ((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 + 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)
+                 {
+                   (disk->read_hook) (sector, real_offset,
+                                      ((size > GRUB_DISK_SECTOR_SIZE)
+                                       ? GRUB_DISK_SECTOR_SIZE
+                                       : size));
+                   sector++;
+                   size -= GRUB_DISK_SECTOR_SIZE - 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);
+       }
+
+      /* Call the read hook, if any.  */
+      if (disk->read_hook)
+       {
+         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;
+             
+             s++;
+             l -= GRUB_DISK_SECTOR_SIZE - real_offset;
+             real_offset = 0;
+           }
+       }
+      
+      sector = start_sector + GRUB_DISK_CACHE_SIZE;
+      buf += len;
+      size -= len;
+      real_offset = 0;
+    }
+  
+ finish:
+  
+  grub_free (tmp_buf);
+  
+  return grub_errno;
+}
+
+grub_err_t
+grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
+                grub_off_t offset, grub_size_t size, const char *buf)
+{
+  unsigned real_offset;
+  
+  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;
+  
+  while (size)
+    {
+      if (real_offset != 0 || (size < GRUB_DISK_SECTOR_SIZE && size != 0))
+       {
+         char tmp_buf[GRUB_DISK_SECTOR_SIZE];
+         grub_size_t len;
+         
+         if (grub_disk_read (disk, sector, 0, GRUB_DISK_SECTOR_SIZE, tmp_buf)
+             != GRUB_ERR_NONE)
+           goto finish;
+
+         len = GRUB_DISK_SECTOR_SIZE - real_offset;
+         if (len > size)
+           len = size;
+         
+         grub_memcpy (tmp_buf + real_offset, buf, len);
+
+         grub_disk_cache_invalidate (disk->dev->id, disk->id, sector);
+
+         if ((disk->dev->write) (disk, sector, 1, tmp_buf) != GRUB_ERR_NONE)
+           goto finish;
+
+         sector++;
+         buf += len;
+         size -= len;
+         real_offset = 0;
+       }
+      else
+       {
+         grub_size_t len;
+         grub_size_t n;
+
+         len = size & ~(GRUB_DISK_SECTOR_SIZE - 1);
+         n = size >> GRUB_DISK_SECTOR_BITS;
+         
+         if ((disk->dev->write) (disk, sector, n, buf) != GRUB_ERR_NONE)
+           goto finish;
+
+         while (n--)
+           grub_disk_cache_invalidate (disk->dev->id, disk->id, sector++);
+
+         buf += len;
+         size -= len;
+       }
+    }
+
+ finish:
+
+  return grub_errno;
+}
+
+grub_uint64_t 
+grub_disk_get_size (grub_disk_t disk)
+{
+  if (disk->partition)
+    return grub_partition_get_len (disk->partition);
+  else
+    return disk->total_sectors;
+}
diff --git a/kern/dl.c b/kern/dl.c
new file mode 100644 (file)
index 0000000..bc21403
--- /dev/null
+++ b/kern/dl.c
@@ -0,0 +1,725 @@
+/* dl.c - loadable module support */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,2005,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/>.
+ */
+
+#include <config.h>
+#include <grub/elf.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/types.h>
+#include <grub/symbol.h>
+#include <grub/file.h>
+#include <grub/env.h>
+#include <grub/cache.h>
+
+#if GRUB_CPU_SIZEOF_VOID_P == 4
+
+typedef Elf32_Word Elf_Word;
+typedef Elf32_Addr Elf_Addr;
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Shdr Elf_Shdr;
+typedef Elf32_Sym Elf_Sym;
+
+# define ELF_ST_BIND(val)      ELF32_ST_BIND (val)
+# define ELF_ST_TYPE(val)      ELF32_ST_TYPE (val)
+
+#elif GRUB_CPU_SIZEOF_VOID_P == 8
+
+typedef Elf64_Word Elf_Word;
+typedef Elf64_Addr Elf_Addr;
+typedef Elf64_Ehdr Elf_Ehdr;
+typedef Elf64_Shdr Elf_Shdr;
+typedef Elf64_Sym Elf_Sym;
+
+# define ELF_ST_BIND(val)      ELF64_ST_BIND (val)
+# define ELF_ST_TYPE(val)      ELF64_ST_TYPE (val)
+
+#endif
+
+\f
+
+struct grub_dl_list
+{
+  struct grub_dl_list *next;
+  grub_dl_t mod;
+};
+typedef struct grub_dl_list *grub_dl_list_t;
+
+static grub_dl_list_t grub_dl_head;
+
+static grub_err_t
+grub_dl_add (grub_dl_t mod)
+{
+  grub_dl_list_t l;
+
+  if (grub_dl_get (mod->name))
+    return grub_error (GRUB_ERR_BAD_MODULE,
+                      "`%s' is already loaded", mod->name);
+  
+  l = (grub_dl_list_t) grub_malloc (sizeof (*l));
+  if (! l)
+    return grub_errno;
+
+  l->mod = mod;
+  l->next = grub_dl_head;
+  grub_dl_head = l;
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_dl_remove (grub_dl_t mod)
+{
+  grub_dl_list_t *p, q;
+
+  for (p = &grub_dl_head, q = *p; q; p = &q->next, q = *p)
+    if (q->mod == mod)
+      {
+       *p = q->next;
+       grub_free (q);
+       return;
+      }
+}
+
+grub_dl_t
+grub_dl_get (const char *name)
+{
+  grub_dl_list_t l;
+
+  for (l = grub_dl_head; l; l = l->next)
+    if (grub_strcmp (name, l->mod->name) == 0)
+      return l->mod;
+
+  return 0;
+}
+
+void
+grub_dl_iterate (int (*hook) (grub_dl_t mod))
+{
+  grub_dl_list_t l;
+
+  for (l = grub_dl_head; l; l = l->next)
+    if (hook (l->mod))
+      break;
+}
+
+\f
+
+struct grub_symbol
+{
+  struct grub_symbol *next;
+  const char *name;
+  void *addr;
+  grub_dl_t mod;       /* The module to which this symbol belongs.  */
+};
+typedef struct grub_symbol *grub_symbol_t;
+
+/* The size of the symbol table.  */
+#define GRUB_SYMTAB_SIZE       509
+
+/* The symbol table (using an open-hash).  */
+static struct grub_symbol *grub_symtab[GRUB_SYMTAB_SIZE];
+
+/* Simple hash function.  */
+static unsigned
+grub_symbol_hash (const char *s)
+{
+  unsigned key = 0;
+
+  while (*s)
+    key = key * 65599 + *s++;
+
+  return (key + (key >> 5)) % GRUB_SYMTAB_SIZE;
+}
+
+/* Resolve the symbol name NAME and return the address.
+   Return NULL, if not found.  */
+void *
+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 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_symbol_t sym;
+  unsigned k;
+  
+  sym = (grub_symbol_t) grub_malloc (sizeof (*sym));
+  if (! sym)
+    return grub_errno;
+
+  if (mod)
+    {
+      sym->name = grub_strdup (name);
+      if (! sym->name)
+       {
+         grub_free (sym);
+         return grub_errno;
+       }
+    }
+  else
+    sym->name = name;
+  
+  sym->addr = addr;
+  sym->mod = mod;
+  
+  k = grub_symbol_hash (name);
+  sym->next = grub_symtab[k];
+  grub_symtab[k] = sym;
+
+  return GRUB_ERR_NONE;
+}
+
+/* Unregister all the symbols defined in the module MOD.  */
+static void
+grub_dl_unregister_symbols (grub_dl_t mod)
+{
+  unsigned i;
+
+  if (! mod)
+    grub_fatal ("core symbols cannot be unregistered");
+  
+  for (i = 0; i < GRUB_SYMTAB_SIZE; i++)
+    {
+      grub_symbol_t sym, *p, q;
+
+      for (p = &grub_symtab[i], sym = *p; sym; sym = q)
+       {
+         q = sym->next;
+         if (sym->mod == mod)
+           {
+             *p = q;
+             grub_free ((void *) sym->name);
+             grub_free (sym);
+           }
+         else
+           p = &sym->next;
+       }
+    }
+}
+
+/* Return the address of a section whose index is N.  */
+static void *
+grub_dl_get_section_addr (grub_dl_t mod, unsigned n)
+{
+  grub_dl_segment_t seg;
+
+  for (seg = mod->segment; seg; seg = seg->next)
+    if (seg->section == n)
+      return seg->addr;
+
+  return 0;
+}
+
+/* Check if EHDR is a valid ELF header.  */
+grub_err_t
+grub_dl_check_header (void *ehdr, grub_size_t size)
+{
+  Elf_Ehdr *e = ehdr;
+
+  /* Check the header size.  */
+  if (size < sizeof (Elf_Ehdr))
+    return grub_error (GRUB_ERR_BAD_OS, "ELF header smaller than expected");
+
+  /* Check the magic numbers.  */
+  if (grub_arch_dl_check_header (ehdr)
+      || e->e_ident[EI_MAG0] != ELFMAG0
+      || e->e_ident[EI_MAG1] != ELFMAG1
+      || e->e_ident[EI_MAG2] != ELFMAG2
+      || e->e_ident[EI_MAG3] != ELFMAG3
+      || e->e_ident[EI_VERSION] != EV_CURRENT
+      || e->e_version != EV_CURRENT)
+    return grub_error (GRUB_ERR_BAD_OS, "invalid arch independent ELF magic");
+
+  return GRUB_ERR_NONE;
+}
+
+/* Load all segments from memory specified by E.  */
+static grub_err_t
+grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
+{
+  unsigned i;
+  Elf_Shdr *s;
+  
+  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_flags & SHF_ALLOC)
+       {
+         grub_dl_segment_t seg;
+
+         seg = (grub_dl_segment_t) grub_malloc (sizeof (*seg));
+         if (! seg)
+           return grub_errno;
+         
+         if (s->sh_size)
+           {
+             void *addr;
+
+             addr = grub_memalign (s->sh_addralign, s->sh_size);
+             if (! addr)
+               {
+                 grub_free (seg);
+                 return grub_errno;
+               }
+
+             switch (s->sh_type)
+               {
+               case SHT_PROGBITS:
+                 grub_memcpy (addr, (char *) e + s->sh_offset, s->sh_size);
+                 break;
+               case SHT_NOBITS:
+                 grub_memset (addr, 0, s->sh_size);
+                 break;
+               }
+
+             seg->addr = addr;
+           }
+         else
+           seg->addr = 0;
+
+         seg->size = s->sh_size;
+         seg->section = i;
+         seg->next = mod->segment;
+         mod->segment = seg;
+       }
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
+{
+  unsigned i;
+  Elf_Shdr *s;
+  Elf_Sym *sym;
+  const char *str;
+  Elf_Word size, 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_SYMTAB)
+      break;
+
+  if (i == e->e_shnum)
+    return grub_error (GRUB_ERR_BAD_MODULE, "no symbol table");
+
+  sym = (Elf_Sym *) ((char *) e + s->sh_offset);
+  size = s->sh_size;
+  entsize = s->sh_entsize;
+  
+  s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shentsize * s->sh_link);
+  str = (char *) e + s->sh_offset;
+
+  for (i = 0;
+       i < size / entsize;
+       i++, sym = (Elf_Sym *) ((char *) sym + entsize))
+    {
+      unsigned char type = ELF_ST_TYPE (sym->st_info);
+      unsigned char bind = ELF_ST_BIND (sym->st_info);
+      const char *name = str + sym->st_name;
+      
+      switch (type)
+       {
+       case STT_NOTYPE:
+         /* 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)
+               return grub_error (GRUB_ERR_BAD_MODULE,
+                                  "the symbol `%s' not found", name);
+           }
+         else
+           sym->st_value = 0;
+         break;
+
+       case STT_OBJECT:
+         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))
+             return grub_errno;
+         break;
+
+       case STT_FUNC:
+         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))
+             return grub_errno;
+         
+         if (grub_strcmp (name, "grub_mod_init") == 0)
+           mod->init = (void (*) (grub_dl_t)) sym->st_value;
+         else if (grub_strcmp (name, "grub_mod_fini") == 0)
+           mod->fini = (void (*) (void)) sym->st_value;
+         break;
+
+       case STT_SECTION:
+         sym->st_value = (Elf_Addr) grub_dl_get_section_addr (mod,
+                                                              sym->st_shndx);
+         break;
+
+       case STT_FILE:
+         sym->st_value = 0;
+         break;
+
+       default:
+         return grub_error (GRUB_ERR_BAD_MODULE,
+                            "unknown symbol type `%d'", (int) type);
+       }
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_dl_call_init (grub_dl_t mod)
+{
+  if (mod->init)
+    (mod->init) (mod);
+}
+
+static grub_err_t
+grub_dl_resolve_name (grub_dl_t mod, 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, ".modname") == 0)
+      {
+       mod->name = grub_strdup ((char *) e + s->sh_offset);
+       if (! mod->name)
+         return grub_errno;
+       break;
+      }
+
+  if (i == e->e_shnum)
+    return grub_error (GRUB_ERR_BAD_MODULE, "no module name found");
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_dl_resolve_dependencies (grub_dl_t mod, 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, ".moddeps") == 0)
+      {
+       const char *name = (char *) e + s->sh_offset;
+       const char *max = name + s->sh_size;
+
+       while ((name < max) && (*name))
+         {
+           grub_dl_t m;
+           grub_dl_dep_t dep;
+           
+           m = grub_dl_load (name);
+           if (! m)
+             return grub_errno;
+
+           grub_dl_ref (m);
+           
+           dep = (grub_dl_dep_t) grub_malloc (sizeof (*dep));
+           if (! dep)
+             return grub_errno;
+           
+           dep->mod = m;
+           dep->next = mod->dep;
+           mod->dep = dep;
+           
+           name += grub_strlen (name) + 1;
+         }
+      }
+
+  return GRUB_ERR_NONE;
+}
+
+int
+grub_dl_ref (grub_dl_t mod)
+{
+  grub_dl_dep_t dep;
+
+  for (dep = mod->dep; dep; dep = dep->next)
+    grub_dl_ref (dep->mod);
+  
+  return ++mod->ref_count;
+}
+
+int
+grub_dl_unref (grub_dl_t mod)
+{
+  grub_dl_dep_t dep;
+
+  for (dep = mod->dep; dep; dep = dep->next)
+    grub_dl_unref (dep->mod);
+  
+  return --mod->ref_count;
+}
+
+static void
+grub_dl_flush_cache (grub_dl_t mod)
+{
+  grub_dl_segment_t seg;
+
+  for (seg = mod->segment; seg; seg = seg->next) {
+    if (seg->size) {
+      grub_dprintf ("modules", "flushing 0x%lx bytes at %p\n",
+                   (unsigned long) seg->size, seg->addr);
+      grub_arch_sync_caches (seg->addr, seg->size);
+    }
+  }
+}
+
+/* Load a module from core memory.  */
+grub_dl_t
+grub_dl_load_core (void *addr, grub_size_t size)
+{
+  Elf_Ehdr *e;
+  grub_dl_t mod;
+
+  grub_dprintf ("modules", "module at %p, size 0x%lx\n", addr,
+               (unsigned long) size);
+  e = addr;
+  if (grub_dl_check_header (e, size))
+    return 0;
+
+  if (e->e_type != ET_REL)
+    {
+      grub_error (GRUB_ERR_BAD_MODULE, "invalid ELF file type");
+      return 0;
+    }
+
+  /* Make sure that every section is within the core.  */
+  if (size < e->e_shoff + e->e_shentsize * e->e_shnum)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "ELF sections outside core");
+      return 0;
+    }
+
+  mod = (grub_dl_t) grub_malloc (sizeof (*mod));
+  if (! mod)
+    return 0;
+
+  mod->name = 0;
+  mod->ref_count = 1;
+  mod->dep = 0;
+  mod->segment = 0;
+  mod->init = 0;
+  mod->fini = 0;
+
+  grub_dprintf ("modules", "relocating to %p\n", mod);
+  if (grub_dl_resolve_name (mod, e)
+      || grub_dl_resolve_dependencies (mod, e)
+      || grub_dl_load_segments (mod, e)
+      || grub_dl_resolve_symbols (mod, e)
+      || grub_arch_dl_relocate_symbols (mod, e))
+    {
+      mod->fini = 0;
+      grub_dl_unload (mod);
+      return 0;
+    }
+
+  grub_dl_flush_cache (mod);
+
+  grub_dprintf ("modules", "module name: %s\n", mod->name);
+  grub_dprintf ("modules", "init function: %p\n", mod->init);
+  grub_dl_call_init (mod);
+
+  if (grub_dl_add (mod))
+    {
+      grub_dl_unload (mod);
+      return 0;
+    }
+
+  return mod;
+}
+
+/* Load a module from the file FILENAME.  */
+grub_dl_t
+grub_dl_load_file (const char *filename)
+{
+  grub_file_t file;
+  grub_ssize_t size;
+  void *core = 0;
+  grub_dl_t mod = 0;
+  
+  file = grub_file_open (filename);
+  if (! file)
+    return 0;
+
+  size = grub_file_size (file);
+  core = grub_malloc (size);
+  if (! core)
+    goto failed;
+
+  if (grub_file_read (file, core, size) != (int) size)
+    goto failed;
+
+  mod = grub_dl_load_core (core, size);
+  if (! mod)
+    goto failed;
+  
+  mod->ref_count = 0;
+
+ failed:
+  grub_file_close (file);
+  grub_free (core);
+
+  return mod;
+}
+
+/* Load a module using a symbolic name.  */
+grub_dl_t
+grub_dl_load (const char *name)
+{
+  char *filename;
+  grub_dl_t mod;
+  char *grub_dl_dir = grub_env_get ("prefix");
+
+  mod = grub_dl_get (name);
+  if (mod)
+    return mod;
+  
+  if (! grub_dl_dir) {
+    grub_error (GRUB_ERR_FILE_NOT_FOUND, "\"prefix\" is not set");
+    return 0;
+  }
+
+  filename = (char *) grub_malloc (grub_strlen (grub_dl_dir) + 1
+                                  + grub_strlen (name) + 4 + 1);
+  if (! filename)
+    return 0;
+  
+  grub_sprintf (filename, "%s/%s.mod", grub_dl_dir, name);
+  mod = grub_dl_load_file (filename);
+  grub_free (filename);
+
+  if (! mod)
+    return 0;
+  
+  if (grub_strcmp (mod->name, name) != 0)
+    grub_error (GRUB_ERR_BAD_MODULE, "mismatched names");
+  
+  return mod;
+}
+
+/* Unload the module MOD.  */
+int
+grub_dl_unload (grub_dl_t mod)
+{
+  grub_dl_dep_t dep, depn;
+  grub_dl_segment_t seg, segn;
+
+  if (mod->ref_count > 0)
+    return 0;
+
+  if (mod->fini)
+    (mod->fini) ();
+  
+  grub_dl_remove (mod);
+  grub_dl_unregister_symbols (mod);
+  
+  for (dep = mod->dep; dep; dep = depn)
+    {
+      depn = dep->next;
+      
+      if (! grub_dl_unref (dep->mod))
+       grub_dl_unload (dep->mod);
+      
+      grub_free (dep);
+    }
+
+  for (seg = mod->segment; seg; seg = segn)
+    {
+      segn = seg->next;
+      grub_free (seg->addr);
+      grub_free (seg);
+    }
+  
+  grub_free (mod->name);
+  grub_free (mod);
+  return 1;
+}
+
+/* Unload unneeded modules.  */
+void
+grub_dl_unload_unneeded (void)
+{
+  /* Because grub_dl_remove modifies the list of modules, this
+     implementation is tricky.  */
+  grub_dl_list_t p = grub_dl_head;
+  
+  while (p)
+    {
+      if (grub_dl_unload (p->mod))
+       {
+         p = grub_dl_head;
+         continue;
+       }
+
+      p = p->next;
+    }
+}
+
+/* Unload all modules.  */
+void
+grub_dl_unload_all (void)
+{
+  while (grub_dl_head)
+    {
+      grub_dl_list_t p;
+      
+      grub_dl_unload_unneeded ();
+
+      /* Force to decrement the ref count. This will purge pre-loaded
+        modules and manually inserted modules.  */
+      for (p = grub_dl_head; p; p = p->next)
+       p->mod->ref_count--;
+    }
+}
diff --git a/kern/efi/efi.c b/kern/efi/efi.c
new file mode 100644 (file)
index 0000000..9c9a400
--- /dev/null
@@ -0,0 +1,736 @@
+/* efi.c - generic EFI support */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/console_control.h>
+#include <grub/efi/pe32.h>
+#include <grub/machine/time.h>
+#include <grub/term.h>
+#include <grub/kernel.h>
+#include <grub/mm.h>
+
+/* The handle of GRUB itself. Filled in by the startup code.  */
+grub_efi_handle_t grub_efi_image_handle;
+
+/* The pointer to a system table. Filled in by the startup code.  */
+grub_efi_system_table_t *grub_efi_system_table;
+
+static grub_efi_guid_t console_control_guid = GRUB_EFI_CONSOLE_CONTROL_GUID;
+static grub_efi_guid_t loaded_image_guid = GRUB_EFI_LOADED_IMAGE_GUID;
+static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID;
+
+void *
+grub_efi_locate_protocol (grub_efi_guid_t *protocol, void *registration)
+{
+  void *interface;
+  grub_efi_status_t status;
+  
+  status = efi_call_3 (grub_efi_system_table->boot_services->locate_protocol,
+                       protocol, registration, &interface);
+  if (status != GRUB_EFI_SUCCESS)
+    return 0;
+  
+  return interface;
+}
+
+/* Return the array of handles which meet the requirement. If successful,
+   the number of handles is stored in NUM_HANDLES. The array is allocated
+   from the heap.  */
+grub_efi_handle_t *
+grub_efi_locate_handle (grub_efi_locate_search_type_t search_type,
+                       grub_efi_guid_t *protocol,
+                       void *search_key,
+                       grub_efi_uintn_t *num_handles)
+{
+  grub_efi_boot_services_t *b;
+  grub_efi_status_t status;
+  grub_efi_handle_t *buffer;
+  grub_efi_uintn_t buffer_size = 8 * sizeof (grub_efi_handle_t);
+  
+  buffer = grub_malloc (buffer_size);
+  if (! buffer)
+    return 0;
+  
+  b = grub_efi_system_table->boot_services;
+  status = efi_call_5 (b->locate_handle, search_type, protocol, search_key,
+                            &buffer_size, buffer);
+  if (status == GRUB_EFI_BUFFER_TOO_SMALL)
+    {
+      grub_free (buffer);
+      buffer = grub_malloc (buffer_size);
+      if (! buffer)
+       return 0;
+      
+      status = efi_call_5 (b->locate_handle, search_type, protocol, search_key,
+                                &buffer_size, buffer);
+    }
+
+  if (status != GRUB_EFI_SUCCESS)
+    {
+      grub_free (buffer);
+      return 0;
+    }
+
+  *num_handles = buffer_size / sizeof (grub_efi_handle_t);
+  return buffer;
+}
+
+void *
+grub_efi_open_protocol (grub_efi_handle_t handle,
+                       grub_efi_guid_t *protocol,
+                       grub_efi_uint32_t attributes)
+{
+  grub_efi_boot_services_t *b;
+  grub_efi_status_t status;
+  void *interface;
+  
+  b = grub_efi_system_table->boot_services;
+  status = efi_call_6 (b->open_protocol, handle,
+                      protocol,
+                      &interface,
+                      grub_efi_image_handle,
+                      0,
+                      attributes);
+  if (status != GRUB_EFI_SUCCESS)
+    return 0;
+
+  return interface;
+}
+
+int
+grub_efi_set_text_mode (int on)
+{
+  grub_efi_console_control_protocol_t *c;
+  grub_efi_screen_mode_t mode, new_mode;
+
+  c = grub_efi_locate_protocol (&console_control_guid, 0);
+  if (! c)
+    /* No console control protocol instance available, assume it is
+       already in text mode. */
+    return 1;
+  
+  if (efi_call_4 (c->get_mode, c, &mode, 0, 0) != GRUB_EFI_SUCCESS)
+    return 0;
+
+  new_mode = on ? GRUB_EFI_SCREEN_TEXT : GRUB_EFI_SCREEN_GRAPHICS;
+  if (mode != new_mode)
+    if (efi_call_2 (c->set_mode, c, new_mode) != GRUB_EFI_SUCCESS)
+      return 0;
+
+  return 1;
+}
+
+void
+grub_efi_stall (grub_efi_uintn_t microseconds)
+{
+  efi_call_1 (grub_efi_system_table->boot_services->stall, microseconds);
+}
+
+grub_efi_loaded_image_t *
+grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
+{
+  return grub_efi_open_protocol (image_handle,
+                                &loaded_image_guid,
+                                GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+}
+
+void
+grub_exit (void)
+{
+  grub_efi_fini ();
+  efi_call_4 (grub_efi_system_table->boot_services->exit,
+              grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0);
+}
+
+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);
+}
+
+void
+grub_halt (void)
+{
+  grub_efi_fini ();
+  efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
+              GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL);
+}
+
+int
+grub_efi_exit_boot_services (grub_efi_uintn_t map_key)
+{
+  grub_efi_boot_services_t *b;
+  grub_efi_status_t status;
+  
+  b = grub_efi_system_table->boot_services;
+  status = efi_call_2 (b->exit_boot_services, grub_efi_image_handle, map_key);
+  return status == GRUB_EFI_SUCCESS;
+}
+
+grub_uint32_t
+grub_get_rtc (void)
+{
+  grub_efi_time_t time;
+  grub_efi_runtime_services_t *r;
+
+  r = grub_efi_system_table->runtime_services;
+  if (efi_call_2 (r->get_time, &time, 0) != GRUB_EFI_SUCCESS)
+    /* What is possible in this case?  */
+    return 0;
+
+  return (((time.minute * 60 + time.second) * 1000
+          + time.nanosecond / 1000000)
+         * GRUB_TICKS_PER_SECOND / 1000);
+}
+
+/* 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_loaded_image_t *image;
+  struct grub_pe32_header *header;
+  struct grub_pe32_coff_header *coff_header;
+  struct grub_pe32_section_table *sections;
+  struct grub_pe32_section_table *section;
+  struct grub_module_info *info;
+  grub_uint16_t i;
+  
+  image = grub_efi_get_loaded_image (grub_efi_image_handle);
+  if (! image)
+    return 0;
+
+  header = image->image_base;
+  coff_header = &(header->coff_header);
+  sections
+    = (struct grub_pe32_section_table *) ((char *) coff_header
+                                         + sizeof (*coff_header)
+                                         + coff_header->optional_header_size);
+
+  for (i = 0, section = sections;
+       i < coff_header->num_sections;
+       i++, section++)
+    {
+      if (grub_strcmp (section->name, "mods") == 0)
+       break;
+    }
+
+  if (i == coff_header->num_sections)
+    return 0;
+
+  info = (struct grub_module_info *) ((char *) image->image_base
+                                     + section->virtual_address);
+  if (info->magic != GRUB_MODULE_MAGIC)
+    return 0;
+
+  return (grub_addr_t) info;
+}
+
+char *
+grub_efi_get_filename (grub_efi_device_path_t *dp)
+{
+  char *name = 0;
+  
+  while (1)
+    {
+      grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
+      grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
+
+      if (type == GRUB_EFI_END_DEVICE_PATH_TYPE)
+       break;
+      else if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
+              && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
+       {
+         grub_efi_file_path_device_path_t *fp;
+         grub_efi_uint16_t len;
+         char *p;
+         grub_size_t size;
+
+         if (name)
+           {
+             size = grub_strlen (name);
+             name[size] = '/';
+             size++;
+           }
+         else
+           size = 0;
+         
+         len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
+                / sizeof (grub_efi_char16_t));
+         p = grub_realloc (name, size + len * 4 + 1);
+         if (! p)
+           {
+             grub_free (name);
+             return 0;
+           }
+
+         name = p;
+         fp = (grub_efi_file_path_device_path_t *) dp;
+         *grub_utf16_to_utf8 ((grub_uint8_t *) name + size,
+                              fp->path_name, len) = '\0';
+       }
+
+      dp = GRUB_EFI_NEXT_DEVICE_PATH (dp);
+    }
+
+  if (name)
+    {
+      /* EFI breaks paths with backslashes.  */
+      char *p;
+
+      for (p = name; *p; p++)
+       if (*p == '\\')
+         *p = '/';
+    }
+
+  return name;
+}
+
+grub_efi_device_path_t *
+grub_efi_get_device_path (grub_efi_handle_t handle)
+{
+  return grub_efi_open_protocol (handle, &device_path_guid,
+                                GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+}
+
+/* Print the chain of Device Path nodes. This is mainly for debugging. */
+void
+grub_efi_print_device_path (grub_efi_device_path_t *dp)
+{
+  while (1)
+    {
+      grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
+      grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
+      grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
+
+      switch (type)
+       {
+       case GRUB_EFI_END_DEVICE_PATH_TYPE:
+         switch (subtype)
+           {
+           case GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE:
+             grub_printf ("/EndEntire\n");
+             //grub_putchar ('\n');
+             break;
+           case GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE:
+             grub_printf ("/EndThis\n");
+             //grub_putchar ('\n');
+             break;
+           default:
+             grub_printf ("/EndUnknown(%x)\n", (unsigned) subtype);
+             break;
+           }
+         break;
+
+       case GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE:
+         switch (subtype)
+           {
+           case GRUB_EFI_PCI_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_pci_device_path_t pci;
+               grub_memcpy (&pci, dp, len);
+               grub_printf ("/PCI(%x,%x)",
+                            (unsigned) pci.function, (unsigned) pci.device);
+             }
+             break;
+           case GRUB_EFI_PCCARD_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_pccard_device_path_t pccard;
+               grub_memcpy (&pccard, dp, len);
+               grub_printf ("/PCCARD(%x)",
+                            (unsigned) pccard.function);
+             }
+             break;
+           case GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_memory_mapped_device_path_t mmapped;
+               grub_memcpy (&mmapped, dp, len);
+               grub_printf ("/MMap(%x,%llx,%llx)",
+                            (unsigned) mmapped.memory_type,
+                            (unsigned long long) mmapped.start_address,
+                            (unsigned long long) mmapped.end_address);
+             }
+             break;
+           case GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_vendor_device_path_t vendor;
+               grub_memcpy (&vendor, dp, sizeof (vendor));
+               grub_printf ("/Vendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
+                            (unsigned) vendor.vendor_guid.data1,
+                            (unsigned) vendor.vendor_guid.data2,
+                            (unsigned) vendor.vendor_guid.data3,
+                            (unsigned) vendor.vendor_guid.data4[0],
+                            (unsigned) vendor.vendor_guid.data4[1],
+                            (unsigned) vendor.vendor_guid.data4[2],
+                            (unsigned) vendor.vendor_guid.data4[3],
+                            (unsigned) vendor.vendor_guid.data4[4],
+                            (unsigned) vendor.vendor_guid.data4[5],
+                            (unsigned) vendor.vendor_guid.data4[6],
+                            (unsigned) vendor.vendor_guid.data4[7]);
+             }
+             break;
+           case GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_controller_device_path_t controller;
+               grub_memcpy (&controller, dp, len);
+               grub_printf ("/Ctrl(%x)",
+                            (unsigned) controller.controller_number);
+             }
+             break;
+           default:
+             grub_printf ("/UnknownHW(%x)", (unsigned) subtype);
+             break;
+           }
+         break;
+
+       case GRUB_EFI_ACPI_DEVICE_PATH_TYPE:
+         switch (subtype)
+           {
+           case GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_acpi_device_path_t acpi;
+               grub_memcpy (&acpi, dp, len);
+               grub_printf ("/ACPI(%x,%x)",
+                            (unsigned) acpi.hid,
+                            (unsigned) acpi.uid);
+             }
+             break;
+           case GRUB_EFI_EXPANDED_ACPI_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_expanded_acpi_device_path_t eacpi;
+               grub_memcpy (&eacpi, dp, sizeof (eacpi));
+               grub_printf ("/ACPI(");
+               
+               if (GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp)[0] == '\0')
+                 grub_printf ("%x,", (unsigned) eacpi.hid);
+               else
+                 grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp));
+               
+               if (GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp)[0] == '\0')
+                 grub_printf ("%x,", (unsigned) eacpi.uid);
+               else
+                 grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp));
+               
+               if (GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp)[0] == '\0')
+                 grub_printf ("%x)", (unsigned) eacpi.cid);
+               else
+                 grub_printf ("%s)", GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp));
+             }
+             break;
+           default:
+             grub_printf ("/UnknownACPI(%x)", (unsigned) subtype);
+             break;
+           }
+         break;
+
+       case GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE:
+         switch (subtype)
+           {
+           case GRUB_EFI_ATAPI_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_atapi_device_path_t atapi;
+               grub_memcpy (&atapi, dp, len);
+               grub_printf ("/ATAPI(%x,%x,%x)",
+                            (unsigned) atapi.primary_secondary,
+                            (unsigned) atapi.slave_master,
+                            (unsigned) atapi.lun);
+             }
+             break;
+           case GRUB_EFI_SCSI_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_scsi_device_path_t scsi;
+               grub_memcpy (&scsi, dp, len);
+               grub_printf ("/SCSI(%x,%x)",
+                            (unsigned) scsi.pun,
+                            (unsigned) scsi.lun);
+             }
+             break;
+           case GRUB_EFI_FIBRE_CHANNEL_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_fibre_channel_device_path_t fc;
+               grub_memcpy (&fc, dp, len);
+               grub_printf ("/FibreChannel(%llx,%llx)",
+                            (unsigned long long) fc.wwn,
+                            (unsigned long long) fc.lun);
+             }
+             break;
+           case GRUB_EFI_1394_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_1394_device_path_t firewire;
+               grub_memcpy (&firewire, dp, len);
+               grub_printf ("/1394(%llx)", (unsigned long long) firewire.guid);
+             }
+             break;
+           case GRUB_EFI_USB_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_usb_device_path_t usb;
+               grub_memcpy (&usb, dp, len);
+               grub_printf ("/USB(%x,%x)",
+                            (unsigned) usb.parent_port_number,
+                            (unsigned) usb.interface);
+             }
+             break;
+           case GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_usb_class_device_path_t usb_class;
+               grub_memcpy (&usb_class, dp, len);
+               grub_printf ("/USBClass(%x,%x,%x,%x,%x)",
+                            (unsigned) usb_class.vendor_id,
+                            (unsigned) usb_class.product_id,
+                            (unsigned) usb_class.device_class,
+                            (unsigned) usb_class.device_subclass,
+                            (unsigned) usb_class.device_protocol);
+             }
+             break;
+           case GRUB_EFI_I2O_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_i2o_device_path_t i2o;
+               grub_memcpy (&i2o, dp, len);
+               grub_printf ("/I2O(%x)", (unsigned) i2o.tid);
+             }
+             break;
+           case GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_mac_address_device_path_t mac;
+               grub_memcpy (&mac, dp, len);
+               grub_printf ("/MacAddr(%02x:%02x:%02x:%02x:%02x:%02x,%x)",
+                            (unsigned) mac.mac_address[0],
+                            (unsigned) mac.mac_address[1],
+                            (unsigned) mac.mac_address[2],
+                            (unsigned) mac.mac_address[3],
+                            (unsigned) mac.mac_address[4],
+                            (unsigned) mac.mac_address[5],
+                            (unsigned) mac.if_type);
+             }
+             break;
+           case GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_ipv4_device_path_t ipv4;
+               grub_memcpy (&ipv4, dp, len);
+               grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x)",
+                            (unsigned) ipv4.local_ip_address[0],
+                            (unsigned) ipv4.local_ip_address[1],
+                            (unsigned) ipv4.local_ip_address[2],
+                            (unsigned) ipv4.local_ip_address[3],
+                            (unsigned) ipv4.remote_ip_address[0],
+                            (unsigned) ipv4.remote_ip_address[1],
+                            (unsigned) ipv4.remote_ip_address[2],
+                            (unsigned) ipv4.remote_ip_address[3],
+                            (unsigned) ipv4.local_port,
+                            (unsigned) ipv4.remote_port,
+                            (unsigned) ipv4.protocol,
+                            (unsigned) ipv4.static_ip_address);
+             }
+             break;
+           case GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_ipv6_device_path_t ipv6;
+               grub_memcpy (&ipv6, dp, len);
+               grub_printf ("/IPv6(%x:%x:%x:%x:%x:%x:%x:%x,%x:%x:%x:%x:%x:%x:%x:%x,%u,%u,%x,%x)",
+                            (unsigned) ipv6.local_ip_address[0],
+                            (unsigned) ipv6.local_ip_address[1],
+                            (unsigned) ipv6.local_ip_address[2],
+                            (unsigned) ipv6.local_ip_address[3],
+                            (unsigned) ipv6.local_ip_address[4],
+                            (unsigned) ipv6.local_ip_address[5],
+                            (unsigned) ipv6.local_ip_address[6],
+                            (unsigned) ipv6.local_ip_address[7],
+                            (unsigned) ipv6.remote_ip_address[0],
+                            (unsigned) ipv6.remote_ip_address[1],
+                            (unsigned) ipv6.remote_ip_address[2],
+                            (unsigned) ipv6.remote_ip_address[3],
+                            (unsigned) ipv6.remote_ip_address[4],
+                            (unsigned) ipv6.remote_ip_address[5],
+                            (unsigned) ipv6.remote_ip_address[6],
+                            (unsigned) ipv6.remote_ip_address[7],
+                            (unsigned) ipv6.local_port,
+                            (unsigned) ipv6.remote_port,
+                            (unsigned) ipv6.protocol,
+                            (unsigned) ipv6.static_ip_address);
+             }
+             break;
+           case GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_infiniband_device_path_t ib;
+               grub_memcpy (&ib, dp, len);
+               grub_printf ("/InfiniBand(%x,%llx,%llx,%llx)",
+                            (unsigned) ib.port_gid[0], /* XXX */
+                            (unsigned long long) ib.remote_id,
+                            (unsigned long long) ib.target_port_id,
+                            (unsigned long long) ib.device_id);
+             }
+             break;
+           case GRUB_EFI_UART_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_uart_device_path_t uart;
+               grub_memcpy (&uart, dp, len);
+               grub_printf ("/UART(%llu,%u,%x,%x)",
+                            (unsigned long long) uart.baud_rate,
+                            uart.data_bits,
+                            uart.parity,
+                            uart.stop_bits);
+             }
+             break;
+           case GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_vendor_messaging_device_path_t vendor;
+               grub_memcpy (&vendor, dp, sizeof (vendor));
+               grub_printf ("/Vendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
+                            (unsigned) vendor.vendor_guid.data1,
+                            (unsigned) vendor.vendor_guid.data2,
+                            (unsigned) vendor.vendor_guid.data3,
+                            (unsigned) vendor.vendor_guid.data4[0],
+                            (unsigned) vendor.vendor_guid.data4[1],
+                            (unsigned) vendor.vendor_guid.data4[2],
+                            (unsigned) vendor.vendor_guid.data4[3],
+                            (unsigned) vendor.vendor_guid.data4[4],
+                            (unsigned) vendor.vendor_guid.data4[5],
+                            (unsigned) vendor.vendor_guid.data4[6],
+                            (unsigned) vendor.vendor_guid.data4[7]);
+             }
+             break;
+           default:
+             grub_printf ("/UnknownMessaging(%x)", (unsigned) subtype);
+             break;
+           }
+         break;
+
+       case GRUB_EFI_MEDIA_DEVICE_PATH_TYPE:
+         switch (subtype)
+           {
+           case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_hard_drive_device_path_t hd;
+               grub_memcpy (&hd, dp, len);
+               grub_printf ("/HD(%u,%llx,%llx,%02x%02x%02x%02x%02x%02x%02x%02x,%x,%x)",
+                            hd.partition_number,
+                            (unsigned long long) hd.partition_start,
+                            (unsigned long long) hd.partition_size,
+                            (unsigned) hd.partition_signature[0],
+                            (unsigned) hd.partition_signature[1],
+                            (unsigned) hd.partition_signature[2],
+                            (unsigned) hd.partition_signature[3],
+                            (unsigned) hd.partition_signature[4],
+                            (unsigned) hd.partition_signature[5],
+                            (unsigned) hd.partition_signature[6],
+                            (unsigned) hd.partition_signature[7],
+                            (unsigned) hd.mbr_type,
+                            (unsigned) hd.signature_type);
+             }
+             break;
+           case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_cdrom_device_path_t cd;
+               grub_memcpy (&cd, dp, len);
+               grub_printf ("/CD(%u,%llx,%llx)",
+                            cd.boot_entry,
+                            (unsigned long long) cd.partition_start,
+                            (unsigned long long) cd.partition_size);
+             }
+             break;
+           case GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_vendor_media_device_path_t vendor;
+               grub_memcpy (&vendor, dp, sizeof (vendor));
+               grub_printf ("/Vendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
+                            (unsigned) vendor.vendor_guid.data1,
+                            (unsigned) vendor.vendor_guid.data2,
+                            (unsigned) vendor.vendor_guid.data3,
+                            (unsigned) vendor.vendor_guid.data4[0],
+                            (unsigned) vendor.vendor_guid.data4[1],
+                            (unsigned) vendor.vendor_guid.data4[2],
+                            (unsigned) vendor.vendor_guid.data4[3],
+                            (unsigned) vendor.vendor_guid.data4[4],
+                            (unsigned) vendor.vendor_guid.data4[5],
+                            (unsigned) vendor.vendor_guid.data4[6],
+                            (unsigned) vendor.vendor_guid.data4[7]);
+             }
+             break;
+           case GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_file_path_device_path_t *fp;
+               grub_uint8_t buf[(len - 4) * 2 + 1];
+               fp = (grub_efi_file_path_device_path_t *) dp;
+               *grub_utf16_to_utf8 (buf, fp->path_name,
+                                    (len - 4) / sizeof (grub_efi_char16_t))
+                 = '\0';
+               grub_printf ("/File(%s)", buf);
+             }
+             break;
+           case GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_protocol_device_path_t proto;
+               grub_memcpy (&proto, dp, sizeof (proto));
+               grub_printf ("/Protocol(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
+                            (unsigned) proto.guid.data1,
+                            (unsigned) proto.guid.data2,
+                            (unsigned) proto.guid.data3,
+                            (unsigned) proto.guid.data4[0],
+                            (unsigned) proto.guid.data4[1],
+                            (unsigned) proto.guid.data4[2],
+                            (unsigned) proto.guid.data4[3],
+                            (unsigned) proto.guid.data4[4],
+                            (unsigned) proto.guid.data4[5],
+                            (unsigned) proto.guid.data4[6],
+                            (unsigned) proto.guid.data4[7]);
+             }
+             break;
+           default:
+             grub_printf ("/UnknownMedia(%x)", (unsigned) subtype);
+             break;
+           }
+         break;
+
+       case GRUB_EFI_BIOS_DEVICE_PATH_TYPE:
+         switch (subtype)
+           {
+           case GRUB_EFI_BIOS_DEVICE_PATH_SUBTYPE:
+             {
+               grub_efi_bios_device_path_t bios;
+               grub_memcpy (&bios, dp, sizeof (bios));
+               grub_printf ("/BIOS(%x,%x,%s)",
+                            (unsigned) bios.device_type,
+                            (unsigned) bios.status_flags,
+                            (char *) (dp + 1));
+             }
+             break;
+           default:
+             grub_printf ("/UnknownBIOS(%x)", (unsigned) subtype);
+             break;
+           }
+         break;
+
+       default:
+         grub_printf ("/UnknownType(%x,%x)\n",
+                      (unsigned) type,
+                      (unsigned) subtype);
+         return;
+         break;
+       }
+      
+      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
+       break;
+
+      dp = (grub_efi_device_path_t *) ((char *) dp + len);
+    }
+}
diff --git a/kern/efi/init.c b/kern/efi/init.c
new file mode 100644 (file)
index 0000000..115a087
--- /dev/null
@@ -0,0 +1,87 @@
+/* init.c - generic EFI initialization and finalization */
+/*
+ *  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/>.
+ */
+
+#include <grub/efi/efi.h>
+#include <grub/efi/console.h>
+#include <grub/efi/disk.h>
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/mm.h>
+#include <grub/machine/kernel.h>
+
+void
+grub_efi_init (void)
+{
+  /* First of all, initialize the console so that GRUB can display
+     messages.  */
+  grub_console_init ();
+
+  /* Initialize the memory management system.  */
+  grub_efi_mm_init ();
+
+  grub_efidisk_init ();
+}
+
+void
+grub_efi_set_prefix (void)
+{
+  grub_efi_loaded_image_t *image;
+  
+  image = grub_efi_get_loaded_image (grub_efi_image_handle);
+  if (image)
+    {
+      char *device;
+      char *file;
+
+      device = grub_efidisk_get_device_name (image->device_handle);
+      file = grub_efi_get_filename (image->file_path);
+      
+      if (device && file)
+       {
+         char *p;
+         char *prefix;
+         
+         /* Get the directory.  */
+         p = grub_strrchr (file, '/');
+         if (p)
+           *p = '\0';
+
+         prefix = grub_malloc (1 + grub_strlen (device) + 1
+                               + grub_strlen (file) + 1);
+         if (prefix)
+           {
+             grub_sprintf (prefix, "(%s)%s", device, file);
+             grub_env_set ("prefix", prefix);
+             grub_free (prefix);
+           }
+       }
+      
+      grub_free (device);
+      grub_free (file);
+    }
+}
+
+void
+grub_efi_fini (void)
+{
+  grub_efidisk_fini ();
+  grub_efi_mm_fini ();
+  grub_console_fini ();
+}
diff --git a/kern/efi/mm.c b/kern/efi/mm.c
new file mode 100644 (file)
index 0000000..35b12ab
--- /dev/null
@@ -0,0 +1,429 @@
+/* mm.c - generic EFI memory management */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+
+#define NEXT_MEMORY_DESCRIPTOR(desc, size)     \
+  ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
+
+#define BYTES_TO_PAGES(bytes)  ((bytes) >> 12)
+#define PAGES_TO_BYTES(pages)  ((pages) << 12)
+
+/* The size of a memory map obtained from the firmware. This must be
+   a multiplier of 4KB.  */
+#define MEMORY_MAP_SIZE        0x3000
+
+/* Maintain the list of allocated pages.  */
+struct allocated_page
+{
+  grub_efi_physical_address_t addr;
+  grub_efi_uint64_t num_pages;
+};
+
+#define ALLOCATED_PAGES_SIZE   0x1000
+#define MAX_ALLOCATED_PAGES    \
+  (ALLOCATED_PAGES_SIZE / sizeof (struct allocated_page))
+
+static struct allocated_page *allocated_pages = 0;
+
+/* The minimum and maximum heap size for GRUB itself.  */
+#define MIN_HEAP_SIZE  0x100000
+#define MAX_HEAP_SIZE  (16 * 0x100000)
+
+
+/* Allocate pages. Return the pointer to the first of allocated pages.  */
+void *
+grub_efi_allocate_pages (grub_efi_physical_address_t address,
+                        grub_efi_uintn_t pages)
+{
+  grub_efi_allocate_type_t type;
+  grub_efi_status_t status;
+  grub_efi_boot_services_t *b;
+
+#if GRUB_TARGET_SIZEOF_VOID_P < 8
+  /* Limit the memory access to less than 4GB for 32-bit platforms.  */
+  if (address > 0xffffffff)
+    return 0;
+  
+  if (address == 0)
+    {
+      type = GRUB_EFI_ALLOCATE_MAX_ADDRESS;
+      address = 0xffffffff;
+    }
+  else
+    type = GRUB_EFI_ALLOCATE_ADDRESS;
+#else
+  if (address == 0)
+    type = GRUB_EFI_ALLOCATE_ANY_PAGES;
+  else
+    type = GRUB_EFI_ALLOCATE_ADDRESS;
+#endif
+
+  b = grub_efi_system_table->boot_services;
+  status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address);
+  if (status != GRUB_EFI_SUCCESS)
+    return 0;
+
+  if (address == 0)
+    {
+      /* Uggh, the address 0 was allocated... This is too annoying,
+        so reallocate another one.  */
+      address = 0xffffffff;
+      status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address);
+      grub_efi_free_pages (0, pages);
+      if (status != GRUB_EFI_SUCCESS)
+       return 0;
+    }
+      
+  if (allocated_pages)
+    {
+      unsigned i;
+
+      for (i = 0; i < MAX_ALLOCATED_PAGES; i++)
+       if (allocated_pages[i].addr == 0)
+         {
+           allocated_pages[i].addr = address;
+           allocated_pages[i].num_pages = pages;
+           break;
+         }
+
+      if (i == MAX_ALLOCATED_PAGES)
+       grub_fatal ("too many page allocations");
+    }
+  
+  return (void *) ((grub_addr_t) address);
+}
+
+/* Free pages starting from ADDRESS.  */
+void
+grub_efi_free_pages (grub_efi_physical_address_t address,
+                    grub_efi_uintn_t pages)
+{
+  grub_efi_boot_services_t *b;
+
+  if (allocated_pages
+      && ((grub_efi_physical_address_t) ((grub_addr_t) allocated_pages)
+         != address))
+    {
+      unsigned i;
+      
+      for (i = 0; i < MAX_ALLOCATED_PAGES; i++)
+       if (allocated_pages[i].addr == address)
+         {
+           allocated_pages[i].addr = 0;
+           break;
+         }
+    }
+  
+  b = grub_efi_system_table->boot_services;
+  efi_call_2 (b->free_pages, address, pages);
+}
+
+/* Get the memory map as defined in the EFI spec. Return 1 if successful,
+   return 0 if partial, or return -1 if an error occurs.  */
+int
+grub_efi_get_memory_map (grub_efi_uintn_t *memory_map_size,
+                        grub_efi_memory_descriptor_t *memory_map,
+                        grub_efi_uintn_t *map_key,
+                        grub_efi_uintn_t *descriptor_size,
+                        grub_efi_uint32_t *descriptor_version)
+{
+  grub_efi_status_t status;
+  grub_efi_boot_services_t *b;
+  grub_efi_uintn_t key;
+  grub_efi_uint32_t version;
+
+  /* Allow some parameters to be missing.  */
+  if (! map_key)
+    map_key = &key;
+  if (! descriptor_version)
+    descriptor_version = &version;
+  
+  b = grub_efi_system_table->boot_services;
+  status = efi_call_5 (b->get_memory_map, memory_map_size, memory_map, map_key,
+                             descriptor_size, descriptor_version);
+  if (status == GRUB_EFI_SUCCESS)
+    return 1;
+  else if (status == GRUB_EFI_BUFFER_TOO_SMALL)
+    return 0;
+  else
+    return -1;
+}
+
+/* Sort the memory map in place.  */
+static void
+sort_memory_map (grub_efi_memory_descriptor_t *memory_map,
+                grub_efi_uintn_t desc_size,
+                grub_efi_memory_descriptor_t *memory_map_end)
+{
+  grub_efi_memory_descriptor_t *d1;
+  grub_efi_memory_descriptor_t *d2;
+  
+  for (d1 = memory_map;
+       d1 < memory_map_end;
+       d1 = NEXT_MEMORY_DESCRIPTOR (d1, desc_size))
+    {
+      grub_efi_memory_descriptor_t *max_desc = d1;
+      
+      for (d2 = NEXT_MEMORY_DESCRIPTOR (d1, desc_size);
+          d2 < memory_map_end;
+          d2 = NEXT_MEMORY_DESCRIPTOR (d2, desc_size))
+       {
+         if (max_desc->num_pages < d2->num_pages)
+           max_desc = d2;
+       }
+
+      if (max_desc != d1)
+       {
+         grub_efi_memory_descriptor_t tmp;
+
+         tmp = *d1;
+         *d1 = *max_desc;
+         *max_desc = tmp;
+       }
+    }
+}
+
+/* Filter the descriptors. GRUB needs only available memory.  */
+static grub_efi_memory_descriptor_t *
+filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
+                  grub_efi_memory_descriptor_t *filtered_memory_map,
+                  grub_efi_uintn_t desc_size,
+                  grub_efi_memory_descriptor_t *memory_map_end)
+{
+  grub_efi_memory_descriptor_t *desc;
+  grub_efi_memory_descriptor_t *filtered_desc;
+
+  for (desc = memory_map, filtered_desc = filtered_memory_map;
+       desc < memory_map_end;
+       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+    {
+      if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
+#if GRUB_TARGET_SIZEOF_VOID_P < 8
+         && desc->physical_start <= 0xffffffff
+#endif
+         && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000
+         && desc->num_pages != 0)
+       {
+         grub_memcpy (filtered_desc, desc, desc_size);
+         
+         /* Avoid less than 1MB, because some loaders seem to be confused.  */
+         if (desc->physical_start < 0x100000)
+           {
+             desc->num_pages -= BYTES_TO_PAGES (0x100000
+                                                - desc->physical_start);
+             desc->physical_start = 0x100000;
+           }
+         
+#if GRUB_TARGET_SIZEOF_VOID_P < 8
+         if (BYTES_TO_PAGES (filtered_desc->physical_start)
+             + filtered_desc->num_pages
+             > BYTES_TO_PAGES (0x100000000LL))
+           filtered_desc->num_pages
+             = (BYTES_TO_PAGES (0x100000000LL)
+                - BYTES_TO_PAGES (filtered_desc->physical_start));
+#endif
+         
+         if (filtered_desc->num_pages == 0)
+           continue;
+         
+         filtered_desc = NEXT_MEMORY_DESCRIPTOR (filtered_desc, desc_size);
+       }
+    }
+
+  return filtered_desc;
+}
+
+/* Return the total number of pages.  */
+static grub_efi_uint64_t
+get_total_pages (grub_efi_memory_descriptor_t *memory_map,
+                grub_efi_uintn_t desc_size,
+                grub_efi_memory_descriptor_t *memory_map_end)
+{
+  grub_efi_memory_descriptor_t *desc;
+  grub_efi_uint64_t total = 0;
+  
+  for (desc = memory_map;
+       desc < memory_map_end;
+       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+    total += desc->num_pages;
+
+  return total;
+}
+
+/* Add memory regions.  */
+static void
+add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
+                   grub_efi_uintn_t desc_size,
+                   grub_efi_memory_descriptor_t *memory_map_end,
+                   grub_efi_uint64_t required_pages)
+{
+  grub_efi_memory_descriptor_t *desc;
+  
+  for (desc = memory_map;
+       desc < memory_map_end;
+       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+    {
+      grub_efi_uint64_t pages;
+      grub_efi_physical_address_t start;
+      void *addr;
+
+      start = desc->physical_start;
+      pages = desc->num_pages;
+      if (pages > required_pages)
+       {
+         start += PAGES_TO_BYTES (pages - required_pages);
+         pages = required_pages;
+       }
+
+      addr = grub_efi_allocate_pages (start, pages);
+      if (! addr)
+       grub_fatal ("cannot allocate conventional memory %p with %u pages",
+                   (void *) ((grub_addr_t) start),
+                   (unsigned) pages);
+
+      grub_mm_init_region (addr, PAGES_TO_BYTES (pages));
+
+      required_pages -= pages;
+      if (required_pages == 0)
+       break;
+    }
+
+  if (required_pages > 0)
+    grub_fatal ("too little memory");
+}
+
+#if 0
+/* Print the memory map.  */
+static void
+print_memory_map (grub_efi_memory_descriptor_t *memory_map,
+                 grub_efi_uintn_t desc_size,
+                 grub_efi_memory_descriptor_t *memory_map_end)
+{
+  grub_efi_memory_descriptor_t *desc;
+  int i;
+  
+  for (desc = memory_map, i = 0;
+       desc < memory_map_end;
+       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size), i++)
+    {
+      grub_printf ("MD: t=%x, p=%llx, v=%llx, n=%llx, a=%llx\n",
+                  desc->type, desc->physical_start, desc->virtual_start,
+                  desc->num_pages, desc->attribute);
+    }
+}
+#endif
+
+void
+grub_efi_mm_init (void)
+{
+  grub_efi_memory_descriptor_t *memory_map;
+  grub_efi_memory_descriptor_t *memory_map_end;
+  grub_efi_memory_descriptor_t *filtered_memory_map;
+  grub_efi_memory_descriptor_t *filtered_memory_map_end;
+  grub_efi_uintn_t map_size;
+  grub_efi_uintn_t desc_size;
+  grub_efi_uint64_t total_pages;
+  grub_efi_uint64_t required_pages;
+
+  /* First of all, allocate pages to maintain allocations.  */
+  allocated_pages
+    = grub_efi_allocate_pages (0, BYTES_TO_PAGES (ALLOCATED_PAGES_SIZE));
+  if (! allocated_pages)
+    grub_fatal ("cannot allocate memory");
+
+  grub_memset (allocated_pages, 0, ALLOCATED_PAGES_SIZE);
+  
+  /* Prepare a memory region to store two memory maps.  */
+  memory_map = grub_efi_allocate_pages (0,
+                                       2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
+  if (! memory_map)
+    grub_fatal ("cannot allocate memory");
+
+  filtered_memory_map = NEXT_MEMORY_DESCRIPTOR (memory_map, MEMORY_MAP_SIZE);
+
+  /* Obtain descriptors for available memory.  */
+  map_size = MEMORY_MAP_SIZE;
+
+  if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) < 0)
+    grub_fatal ("cannot get memory map");
+
+  memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size);
+  
+  filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map,
+                                              desc_size, memory_map_end);
+  
+  /* By default, request a quarter of the available memory.  */
+  total_pages = get_total_pages (filtered_memory_map, desc_size,
+                                filtered_memory_map_end);
+  required_pages = (total_pages >> 2);
+  if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE))
+    required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE);
+  else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE))
+    required_pages = BYTES_TO_PAGES (MAX_HEAP_SIZE);
+
+  /* Sort the filtered descriptors, so that GRUB can allocate pages
+     from smaller regions.  */
+  sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end);
+
+  /* Allocate memory regions for GRUB's memory management.  */
+  add_memory_regions (filtered_memory_map, desc_size,
+                     filtered_memory_map_end, required_pages);
+
+#if 0
+  /* For debug.  */
+  map_size = MEMORY_MAP_SIZE;
+
+  if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) < 0)
+    grub_fatal ("cannot get memory map");
+
+  grub_printf ("printing memory map\n");
+  print_memory_map (memory_map, desc_size,
+                   NEXT_MEMORY_DESCRIPTOR (memory_map, map_size));
+  grub_abort ();
+#endif
+  
+  /* Release the memory maps.  */
+  grub_efi_free_pages ((grub_addr_t) memory_map,
+                      2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
+}
+
+void
+grub_efi_mm_fini (void)
+{
+  if (allocated_pages)
+    {
+      unsigned i;
+
+      for (i = 0; i < MAX_ALLOCATED_PAGES; i++)
+       {
+         struct allocated_page *p;
+
+         p = allocated_pages + i;
+         if (p->addr != 0)
+           grub_efi_free_pages ((grub_addr_t) p->addr, p->num_pages);
+       }
+
+      grub_efi_free_pages ((grub_addr_t) allocated_pages,
+                          BYTES_TO_PAGES (ALLOCATED_PAGES_SIZE));
+    }
+}
diff --git a/kern/elf.c b/kern/elf.c
new file mode 100644 (file)
index 0000000..8ddf9e5
--- /dev/null
@@ -0,0 +1,464 @@
+/* elf.c - load ELF files */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,2006,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/>.
+ */
+
+#include <grub/err.h>
+#include <grub/elf.h>
+#include <grub/elfload.h>
+#include <grub/file.h>
+#include <grub/gzio.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+
+/* Check if EHDR is a valid ELF header.  */
+static grub_err_t
+grub_elf_check_header (grub_elf_t elf)
+{
+  Elf32_Ehdr *e = &elf->ehdr.ehdr32;
+
+  if (e->e_ident[EI_MAG0] != ELFMAG0
+      || e->e_ident[EI_MAG1] != ELFMAG1
+      || e->e_ident[EI_MAG2] != ELFMAG2
+      || e->e_ident[EI_MAG3] != ELFMAG3
+      || e->e_ident[EI_VERSION] != EV_CURRENT
+      || e->e_version != EV_CURRENT)
+    return grub_error (GRUB_ERR_BAD_OS, "invalid arch independent ELF magic");
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_elf_close (grub_elf_t elf)
+{
+  grub_file_t file = elf->file;
+
+  grub_free (elf->phdrs);
+  grub_free (elf);
+
+  if (file)
+    grub_file_close (file);
+
+  return grub_errno;
+}
+
+grub_elf_t
+grub_elf_file (grub_file_t file)
+{
+  grub_elf_t elf;
+
+  elf = grub_malloc (sizeof (*elf));
+  if (! elf)
+    return 0;
+
+  elf->file = file;
+  elf->phdrs = 0;
+
+  if (grub_file_seek (elf->file, 0) == (grub_off_t) -1)
+    goto fail;
+
+  if (grub_file_read (elf->file, (char *) &elf->ehdr, sizeof (elf->ehdr))
+      != sizeof (elf->ehdr))
+    {
+      grub_error_push ();
+      grub_error (GRUB_ERR_READ_ERROR, "Cannot read ELF header.");
+      goto fail;
+    }
+
+  if (grub_elf_check_header (elf))
+    goto fail;
+
+  return elf;
+
+fail:
+  grub_free (elf->phdrs);
+  grub_free (elf);
+  return 0;
+}
+
+grub_elf_t
+grub_elf_open (const char *name)
+{
+  grub_file_t file;
+  grub_elf_t elf;
+
+  file = grub_gzfile_open (name, 1);
+  if (! file)
+    return 0;
+
+  elf = grub_elf_file (file);
+  if (! elf)
+    grub_file_close (file);
+
+  return elf;
+}
+
+\f
+/* 32-bit */
+
+int
+grub_elf_is_elf32 (grub_elf_t elf)
+{
+  return elf->ehdr.ehdr32.e_ident[EI_CLASS] == ELFCLASS32;
+}
+
+static grub_err_t
+grub_elf32_load_phdrs (grub_elf_t elf)
+{
+  grub_ssize_t phdrs_size;
+
+  phdrs_size = elf->ehdr.ehdr32.e_phnum * elf->ehdr.ehdr32.e_phentsize;
+
+  grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n",
+               (unsigned long long) elf->ehdr.ehdr32.e_phoff,
+               (unsigned long) phdrs_size);
+
+  elf->phdrs = grub_malloc (phdrs_size);
+  if (! elf->phdrs)
+    return grub_errno;
+
+  if ((grub_file_seek (elf->file, elf->ehdr.ehdr32.e_phoff) == (grub_off_t) -1)
+      || (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size))
+    {
+      grub_error_push ();
+      return grub_error (GRUB_ERR_READ_ERROR, "Cannot read program headers");
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_elf32_phdr_iterate (grub_elf_t elf,
+                        int NESTED_FUNC_ATTR (*hook) (grub_elf_t, Elf32_Phdr *, void *),
+                        void *hook_arg)
+{
+  Elf32_Phdr *phdrs;
+  unsigned int i;
+
+  if (! elf->phdrs)
+    if (grub_elf32_load_phdrs (elf))
+      return grub_errno;
+  phdrs = elf->phdrs;
+
+  for (i = 0; i < elf->ehdr.ehdr32.e_phnum; i++)
+    {
+      Elf32_Phdr *phdr = phdrs + i;
+      grub_dprintf ("elf",
+                   "Segment %u: type 0x%x paddr 0x%lx memsz 0x%lx "
+                   "filesz %lx\n",
+                   i, phdr->p_type,
+                   (unsigned long) phdr->p_paddr,
+                   (unsigned long) phdr->p_memsz,
+                   (unsigned long) phdr->p_filesz);
+      if (hook (elf, phdr, hook_arg))
+       break;
+    }
+
+  return grub_errno;
+}
+
+/* Calculate the amount of memory spanned by the segments.  */
+grub_size_t
+grub_elf32_size (grub_elf_t elf)
+{
+  Elf32_Addr segments_start = (Elf32_Addr) -1;
+  Elf32_Addr segments_end = 0;
+  int nr_phdrs = 0;
+
+  /* Run through the program headers to calculate the total memory size we
+   * should claim.  */
+  auto int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf, Elf32_Phdr *phdr, void *_arg);
+  int NESTED_FUNC_ATTR calcsize (grub_elf_t UNUSED _elf, Elf32_Phdr *phdr, void UNUSED *_arg)
+    {
+      /* Only consider loadable segments.  */
+      if (phdr->p_type != PT_LOAD)
+       return 0;
+      nr_phdrs++;
+      if (phdr->p_paddr < segments_start)
+       segments_start = phdr->p_paddr;
+      if (phdr->p_paddr + phdr->p_memsz > segments_end)
+       segments_end = phdr->p_paddr + phdr->p_memsz;
+      return 0;
+    }
+
+  grub_elf32_phdr_iterate (elf, calcsize, 0);
+
+  if (nr_phdrs == 0)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "No program headers present");
+      return 0;
+    }
+
+  if (segments_end < segments_start)
+    {
+      /* Very bad addresses.  */
+      grub_error (GRUB_ERR_BAD_OS, "Bad program header load addresses");
+      return 0;
+    }
+
+  return segments_end - segments_start;
+}
+
+
+/* Load every loadable segment into memory specified by `_load_hook'.  */
+grub_err_t
+grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook,
+                grub_addr_t *base, grub_size_t *size)
+{
+  grub_addr_t load_base = (grub_addr_t) -1ULL;
+  grub_size_t load_size = 0;
+  grub_err_t err;
+
+  auto int NESTED_FUNC_ATTR grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook);
+  int NESTED_FUNC_ATTR grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook)
+  {
+    grub_elf32_load_hook_t load_hook = (grub_elf32_load_hook_t) hook;
+    grub_addr_t load_addr;
+
+    if (phdr->p_type != PT_LOAD)
+      return 0;
+
+    load_addr = phdr->p_paddr;
+    if (load_hook && load_hook (phdr, &load_addr))
+      return 1;
+
+    if (load_addr < load_base)
+      load_base = load_addr;
+
+    grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n",
+                 (unsigned long long) load_addr,
+                 (unsigned long long) phdr->p_memsz);
+
+    if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1)
+      {
+       grub_error_push ();
+       return grub_error (GRUB_ERR_BAD_OS,
+                          "Invalid offset in program header.");
+      }
+
+    if (phdr->p_filesz)
+      {
+       grub_ssize_t read;
+       read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz);
+       if (read != (grub_ssize_t) phdr->p_filesz)
+         {
+           /* XXX How can we free memory from `load_hook'? */
+           grub_error_push ();
+           return grub_error (GRUB_ERR_BAD_OS,
+                              "Couldn't read segment from file: "
+                              "wanted 0x%lx bytes; read 0x%lx bytes.",
+                              phdr->p_filesz, read);
+         }
+      }
+
+    if (phdr->p_filesz < phdr->p_memsz)
+      grub_memset ((void *) (long) (load_addr + phdr->p_filesz),
+                  0, phdr->p_memsz - phdr->p_filesz);
+
+    load_size += phdr->p_memsz;
+
+    return 0;
+  }
+
+  err = grub_elf32_phdr_iterate (_elf, grub_elf32_load_segment, _load_hook);
+
+  if (base)
+    *base = load_base;
+  if (size)
+    *size = load_size;
+
+  return err;
+}
+
+
+\f
+/* 64-bit */
+
+int
+grub_elf_is_elf64 (grub_elf_t elf)
+{
+  return elf->ehdr.ehdr64.e_ident[EI_CLASS] == ELFCLASS64;
+}
+
+static grub_err_t
+grub_elf64_load_phdrs (grub_elf_t elf)
+{
+  grub_ssize_t phdrs_size;
+
+  phdrs_size = elf->ehdr.ehdr64.e_phnum * elf->ehdr.ehdr64.e_phentsize;
+
+  grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n",
+               (unsigned long long) elf->ehdr.ehdr64.e_phoff,
+               (unsigned long) phdrs_size);
+
+  elf->phdrs = grub_malloc (phdrs_size);
+  if (! elf->phdrs)
+    return grub_errno;
+
+  if ((grub_file_seek (elf->file, elf->ehdr.ehdr64.e_phoff) == (grub_off_t) -1)
+      || (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size))
+    {
+      grub_error_push ();
+      return grub_error (GRUB_ERR_READ_ERROR, "Cannot read program headers");
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_elf64_phdr_iterate (grub_elf_t elf,
+                        int NESTED_FUNC_ATTR (*hook) (grub_elf_t, Elf64_Phdr *, void *),
+                        void *hook_arg)
+{
+  Elf64_Phdr *phdrs;
+  unsigned int i;
+
+  if (! elf->phdrs)
+    if (grub_elf64_load_phdrs (elf))
+      return grub_errno;
+  phdrs = elf->phdrs;
+
+  for (i = 0; i < elf->ehdr.ehdr64.e_phnum; i++)
+    {
+      Elf64_Phdr *phdr = phdrs + i;
+      grub_dprintf ("elf",
+                   "Segment %u: type 0x%x paddr 0x%lx memsz 0x%lx "
+                   "filesz %lx\n",
+                   i, phdr->p_type,
+                   (unsigned long) phdr->p_paddr,
+                   (unsigned long) phdr->p_memsz,
+                   (unsigned long) phdr->p_filesz);
+      if (hook (elf, phdr, hook_arg))
+       break;
+    }
+
+  return grub_errno;
+}
+
+/* Calculate the amount of memory spanned by the segments.  */
+grub_size_t
+grub_elf64_size (grub_elf_t elf)
+{
+  Elf64_Addr segments_start = (Elf64_Addr) -1;
+  Elf64_Addr segments_end = 0;
+  int nr_phdrs = 0;
+
+  /* Run through the program headers to calculate the total memory size we
+   * should claim.  */
+  auto int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf, Elf64_Phdr *phdr, void *_arg);
+  int NESTED_FUNC_ATTR calcsize (grub_elf_t UNUSED _elf, Elf64_Phdr *phdr, void UNUSED *_arg)
+    {
+      /* Only consider loadable segments.  */
+      if (phdr->p_type != PT_LOAD)
+       return 0;
+      nr_phdrs++;
+      if (phdr->p_paddr < segments_start)
+       segments_start = phdr->p_paddr;
+      if (phdr->p_paddr + phdr->p_memsz > segments_end)
+       segments_end = phdr->p_paddr + phdr->p_memsz;
+      return 0;
+    }
+
+  grub_elf64_phdr_iterate (elf, calcsize, 0);
+
+  if (nr_phdrs == 0)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "No program headers present");
+      return 0;
+    }
+
+  if (segments_end < segments_start)
+    {
+      /* Very bad addresses.  */
+      grub_error (GRUB_ERR_BAD_OS, "Bad program header load addresses");
+      return 0;
+    }
+
+  return segments_end - segments_start;
+}
+
+
+/* Load every loadable segment into memory specified by `_load_hook'.  */
+grub_err_t
+grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook,
+                grub_addr_t *base, grub_size_t *size)
+{
+  grub_addr_t load_base = (grub_addr_t) -1ULL;
+  grub_size_t load_size = 0;
+  grub_err_t err;
+
+  auto int NESTED_FUNC_ATTR grub_elf64_load_segment (grub_elf_t elf, Elf64_Phdr *phdr,
+                                                    void *hook);
+  int NESTED_FUNC_ATTR grub_elf64_load_segment (grub_elf_t elf, Elf64_Phdr *phdr, void *hook)
+  {
+    grub_elf64_load_hook_t load_hook = (grub_elf64_load_hook_t) hook;
+    grub_addr_t load_addr;
+
+    if (phdr->p_type != PT_LOAD)
+      return 0;
+
+    load_addr = phdr->p_paddr;
+    if (load_hook && load_hook (phdr, &load_addr))
+      return 1;
+
+    if (load_addr < load_base)
+      load_base = load_addr;
+
+    grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n",
+                 (unsigned long long) load_addr,
+                 (unsigned long long) phdr->p_memsz);
+
+    if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1)
+      {
+       grub_error_push ();
+       return grub_error (GRUB_ERR_BAD_OS,
+                          "Invalid offset in program header.");
+      }
+
+    if (phdr->p_filesz)
+      {
+       grub_ssize_t read;
+       read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz);
+       if (read != (grub_ssize_t) phdr->p_filesz)
+          {
+           /* XXX How can we free memory from `load_hook'?  */
+           grub_error_push ();
+           return grub_error (GRUB_ERR_BAD_OS,
+                             "Couldn't read segment from file: "
+                             "wanted 0x%lx bytes; read 0x%lx bytes.",
+                             phdr->p_filesz, read);
+          }
+      }
+
+    if (phdr->p_filesz < phdr->p_memsz)
+      grub_memset ((void *) (long) (load_addr + phdr->p_filesz),
+                  0, phdr->p_memsz - phdr->p_filesz);
+
+    load_size += phdr->p_memsz;
+
+    return 0;
+  }
+
+  err = grub_elf64_phdr_iterate (_elf, grub_elf64_load_segment, _load_hook);
+
+  if (base)
+    *base = load_base;
+  if (size)
+    *size = load_size;
+
+  return err;
+}
diff --git a/kern/env.c b/kern/env.c
new file mode 100644 (file)
index 0000000..6a74c70
--- /dev/null
@@ -0,0 +1,428 @@
+/* env.c - Environment variables */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2005,2006,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/>.
+ */
+
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+
+/* The size of the hash table.  */
+#define        HASHSZ  13
+
+/* A hashtable for quick lookup of variables.  */
+struct grub_env_context
+{
+  /* A hash table for variables.  */
+  struct grub_env_var *vars[HASHSZ];
+  
+  /* One level deeper on the stack.  */
+  struct grub_env_context *prev;
+};
+
+/* This is used for sorting only.  */
+struct grub_env_sorted_var
+{
+  struct grub_env_var *var;
+  struct grub_env_sorted_var *next;
+};
+
+/* The initial context.  */
+static struct grub_env_context initial_context;
+
+/* The current context.  */
+static struct grub_env_context *current_context = &initial_context;
+
+/* Return the hash representation of the string S.  */
+static unsigned int
+grub_env_hashval (const char *s)
+{
+  unsigned int i = 0;
+
+  /* XXX: This can be done much more efficiently.  */
+  while (*s)
+    i += 5 * *(s++);
+
+  return i % HASHSZ;
+}
+
+static struct grub_env_var *
+grub_env_find (const char *name)
+{
+  struct grub_env_var *var;
+  int idx = grub_env_hashval (name);
+
+  /* Look for the variable in the current context.  */
+  for (var = current_context->vars[idx]; var; var = var->next)
+    if (grub_strcmp (var->name, name) == 0)
+      return var;
+
+  return 0;
+}
+
+grub_err_t
+grub_env_context_open (void)
+{
+  struct grub_env_context *context;
+  int i;
+
+  context = grub_malloc (sizeof (*context));
+  if (! context)
+    return grub_errno;
+
+  grub_memset (context, 0, sizeof (*context));
+  context->prev = current_context;
+  current_context = context;
+
+  /* Copy exported variables.  */
+  for (i = 0; i < HASHSZ; i++)
+    {
+      struct grub_env_var *var;
+      
+      for (var = context->prev->vars[i]; var; var = var->next)
+       {
+         if (var->type == GRUB_ENV_VAR_GLOBAL)
+           {
+             if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE)
+               {
+                 grub_env_context_close ();
+                 return grub_errno;
+               }
+             grub_register_variable_hook (var->name, var->read_hook, var->write_hook);
+           }
+       }
+    }
+  
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_env_context_close (void)
+{
+  struct grub_env_context *context;
+  int i;
+
+  if (! current_context->prev)
+    grub_fatal ("cannot close the initial context");
+  
+  /* Free the variables associated with this context.  */
+  for (i = 0; i < HASHSZ; i++)
+    {
+      struct grub_env_var *p, *q;
+      
+      for (p = current_context->vars[i]; p; p = q)
+       {
+         q = p->next;
+         grub_free (p);
+       }
+    }
+
+  /* Restore the previous context.  */
+  context = current_context->prev;
+  grub_free (current_context);
+  current_context = context;
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_env_insert (struct grub_env_context *context,
+                struct grub_env_var *var)
+{
+  int idx = grub_env_hashval (var->name);
+
+  /* Insert the variable into the hashtable.  */
+  var->prevp = &context->vars[idx];
+  var->next = context->vars[idx];
+  if (var->next)
+    var->next->prevp = &(var->next);
+  context->vars[idx] = var;
+}
+
+static void
+grub_env_remove (struct grub_env_var *var)
+{
+  /* Remove the entry from the variable table.  */
+  *var->prevp = var->next;
+  if (var->next)
+    var->next->prevp = var->prevp;
+}
+
+grub_err_t
+grub_env_export (const char *name)
+{
+  struct grub_env_var *var;
+
+  var = grub_env_find (name);
+  if (var)
+    var->type = GRUB_ENV_VAR_GLOBAL;
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_env_set (const char *name, const char *val)
+{
+  struct grub_env_var *var;
+
+  /* If the variable does already exist, just update the variable.  */
+  var = grub_env_find (name);
+  if (var)
+    {
+      char *old = var->value;
+
+      if (var->write_hook)
+       var->value = var->write_hook (var, val);
+      else
+       var->value = grub_strdup (val);
+      
+      if (! var->value)
+       {
+         var->value = old;
+         return grub_errno;
+       }
+
+      grub_free (old);
+      return GRUB_ERR_NONE;
+    }
+
+  /* The variable does not exist, so create a new one.  */
+  var = grub_malloc (sizeof (*var));
+  if (! var)
+    return grub_errno;
+  
+  grub_memset (var, 0, sizeof (*var));
+
+  /* This is not necessary, because GRUB_ENV_VAR_LOCAL == 0. But leave
+     this for readability.  */
+  var->type = GRUB_ENV_VAR_LOCAL;
+  
+  var->name = grub_strdup (name);
+  if (! var->name)
+    goto fail;
+  
+  var->value = grub_strdup (val);
+  if (! var->value)
+    goto fail;
+
+  grub_env_insert (current_context, var);
+
+  return GRUB_ERR_NONE;
+
+ fail:
+  grub_free (var->name);
+  grub_free (var->value);
+  grub_free (var);
+
+  return grub_errno;
+}
+
+char *
+grub_env_get (const char *name)
+{
+  struct grub_env_var *var;
+  
+  var = grub_env_find (name);
+  if (! var)
+    return 0;
+
+  if (var->read_hook)
+    return var->read_hook (var, var->value);
+
+  return var->value;
+}
+
+void
+grub_env_unset (const char *name)
+{
+  struct grub_env_var *var;
+  
+  var = grub_env_find (name);
+  if (! var)
+    return;
+
+  /* XXX: It is not possible to unset variables with a read or write
+     hook.  */
+  if (var->read_hook || var->write_hook)
+    return;
+
+  grub_env_remove (var);
+
+  grub_free (var->name);
+  if (var->type != GRUB_ENV_VAR_DATA)
+    grub_free (var->value);
+  grub_free (var);
+}
+
+void
+grub_env_iterate (int (*func) (struct grub_env_var *var))
+{
+  struct grub_env_sorted_var *sorted_list = 0;
+  struct grub_env_sorted_var *sorted_var;
+  int i;
+  
+  /* Add variables associated with this context into a sorted list.  */
+  for (i = 0; i < HASHSZ; i++)
+    {
+      struct grub_env_var *var;
+      
+      for (var = current_context->vars[i]; var; var = var->next)
+       {
+         struct grub_env_sorted_var *p, **q;
+
+         /* Ignore data slots.  */
+         if (var->type == GRUB_ENV_VAR_DATA)
+           continue;
+         
+         sorted_var = grub_malloc (sizeof (*sorted_var));
+         if (! sorted_var)
+           goto fail;
+
+         sorted_var->var = var;
+
+         for (q = &sorted_list, p = *q; p; q = &((*q)->next), p = *q)
+           {
+             if (grub_strcmp (p->var->name, var->name) > 0)
+               break;
+           }
+         
+         sorted_var->next = *q;
+         *q = sorted_var;
+       }
+    }
+
+  /* Iterate FUNC on the sorted list.  */
+  for (sorted_var = sorted_list; sorted_var; sorted_var = sorted_var->next)
+    if (func (sorted_var->var))
+      break;
+
+ fail:
+
+  /* Free the sorted list.  */
+  for (sorted_var = sorted_list; sorted_var; )
+    {
+      struct grub_env_sorted_var *tmp = sorted_var->next;
+
+      grub_free (sorted_var);
+      sorted_var = tmp;
+    }
+}
+
+grub_err_t
+grub_register_variable_hook (const char *name,
+                            grub_env_read_hook_t read_hook,
+                            grub_env_write_hook_t write_hook)
+{
+  struct grub_env_var *var = grub_env_find (name);
+
+  if (! var)
+    {
+      if (grub_env_set (name, "") != GRUB_ERR_NONE)
+       return grub_errno;
+      
+      var = grub_env_find (name);
+      /* XXX Insert an assertion?  */
+    }
+  
+  var->read_hook = read_hook;
+  var->write_hook = write_hook;
+
+  return GRUB_ERR_NONE;
+}
+
+static char *
+mangle_data_slot_name (const char *name)
+{
+  char *mangled_name;
+
+  mangled_name = grub_malloc (grub_strlen (name) + 2);
+  if (! mangled_name)
+    return 0;
+  
+  grub_sprintf (mangled_name, "\e%s", name);
+  return mangled_name;
+}
+
+grub_err_t
+grub_env_set_data_slot (const char *name, const void *ptr)
+{
+  char *mangled_name;
+  struct grub_env_var *var;
+
+  mangled_name = mangle_data_slot_name (name);
+  if (! mangled_name)
+    goto fail;
+
+  /* If the variable does already exist, just update the variable.  */
+  var = grub_env_find (mangled_name);
+  if (var)
+    {
+      var->value = (char *) ptr;
+      return GRUB_ERR_NONE;
+    }
+
+  /* The variable does not exist, so create a new one.  */
+  var = grub_malloc (sizeof (*var));
+  if (! var)
+    goto fail;
+  
+  grub_memset (var, 0, sizeof (*var));
+
+  var->type = GRUB_ENV_VAR_DATA;
+  var->name = mangled_name;
+  var->value = (char *) ptr;
+
+  grub_env_insert (current_context, var);
+
+  return GRUB_ERR_NONE;
+
+ fail:
+
+  grub_free (mangled_name);
+  return grub_errno;
+}
+
+void *
+grub_env_get_data_slot (const char *name)
+{
+  char *mangled_name;
+  void *ptr = 0;
+  
+  mangled_name = mangle_data_slot_name (name);
+  if (! mangled_name)
+    goto fail;
+
+  ptr = grub_env_get (mangled_name);
+  grub_free (mangled_name);
+
+ fail:
+  
+  return ptr;
+}
+
+void
+grub_env_unset_data_slot (const char *name)
+{
+  char *mangled_name;
+  
+  mangled_name = mangle_data_slot_name (name);
+  if (! mangled_name)
+    return;
+
+  grub_env_unset (mangled_name);
+  grub_free (mangled_name);
+}
diff --git a/kern/err.c b/kern/err.c
new file mode 100644 (file)
index 0000000..8c78cb7
--- /dev/null
@@ -0,0 +1,134 @@
+/* err.c - error handling routines */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,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/>.
+ */
+
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <stdarg.h>
+
+#define GRUB_MAX_ERRMSG                256
+#define GRUB_ERROR_STACK_SIZE  10
+
+grub_err_t grub_errno;
+char grub_errmsg[GRUB_MAX_ERRMSG];
+
+static struct
+{
+  grub_err_t errno;
+  char errmsg[GRUB_MAX_ERRMSG];
+} grub_error_stack_items[GRUB_ERROR_STACK_SIZE];
+
+static int grub_error_stack_pos;
+static int grub_error_stack_assert;
+
+grub_err_t
+grub_error (grub_err_t n, const char *fmt, ...)
+{
+  va_list ap;
+  
+  grub_errno = n;
+
+  va_start (ap, fmt);
+  grub_vsprintf (grub_errmsg, fmt, ap);
+  va_end (ap);
+
+  return n;
+}
+
+void
+grub_fatal (const char *fmt, ...)
+{
+  va_list ap;
+
+  va_start (ap, fmt);
+  grub_vprintf (fmt, ap);
+  va_end (ap);
+
+  grub_abort ();
+}
+
+void
+grub_error_push (void)
+{
+  /* Only add items to stack, if there is enough room.  */
+  if (grub_error_stack_pos < GRUB_ERROR_STACK_SIZE)
+    {
+      /* Copy active error message to stack.  */
+      grub_error_stack_items[grub_error_stack_pos].errno = grub_errno;
+      grub_memcpy (grub_error_stack_items[grub_error_stack_pos].errmsg,
+                   grub_errmsg,
+                   sizeof (grub_errmsg));
+        
+      /* Advance to next error stack position.  */
+      grub_error_stack_pos++;
+    }
+  else
+    {
+      /* There is no room for new error message. Discard new error message
+         and mark error stack assertion flag.  */
+      grub_error_stack_assert = 1;
+    }
+
+  /* Allow further operation of other components by resetting
+     active errno to GRUB_ERR_NONE.  */
+  grub_errno = GRUB_ERR_NONE;
+}
+
+int
+grub_error_pop (void)
+{
+  if (grub_error_stack_pos > 0)
+    {
+      /* Pop error message from error stack to current active error.  */
+      grub_error_stack_pos--;
+      
+      grub_errno = grub_error_stack_items[grub_error_stack_pos].errno;
+      grub_memcpy (grub_errmsg,
+                   grub_error_stack_items[grub_error_stack_pos].errmsg,
+                   sizeof (grub_errmsg));
+                  
+      return 1;
+    }
+  else
+    {
+      /* There is no more items on error stack, reset to no error state.  */
+      grub_errno = GRUB_ERR_NONE;
+      
+      return 0;
+    }
+}
+
+void
+grub_print_error (void)
+{
+  /* Print error messages in reverse order. First print active error message
+     and then empty error stack.  */
+  do
+    {
+      if (grub_errno != GRUB_ERR_NONE)
+        grub_err_printf ("error: %s\n", grub_errmsg);
+    } 
+  while (grub_error_pop ());
+  
+  /* If there was an assert while using error stack, report about it.  */
+  if (grub_error_stack_assert)
+    {
+      grub_err_printf ("assert: error stack overflow detected!\n");
+      grub_error_stack_assert = 0;
+    }
+}
diff --git a/kern/file.c b/kern/file.c
new file mode 100644 (file)
index 0000000..adf55da
--- /dev/null
@@ -0,0 +1,162 @@
+/* file.c - file I/O functions */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/fs.h>
+#include <grub/device.h>
+
+/* Get the device part of the filename NAME. It is enclosed by parentheses.  */
+char *
+grub_file_get_device_name (const char *name)
+{
+  if (name[0] == '(')
+    {
+      char *p = grub_strchr (name, ')');
+      char *ret;
+      
+      if (! p)
+       {
+         grub_error (GRUB_ERR_BAD_FILENAME, "missing `)'");
+         return 0;
+       }
+
+      ret = (char *) grub_malloc (p - name);
+      if (! ret)
+       return 0;
+      
+      grub_memcpy (ret, name + 1, p - name - 1);
+      ret[p - name - 1] = '\0';
+      return ret;
+    }
+
+  return 0;
+}
+
+grub_file_t
+grub_file_open (const char *name)
+{
+  grub_device_t device;
+  grub_file_t file = 0;
+  char *device_name;
+  char *file_name;
+
+  device_name = grub_file_get_device_name (name);
+  if (grub_errno)
+    return 0;
+
+  /* Get the file part of NAME.  */
+  file_name = grub_strchr (name, ')');
+  if (file_name)
+    file_name++;
+  else
+    file_name = (char *) name;
+
+  device = grub_device_open (device_name);
+  grub_free (device_name);
+  if (! device)
+    goto fail;
+  
+  file = (grub_file_t) grub_malloc (sizeof (*file));
+  if (! file)
+    goto fail;
+  
+  file->device = device;
+  file->offset = 0;
+  file->data = 0;
+  file->read_hook = 0;
+    
+  if (device->disk && file_name[0] != '/')
+    /* This is a block list.  */
+    file->fs = &grub_fs_blocklist;
+  else
+    {
+      file->fs = grub_fs_probe (device);
+      if (! file->fs)
+       goto fail;
+    }
+
+  if ((file->fs->open) (file, file_name) != GRUB_ERR_NONE)
+    goto fail;
+
+  return file;
+
+ fail:
+  if (device)
+    grub_device_close (device);
+
+  /* if (net) grub_net_close (net);  */
+
+  grub_free (file);
+  
+  return 0;
+}
+
+grub_ssize_t
+grub_file_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  grub_ssize_t res;
+  
+  if (len == 0 || len > file->size - file->offset)
+    len = file->size - file->offset;
+
+  /* Prevent an overflow.  */
+  if ((grub_ssize_t) len < 0)
+    len >>= 1;
+  
+  if (len == 0)
+    return 0;
+  
+  res = (file->fs->read) (file, buf, len);
+  if (res > 0)
+    file->offset += res;
+
+  return res;
+}
+
+grub_err_t
+grub_file_close (grub_file_t file)
+{
+  if (file->fs->close)
+    (file->fs->close) (file);
+
+  if (file->device)
+    grub_device_close (file->device);
+  grub_free (file);
+  return grub_errno;
+}
+
+grub_off_t
+grub_file_seek (grub_file_t file, grub_off_t offset)
+{
+  grub_off_t old;
+
+  if (offset > file->size)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE,
+                 "attempt to seek outside of the file");
+      return -1;
+    }
+  
+  old = file->offset;
+  file->offset = offset;
+  return old;
+}
diff --git a/kern/fs.c b/kern/fs.c
new file mode 100644 (file)
index 0000000..4e21de2
--- /dev/null
+++ b/kern/fs.c
@@ -0,0 +1,263 @@
+/* fs.c - filesystem manager */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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/>.
+ */
+
+#include <grub/disk.h>
+#include <grub/net.h>
+#include <grub/fs.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/mm.h>
+#include <grub/term.h>
+
+static grub_fs_t grub_fs_list;
+
+grub_fs_autoload_hook_t grub_fs_autoload_hook = 0;
+
+void
+grub_fs_register (grub_fs_t fs)
+{
+  fs->next = grub_fs_list;
+  grub_fs_list = fs;
+}
+
+void
+grub_fs_unregister (grub_fs_t fs)
+{
+  grub_fs_t *p, q;
+
+  for (p = &grub_fs_list, q = *p; q; p = &(q->next), q = q->next)
+    if (q == fs)
+      {
+       *p = q->next;
+       break;
+      }
+}
+
+void
+grub_fs_iterate (int (*hook) (const grub_fs_t fs))
+{
+  grub_fs_t p;
+
+  for (p = grub_fs_list; p; p = p->next)
+    if (hook (p))
+      break;
+}
+
+grub_fs_t
+grub_fs_probe (grub_device_t device)
+{
+  grub_fs_t p;
+  auto int dummy_func (const char *filename, int dir);
+
+  int dummy_func (const char *filename __attribute__ ((unused)),
+                 int dir __attribute__ ((unused)))
+    {
+      return 1;
+    }
+
+  if (device->disk)
+    {
+      /* Make it sure not to have an infinite recursive calls.  */
+      static int count = 0;
+
+      for (p = grub_fs_list; p; p = p->next)
+       {
+         grub_dprintf ("fs", "Detecting %s...\n", p->name);
+         (p->dir) (device, "/", dummy_func);
+         if (grub_errno == GRUB_ERR_NONE)
+           return p;
+
+         grub_error_push ();
+         grub_dprintf ("fs", "%s detection failed.\n", p->name);
+         grub_error_pop ();
+
+         if (grub_errno != GRUB_ERR_BAD_FS)
+           return 0;
+
+         grub_errno = GRUB_ERR_NONE;
+       }
+
+      /* Let's load modules automatically.  */
+      if (grub_fs_autoload_hook && count == 0)
+       {
+         count++;
+         
+         while (grub_fs_autoload_hook ())
+           {
+             p = grub_fs_list;
+             
+             (p->dir) (device, "/", dummy_func);
+             if (grub_errno == GRUB_ERR_NONE)
+               {
+                 count--;
+                 return p;
+               }
+             
+             if (grub_errno != GRUB_ERR_BAD_FS)
+               {
+                 count--;
+                 return 0;
+               }
+             
+             grub_errno = GRUB_ERR_NONE;
+           }
+
+         count--;
+       }
+    }
+  else if (device->net->fs)
+    return device->net->fs;
+
+  grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem");
+  return 0;
+}
+
+\f
+
+/* Block list support routines.  */
+
+struct grub_fs_block
+{
+  grub_disk_addr_t offset;
+  unsigned long length;
+};
+
+static grub_err_t
+grub_fs_blocklist_open (grub_file_t file, const char *name)
+{
+  char *p = (char *) name;
+  unsigned num = 0;
+  unsigned i;
+  grub_disk_t disk = file->device->disk;
+  struct grub_fs_block *blocks;
+  
+  /* First, count the number of blocks.  */
+  do
+    {
+      num++;
+      p = grub_strchr (p, ',');
+      if (p)
+       p++;
+    }
+  while (p);
+
+  /* Allocate a block list.  */
+  blocks = grub_malloc (sizeof (struct grub_fs_block) * (num + 1));
+  if (! blocks)
+    return 0;
+
+  file->size = 0;
+  p = (char *) name;
+  for (i = 0; i < num; i++)
+    {
+      if (*p != '+')
+       {
+         blocks[i].offset = grub_strtoull (p, &p, 0);
+         if (grub_errno != GRUB_ERR_NONE || *p != '+')
+           {
+             grub_error (GRUB_ERR_BAD_FILENAME,
+                         "invalid file name `%s'", name);
+             goto fail;
+           }
+       }
+      else
+       blocks[i].offset = 0;
+
+      p++;
+      blocks[i].length = grub_strtoul (p, &p, 0);
+      if (grub_errno != GRUB_ERR_NONE
+         || blocks[i].length == 0
+         || (*p && *p != ',' && ! grub_isspace (*p)))
+       {
+         grub_error (GRUB_ERR_BAD_FILENAME,
+                     "invalid file name `%s'", name);
+         goto fail;
+       }
+
+      if (disk->total_sectors < blocks[i].offset + blocks[i].length)
+       {
+         grub_error (GRUB_ERR_BAD_FILENAME, "beyond the total sectors");
+         goto fail;
+       }
+      
+      file->size += (blocks[i].length << GRUB_DISK_SECTOR_BITS);
+      p++;
+    }
+
+  blocks[i].length = 0;
+  file->data = blocks;
+  
+  return GRUB_ERR_NONE;
+
+ fail:
+  grub_free (blocks);
+  return grub_errno;
+}
+
+static grub_ssize_t
+grub_fs_blocklist_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_fs_block *p;
+  grub_disk_addr_t sector;
+  grub_off_t offset;
+  grub_ssize_t ret = 0;
+
+  if (len > file->size - file->offset)
+    len = file->size - file->offset;
+
+  sector = (file->offset >> GRUB_DISK_SECTOR_BITS);
+  offset = (file->offset & (GRUB_DISK_SECTOR_SIZE - 1));
+  for (p = file->data; p->length && len > 0; p++)
+    {
+      if (sector < p->length)
+       {
+         grub_size_t size;
+
+         size = len;
+         if (((size + offset + GRUB_DISK_SECTOR_SIZE - 1)
+              >> GRUB_DISK_SECTOR_BITS) > p->length - sector)
+           size = ((p->length - sector) << GRUB_DISK_SECTOR_BITS) - offset;
+         
+         if (grub_disk_read (file->device->disk, p->offset + sector, offset,
+                             size, buf) != GRUB_ERR_NONE)
+           return -1;
+         
+         ret += size;
+         len -= size;
+         sector -= ((size + offset) >> GRUB_DISK_SECTOR_BITS);
+         offset = ((size + offset) & (GRUB_DISK_SECTOR_SIZE - 1));
+       }
+      else
+       sector -= p->length;
+    }
+
+  return ret;
+}
+
+struct grub_fs grub_fs_blocklist =
+  {
+    .name = "blocklist",
+    .dir = 0,
+    .open = grub_fs_blocklist_open,
+    .read = grub_fs_blocklist_read,
+    .close = 0,
+    .next = 0
+  };
diff --git a/kern/generic/millisleep.c b/kern/generic/millisleep.c
new file mode 100644 (file)
index 0000000..20d883d
--- /dev/null
@@ -0,0 +1,39 @@
+/* millisleep.c - generic millisleep function.
+ * The generic implementation of these functions can be used for architectures
+ * or platforms that do not have a more specialized implementation. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,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/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/time.h>
+
+void
+grub_millisleep (grub_uint32_t ms)
+{
+  grub_uint64_t start;
+
+  start = grub_get_time_ms ();
+
+  /* Instead of setting an end time and looping while the current time is 
+     less than that, comparing the elapsed sleep time with the desired sleep
+     time handles the (unlikely!) case that the timer would wrap around 
+     during the sleep. */
+
+  while (grub_get_time_ms () - start < ms)
+    grub_cpu_idle ();
+}
diff --git a/kern/generic/rtc_get_time_ms.c b/kern/generic/rtc_get_time_ms.c
new file mode 100644 (file)
index 0000000..74979e7
--- /dev/null
@@ -0,0 +1,37 @@
+/* rtc_get_time_ms.c - get_time_ms implementation using platform RTC.
+ * The generic implementation of these functions can be used for architectures
+ * or platforms that do not have a more specialized implementation. */
+/*
+ *  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/time.h>
+#include <grub/misc.h>
+
+/* Calculate the time in milliseconds since the epoch based on the RTC. */
+grub_uint64_t
+grub_rtc_get_time_ms (void)
+{
+  /* By dimensional analysis: 
+    
+      1000 ms   N rtc ticks       1 s
+      ------- * ----------- * ----------- = 1000*N/T ms
+        1 s          1        T rtc ticks
+   */
+  grub_uint64_t ticks_ms_per_sec = ((grub_uint64_t) 1000) * grub_get_rtc ();
+  return grub_divmod64 (ticks_ms_per_sec, GRUB_TICKS_PER_SECOND, 0);
+}
diff --git a/kern/i386/coreboot/init.c b/kern/i386/coreboot/init.c
new file mode 100644 (file)
index 0000000..9978d4a
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,2005,2006,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/>.
+ */
+
+#include <grub/kernel.h>
+#include <grub/mm.h>
+#include <grub/machine/time.h>
+#include <grub/machine/init.h>
+#include <grub/machine/memory.h>
+#include <grub/machine/console.h>
+#include <grub/machine/kernel.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/loader.h>
+#include <grub/env.h>
+#include <grub/cache.h>
+#include <grub/time.h>
+#include <grub/symbol.h>
+#include <grub/cpu/io.h>
+#include <grub/cpu/kernel.h>
+
+#define GRUB_FLOPPY_REG_DIGITAL_OUTPUT         0x3f2
+
+extern char _start[];
+extern char _end[];
+
+grub_addr_t grub_os_area_addr;
+grub_size_t grub_os_area_size;
+
+grub_uint32_t
+grub_get_rtc (void)
+{
+  grub_fatal ("grub_get_rtc() is not implemented.\n");
+}
+
+/* Stop the floppy drive from spinning, so that other software is
+   jumped to with a known state.  */
+void
+grub_stop_floppy (void)
+{
+  grub_outb (0, GRUB_FLOPPY_REG_DIGITAL_OUTPUT);
+}
+
+void
+grub_exit (void)
+{
+  grub_fatal ("grub_exit() is not implemented.\n");
+}
+
+void
+grub_arch_sync_caches (void *address __attribute__ ((unused)),
+                      grub_size_t len __attribute__ ((unused)))
+{
+}
+
+void
+grub_machine_init (void)
+{
+  /* Initialize the console as early as possible.  */
+  grub_vga_text_init ();
+  grub_at_keyboard_init ();
+
+  auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
+  {
+#if GRUB_CPU_SIZEOF_VOID_P == 4
+    /* Restrict ourselves to 32-bit memory space.  */
+    if (addr > ULONG_MAX)
+      {
+       grub_upper_mem = ULONG_MAX;
+       return 0;
+      }
+    if (addr + size > ULONG_MAX)
+      size = ULONG_MAX - addr;
+#endif
+
+    grub_upper_mem = grub_max (grub_upper_mem, addr + size);
+
+    if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
+      return 0;
+
+    /* Avoid the lower memory.  */
+    if (addr < GRUB_MEMORY_MACHINE_LOWER_SIZE)
+      {
+       if (addr + size <= GRUB_MEMORY_MACHINE_LOWER_SIZE)
+         return 0;
+       else
+         {
+           size -= GRUB_MEMORY_MACHINE_LOWER_SIZE - addr;
+           addr = GRUB_MEMORY_MACHINE_LOWER_SIZE;
+         }
+      }
+
+    if (addr == GRUB_MEMORY_MACHINE_UPPER_START
+       || (addr >= GRUB_MEMORY_MACHINE_LOWER_SIZE
+           && addr <= GRUB_MEMORY_MACHINE_UPPER_START
+           && (addr + size > GRUB_MEMORY_MACHINE_UPPER_START)))
+      {
+       grub_size_t quarter = size >> 2;
+
+       grub_os_area_addr = addr;
+       grub_os_area_size = size - quarter;
+       grub_mm_init_region ((void *) (grub_os_area_addr + grub_os_area_size),
+                            quarter);
+      }
+    else
+      grub_mm_init_region ((void *) (grub_addr_t) addr, (grub_size_t) size);
+
+    return 0;
+  }
+
+  grub_machine_mmap_init ();
+  grub_machine_mmap_iterate (heap_init);
+
+  /* This variable indicates size, not offset.  */
+  grub_upper_mem -= GRUB_MEMORY_MACHINE_UPPER_START;
+
+  grub_tsc_init ();
+}
+
+void
+grub_machine_set_prefix (void)
+{
+  /* Initialize the prefix.  */
+  grub_env_set ("prefix", grub_prefix);
+}
+
+void
+grub_machine_fini (void)
+{
+  grub_at_keyboard_fini ();
+  grub_vga_text_fini ();
+}
+
+/* Return the end of the core image.  */
+grub_addr_t
+grub_arch_modules_addr (void)
+{
+  return ALIGN_UP((grub_addr_t) _end, GRUB_MOD_ALIGN);
+}
diff --git a/kern/i386/coreboot/mmap.c b/kern/i386/coreboot/mmap.c
new file mode 100644 (file)
index 0000000..b15369e
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ *  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/>.
+ */
+
+#include <grub/machine/memory.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+
+static grub_err_t
+grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t))
+{
+  grub_linuxbios_table_header_t table_header;
+  grub_linuxbios_table_item_t table_item;
+
+  auto int check_signature (grub_linuxbios_table_header_t);
+  int check_signature (grub_linuxbios_table_header_t tbl_header)
+  {
+    if (! grub_memcmp (tbl_header->signature, "LBIO", 4))
+      return 1;
+
+    return 0;
+  }
+
+  /* Assuming table_header is aligned to its size (8 bytes).  */
+
+  for (table_header = (grub_linuxbios_table_header_t) 0x500;
+       table_header < (grub_linuxbios_table_header_t) 0x1000; table_header++)
+    if (check_signature (table_header))
+      goto signature_found;
+
+  for (table_header = (grub_linuxbios_table_header_t) 0xf0000;
+       table_header < (grub_linuxbios_table_header_t) 0x100000; table_header++)
+    if (check_signature (table_header))
+      goto signature_found;
+
+  grub_fatal ("Could not find coreboot table\n");
+
+signature_found:
+
+  table_item =
+    (grub_linuxbios_table_item_t) ((long) table_header +
+                              (long) table_header->size);
+  for (; table_item->size;
+       table_item = (grub_linuxbios_table_item_t) ((long) table_item + (long) table_item->size))
+    if (hook (table_item))
+      return 1;
+
+  return 0;
+}
+
+void
+grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
+{
+  mem_region_t mem_region;
+
+  auto int iterate_linuxbios_table (grub_linuxbios_table_item_t);
+  int iterate_linuxbios_table (grub_linuxbios_table_item_t table_item)
+  {
+    if (table_item->tag != GRUB_LINUXBIOS_MEMBER_MEMORY)
+      return 0;
+
+    mem_region =
+      (mem_region_t) ((long) table_item +
+                                sizeof (struct grub_linuxbios_table_item));
+    while ((long) mem_region < (long) table_item + (long) table_item->size)
+      {
+       if (hook (mem_region->addr, mem_region->size,
+                 /* Multiboot mmaps match with the coreboot mmap definition.
+                    Therefore, we can just pass type through.  */
+                 mem_region->type))
+         return 1;
+
+       mem_region++;
+      }
+
+    return 0;
+  }
+
+  grub_linuxbios_table_iterate (iterate_linuxbios_table);
+
+  return 0;
+}
diff --git a/kern/i386/coreboot/startup.S b/kern/i386/coreboot/startup.S
new file mode 100644 (file)
index 0000000..835978b
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2005,2006,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/>.
+ */
+
+#define ASM_FILE       1
+
+#include <grub/symbol.h>
+#include <grub/machine/memory.h>
+#include <grub/cpu/linux.h>
+#include <grub/cpu/kernel.h>
+#include <multiboot.h>
+#include <multiboot2.h>
+
+/*
+ * Note: GRUB is compiled with the options -mrtd and -mregparm=3.
+ *       So the first three arguments are passed in %eax, %edx, and %ecx,
+ *       respectively, and if a function has a fixed number of arguments
+ *       and the number if greater than three, the function must return
+ *       with "ret $N" where N is ((the number of arguments) - 3) * 4.
+ */
+
+       .file   "startup.S"
+       .text
+       .globl  start, _start
+start:
+_start:
+       jmp codestart
+
+       /*
+        *  This is a special data area at a fixed offset from the beginning.
+        */
+
+       . = EXT_C(start) + GRUB_KERNEL_CPU_PREFIX
+
+VARIABLE(grub_prefix)
+       /* to be filled by grub-mkimage */
+
+       /*
+        *  Leave some breathing room for the prefix.
+        */
+
+       . = EXT_C(start) + GRUB_KERNEL_CPU_DATA_END
+
+/*
+ *  Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
+ */
+       .p2align        2       /* force 4-byte alignment */
+multiboot_header:
+       /* magic */
+       .long   0x1BADB002
+       /* flags */
+       .long   MULTIBOOT_MEMORY_INFO
+       /* checksum */
+       .long   -0x1BADB002 - MULTIBOOT_MEMORY_INFO
+
+codestart:
+       cmpl    $MULTIBOOT_MAGIC2, %eax
+       jne 0f
+       movl    %ebx, EXT_C(startup_multiboot_info)
+0:
+
+       /* initialize the stack */
+       movl $GRUB_MEMORY_MACHINE_PROT_STACK, %esp
+
+       /* jump to the main body of C code */
+       jmp EXT_C(grub_main)
+
+/*
+ *  This call is special...  it never returns...  in fact it should simply
+ *  hang at this point!
+ */
+FUNCTION(grub_stop)
+       hlt
+       jmp EXT_C(grub_stop)
+
+/*
+ *  prot_to_real and associated structures (but NOT real_to_prot, that is
+ *  only needed for BIOS gates).
+ */
+#include "../realmode.S"
+
+/*
+ *  Routines needed by Linux and Multiboot loaders.
+ */
+#include "../loader.S"
diff --git a/kern/i386/dl.c b/kern/i386/dl.c
new file mode 100644 (file)
index 0000000..e9e43e5
--- /dev/null
@@ -0,0 +1,111 @@
+/* dl-386.c - arch-dependent part of loadable module support */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+
+/* Check if EHDR is a valid ELF header.  */
+grub_err_t
+grub_arch_dl_check_header (void *ehdr)
+{
+  Elf32_Ehdr *e = ehdr;
+
+  /* Check the magic numbers.  */
+  if (e->e_ident[EI_CLASS] != ELFCLASS32
+      || e->e_ident[EI_DATA] != ELFDATA2LSB
+      || e->e_machine != EM_386)
+    return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic");
+
+  return GRUB_ERR_NONE;
+}
+
+/* Relocate symbols.  */
+grub_err_t
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
+{
+  Elf32_Ehdr *e = ehdr;
+  Elf32_Shdr *s;
+  Elf32_Sym *symtab;
+  Elf32_Word entsize;
+  unsigned i;
+
+  /* Find a symbol table.  */
+  for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf32_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");
+  
+  symtab = (Elf32_Sym *) ((char *) e + s->sh_offset);
+  entsize = s->sh_entsize;
+
+  for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_REL)
+      {
+       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)
+         {
+           Elf32_Rel *rel, *max;
+           
+           for (rel = (Elf32_Rel *) ((char *) e + s->sh_offset),
+                  max = rel + s->sh_size / s->sh_entsize;
+                rel < max;
+                rel++)
+             {
+               Elf32_Word *addr;
+               Elf32_Sym *sym;
+               
+               if (seg->size < rel->r_offset)
+                 return grub_error (GRUB_ERR_BAD_MODULE,
+                                    "reloc offset is out of the segment");
+               
+               addr = (Elf32_Word *) ((char *) seg->addr + rel->r_offset);
+               sym = (Elf32_Sym *) ((char *) symtab
+                                    + entsize * ELF32_R_SYM (rel->r_info));
+               
+               switch (ELF32_R_TYPE (rel->r_info))
+                 {
+                 case R_386_32:
+                   *addr += sym->st_value;
+                   break;
+
+                 case R_386_PC32:
+                   *addr += (sym->st_value - (Elf32_Word) seg->addr
+                             - rel->r_offset);
+                   break;
+                 }
+             }
+         }
+      }
+
+  return GRUB_ERR_NONE;
+}
diff --git a/kern/i386/efi/init.c b/kern/i386/efi/init.c
new file mode 100644 (file)
index 0000000..e1950d7
--- /dev/null
@@ -0,0 +1,53 @@
+/* init.c - initialize an x86-based EFI system */
+/*
+ *  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/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/cache.h>
+#include <grub/kernel.h>
+#include <grub/efi/efi.h>
+#include <grub/i386/tsc.h>
+
+void
+grub_machine_init (void)
+{
+  grub_efi_init ();
+  grub_tsc_init ();
+}
+
+void
+grub_machine_fini (void)
+{
+  grub_efi_fini ();
+}
+
+void
+grub_machine_set_prefix (void)
+{
+  grub_efi_set_prefix ();
+}
+
+void
+grub_arch_sync_caches (void *address __attribute__ ((unused)),
+                       grub_size_t len __attribute__ ((unused)))
+{
+}
diff --git a/kern/i386/efi/startup.S b/kern/i386/efi/startup.S
new file mode 100644 (file)
index 0000000..4709b3f
--- /dev/null
@@ -0,0 +1,64 @@
+/* startup.S - bootstrap GRUB itself */
+/*
+ *  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/>.
+ */
+
+#include <config.h>
+#include <grub/symbol.h>
+#include <grub/boot.h>
+
+        .file   "startup.S"
+        .text
+        .globl  start, _start
+start:
+_start:
+       jmp codestart
+
+        /*
+         *  Compatibility version number
+         *
+         *  These MUST be at byte offset 6 and 7 of the executable
+         *  DO NOT MOVE !!!
+         */
+        . = EXT_C(start) + 0x6
+        .byte   GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
+
+        /*
+         *  This is a special data area 8 bytes from the beginning.
+         */
+
+        . = EXT_C(start) + 0x8
+
+VARIABLE(grub_prefix)
+       /* to be filled by grub-mkimage */
+
+        /*
+         *  Leave some breathing room for the prefix.
+         */
+
+        . = EXT_C(start) + 0x50
+
+codestart:
+       /*
+        *  EFI_SYSTEM_TABLE * and EFI_HANDLE are passed on the stack.
+        */
+       movl    4(%esp), %eax
+       movl    %eax, EXT_C(grub_efi_image_handle)
+       movl    8(%esp), %eax
+       movl    %eax, EXT_C(grub_efi_system_table)
+       call    EXT_C(grub_main)
+       ret
diff --git a/kern/i386/halt.c b/kern/i386/halt.c
new file mode 100644 (file)
index 0000000..3895ae1
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  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/cpu/io.h>
+#include <grub/cpu/halt.h>
+#include <grub/misc.h>
+
+const char bochs_shutdown[] = "Shutdown";
+
+void
+grub_halt (void)
+{
+  int i;
+
+  /* Disable interrupts.  */
+  __asm__ __volatile__ ("cli");
+
+  /* Bochs, QEMU, etc.  */
+  for (i = 0; i < sizeof (bochs_shutdown) - 1; i++)
+    grub_outb (bochs_shutdown[i], 0x8900);
+
+  grub_printf ("GRUB doesn't know how to halt this machine yet!\n");
+
+  /* In order to return we'd have to check what the previous status of IF
+     flag was.  But user most likely doesn't want to return anyway ...  */
+  grub_stop ();
+}
diff --git a/kern/i386/ieee1275/init.c b/kern/i386/ieee1275/init.c
new file mode 100644 (file)
index 0000000..066373e
--- /dev/null
@@ -0,0 +1,32 @@
+/*  init.c -- Initialize GRUB on Open Firmware.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,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/>.
+ */
+
+#include <grub/types.h>
+#include <grub/cache.h>
+
+void
+grub_stop_floppy (void)
+{
+}
+
+void 
+grub_arch_sync_caches (void *address __attribute__ ((unused)),
+                      grub_size_t len __attribute__ ((unused)))
+{
+}
diff --git a/kern/i386/ieee1275/startup.S b/kern/i386/ieee1275/startup.S
new file mode 100644 (file)
index 0000000..db6ce1e
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2005,2006,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/>.
+ */
+
+#define ASM_FILE       1
+
+#include <grub/symbol.h>
+#include <grub/machine/memory.h>
+#include <grub/cpu/linux.h>
+#include <grub/cpu/kernel.h>
+#include <multiboot.h>
+#include <multiboot2.h>
+
+/*
+ * Note: GRUB is compiled with the options -mrtd and -mregparm=3.
+ *       So the first three arguments are passed in %eax, %edx, and %ecx,
+ *       respectively, and if a function has a fixed number of arguments
+ *       and the number if greater than three, the function must return
+ *       with "ret $N" where N is ((the number of arguments) - 3) * 4.
+ */
+
+       .file   "startup.S"
+       .text
+       .globl  start, _start
+
+start:
+_start:
+       jmp codestart
+
+       /*
+        *  This is a special data area at a fixed offset from the beginning.
+        */
+
+       . = EXT_C(start) + GRUB_KERNEL_CPU_PREFIX
+
+VARIABLE(grub_prefix)
+       /* to be filled by grub-mkimage */
+
+       /*
+        *  Leave some breathing room for the prefix.
+        */
+
+       . = EXT_C(start) + GRUB_KERNEL_CPU_DATA_END
+
+codestart:
+       movl %eax, EXT_C(grub_ieee1275_entry_fn)
+       jmp EXT_C(grub_main)
+
+/*
+ *  This call is special...  it never returns...  in fact it should simply
+ *  hang at this point!
+ */
+FUNCTION(grub_stop)
+       hlt
+       jmp EXT_C(grub_stop)
+
+/*
+ *  prot_to_real and associated structures (but NOT real_to_prot, that is
+ *  only needed for BIOS gates).
+ */
+#include "../realmode.S"
+
+/*
+ *  Routines needed by Linux and Multiboot loaders.
+ */
+#include "../loader.S"
diff --git a/kern/i386/loader.S b/kern/i386/loader.S
new file mode 100644 (file)
index 0000000..cacbbea
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2005,2006,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/>.
+ */
+
+
+/*
+ * Note: These functions defined in this file may be called from C.
+ *       Be careful of that you must not modify some registers. Quote
+ *       from gcc-2.95.2/gcc/config/i386/i386.h:
+
+   1 for registers not available across function calls.
+   These must include the FIXED_REGISTERS and also any
+   registers that can be used without being saved.
+   The latter must include the registers where values are returned
+   and the register where structure-value addresses are passed.
+   Aside from that, you can include as many other registers as you like.
+
+  ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg
+{  1, 1, 1, 0, 0, 0, 0, 1, 1,  1,  1,  1,  1,  1,  1,  1,  1 }
+ */
+
+/*
+ * Note: GRUB is compiled with the options -mrtd and -mregparm=3.
+ *       So the first three arguments are passed in %eax, %edx, and %ecx,
+ *       respectively, and if a function has a fixed number of arguments
+ *       and the number if greater than three, the function must return
+ *       with "ret $N" where N is ((the number of arguments) - 3) * 4.
+ */
+
+/*
+ *  This is the area for all of the special variables.
+ */
+
+       .p2align        2       /* force 4-byte alignment */
+
+/*
+ * void grub_linux_boot_zimage (void)
+ */
+VARIABLE(grub_linux_prot_size)
+       .long   0
+VARIABLE(grub_linux_tmp_addr)
+       .long   0
+VARIABLE(grub_linux_real_addr)
+       .long   0
+VARIABLE(grub_linux_is_bzimage)
+       .long   0
+
+FUNCTION(grub_linux_boot)
+       /* Must be done before zImage copy.  */
+       call    EXT_C(grub_dl_unload_all)
+
+       movl    EXT_C(grub_linux_is_bzimage), %ebx
+       test    %ebx, %ebx
+       jne bzimage
+
+       /* copy the kernel */
+       movl    EXT_C(grub_linux_prot_size), %ecx
+       addl    $3, %ecx
+       shrl    $2, %ecx
+       movl    $GRUB_LINUX_BZIMAGE_ADDR, %esi
+       movl    $GRUB_LINUX_ZIMAGE_ADDR, %edi
+       cld
+       rep
+       movsl
+
+bzimage:
+       movl    EXT_C(grub_linux_real_addr), %ebx
+
+       /* copy the real mode code */
+       movl    EXT_C(grub_linux_tmp_addr), %esi
+       movl    %ebx, %edi
+       movl    $GRUB_LINUX_SETUP_MOVE_SIZE, %ecx
+       cld
+       rep
+       movsb
+
+       /* change %ebx to the segment address */
+       shrl    $4, %ebx
+       movl    %ebx, %eax
+       addl    $0x20, %eax
+       movw    %ax, linux_setup_seg
+
+       /* XXX new stack pointer in safe area for calling functions */
+       movl    $0x4000, %esp
+       call    EXT_C(grub_stop_floppy)
+
+       /* final setup for linux boot */
+       call    prot_to_real
+       .code16
+
+       cli
+       movw    %bx, %ss
+       movw    $GRUB_LINUX_SETUP_STACK, %sp
+
+       movw    %bx, %ds
+       movw    %bx, %es
+       movw    %bx, %fs
+       movw    %bx, %gs
+
+       /* ljmp */
+       .byte   0xea
+       .word   0
+linux_setup_seg:
+       .word   0
+       .code32
+
+
+/*
+ * This starts the multiboot kernel.
+ */
+
+VARIABLE(grub_multiboot_payload_size)
+       .long   0
+VARIABLE(grub_multiboot_payload_orig)
+       .long   0
+VARIABLE(grub_multiboot_payload_dest)
+       .long   0
+VARIABLE(grub_multiboot_payload_entry_offset)
+       .long   0
+
+/*
+ * The relocators below understand the following parameters:
+ * ecx:        Size of the block to be copied.
+ * esi:        Where to copy from (always lowest address, even if we're relocating
+ *      backwards).
+ * edi:        Where to copy to (likewise).
+ * edx:        Offset of the entry point (relative to the beginning of the block).
+ */
+VARIABLE(grub_multiboot_forward_relocator)
+       /* Add entry offset.  */
+       addl    %edi, %edx
+
+       /* Forward copy.  */
+       cld
+       rep
+       movsb
+
+       jmp     *%edx
+VARIABLE(grub_multiboot_forward_relocator_end)
+
+VARIABLE(grub_multiboot_backward_relocator)
+       /* Add entry offset (before %edi is mangled).  */
+       addl    %edi, %edx
+
+       /* Backward movsb is implicitly off-by-one.  compensate that.  */
+       decl    %esi
+       decl    %edi
+
+       /* Backward copy.  */
+       std
+       addl    %ecx, %esi
+       addl    %ecx, %edi
+       rep
+       movsb
+
+       jmp     *%edx
+VARIABLE(grub_multiboot_backward_relocator_end)
+
+FUNCTION(grub_multiboot_real_boot)
+       /* Push the entry address on the stack.  */
+       pushl   %eax
+       /* Move the address of the multiboot information structure to ebx.  */
+       movl    %edx,%ebx
+
+       /* Unload all modules and stop the floppy driver.  */
+       call    EXT_C(grub_dl_unload_all)
+       call    EXT_C(grub_stop_floppy)
+
+       /* Interrupts should be disabled.  */
+       cli
+
+       /* Where do we copy what from.  */
+       movl    EXT_C(grub_multiboot_payload_size), %ecx
+       movl    EXT_C(grub_multiboot_payload_orig), %esi
+       movl    EXT_C(grub_multiboot_payload_dest), %edi
+       movl    EXT_C(grub_multiboot_payload_entry_offset), %edx
+
+       /* Move the magic value into eax.  */
+       movl    $MULTIBOOT_MAGIC2, %eax
+                               
+       /* Jump to the relocator.  */
+       popl    %ebp
+       jmp     *%ebp
+       
+/*
+ * This starts the multiboot 2 kernel.
+ */
+
+FUNCTION(grub_multiboot2_real_boot)
+        /* Push the entry address on the stack.  */
+        pushl   %eax
+        /* Move the address of the multiboot information structure to ebx.  */
+        movl    %edx,%ebx
+
+        /* Unload all modules and stop the floppy driver.  */
+        call    EXT_C(grub_dl_unload_all)
+        call    EXT_C(grub_stop_floppy)
+
+        /* Interrupts should be disabled.  */
+        cli
+
+        /* Move the magic value into eax and jump to the kernel.  */
+        movl    $MULTIBOOT2_BOOTLOADER_MAGIC,%eax
+        popl    %ecx
+        jmp     *%ecx
+
+/*
+ * Use cdecl calling convention for *BSD kernels.
+ */
+
+FUNCTION(grub_unix_real_boot)
+
+        call    EXT_C(grub_dl_unload_all)
+        call    EXT_C(grub_stop_floppy)
+
+       /* Interrupts should be disabled.  */
+        cli
+
+       /* Discard `grub_unix_real_boot' return address.  */
+        popl    %eax
+
+        /* Fetch `entry' address ...  */
+        popl   %eax
+
+        /*
+         * ... and put our return address in its place. The kernel will
+         * ignore it, but it expects %esp to point to it.
+         */
+        call   *%eax
diff --git a/kern/i386/multiboot_mmap.c b/kern/i386/multiboot_mmap.c
new file mode 100644 (file)
index 0000000..8331bd5
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,2005,2006,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/>.
+ */
+
+#include <grub/machine/init.h>
+#include <grub/machine/memory.h>
+#include <grub/types.h>
+#include <grub/multiboot.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+
+grub_size_t grub_lower_mem, grub_upper_mem;
+
+/* A pointer to the MBI in its initial location.  */
+struct grub_multiboot_info *startup_multiboot_info;
+
+/* The MBI has to be copied to our BSS so that it won't be
+   overwritten.  This is its final location.  */
+static struct grub_multiboot_info kern_multiboot_info;
+
+/* Unfortunately we can't use heap at this point.  But 32 looks like a sane
+   limit (used by memtest86).  */
+static grub_uint8_t mmap_entries[sizeof (struct grub_multiboot_mmap_entry) * 32];
+
+void
+grub_machine_mmap_init ()
+{
+  if (! startup_multiboot_info)
+    grub_fatal ("Must be loaded using Multiboot specification (is this an old version of coreboot?)");
+
+  /* Move MBI to a safe place.  */
+  grub_memmove (&kern_multiboot_info, startup_multiboot_info, sizeof (struct grub_multiboot_info));
+
+  if ((kern_multiboot_info.flags & MULTIBOOT_INFO_MEM_MAP) == 0)
+    grub_fatal ("Missing Multiboot memory information");
+
+  /* Move the memory map to a safe place.  */
+  if (kern_multiboot_info.mmap_length > sizeof (mmap_entries))
+    {
+      grub_printf ("WARNING: Memory map size exceeds limit; it will be truncated\n");
+      kern_multiboot_info.mmap_length = sizeof (mmap_entries);
+    }
+  grub_memmove (mmap_entries, (void *) kern_multiboot_info.mmap_addr, kern_multiboot_info.mmap_length);
+  kern_multiboot_info.mmap_addr = (grub_uint32_t) mmap_entries;
+
+  if ((kern_multiboot_info.flags & MULTIBOOT_INFO_MEMORY) == 0)
+    {
+      grub_lower_mem = GRUB_MEMORY_MACHINE_LOWER_USABLE;
+      grub_upper_mem = 0;
+    }
+  else
+    {
+      grub_lower_mem = kern_multiboot_info.mem_lower * 1024;
+      grub_upper_mem = kern_multiboot_info.mem_upper * 1024;
+    }
+}
+
+grub_err_t
+grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
+{
+  struct grub_multiboot_mmap_entry *entry = (void *) kern_multiboot_info.mmap_addr;
+
+  while ((unsigned long) entry < kern_multiboot_info.mmap_addr + kern_multiboot_info.mmap_length)
+    {
+      if (hook (entry->addr, entry->len, entry->type))
+       break;
+
+      entry = (void *) ((grub_addr_t) entry + entry->size + sizeof (entry->size));
+    }
+
+  return 0;
+}
diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c
new file mode 100644 (file)
index 0000000..c604e93
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,2005,2006,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/>.
+ */
+
+#include <grub/kernel.h>
+#include <grub/mm.h>
+#include <grub/machine/init.h>
+#include <grub/machine/memory.h>
+#include <grub/machine/console.h>
+#include <grub/machine/kernel.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/loader.h>
+#include <grub/env.h>
+#include <grub/cache.h>
+#include <grub/time.h>
+#include <grub/cpu/tsc.h>
+
+struct mem_region
+{
+  grub_addr_t addr;
+  grub_size_t size;
+};
+
+#define MAX_REGIONS    32
+
+static struct mem_region mem_regions[MAX_REGIONS];
+static int num_regions;
+
+grub_addr_t grub_os_area_addr;
+grub_size_t grub_os_area_size;
+grub_size_t grub_lower_mem, grub_upper_mem;
+
+void 
+grub_arch_sync_caches (void *address __attribute__ ((unused)),
+                      grub_size_t len __attribute__ ((unused)))
+{
+}
+
+static char *
+make_install_device (void)
+{
+  /* XXX: This should be enough.  */
+  char dev[100];
+
+  if (grub_prefix[0] != '(')
+    {
+      /* If the root drive is not set explicitly, assume that it is identical
+         to the boot drive.  */
+      if (grub_root_drive == 0xFF)
+        grub_root_drive = grub_boot_drive;
+      
+      grub_sprintf (dev, "(%cd%u", (grub_root_drive & 0x80) ? 'h' : 'f',
+                    grub_root_drive & 0x7f);
+      
+      if (grub_install_dos_part >= 0)
+       grub_sprintf (dev + grub_strlen (dev), ",%u", grub_install_dos_part + 1);
+      
+      if (grub_install_bsd_part >= 0)
+       grub_sprintf (dev + grub_strlen (dev), ",%c", grub_install_bsd_part + 'a');
+      
+      grub_sprintf (dev + grub_strlen (dev), ")%s", grub_prefix);
+      grub_strcpy (grub_prefix, dev);
+    }
+      
+  return grub_prefix;
+}
+
+/* Add a memory region.  */
+static void
+add_mem_region (grub_addr_t addr, grub_size_t size)
+{
+  if (num_regions == MAX_REGIONS)
+    /* Ignore.  */
+    return;
+
+  mem_regions[num_regions].addr = addr;
+  mem_regions[num_regions].size = size;
+  num_regions++;
+}
+
+/* Compact memory regions.  */
+static void
+compact_mem_regions (void)
+{
+  int i, j;
+
+  /* Sort them.  */
+  for (i = 0; i < num_regions - 1; i++)
+    for (j = i + 1; j < num_regions; j++)
+      if (mem_regions[i].addr > mem_regions[j].addr)
+       {
+         struct mem_region tmp = mem_regions[i];
+         mem_regions[i] = mem_regions[j];
+         mem_regions[j] = tmp;
+       }
+
+  /* Merge overlaps.  */
+  for (i = 0; i < num_regions - 1; i++)
+    if (mem_regions[i].addr + mem_regions[i].size >= mem_regions[i + 1].addr)
+      {
+       j = i + 1;
+       
+       if (mem_regions[i].addr + mem_regions[i].size
+           < mem_regions[j].addr + mem_regions[j].size)
+         mem_regions[i].size = (mem_regions[j].addr + mem_regions[j].size
+                                - mem_regions[i].addr);
+
+       grub_memmove (mem_regions + j, mem_regions + j + 1,
+                     (num_regions - j - 1) * sizeof (struct mem_region));
+       i--;
+        num_regions--;
+      }
+}
+
+void
+grub_machine_init (void)
+{
+  int i;
+  
+  /* Initialize the console as early as possible.  */
+  grub_console_init ();
+  
+  grub_lower_mem = grub_get_memsize (0) << 10;
+  
+  /* Sanity check.  */
+  if (grub_lower_mem < GRUB_MEMORY_MACHINE_RESERVED_END)
+    grub_fatal ("too small memory");
+
+#if 0
+  /* Turn on Gate A20 to access >1MB.  */
+  grub_gate_a20 (1);
+#endif
+
+  /* Add the lower memory into free memory.  */
+  if (grub_lower_mem >= GRUB_MEMORY_MACHINE_RESERVED_END)
+    add_mem_region (GRUB_MEMORY_MACHINE_RESERVED_END,
+                   grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END);
+  
+  auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
+    {
+      /* Avoid the lower memory.  */
+      if (addr < 0x100000)
+       {
+         if (size <= 0x100000 - addr)
+           return 0;
+         
+         size -= 0x100000 - addr;
+         addr = 0x100000;
+       }
+       
+      /* Ignore >4GB.  */
+      if (addr <= 0xFFFFFFFF && type == GRUB_MACHINE_MEMORY_AVAILABLE)
+       {
+         grub_size_t len;
+         
+         len = (grub_size_t) ((addr + size > 0xFFFFFFFF)
+                ? 0xFFFFFFFF - addr
+                : size);
+         add_mem_region (addr, len);
+       }
+
+      return 0;
+    }
+
+  grub_machine_mmap_iterate (hook);
+  
+  compact_mem_regions ();
+
+  /* Add the memory regions to free memory, except for the region starting
+     from 1MB. This region is partially used for loading OS images.
+     For now, 1/4 of this is added to free memory.  */
+  for (i = 0; i < num_regions; i++)
+    if (mem_regions[i].addr == 0x100000)
+      {
+       grub_size_t quarter = mem_regions[i].size >> 2;
+
+       grub_upper_mem = mem_regions[i].size;
+       grub_os_area_addr = mem_regions[i].addr;
+       grub_os_area_size = mem_regions[i].size - quarter;
+       grub_mm_init_region ((void *) (grub_os_area_addr + grub_os_area_size),
+                            quarter);
+      }
+    else
+      grub_mm_init_region ((void *) mem_regions[i].addr, mem_regions[i].size);
+  
+  if (! grub_os_area_addr)
+    grub_fatal ("no upper memory");
+
+  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 ();
+}
+
+/* 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);
+}
diff --git a/kern/i386/pc/lzma_decode.S b/kern/i386/pc/lzma_decode.S
new file mode 100644 (file)
index 0000000..a5a8684
--- /dev/null
@@ -0,0 +1,677 @@
+/*
+ *  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/>.
+ */
+
+#define FIXED_PROPS
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+#define kNumTopBits 24
+#define kTopValue (1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+
+#if 0
+
+DbgOut:
+       pushf
+       pushl   %ebp
+       pushl   %edi
+       pushl   %esi
+       pushl   %edx
+       pushl   %ecx
+       pushl   %ebx
+       pushl   %eax
+
+       call    _DebugPrint
+
+       popl    %eax
+       popl    %ebx
+       popl    %ecx
+       popl    %edx
+       popl    %esi
+       popl    %edi
+       popl    %ebp
+       popf
+
+       ret
+
+
+/*
+ * int LzmaDecodeProperties(CLzmaProperties *propsRes,
+ *                          const unsigned char *propsData,
+ *                          int size);
+ */
+
+_LzmaDecodePropertiesA:
+       movb    (%edx), %dl
+
+       xorl    %ecx, %ecx
+1:
+       cmpb    $45, %dl
+       jb      2f
+       incl    %ecx
+       subb    $45, %dl
+       jmp     1b
+2:
+       movl    %ecx, 8(%eax)           /* pb */
+       xorl    %ecx, %ecx
+1:
+       cmpb    $9, %dl
+       jb      2f
+       incl    %ecx
+       subb    $9, %dl
+2:
+       movl    %ecx, 4(%eax)           /* lp */
+       movb    %dl, %cl
+       movl    %ecx, (%eax)            /* lc */
+
+#endif
+
+#ifndef ASM_FILE
+       xorl    %eax, %eax
+#endif
+       ret
+
+#define out_size       8(%ebp)
+
+#define now_pos                -4(%ebp)
+#define prev_byte      -8(%ebp)
+#define range          -12(%ebp)
+#define code           -16(%ebp)
+#define state          -20(%ebp)
+#define rep0           -24(%ebp)
+#define rep1           -28(%ebp)
+#define rep2           -32(%ebp)
+#define rep3           -36(%ebp)
+
+#ifdef FIXED_PROPS
+
+#define FIXED_LC       3
+#define FIXED_LP       0
+#define FIXED_PB       2
+
+#define POS_STATE_MASK ((1 << (FIXED_PB)) - 1)
+#define LIT_POS_MASK   ((1 << (FIXED_LP)) - 1)
+
+#define LOCAL_SIZE     36
+
+#else
+
+#define lc             (%ebx)
+#define lp             4(%ebx)
+#define pb             8(%ebx)
+#define probs          12(%ebx)
+
+#define pos_state_mask -40(%ebp)
+#define lit_pos_mask   -44(%ebp)
+
+#define LOCAL_SIZE     44
+
+#endif
+
+RangeDecoderBitDecode:
+#ifdef FIXED_PROPS
+       leal    (%ebx, %eax, 4), %eax
+#else
+       shll    $2, %eax
+       addl    probs, %eax
+#endif
+
+       movl    %eax, %ecx
+       movl    (%ecx), %eax
+
+       movl    range, %edx
+       shrl    $kNumBitModelTotalBits, %edx
+       mull    %edx
+
+       cmpl    code, %eax
+       jbe     1f
+
+       movl    %eax, range
+       movl    $kBitModelTotal, %edx
+       subl    (%ecx), %edx
+       shrl    $kNumMoveBits, %edx
+       addl    %edx, (%ecx)
+       clc
+3:
+       pushf
+       cmpl    $kTopValue, range
+       jnc     2f
+       shll    $8, code
+       lodsb
+       movb    %al, code
+       shll    $8, range
+2:
+       popf
+       ret
+1:
+       subl    %eax, range
+       subl    %eax, code
+       movl    (%ecx), %edx
+       shrl    $kNumMoveBits, %edx
+       subl    %edx, (%ecx)
+       stc
+       jmp     3b
+
+RangeDecoderBitTreeDecode:
+RangeDecoderReverseBitTreeDecode:
+       movzbl  %cl, %ecx
+       xorl    %edx, %edx
+       pushl   %edx
+       incl    %edx
+       pushl   %edx
+
+1:
+       pushl   %eax
+       pushl   %ecx
+       pushl   %edx
+
+       addl    %edx, %eax
+       call    RangeDecoderBitDecode
+
+       popl    %edx
+       popl    %ecx
+
+       jnc     2f
+       movl    4(%esp), %eax
+       orl     %eax, 8(%esp)
+       stc
+
+2:
+       adcl    %edx, %edx
+       popl    %eax
+
+       shll    $1, (%esp)
+       loop    1b
+
+       popl    %ecx
+       subl    %ecx, %edx              /* RangeDecoderBitTreeDecode */
+       popl    %ecx                    /* RangeDecoderReverseBitTreeDecode */
+       ret
+
+LzmaLenDecode:
+       pushl   %eax
+       addl    $LenChoice, %eax
+       call    RangeDecoderBitDecode
+       popl    %eax
+       jc      1f
+       pushl   $0
+       movb    $kLenNumLowBits, %cl
+       addl    $LenLow, %eax
+2:
+       movl    12(%esp), %edx
+       shll    %cl, %edx
+       addl    %edx, %eax
+3:
+
+       call    RangeDecoderBitTreeDecode
+       popl    %eax
+       addl    %eax, %edx
+       ret
+
+1:
+       pushl   %eax
+       addl    $LenChoice2, %eax
+       call    RangeDecoderBitDecode
+       popl    %eax
+       jc      1f
+       pushl   $kLenNumLowSymbols
+       movb    $kLenNumMidBits, %cl
+       addl    $LenMid, %eax
+       jmp     2b
+
+1:
+       pushl   $(kLenNumLowSymbols + kLenNumMidSymbols)
+       addl    $LenHigh, %eax
+       movb    $kLenNumHighBits, %cl
+       jmp     3b
+
+WriteByte:
+       movb    %al, prev_byte
+       stosb
+       incl    now_pos
+       ret
+
+/*
+ * int LzmaDecode(CLzmaDecoderState *vs,
+ *                const unsigned char *inStream,
+ *                unsigned char *outStream,
+ *                SizeT outSize);
+ */
+
+_LzmaDecodeA:
+
+       pushl   %ebp
+       movl    %esp, %ebp
+       subl    $LOCAL_SIZE, %esp
+
+#ifndef ASM_FILE
+       pushl   %esi
+       pushl   %edi
+       pushl   %ebx
+
+       movl    %eax, %ebx
+       movl    %edx, %esi
+       pushl   %ecx
+#else
+       pushl   %edi
+#endif
+
+       cld
+
+#ifdef FIXED_PROPS
+       movl    %ebx, %edi
+       movl    $(Literal + (LZMA_LIT_SIZE << (FIXED_LC + FIXED_LP))), %ecx
+#else
+       movl    $LZMA_LIT_SIZE, %eax
+       movb    lc, %cl
+       addb    lp, %cl
+       shll    %cl, %eax
+       addl    $Literal, %eax
+       movl    %eax, %ecx
+       movl    probs, %edi
+#endif
+
+       movl    $(kBitModelTotal >> 1), %eax
+
+       rep
+       stosl
+
+       popl    %edi
+
+       xorl    %eax, %eax
+       movl    %eax, now_pos
+       movl    %eax, prev_byte
+       movl    %eax, state
+
+       incl    %eax
+       movl    %eax, rep0
+       movl    %eax, rep1
+       movl    %eax, rep2
+       movl    %eax, rep3
+
+#ifndef FIXED_PROPS
+       movl    %eax, %edx
+       movb    pb, %cl
+       shll    %cl, %edx
+       decl    %edx
+       movl    %edx, pos_state_mask
+
+       movl    %eax, %edx
+       movb    lp, %cl
+       shll    %cl, %edx
+       decl    %edx
+       movl    %edx, lit_pos_mask;
+#endif
+
+       /* RangeDecoderInit */
+       negl    %eax
+       movl    %eax, range
+
+       incl    %eax
+       movb    $5, %cl
+
+1:
+       shll    $8, %eax
+       lodsb
+       loop    1b
+
+       movl    %eax, code
+
+lzma_decode_loop:
+       movl    now_pos, %eax
+       cmpl    out_size, %eax
+
+       jb      1f
+
+#ifndef ASM_FILE
+       xorl    %eax, %eax
+
+       popl    %ebx
+       popl    %edi
+       popl    %esi
+#endif
+
+       movl    %ebp, %esp
+       popl    %ebp
+       ret
+
+1:
+#ifdef FIXED_PROPS
+       andl    $POS_STATE_MASK, %eax
+#else
+       andl    pos_state_mask, %eax
+#endif
+       pushl   %eax                            /* posState */
+       movl    state, %edx
+       shll    $kNumPosBitsMax, %edx
+       addl    %edx, %eax
+       pushl   %eax                            /* (state << kNumPosBitsMax) + posState */
+
+       call    RangeDecoderBitDecode
+       jc      1f
+
+       movl    now_pos, %eax
+
+#ifdef FIXED_PROPS
+       andl    $LIT_POS_MASK, %eax
+       shll    $FIXED_LC, %eax
+       movl    prev_byte, %edx
+       shrl    $(8 - FIXED_LC), %edx
+#else
+       andl    lit_pos_mask, %eax
+       movb    lc, %cl
+       shll    %cl, %eax
+       negb    %cl
+       addb    $8, %cl
+       movl    prev_byte, %edx
+       shrl    %cl, %edx
+#endif
+
+       addl    %edx, %eax
+       movl    $LZMA_LIT_SIZE, %edx
+       mull    %edx
+       addl    $Literal, %eax
+       pushl   %eax
+
+       incl    %edx                    /* edx = 1 */
+
+       movl    rep0, %eax
+       negl    %eax
+       pushl   (%edi, %eax)            /* matchByte */
+
+       cmpb    $kNumLitStates, state
+       jb      5f
+
+       /* LzmaLiteralDecodeMatch */
+
+3:
+       cmpl    $0x100, %edx
+       jae     4f
+
+       xorl    %eax, %eax
+       shlb    $1, (%esp)
+       adcl    %eax, %eax
+
+       pushl   %eax
+       pushl   %edx
+
+       shll    $8, %eax
+       leal    0x100(%edx, %eax), %eax
+       addl    12(%esp), %eax
+       call    RangeDecoderBitDecode
+
+       setc    %al
+       popl    %edx
+       adcl    %edx, %edx
+
+       popl    %ecx
+       cmpb    %cl, %al
+       jz      3b
+
+5:
+
+       /* LzmaLiteralDecode */
+
+       cmpl    $0x100, %edx
+       jae     4f
+
+       pushl   %edx
+       movl    %edx, %eax
+       addl    8(%esp), %eax
+       call    RangeDecoderBitDecode
+       popl    %edx
+       adcl    %edx, %edx
+       jmp     5b
+
+4:
+       addl    $16, %esp
+
+       movb    %dl, %al
+       call    WriteByte
+
+       movb    state, %al
+       cmpb    $4, %al
+       jae     2f
+       xorb    %al, %al
+       jmp     3f
+2:
+       subb    $3, %al
+       cmpb    $7, %al
+       jb      3f
+       subb    $3, %al
+3:
+       movb    %al, state
+       jmp     lzma_decode_loop
+
+1:
+       movl    state, %eax
+       addl    $IsRep, %eax
+       call    RangeDecoderBitDecode
+       jnc     1f
+
+       movl    state, %eax
+       addl    $IsRepG0, %eax
+       call    RangeDecoderBitDecode
+       jc      10f
+
+       movl    (%esp), %eax
+       addl    $IsRep0Long, %eax
+       call    RangeDecoderBitDecode
+       jc      20f
+
+       cmpb    $7, state
+       movb    $9, state
+       jb      100f
+       addb    $2, state
+100:
+
+       movl    $1, %ecx
+
+3:
+       movl    rep0, %edx
+       negl    %edx
+
+4:
+       movb    (%edi, %edx), %al
+       call    WriteByte
+       loop    4b
+
+       popl    %eax
+       popl    %eax
+       jmp     lzma_decode_loop
+
+10:
+       movl    state, %eax
+       addl    $IsRepG1, %eax
+       call    RangeDecoderBitDecode
+       movl    rep1, %edx
+       jnc     100f
+
+       movl    state, %eax
+       addl    $IsRepG2, %eax
+       call    RangeDecoderBitDecode
+       movl    rep2, %edx
+       jnc     1000f
+       movl    rep2, %edx
+       xchgl   rep3, %edx
+1000:
+       pushl   rep1
+       popl    rep2
+100:
+       xchg    rep0, %edx
+       movl    %edx, rep1
+20:
+
+       movl    $RepLenCoder, %eax
+       call    LzmaLenDecode
+
+       cmpb    $7, state
+       movb    $8, state
+       jb      100f
+       addb    $3, state
+100:
+       jmp     2f
+
+1:
+       movl    rep0, %eax
+       xchgl   rep1, %eax
+       xchgl   rep2, %eax
+       movl    %eax, rep3
+
+       cmpb    $7, state
+       movb    $7, state
+       jb      10f
+       addb    $3, state
+10:
+
+       movl    $LenCoder, %eax
+       call    LzmaLenDecode
+       pushl   %edx
+
+       movl    $(kNumLenToPosStates - 1), %eax
+       cmpl    %eax, %edx
+       jbe     100f
+       movl    %eax, %edx
+100:
+       movb    $kNumPosSlotBits, %cl
+       shll    %cl, %edx
+       leal    PosSlot(%edx), %eax
+       call    RangeDecoderBitTreeDecode
+
+       movl    %edx, rep0
+       cmpl    $kStartPosModelIndex, %edx
+       jb      100f
+
+       movl    %edx, %ecx
+       shrl    $1, %ecx
+       decl    %ecx
+
+       movzbl  %dl, %eax
+       andb    $1, %al
+       orb     $2, %al
+       shll    %cl, %eax
+       movl    %eax, rep0
+
+       cmpl    $kEndPosModelIndex, %edx
+       jae     200f
+       movl    rep0, %eax
+       addl    $(SpecPos - 1), %eax
+       subl    %edx, %eax
+       jmp     300f
+200:
+
+       subb    $kNumAlignBits, %cl
+
+       /* RangeDecoderDecodeDirectBits */
+       xorl    %edx, %edx
+
+1000:
+       shrl    $1, range
+       shll    $1, %edx
+
+       movl    range, %eax
+       cmpl    %eax, code
+       jb      2000f
+       subl    %eax, code
+       orb     $1, %dl
+2000:
+
+       cmpl    $kTopValue, %eax
+       jae     3000f
+       shll    $8, range
+       shll    $8, code
+       lodsb
+       movb    %al, code
+
+3000:
+       loop    1000b
+
+       movb    $kNumAlignBits, %cl
+       shll    %cl, %edx
+       addl    %edx, rep0
+
+       movl    $Align, %eax
+
+300:
+       call    RangeDecoderReverseBitTreeDecode
+       addl    %ecx, rep0
+
+100:
+       incl    rep0
+       popl    %edx
+
+2:
+
+       addl    $kMatchMinLen, %edx
+       movl    %edx, %ecx
+
+       jmp     3b
diff --git a/kern/i386/pc/lzo1x.S b/kern/i386/pc/lzo1x.S
new file mode 100644 (file)
index 0000000..e942e98
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
+ *  Copyright (C) 2003,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/>.
+ */
+       
+/*
+ * This code was stolen from the files enter.sh, leave.sh, lzo1x_d.sh,
+ * lzo1x_f.s and lzo_asm.h in LZO version 1.08, and was heavily modified
+ * to adapt it to GRUB's requirement.
+ *
+ * See <http://www.oberhumer.com/opensource/lzo/>, for more information
+ * about LZO.
+ */
+
+#define INP    4+16(%esp)
+#define INS    8+16(%esp)
+#define OUTP   12+16(%esp)
+#define NN     3
+#define N_3    %ebp
+#define N_255  $255
+#define LODSB  movb (%esi), %al ;  incl %esi
+#define NOTL_3(r)      xorl N_3, r
+#define MOVSL(r1,r2,x) movl (r1), x ; addl $4, r1 ; movl x, (r2) ; addl $4, r2
+#define COPYL_C(r1,r2,x,rc)    9: MOVSL(r1,r2,x) ; decl rc ; jnz 9b
+#define COPYL(r1,r2,x) COPYL_C(r1,r2,x,%ecx)
+       
+lzo1x_decompress:
+       pushl   %ebp
+       pushl   %edi
+       pushl   %esi
+       pushl   %ebx
+
+       cld
+
+       movl    INP, %esi
+       movl    OUTP, %edi
+       movl    $3, %ebp
+
+       
+       xorl    %eax, %eax
+       xorl    %ebx, %ebx      /* high bits 9-32 stay 0 */
+       lodsb
+       cmpb    $17, %al
+       jbe     .L01
+       subb    $17-NN, %al
+       jmp     .LFLR
+
+
+/***********************************************************************
+// literal run
+************************************************************************/
+
+0:     addl    N_255, %eax
+1:     movb    (%esi), %bl
+       incl    %esi
+       orb     %bl, %bl
+       jz      0b
+       leal    18+NN(%eax,%ebx), %eax
+       jmp     3f
+
+
+.L00:
+       LODSB
+.L01:
+       cmpb    $16, %al
+       jae     .LMATCH
+
+       /* a literal run */
+       orb     %al, %al
+       jz      1b
+       addl    $3+NN, %eax
+3:
+.LFLR:
+       movl    %eax, %ecx
+       NOTL_3(%eax)
+       shrl    $2, %ecx
+       andl    N_3, %eax
+       COPYL(%esi,%edi,%edx)
+       subl    %eax, %esi
+       subl    %eax, %edi
+
+       LODSB
+       cmpb    $16, %al
+       jae     .LMATCH
+
+
+/***********************************************************************
+// R1
+************************************************************************/
+
+       shrl    $2, %eax
+       movb    (%esi), %bl
+       leal    -0x801(%edi), %edx
+       leal    (%eax,%ebx,4), %eax
+       incl    %esi
+       subl    %eax, %edx
+       movl    (%edx), %ecx
+       movl    %ecx, (%edi)
+       addl    N_3, %edi
+       jmp     .LMDONE
+
+
+/***********************************************************************
+// M2
+************************************************************************/
+
+.LMATCH:
+       cmpb    $64, %al
+       jb      .LM3MATCH
+
+       /* a M2 match */
+       movl    %eax, %ecx
+       shrl    $2, %eax
+       leal    -1(%edi), %edx
+       andl    $7, %eax
+       movb    (%esi), %bl
+       shrl    $5, %ecx
+       leal    (%eax,%ebx,8), %eax
+       incl    %esi
+       subl    %eax, %edx
+
+       addl    $1+3, %ecx
+
+       cmpl    N_3, %eax
+       jae     .LCOPYLONG
+       jmp     .LCOPYBYTE
+
+
+/***********************************************************************
+// M3
+************************************************************************/
+
+0:     addl    N_255, %eax
+1:     movb    (%esi), %bl
+       incl    %esi
+       orb     %bl, %bl
+       jz      0b
+       leal    33+NN(%eax,%ebx), %ecx
+       xorl    %eax, %eax
+       jmp     3f
+
+
+.LM3MATCH:
+       cmpb    $32, %al
+       jb      .LM4MATCH
+
+       /* a M3 match */
+       andl    $31, %eax
+       jz      1b
+       lea     2+NN(%eax), %ecx
+3:
+       movw    (%esi), %ax
+       leal    -1(%edi), %edx
+       shrl    $2, %eax
+       addl    $2, %esi
+       subl    %eax, %edx
+
+       cmpl    N_3, %eax
+       jb      .LCOPYBYTE
+
+
+/***********************************************************************
+// copy match
+************************************************************************/
+
+.LCOPYLONG:                     /* copy match using longwords */
+       leal    -3(%edi,%ecx), %eax
+       shrl    $2, %ecx
+       COPYL(%edx,%edi,%ebx)
+       movl    %eax, %edi
+       xorl    %ebx, %ebx
+
+.LMDONE:
+       movb    -2(%esi), %al
+       andl    N_3, %eax
+       jz      .L00
+.LFLR3:
+       movl    (%esi), %edx
+       addl    %eax, %esi
+       movl    %edx, (%edi)
+       addl    %eax, %edi
+
+       LODSB
+       jmp     .LMATCH
+
+
+.LCOPYBYTE:                     /* copy match using bytes */
+       xchgl   %edx,%esi
+       subl    N_3,%ecx
+
+       rep
+       movsb
+       movl    %edx, %esi
+       jmp     .LMDONE
+
+
+/***********************************************************************
+// M4
+************************************************************************/
+
+0:     addl    N_255, %ecx
+1:     movb    (%esi), %bl
+       incl    %esi
+       orb     %bl, %bl
+       jz      0b
+       leal    9+NN(%ebx,%ecx), %ecx
+       jmp     3f
+
+
+.LM4MATCH:
+       cmpb    $16, %al
+       jb      .LM1MATCH
+
+       /* a M4 match */
+       movl    %eax, %ecx
+       andl    $8, %eax
+       shll    $13, %eax       /* save in bit 16 */
+       andl    $7, %ecx
+       jz      1b
+       addl    $2+NN, %ecx
+3:
+       movw    (%esi), %ax
+       addl    $2, %esi
+       leal    -0x4000(%edi), %edx
+       shrl    $2, %eax
+       jz      .LEOF
+       subl    %eax, %edx
+       jmp     .LCOPYLONG
+
+
+/***********************************************************************
+// M1
+************************************************************************/
+
+.LM1MATCH:
+       /* a M1 match */
+       shrl    $2, %eax
+       movb    (%esi), %bl
+       leal    -1(%edi), %edx
+       leal    (%eax,%ebx,4), %eax
+       incl    %esi
+       subl    %eax, %edx
+
+       movb    (%edx), %al     /* we must use this because edx can be edi-1 */
+       movb    %al, (%edi)
+       movb    1(%edx), %bl
+       movb    %bl, 1(%edi)
+       addl    $2, %edi
+       jmp     .LMDONE
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+.LEOF:
+/****  xorl    %eax,%eax          eax=0 from above */
+
+       cmpl    $3+NN, %ecx     /* ecx must be 3/6 */
+       setnz   %al
+
+       /* check compressed size */
+       movl    INP, %edx
+       addl    INS, %edx
+       cmpl    %edx, %esi       /* check compressed size */
+       ja      .L_input_overrun
+       jb      .L_input_not_consumed
+
+.L_leave:
+       negl    %eax
+       jnz     1f
+       
+       subl    OUTP, %edi       /* write back the uncompressed size */
+       movl    %edi, %eax
+
+1:     popl    %ebx
+       popl    %esi
+       popl    %edi
+       popl    %ebp
+       ret
+
+.L_input_not_consumed:
+        movl    $8, %eax         /* LZO_E_INPUT_NOT_CONSUMED */
+        jmp     .L_leave
+
+.L_input_overrun:
+        movl    $4, %eax         /* LZO_E_INPUT_OVERRUN */
+        jmp     .L_leave
+
+#undef INP
+#undef INS
+#undef OUTP
+#undef NN
+#undef NN
+#undef N_3
+#undef N_255
+#undef LODSB
+#undef NOTL_3
+#undef MOVSL
+#undef COPYL_C
+#undef COPYL
diff --git a/kern/i386/pc/mmap.c b/kern/i386/pc/mmap.c
new file mode 100644 (file)
index 0000000..d289c73
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,2005,2006,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/>.
+ */
+
+#include <grub/machine/init.h>
+#include <grub/machine/memory.h>
+#include <grub/err.h>
+#include <grub/types.h>
+
+grub_err_t
+grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
+{
+  grub_uint32_t cont;
+  struct grub_machine_mmap_entry *entry
+    = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+  
+  /* Check if grub_get_mmap_entry works.  */
+  cont = grub_get_mmap_entry (entry, 0);
+
+  if (entry->size)
+    do
+      {
+       if (hook (entry->addr, entry->len,
+                 /* Multiboot mmaps have been defined to match with the E820 definition.
+                    Therefore, we can just pass type through.  */
+                 entry->type))
+         break;
+
+       if (! cont)
+         break;
+
+       cont = grub_get_mmap_entry (entry, cont);
+      }
+    while (entry->size);
+  else
+    {
+      grub_uint32_t eisa_mmap = grub_get_eisa_mmap ();
+
+      if (eisa_mmap)
+       {
+         if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10, GRUB_MACHINE_MEMORY_AVAILABLE) == 0)
+           hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MACHINE_MEMORY_AVAILABLE);
+       }
+      else
+       hook (0x100000, grub_get_memsize (1) << 10, GRUB_MACHINE_MEMORY_AVAILABLE);
+    }
+
+  return 0;
+}
diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S
new file mode 100644 (file)
index 0000000..18f61d8
--- /dev/null
@@ -0,0 +1,2156 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2005,2006,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/>.
+ */
+
+
+/*
+ * Note: These functions defined in this file may be called from C.
+ *       Be careful of that you must not modify some registers. Quote
+ *       from gcc-2.95.2/gcc/config/i386/i386.h:
+       
+   1 for registers not available across function calls.
+   These must include the FIXED_REGISTERS and also any
+   registers that can be used without being saved.
+   The latter must include the registers where values are returned
+   and the register where structure-value addresses are passed.
+   Aside from that, you can include as many other registers as you like.
+
+  ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg
+{  1, 1, 1, 0, 0, 0, 0, 1, 1,  1,  1,  1,  1,  1,  1,  1,  1 }
+ */
+
+/*
+ * Note: GRUB is compiled with the options -mrtd and -mregparm=3.
+ *       So the first three arguments are passed in %eax, %edx, and %ecx,
+ *       respectively, and if a function has a fixed number of arguments
+ *       and the number if greater than three, the function must return
+ *       with "ret $N" where N is ((the number of arguments) - 3) * 4.
+ */
+
+#include <config.h>
+#include <grub/symbol.h>
+#include <grub/boot.h>
+#include <grub/machine/boot.h>
+#include <grub/machine/memory.h>
+#include <grub/machine/console.h>
+#include <grub/cpu/linux.h>
+#include <grub/machine/kernel.h>
+#include <grub/term.h>
+#include <multiboot.h>
+#include <multiboot2.h>
+               
+#define ABS(x) ((x) - EXT_C(start) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
+       
+       .file   "startup.S"
+
+       .text
+
+       /* Tell GAS to generate 16-bit instructions so that this code works
+          in real mode. */
+       .code16
+
+       .globl  start, _start
+start:
+_start:
+       /*
+        *  Guarantee that "main" is loaded at 0x0:0x8200.
+        */
+       ljmp $0, $ABS(codestart)
+
+       /*
+        *  Compatibility version number
+        *
+        *  These MUST be at byte offset 6 and 7 of the executable
+        *  DO NOT MOVE !!!
+        */
+       . = EXT_C(start) + 0x6
+       .byte   GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
+
+       /*
+        *  This is a special data area 8 bytes from the beginning.
+        */
+
+       . = EXT_C(start) + 0x8
+
+VARIABLE(grub_total_module_size)
+       .long   0
+VARIABLE(grub_kernel_image_size)
+       .long   0
+VARIABLE(grub_compressed_size)
+       .long   0
+VARIABLE(grub_install_dos_part)
+       .long   0xFFFFFFFF
+VARIABLE(grub_install_bsd_part)
+       .long   0xFFFFFFFF
+VARIABLE(grub_prefix)
+       /* to be filled by grub-mkimage */
+
+       /*
+        *  Leave some breathing room for the prefix.
+        */
+
+       . = EXT_C(start) + GRUB_KERNEL_MACHINE_DATA_END
+
+/*
+ * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
+ * This uses the a.out kludge to load raw binary to the area starting at 1MB,
+ * and relocates itself after loaded.
+ */
+       .p2align        2       /* force 4-byte alignment */
+multiboot_header:
+       /* magic */
+       .long   0x1BADB002
+       /* flags */
+       .long   (1 << 16)
+       /* checksum */
+       .long   -0x1BADB002 - (1 << 16)
+       /* header addr */
+       .long   multiboot_header - _start + 0x100000 + 0x200
+       /* load addr */
+       .long   0x100000
+       /* load end addr */
+       .long   0
+       /* bss end addr */
+       .long   0
+       /* entry addr */
+       .long   multiboot_entry - _start + 0x100000 + 0x200
+       
+multiboot_entry:
+       .code32
+       /* obtain the boot device */
+       movl    12(%ebx), %edx
+
+       /* relocate the code */
+       movl    $(GRUB_KERNEL_MACHINE_RAW_SIZE + 0x200), %ecx
+       addl    EXT_C(grub_compressed_size) - _start + 0x100000 + 0x200, %ecx
+       movl    $0x100000, %esi
+       movl    $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi
+       cld
+       rep
+       movsb
+       /* jump to the real address */
+       movl    $multiboot_trampoline, %eax
+       jmp     *%eax
+       
+multiboot_trampoline:
+       /* fill the boot information */
+       movl    %edx, %eax
+       shrl    $8, %eax
+       xorl    %ebx, %ebx
+       cmpb    $0xFF, %ah
+       je      1f
+       movb    %ah, %bl
+       movl    %ebx, EXT_C(grub_install_dos_part)
+1:
+       cmpb    $0xFF, %al
+       je      2f
+       movb    %al, %bl
+       movl    %ebx, EXT_C(grub_install_bsd_part)
+2:
+       shrl    $24, %edx
+        movb    $0xFF, %dh
+       /* enter the usual booting */
+       call    prot_to_real
+       .code16
+       
+/* the real mode code continues... */
+codestart:
+       cli             /* we're not safe here! */
+
+       /* set up %ds, %ss, and %es */
+       xorw    %ax, %ax
+       movw    %ax, %ds
+       movw    %ax, %ss
+       movw    %ax, %es
+
+       /* set up the real mode/BIOS stack */
+       movl    $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp
+       movl    %ebp, %esp
+
+       sti             /* we're safe again */
+
+       /* save boot and root drive references */
+       ADDR32  movb    %dl, EXT_C(grub_boot_drive)
+       ADDR32  movb    %dh, EXT_C(grub_root_drive)
+
+       /* reset disk system (%ah = 0) */
+       int     $0x13
+       
+       /* transition to protected mode */
+       DATA32  call real_to_prot
+
+       /* The ".code32" directive takes GAS out of 16-bit mode. */
+       .code32
+
+       incl    %eax
+       call    EXT_C(grub_gate_a20)
+       
+#if defined(ENABLE_LZO)
+       /* decompress the compressed part and put the result at 1MB */
+       movl    $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %esi
+       movl    $(START_SYMBOL + GRUB_KERNEL_MACHINE_RAW_SIZE), %edi
+
+       pushl   %esi
+       pushl   EXT_C(grub_compressed_size)
+       pushl   %edi
+       call    lzo1x_decompress
+       addl    $12, %esp
+
+       movl    %eax, %ecx
+       cld
+#elif defined(ENABLE_LZMA)
+       movl    $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi
+       movl    $(START_SYMBOL + GRUB_KERNEL_MACHINE_RAW_SIZE), %esi
+       pushl   %edi
+       pushl   %esi
+       movl    EXT_C(grub_kernel_image_size), %ecx
+       addl    EXT_C(grub_total_module_size), %ecx
+       subl    $GRUB_KERNEL_MACHINE_RAW_SIZE, %ecx
+       pushl   %ecx
+       leal    (%edi, %ecx), %ebx
+       call    _LzmaDecodeA
+       /* _LzmaDecodeA clears DF, so no need to run cld */
+       popl    %ecx
+       popl    %edi
+       popl    %esi
+#endif
+
+       /* copy back the decompressed part (except the modules) */
+       subl    EXT_C(grub_total_module_size), %ecx
+       rep
+       movsb
+
+#if 0
+       /* copy modules before cleaning out the bss */
+       movl    EXT_C(grub_total_module_size), %ecx
+       movl    EXT_C(grub_kernel_image_size), %esi
+       addl    %ecx, %esi
+       addl    $START_SYMBOL, %esi
+       decl    %esi
+       movl    $END_SYMBOL, %edi
+       addl    %ecx, %edi
+       decl    %edi
+       std
+       rep
+       movsb
+#endif
+       
+       /* clean out the bss */
+       movl    $BSS_START_SYMBOL, %edi
+
+       /* compute the bss length */
+       movl    $END_SYMBOL, %ecx
+       subl    %edi, %ecx
+                       
+       /* clean out */
+       xorl    %eax, %eax
+       cld
+       rep
+       stosb
+       
+       /*
+        *  Call the start of main body of C code.
+        */
+       call EXT_C(grub_main)
+
+#include "../realmode.S"
+
+/*
+ *  This is the area for all of the special variables.
+ */
+
+       .p2align        2       /* force 4-byte alignment */
+
+VARIABLE(grub_boot_drive)
+       .long   0
+
+VARIABLE(grub_root_drive)
+       .long   0
+
+VARIABLE(grub_start_addr)
+       .long   START_SYMBOL
+
+VARIABLE(grub_end_addr)
+       .long   END_SYMBOL
+       
+VARIABLE(grub_apm_bios_info)
+       .word   0       /* version */
+       .word   0       /* cseg */
+       .long   0       /* offset */
+       .word   0       /* cseg_16 */
+       .word   0       /* dseg_16 */
+       .word   0       /* cseg_len */
+       .word   0       /* cseg_16_len */
+       .word   0       /* dseg_16_len */
+       
+       .p2align        2       /* force 4-byte alignment */
+       
+/*
+ *  These next two routines, "real_to_prot" and "prot_to_real" are structured
+ *  in a very specific way.  Be very careful when changing them.
+ *
+ *  NOTE:  Use of either one messes up %eax and %ebp.
+ */
+
+real_to_prot:
+       .code16
+       cli
+
+       /* load the GDT register */
+       DATA32  ADDR32  lgdt    %cs:gdtdesc
+
+       /* turn on protected mode */
+       movl    %cr0, %eax
+       orl     $GRUB_MEMORY_MACHINE_CR0_PE_ON, %eax
+       movl    %eax, %cr0
+
+       /* jump to relocation, flush prefetch queue, and reload %cs */
+       DATA32  ljmp    $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg
+
+       .code32
+protcseg:
+       /* reload other segment registers */
+       movw    $GRUB_MEMORY_MACHINE_PROT_MODE_DSEG, %ax
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %fs
+       movw    %ax, %gs
+       movw    %ax, %ss
+
+       /* put the return address in a known safe location */
+       movl    (%esp), %eax
+       movl    %eax, GRUB_MEMORY_MACHINE_REAL_STACK
+
+       /* get protected mode stack */
+       movl    protstack, %eax
+       movl    %eax, %esp
+       movl    %eax, %ebp
+
+       /* get return address onto the right stack */
+       movl    GRUB_MEMORY_MACHINE_REAL_STACK, %eax
+       movl    %eax, (%esp)
+
+       /* zero %eax */
+       xorl    %eax, %eax
+
+       /* return on the old (or initialized) stack! */
+       ret
+
+/*
+ * grub_gate_a20(int on)
+ *
+ * Gate address-line 20 for high memory.
+ *
+ * This routine is probably overconservative in what it does, but so what?
+ *
+ * It also eats any keystrokes in the keyboard buffer.  :-(
+ */
+
+FUNCTION(grub_gate_a20)
+       movl    %eax, %edx
+
+gate_a20_test_current_state:   
+       /* first of all, test if already in a good state */
+       call    gate_a20_check_state
+       cmpb    %al, %dl
+       jnz     gate_a20_try_bios
+       ret
+
+gate_a20_try_bios:
+       /* second, try a BIOS call */
+       pushl   %ebp
+       call    prot_to_real
+
+       .code16
+       movw    $0x2400, %ax
+       testb   %dl, %dl
+       jz      1f
+       incw    %ax
+1:     int     $0x15
+
+       DATA32  call    real_to_prot
+       .code32
+
+       popl    %ebp
+       call    gate_a20_check_state
+       cmpb    %al, %dl
+       jnz     gate_a20_try_system_control_port_a
+       ret
+       
+gate_a20_try_system_control_port_a:
+       /*
+        * In macbook, the keyboard test would hang the machine, so we move
+        * this forward.
+        */
+       /* fourth, try the system control port A */
+       inb     $0x92
+       andb    $(~0x03), %al
+       testb   %dl, %dl
+       jz      6f
+       orb     $0x02, %al
+6:     outb    $0x92
+
+       /* When turning off Gate A20, do not check the state strictly,
+          because a failure is not fatal usually, and Gate A20 is always
+          on some modern machines.  */
+       testb   %dl, %dl
+       jz      7f
+       call    gate_a20_check_state
+       cmpb    %al, %dl
+       jnz     gate_a20_try_keyboard_controller
+7:     ret
+
+gate_a20_flush_keyboard_buffer:
+       inb     $0x64
+       andb    $0x02, %al
+       jnz     gate_a20_flush_keyboard_buffer
+2:     
+       inb     $0x64
+       andb    $0x01, %al
+       jz      3f
+       inb     $0x60
+       jmp     2b
+3:
+       ret
+       
+gate_a20_try_keyboard_controller:      
+       /* third, try the keyboard controller */
+       call    gate_a20_flush_keyboard_buffer
+
+       movb    $0xd1, %al
+       outb    $0x64
+4:     
+       inb     $0x64
+       andb    $0x02, %al
+       jnz     4b
+
+       movb    $0xdd, %al
+       testb   %dl, %dl
+       jz      5f
+       orb     $0x02, %al
+5:     outb    $0x60
+       call    gate_a20_flush_keyboard_buffer
+
+       /* output a dummy command (USB keyboard hack) */
+       movb    $0xff, %al
+       outb    $0x64
+       call    gate_a20_flush_keyboard_buffer
+
+       call    gate_a20_check_state
+       cmpb    %al, %dl
+       /* everything failed, so restart from the beginning */
+       jnz     gate_a20_try_bios
+       ret
+       
+gate_a20_check_state:
+       /* iterate the checking for a while */
+       movl    $100, %ecx
+1:     
+       call    3f
+       cmpb    %al, %dl
+       jz      2f
+       loop    1b
+2:
+       ret
+3:     
+       pushl   %ebx
+       pushl   %ecx
+       xorl    %eax, %eax
+       /* compare the byte at 0x8000 with that at 0x108000 */
+       movl    $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx
+       pushl   %ebx
+       /* save the original byte in CL */
+       movb    (%ebx), %cl
+       /* store the value at 0x108000 in AL */
+       addl    $0x100000, %ebx
+       movb    (%ebx), %al
+       /* try to set one less value at 0x8000 */
+       popl    %ebx
+       movb    %al, %ch
+       decb    %ch
+       movb    %ch, (%ebx)
+       /* serialize */
+       outb    %al, $0x80
+       outb    %al, $0x80
+       /* obtain the value at 0x108000 in CH */
+       pushl   %ebx
+       addl    $0x100000, %ebx
+       movb    (%ebx), %ch
+       /* this result is 1 if A20 is on or 0 if it is off */
+       subb    %ch, %al
+       xorb    $1, %al
+       /* restore the original */
+       popl    %ebx
+       movb    %cl, (%ebx)
+       popl    %ecx
+       popl    %ebx
+       ret
+
+#if defined(ENABLE_LZO)
+#include "lzo1x.S"
+#elif defined(ENABLE_LZMA)
+#include "lzma_decode.S"
+#endif
+
+/*
+ * The code beyond this point is compressed.  Assert that the uncompressed
+ * code fits GRUB_KERNEL_MACHINE_RAW_SIZE.
+ */
+       . = EXT_C(start) + GRUB_KERNEL_MACHINE_RAW_SIZE
+
+/*
+ *  This call is special...  it never returns...  in fact it should simply
+ *  hang at this point!
+ */
+
+FUNCTION(grub_stop)
+       call    prot_to_real
+
+       /*
+        * This next part is sort of evil.  It takes advantage of the
+        * byte ordering on the x86 to work in either 16-bit or 32-bit
+        * mode, so think about it before changing it.
+        */
+
+FUNCTION(grub_hard_stop)
+       hlt
+       jmp EXT_C(grub_hard_stop)
+
+
+/*
+ * grub_stop_floppy()
+ *
+ * Stop the floppy drive from spinning, so that other software is
+ * jumped to with a known state.
+ */
+FUNCTION(grub_stop_floppy)
+       movw    $0x3F2, %dx
+       xorb    %al, %al
+       outb    %al, %dx
+       ret
+
+/*
+ * grub_exit()
+ *
+ * Exit the system.
+ */
+FUNCTION(grub_exit)
+       call    prot_to_real
+       .code16
+       /* Tell the BIOS a boot failure. If this does not work, reboot.  */
+       int     $0x18
+       jmp     cold_reboot
+       .code32
+       
+/*
+ * grub_reboot()
+ *
+ * Reboot the system. At the moment, rely on BIOS.
+ */
+FUNCTION(grub_reboot)
+       call    prot_to_real
+       .code16
+cold_reboot:   
+       /* cold boot */
+       movw    $0x0472, %di
+       movw    %ax, (%di)
+       ljmp    $0xFFFF, $0x0000
+       .code32
+       
+/*
+ * grub_halt(int no_apm)
+ *
+ * Halt the system, using APM if possible. If NO_APM is true, don't use
+ * APM even if it is available.
+ */
+FUNCTION(grub_halt)
+       /* see if zero */
+       testl   %eax, %eax
+       jnz     EXT_C(grub_stop)
+
+       call    prot_to_real
+       .code16
+       
+       /* detect APM */
+       movw    $0x5300, %ax
+       xorw    %bx, %bx
+       int     $0x15
+       jc      EXT_C(grub_hard_stop)
+       /* don't check %bx for buggy BIOSes... */
+
+       /* disconnect APM first */
+       movw    $0x5304, %ax
+       xorw    %bx, %bx
+       int     $0x15
+
+       /* connect APM */
+       movw    $0x5301, %ax
+       xorw    %bx, %bx
+       int     $0x15
+       jc      EXT_C(grub_hard_stop)
+
+       /* set APM protocol level - 1.1 or bust. (this covers APM 1.2 also) */
+       movw    $0x530E, %ax
+       xorw    %bx, %bx
+       movw    $0x0101, %cx
+       int     $0x15
+       jc      EXT_C(grub_hard_stop)
+       
+       /* set the power state to off */
+       movw    $0x5307, %ax
+       movw    $1, %bx
+       movw    $3, %cx
+       int     $0x15
+
+       /* shouldn't reach here */
+       jmp     EXT_C(grub_hard_stop)
+       .code32
+       
+       
+/*
+ *  void grub_chainloader_real_boot (int drive, void *part_addr)
+ *
+ *  This starts another boot loader.
+ */
+
+FUNCTION(grub_chainloader_real_boot)
+       pushl   %edx
+       pushl   %eax
+
+       call    EXT_C(grub_dl_unload_all)
+
+       /* Turn off Gate A20 */
+       xorl    %eax, %eax
+       call    EXT_C(grub_gate_a20)
+
+       /* set up to pass boot drive */
+       popl    %edx
+
+       /* ESI must point to a partition table entry */
+       popl    %esi
+
+       call    prot_to_real
+       .code16
+       ljmp    $0, $GRUB_MEMORY_MACHINE_BOOT_LOADER_ADDR
+       .code32
+
+#include "../loader.S"
+
+/*
+ *   int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap)
+ *
+ *   Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP
+ *   is passed for disk address packet. If an error occurs, return
+ *   non-zero, otherwise zero.
+ */
+
+FUNCTION(grub_biosdisk_rw_int13_extensions)
+       pushl   %ebp
+       pushl   %esi
+
+       /* compute the address of disk_address_packet */
+       movw    %cx, %si
+       xorw    %cx, %cx
+       shrl    $4, %ecx        /* save the segment to cx */
+
+       /* ah */
+       movb    %al, %dh
+       /* enter real mode */
+       call    prot_to_real
+       
+       .code16
+       movb    %dh, %ah
+       movw    %cx, %ds
+       int     $0x13           /* do the operation */
+       movb    %ah, %dl        /* save return value */
+       /* back to protected mode */
+       DATA32  call    real_to_prot
+       .code32
+
+       movb    %dl, %al        /* return value in %eax */
+
+       popl    %esi
+       popl    %ebp
+
+       ret
+       
+/*
+ *   int grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff,
+ *                                  int soff, int nsec, int segment)
+ *
+ *   Call standard and old INT13 (int 13 %ah=AH) for DRIVE. Read/write
+ *   NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs,
+ *   return non-zero, otherwise zero.
+ */
+
+FUNCTION(grub_biosdisk_rw_standard)
+       pushl   %ebp
+       movl    %esp, %ebp
+
+       pushl   %ebx
+       pushl   %edi
+       pushl   %esi
+
+       /* set up CHS information */
+
+       /* set %ch to low eight bits of cylinder */
+       xchgb   %cl, %ch
+       /* set bits 6-7 of %cl to high two bits of cylinder */
+       shlb    $6, %cl
+       /* set bits 0-5 of %cl to sector */
+       addb    0xc(%ebp), %cl
+       /* set %dh to head */
+       movb    0x8(%ebp), %dh
+       /* set %ah to AH */
+       movb    %al, %ah
+       /* set %al to NSEC */
+       movb    0x10(%ebp), %al
+       /* save %ax in %di */
+       movw    %ax, %di
+       /* save SEGMENT in %bx */
+       movw    0x14(%ebp), %bx
+               
+       /* enter real mode */
+       call    prot_to_real
+
+       .code16
+       movw    %bx, %es
+       xorw    %bx, %bx
+       movw    $3, %si         /* attempt at least three times */
+
+1:     
+       movw    %di, %ax
+       int     $0x13           /* do the operation */
+       jnc     2f              /* check if successful */
+
+       movb    %ah, %bl        /* save return value */
+       /* if fail, reset the disk system */
+       xorw    %ax, %ax
+       int     $0x13
+       
+       decw    %si
+       cmpw    $0, %si
+       je      2f
+       xorb    %bl, %bl
+       jmp     1b              /* retry */
+2:     
+       /* back to protected mode */
+       DATA32  call    real_to_prot
+       .code32
+
+       movb    %bl, %al        /* return value in %eax */
+       
+       popl    %esi
+       popl    %edi
+       popl    %ebx
+       popl    %ebp
+
+       ret     $(4 * 4)
+
+
+/*
+ *   int grub_biosdisk_check_int13_extensions (int drive)
+ *
+ *   Check if LBA is supported for DRIVE. If it is supported, then return
+ *   the major version of extensions, otherwise zero.
+ */
+
+FUNCTION(grub_biosdisk_check_int13_extensions)
+       pushl   %ebp
+       pushl   %ebx
+
+       /* drive */
+       movb    %al, %dl
+       /* enter real mode */
+       call    prot_to_real
+
+       .code16
+       movb    $0x41, %ah
+       movw    $0x55aa, %bx
+       int     $0x13           /* do the operation */
+       
+       /* check the result */
+       jc      1f
+       cmpw    $0xaa55, %bx
+       jne     1f
+
+       movb    %ah, %bl        /* save the major version into %bl */
+
+       /* check if AH=0x42 is supported */
+       andw    $1, %cx
+       jnz     2f
+       
+1:
+       xorb    %bl, %bl
+2:
+       /* back to protected mode */
+       DATA32  call    real_to_prot
+       .code32
+
+       movb    %bl, %al        /* return value in %eax */
+
+       popl    %ebx
+       popl    %ebp
+
+       ret
+
+
+/*
+ *   int grub_biosdisk_get_cdinfo_int13_extensions (int drive, void *cdrp)
+ *
+ *   Return the cdrom information of DRIVE in CDRP. If an error occurs,
+ *   then return non-zero, otherwise zero.
+ */
+
+FUNCTION(grub_biosdisk_get_cdinfo_int13_extensions)
+       movw    $0x4B01, %cx
+       jmp     1f
+
+/*
+ *   int grub_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp)
+ *
+ *   Return the geometry of DRIVE in a drive parameters, DRP. If an error
+ *   occurs, then return non-zero, otherwise zero.
+ */
+
+FUNCTION(grub_biosdisk_get_diskinfo_int13_extensions)
+       movb    $0x48, %ch
+1:
+       pushl   %ebp
+       pushl   %ebx
+       pushl   %esi
+
+       /* compute the address of drive parameters */
+       movw    %dx, %si
+       andl    $0xf, %esi
+       shrl    $4, %edx
+       movw    %dx, %bx        /* save the segment into %bx */
+       /* drive */
+       movb    %al, %dl
+       /* enter real mode */
+       call    prot_to_real
+
+       .code16
+       movw    %cx, %ax
+       movw    %bx, %ds
+       int     $0x13           /* do the operation */
+       movb    %ah, %bl        /* save return value in %bl */
+       /* back to protected mode */
+       DATA32  call    real_to_prot
+       .code32
+
+       movb    %bl, %al        /* return value in %eax */
+
+       popl    %esi
+       popl    %ebx
+       popl    %ebp
+       
+       ret
+
+
+/*
+ *   int grub_biosdisk_get_diskinfo_standard (int drive,
+ *                                            unsigned long *cylinders, 
+ *                                            unsigned long *heads,
+ *                                            unsigned long *sectors)
+ *
+ *   Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an
+ *   error occurs, then return non-zero, otherwise zero.
+ */
+
+FUNCTION(grub_biosdisk_get_diskinfo_standard)
+       pushl   %ebp
+       pushl   %ebx
+       pushl   %edi
+
+       /* push CYLINDERS */
+       pushl   %edx
+       /* push HEADS */
+       pushl   %ecx
+       /* SECTORS is on the stack */
+       
+       /* drive */
+       movb    %al, %dl
+       /* enter real mode */
+       call    prot_to_real
+
+       .code16
+       movb    $0x8, %ah
+       int     $0x13           /* do the operation */
+       /* check if successful */
+       testb   %ah, %ah
+       jnz     1f
+       /* bogus BIOSes may not return an error number */
+       testb   $0x3f, %cl      /* 0 sectors means no disk */
+       jnz     1f              /* if non-zero, then succeed */
+       /* XXX 0x60 is one of the unused error numbers */
+       movb    $0x60, %ah
+1:
+       movb    %ah, %bl        /* save return value in %bl */
+       /* back to protected mode */
+       DATA32  call    real_to_prot
+       .code32
+
+       /* pop HEADS */
+       popl    %edi
+       movb    %dh, %al
+       incl    %eax    /* the number of heads is counted from zero */
+       movl    %eax, (%edi)
+
+       /* pop CYLINDERS */
+       popl    %edi
+       movb    %ch, %al
+       movb    %cl, %ah
+       shrb    $6, %ah /* the number of cylinders is counted from zero */
+       incl    %eax
+       movl    %eax, (%edi)
+
+       /* SECTORS */
+       movl    0x10(%esp), %edi
+       andb    $0x3f, %cl
+       movzbl  %cl, %eax
+       movl    %eax, (%edi)
+       
+       xorl    %eax, %eax
+       movb    %bl, %al        /* return value in %eax */
+
+       popl    %edi
+       popl    %ebx
+       popl    %ebp
+
+       ret     $4
+
+
+/*
+ * int grub_biosdisk_get_num_floppies (void)
+ */
+FUNCTION(grub_biosdisk_get_num_floppies)
+       pushl   %ebp
+
+       xorl    %edx, %edx
+       call    prot_to_real
+       
+       .code16
+       /* reset the disk system first */
+       int     $0x13
+1:
+       stc
+       
+       /* call GET DISK TYPE */
+       movb    $0x15, %ah
+       int     $0x13
+
+       jc      2f
+
+       /* check if this drive exists */        
+       testb   $0x3, %ah
+       jz      2f
+
+       incb    %dl
+       cmpb    $2, %dl
+       jne     1b
+2:
+       DATA32  call    real_to_prot
+       .code32
+
+       movl    %edx, %eax
+       popl    %ebp
+       ret
+       
+       
+/*
+ *
+ * grub_get_memsize(i) :  return the memory size in KB. i == 0 for conventional
+ *             memory, i == 1 for extended memory
+ *     BIOS call "INT 12H" to get conventional memory size
+ *     BIOS call "INT 15H, AH=88H" to get extended memory size
+ *             Both have the return value in AX.
+ *
+ */
+
+FUNCTION(grub_get_memsize)
+       pushl   %ebp
+
+       movl    %eax, %edx
+
+       call    prot_to_real    /* enter real mode */
+       .code16
+
+       testl   %edx, %edx
+       jnz     xext
+
+       int     $0x12
+       jmp     xdone
+
+xext:
+       movb    $0x88, %ah
+       int     $0x15
+
+xdone:
+       movw    %ax, %dx
+
+       DATA32  call    real_to_prot
+       .code32
+
+       movw    %dx, %ax
+
+       popl    %ebp
+       ret
+
+
+/*
+ *
+ * grub_get_eisa_mmap() :  return packed EISA memory map, lower 16 bits is
+ *             memory between 1M and 16M in 1K parts, upper 16 bits is
+ *             memory above 16M in 64K parts.  If error, return zero.
+ *     BIOS call "INT 15H, AH=E801H" to get EISA memory map,
+ *             AX = memory between 1M and 16M in 1K parts.
+ *             BX = memory above 16M in 64K parts.
+ *
+ */
+
+FUNCTION(grub_get_eisa_mmap)
+       pushl   %ebp
+       pushl   %ebx
+
+       call    prot_to_real    /* enter real mode */
+       .code16
+
+       movw    $0xe801, %ax
+       int     $0x15
+
+       shll    $16, %ebx
+       movw    %ax, %bx
+
+       DATA32  call    real_to_prot
+       .code32
+
+       cmpb    $0x86, %bh
+       je      xnoteisa
+
+       movl    %ebx, %eax
+
+xnoteisa:
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ *
+ * grub_get_mmap_entry(addr, cont) : address and old continuation value (zero to
+ *             start), for the Query System Address Map BIOS call.
+ *
+ *  Sets the first 4-byte int value of "addr" to the size returned by
+ *  the call.  If the call fails, sets it to zero.
+ *
+ *     Returns:  new (non-zero) continuation value, 0 if done.
+ */
+
+FUNCTION(grub_get_mmap_entry)
+       pushl   %ebp
+       pushl   %ebx
+       pushl   %edi
+       pushl   %esi
+
+       /* push ADDR */
+       pushl   %eax
+       
+       /* place address (+4) in ES:DI */
+       addl    $4, %eax
+       movl    %eax, %edi
+       andl    $0xf, %edi
+       shrl    $4, %eax
+       movl    %eax, %esi
+
+       /* set continuation value */
+       movl    %edx, %ebx
+
+       /* set default maximum buffer size */
+       movl    $0x14, %ecx
+
+       /* set EDX to 'SMAP' */
+       movl    $0x534d4150, %edx
+
+       call    prot_to_real    /* enter real mode */
+       .code16
+
+       movw    %si, %es
+       movl    $0xe820, %eax
+       int     $0x15
+
+       DATA32  jc      xnosmap
+
+       cmpl    $0x534d4150, %eax
+       jne     xnosmap
+
+       cmpl    $0x14, %ecx
+       jl      xnosmap
+
+       cmpl    $0x400, %ecx
+       jg      xnosmap
+
+       jmp     xsmap
+
+xnosmap:
+       xorl    %ecx, %ecx
+
+xsmap:
+       DATA32  call    real_to_prot
+       .code32
+
+       /* write length of buffer (zero if error) into ADDR */
+       popl    %eax
+       movl    %ecx, (%eax)
+
+       /* set return value to continuation */
+       movl    %ebx, %eax
+
+       popl    %esi
+       popl    %edi
+       popl    %ebx
+       popl    %ebp
+       ret
+
+       
+/*
+ * void grub_console_real_putchar (int c)
+ *
+ * Put the character C on the console. Because GRUB wants to write a
+ * character with an attribute, this implementation is a bit tricky.
+ * If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh
+ * (TELETYPE OUTPUT). Otherwise, save the original position, put a space,
+ * save the current position, restore the original position, write the
+ * character and the attribute, and restore the current position.
+ *
+ * The reason why this is so complicated is that there is no easy way to
+ * get the height of the screen, and the TELETYPE OUTPUT BIOS call doesn't
+ * support setting a background attribute.
+ */
+FUNCTION(grub_console_real_putchar)
+       movl    %eax, %edx
+       pusha
+       movb    EXT_C(grub_console_cur_color), %bl
+       
+       call    prot_to_real
+       .code16
+       movb    %dl, %al
+       xorb    %bh, %bh
+
+       /* use teletype output if control character */
+       cmpb    $0x7, %al
+       je      1f
+       cmpb    $0x8, %al
+       je      1f
+       cmpb    $0xa, %al
+       je      1f
+       cmpb    $0xd, %al
+       je      1f
+
+       /* save the character and the attribute on the stack */
+       pushw   %ax
+       pushw   %bx
+       
+       /* get the current position */
+       movb    $0x3, %ah
+       int     $0x10
+
+       /* check the column with the width */
+       cmpb    $79, %dl
+       jl      2f
+       
+       /* print CR and LF, if next write will exceed the width */      
+       movw    $0x0e0d, %ax
+       int     $0x10
+       movb    $0x0a, %al
+       int     $0x10
+       
+       /* get the current position */
+       movb    $0x3, %ah
+       int     $0x10
+
+2:     
+       /* restore the character and the attribute */
+       popw    %bx
+       popw    %ax
+       
+       /* write the character with the attribute */
+       movb    $0x9, %ah
+       movw    $1, %cx
+       int     $0x10
+
+       /* move the cursor forward */
+       incb    %dl
+       movb    $0x2, %ah
+       int     $0x10
+
+       jmp     3f
+
+1:     movw    $1, %bx
+       movb    $0xe, %ah
+       int     $0x10
+       
+3:     DATA32  call    real_to_prot
+       .code32
+       
+       popa
+       ret
+       
+
+/*
+ * int grub_console_getkey (void)
+ * BIOS call "INT 16H Function 00H" to read character from keyboard
+ *     Call with       %ah = 0x0
+ *     Return:         %ah = keyboard scan code
+ *                     %al = ASCII character
+ */
+
+/* this table is used in translate_keycode below */
+translation_table:
+       .word   GRUB_CONSOLE_KEY_LEFT, GRUB_TERM_LEFT
+       .word   GRUB_CONSOLE_KEY_RIGHT, GRUB_TERM_RIGHT
+       .word   GRUB_CONSOLE_KEY_UP, GRUB_TERM_UP
+       .word   GRUB_CONSOLE_KEY_DOWN, GRUB_TERM_DOWN
+       .word   GRUB_CONSOLE_KEY_HOME, GRUB_TERM_HOME
+       .word   GRUB_CONSOLE_KEY_END, GRUB_TERM_END
+       .word   GRUB_CONSOLE_KEY_DC, GRUB_TERM_DC
+       .word   GRUB_CONSOLE_KEY_BACKSPACE, GRUB_TERM_BACKSPACE
+       .word   GRUB_CONSOLE_KEY_PPAGE, GRUB_TERM_PPAGE
+       .word   GRUB_CONSOLE_KEY_NPAGE, GRUB_TERM_NPAGE
+       .word   0
+       
+/*
+ * translate_keycode translates the key code %dx to an ascii code.
+ */
+       .code16
+
+translate_keycode:
+       pushw   %bx
+       pushw   %si
+       
+       movw    $ABS(translation_table), %si
+       
+1:     lodsw
+       /* check if this is the end */
+       testw   %ax, %ax
+       jz      2f
+       /* load the ascii code into %ax */
+       movw    %ax, %bx
+       lodsw
+       /* check if this matches the key code */
+       cmpw    %bx, %dx
+       jne     1b
+       /* translate %dx, if successful */
+       movw    %ax, %dx
+
+2:     popw    %si
+       popw    %bx
+       ret
+
+       .code32
+       
+FUNCTION(grub_console_getkey)
+       pushl   %ebp
+
+       call    prot_to_real
+       .code16
+
+       /*
+        * Due to a bug in apple's bootcamp implementation, INT 16/AH = 0 would
+        * cause the machine to hang at the second keystroke. However, we can
+        * work around this problem by ensuring the presence of keystroke with
+        * INT 16/AH = 1 before calling INT 16/AH = 0.
+        */
+
+1:
+       movb    $1, %ah
+       int     $0x16
+       jnz     2f
+       hlt
+       jmp     1b
+
+2:
+
+       movb    $0, %ah
+       int     $0x16
+
+       movw    %ax, %dx                /* real_to_prot uses %eax */
+       call    translate_keycode
+               
+       DATA32  call    real_to_prot
+       .code32
+
+       movw    %dx, %ax
+
+       popl    %ebp
+       ret
+
+
+/*
+ * int grub_console_checkkey (void)
+ *     if there is a character pending, return it; otherwise return -1
+ * BIOS call "INT 16H Function 01H" to check whether a character is pending
+ *     Call with       %ah = 0x1
+ *     Return:
+ *             If key waiting to be input:
+ *                     %ah = keyboard scan code
+ *                     %al = ASCII character
+ *                     Zero flag = clear
+ *             else
+ *                     Zero flag = set
+ */
+FUNCTION(grub_console_checkkey)
+       pushl   %ebp
+       xorl    %edx, %edx
+       
+       call    prot_to_real    /* enter real mode */
+       .code16
+
+       movb    $0x1, %ah
+       int     $0x16
+
+       jz      notpending
+       
+       movw    %ax, %dx
+       DATA32  jmp     pending
+
+notpending:
+       decl    %edx
+
+pending:
+       DATA32  call    real_to_prot
+       .code32
+
+       movl    %edx, %eax
+
+       popl    %ebp
+       ret
+
+       
+/*
+ * grub_uint16_t grub_console_getxy (void)
+ * BIOS call "INT 10H Function 03h" to get cursor position
+ *     Call with       %ah = 0x03
+ *                     %bh = page
+ *      Returns         %ch = starting scan line
+ *                      %cl = ending scan line
+ *                      %dh = row (0 is top)
+ *                      %dl = column (0 is left)
+ */
+
+
+FUNCTION(grub_console_getxy)
+       pushl   %ebp
+       pushl   %ebx                    /* save EBX */
+
+       call    prot_to_real
+       .code16
+
+        xorb   %bh, %bh                /* set page to 0 */
+       movb    $0x3, %ah
+       int     $0x10                   /* get cursor position */
+
+       DATA32  call    real_to_prot
+       .code32
+
+       movb    %dl, %ah
+       movb    %dh, %al
+
+       popl    %ebx
+       popl    %ebp
+       ret
+
+
+/*
+ * void grub_console_gotoxy(grub_uint8_t x, grub_uint8_t y)
+ * BIOS call "INT 10H Function 02h" to set cursor position
+ *     Call with       %ah = 0x02
+ *                     %bh = page
+ *                      %dh = row (0 is top)
+ *                      %dl = column (0 is left)
+ */
+
+
+FUNCTION(grub_console_gotoxy)
+       pushl   %ebp
+       pushl   %ebx                    /* save EBX */
+
+       movb    %dl, %dh        /* %dh = y */
+       movb    %al, %dl        /* %dl = x */
+
+       call    prot_to_real
+       .code16
+
+        xorb   %bh, %bh                /* set page to 0 */
+       movb    $0x2, %ah
+       int     $0x10                   /* set cursor position */
+
+       DATA32  call    real_to_prot
+       .code32
+
+       popl    %ebx
+       popl    %ebp
+       ret
+
+       
+/*
+ * void grub_console_cls (void)
+ * BIOS call "INT 10H Function 09h" to write character and attribute
+ *     Call with       %ah = 0x09
+ *                      %al = (character)
+ *                      %bh = (page number)
+ *                      %bl = (attribute)
+ *                      %cx = (number of times)
+ */
+
+FUNCTION(grub_console_cls)
+       pushl   %ebp
+       pushl   %ebx                    /* save EBX */
+
+       call    prot_to_real
+       .code16
+
+       /* move the cursor to the beginning */
+       movb    $0x02, %ah
+       xorb    %bh, %bh
+       xorw    %dx, %dx
+       int     $0x10
+
+       /* write spaces to the entire screen */
+       movw    $0x0920, %ax
+       movw    $0x07, %bx
+       movw    $(80 * 25), %cx
+        int    $0x10
+
+       /* move back the cursor */
+       movb    $0x02, %ah
+       int     $0x10
+
+       DATA32  call    real_to_prot
+       .code32
+
+       popl    %ebx
+       popl    %ebp
+       ret
+
+       
+/*
+ * void grub_console_setcursor (int on)
+ * BIOS call "INT 10H Function 01h" to set cursor type
+ *      Call with       %ah = 0x01
+ *                      %ch = cursor starting scanline
+ *                      %cl = cursor ending scanline
+ */
+
+console_cursor_state:
+       .byte   1
+console_cursor_shape:
+       .word   0
+       
+FUNCTION(grub_console_setcursor)
+       pushl   %ebp
+       pushl   %ebx
+
+       /* push ON */
+       pushl   %eax
+       
+       /* check if the standard cursor shape has already been saved */
+       movw    console_cursor_shape, %ax
+       testw   %ax, %ax
+       jne     1f
+
+       call    prot_to_real
+       .code16
+
+       movb    $0x03, %ah
+       xorb    %bh, %bh
+       int     $0x10
+
+       DATA32  call    real_to_prot
+       .code32
+
+       movw    %cx, console_cursor_shape
+1:
+       /* set %cx to the designated cursor shape */
+       movw    $0x2000, %cx
+       popl    %eax
+       testl   %eax, %eax
+       jz      2f
+       movw    console_cursor_shape, %cx
+2:     
+       call    prot_to_real
+       .code16
+
+       movb    $0x1, %ah
+       int     $0x10 
+
+       DATA32  call    real_to_prot
+       .code32
+
+       popl    %ebx
+       popl    %ebp
+       ret
+               
+/*
+ * grub_getrtsecs()
+ *     if a seconds value can be read, read it and return it (BCD),
+ *      otherwise return 0xFF
+ * BIOS call "INT 1AH Function 02H" to check whether a character is pending
+ *     Call with       %ah = 0x2
+ *     Return:
+ *             If RT Clock can give correct values
+ *                     %ch = hour (BCD)
+ *                     %cl = minutes (BCD)
+ *                      %dh = seconds (BCD)
+ *                      %dl = daylight savings time (00h std, 01h daylight)
+ *                     Carry flag = clear
+ *             else
+ *                     Carry flag = set
+ *                         (this indicates that the clock is updating, or
+ *                          that it isn't running)
+ */
+FUNCTION(grub_getrtsecs)
+       pushl   %ebp
+
+       call    prot_to_real    /* enter real mode */
+       .code16
+
+       clc
+       movb    $0x2, %ah
+       int     $0x1a
+
+       DATA32  jnc     gottime
+       movb    $0xff, %dh
+
+gottime:
+       DATA32  call    real_to_prot
+       .code32
+
+       movb    %dh, %al
+
+       popl    %ebp
+       ret
+
+       
+/*
+ * grub_get_rtc()
+ *     return the real time in ticks, of which there are about
+ *     18-20 per second
+ */
+FUNCTION(grub_get_rtc)
+       pushl   %ebp
+
+       call    prot_to_real    /* enter real mode */
+       .code16
+
+       /* %ax is already zero */
+        int    $0x1a
+
+       DATA32  call    real_to_prot
+       .code32
+
+       movl    %ecx, %eax
+       shll    $16, %eax
+       movw    %dx, %ax
+
+       popl    %ebp
+       ret
+
+
+/*
+ * unsigned char grub_vga_set_mode (unsigned char mode)
+ */
+FUNCTION(grub_vga_set_mode)
+       pushl   %ebp
+       pushl   %ebx
+       movl    %eax, %ecx
+
+       call    prot_to_real
+       .code16
+       /* get current mode */
+       xorw    %bx, %bx
+       movb    $0x0f, %ah
+       int     $0x10
+       movb    %al, %dl
+
+       /* set the new mode */
+       movb    %cl, %al
+       xorb    %ah, %ah
+       int     $0x10
+
+       DATA32  call    real_to_prot
+       .code32
+
+       movb    %dl, %al
+       popl    %ebx
+       popl    %ebp
+       ret
+
+
+/*
+ * unsigned char *grub_vga_get_font (void)
+ */
+FUNCTION(grub_vga_get_font)
+       pushl   %ebp
+       pushl   %ebx
+
+       call    prot_to_real
+       .code16
+       movw    $0x1130, %ax
+       movb    $0x06, %bh
+       int     $0x10
+       movw    %es, %bx
+       movw    %bp, %dx
+       DATA32  call    real_to_prot
+       .code32
+
+       movzwl  %bx, %ecx
+       shll    $4, %ecx
+       movw    %dx, %ax
+       addl    %ecx, %eax
+
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * grub_vbe_bios_status_t grub_vbe_get_controller_info (struct grub_vbe_info_block *controller_info)
+ *
+ * Register allocations for parameters:
+ * %eax                *controller_info
+ */
+FUNCTION(grub_vbe_bios_get_controller_info)
+       pushl   %ebp
+       pushl   %edi
+       pushl   %edx
+
+       movw    %ax, %di        /* Store *controller_info to %edx:%di.  */
+       xorw    %ax, %ax
+       shrl    $4, %eax
+       mov     %eax, %edx      /* prot_to_real destroys %eax.  */
+       
+       call    prot_to_real
+       .code16
+
+       pushw   %es
+
+       movw    %dx, %es        /* *controller_info is now on %es:%di.  */
+       movw    $0x4f00, %ax
+       int     $0x10
+
+       movw    %ax, %dx        /* real_to_prot destroys %eax.  */
+
+       popw    %es
+
+       DATA32 call     real_to_prot
+       .code32
+
+       movl    %edx, %eax
+       andl    $0x0FFFF, %eax  /* Return value in %eax.  */
+       
+       pop     %edx
+       popl    %edi
+       popl    %ebp
+       ret
+
+/*
+ * grub_vbe_status_t grub_vbe_bios_get_mode_info (grub_uint32_t mode,
+ *                                               struct grub_vbe_mode_info_block *mode_info)
+ *
+ * Register allocations for parameters:
+ * %eax                mode
+ * %edx                *mode_info
+ */
+FUNCTION(grub_vbe_bios_get_mode_info)
+       pushl   %ebp
+       pushl   %edi
+
+       movl    %eax, %ecx      /* Store mode number to %ecx.  */
+
+       movw    %dx, %di        /* Store *mode_info to %edx:%di.  */
+       xorw    %dx, %dx
+       shrl    $4, %edx
+
+       call    prot_to_real
+       .code16
+
+       pushw   %es
+
+       movw    %dx, %es        /* *mode_info is now on %es:%di.  */
+       movw    $0x4f01, %ax
+       int     $0x10
+
+       movw    %ax, %dx        /* real_to_prot destroys %eax.  */
+
+       popw    %es
+
+       DATA32 call     real_to_prot
+       .code32
+
+       movl    %edx, %eax
+       andl    $0x0FFFF, %eax  /* Return value in %eax.  */
+
+       popl    %edi
+       popl    %ebp
+       ret
+
+/*
+ * grub_vbe_status_t grub_vbe_bios_set_mode (grub_uint32_t mode,
+ *                                          struct grub_vbe_crtc_info_block *crtc_info)
+ *
+ * Register allocations for parameters:
+ * %eax                mode
+ * %edx                *crtc_info
+ */
+FUNCTION(grub_vbe_bios_set_mode)
+       pushl   %ebp
+       pushl   %ebx
+       pushl   %edi
+
+       movl    %eax, %ebx      /* Store mode in %ebx.  */
+
+       movw    %dx, %di        /* Store *crtc_info to %edx:%di.  */
+       xorw    %dx, %dx
+       shrl    $4, %edx
+
+       call    prot_to_real
+       .code16
+
+       pushw   %es
+
+       movw    %dx, %es        /* *crtc_info is now on %es:%di.  */
+
+       movw    $0x4f02, %ax
+       int     $0x10
+
+       movw    %ax, %dx        /* real_to_prot destroys %eax.  */
+
+       popw    %es
+
+       DATA32 call     real_to_prot
+       .code32
+       
+       movw    %dx, %ax
+       andl    $0xFFFF, %eax   /* Return value in %eax.  */
+
+       popl    %edi
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * grub_vbe_status_t grub_vbe_bios_get_mode (grub_uint32_t *mode)
+ *
+ * Register allocations for parameters:
+ * %eax                *mode
+ */
+FUNCTION(grub_vbe_bios_get_mode)
+       pushl   %ebp
+       pushl   %ebx
+       pushl   %edi
+       pushl   %edx
+       pushl   %eax            /* Push *mode to stack.  */
+
+       call    prot_to_real
+       .code16
+
+       movw    $0x4f03, %ax
+       int     $0x10
+
+       movw    %ax, %dx        /* real_to_prot destroys %eax.  */
+
+       DATA32 call     real_to_prot
+       .code32
+
+       popl    %edi            /* Pops *mode from stack to %edi.  */
+       andl    $0xFFFF, %ebx
+       movl    %ebx, (%edi)
+
+       movw    %dx, %ax
+       andl    $0xFFFF, %eax   /* Return value in %eax.  */
+
+       popl    %edx
+       popl    %edi
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * grub_vbe_status_t grub_vbe_bios_set_memory_window (grub_uint32_t window,
+ *                                                   grub_uint32_t position);
+ *
+ * Register allocations for parameters:
+ * %eax                window
+ * %edx                position
+ */
+FUNCTION(grub_vbe_bios_set_memory_window)
+       pushl   %ebp
+       pushl   %ebx
+
+       movl    %eax, %ebx
+
+       call    prot_to_real
+       .code16
+
+       movw    $0x4f05, %ax
+       andw    $0x00ff, %bx    /* BL = window, BH = 0, Set memory window.  */
+       int     $0x10
+
+       movw    %ax, %dx        /* real_to_prot destroys %eax.  */
+
+       DATA32 call     real_to_prot
+       .code32
+       
+       movw    %dx, %ax
+       andl    $0xFFFF, %eax   /* Return value in %eax.  */
+
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * grub_vbe_status_t grub_vbe_bios_get_memory_window (grub_uint32_t window,
+ *                                                   grub_uint32_t *position);
+ *
+ * Register allocations for parameters:
+ * %eax                window
+ * %edx                *position
+ */
+FUNCTION(grub_vbe_bios_get_memory_window)
+       pushl   %ebp
+       pushl   %ebx
+       pushl   %edi
+       pushl   %edx            /* Push *position to stack.  */
+
+       movl    %eax, %ebx      /* Store window in %ebx.  */
+
+       call    prot_to_real
+       .code16
+
+       movw    $0x4f05, %ax
+       andw    $0x00ff, %bx    /* BL = window.  */
+       orw     $0x0100, %bx    /* BH = 1, Get memory window.  */
+       int     $0x10
+
+       movw    %ax, %bx        /* real_to_prot destroys %eax.  */
+
+       DATA32 call     real_to_prot
+       .code32
+
+       popl    %edi            /* pops *position from stack to %edi.  */
+       andl    $0xFFFF, %edx
+       movl    %edx, (%edi)    /* Return position to caller.  */
+
+       movw    %bx, %ax
+       andl    $0xFFFF, %eax   /* Return value in %eax.  */
+
+       popl    %edi
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * grub_vbe_status_t grub_vbe_bios_set_scanline_length (grub_uint32_t length)
+ *
+ * Register allocations for parameters:
+ * %eax                length
+ */
+FUNCTION(grub_vbe_bios_set_scanline_length)
+       pushl   %ebp
+       pushl   %ebx
+       pushl   %edx
+
+       movl    %eax, %ecx      /* Store length in %ecx.  */
+
+       call    prot_to_real
+       .code16
+
+       movw    $0x4f06, %ax
+       movw    $0x0002, %bx    /* BL = 2, Set Scan Line in Bytes.  */
+       int     $0x10
+
+       movw    %ax, %dx        /* real_to_prot destroys %eax.  */
+
+       DATA32 call     real_to_prot
+       .code32
+       
+       movw    %dx, %ax
+       andl    $0xFFFF, %eax   /* Return value in %eax.  */
+
+       popl    %edx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * grub_vbe_status_t grub_vbe_bios_get_scanline_length (grub_uint32_t *length)
+ *
+ * Register allocations for parameters:
+ * %eax                *length
+ */
+FUNCTION(grub_vbe_bios_get_scanline_length)
+       pushl   %ebp
+       pushl   %ebx
+       pushl   %edi
+       pushl   %edx            /* Push *length to stack.  */
+
+       call    prot_to_real
+       .code16
+
+       movw    $0x4f06, %ax
+       movw    $0x0001, %bx    /* BL = 1, Get Scan Line Length (in bytes).  */
+       int     $0x10
+
+       movw    %ax, %dx        /* real_to_prot destroys %eax.  */
+
+       DATA32 call     real_to_prot
+       .code32
+
+       popl    %edi            /* Pops *length from stack to %edi.  */
+       andl    $0xFFFF, %ebx
+       movl    %ebx, (%edi)    /* Return length to caller.  */
+
+       movw    %dx, %ax
+       andl    $0xFFFF, %eax   /* Return value in %eax.  */
+
+       popl    %edi
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * grub_vbe_status_t grub_vbe_bios_set_display_start (grub_uint32_t x,
+ *                                                   grub_uint32_t y)
+ *
+ * Register allocations for parameters:
+ * %eax                x
+ * %edx                y
+ */
+FUNCTION(grub_vbe_bios_set_display_start)
+       pushl   %ebp
+       pushl   %ebx
+
+       movl    %eax, %ecx      /* Store x in %ecx.  */
+
+       call    prot_to_real
+       .code16
+
+       movw    $0x4f07, %ax
+       movw    $0x0080, %bx    /* BL = 80h, Set Display Start 
+                                  during Vertical Retrace.  */
+       int     $0x10
+
+       movw    %ax, %dx        /* real_to_prot destroys %eax.  */
+
+       DATA32 call     real_to_prot
+       .code32
+       
+       movw    %dx, %ax
+       andl    $0xFFFF, %eax   /* Return value in %eax.  */
+
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * grub_vbe_status_t grub_vbe_bios_get_display_start (grub_uint32_t *x,
+ *                                                   grub_uint32_t *y)
+ *
+ * Register allocations for parameters:
+ * %eax                *x
+ * %edx                *y
+ */
+FUNCTION(grub_vbe_bios_get_display_start)
+       pushl   %ebp
+       pushl   %ebx
+       pushl   %edi
+       pushl   %eax            /* Push *x to stack.  */
+       pushl   %edx            /* Push *y to stack.  */
+
+       call    prot_to_real
+       .code16
+
+       movw    $0x4f07, %ax
+       movw    $0x0001, %bx    /* BL = 1, Get Display Start.  */
+       int     $0x10
+
+       movw    %ax, %bx        /* real_to_prot destroys %eax.  */
+
+       DATA32 call     real_to_prot
+       .code32
+
+       popl    %edi            /* Pops *y from stack to %edi.  */
+       andl    $0xFFFF, %edx
+       movl    %edx, (%edi)    /* Return y-position to caller.  */
+
+       popl    %edi            /* Pops *x from stack to %edi.  */
+       andl    $0xFFFF, %ecx
+       movl    %ecx, (%edi)    /* Return x-position to caller.  */
+
+       movw    %bx, %ax
+       andl    $0xFFFF, %eax   /* Return value in %eax.  */
+
+       popl    %edi
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * grub_vbe_status_t grub_vbe_bios_set_palette_data (grub_uint32_t color_count,
+ *                                                  grub_uint32_t start_index,
+ *                                                  struct grub_vbe_palette_data *palette_data)
+ *
+ * Register allocations for parameters:
+ * %eax                color_count
+ * %edx                start_index
+ * %ecx                *palette_data
+ */
+FUNCTION(grub_vbe_bios_set_palette_data)
+       pushl   %ebp
+       pushl   %ebx
+       pushl   %edi
+
+       movl    %eax, %ebx      /* Store color_count in %ebx.  */
+
+       movw    %cx, %di        /* Store *palette_data to %ecx:%di.  */
+       xorw    %cx, %cx
+       shrl    $4, %ecx
+
+       call    prot_to_real
+       .code16
+
+       pushw   %es
+
+       movw    %cx, %es        /* *palette_data is now on %es:%di.  */
+       movw    %bx, %cx        /* color_count is now on %cx.  */
+
+       movw    $0x4f09, %ax
+       xorw    %bx, %bx        /* BL = 0, Set Palette Data.  */
+       int     $0x10
+
+       movw    %ax, %dx        /* real_to_prot destroys %eax.  */
+
+       popw    %es
+
+       DATA32 call     real_to_prot
+       .code32
+       
+       movw    %dx, %ax
+       andl    $0xFFFF, %eax   /* Return value in %eax.  */
+
+       popl    %edi
+       popl    %ebx
+       popl    %ebp
+       ret
+
+
+pxe_rm_entry:
+       .long   0
+
+/*
+ * struct grub_pxenv *grub_pxe_scan (void);
+ */
+FUNCTION(grub_pxe_scan)
+       pushl   %ebp
+       pushl   %ebx
+
+       xorl    %ebx, %ebx
+       xorl    %ecx, %ecx
+
+       call    prot_to_real
+       .code16
+
+       pushw   %es
+
+       movw    $0x5650, %ax
+       int     $0x1A
+       cmpw    $0x564E, %ax
+       jnz     1f
+       cmpl    $0x4E455850, %es:(%bx)          /* PXEN(V+)  */
+       jnz     1f
+       cmpw    $0x201, %es:6(%bx)              /* API version  */
+       jb      1f
+       lesw    %es:0x28(%bx), %bx              /* !PXE structure  */
+       cmpl    $0x45585021, %es:(%bx)          /* !PXE  */
+       jnz     1f
+       movw    %es, %cx
+       jmp     2f
+1:
+       xorw    %bx, %bx
+       xorw    %cx, %cx
+2:
+
+       popw    %es
+
+       DATA32 call     real_to_prot
+       .code32
+
+       xorl    %eax, %eax
+       leal    (%eax, %ecx, 4), %ecx
+       leal    (%ebx, %ecx, 4), %eax           /* eax = ecx * 16 + ebx  */
+
+       orl     %eax, %eax
+       jz      1f
+
+       movl    0x10(%eax), %ecx
+       movl    %ecx, pxe_rm_entry
+
+1:
+
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * int grub_pxe_call (int func, void* data);
+ */
+FUNCTION(grub_pxe_call)
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %esi
+       pushl   %edi
+       pushl   %ebx
+
+       movl    %eax, %ecx
+       movl    %edx, %eax
+       andl    $0xF, %eax
+       shrl    $4, %edx
+       shll    $16, %edx
+       addl    %eax, %edx
+       movl    pxe_rm_entry, %ebx
+
+       call    prot_to_real
+       .code16
+
+       pushl   %ebx
+       pushl   %edx
+       pushw   %cx
+       movw    %sp, %bx
+       lcall   *%ss:6(%bx)
+       cld
+       addw    $10, %sp
+       movw    %ax, %cx
+
+       DATA32  call    real_to_prot
+       .code32
+
+       movzwl  %cx, %eax
+
+       popl    %ebx
+       popl    %edi
+       popl    %esi
+       popl    %ebp
+       ret
diff --git a/kern/i386/pit.c b/kern/i386/pit.c
new file mode 100644 (file)
index 0000000..82a17d3
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *  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/i386/io.h>
+#include <grub/i386/pit.h>
+
+#define TIMER2_REG_CONTROL     0x42
+#define TIMER_REG_COMMAND      0x43
+#define TIMER2_REG_LATCH       0x61
+
+#define TIMER2_SELECT          0x80
+#define TIMER_ENABLE_LSB       0x20
+#define TIMER_ENABLE_MSB       0x10
+#define TIMER2_LATCH           0x20
+#define TIMER2_SPEAKER         0x02
+#define TIMER2_GATE            0x01
+
+void
+grub_pit_wait (grub_uint16_t tics)
+{
+  /* Disable timer2 gate and speaker.  */
+  grub_outb (grub_inb (TIMER2_REG_LATCH) & ~ (TIMER2_SPEAKER | TIMER2_GATE),
+             TIMER2_REG_LATCH);
+
+  /* Set tics.  */
+  grub_outb (TIMER2_SELECT | TIMER_ENABLE_LSB | TIMER_ENABLE_MSB, TIMER_REG_COMMAND);
+  grub_outb (tics & 0xff, TIMER2_REG_CONTROL);
+  grub_outb (tics >> 8, TIMER2_REG_CONTROL);
+
+  /* Enable timer2 gate, keep speaker disabled.  */
+  grub_outb ((grub_inb (TIMER2_REG_LATCH) & ~ TIMER2_SPEAKER) | TIMER2_GATE,
+             TIMER2_REG_LATCH);
+
+  /* Wait.  */
+  while ((grub_inb (TIMER2_REG_LATCH) & TIMER2_LATCH) == 0x00);
+
+  /* Disable timer2 gate and speaker.  */
+  grub_outb (grub_inb (TIMER2_REG_LATCH) & ~ (TIMER2_SPEAKER | TIMER2_GATE),
+             TIMER2_REG_LATCH);
+}
diff --git a/kern/i386/realmode.S b/kern/i386/realmode.S
new file mode 100644 (file)
index 0000000..680353e
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2005,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/>.
+ */
+
+
+/*
+ * Note: These functions defined in this file may be called from C.
+ *       Be careful of that you must not modify some registers. Quote
+ *       from gcc-2.95.2/gcc/config/i386/i386.h:
+       
+   1 for registers not available across function calls.
+   These must include the FIXED_REGISTERS and also any
+   registers that can be used without being saved.
+   The latter must include the registers where values are returned
+   and the register where structure-value addresses are passed.
+   Aside from that, you can include as many other registers as you like.
+
+  ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg
+{  1, 1, 1, 0, 0, 0, 0, 1, 1,  1,  1,  1,  1,  1,  1,  1,  1 }
+ */
+
+/*
+ * Note: GRUB is compiled with the options -mrtd and -mregparm=3.
+ *       So the first three arguments are passed in %eax, %edx, and %ecx,
+ *       respectively, and if a function has a fixed number of arguments
+ *       and the number if greater than three, the function must return
+ *       with "ret $N" where N is ((the number of arguments) - 3) * 4.
+ */
+
+/*
+ *  This is the area for all of the special variables.
+ */
+
+       .p2align        2       /* force 4-byte alignment */
+
+protstack:
+       .long   GRUB_MEMORY_MACHINE_PROT_STACK
+
+/*
+ * This is the Global Descriptor Table
+ *
+ *  An entry, a "Segment Descriptor", looks like this:
+ *
+ * 31          24         19   16                 7           0
+ * ------------------------------------------------------------
+ * |             | |B| |A|       | |   |1|0|E|W|A|            |
+ * | BASE 31..24 |G|/|L|V| LIMIT |P|DPL|  TYPE   | BASE 23:16 |  4
+ * |             | |D| |L| 19..16| |   |1|1|C|R|A|            |
+ * ------------------------------------------------------------
+ * |                             |                            |
+ * |        BASE 15..0           |       LIMIT 15..0          |  0
+ * |                             |                            |
+ * ------------------------------------------------------------
+ *
+ *  Note the ordering of the data items is reversed from the above
+ *  description.
+ */
+
+       .p2align        2       /* force 4-byte alignment */
+gdt:
+       .word   0, 0
+       .byte   0, 0, 0, 0
+
+       /* -- code segment --
+        * base = 0x00000000, limit = 0xFFFFF (4 KiB Granularity), present
+        * type = 32bit code execute/read, DPL = 0
+        */
+       .word   0xFFFF, 0
+       .byte   0, 0x9A, 0xCF, 0
+
+       /* -- data segment --
+        * base = 0x00000000, limit 0xFFFFF (4 KiB Granularity), present
+        * type = 32 bit data read/write, DPL = 0 
+        */
+       .word   0xFFFF, 0
+       .byte   0, 0x92, 0xCF, 0
+
+       /* -- 16 bit real mode CS --
+        * base = 0x00000000, limit 0x0FFFF (1 B Granularity), present
+        * type = 16 bit code execute/read only/conforming, DPL = 0
+        */
+       .word   0xFFFF, 0
+       .byte   0, 0x9E, 0, 0
+
+       /* -- 16 bit real mode DS --
+        * base = 0x00000000, limit 0x0FFFF (1 B Granularity), present
+        * type = 16 bit data read/write, DPL = 0
+        */
+       .word   0xFFFF, 0
+       .byte   0, 0x92, 0, 0
+
+
+/* this is the GDT descriptor */
+gdtdesc:
+       .word   0x27                    /* limit */
+       .long   gdt                     /* addr */
+
+/*
+ *  These next routine, "prot_to_real" is structured in a very
+ *  specific way.  Be very careful when changing it.
+ *
+ *  NOTE:  Use of it messes up %eax and %ebp.
+ */
+
+prot_to_real:
+       /* just in case, set GDT */
+       lgdt    gdtdesc
+
+       /* save the protected mode stack */
+       movl    %esp, %eax
+       movl    %eax, protstack
+
+       /* get the return address */
+       movl    (%esp), %eax
+       movl    %eax, GRUB_MEMORY_MACHINE_REAL_STACK
+
+       /* set up new stack */
+       movl    $GRUB_MEMORY_MACHINE_REAL_STACK, %eax
+       movl    %eax, %esp
+       movl    %eax, %ebp
+
+       /* set up segment limits */
+       movw    $GRUB_MEMORY_MACHINE_PSEUDO_REAL_DSEG, %ax
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %fs
+       movw    %ax, %gs
+       movw    %ax, %ss
+
+       /* this might be an extra step */
+       /* jump to a 16 bit segment */
+       ljmp    $GRUB_MEMORY_MACHINE_PSEUDO_REAL_CSEG, $tmpcseg
+
+tmpcseg:
+       .code16
+
+       /* clear the PE bit of CR0 */
+       movl    %cr0, %eax
+       andl    $(~GRUB_MEMORY_MACHINE_CR0_PE_ON), %eax
+       movl    %eax, %cr0
+
+       /* flush prefetch queue, reload %cs */
+       DATA32  ljmp    $0, $realcseg
+
+realcseg:
+       /* we are in real mode now
+        * set up the real mode segment registers : DS, SS, ES
+        */
+       /* zero %eax */
+       xorl    %eax, %eax
+
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %fs
+       movw    %ax, %gs
+       movw    %ax, %ss
+
+       /* restore interrupts */
+       sti
+
+       /* return on new stack! */
+       DATA32  ret
+
+       .code32
diff --git a/kern/i386/reboot.c b/kern/i386/reboot.c
new file mode 100644 (file)
index 0000000..d2b0060
--- /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/>.
+ */
+
+#include <grub/cpu/io.h>
+#include <grub/cpu/at_keyboard.h>
+#include <grub/misc.h>
+
+void
+grub_reboot (void)
+{
+  /* Use the keyboard controller to reboot.  That's what keyboards were
+     designed for, isn't it?  */
+  grub_outb (KEYBOARD_COMMAND_REBOOT, KEYBOARD_REG_STATUS);
+
+  grub_printf ("GRUB doesn't know how to reboot this machine yet!\n");
+}
diff --git a/kern/i386/tsc.c b/kern/i386/tsc.c
new file mode 100644 (file)
index 0000000..4d3f05a
--- /dev/null
@@ -0,0 +1,74 @@
+/* kern/i386/tsc.c - x86 TSC time source implementation
+ * Requires Pentium or better x86 CPU that supports the RDTSC instruction.
+ * This module uses the RTC (via grub_get_rtc()) to calibrate the TSC to 
+ * real time.
+ *
+ *  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/time.h>
+#include <grub/misc.h>
+#include <grub/i386/tsc.h>
+#include <grub/i386/pit.h>
+
+/* This defines the value TSC had at the epoch (that is, when we calibrated it). */
+static grub_uint64_t tsc_boot_time;
+
+/* Calibrated TSC rate.  (In TSC ticks per millisecond.) */
+static grub_uint64_t tsc_ticks_per_ms;
+
+
+grub_uint64_t
+grub_tsc_get_time_ms (void)
+{
+  return tsc_boot_time + grub_divmod64 (grub_get_tsc (), tsc_ticks_per_ms, 0);
+}
+
+
+/* How many RTC ticks to use for calibration loop. (>= 1) */
+#define CALIBRATION_TICKS 2
+
+/* Calibrate the TSC based on the RTC.  */
+static void
+calibrate_tsc (void)
+{
+  /* First calibrate the TSC rate (relative, not absolute time). */
+  grub_uint64_t start_tsc;
+  grub_uint64_t end_tsc;
+
+  start_tsc = grub_get_tsc ();
+  grub_pit_wait (0xffff);
+  end_tsc = grub_get_tsc ();
+
+  tsc_ticks_per_ms = grub_divmod64 (end_tsc - start_tsc, 55, 0);
+}
+
+void
+grub_tsc_init (void)
+{
+  if (grub_cpu_is_tsc_supported ())
+    {
+      tsc_boot_time = grub_get_tsc ();
+      calibrate_tsc ();
+      grub_install_get_time_ms (grub_tsc_get_time_ms);
+    }
+  else
+    {
+      grub_install_get_time_ms (grub_rtc_get_time_ms);
+    }
+}
diff --git a/kern/ieee1275/cmain.c b/kern/ieee1275/cmain.c
new file mode 100644 (file)
index 0000000..b5e2ba6
--- /dev/null
@@ -0,0 +1,167 @@
+/* cmain.c - Startup code for the PowerPC.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,2006,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/>.
+ */
+
+#include <alloca.h>
+#include <stdint.h>
+#include <grub/kernel.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/machine/kernel.h>
+#include <grub/ieee1275/ieee1275.h>
+
+int (*grub_ieee1275_entry_fn) (void *);
+
+grub_ieee1275_phandle_t grub_ieee1275_chosen;
+grub_ieee1275_ihandle_t grub_ieee1275_mmu;
+
+static grub_uint32_t grub_ieee1275_flags;
+\f
+
+
+int
+grub_ieee1275_test_flag (enum grub_ieee1275_flag flag)
+{
+  return (grub_ieee1275_flags & (1 << flag));
+}
+
+void
+grub_ieee1275_set_flag (enum grub_ieee1275_flag flag)
+{
+  grub_ieee1275_flags |= (1 << flag);
+}
+
+#define SF "SmartFirmware(tm)"
+#define OHW "PPC Open Hack'Ware"
+
+static void
+grub_ieee1275_find_options (void)
+{
+  grub_ieee1275_phandle_t root;
+  grub_ieee1275_phandle_t options;
+  grub_ieee1275_phandle_t openprom;
+  grub_ieee1275_phandle_t bootrom;
+  int rc;
+  grub_uint32_t realmode = 0;
+  char tmp[32];
+  int is_smartfirmware = 0;
+  int is_olpc = 0;
+
+  grub_ieee1275_finddevice ("/", &root);
+  grub_ieee1275_finddevice ("/options", &options);
+  grub_ieee1275_finddevice ("/openprom", &openprom);
+
+  rc = grub_ieee1275_get_integer_property (options, "real-mode?", &realmode,
+                                          sizeof realmode, 0);
+  if (((rc >= 0) && realmode) || (grub_ieee1275_mmu == 0))
+    grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_REAL_MODE);
+
+  rc = grub_ieee1275_get_property (openprom, "CodeGen-copyright",
+                                  tmp, sizeof (tmp), 0);
+  if (rc >= 0 && !grub_strncmp (tmp, SF, sizeof (SF) - 1))
+    is_smartfirmware = 1;
+
+  rc = grub_ieee1275_get_property (root, "architecture",
+                                  tmp, sizeof (tmp), 0);
+  if (rc >= 0 && !grub_strcmp (tmp, "OLPC"))
+    is_olpc = 1;
+
+  if (is_smartfirmware)
+    {
+      /* Broken in all versions */
+      grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_OUTPUT);
+
+      /* There are two incompatible ways of checking the version number.  Try
+         both. */
+      rc = grub_ieee1275_get_property (openprom, "SmartFirmware-version",
+                                      tmp, sizeof (tmp), 0);
+      if (rc < 0)
+       rc = grub_ieee1275_get_property (openprom, "firmware-version",
+                                        tmp, sizeof (tmp), 0);
+      if (rc >= 0)
+       {
+         /* It is tempting to implement a version parser to set the flags for
+            e.g. 1.3 and below.  However, there's a special situation here.
+            3rd party updates which fix the partition bugs are common, and for
+            some reason their fixes aren't being merged into trunk.  So for
+            example we know that 1.2 and 1.3 are broken, but there's 1.2.99
+            and 1.3.99 which are known good (and applying this workaround
+            would cause breakage). */
+         if (!grub_strcmp (tmp, "1.0")
+             || !grub_strcmp (tmp, "1.1")
+             || !grub_strcmp (tmp, "1.2")
+             || !grub_strcmp (tmp, "1.3"))
+           {
+             grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0);
+             grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS);
+           }
+       }
+    }
+
+  if (is_olpc)
+    {
+      /* OLPC / XO laptops have three kinds of storage devices:
+
+        - NAND flash.  These are accessible via OFW callbacks, but:
+          - Follow strange semantics, imposed by hardware constraints.
+          - Its ABI is undocumented, and not stable.
+          They lack "device_type" property, which conveniently makes GRUB
+          skip them.
+
+        - USB drives.  Not accessible, because OFW shuts down the controller
+          in order to prevent collisions with applications accessing it
+          directly.  Even worse, attempts to access it will NOT return
+          control to the caller, so we have to avoid probing them.
+
+        - SD cards.  These work fine.
+
+        To avoid brekage, we only need to skip USB probing.  However,
+        since detecting SD cards is more reliable, we do that instead.
+      */
+
+      grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY);
+    }
+
+  if (! grub_ieee1275_finddevice ("/rom/boot-rom", &bootrom))
+    {
+      rc = grub_ieee1275_get_property (bootrom, "model", tmp, sizeof (tmp), 0);
+      if (rc >= 0 && !grub_strncmp (tmp, OHW, sizeof (OHW) - 1))
+       {
+         grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_OUTPUT);
+         grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CANNOT_SET_COLORS);
+         grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET);
+         grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM);
+         grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_ANSI);
+       }
+    }
+}
+
+#undef SF
+#undef OHW
+
+void
+grub_ieee1275_init (void)
+{
+  grub_ieee1275_finddevice ("/chosen", &grub_ieee1275_chosen);
+
+  if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen, "mmu", &grub_ieee1275_mmu,
+                                         sizeof grub_ieee1275_mmu, 0) < 0)
+    grub_ieee1275_mmu = 0;
+
+  grub_ieee1275_find_options ();
+}
diff --git a/kern/ieee1275/ieee1275.c b/kern/ieee1275/ieee1275.c
new file mode 100644 (file)
index 0000000..aa48e20
--- /dev/null
@@ -0,0 +1,602 @@
+/* of.c - Access the Open Firmware client interface.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,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/>.
+ */
+
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/types.h>
+
+#define IEEE1275_PHANDLE_INVALID  ((grub_ieee1275_phandle_t) -1)
+#define IEEE1275_IHANDLE_INVALID  ((grub_ieee1275_ihandle_t) 0)
+#define IEEE1275_CELL_INVALID     ((grub_ieee1275_cell_t) -1)
+
+\f
+
+int
+grub_ieee1275_finddevice (char *name, grub_ieee1275_phandle_t *phandlep)
+{
+  struct find_device_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t device;
+    grub_ieee1275_phandle_t phandle;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "finddevice", 1, 1);
+  args.device = (grub_ieee1275_cell_t) name;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *phandlep = args.phandle;
+  if (args.phandle == IEEE1275_PHANDLE_INVALID)
+    return -1;
+  return 0;
+}
+
+int
+grub_ieee1275_get_property (grub_ieee1275_phandle_t phandle,
+                           const char *property, void *buf,
+                           grub_size_t size, grub_ssize_t *actual)
+{
+  struct get_property_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_phandle_t phandle;
+    grub_ieee1275_cell_t prop;
+    grub_ieee1275_cell_t buf;
+    grub_ieee1275_cell_t buflen;
+    grub_ieee1275_cell_t size;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "getprop", 4, 1);
+  args.phandle = phandle;
+  args.prop = (grub_ieee1275_cell_t) property;
+  args.buf = (grub_ieee1275_cell_t) buf;
+  args.buflen = (grub_ieee1275_cell_t) size;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  if (actual)
+    *actual = (grub_ssize_t) args.size;
+  if (args.size == IEEE1275_CELL_INVALID)
+    return -1;
+  return 0;
+}
+
+int
+grub_ieee1275_get_integer_property (grub_ieee1275_phandle_t phandle,
+                                   const char *property, grub_uint32_t *buf,
+                                   grub_size_t size, grub_ssize_t *actual)
+{
+  int ret;
+  ret = grub_ieee1275_get_property (phandle, property, (void *) buf, size, actual);
+#ifndef GRUB_CPU_WORDS_BIGENDIAN
+  /* Integer properties are always in big endian.  */
+  if (ret == 0)
+    {
+      unsigned int i;
+      size /= sizeof (grub_uint32_t);
+      for (i = 0; i < size; i++)
+       buf[i] = grub_be_to_cpu32 (buf[i]);
+    }
+#endif
+  return ret;
+}
+
+int
+grub_ieee1275_next_property (grub_ieee1275_phandle_t phandle, char *prev_prop,
+                            char *prop)
+{
+  struct get_property_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_phandle_t phandle;
+    grub_ieee1275_cell_t prev_prop;
+    grub_ieee1275_cell_t next_prop;
+    grub_ieee1275_cell_t flags;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "nextprop", 3, 1);
+  args.phandle = phandle;
+  args.prev_prop = (grub_ieee1275_cell_t) prev_prop;
+  args.next_prop = (grub_ieee1275_cell_t) prop;
+  args.flags = (grub_ieee1275_cell_t) -1;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  return (int) args.flags;
+}
+
+int
+grub_ieee1275_get_property_length (grub_ieee1275_phandle_t phandle, 
+                                  const char *prop, grub_ssize_t *length)
+{
+  struct get_property_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_phandle_t phandle;
+    grub_ieee1275_cell_t prop;
+    grub_ieee1275_cell_t length;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "getproplen", 2, 1);
+  args.phandle = phandle;
+  args.prop = (grub_ieee1275_cell_t) prop;
+  args.length = (grub_ieee1275_cell_t) -1;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *length = args.length;
+  if (args.length == IEEE1275_CELL_INVALID)
+    return -1;
+  return 0;
+}
+
+int
+grub_ieee1275_instance_to_package (grub_ieee1275_ihandle_t ihandle,
+                                  grub_ieee1275_phandle_t *phandlep)
+{
+  struct instance_to_package_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_ihandle_t ihandle;
+    grub_ieee1275_phandle_t phandle;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "instance-to-package", 1, 1);
+  args.ihandle = ihandle;
+  
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *phandlep = args.phandle;
+  if (args.phandle == IEEE1275_PHANDLE_INVALID)
+    return -1;
+  return 0;
+}
+
+int
+grub_ieee1275_package_to_path (grub_ieee1275_phandle_t phandle,
+                              char *path, grub_size_t len,
+                              grub_ssize_t *actual)
+{
+  struct instance_to_package_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_phandle_t phandle;
+    grub_ieee1275_cell_t buf;
+    grub_ieee1275_cell_t buflen;
+    grub_ieee1275_cell_t actual;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "package-to-path", 3, 1);
+  args.phandle = phandle;
+  args.buf = (grub_ieee1275_cell_t) path;
+  args.buflen = (grub_ieee1275_cell_t) len;
+  
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  if (actual)
+    *actual = args.actual;
+  if (args.actual == IEEE1275_CELL_INVALID)
+    return -1;
+  return 0;
+}
+
+int
+grub_ieee1275_instance_to_path (grub_ieee1275_ihandle_t ihandle,
+                               char *path, grub_size_t len,
+                               grub_ssize_t *actual)
+{
+  struct instance_to_path_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_ihandle_t ihandle;
+    grub_ieee1275_cell_t buf;
+    grub_ieee1275_cell_t buflen;
+    grub_ieee1275_cell_t actual;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "instance-to-path", 3, 1);
+  args.ihandle = ihandle;
+  args.buf = (grub_ieee1275_cell_t) path;
+  args.buflen = (grub_ieee1275_cell_t) len;
+  
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  if (actual)
+    *actual = args.actual;
+  if (args.actual == IEEE1275_CELL_INVALID)
+    return -1;
+  return 0;
+}
+
+int
+grub_ieee1275_write (grub_ieee1275_ihandle_t ihandle, void *buffer, 
+                    grub_size_t len, grub_ssize_t *actualp)
+{
+  struct write_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_ihandle_t ihandle;
+    grub_ieee1275_cell_t buf;
+    grub_ieee1275_cell_t len;
+    grub_ieee1275_cell_t actual;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "write", 3, 1);
+  args.ihandle = ihandle;
+  args.buf = (grub_ieee1275_cell_t) buffer;
+  args.len = (grub_ieee1275_cell_t) len;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  if (actualp)
+    *actualp = args.actual;
+  return 0;
+}
+
+int
+grub_ieee1275_read (grub_ieee1275_ihandle_t ihandle, void *buffer,
+                   grub_size_t len, grub_ssize_t *actualp)
+{
+  struct write_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_ihandle_t ihandle;
+    grub_ieee1275_cell_t buf;
+    grub_ieee1275_cell_t len;
+    grub_ieee1275_cell_t actual;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "read", 3, 1);
+  args.ihandle = ihandle;
+  args.buf = (grub_ieee1275_cell_t) buffer;
+  args.len = (grub_ieee1275_cell_t) len;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  if (actualp)
+    *actualp = args.actual;
+  return 0;
+}
+
+int
+grub_ieee1275_seek (grub_ieee1275_ihandle_t ihandle, int pos_hi,
+                   int pos_lo, grub_ssize_t *result)
+{
+  struct write_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_ihandle_t ihandle;
+    grub_ieee1275_cell_t pos_hi;
+    grub_ieee1275_cell_t pos_lo;
+    grub_ieee1275_cell_t result;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "seek", 3, 1);
+  args.ihandle = ihandle;
+  args.pos_hi = (grub_ieee1275_cell_t) pos_hi;
+  args.pos_lo = (grub_ieee1275_cell_t) pos_lo;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  if (result)
+    *result = args.result;
+  return 0;
+}
+
+int
+grub_ieee1275_peer (grub_ieee1275_phandle_t node,
+                   grub_ieee1275_phandle_t *result)
+{
+  struct peer_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_phandle_t node;
+    grub_ieee1275_phandle_t result;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "peer", 1, 1);
+  args.node = node;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *result = args.result;
+  if (args.result == 0)
+    return -1;
+  return 0;
+}
+
+int
+grub_ieee1275_child (grub_ieee1275_phandle_t node,
+                    grub_ieee1275_phandle_t *result)
+{
+  struct child_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_phandle_t node;
+    grub_ieee1275_phandle_t result;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "child", 1, 1);
+  args.node = node;
+  args.result = IEEE1275_PHANDLE_INVALID;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *result = args.result;
+  if (args.result == 0)
+    return -1;
+  return 0;
+}
+
+int
+grub_ieee1275_parent (grub_ieee1275_phandle_t node,
+                     grub_ieee1275_phandle_t *result)
+{
+  struct parent_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_phandle_t node;
+    grub_ieee1275_phandle_t result;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "parent", 1, 1);
+  args.node = node;
+  args.result = IEEE1275_PHANDLE_INVALID;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *result = args.result;
+  return 0;
+}
+
+int
+grub_ieee1275_interpret (const char *command, grub_ieee1275_cell_t *catch)
+{
+  struct enter_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t command;
+    grub_ieee1275_cell_t catch;
+  }
+  args;
+
+  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
+    return -1;
+
+  INIT_IEEE1275_COMMON (&args.common, "interpret", 1, 1);
+  args.command = (grub_ieee1275_cell_t) command;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  if (catch)
+    *catch = args.catch;
+  return 0;
+}
+
+int
+grub_ieee1275_enter (void)
+{
+  struct enter_args
+  {
+    struct grub_ieee1275_common_hdr common;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "enter", 0, 0);
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  return 0;
+}
+
+void
+grub_ieee1275_exit (void)
+{
+  struct exit_args
+  {
+    struct grub_ieee1275_common_hdr common;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "exit", 0, 0);
+
+  IEEE1275_CALL_ENTRY_FN (&args);
+  for (;;) ;
+}
+
+int
+grub_ieee1275_open (const char *path, grub_ieee1275_ihandle_t *result)
+{
+  struct open_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t path;
+    grub_ieee1275_ihandle_t result;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "open", 1, 1);
+  args.path = (grub_ieee1275_cell_t) path;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *result = args.result;
+  if (args.result == IEEE1275_IHANDLE_INVALID)
+    return -1;
+  return 0;
+}
+
+int
+grub_ieee1275_close (grub_ieee1275_ihandle_t ihandle)
+{
+  struct close_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_ihandle_t ihandle;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "close", 1, 0);
+  args.ihandle = ihandle;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  return 0;
+}
+
+int
+grub_ieee1275_claim (grub_addr_t addr, grub_size_t size, unsigned int align,
+                    grub_addr_t *result)
+{
+  struct claim_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t addr;
+    grub_ieee1275_cell_t size;
+    grub_ieee1275_cell_t align;
+    grub_ieee1275_cell_t base;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "claim", 3, 1);
+  args.addr = (grub_ieee1275_cell_t) addr;
+  args.size = (grub_ieee1275_cell_t) size;
+  args.align = (grub_ieee1275_cell_t) align;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  if (result)
+    *result = args.base;
+  if (args.base == IEEE1275_CELL_INVALID)
+    return -1;
+  return 0;
+}
+
+int
+grub_ieee1275_release (grub_addr_t addr, grub_size_t size)
+{
+ struct release_args
+ {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t addr;
+    grub_ieee1275_cell_t size;
+ }
+ args;
+
+  INIT_IEEE1275_COMMON (&args.common, "release", 2, 0);
+  args.addr = addr;
+  args.size = size;
+  
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  return 0;
+}
+
+int
+grub_ieee1275_set_property (grub_ieee1275_phandle_t phandle,
+                           const char *propname, void *buf,
+                           grub_size_t size, grub_ssize_t *actual)
+{
+  struct set_property_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_phandle_t phandle;
+    grub_ieee1275_cell_t propname;
+    grub_ieee1275_cell_t buf;
+    grub_ieee1275_cell_t size;
+    grub_ieee1275_cell_t actual;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "setprop", 4, 1);
+  args.size = (grub_ieee1275_cell_t) size;
+  args.buf = (grub_ieee1275_cell_t) buf;
+  args.propname = (grub_ieee1275_cell_t) propname;
+  args.phandle = (grub_ieee1275_cell_t) phandle;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *actual = args.actual;
+  if ((args.actual == IEEE1275_CELL_INVALID) || (args.actual != args.size))
+    return -1;
+  return 0;
+}
+
+int
+grub_ieee1275_set_color (grub_ieee1275_ihandle_t ihandle,
+                        int index, int r, int g, int b)
+{
+  struct set_color_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    char *method;
+    grub_ieee1275_ihandle_t ihandle;
+    grub_ieee1275_cell_t index;
+    grub_ieee1275_cell_t b;
+    grub_ieee1275_cell_t g;
+    grub_ieee1275_cell_t r;
+    grub_ieee1275_cell_t catch_result;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1);
+  args.method = "color!";
+  args.ihandle = ihandle;
+  args.index = index;
+  args.r = r;
+  args.g = g;
+  args.b = b;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  return args.catch_result;
+}
+
+int
+grub_ieee1275_milliseconds (grub_uint32_t *msecs)
+{
+  struct milliseconds_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t msecs;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "milliseconds", 0, 1);
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+  *msecs = args.msecs;
+  return 0;
+}
diff --git a/kern/ieee1275/init.c b/kern/ieee1275/init.c
new file mode 100644 (file)
index 0000000..d345ba2
--- /dev/null
@@ -0,0 +1,291 @@
+/*  init.c -- Initialize GRUB on the newworld mac (PPC).  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,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/>.
+ */
+
+#include <grub/kernel.h>
+#include <grub/dl.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+#include <grub/partition.h>
+#include <grub/normal.h>
+#include <grub/fs.h>
+#include <grub/setjmp.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/time.h>
+#include <grub/machine/console.h>
+#include <grub/machine/kernel.h>
+#include <grub/cpu/kernel.h>
+#include <grub/ieee1275/ofdisk.h>
+#include <grub/ieee1275/ieee1275.h>
+
+/* The minimal heap size we can live with. */
+#define HEAP_MIN_SIZE          (unsigned long) (2 * 1024 * 1024)
+
+/* The maximum heap size we're going to claim */
+#define HEAP_MAX_SIZE          (unsigned long) (4 * 1024 * 1024)
+
+/* If possible, we will avoid claiming heap above this address, because it
+   seems to cause relocation problems with OSes that link at 4 MiB */
+#define HEAP_MAX_ADDR          (unsigned long) (4 * 1024 * 1024)
+
+extern char _start[];
+extern char _end[];
+
+void
+grub_exit (void)
+{
+  grub_ieee1275_exit ();
+}
+
+/* Translate an OF filesystem path (separated by backslashes), into a GRUB
+   path (separated by forward slashes).  */
+static void
+grub_translate_ieee1275_path (char *filepath)
+{
+  char *backslash;
+
+  backslash = grub_strchr (filepath, '\\');
+  while (backslash != 0)
+    {
+      *backslash = '/';
+      backslash = grub_strchr (filepath, '\\');
+    }
+}
+
+void
+grub_machine_set_prefix (void)
+{
+  char bootpath[64]; /* XXX check length */
+  char *filename;
+  char *prefix;
+
+  if (grub_env_get ("prefix"))
+    /* We already set prefix in grub_machine_init().  */
+    return;
+
+  if (grub_prefix[0])
+    {
+      grub_env_set ("prefix", grub_prefix);
+      /* Prefix is hardcoded in the core image.  */
+      return;
+    }
+
+  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);
+
+  filename = grub_ieee1275_get_filename (bootpath);
+  if (filename)
+    {
+      char *newprefix;
+      char *lastslash = grub_strrchr (filename, '\\');
+
+      /* Truncate at last directory.  */
+      if (lastslash)
+        {
+         *lastslash = '\0';
+         grub_translate_ieee1275_path (filename);
+
+         newprefix = grub_malloc (grub_strlen (prefix)
+                                  + grub_strlen (filename));
+         grub_sprintf (newprefix, "%s%s", prefix, filename);
+         grub_free (prefix);
+         prefix = newprefix;
+       }
+    }
+
+  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)
+{
+  unsigned long total = 0;
+
+  auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type);
+  int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type)
+  {
+    if (type != 1)
+      return 0;
+
+    len -= 1; /* Required for some firmware.  */
+
+    /* Never exceed HEAP_MAX_SIZE  */
+    if (total + len > HEAP_MAX_SIZE)
+      len = HEAP_MAX_SIZE - total;
+
+    /* Avoid claiming anything above HEAP_MAX_ADDR, if possible. */
+    if ((addr < HEAP_MAX_ADDR) &&                              /* if it's too late, don't bother */
+        (addr + len > HEAP_MAX_ADDR) &&                                /* if it wasn't available anyway, don't bother */
+        (total + (HEAP_MAX_ADDR - addr) > HEAP_MIN_SIZE))      /* only limit ourselves when we can afford to */
+       len = HEAP_MAX_ADDR - addr;
+
+    /* In theory, firmware should already prevent this from happening by not
+       listing our own image in /memory/available.  The check below is intended
+       as a safegard in case that doesn't happen.  It does, however, not protect
+       us from corrupting our module area, which extends up to a
+       yet-undetermined region above _end.  */
+    if ((addr < (grub_addr_t) _end) && ((addr + len) > (grub_addr_t) _start))
+      {
+        grub_printf ("Warning: attempt to claim over our own code!\n");
+        len = 0;
+      }
+
+    if (len)
+      {
+       /* Claim and use it.  */
+       if (grub_claimmap (addr, len) < 0)
+         return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+                            "Failed to claim heap at 0x%llx, len 0x%llx\n",
+                            addr, len);
+       grub_mm_init_region ((void *) (grub_addr_t) addr, len);
+      }
+
+    total += len;
+    if (total >= HEAP_MAX_SIZE)
+      return 1;
+
+    return 0;
+  }
+
+  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
+    heap_init (HEAP_MAX_ADDR - HEAP_MIN_SIZE, HEAP_MIN_SIZE, 1);
+  else
+    grub_machine_mmap_iterate (heap_init);
+}
+
+#ifdef __i386__
+
+grub_uint32_t grub_upper_mem;
+
+/* We need to call this before grub_claim_memory.  */
+static void
+grub_get_extended_memory (void)
+{
+  auto int NESTED_FUNC_ATTR find_ext_mem (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type);
+  int NESTED_FUNC_ATTR find_ext_mem (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type)
+    {
+      if (type == 1 && addr == 0x100000)
+        {
+          grub_upper_mem = len;
+          return 1;
+        }
+
+      return 0;
+    }
+
+  grub_machine_mmap_iterate (find_ext_mem);
+}
+
+#endif
+
+static grub_uint64_t ieee1275_get_time_ms (void);
+
+void
+grub_machine_init (void)
+{
+  char args[256];
+  int actual;
+
+  grub_ieee1275_init ();
+
+  grub_console_init ();
+#ifdef __i386__
+  grub_get_extended_memory ();
+#endif
+  grub_claim_heap ();
+  grub_ofdisk_init ();
+
+  /* Process commandline.  */
+  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);
+           }
+       }
+    }
+
+  grub_install_get_time_ms (ieee1275_get_time_ms);
+}
+
+void
+grub_machine_fini (void)
+{
+  grub_ofdisk_fini ();
+  grub_console_fini ();
+}
+
+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)
+{
+  return ALIGN_UP((grub_addr_t) _end + GRUB_MOD_GAP, GRUB_MOD_ALIGN);
+}
diff --git a/kern/ieee1275/mmap.c b/kern/ieee1275/mmap.c
new file mode 100644 (file)
index 0000000..5b30dbb
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,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/>.
+ */
+
+#include <grub/machine/memory.h>
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/types.h>
+
+grub_err_t
+grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t))
+{
+  grub_ieee1275_phandle_t root;
+  grub_ieee1275_phandle_t memory;
+  grub_uint32_t available[32];
+  grub_ssize_t available_size;
+  grub_uint32_t address_cells = 1;
+  grub_uint32_t size_cells = 1;
+  int i;
+
+  /* Determine the format of each entry in `available'.  */
+  grub_ieee1275_finddevice ("/", &root);
+  grub_ieee1275_get_integer_property (root, "#address-cells", &address_cells,
+                                     sizeof address_cells, 0);
+  grub_ieee1275_get_integer_property (root, "#size-cells", &size_cells,
+                                     sizeof size_cells, 0);
+
+  /* Load `/memory/available'.  */
+  if (grub_ieee1275_finddevice ("/memory", &memory))
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                      "Couldn't find /memory node");
+  if (grub_ieee1275_get_integer_property (memory, "available", available,
+                                         sizeof available, &available_size))
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                      "Couldn't examine /memory/available property");
+
+  /* Decode each entry and call `hook'.  */
+  i = 0;
+  available_size /= sizeof (grub_uint32_t);
+  while (i < available_size)
+    {
+      grub_uint64_t address;
+      grub_uint64_t size;
+
+      address = available[i++];
+      if (address_cells == 2)
+       address = (address << 32) | available[i++];
+
+      size = available[i++];
+      if (size_cells == 2)
+       size = (size << 32) | available[i++];
+
+      if (hook (address, size, GRUB_MACHINE_MEMORY_AVAILABLE))
+       break;
+    }
+
+  return grub_errno;
+}
diff --git a/kern/ieee1275/openfw.c b/kern/ieee1275/openfw.c
new file mode 100644 (file)
index 0000000..e88f3b3
--- /dev/null
@@ -0,0 +1,363 @@
+/*  openfw.c -- Open firmware support functions.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,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/>.
+ */
+
+#include <alloca.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/machine/kernel.h>
+#include <grub/ieee1275/ieee1275.h>
+
+enum grub_ieee1275_parse_type
+{
+  GRUB_PARSE_FILENAME,
+  GRUB_PARSE_PARTITION,
+};
+
+/* Walk children of 'devpath', calling hook for each.  */
+grub_err_t
+grub_children_iterate (char *devpath,
+                 int (*hook) (struct grub_ieee1275_devalias *alias))
+{
+  grub_ieee1275_phandle_t dev;
+  grub_ieee1275_phandle_t child;
+
+  if (grub_ieee1275_finddevice (devpath, &dev))
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Unknown device");
+
+  if (grub_ieee1275_child (dev, &child))
+    return grub_error (GRUB_ERR_BAD_DEVICE, "Device has no children");
+
+  do
+    {
+      /* XXX: Don't use hardcoded path lengths.  */
+      char childtype[64];
+      char childpath[64];
+      char childname[64];
+      char fullname[64];
+      struct grub_ieee1275_devalias alias;
+      int actual;
+
+      if (grub_ieee1275_get_property (child, "device_type", &childtype,
+                                     sizeof childtype, &actual))
+       continue;
+
+      if (grub_ieee1275_package_to_path (child, childpath, sizeof childpath,
+                                        &actual))
+       continue;
+
+      if (grub_ieee1275_get_property (child, "name", &childname,
+                                     sizeof childname, &actual))
+       continue;
+
+      grub_sprintf (fullname, "%s/%s", devpath, childname);
+
+      alias.type = childtype;
+      alias.path = childpath;
+      alias.name = fullname;
+      hook (&alias);
+    }
+  while (grub_ieee1275_peer (child, &child));
+
+  return 0;
+}
+
+/* Iterate through all device aliases.  This function can be used to
+   find a device of a specific type.  */
+grub_err_t
+grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias))
+{
+  grub_ieee1275_phandle_t aliases;
+  char aliasname[32];
+  int actual;
+  struct grub_ieee1275_devalias alias;
+
+  if (grub_ieee1275_finddevice ("/aliases", &aliases))
+    return -1;
+
+  /* Find the first property.  */
+  aliasname[0] = '\0';
+
+  while (grub_ieee1275_next_property (aliases, aliasname, aliasname))
+    {
+      grub_ieee1275_phandle_t dev;
+      grub_ssize_t pathlen;
+      char *devpath;
+      /* XXX: This should be large enough for any possible case.  */
+      char devtype[64];
+
+      grub_dprintf ("devalias", "devalias name = %s\n", aliasname);
+
+      grub_ieee1275_get_property_length (aliases, aliasname, &pathlen);
+
+      /* The property `name' is a special case we should skip.  */
+      if (!grub_strcmp (aliasname, "name"))
+       continue;
+
+      devpath = grub_malloc (pathlen);
+      if (! devpath)
+       return grub_errno;
+
+      if (grub_ieee1275_get_property (aliases, aliasname, devpath, pathlen,
+                                     &actual))
+       {
+         grub_dprintf ("devalias", "get_property (%s) failed\n", aliasname);
+         goto nextprop;
+       }
+
+      if (grub_ieee1275_finddevice (devpath, &dev))
+       {
+         grub_dprintf ("devalias", "finddevice (%s) failed\n", devpath);
+         goto nextprop;
+       }
+
+      if (grub_ieee1275_get_property (dev, "device_type", devtype,
+                                     sizeof devtype, &actual))
+       {
+         /* NAND device don't have device_type property.  */
+          devtype[0] = 0;
+       }
+
+      alias.name = aliasname;
+      alias.path = devpath;
+      alias.type = devtype;
+      hook (&alias);
+
+nextprop:
+      grub_free (devpath);
+    }
+
+  return 0;
+}
+
+/* Call the "map" method of /chosen/mmu.  */
+static int
+grub_map (grub_addr_t phys, grub_addr_t virt, grub_uint32_t size,
+                  grub_uint8_t mode)
+{
+  struct map_args {
+    struct grub_ieee1275_common_hdr common;
+    char *method;
+    grub_ieee1275_ihandle_t ihandle;
+    grub_uint32_t mode;
+    grub_uint32_t size;
+    grub_uint32_t virt;
+    grub_uint32_t phys;
+    int catch_result;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1);
+  args.method = "map";
+  args.ihandle = grub_ieee1275_mmu;
+  args.phys = phys;
+  args.virt = virt;
+  args.size = size;
+  args.mode = mode; /* Format is WIMG0PP.  */
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  return args.catch_result;
+}
+
+int
+grub_claimmap (grub_addr_t addr, grub_size_t size)
+{
+  if (grub_ieee1275_claim (addr, size, 0, 0))
+    return -1;
+
+  if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_REAL_MODE)
+      && grub_map (addr, addr, size, 0x00))
+    {
+      grub_printf ("map failed: address 0x%x, size 0x%x\n", addr, size);
+      grub_ieee1275_release (addr, size);
+      return -1;
+    }
+
+  return 0;
+}
+
+/* Get the device arguments of the Open Firmware node name `path'.  */
+static char *
+grub_ieee1275_get_devargs (const char *path)
+{
+  char *colon = grub_strchr (path, ':');
+
+  if (! colon)
+    return 0;
+
+  return grub_strdup (colon + 1);
+}
+
+/* Get the device path of the Open Firmware node name `path'.  */
+static char *
+grub_ieee1275_get_devname (const char *path)
+{
+  char *colon = grub_strchr (path, ':');
+  char *newpath = 0;
+  int pathlen = grub_strlen (path);
+  auto int match_alias (struct grub_ieee1275_devalias *alias);
+
+  int match_alias (struct grub_ieee1275_devalias *curalias)
+    {
+      /* briQ firmware can change capitalization in /chosen/bootpath.  */
+      if (! grub_strncasecmp (curalias->path, path, pathlen))
+        {
+         newpath = grub_strdup (curalias->name);
+         return 1;
+       }
+
+      return 0;
+    }
+
+  if (colon)
+    pathlen = (int)(colon - path);
+
+  /* Try to find an alias for this device.  */
+  grub_devalias_iterate (match_alias);
+
+  if (! newpath)
+    newpath = grub_strndup (path, pathlen);
+
+  return newpath;
+}
+
+static char *
+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))
+    {
+      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Device %s not found\n", device);
+      goto fail;
+    }
+  if (grub_ieee1275_get_property (dev, "device_type", &type, sizeof type, 0))
+    {
+      grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                 "Device %s lacks a device_type property\n", device);
+      goto fail;
+    }
+
+  if (!grub_strcmp ("block", type))
+    {
+      /* The syntax of the device arguments is defined in the CHRP and PReP
+         IEEE1275 bindings: "[partition][,[filename]]".  */
+      char *comma = grub_strchr (args, ',');
+
+      if (ptype == GRUB_PARSE_FILENAME)
+       {
+         if (comma)
+           {
+             char *filepath = comma + 1;
+
+             ret = grub_malloc (grub_strlen (filepath) + 1);
+             /* Make sure filepath has leading backslash.  */
+             if (filepath[0] != '\\')
+               grub_sprintf (ret, "\\%s", filepath);
+             else
+               grub_strcpy (ret, filepath);
+           }
+       }
+      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>".  */
+      grub_printf ("Unsupported type %s for device %s\n", type, device);
+    }
+
+fail:
+  grub_free (device);
+  grub_free (args);
+  return ret;
+}
+
+char *
+grub_ieee1275_get_filename (const char *path)
+{
+  return grub_ieee1275_parse_args (path, GRUB_PARSE_FILENAME);
+}
+
+/* Convert a device name from IEEE1275 syntax to GRUB syntax.  */
+char *
+grub_ieee1275_encode_devname (const char *path)
+{
+  char *device = grub_ieee1275_get_devname (path);
+  char *partition = grub_ieee1275_parse_args (path, GRUB_PARSE_PARTITION);
+  char *encoding;
+
+  if (partition)
+    {
+      unsigned int partno = grub_strtoul (partition, 0, 0);
+
+      if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS))
+       /* GRUB partition 1 is OF partition 0.  */
+       partno++;
+
+      /* Assume partno will require less than five bytes to encode.  */
+      encoding = grub_malloc (grub_strlen (device) + 3 + 5);
+      grub_sprintf (encoding, "(%s,%d)", device, partno);
+    }
+  else
+    {
+      encoding = grub_malloc (grub_strlen (device) + 2);
+      grub_sprintf (encoding, "(%s)", device);
+    }
+
+  grub_free (partition);
+  grub_free (device);
+
+  return encoding;
+}
+
+void
+grub_reboot (void)
+{
+  grub_ieee1275_interpret ("reset-all", 0);
+}
+
+void
+grub_halt (void)
+{
+  /* Not standarized.  We try both known commands.  */
+
+  grub_ieee1275_interpret ("shut-down", 0);
+  grub_ieee1275_interpret ("power-off", 0);
+}
diff --git a/kern/loader.c b/kern/loader.c
new file mode 100644 (file)
index 0000000..2b67d49
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,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/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/kernel.h>
+
+static grub_err_t (*grub_loader_boot_func) (void);
+static grub_err_t (*grub_loader_unload_func) (void);
+static int grub_loader_noreturn;
+
+static int grub_loader_loaded;
+
+int
+grub_loader_is_loaded (void)
+{
+  return grub_loader_loaded;
+}
+
+void
+grub_loader_set (grub_err_t (*boot) (void),
+                grub_err_t (*unload) (void),
+                int noreturn)
+{
+  if (grub_loader_loaded && grub_loader_unload_func)
+    grub_loader_unload_func ();
+  
+  grub_loader_boot_func = boot;
+  grub_loader_unload_func = unload;
+  grub_loader_noreturn = noreturn;
+  
+  grub_loader_loaded = 1;
+}
+
+void
+grub_loader_unset(void)
+{
+  if (grub_loader_loaded && grub_loader_unload_func)
+    grub_loader_unload_func ();
+  
+  grub_loader_boot_func = 0;
+  grub_loader_unload_func = 0;
+
+  grub_loader_loaded = 0;
+}
+
+grub_err_t
+grub_loader_boot (void)
+{
+  if (! grub_loader_loaded)
+    return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel");
+
+  if (grub_loader_noreturn)
+    grub_machine_fini ();
+  
+  return (grub_loader_boot_func) ();
+}
+
diff --git a/kern/main.c b/kern/main.c
new file mode 100644 (file)
index 0000000..40300b2
--- /dev/null
@@ -0,0 +1,152 @@
+/* main.c - the kernel main routine */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2005,2006,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/kernel.h>
+#include <grub/misc.h>
+#include <grub/symbol.h>
+#include <grub/dl.h>
+#include <grub/term.h>
+#include <grub/rescue.h>
+#include <grub/file.h>
+#include <grub/device.h>
+#include <grub/env.h>
+#include <grub/mm.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;
+    }
+}
+
+/* Load all modules in core.  */
+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);
+
+      return 0;
+    }
+
+  grub_module_iterate (hook);
+}
+
+/* Write hook for the environment variables of root. Remove surrounding
+   parentheses, if any.  */
+static char *
+grub_env_write_root (struct grub_env_var *var __attribute__ ((unused)),
+                    const char *val)
+{
+  /* XXX Is it better to check the existence of the device?  */
+  grub_size_t len = grub_strlen (val);
+  
+  if (val[0] == '(' && val[len - 1] == ')')
+    return grub_strndup (val + 1, len - 2);
+
+  return grub_strdup (val);
+}
+
+/* Set the root device according to the dl prefix.  */
+static void
+grub_set_root_dev (void)
+{
+  const char *prefix;
+
+  grub_register_variable_hook ("root", 0, grub_env_write_root);
+  grub_env_export ("root");
+  
+  prefix = grub_env_get ("prefix");
+  
+  if (prefix)
+    {
+      char *dev;
+
+      dev = grub_file_get_device_name (prefix);
+      if (dev)
+       {
+         grub_env_set ("root", dev);
+         grub_free (dev);
+       }
+    }
+}
+
+/* Load the normal mode module and execute the normal mode if possible.  */
+static void
+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.  */
+  grub_print_error ();
+}
+
+/* The main routine.  */
+void
+grub_main (void)
+{
+  /* First of all, initialize the machine.  */
+  grub_machine_init ();
+
+  /* Hello.  */
+  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
+  grub_printf ("Welcome to GRUB!\n\n");
+  grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
+
+  /* Load pre-loaded modules and free the space.  */
+  grub_register_exported_symbols ();
+  grub_load_modules ();
+
+  /* It is better to set the root device as soon as possible,
+     for convenience.  */
+  grub_machine_set_prefix ();
+  grub_env_export ("prefix");
+  grub_set_root_dev ();
+
+  /* Load the normal mode module.  */
+  grub_load_normal_mode ();
+  
+  /* Enter the rescue mode.  */
+  grub_enter_rescue_mode ();
+}
diff --git a/kern/misc.c b/kern/misc.c
new file mode 100644 (file)
index 0000000..641bd7a
--- /dev/null
@@ -0,0 +1,1089 @@
+/* misc.c - definitions of misc functions */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,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/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <stdarg.h>
+#include <grub/term.h>
+#include <grub/env.h>
+
+void *
+grub_memmove (void *dest, const void *src, grub_size_t n)
+{
+  char *d = (char *) dest;
+  const char *s = (const char *) src;
+
+  if (d < s)
+    while (n--)
+      *d++ = *s++;
+  else
+    {
+      d += n;
+      s += n;
+      
+      while (n--)
+       *--d = *--s;
+    }
+  
+  return dest;
+}
+void *memmove (void *dest, const void *src, grub_size_t n)
+  __attribute__ ((alias ("grub_memmove")));
+/* GCC emits references to memcpy() for struct copies etc.  */
+void *memcpy (void *dest, const void *src, grub_size_t n)
+  __attribute__ ((alias ("grub_memmove")));
+
+char *
+grub_strcpy (char *dest, const char *src)
+{
+  char *p = dest;
+
+  while ((*p++ = *src++) != '\0')
+    ;
+
+  return dest;
+}
+
+char *
+grub_strncpy (char *dest, const char *src, int c)
+{
+  char *p = dest;
+  
+  while ((*p++ = *src++) != '\0' && --c)
+    ;
+
+  return dest;
+}
+
+char *
+grub_stpcpy (char *dest, const char *src)
+{
+  char *d = dest;
+  const char *s = src;
+
+  do
+    *d++ = *s;
+  while (*s++ != '\0');
+
+  return d - 1;
+}
+
+char *
+grub_strcat (char *dest, const char *src)
+{
+  char *p = dest;
+
+  while (*p)
+    p++;
+
+  while ((*p = *src) != '\0')
+    {
+      p++;
+      src++;
+    }
+
+  return dest;
+}
+
+char *
+grub_strncat (char *dest, const char *src, int c)
+{
+  char *p = dest;
+
+  while (*p)
+    p++;
+
+  while ((*p = *src) != '\0' && c--)
+    {
+      p++;
+      src++;
+    }
+
+  *p = '\0';
+
+  return dest;
+}
+
+int
+grub_printf (const char *fmt, ...)
+{
+  va_list ap;
+  int ret;
+  
+  va_start (ap, fmt);
+  ret = grub_vprintf (fmt, ap);
+  va_end (ap);
+
+  return ret;
+}  
+
+#ifndef GRUB_UTIL
+int grub_err_printf (const char *fmt, ...)
+__attribute__ ((alias("grub_printf")));
+#endif
+
+void
+grub_real_dprintf (const char *file, const int line, const char *condition,
+                  const char *fmt, ...)
+{
+  va_list args;
+  const char *debug = grub_env_get ("debug");
+  
+  if (! debug)
+    return;
+  
+  if (grub_strword (debug, "all") || grub_strword (debug, condition))
+    {
+      grub_printf ("%s:%d: ", file, line);
+      va_start (args, fmt);
+      grub_vprintf (fmt, args);
+      va_end (args);
+    }
+}
+
+int
+grub_vprintf (const char *fmt, va_list args)
+{
+  int ret;
+
+  ret = grub_vsprintf (0, fmt, args);
+  grub_refresh ();
+  return ret;
+}
+
+int
+grub_memcmp (const void *s1, const void *s2, grub_size_t n)
+{
+  const char *t1 = s1;
+  const char *t2 = s2;
+  
+  while (n--)
+    {
+      if (*t1 != *t2)
+       return (int) *t1 - (int) *t2;
+
+      t1++;
+      t2++;
+    }
+
+  return 0;
+}
+int memcmp (const void *s1, const void *s2, grub_size_t n)
+  __attribute__ ((alias ("grub_memcmp")));
+
+int
+grub_strcmp (const char *s1, const char *s2)
+{
+  while (*s1 && *s2)
+    {
+      if (*s1 != *s2)
+       break;
+      
+      s1++;
+      s2++;
+    }
+
+  return (int) *s1 - (int) *s2;
+}
+
+int
+grub_strncmp (const char *s1, const char *s2, grub_size_t n)
+{
+  if (n == 0)
+    return 0;
+  
+  while (*s1 && *s2 && --n)
+    {
+      if (*s1 != *s2)
+       break;
+      
+      s1++;
+      s2++;
+    }
+
+  return (int) *s1 - (int) *s2;
+}
+
+int
+grub_strcasecmp (const char *s1, const char *s2)
+{
+  while (*s1 && *s2)
+    {
+      if (grub_tolower (*s1) != grub_tolower (*s2))
+       break;
+
+      s1++;
+      s2++;
+    }
+
+  return (int) grub_tolower (*s1) - (int) grub_tolower (*s2);
+}
+
+int
+grub_strncasecmp (const char *s1, const char *s2, grub_size_t n)
+{
+  if (n == 0)
+    return 0;
+
+  while (*s1 && *s2 && --n)
+    {
+      if (grub_tolower (*s1) != grub_tolower (*s2))
+       break;
+      
+      s1++;
+      s2++;
+    }
+
+  return (int) grub_tolower (*s1) - (int) grub_tolower (*s2);
+}
+
+char *
+grub_strchr (const char *s, int c)
+{
+  while (*s)
+    {
+      if (*s == c)
+       return (char *) s;
+      s++;
+    }
+
+  return 0;
+}
+
+char *
+grub_strrchr (const char *s, int c)
+{
+  char *p = 0;
+
+  while (*s)
+    {
+      if (*s == c)
+       p = (char *) s;
+      s++;
+    }
+
+  return p;
+}
+
+/* Copied from gnulib.
+   Written by Bruno Haible <bruno@clisp.org>, 2005. */
+char *
+grub_strstr (const char *haystack, const char *needle)
+{
+  /* Be careful not to look at the entire extent of haystack or needle
+     until needed.  This is useful because of these two cases:
+       - haystack may be very long, and a match of needle found early,
+       - needle may be very long, and not even a short initial segment of
+       needle may be found in haystack.  */
+  if (*needle != '\0')
+    {
+      /* Speed up the following searches of needle by caching its first
+        character.  */
+      char b = *needle++;
+      
+      for (;; haystack++)
+       {
+         if (*haystack == '\0')
+           /* No match.  */
+           return NULL;
+         if (*haystack == b)
+           /* The first character matches.  */
+           {
+             const char *rhaystack = haystack + 1;
+             const char *rneedle = needle;
+
+             for (;; rhaystack++, rneedle++)
+               {
+                 if (*rneedle == '\0')
+                   /* Found a match.  */
+                   return (char *) haystack;
+                 if (*rhaystack == '\0')
+                   /* No match.  */
+                   return NULL;
+                 if (*rhaystack != *rneedle)
+                   /* Nothing in this round.  */
+                   break;
+               }
+           }
+       }
+    }
+  else
+    return (char *) haystack;
+}
+
+int
+grub_strword (const char *haystack, const char *needle)
+{
+  const char *n_pos = needle;
+
+  while (grub_iswordseparator (*haystack))
+    haystack++;
+
+  while (*haystack)
+    {
+      /* Crawl both the needle and the haystack word we're on.  */
+      while(*haystack && !grub_iswordseparator (*haystack)
+            && *haystack == *n_pos)
+        {
+          haystack++;
+          n_pos++;
+        }
+
+      /* If we reached the end of both words at the same time, the word
+      is found. If not, eat everything in the haystack that isn't the
+      next word (or the end of string) and "reset" the needle.  */
+      if ( (!*haystack || grub_iswordseparator (*haystack))
+         && (!*n_pos || grub_iswordseparator (*n_pos)))
+        return 1;
+      else
+        {
+          n_pos = needle;
+          while (*haystack && !grub_iswordseparator (*haystack))
+            haystack++;
+          while (grub_iswordseparator (*haystack))
+            haystack++;
+        }
+    }
+
+  return 0;
+}
+
+int
+grub_iswordseparator (int c)
+{
+  return (grub_isspace (c) || c == ',' || c == ';' || c == '|' || c == '&');
+}
+
+int
+grub_isspace (int c)
+{
+  return (c == '\n' || c == '\r' || c == ' ' || c == '\t');
+}
+
+int
+grub_isprint (int c)
+{
+  return (c >= ' ' && c <= '~');
+}
+
+int
+grub_isalpha (int c)
+{
+  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+}
+
+int
+grub_isdigit (int c)
+{
+  return (c >= '0' && c <= '9');
+}
+
+int
+grub_isgraph (int c)
+{
+  return (c >= '!' && c <= '~');
+}
+
+int
+grub_tolower (int c)
+{
+  if (c >= 'A' && c <= 'Z')
+    return c - 'A' + 'a';
+
+  return c;
+}
+
+
+unsigned long
+grub_strtoul (const char *str, char **end, int base)
+{
+  unsigned long long num;
+
+  num = grub_strtoull (str, end, base);
+  if (num > ~0UL)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
+      return ~0UL;
+    }
+
+  return (unsigned long) num;
+}
+
+unsigned long long
+grub_strtoull (const char *str, char **end, int base)
+{
+  unsigned long long num = 0;
+  int found = 0;
+  
+  /* Skip white spaces.  */
+  while (*str && grub_isspace (*str))
+    str++;
+  
+  /* Guess the base, if not specified. The prefix `0x' means 16, and
+     the prefix `0' means 8.  */
+  if (base == 0 && str[0] == '0')
+    {
+      if (str[1] == 'x')
+       {
+         if (base == 0 || base == 16)
+           {
+             base = 16;
+             str += 2;
+           }
+       }
+      else if (str[1] >= '0' && str[1] <= '7')
+       base = 8;
+    }
+  
+  if (base == 0)
+    base = 10;
+
+  while (*str)
+    {
+      unsigned long digit;
+
+      digit = grub_tolower (*str) - '0';
+      if (digit > 9)
+       {
+         digit += '0' - 'a' + 10;
+         if (digit >= (unsigned long) base)
+           break;
+       }
+
+      found = 1;
+
+      /* NUM * BASE + DIGIT > ~0ULL */
+      if (num > grub_divmod64 (~0ULL - digit, base, 0))
+       {
+         grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
+         return ~0ULL;
+       }
+
+      num = num * base + digit;
+      str++;
+    }
+
+  if (! found)
+    {
+      grub_error (GRUB_ERR_BAD_NUMBER, "unrecognized number");
+      return 0;
+    }
+  
+  if (end)
+    *end = (char *) str;
+
+  return num;
+}
+
+char *
+grub_strdup (const char *s)
+{
+  grub_size_t len;
+  char *p;
+  
+  len = grub_strlen (s) + 1;
+  p = (char *) grub_malloc (len);
+  if (! p)
+    return 0;
+
+  return grub_memcpy (p, s, len);
+}
+
+char *
+grub_strndup (const char *s, grub_size_t n)
+{
+  grub_size_t len;
+  char *p;
+  
+  len = grub_strlen (s);
+  if (len > n)
+    len = n;
+  p = (char *) grub_malloc (len + 1);
+  if (! p)
+    return 0;
+  
+  grub_memcpy (p, s, len);
+  p[len] = '\0';
+  return p;
+}
+
+void *
+grub_memset (void *s, int c, grub_size_t n)
+{
+  unsigned char *p = (unsigned char *) s;
+
+  while (n--)
+    *p++ = (unsigned char) c;
+
+  return s;
+}
+void *memset (void *s, int c, grub_size_t n)
+  __attribute__ ((alias ("grub_memset")));
+
+grub_size_t
+grub_strlen (const char *s)
+{
+  const char *p = s;
+
+  while (*p)
+    p++;
+
+  return p - s;
+}
+
+static inline void
+grub_reverse (char *str)
+{
+  char *p = str + grub_strlen (str) - 1;
+
+  while (str < p)
+    {
+      char tmp;
+
+      tmp = *str;
+      *str = *p;
+      *p = tmp;
+      str++;
+      p--;
+    }
+}
+
+static char *
+grub_itoa (char *str, int c, unsigned n)
+{
+  unsigned base = (c == 'x') ? 16 : 10;
+  char *p;
+  
+  if ((int) n < 0 && c == 'd')
+    {
+      n = (unsigned) (-((int) n));
+      *str++ = '-';
+    }
+
+  p = str;
+  do
+    {
+      unsigned d = n % base;
+      *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
+    }
+  while (n /= base);
+  *p = 0;
+
+  grub_reverse (str);
+  return p;
+}
+
+/* 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)
+{
+  /* 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
+     represents the high 64 bits in 128-bits space.  */
+  unsigned bits = 64;
+  unsigned long long q = 0;
+  unsigned m = 0;
+
+  /* Skip the slow computation if 32-bit arithmetic is possible.  */
+  if (n < 0xffffffff)
+    {
+      if (r)
+       *r = ((grub_uint32_t) n) % d;
+
+      return ((grub_uint32_t) n) / d;
+    }
+  
+  while (bits--)
+    {
+      m <<= 1;
+      
+      if (n & (1ULL << 63))
+       m |= 1;
+      
+      q <<= 1;
+      n <<= 1;
+      
+      if (m >= d)
+       {
+         q |= 1;
+         m -= d;
+       }
+    }
+
+  if (r)
+    *r = m;
+  
+  return q;
+}
+
+/* Convert a long long value to a string. This function avoids 64-bit
+   modular arithmetic or divisions.  */
+static char *
+grub_lltoa (char *str, int c, unsigned long long n)
+{
+  unsigned base = (c == 'x') ? 16 : 10;
+  char *p;
+  
+  if ((long long) n < 0 && c == 'd')
+    {
+      n = (unsigned long long) (-((long long) n));
+      *str++ = '-';
+    }
+
+  p = str;
+
+  if (base == 16)
+    do
+      {
+       unsigned d = (unsigned) (n & 0xf);
+       *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
+      }
+    while (n >>= 4);
+  else
+    /* BASE == 10 */
+    do
+      {
+       unsigned m;
+       
+       n = grub_divmod64 (n, 10, &m);
+       *p++ = m + '0';
+      }
+    while (n);
+  
+  *p = 0;
+
+  grub_reverse (str);
+  return p;
+}
+
+int
+grub_vsprintf (char *str, const char *fmt, va_list args)
+{
+  char c;
+  int count = 0;
+  auto void write_char (unsigned char ch);
+  auto void write_str (const char *s);
+  auto void write_fill (const char ch, int n);
+  
+  void write_char (unsigned char ch)
+    {
+      if (str)
+       *str++ = ch;
+      else
+       grub_putchar (ch);
+
+      count++;
+    }
+
+  void write_str (const char *s)
+    {
+      while (*s)
+       write_char (*s++);
+    }
+
+  void write_fill (const char ch, int n)
+    {
+      int i;
+      for (i = 0; i < n; i++)
+       write_char (ch);
+    }
+  
+  while ((c = *fmt++) != 0)
+    {
+      if (c != '%')
+       write_char (c);
+      else
+       {
+         char tmp[32];
+         char *p;
+         unsigned int format1 = 0;
+         unsigned int format2 = ~ 0U;
+         char zerofill = ' ';
+         int rightfill = 0;
+         int n;
+         int longfmt = 0;
+         int longlongfmt = 0;
+
+         if (*fmt && *fmt =='-')
+           {
+             rightfill = 1;
+             fmt++;
+           }
+
+         p = (char *) fmt;
+         /* Read formatting parameters.  */
+         while (*p && grub_isdigit (*p))
+           p++;
+
+         if (p > fmt)
+           {
+             char s[p - fmt + 1];
+             grub_strncpy (s, fmt, p - fmt);
+             s[p - fmt] = 0;
+             if (s[0] == '0')
+               zerofill = '0';
+             format1 = grub_strtoul (s, 0, 10);
+             fmt = p;
+           }
+
+         if (*p && *p == '.')
+           {
+             p++;
+             fmt++;
+             while (*p && grub_isdigit (*p))
+               p++;
+
+             if (p > fmt)
+               {
+                 char fstr[p - fmt + 1];
+                 grub_strncpy (fstr, fmt, p - fmt);
+                 fstr[p - fmt] = 0;
+                 format2 = grub_strtoul (fstr, 0, 10);
+                 fmt = p;
+               }
+           }
+
+         c = *fmt++;
+         if (c == 'l')
+           {
+             longfmt = 1;
+             c = *fmt++;
+             if (c == 'l')
+               {
+                 longlongfmt = 1;
+                 c = *fmt++;
+               }
+           }
+
+         switch (c)
+           {
+           case 'p':
+             write_str ("0x");
+             c = 'x';
+             longlongfmt |= (sizeof (void *) == sizeof (long long));
+             /* fall through */
+           case 'x':
+           case 'u':
+           case 'd':
+             if (longlongfmt)
+               {
+                 long long ll;
+
+                 ll = va_arg (args, long long);
+                 grub_lltoa (tmp, c, ll);
+               }
+             else
+               {
+                 if (longfmt)
+                   n = va_arg (args, long);
+                 else
+                   n = va_arg (args, int);
+                 grub_itoa (tmp, c, n);
+               }
+             if (! rightfill && grub_strlen (tmp) < format1)
+               write_fill (zerofill, format1 - grub_strlen (tmp));
+             write_str (tmp);
+             if (rightfill && grub_strlen (tmp) < format1)
+               write_fill (zerofill, format1 - grub_strlen (tmp));
+             break;
+             
+           case 'c':
+             n = va_arg (args, int);
+             write_char (n & 0xff);
+             break;
+
+           case 'C':
+             {
+               grub_uint32_t code = va_arg (args, grub_uint32_t);
+               int shift;
+               unsigned mask;
+               
+               if (code <= 0x7f)
+                 {
+                   shift = 0;
+                   mask = 0;
+                 }
+               else if (code <= 0x7ff)
+                 {
+                   shift = 6;
+                   mask = 0xc0;
+                 }
+               else if (code <= 0xffff)
+                 {
+                   shift = 12;
+                   mask = 0xe0;
+                 }
+               else if (code <= 0x1fffff)
+                 {
+                   shift = 18;
+                   mask = 0xf0;
+                 }
+               else if (code <= 0x3ffffff)
+                 {
+                   shift = 24;
+                   mask = 0xf8;
+                 }
+               else if (code <= 0x7fffffff)
+                 {
+                   shift = 30;
+                   mask = 0xfc;
+                 }
+               else
+                 {
+                   code = '?';
+                   shift = 0;
+                   mask = 0;
+                 }
+
+               write_char (mask | (code >> shift));
+               
+               for (shift -= 6; shift >= 0; shift -= 6)
+                 write_char (0x80 | (0x3f & (code >> shift)));
+             }
+             break;
+
+           case 's':
+             p = va_arg (args, char *);
+             if (p)
+               {
+                 grub_size_t len = 0;
+                 while (len < format2 && p[len])
+                   len++;
+
+                 if (!rightfill && len < format1)
+                   write_fill (zerofill, format1 - len);
+
+                 grub_size_t i;
+                 for (i = 0; i < len; i++)
+                   write_char (*p++);
+
+                 if (rightfill && len < format1)
+                   write_fill (zerofill, format1 - len);
+               }
+             else
+               write_str ("(null)");
+             
+             break;
+
+           default:
+             write_char (c);
+             break;
+           }
+       }
+    }
+
+  if (str)
+    *str = '\0';
+
+  if (count && !str)
+    grub_refresh ();
+  
+  return count;
+}
+
+int
+grub_sprintf (char *str, const char *fmt, ...)
+{
+  va_list ap;
+  int ret;
+  
+  va_start (ap, fmt);
+  ret = grub_vsprintf (str, fmt, ap);
+  va_end (ap);
+
+  return ret;
+}
+
+/* Convert UTF-16 to UTF-8.  */
+grub_uint8_t *
+grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src,
+                   grub_size_t size)
+{
+  grub_uint32_t code_high = 0;
+
+  while (size--)
+    {
+      grub_uint32_t code = *src++;
+
+      if (code_high)
+       {
+         if (code >= 0xDC00 && code <= 0xDFFF)
+           {
+             /* Surrogate pair.  */
+             code = ((code_high - 0xD800) << 12) + (code - 0xDC00) + 0x10000;
+             
+             *dest++ = (code >> 18) | 0xF0;
+             *dest++ = ((code >> 12) & 0x3F) | 0x80;
+             *dest++ = ((code >> 6) & 0x3F) | 0x80;
+             *dest++ = (code & 0x3F) | 0x80;
+           }
+         else
+           {
+             /* Error...  */
+             *dest++ = '?';
+           }
+
+         code_high = 0;
+       }
+      else
+       {
+         if (code <= 0x007F)
+           *dest++ = code;
+         else if (code <= 0x07FF)
+           {
+             *dest++ = (code >> 6) | 0xC0;
+             *dest++ = (code & 0x3F) | 0x80;
+           }
+         else if (code >= 0xD800 && code <= 0xDBFF)
+           {
+             code_high = code;
+             continue;
+           }
+         else if (code >= 0xDC00 && code <= 0xDFFF)
+           {
+             /* Error... */
+             *dest++ = '?';
+           }
+         else
+           {
+             *dest++ = (code >> 12) | 0xE0;
+             *dest++ = ((code >> 6) & 0x3F) | 0x80;
+             *dest++ = (code & 0x3F) | 0x80;
+           }
+       }
+    }
+
+  return dest;
+}
+
+/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
+   bytes (if SRCSIZE is -1, it is ignored) in length to a UCS-4 string.
+   Return the number of characters converted. DEST must be able to hold
+   at least DESTSIZE characters. If an invalid sequence is found, return -1.
+   If SRCEND is not NULL, then *SRCEND is set to the next byte after the
+   last byte used in SRC.  */
+grub_ssize_t
+grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
+                  const grub_uint8_t *src, grub_size_t srcsize,
+                  const grub_uint8_t **srcend)
+{
+  grub_uint32_t *p = dest;
+  int count = 0;
+  grub_uint32_t code = 0;
+  
+  if (srcend)
+    *srcend = src;
+
+  while (srcsize && destsize)
+    {
+      grub_uint32_t c = *src++;
+      if (srcsize != (grub_size_t)-1)
+       srcsize--;
+      if (count)
+       {
+         if ((c & 0xc0) != 0x80)
+           {
+             /* invalid */
+             return -1;
+           }
+         else
+           {
+             code <<= 6;
+             code |= (c & 0x3f);
+             count--;
+           }
+       }
+      else
+       {
+         if (c == 0)
+           break;
+         
+         if ((c & 0x80) == 0x00)
+           code = c;
+         else if ((c & 0xe0) == 0xc0)
+           {
+             count = 1;
+             code = c & 0x1f;
+           }
+         else if ((c & 0xf0) == 0xe0)
+           {
+             count = 2;
+             code = c & 0x0f;
+           }
+         else if ((c & 0xf8) == 0xf0)
+           {
+             count = 3;
+             code = c & 0x07;
+           }
+         else if ((c & 0xfc) == 0xf8)
+           {
+             count = 4;
+             code = c & 0x03;
+           }
+         else if ((c & 0xfe) == 0xfc)
+           {
+             count = 5;
+             code = c & 0x01;
+           }
+         else
+           return -1;
+       }
+
+      if (count == 0)
+       {
+         *p++ = code;
+         destsize--;
+       }
+    }
+
+  if (srcend)
+    *srcend = src;
+  return p - dest;
+}
+
+/* Abort GRUB. This function does not return.  */
+void
+grub_abort (void)
+{
+  if (grub_term_get_current_output ())
+    {
+      grub_printf ("\nAborted.");
+
+      if (grub_term_get_current_input ())
+       {
+         grub_printf (" Press any key to exit.");
+         grub_getkey ();
+       }
+    }
+
+  grub_exit ();
+}
+/* GCC emits references to abort().  */
+void abort (void) __attribute__ ((alias ("grub_abort")));
+
+#ifdef NEED_ENABLE_EXECUTE_STACK
+/* Some gcc versions generate a call to this function
+   in trampolines for nested functions.  */
+__enable_execute_stack (void *addr __attribute__ ((unused)))
+{
+}
+#endif
+
diff --git a/kern/mm.c b/kern/mm.c
new file mode 100644 (file)
index 0000000..a31dc2e
--- /dev/null
+++ b/kern/mm.c
@@ -0,0 +1,559 @@
+/* mm.c - functions for memory manager */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,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/>.
+ */
+
+/*
+  The design of this memory manager.
+
+  This is a simple implementation of malloc with a few extensions. These are
+  the extensions:
+
+  - memalign is implemented efficiently.
+
+  - multiple regions may be used as free space. They may not be
+  contiguous.
+
+  Regions are managed by a singly linked list, and the meta information is
+  stored in the beginning of each region. Space after the meta information
+  is used to allocate memory.
+
+  The memory space is used as cells instead of bytes for simplicity. This
+  is important for some CPUs which may not access multiple bytes at a time
+  when the first byte is not aligned at a certain boundary (typically,
+  4-byte or 8-byte). The size of each cell is equal to the size of struct
+  grub_mm_header, so the header of each allocated/free block fits into one
+  cell precisely. One cell is 16 bytes on 32-bit platforms and 32 bytes
+  on 64-bit platforms.
+
+  There are two types of blocks: allocated blocks and free blocks.
+
+  In allocated blocks, the header of each block has only its size. Note that
+  this size is based on cells but not on bytes. The header is located right
+  before the returned pointer, that is, the header resides at the previous
+  cell.
+
+  Free blocks constitutes a ring, using a singly linked list. The first free
+  block is pointed to by the meta information of a region. The allocator
+  attempts to pick up the second block instead of the first one. This is
+  a typical optimization against defragmentation, and makes the
+  implementation a bit easier.
+
+  For safety, both allocated blocks and free ones are marked by magic
+  numbers. Whenever anything unexpected is detected, GRUB aborts the
+  operation.
+ */
+
+#include <config.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/types.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+
+#ifdef MM_DEBUG
+# undef grub_malloc
+# undef grub_realloc
+# undef grub_free
+# undef grub_memalign
+#endif
+
+/* Magic words.  */
+#define GRUB_MM_FREE_MAGIC     0x2d3c2808
+#define GRUB_MM_ALLOC_MAGIC    0x6db08fa4
+
+typedef struct grub_mm_header
+{
+  struct grub_mm_header *next;
+  grub_size_t size;
+  grub_size_t magic;
+#if GRUB_CPU_SIZEOF_VOID_P == 4
+  char padding[4];
+#elif GRUB_CPU_SIZEOF_VOID_P == 8
+  char padding[8];
+#else
+# error "unknown word size"
+#endif
+}
+*grub_mm_header_t;
+
+#if GRUB_CPU_SIZEOF_VOID_P == 4
+# define GRUB_MM_ALIGN_LOG2    4
+#elif GRUB_CPU_SIZEOF_VOID_P == 8
+# define GRUB_MM_ALIGN_LOG2    5
+#endif
+
+#define GRUB_MM_ALIGN  (1 << GRUB_MM_ALIGN_LOG2)
+
+typedef struct grub_mm_region
+{
+  struct grub_mm_header *first;
+  struct grub_mm_region *next;
+  grub_addr_t addr;
+  grub_size_t size;
+}
+*grub_mm_region_t;
+
+\f
+
+static grub_mm_region_t base;
+
+/* Get a header from the pointer PTR, and set *P and *R to a pointer
+   to the header and a pointer to its region, respectively. PTR must
+   be allocated.  */
+static void
+get_header_from_pointer (void *ptr, grub_mm_header_t *p, grub_mm_region_t *r)
+{
+  if ((grub_addr_t) ptr & (GRUB_MM_ALIGN - 1))
+    grub_fatal ("unaligned pointer %p", ptr);
+
+  for (*r = base; *r; *r = (*r)->next)
+    if ((grub_addr_t) ptr > (*r)->addr
+       && (grub_addr_t) ptr <= (*r)->addr + (*r)->size)
+      break;
+
+  if (! *r)
+    grub_fatal ("out of range pointer %p", ptr);
+
+  *p = (grub_mm_header_t) ptr - 1;
+  if ((*p)->magic != GRUB_MM_ALLOC_MAGIC)
+    grub_fatal ("alloc magic is broken at %p", *p);
+}
+
+/* Initialize a region starting from ADDR and whose size is SIZE,
+   to use it as free space.  */
+void
+grub_mm_init_region (void *addr, grub_size_t size)
+{
+  grub_mm_header_t h;
+  grub_mm_region_t r, *p, q;
+
+#if 0
+  grub_printf ("Using memory for heap: start=%p, end=%p\n", addr, addr + (unsigned int) size);
+#endif
+
+  /* If this region is too small, ignore it.  */
+  if (size < GRUB_MM_ALIGN * 2)
+    return;
+
+  /* Allocate a region from the head.  */
+  r = (grub_mm_region_t) (((grub_addr_t) addr + GRUB_MM_ALIGN - 1)
+                         & (~(GRUB_MM_ALIGN - 1)));
+  size -= (char *) r - (char *) addr + sizeof (*r);
+
+  h = (grub_mm_header_t) ((char *) r + GRUB_MM_ALIGN);
+  h->next = h;
+  h->magic = GRUB_MM_FREE_MAGIC;
+  h->size = (size >> GRUB_MM_ALIGN_LOG2);
+
+  r->first = h;
+  r->addr = (grub_addr_t) h;
+  r->size = (h->size << GRUB_MM_ALIGN_LOG2);
+
+  /* Find where to insert this region. Put a smaller one before bigger ones,
+     to prevent fragmentation.  */
+  for (p = &base, q = *p; q; p = &(q->next), q = *p)
+    if (q->size > r->size)
+      break;
+
+  *p = r;
+  r->next = q;
+}
+
+/* Allocate the number of units N with the alignment ALIGN from the ring
+   buffer starting from *FIRST.  ALIGN must be a power of two. Both N and
+   ALIGN are in units of GRUB_MM_ALIGN.  Return a non-NULL if successful,
+   otherwise return NULL.  */
+static void *
+grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
+{
+  grub_mm_header_t p, q;
+
+  /* When everything is allocated side effect is that *first will have alloc
+     magic marked, meaning that there is no room in this region.  */
+  if ((*first)->magic == GRUB_MM_ALLOC_MAGIC)
+    return 0;
+
+  /* Try to search free slot for allocation in this memory region.  */
+  for (q = *first, p = q->next; ; q = p, p = p->next)
+    {
+      grub_off_t extra;
+
+      extra = ((grub_addr_t) (p + 1) >> GRUB_MM_ALIGN_LOG2) % align;
+      if (extra)
+       extra = align - extra;
+
+      if (! p)
+       grub_fatal ("null in the ring");
+
+      if (p->magic != GRUB_MM_FREE_MAGIC)
+       grub_fatal ("free magic is broken at %p: 0x%x", p, p->magic);
+
+      if (p->size >= n + extra)
+       {
+         if (extra == 0 && p->size == n)
+           {
+             /* There is no special alignment requirement and memory block
+                is complete match.
+
+                1. Just mark memory block as allocated and remove it from
+                   free list.
+
+                Result:
+                +---------------+ previous block's next
+                | alloc, size=n |          |
+                +---------------+          v
+              */
+             q->next = p->next;
+             p->magic = GRUB_MM_ALLOC_MAGIC;
+           }
+         else if (extra == 0 || p->size == n + extra)
+           {
+             /* There might be alignment requirement, when taking it into
+                account memory block fits in.
+
+                1. Allocate new area at end of memory block.
+                2. Reduce size of available blocks from original node.
+                3. Mark new area as allocated and "remove" it from free
+                   list.
+
+                Result:
+                +---------------+
+                | free, size-=n | next --+
+                +---------------+        |
+                | alloc, size=n |        |
+                +---------------+        v
+              */
+             p->size -= n;
+             p += p->size;
+             p->size = n;
+             p->magic = GRUB_MM_ALLOC_MAGIC;
+           }
+         else
+           {
+             /* There is alignment requirement and there is room in memory
+                block.  Split memory block to three pieces.
+
+                1. Create new memory block right after section being
+                   allocated.  Mark it as free.
+                2. Add new memory block to free chain.
+                3. Mark current memory block having only extra blocks.
+                4. Advance to aligned block and mark that as allocated and
+                   "remove" it from free list.
+
+                Result:
+                +------------------------------+
+                | free, size=extra             | next --+
+                +------------------------------+        |
+                | alloc, size=n                |        |
+                +------------------------------+        |
+                | free, size=orig.size-extra-n | <------+, next --+
+                +------------------------------+                  v
+              */
+             grub_mm_header_t r;
+
+             r = p + extra + n;
+             r->magic = GRUB_MM_FREE_MAGIC;
+             r->size = p->size - extra - n;
+             r->next = p->next;
+
+             p->size = extra;
+             p->next = r;
+             p += extra;
+             p->size = n;
+             p->magic = GRUB_MM_ALLOC_MAGIC;
+           }
+
+         /* Mark find as a start marker for next allocation to fasten it.
+            This will have side effect of fragmenting memory as small
+            pieces before this will be un-used.  */
+         *first = q;
+
+         return p + 1;
+       }
+
+      /* Search was completed without result.  */
+      if (p == *first)
+       break;
+    }
+
+  return 0;
+}
+
+/* Allocate SIZE bytes with the alignment ALIGN and return the pointer.  */
+void *
+grub_memalign (grub_size_t align, grub_size_t size)
+{
+  grub_mm_region_t r;
+  grub_size_t n = ((size + GRUB_MM_ALIGN - 1) >> GRUB_MM_ALIGN_LOG2) + 1;
+  int count = 0;
+
+  align = (align >> GRUB_MM_ALIGN_LOG2);
+  if (align == 0)
+    align = 1;
+
+ again:
+
+  for (r = base; r; r = r->next)
+    {
+      void *p;
+
+      p = grub_real_malloc (&(r->first), n, align);
+      if (p)
+       return p;
+    }
+
+  /* If failed, increase free memory somehow.  */
+  switch (count)
+    {
+    case 0:
+      /* Invalidate disk caches.  */
+      grub_disk_cache_invalidate_all ();
+      count++;
+      goto again;
+
+    case 1:
+      /* Unload unneeded modules.  */
+      grub_dl_unload_unneeded ();
+      count++;
+      goto again;
+
+    default:
+      break;
+    }
+
+  grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+  return 0;
+}
+
+/* Allocate SIZE bytes and return the pointer.  */
+void *
+grub_malloc (grub_size_t size)
+{
+  return grub_memalign (0, size);
+}
+
+/* Deallocate the pointer PTR.  */
+void
+grub_free (void *ptr)
+{
+  grub_mm_header_t p;
+  grub_mm_region_t r;
+
+  if (! ptr)
+    return;
+
+  get_header_from_pointer (ptr, &p, &r);
+
+  if (r->first->magic == GRUB_MM_ALLOC_MAGIC)
+    {
+      p->magic = GRUB_MM_FREE_MAGIC;
+      r->first = p->next = p;
+    }
+  else
+    {
+      grub_mm_header_t q;
+
+#if 0
+      q = r->first;
+      do
+       {
+         grub_printf ("%s:%d: q=%p, q->size=0x%x, q->magic=0x%x\n",
+                      __FILE__, __LINE__, q, q->size, q->magic);
+         q = q->next;
+       }
+      while (q != r->first);
+#endif
+
+      for (q = r->first; q >= p || q->next <= p; q = q->next)
+       {
+         if (q->magic != GRUB_MM_FREE_MAGIC)
+           grub_fatal ("free magic is broken at %p: 0x%x", q, q->magic);
+
+         if (q >= q->next && (q < p || q->next > p))
+           break;
+       }
+
+      p->magic = GRUB_MM_FREE_MAGIC;
+      p->next = q->next;
+      q->next = p;
+
+      if (p + p->size == p->next)
+       {
+         if (p->next == q)
+           q = p;
+
+         p->next->magic = 0;
+         p->size += p->next->size;
+         p->next = p->next->next;
+       }
+
+      if (q + q->size == p)
+       {
+         p->magic = 0;
+         q->size += p->size;
+         q->next = p->next;
+       }
+
+      r->first = q;
+    }
+}
+
+/* Reallocate SIZE bytes and return the pointer. The contents will be
+   the same as that of PTR.  */
+void *
+grub_realloc (void *ptr, grub_size_t size)
+{
+  grub_mm_header_t p;
+  grub_mm_region_t r;
+  void *q;
+  grub_size_t n;
+
+  if (! ptr)
+    return grub_malloc (size);
+
+  if (! size)
+    {
+      grub_free (ptr);
+      return 0;
+    }
+
+  /* FIXME: Not optimal.  */
+  n = ((size + GRUB_MM_ALIGN - 1) >> GRUB_MM_ALIGN_LOG2) + 1;
+  get_header_from_pointer (ptr, &p, &r);
+
+  if (p->size >= n)
+    return ptr;
+
+  q = grub_malloc (size);
+  if (! q)
+    return q;
+
+  grub_memcpy (q, ptr, size);
+  grub_free (ptr);
+  return q;
+}
+
+#ifdef MM_DEBUG
+int grub_mm_debug = 0;
+
+void
+grub_mm_dump_free (void)
+{
+  grub_mm_region_t r;
+
+  for (r = base; r; r = r->next)
+    {
+      grub_mm_header_t p;
+
+      /* Follow the free list.  */
+      p = r->first;
+      do
+       {
+         if (p->magic != GRUB_MM_FREE_MAGIC)
+           grub_fatal ("free magic is broken at %p: 0x%x", p, p->magic);
+
+         grub_printf ("F:%p:%u:%p\n",
+                      p, (unsigned int) p->size << GRUB_MM_ALIGN_LOG2, p->next);
+         p = p->next;
+       }
+      while (p != r->first);
+    }
+
+  grub_printf ("\n");
+}
+
+void
+grub_mm_dump (unsigned lineno)
+{
+  grub_mm_region_t r;
+
+  grub_printf ("called at line %u\n", lineno);
+  for (r = base; r; r = r->next)
+    {
+      grub_mm_header_t p;
+
+      for (p = (grub_mm_header_t) ((r->addr + GRUB_MM_ALIGN - 1)
+                                  & (~(GRUB_MM_ALIGN - 1)));
+          (grub_addr_t) p < r->addr + r->size;
+          p++)
+       {
+         switch (p->magic)
+           {
+           case GRUB_MM_FREE_MAGIC:
+             grub_printf ("F:%p:%u:%p\n",
+                          p, (unsigned int) p->size << GRUB_MM_ALIGN_LOG2, p->next);
+             break;
+           case GRUB_MM_ALLOC_MAGIC:
+             grub_printf ("A:%p:%u\n", p, (unsigned int) p->size << GRUB_MM_ALIGN_LOG2);
+             break;
+           }
+       }
+    }
+
+  grub_printf ("\n");
+}
+
+void *
+grub_debug_malloc (const char *file, int line, grub_size_t size)
+{
+  void *ptr;
+
+  if (grub_mm_debug)
+    grub_printf ("%s:%d: malloc (0x%x) = ", file, line, size);
+  ptr = grub_malloc (size);
+  if (grub_mm_debug)
+    grub_printf ("%p\n", ptr);
+  return ptr;
+}
+
+void
+grub_debug_free (const char *file, int line, void *ptr)
+{
+  if (grub_mm_debug)
+    grub_printf ("%s:%d: free (%p)\n", file, line, ptr);
+  grub_free (ptr);
+}
+
+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%x) = ", file, line, ptr, size);
+  ptr = grub_realloc (ptr, size);
+  if (grub_mm_debug)
+    grub_printf ("%p\n", ptr);
+  return ptr;
+}
+
+void *
+grub_debug_memalign (const char *file, int line, grub_size_t align,
+                   grub_size_t size)
+{
+  void *ptr;
+
+  if (grub_mm_debug)
+    grub_printf ("%s:%d: memalign (0x%x, 0x%x) = ",
+                file, line, align, size);
+  ptr = grub_memalign (align, size);
+  if (grub_mm_debug)
+    grub_printf ("%p\n", ptr);
+  return ptr;
+}
+
+#endif /* MM_DEBUG */
diff --git a/kern/parser.c b/kern/parser.c
new file mode 100644 (file)
index 0000000..e931853
--- /dev/null
@@ -0,0 +1,229 @@
+/* parser.c - the part of the parser that can return partial tokens */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/parser.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+
+
+/* All the possible state transitions on the command line.  If a
+   transition can not be found, it is assumed that there is no
+   transition and keep_value is assumed to be 1.  */
+static struct grub_parser_state_transition state_transitions[] =
+{
+  { GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_QUOTE, '\'', 0},
+  { GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_DQUOTE, '\"', 0},
+  { GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_VAR, '$', 0},
+  { GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_ESC, '\\', 0},
+
+  { GRUB_PARSER_STATE_ESC, GRUB_PARSER_STATE_TEXT, 0, 1},
+
+  { GRUB_PARSER_STATE_QUOTE, GRUB_PARSER_STATE_TEXT, '\'', 0},
+
+  { GRUB_PARSER_STATE_DQUOTE, GRUB_PARSER_STATE_TEXT, '\"', 0},
+  { GRUB_PARSER_STATE_DQUOTE, GRUB_PARSER_STATE_QVAR, '$', 0},
+
+  { GRUB_PARSER_STATE_VAR, GRUB_PARSER_STATE_VARNAME2, '{', 0},
+  { GRUB_PARSER_STATE_VAR, GRUB_PARSER_STATE_VARNAME, 0, 1},
+  { GRUB_PARSER_STATE_VARNAME, GRUB_PARSER_STATE_TEXT, ' ', 1},
+  { GRUB_PARSER_STATE_VARNAME2, GRUB_PARSER_STATE_TEXT, '}', 0},
+
+  { GRUB_PARSER_STATE_QVAR, GRUB_PARSER_STATE_QVARNAME2, '{', 0},
+  { GRUB_PARSER_STATE_QVAR, GRUB_PARSER_STATE_QVARNAME, 0, 1},
+  { GRUB_PARSER_STATE_QVARNAME, GRUB_PARSER_STATE_DQUOTE, ' ', 1},
+  { GRUB_PARSER_STATE_QVARNAME, GRUB_PARSER_STATE_TEXT, '\"', 0},
+  { GRUB_PARSER_STATE_QVARNAME2, GRUB_PARSER_STATE_DQUOTE, '}', 0},
+
+  { 0, 0, 0, 0}
+};
+
+
+/* Determines the state following STATE, determined by C.  */
+grub_parser_state_t
+grub_parser_cmdline_state (grub_parser_state_t state, char c, char *result)
+{
+  struct grub_parser_state_transition *transition;
+  struct grub_parser_state_transition *next_match = 0;
+  struct grub_parser_state_transition default_transition;
+  int found = 0;
+
+  default_transition.to_state = state;
+  default_transition.keep_value = 1;
+
+  /* Look for a good translation.  */
+  for (transition = state_transitions; transition->from_state; transition++)
+    {
+      /* An exact match was found, use it.  */
+      if (transition->from_state == state && transition->input == c)
+       {
+         found = 1;
+         break;
+       }
+
+      /* A less perfect match was found, use this one if no exact
+        match can be found.  */
+      if (transition->from_state == state && transition->input == 0)
+       next_match = transition;
+    }
+
+  if (! found)
+    {
+      if (next_match)
+       transition = next_match;
+      else
+       transition = &default_transition;
+    }
+
+  if (transition->keep_value)
+    *result = c;
+  else
+    *result = 0;
+  return transition->to_state;
+}
+
+
+grub_err_t
+grub_parser_split_cmdline (const char *cmdline, grub_err_t (*getline) (char **),
+                          int *argc, char ***argv)
+{
+  grub_parser_state_t state = GRUB_PARSER_STATE_TEXT;
+  /* XXX: Fixed size buffer, perhaps this buffer should be dynamically
+     allocated.  */
+  char buffer[1024];
+  char *bp = buffer;
+  char *rd = (char *) cmdline;
+  char varname[200];
+  char *vp = varname;
+  char *args;
+  int i;
+
+  auto int check_varstate (grub_parser_state_t s);
+
+  int check_varstate (grub_parser_state_t s)
+    {
+      return (s == GRUB_PARSER_STATE_VARNAME
+             || s == GRUB_PARSER_STATE_VARNAME2
+             || s == GRUB_PARSER_STATE_QVARNAME
+             || s == GRUB_PARSER_STATE_QVARNAME2);
+    }
+
+  auto void add_var (grub_parser_state_t newstate);
+
+  void add_var (grub_parser_state_t newstate)
+    {
+      char *val;
+
+      /* Check if a variable was being read in and the end of the name
+        was reached.  */
+      if (! (check_varstate (state) && !check_varstate (newstate)))
+       return;
+
+      *(vp++) = '\0';
+      val = grub_env_get (varname);
+      vp = varname;
+      if (! val)
+       return;
+      
+      /* Insert the contents of the variable in the buffer.  */
+      for (; *val; val++)
+       *(bp++) = *val;
+    }
+
+  *argc = 1;
+  do
+    {
+      if (! *rd)
+       {
+         if (getline)
+           getline (&rd);
+         else break;
+       }
+
+      for (; *rd; rd++)
+       {
+         grub_parser_state_t newstate;
+         char use;
+         
+         newstate = grub_parser_cmdline_state (state, *rd, &use);
+
+         /* If a variable was being processed and this character does
+            not describe the variable anymore, write the variable to
+            the buffer.  */
+         add_var (newstate);
+
+         if (check_varstate (newstate))
+           {
+             if (use)
+               *(vp++) = use;
+           }
+         else
+           {
+             if (newstate == GRUB_PARSER_STATE_TEXT
+                 && state != GRUB_PARSER_STATE_ESC && use == ' ')
+               {
+                 /* Don't add more than one argument if multiple
+                    spaces are used.  */
+                 if (bp != buffer && *(bp - 1))
+                   {
+                     *(bp++) = '\0';
+                     (*argc)++;
+                   }
+               }
+             else if (use)
+               *(bp++) = use;
+           }
+         state = newstate;
+       }
+    } while (state != GRUB_PARSER_STATE_TEXT && !check_varstate (state));
+  *(bp++) = '\0';
+
+  /* A special case for when the last character was part of a
+     variable.  */
+  add_var (GRUB_PARSER_STATE_TEXT);
+  
+
+  /* Reserve memory for the return values.  */
+  args = grub_malloc (bp - buffer);
+  if (! args)
+    return grub_errno;
+  grub_memcpy (args, buffer, bp - buffer);
+  
+  *argv = grub_malloc (sizeof (char *) * (*argc + 1));
+  if (! *argv)
+    {
+      grub_free (args);
+      return grub_errno;
+    }
+
+  /* The arguments are separated with 0's, setup argv so it points to
+     the right values.  */
+  bp = args;
+  for (i = 0; i < *argc; i++)
+    {
+      (*argv)[i] = bp;
+      while (*bp)
+       bp++;
+      bp++;
+    }
+
+  (*argc)--;
+
+  return 0;
+}
diff --git a/kern/partition.c b/kern/partition.c
new file mode 100644 (file)
index 0000000..cb0e4f7
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,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/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/partition.h>
+#include <grub/disk.h>
+
+static grub_partition_map_t grub_partition_map_list;
+
+void
+grub_partition_map_register (grub_partition_map_t partmap)
+{
+  partmap->next = grub_partition_map_list;
+  grub_partition_map_list = partmap;
+}
+
+void
+grub_partition_map_unregister (grub_partition_map_t partmap)
+{
+  grub_partition_map_t *p, q;
+  
+  for (p = &grub_partition_map_list, q = *p; q; p = &(q->next), q = q->next)
+    if (q == partmap)
+      {
+        *p = q->next;
+       break;
+      }
+}
+
+int
+grub_partition_map_iterate (int (*hook) (const grub_partition_map_t partmap))
+{
+  grub_partition_map_t p;
+
+  for (p = grub_partition_map_list; p; p = p->next)
+    if (hook (p))
+      return 1;
+
+  return 0;
+}
+
+grub_partition_t
+grub_partition_probe (struct grub_disk *disk, const char *str)
+{
+  grub_partition_t part = 0;
+
+  auto int part_map_probe (const grub_partition_map_t partmap);
+
+  int part_map_probe (const grub_partition_map_t partmap)
+    {
+      part = partmap->probe (disk, str);
+      if (part)
+       return 1;
+
+      if (grub_errno == GRUB_ERR_BAD_PART_TABLE)
+       {
+         /* Continue to next partition map type.  */
+         grub_errno = GRUB_ERR_NONE;
+         return 0;
+       }
+
+      return 1;
+    }
+
+  /* Use the first partition map type found.  */
+  grub_partition_map_iterate (part_map_probe);
+
+  return part;
+}
+
+int
+grub_partition_iterate (struct grub_disk *disk,
+                       int (*hook) (grub_disk_t disk,
+                                    const grub_partition_t partition))
+{
+  grub_partition_map_t partmap = 0;
+  int ret = 0;
+  
+  auto int part_map_iterate (const grub_partition_map_t p);
+  auto int part_map_iterate_hook (grub_disk_t d,
+                                 const grub_partition_t partition);
+
+  int part_map_iterate_hook (grub_disk_t d __attribute__ ((unused)),
+                            const grub_partition_t partition __attribute__ ((unused)))
+    {
+      return 1;
+    }
+  
+  int part_map_iterate (const grub_partition_map_t p)
+    {
+      grub_dprintf ("partition", "Detecting %s...\n", p->name);
+      p->iterate (disk, part_map_iterate_hook);
+
+      if (grub_errno != GRUB_ERR_NONE)
+       {
+         /* Continue to next partition map type.  */
+         grub_dprintf ("partition", "%s detection failed.\n", p->name);
+         grub_errno = GRUB_ERR_NONE;
+         return 0;
+       }
+
+      grub_dprintf ("partition", "%s detection succeeded.\n", p->name);
+      partmap = p;
+      return 1;
+    }
+
+  grub_partition_map_iterate (part_map_iterate);
+  if (partmap)
+    ret = partmap->iterate (disk, hook);
+  
+  return ret;
+}
+
+char *
+grub_partition_get_name (const grub_partition_t partition)
+{
+  return partition->partmap->get_name (partition);
+}
diff --git a/kern/powerpc/cache.S b/kern/powerpc/cache.S
new file mode 100644 (file)
index 0000000..da982af
--- /dev/null
@@ -0,0 +1,48 @@
+/* cache.S - Flush the processor cache for a specific region.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,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/>.
+ */
+
+#define CACHE_LINE_BYTES 32
+
+       .text
+
+       .align 2
+       .globl grub_arch_sync_caches
+grub_arch_sync_caches:
+       /* `address' may not be CACHE_LINE_BYTES-aligned.  */
+       andi. 6, 3, CACHE_LINE_BYTES - 1 /* Find the misalignment.  */
+       add 4, 4, 6 /* Adjust `size' to compensate.  */
+
+       /* Force the dcache lines to memory.  */
+       li 5, 0
+1:     dcbst 5, 3
+       addi 5, 5, CACHE_LINE_BYTES
+       cmpw 5, 4
+       blt 1b
+       sync            /* Force all dcbsts to complete.  */
+
+       /* Invalidate the icache lines.  */
+       li 5, 0
+1:     icbi 5, 3
+       addi 5, 5, CACHE_LINE_BYTES
+       cmpw 5, 4
+       blt 1b
+       sync            /* Force all icbis to complete.  */
+       isync           /* Discard partially executed instructions that were
+                          loaded from the invalid icache.  */
+       blr
diff --git a/kern/powerpc/dl.c b/kern/powerpc/dl.c
new file mode 100644 (file)
index 0000000..0663a96
--- /dev/null
@@ -0,0 +1,138 @@
+/* dl.c - arch-dependent part of loadable module support */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+
+/* Check if EHDR is a valid ELF header.  */
+grub_err_t
+grub_arch_dl_check_header (void *ehdr)
+{
+  Elf32_Ehdr *e = ehdr;
+
+  /* Check the magic numbers.  */
+  if (e->e_ident[EI_CLASS] != ELFCLASS32
+      || e->e_ident[EI_DATA] != ELFDATA2MSB
+      || e->e_machine != EM_PPC)
+    return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic");
+
+  return GRUB_ERR_NONE;
+}
+
+
+/* Relocate symbols.  */
+grub_err_t
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
+{
+  Elf32_Ehdr *e = ehdr;
+  Elf32_Shdr *s;
+  Elf32_Sym *symtab;
+  Elf32_Word entsize;
+  unsigned i;
+  
+  /* Find a symbol table.  */
+  for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf32_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");
+  
+  symtab = (Elf32_Sym *) ((char *) e + s->sh_offset);
+  entsize = s->sh_entsize;
+  
+  for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf32_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)
+         {
+           Elf32_Rela *rel, *max;
+           
+           for (rel = (Elf32_Rela *) ((char *) e + s->sh_offset),
+                  max = rel + s->sh_size / s->sh_entsize;
+                rel < max;
+                rel++)
+             {
+               Elf32_Word *addr;
+               Elf32_Sym *sym;
+               grub_uint32_t value;
+               
+               if (seg->size < rel->r_offset)
+                 return grub_error (GRUB_ERR_BAD_MODULE,
+                                    "reloc offset is out of the segment");
+               
+               addr = (Elf32_Word *) ((char *) seg->addr + rel->r_offset);
+               sym = (Elf32_Sym *) ((char *) symtab
+                                    + entsize * ELF32_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 (ELF32_R_TYPE (rel->r_info))
+                 {
+                 case R_PPC_ADDR16_LO:
+                   *(Elf32_Half *) addr = value;
+                   break;
+                   
+                 case R_PPC_REL24:
+                   {
+                     Elf32_Sword delta = value - (Elf32_Word) addr;
+                     
+                     if (delta << 6 >> 6 != delta)
+                       return grub_error (GRUB_ERR_BAD_MODULE, "Relocation overflow");
+                     *addr = (*addr & 0xfc000003) | (delta & 0x3fffffc);
+                     break;
+                   }
+                   
+                 case R_PPC_ADDR16_HA:
+                   *(Elf32_Half *) addr = (value + 0x8000) >> 16;
+                   break;
+                   
+                 case R_PPC_ADDR32:
+                   *addr = value;
+                   break;
+                   
+                 case R_PPC_REL32:
+                   *addr = value - (Elf32_Word) addr;
+                   break;
+                   
+                 default:
+                   return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                                      "This relocation (%d) is not implemented yet",
+                                      ELF32_R_TYPE (rel->r_info));
+                 }
+             }
+         }
+      }
+  
+  return GRUB_ERR_NONE;
+}
diff --git a/kern/powerpc/ieee1275/startup.S b/kern/powerpc/ieee1275/startup.S
new file mode 100644 (file)
index 0000000..4b18fd7
--- /dev/null
@@ -0,0 +1,64 @@
+/* startup.S - Startup code for the PowerPC.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,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/>.
+ */
+
+#include <grub/symbol.h>
+#include <grub/cpu/kernel.h>
+
+.extern __bss_start
+.extern _end
+
+       .text
+       .align  2
+       .globl  start, _start
+start:
+_start:
+       b       codestart
+
+       . = EXT_C(start) + GRUB_KERNEL_CPU_PREFIX
+
+VARIABLE(grub_prefix)
+       /* to be filled by grub-mkelfimage */
+
+       /*
+        *  Leave some breathing room for the prefix.
+        */
+
+       . = EXT_C(start) + GRUB_KERNEL_CPU_DATA_END
+
+codestart:
+       li      2, 0
+       li      13, 0
+
+       /* Stage1 won't zero BSS for us. In other cases, why not do it again?  */
+       lis     6, (__bss_start - 4)@h
+       ori     6, 6, (__bss_start - 4)@l
+       lis     7, (_end - 4)@h
+       ori     7, 7, (_end - 4)@l
+       subf    7, 6, 7
+       srwi    7, 7, 2 /* We store 4 bytes at a time.  */
+       mtctr   7
+2:     stwu    2, 4(6) /* We know r2 is already 0 from above.  */
+       bdnz    2b
+
+       /* Store r5 in grub_ieee1275_entry_fn.  */
+       lis     9, grub_ieee1275_entry_fn@ha
+       stw     5, grub_ieee1275_entry_fn@l(9)
+
+       bl      grub_main
+1:     b       1b
diff --git a/kern/rescue.c b/kern/rescue.c
new file mode 100644 (file)
index 0000000..e333ab5
--- /dev/null
@@ -0,0 +1,709 @@
+/* rescue.c - rescue mode */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,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/>.
+ */
+
+#include <grub/kernel.h>
+#include <grub/rescue.h>
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/loader.h>
+#include <grub/dl.h>
+#include <grub/partition.h>
+#include <grub/env.h>
+#include <grub/parser.h>
+
+#define GRUB_RESCUE_BUF_SIZE   256
+#define GRUB_RESCUE_MAX_ARGS   20
+
+struct grub_rescue_command
+{
+  const char *name;
+  void (*func) (int argc, char *argv[]);
+  const char *message;
+  struct grub_rescue_command *next;
+};
+typedef struct grub_rescue_command *grub_rescue_command_t;
+
+static char linebuf[GRUB_RESCUE_BUF_SIZE];
+
+static grub_rescue_command_t grub_rescue_command_list;
+
+void
+grub_rescue_register_command (const char *name,
+                             void (*func) (int argc, char *argv[]),
+                             const char *message)
+{
+  grub_rescue_command_t cmd;
+
+  cmd = (grub_rescue_command_t) grub_malloc (sizeof (*cmd));
+  if (! cmd)
+    return;
+
+  cmd->name = name;
+  cmd->func = func;
+  cmd->message = message;
+
+  cmd->next = grub_rescue_command_list;
+  grub_rescue_command_list = cmd;
+}
+
+void
+grub_rescue_unregister_command (const char *name)
+{
+  grub_rescue_command_t *p, q;
+
+  for (p = &grub_rescue_command_list, q = *p; q; p = &(q->next), q = q->next)
+    if (grub_strcmp (name, q->name) == 0)
+      {
+       *p = q->next;
+       grub_free (q);
+       break;
+      }
+}
+
+/* Prompt to input a command and read the line.  */
+static void
+grub_rescue_get_command_line (const char *prompt)
+{
+  int c;
+  int pos = 0;
+  
+  grub_printf (prompt);
+  grub_memset (linebuf, 0, GRUB_RESCUE_BUF_SIZE);
+  
+  while ((c = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && c != '\r')
+    {
+      if (grub_isprint (c))
+       {
+         if (pos < GRUB_RESCUE_BUF_SIZE - 1)
+           {
+             linebuf[pos++] = c;
+             grub_putchar (c);
+           }
+       }
+      else if (c == '\b')
+       {
+         if (pos > 0)
+           {
+             linebuf[--pos] = 0;
+             grub_putchar (c);
+             grub_putchar (' ');
+             grub_putchar (c);
+           }
+       }
+      grub_refresh ();
+    }
+
+  grub_putchar ('\n');
+  grub_refresh ();
+}
+
+/* boot */
+static void
+grub_rescue_cmd_boot (int argc __attribute__ ((unused)),
+                     char *argv[] __attribute__ ((unused)))
+{
+  grub_loader_boot ();
+}
+
+/* cat FILE */
+static void
+grub_rescue_cmd_cat (int argc, char *argv[])
+{
+  grub_file_t file;
+  char buf[GRUB_DISK_SECTOR_SIZE];
+  grub_ssize_t size;
+
+  if (argc < 1)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
+      return;
+    }
+  
+  file = grub_file_open (argv[0]);
+  if (! file)
+    return;
+
+  while ((size = grub_file_read (file, buf, sizeof (buf))) > 0)
+    {
+      int i;
+
+      for (i = 0; i < size; i++)
+       {
+         unsigned char c = buf[i];
+
+         if ((grub_isprint (c) || grub_isspace (c)) && c != '\r')
+           grub_putchar (c);
+         else
+           {
+             grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
+             grub_printf ("<%x>", (int) c);
+             grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
+           }
+       }
+    }
+
+  grub_putchar ('\n');
+  grub_refresh ();
+  grub_file_close (file);
+}
+
+static int
+grub_rescue_print_devices (const char *name)
+{
+  grub_printf ("(%s) ", name);
+  
+  return 0;
+}
+
+static int
+grub_rescue_print_files (const char *filename, int dir)
+{
+  grub_printf ("%s%s ", filename, dir ? "/" : "");
+  
+  return 0;
+}
+
+/* ls [ARG] */
+static void
+grub_rescue_cmd_ls (int argc, char *argv[])
+{
+  if (argc < 1)
+    {
+      grub_device_iterate (grub_rescue_print_devices);
+      grub_putchar ('\n');
+      grub_refresh ();
+    }
+  else
+    {
+      char *device_name;
+      grub_device_t dev;
+      grub_fs_t fs;
+      char *path;
+      
+      device_name = grub_file_get_device_name (argv[0]);
+      dev = grub_device_open (device_name);
+      if (! dev)
+       goto fail;
+
+      fs = grub_fs_probe (dev);
+      path = grub_strchr (argv[0], ')');
+      if (! path)
+       path = argv[0];
+      else
+       path++;
+      
+      if (! path && ! device_name)
+       {
+         grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument");
+         goto fail;
+       }
+      
+      if (! path)
+       {
+         if (grub_errno == GRUB_ERR_UNKNOWN_FS)
+           grub_errno = GRUB_ERR_NONE;
+         
+         grub_printf ("(%s): Filesystem is %s.\n",
+                      device_name, fs ? fs->name : "unknown");
+       }
+      else if (fs)
+       {
+         (fs->dir) (dev, path, grub_rescue_print_files);
+         grub_putchar ('\n');
+         grub_refresh ();
+       }
+
+    fail:
+      if (dev)
+       grub_device_close (dev);
+      
+      grub_free (device_name);
+    }
+}
+
+/* help */
+static void
+grub_rescue_cmd_help (int argc __attribute__ ((unused)),
+                     char *argv[] __attribute__ ((unused)))
+{
+  grub_rescue_command_t p, q;
+
+  /* Sort the commands. This is not a good algorithm, but this is enough,
+     because rescue mode has a small number of commands.  */
+  for (p = grub_rescue_command_list; p; p = p->next)
+    for (q = p->next; q; q = q->next)
+      if (grub_strcmp (p->name, q->name) > 0)
+       {
+         struct grub_rescue_command tmp;
+
+         tmp.name = p->name;
+         tmp.func = p->func;
+         tmp.message = p->message;
+
+         p->name = q->name;
+         p->func = q->func;
+         p->message = q->message;
+
+         q->name = tmp.name;
+         q->func = tmp.func;
+         q->message = tmp.message;
+       }
+
+  /* Print them.  */
+  for (p = grub_rescue_command_list; p; p = p->next)
+    grub_printf ("%s\t%s\n", p->name, p->message);
+}
+
+#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
+
+/* root [DEVICE] */
+static void
+grub_rescue_cmd_root (int argc, char *argv[])
+{
+  grub_device_t dev;
+  grub_fs_t fs;
+
+  if (argc > 0)
+    {
+      char *device_name = grub_file_get_device_name (argv[0]);
+      if (! device_name)
+       return;
+
+      grub_env_set ("root", device_name);
+      grub_free (device_name);
+    }
+  
+  dev = grub_device_open (0);
+  if (! dev)
+    return;
+
+  fs = grub_fs_probe (dev);
+  if (grub_errno == GRUB_ERR_UNKNOWN_FS)
+    grub_errno = GRUB_ERR_NONE;
+  
+  grub_printf ("(%s): Filesystem is %s.\n",
+              grub_env_get ("root"), fs ? fs->name : "unknown");
+  
+  grub_device_close (dev);
+}
+
+#if 0
+static void
+grub_rescue_cmd_testload (int argc, char *argv[])
+{
+  grub_file_t file;
+  char *buf;
+  grub_ssize_t size;
+  grub_ssize_t pos;
+  auto void read_func (unsigned long sector, unsigned offset, unsigned len);
+
+  void read_func (unsigned long sector __attribute__ ((unused)),
+                 unsigned offset __attribute__ ((unused)),
+                 unsigned len __attribute__ ((unused)))
+    {
+      grub_putchar ('.');
+      grub_refresh ();
+    }
+
+  if (argc < 1)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
+      return;
+    }
+  
+  file = grub_file_open (argv[0]);
+  if (! file)
+    return;
+
+  size = grub_file_size (file) & ~(GRUB_DISK_SECTOR_SIZE - 1);
+  if (size == 0)
+    {
+      grub_file_close (file);
+      return;
+    }
+  
+  buf = grub_malloc (size);
+  if (! buf)
+    goto fail;
+
+  grub_printf ("Reading %s sequentially", argv[0]);
+  file->read_hook = read_func;
+  if (grub_file_read (file, buf, size) != size)
+    goto fail;
+  grub_printf (" Done.\n");
+
+  /* Read sequentially again.  */
+  grub_printf ("Reading %s sequentially again", argv[0]);
+  if (grub_file_seek (file, 0) < 0)
+    goto fail;
+  
+  for (pos = 0; pos < size; pos += GRUB_DISK_SECTOR_SIZE)
+    {
+      char sector[GRUB_DISK_SECTOR_SIZE];
+      
+      if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE)
+         != GRUB_DISK_SECTOR_SIZE)
+       goto fail;
+
+      if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0)
+       {
+         grub_printf ("\nDiffers in %d\n", pos);
+         goto fail;
+       }
+    }
+  grub_printf (" Done.\n");
+  
+  /* Read backwards and compare.  */
+  grub_printf ("Reading %s backwards", argv[0]);
+  pos = size;
+  while (pos > 0)
+    {
+      char sector[GRUB_DISK_SECTOR_SIZE];
+      
+      pos -= GRUB_DISK_SECTOR_SIZE;
+      
+      if (grub_file_seek (file, pos) < 0)
+       goto fail;
+      
+      if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE)
+         != GRUB_DISK_SECTOR_SIZE)
+       goto fail;
+
+      if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0)
+       {
+         int i;
+         
+         grub_printf ("\nDiffers in %d\n", pos);
+         
+         for (i = 0; i < GRUB_DISK_SECTOR_SIZE; i++)
+           grub_putchar (buf[pos + i]);
+
+         if (i)
+           grub_refresh ();
+
+         goto fail;
+       }
+    }
+  grub_printf (" Done.\n");
+
+ fail:
+
+  grub_file_close (file);
+  grub_free (buf);
+}
+#endif
+
+/* dump ADDRESS [SIZE] */
+static void
+grub_rescue_cmd_dump (int argc, char *argv[])
+{
+  grub_uint8_t *addr;
+  grub_size_t size = 4;
+  
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no address specified");
+      return;
+    }
+
+  addr = (grub_uint8_t *) grub_strtoul (argv[0], 0, 0);
+  if (grub_errno)
+    return;
+
+  if (argc > 1)
+    size = (grub_size_t) grub_strtoul (argv[1], 0, 0);
+
+  while (size--)
+    {
+      grub_printf ("%x%x ", *addr >> 4, *addr & 0xf);
+      addr++;
+    }
+}
+
+/* insmod MODULE */
+static void
+grub_rescue_cmd_insmod (int argc, char *argv[])
+{
+  char *p;
+  grub_dl_t mod;
+  
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
+      return;
+    }
+
+  p = grub_strchr (argv[0], '/');
+  if (! p)
+    mod = grub_dl_load (argv[0]);
+  else
+    mod = grub_dl_load_file (argv[0]);
+
+  if (mod)
+    grub_dl_ref (mod);
+}
+
+/* rmmod MODULE */
+static void
+grub_rescue_cmd_rmmod (int argc, char *argv[])
+{
+  grub_dl_t mod;
+  
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
+      return;
+    }
+
+  mod = grub_dl_get (argv[0]);
+  if (! mod)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no such module");
+      return;
+    }
+
+  if (grub_dl_unref (mod) <= 0)
+    grub_dl_unload (mod);
+}
+
+/* lsmod */
+static void
+grub_rescue_cmd_lsmod (int argc __attribute__ ((unused)),
+                      char *argv[] __attribute__ ((unused)))
+{
+  auto int print_module (grub_dl_t mod);
+
+  int print_module (grub_dl_t mod)
+    {
+      grub_dl_dep_t dep;
+      
+      grub_printf ("%s\t%d\t\t", mod->name, mod->ref_count);
+      for (dep = mod->dep; dep; dep = dep->next)
+       {
+         if (dep != mod->dep)
+           grub_putchar (',');
+
+         grub_printf ("%s", dep->mod->name);
+       }
+      grub_putchar ('\n');
+      grub_refresh ();
+
+      return 0;
+    }
+
+  grub_printf ("Name\tRef Count\tDependencies\n");
+  grub_dl_iterate (print_module);
+}
+
+/* set ENVVAR=VALUE */
+static void
+grub_rescue_cmd_set (int argc, char *argv[])
+{
+  char *var;
+  char *val;
+
+  auto int print_env (struct grub_env_var *env);
+
+  int print_env (struct grub_env_var *env)
+    {
+      grub_printf ("%s=%s\n", env->name, env->value);
+      return 0;
+    }
+
+  if (argc < 1)
+    {
+      grub_env_iterate (print_env);
+      return;
+    }
+
+  var = argv[0];
+  val = grub_strchr (var, '=');
+  if (! val)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "not an assignment");
+      return;
+    }
+
+  val[0] = 0;
+  grub_env_set (var, val + 1);
+  val[0] = '=';
+}
+
+static void
+grub_rescue_cmd_unset (int argc, char *argv[])
+{
+  if (argc < 1)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no environment variable specified");
+      return;
+    }
+
+  grub_env_unset (argv[0]);
+}
+
+/* exit */
+static void
+grub_rescue_cmd_exit (int argc __attribute__ ((unused)),
+                     char *argv[] __attribute__ ((unused)))
+{
+  grub_exit ();
+}
+
+static void
+attempt_normal_mode (void)
+{
+  grub_rescue_command_t cmd;
+
+  for (cmd = grub_rescue_command_list; cmd; cmd = cmd->next)
+    {
+      if (grub_strcmp ("normal", cmd->name) == 0)
+       {
+         (cmd->func) (0, 0);
+         break;
+       }
+    }
+}
+
+/* Enter the rescue mode.  */
+void
+grub_enter_rescue_mode (void)
+{
+  auto grub_err_t getline (char **line);
+  
+  grub_err_t getline (char **line)
+    {
+      grub_rescue_get_command_line ("> ");
+      *line = linebuf;
+      return 0;
+    }
+
+  /* First of all, attempt to execute the normal mode.  */
+  attempt_normal_mode ();
+
+  grub_printf ("Entering rescue mode...\n");
+  
+  grub_rescue_register_command ("boot", grub_rescue_cmd_boot,
+                               "boot an operating system");
+  grub_rescue_register_command ("cat", grub_rescue_cmd_cat,
+                               "show the contents of a file");
+  grub_rescue_register_command ("help", grub_rescue_cmd_help,
+                               "show this message");
+  grub_rescue_register_command ("ls", grub_rescue_cmd_ls,
+                               "list devices or files");
+  grub_rescue_register_command ("root", grub_rescue_cmd_root,
+                               "set the root device");
+  grub_rescue_register_command ("dump", grub_rescue_cmd_dump,
+                               "dump memory");
+  grub_rescue_register_command ("insmod", grub_rescue_cmd_insmod,
+                               "insert a module");
+  grub_rescue_register_command ("rmmod", grub_rescue_cmd_rmmod,
+                               "remove a module");
+  grub_rescue_register_command ("lsmod", grub_rescue_cmd_lsmod,
+                               "show loaded modules");
+  grub_rescue_register_command ("set", grub_rescue_cmd_set,
+                               "set an environment variable");
+  grub_rescue_register_command ("unset", grub_rescue_cmd_unset,
+                               "remove an environment variable");
+  grub_rescue_register_command ("exit", grub_rescue_cmd_exit,
+                               "exit from GRUB");
+  
+  while (1)
+    {
+      char *line = linebuf;
+      char *name;
+      int n;
+      grub_rescue_command_t cmd;
+      char **args;
+
+      /* Print an error, if any.  */
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+
+      /* Get a command line.  */
+      grub_rescue_get_command_line ("grub rescue> ");
+      if (line[0] == 0)
+       continue;
+
+      if (grub_parser_split_cmdline (line, getline, &n, &args) || n < 0)
+       continue;
+
+      /* In case of an assignment set the environment accordingly
+        instead of calling a function.  */
+      if (n == 0 && grub_strchr (line, '='))
+       {
+         char *val = grub_strchr (args[0], '=');
+         val[0] = 0;
+         grub_env_set (args[0], val + 1);
+         val[0] = '=';
+          grub_free (args[0]);
+         continue;
+       }
+
+      /* Get the command name.  */
+      name = args[0];
+
+      /* If nothing is specified, restart.  */
+      if (*name == '\0')
+        {
+          grub_free (args[0]);
+          continue;
+        }
+
+      /* Find the command and execute it.  */
+      for (cmd = grub_rescue_command_list; cmd; cmd = cmd->next)
+       {
+         if (grub_strcmp (name, cmd->name) == 0)
+           {
+             (cmd->func) (n, &args[1]);
+             break;
+           }
+       }
+      
+      /* If not found, print an error message.  */
+      if (! cmd)
+       {
+         grub_printf ("Unknown command `%s'\n", name);
+         grub_printf ("Try `help' for usage\n");
+       }
+
+      grub_free (args[0]);
+    }
+}
diff --git a/kern/sparc64/cache.S b/kern/sparc64/cache.S
new file mode 100644 (file)
index 0000000..2ebb693
--- /dev/null
@@ -0,0 +1,43 @@
+/* cache.S - Flush the processor cache for a specific region.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/symbol.h>
+
+        .file   "cache.S"
+
+        .text
+
+/*
+ * void grub_arch_sync_caches (void *address, grub_size_t len)
+ */
+FUNCTION(grub_arch_sync_caches)
+        save            %o6,    -0xC,  %o6      ! Get a new register window,
+                                                ! reserve space on stack for
+                                                ! %i0, %i1, %i2
+        brz,pn          %i0,    return          ! Return if address == 0.
+         nop
+        brz,pn          %i1,    return          ! Return if len == 0.
+         clr             %i2                    ! index = 0.
+loop:   flush           %i0 + %i2               ! Flush address + index.
+        cmp             %i1,    %i2             ! Compare len & index .
+        bpos,a,pt       %xcc,   loop            ! If len > index, loop.
+         add            %i2,    8,      %i2     ! Go to next doubleword.
+return: ret                                     ! Restore caller's register
+         restore                                ! window and return.
+
diff --git a/kern/sparc64/dl.c b/kern/sparc64/dl.c
new file mode 100644 (file)
index 0000000..28ea352
--- /dev/null
@@ -0,0 +1,138 @@
+/* dl.c - arch-dependent part of loadable module support */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+
+/* Check if EHDR is a valid ELF header.  */
+grub_err_t
+grub_arch_dl_check_header (void *ehdr)
+{
+  Elf64_Ehdr *e = ehdr;
+
+  /* Check the magic numbers.  */
+  if (e->e_ident[EI_CLASS] != ELFCLASS64
+      || e->e_ident[EI_DATA] != ELFDATA2MSB
+      || e->e_machine != EM_SPARCV9)
+    return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic");
+
+  return GRUB_ERR_NONE;
+}
+
+
+/* Relocate symbols.  */
+grub_err_t
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
+{
+  Elf64_Ehdr *e = ehdr;
+  Elf64_Shdr *s;
+  Elf64_Sym *symtab;
+  Elf64_Word entsize;
+  unsigned i;
+  
+  /* Find a symbol table.  */
+  for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf64_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");
+  
+  symtab = (Elf64_Sym *) ((char *) e + s->sh_offset);
+  entsize = s->sh_entsize;
+  
+  for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf64_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)
+         {
+           Elf64_Rela *rel, *max;
+           
+           for (rel = (Elf64_Rela *) ((char *) e + s->sh_offset),
+                  max = rel + s->sh_size / s->sh_entsize;
+                rel < max;
+                rel++)
+             {
+               Elf64_Word *addr;
+               Elf64_Sym *sym;
+               Elf64_Addr value;
+               
+               if (seg->size < rel->r_offset)
+                 return grub_error (GRUB_ERR_BAD_MODULE,
+                                    "reloc offset is out of the segment");
+               
+               addr = (Elf64_Word *) ((char *) seg->addr + rel->r_offset);
+               sym = (Elf64_Sym *) ((char *) symtab
+                                    + entsize * ELF64_R_SYM (rel->r_info));
+
+               value = sym->st_value + rel->r_addend;
+               switch (ELF64_R_TYPE (rel->r_info))
+                 {
+                  case R_SPARC_32: /* 3 V-word32 */
+                    if (value & 0xFFFFFFFF00000000)
+                      return grub_error (GRUB_ERR_BAD_MODULE,
+                                         "Address out of 32 bits range");
+                    *addr = value;
+                    break;
+                  case R_SPARC_WDISP30: /* 7 V-disp30 */
+                    if (((value - (Elf64_Addr) addr) & 0xFFFFFFFF00000000) &&
+                        ((value - (Elf64_Addr) addr) & 0xFFFFFFFF00000000
+                        != 0xFFFFFFFF00000000))
+                      return grub_error (GRUB_ERR_BAD_MODULE,
+                                         "Displacement out of 30 bits range");
+                    *addr = (*addr & 0xC0000000) |
+                      (((grub_int32_t) ((value - (Elf64_Addr) addr) >> 2)) &
+                       0x3FFFFFFF);
+                    break;
+                  case R_SPARC_HI22: /* 9 V-imm22 */
+                    if (((grub_int32_t) value) & 0xFF00000000)
+                      return grub_error (GRUB_ERR_BAD_MODULE,
+                                         "High address out of 22 bits range");
+                    *addr = (*addr & 0xFFC00000) | ((value >> 10) & 0x3FFFFF);
+                    break;
+                  case R_SPARC_LO10: /* 12 T-simm13 */
+                    *addr = (*addr & 0xFFFFFC00) | (value & 0x3FF);
+                    break;
+                  case R_SPARC_64: /* 32 V-xwords64 */
+                    *(Elf64_Xword *) addr = value;
+                    break;
+                 default:
+                   return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                                      "This relocation (%d) is not implemented yet",
+                                      ELF64_R_TYPE (rel->r_info));
+                 }
+             }
+         }
+      }
+  
+  return GRUB_ERR_NONE;
+}
diff --git a/kern/sparc64/ieee1275/init.c b/kern/sparc64/ieee1275/init.c
new file mode 100644 (file)
index 0000000..a342557
--- /dev/null
@@ -0,0 +1,237 @@
+/*  init.c -- Initialize GRUB on the Ultra Sprac (sparc64).  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,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/>.
+ */
+
+#include <grub/kernel.h>
+#include <grub/dl.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+#include <grub/partition.h>
+#include <grub/normal.h>
+#include <grub/fs.h>
+#include <grub/setjmp.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/time.h>
+#include <grub/machine/console.h>
+#include <grub/machine/kernel.h>
+#include <grub/ieee1275/ofdisk.h>
+#include <grub/ieee1275/ieee1275.h>
+
+/* OpenBoot entry point.  */
+int (*grub_ieee1275_entry_fn) (void *);
+grub_ieee1275_phandle_t grub_ieee1275_chosen;
+static grub_uint32_t grub_ieee1275_flags;
+/* FIXME (sparc64).  */
+static const grub_addr_t grub_heap_start = 0x40000;
+static grub_addr_t grub_heap_len;
+
+void
+_start (uint64_t r0 __attribute__((unused)),
+        uint64_t r1 __attribute__((unused)),
+        uint64_t r2 __attribute__((unused)),
+        uint64_t r3 __attribute__((unused)),
+        uint64_t r4,
+        uint64_t r5 __attribute__((unused)));
+void
+_start (uint64_t r0 __attribute__((unused)),
+        uint64_t r1 __attribute__((unused)),
+        uint64_t r2 __attribute__((unused)),
+        uint64_t r3 __attribute__((unused)),
+        uint64_t r4,
+        uint64_t r5 __attribute__((unused)))
+{
+  grub_ieee1275_entry_fn = (int (*)(void *)) r4;
+
+  grub_ieee1275_finddevice ("/chosen", &grub_ieee1275_chosen);
+
+  /* Now invoke the main function.  */
+  grub_main ();
+
+  /* Never reached.  */
+}
+
+int
+grub_ieee1275_test_flag (enum grub_ieee1275_flag flag)
+{
+  return (grub_ieee1275_flags & (1 << flag));
+}
+
+void
+grub_ieee1275_set_flag (enum grub_ieee1275_flag flag)
+{
+  grub_ieee1275_flags |= (1 << flag);
+}
+
+/* Translate an OF filesystem path (separated by backslashes), into a GRUB
+   path (separated by forward slashes).  */
+static void
+grub_translate_ieee1275_path (char *filepath)
+{
+  char *backslash;
+
+  backslash = grub_strchr (filepath, '\\');
+  while (backslash != 0)
+    {
+      *backslash = '/';
+      backslash = grub_strchr (filepath, '\\');
+    }
+}
+
+void
+grub_machine_set_prefix (void)
+{
+  char bootpath[64]; /* XXX check length */
+  char *filename;
+  char *prefix;
+
+  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);
+
+  filename = grub_ieee1275_get_filename (bootpath);
+  if (filename)
+    {
+      char *newprefix;
+      char *lastslash = grub_strrchr (filename, '\\');
+
+      /* Truncate at last directory.  */
+      if (lastslash)
+        {
+         *lastslash = '\0';
+         grub_translate_ieee1275_path (filename);
+
+         newprefix = grub_malloc (grub_strlen (prefix)
+                                  + grub_strlen (filename));
+         grub_sprintf (newprefix, "%s%s", prefix, filename);
+         grub_free (prefix);
+         prefix = newprefix;
+       }
+    }
+
+  grub_env_set ("prefix", prefix);
+
+  grub_free (filename);
+  grub_free (prefix);
+}
+
+grub_uint64_t ieee1275_get_time_ms (void);
+
+void
+grub_machine_init (void)
+{
+  char *args;
+  grub_ssize_t length;
+
+  grub_console_init ();
+
+  /* FIXME (sparc64).  */
+  grub_heap_len = (grub_addr_t) &_start - 0x1000 - grub_heap_start;
+
+  if (grub_ieee1275_claim (grub_heap_start, grub_heap_len, 0, 0))
+      grub_fatal ("Failed to claim heap at %p, len 0x%x\n", grub_heap_start,
+                  grub_heap_len);
+  grub_mm_init_region ((void *) grub_heap_start, grub_heap_len);
+
+  grub_ofdisk_init ();
+
+  /* Process commandline.  */
+  if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootargs",
+                                         &length) == 0 &&
+      length > 0)
+    {
+      grub_ssize_t i = 0;
+
+      args = grub_malloc (length);
+      grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", args,
+                                 length, 0);
+
+      while (i < length)
+       {
+         char *command = &args[i];
+         char *end;
+         char *val;
+
+         end = grub_strchr (command, ';');
+         if (end == 0)
+           i = length; /* 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);
+           }
+       }
+    }
+
+  grub_install_get_time_ms (ieee1275_get_time_ms);
+}
+
+void
+grub_machine_fini (void)
+{
+  grub_ofdisk_fini ();
+  grub_console_fini ();
+}
+
+void
+grub_exit (void)
+{
+  grub_ieee1275_enter ();
+}
+
+grub_uint64_t
+ieee1275_get_time_ms (void)
+{
+  return grub_get_rtc ();
+}
+
+grub_uint32_t
+grub_get_rtc (void)
+{
+  grub_uint32_t msecs;
+
+  if (grub_ieee1275_milliseconds (&msecs))
+    return 0;
+
+  return msecs;
+}
+
+grub_addr_t
+grub_arch_modules_addr (void)
+{
+  return GRUB_IEEE1275_MODULE_BASE;
+}
diff --git a/kern/sparc64/ieee1275/openfw.c b/kern/sparc64/ieee1275/openfw.c
new file mode 100644 (file)
index 0000000..fe9ee96
--- /dev/null
@@ -0,0 +1,373 @@
+/*  openfw.c -- Open firmware support functions.  */
+/*
+ *  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/>.
+ */
+
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/machine/kernel.h> /* Needed ?  */
+#include <grub/ieee1275/ieee1275.h>
+
+enum grub_ieee1275_parse_type
+{
+  GRUB_PARSE_FILENAME,
+  GRUB_PARSE_PARTITION,
+};
+
+/* Walk children of 'devpath', calling hook for each.  */
+grub_err_t
+grub_children_iterate (char *devpath,
+                 int (*hook) (struct grub_ieee1275_devalias *alias))
+{
+  grub_ieee1275_phandle_t dev;
+  grub_ieee1275_phandle_t child;
+
+  grub_ieee1275_finddevice (devpath, &dev);
+  if (((signed) dev) == -1)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Unknown device");
+
+  grub_ieee1275_child (dev, &child);
+  if (((signed) child) == -1)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "Device has no children");
+
+  do
+    {
+      /* XXX: Don't use hardcoded path lengths.  */
+      char childtype[64];
+      char childpath[64];
+      char childname[64];
+      char fullname[64];
+      struct grub_ieee1275_devalias alias;
+      grub_ssize_t actual;
+
+      grub_ieee1275_get_property (child, "device_type", childtype,
+                                 sizeof childtype, &actual);
+      if (actual == -1)
+       continue;
+
+      grub_ieee1275_package_to_path (child, childpath, sizeof childpath,
+                                    &actual);
+      if (actual == -1)
+       continue;
+
+      grub_ieee1275_get_property (child, "name", childname,
+                                 sizeof childname, &actual);
+      if (actual == -1)
+       continue;
+
+      grub_sprintf (fullname, "%s/%s", devpath, childname);
+
+      alias.type = childtype;
+      alias.path = childpath;
+      alias.name = fullname;
+      hook (&alias);
+    }
+  while (grub_ieee1275_peer (child, &child));
+
+  return 0;
+}
+
+/* Iterate through all device aliases.  This function can be used to
+   find a device of a specific type.  */
+grub_err_t
+grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias))
+{
+  grub_ieee1275_phandle_t devalias;
+  char aliasname[32];
+  grub_ssize_t actual;
+  grub_ieee1275_cell_t flags;
+  struct grub_ieee1275_devalias alias;
+
+  if (grub_ieee1275_finddevice ("/aliases", &devalias))
+    return -1;
+
+  aliasname[0] = '\0';
+
+  while (grub_ieee1275_next_property (devalias, aliasname, aliasname, &flags) != -1
+        && ((signed) flags) != -1 )
+    {
+      grub_ieee1275_phandle_t dev;
+      grub_ssize_t pathlen, typelen;
+      char *devpath, *devtype;
+
+      grub_dprintf ("devalias", "devalias name = %s\n", aliasname);
+      
+      /* The property `name' is a special case we should skip.  */
+      if (!grub_strcmp (aliasname, "name"))
+         continue;
+      
+      grub_ieee1275_get_property_length (devalias, aliasname, &pathlen);
+      devpath = grub_malloc (pathlen);
+      if (! devpath)
+       return grub_errno;
+
+      if (grub_ieee1275_get_property (devalias, aliasname, devpath, pathlen,
+                                     &actual))
+       {
+          grub_dprintf ("devalias", "get_property (%s) failed\n", aliasname);
+         grub_free (devpath);
+         continue;
+       }
+      
+      if (grub_ieee1275_finddevice (devpath, &dev) || ((signed) dev) == -1)
+       {
+         grub_dprintf ("devalias", "finddevice (%s) failed\n", devpath);
+         grub_free (devpath);
+         continue;
+       }
+
+      grub_ieee1275_get_property_length (dev, "device_type", &typelen);
+      devtype = grub_malloc (typelen);
+      if (! devtype)
+      {
+        grub_free (devpath);
+        return grub_errno;
+      }
+      if (grub_ieee1275_get_property (dev, "device_type", devtype, typelen, &actual))
+       {
+         grub_dprintf ("devalias", "get device type failed\n");
+          grub_free (devtype);
+         grub_free (devpath);
+         continue;
+       }
+
+      alias.name = aliasname;
+      alias.path= devpath;
+      alias.type = devtype;
+      if((*hook) (&alias))
+        {
+          grub_free (devtype);
+          grub_free (devpath);
+          break;
+        }
+
+      grub_free (devtype);
+      grub_free (devpath);
+    }
+
+  return 0;
+}
+
+/* FIXME (sparc64) */
+#if 0
+/* Call the "map" method of /chosen/mmu.  */
+static int
+grub_map (grub_addr_t phys, grub_addr_t virt, grub_uint32_t size,
+                  grub_uint8_t mode)
+{
+  struct map_args {
+    struct grub_ieee1275_common_hdr common;
+    char *method;
+    grub_ieee1275_ihandle_t ihandle;
+    grub_uint32_t mode;
+    grub_uint32_t size;
+    grub_uint32_t virt;
+    grub_uint32_t phys;
+    int catch_result;
+  } args;
+  grub_ieee1275_ihandle_t mmu;
+  grub_ssize_t len;
+
+  grub_ieee1275_get_integer_property (grub_ieee1275_chosen, "mmu", &mmu, sizeof mmu,
+                                     &len);
+  if (len != sizeof mmu)
+    return -1;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1);
+  args.method = "map";
+  args.ihandle = mmu;
+  args.phys = phys;
+  args.virt = virt;
+  args.size = size;
+  args.mode = mode; /* Format is WIMG0PP.  */
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  return args.catch_result;
+}
+#endif
+
+int
+grub_claimmap (grub_addr_t addr, grub_size_t size)
+{
+  if (grub_ieee1275_claim (addr, size, 0, 0))
+    return -1;
+  return 0;
+}
+
+/* Get the device arguments of the Open Firmware node name `path'.  */
+static char *
+grub_ieee1275_get_devargs (const char *path)
+{
+  char *colon = grub_strchr (path, ':');
+
+  if (! colon)
+    return 0;
+
+  return grub_strdup (colon + 1);
+}
+
+/* Get the device path of the Open Firmware node name `path'.  */
+static char *
+grub_ieee1275_get_devname (const char *path)
+{
+  char *colon = grub_strchr (path, ':');
+  char *newpath = 0;
+  int pathlen = grub_strlen (path);
+  auto int match_alias (struct grub_ieee1275_devalias *alias);
+
+  int match_alias (struct grub_ieee1275_devalias *curalias)
+    {
+      /* briQ firmware can change capitalization in /chosen/bootpath.  */
+      if (! grub_strncasecmp (curalias->path, path, pathlen))
+        {
+         newpath = grub_strndup (curalias->name, grub_strlen (curalias->name));
+         return 1;
+       }
+
+      return 0;
+    }
+
+  if (colon)
+    pathlen = (int)(colon - path);
+
+  /* Try to find an alias for this device.  */
+  grub_devalias_iterate (match_alias);
+
+  if (! newpath)
+    newpath = grub_strdup (path);
+
+  return newpath;
+}
+
+static char *
+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))
+    {
+      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Device %s not found\n", device);
+      goto fail;
+    }
+  if (grub_ieee1275_get_property (dev, "device_type", type, sizeof type, 0))
+    {
+      grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                 "Device %s lacks a device_type property\n", device);
+      goto fail;
+    }
+
+  if (!grub_strcmp ("block", type))
+    {
+      /* The syntax of the device arguments is defined in the CHRP and PReP
+         IEEE1275 bindings: "[partition][,[filename]]".  */
+      char *comma = grub_strchr (args, ',');
+
+      if (ptype == GRUB_PARSE_FILENAME)
+       {
+         if (comma)
+           {
+             char *filepath = comma + 1;
+
+             ret = grub_malloc (grub_strlen (filepath) + 1);
+             /* Make sure filepath has leading backslash.  */
+             if (filepath[0] != '\\')
+               grub_sprintf (ret, "\\%s", filepath);
+             else
+               grub_strcpy (ret, filepath);
+           }
+       }
+      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>".  */
+      grub_printf ("Unsupported type %s for device %s\n", type, device);
+    }
+
+fail:
+  grub_free (device);
+  grub_free (args);
+  return ret;
+}
+
+char *
+grub_ieee1275_get_filename (const char *path)
+{
+  return grub_ieee1275_parse_args (path, GRUB_PARSE_FILENAME);
+}
+
+/* Convert a device name from IEEE1275 syntax to GRUB syntax.  */
+char *
+grub_ieee1275_encode_devname (const char *path)
+{
+  char *device = grub_ieee1275_get_devname (path);
+  char *partition = grub_ieee1275_parse_args (path, GRUB_PARSE_PARTITION);
+  char *encoding;
+
+  if (partition)
+    {
+      unsigned int partno = grub_strtoul (partition, 0, 0);
+
+      /* Assume partno will require less than five bytes to encode.  */
+      encoding = grub_malloc (grub_strlen (device) + 3 + 5);
+      grub_sprintf (encoding, "(%s,%d)", device, partno);
+    }
+  else
+    {
+      encoding = grub_malloc (grub_strlen (device) + 2);
+      grub_sprintf (encoding, "(%s)", device);
+    }
+
+  grub_free (partition);
+  grub_free (device);
+
+  return encoding;
+}
+
+void
+grub_reboot (void)
+{
+  grub_ieee1275_interpret ("reset-all", 0);
+}
+
+void
+grub_halt (void)
+{
+  grub_ieee1275_interpret ("power-off", 0);
+}
diff --git a/kern/term.c b/kern/term.c
new file mode 100644 (file)
index 0000000..8d5a23b
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,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/>.
+ */
+
+#include <grub/term.h>
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+
+/* The list of terminals.  */
+static grub_term_input_t grub_term_list_input;
+static grub_term_output_t grub_term_list_output;
+
+/* The current terminal.  */
+static grub_term_input_t grub_cur_term_input;
+static grub_term_output_t grub_cur_term_output;
+
+/* The amount of lines counted by the pager.  */
+static int grub_more_lines;
+
+/* If the more pager is active.  */
+static int grub_more;
+
+/* The current cursor state.  */
+static int cursor_state = 1;
+
+void
+grub_term_register_input (grub_term_input_t term)
+{
+  term->next = grub_term_list_input;
+  grub_term_list_input = term;
+  if (! grub_cur_term_input)
+    grub_term_set_current_input (term);
+}
+
+void
+grub_term_register_output (grub_term_output_t term)
+{
+  term->next = grub_term_list_output;
+  grub_term_list_output = term;
+  if (! grub_cur_term_output)
+    grub_term_set_current_output (term);
+}
+
+void
+grub_term_unregister_input (grub_term_input_t term)
+{
+  grub_term_input_t *p, q;
+  
+  for (p = &grub_term_list_input, q = *p; q; p = &(q->next), q = q->next)
+    if (q == term)
+      {
+        *p = q->next;
+       break;
+      }
+}
+
+void
+grub_term_unregister_output (grub_term_output_t term)
+{
+  grub_term_output_t *p, q;
+  
+  for (p = &grub_term_list_output, q = *p; q; p = &(q->next), q = q->next)
+    if (q == term)
+      {
+        *p = q->next;
+       break;
+      }
+}
+
+void
+grub_term_iterate_input (int (*hook) (grub_term_input_t term))
+{
+  grub_term_input_t p;
+  
+  for (p = grub_term_list_input; p; p = p->next)
+    if (hook (p))
+      break;
+}
+
+void
+grub_term_iterate_output (int (*hook) (grub_term_output_t term))
+{
+  grub_term_output_t p;
+  
+  for (p = grub_term_list_output; p; p = p->next)
+    if (hook (p))
+      break;
+}
+
+grub_err_t
+grub_term_set_current_input (grub_term_input_t term)
+{
+  if (grub_cur_term_input && grub_cur_term_input->fini)
+    if ((grub_cur_term_input->fini) () != GRUB_ERR_NONE)
+      return grub_errno;
+
+  if (term->init)
+    if ((term->init) () != GRUB_ERR_NONE)
+      return grub_errno;
+  
+  grub_cur_term_input = term;
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_term_set_current_output (grub_term_output_t term)
+{
+  if (grub_cur_term_output && grub_cur_term_output->fini)
+    if ((grub_cur_term_output->fini) () != GRUB_ERR_NONE)
+      return grub_errno;
+
+  if (term->init)
+    if ((term->init) () != GRUB_ERR_NONE)
+      return grub_errno;
+  
+  grub_cur_term_output = term;
+  return GRUB_ERR_NONE;
+}
+
+grub_term_input_t
+grub_term_get_current_input (void)
+{
+  return grub_cur_term_input;
+}
+
+grub_term_output_t
+grub_term_get_current_output (void)
+{
+  return grub_cur_term_output;
+}
+
+/* Put a Unicode character.  */
+void
+grub_putcode (grub_uint32_t code)
+{
+  int height = grub_getwh () & 255;
+
+  if (code == '\t' && grub_cur_term_output->getxy)
+    {
+      int n;
+      
+      n = 8 - ((grub_getxy () >> 8) & 7);
+      while (n--)
+       grub_putcode (' ');
+
+      return;
+    }
+  
+  (grub_cur_term_output->putchar) (code);
+  
+  if (code == '\n')
+    {
+      grub_putcode ('\r');
+
+      grub_more_lines++;
+
+      if (grub_more && grub_more_lines == height - 1)
+       {
+         char key;
+         int pos = grub_getxy ();
+
+         /* Show --MORE-- on the lower left side of the screen.  */
+         grub_gotoxy (1, height - 1);
+         grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
+         grub_printf ("--MORE--");
+         grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
+
+         key = grub_getkey ();
+         
+         /* Remove the message.  */
+         grub_gotoxy (1, height - 1);
+         grub_printf ("        ");
+         grub_gotoxy (pos >> 8, pos & 0xFF);
+         
+         /* Scroll one lines or an entire page, depending on the key.  */
+         if (key == '\r' || key =='\n')
+           grub_more_lines--;
+         else
+           grub_more_lines = 0;
+       }
+    }
+}
+
+/* Put a character. C is one byte of a UTF-8 stream.
+   This function gathers bytes until a valid Unicode character is found.  */
+void
+grub_putchar (int c)
+{
+  static grub_size_t size = 0;
+  static grub_uint8_t buf[6];
+  grub_uint32_t code;
+  grub_ssize_t ret;
+
+  buf[size++] = c;
+  ret = grub_utf8_to_ucs4 (&code, 1, buf, size, 0);
+  
+  if (ret > 0)
+    {
+      size = 0;
+      grub_putcode (code);
+    }
+  else if (ret < 0)
+    {
+      size = 0;
+      grub_putcode ('?');
+    }
+}
+
+/* Return the number of columns occupied by the character code CODE.  */
+grub_ssize_t
+grub_getcharwidth (grub_uint32_t code)
+{
+  return (grub_cur_term_output->getcharwidth) (code);
+}
+
+int
+grub_getkey (void)
+{
+  return (grub_cur_term_input->getkey) ();
+}
+
+int
+grub_checkkey (void)
+{
+  return (grub_cur_term_input->checkkey) ();
+}
+
+grub_uint16_t
+grub_getxy (void)
+{
+  return (grub_cur_term_output->getxy) ();
+}
+
+grub_uint16_t
+grub_getwh (void)
+{
+  return (grub_cur_term_output->getwh) ();
+}
+
+void
+grub_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+  (grub_cur_term_output->gotoxy) (x, y);
+}
+
+void
+grub_cls (void)
+{
+  if ((grub_cur_term_output->flags & GRUB_TERM_DUMB) || (grub_env_get ("debug")))
+    {
+      grub_putchar ('\n');
+      grub_refresh ();
+    }
+  else
+    (grub_cur_term_output->cls) ();
+}
+
+void
+grub_setcolorstate (grub_term_color_state state)
+{
+  if (grub_cur_term_output->setcolorstate)
+    (grub_cur_term_output->setcolorstate) (state);
+}
+
+void
+grub_setcolor (grub_uint8_t normal_color, grub_uint8_t highlight_color)
+{
+  if (grub_cur_term_output->setcolor)
+    (grub_cur_term_output->setcolor) (normal_color, highlight_color);
+}
+
+void
+grub_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_color)
+{
+  if (grub_cur_term_output->getcolor)
+    (grub_cur_term_output->getcolor) (normal_color, highlight_color);
+}
+
+int
+grub_setcursor (int on)
+{
+  int ret = cursor_state;
+
+  if (grub_cur_term_output->setcursor)
+    {
+      (grub_cur_term_output->setcursor) (on);
+      cursor_state = on;
+    }
+  
+  return ret;
+}
+
+int
+grub_getcursor (void)
+{
+  return cursor_state;
+}
+
+void
+grub_refresh (void)
+{
+  if (grub_cur_term_output->refresh)
+    (grub_cur_term_output->refresh) ();
+}
+
+void
+grub_set_more (int onoff)
+{
+  if (onoff == 1)
+    grub_more++;
+  else
+    grub_more--;
+
+  grub_more_lines = 0;
+}
diff --git a/kern/time.c b/kern/time.c
new file mode 100644 (file)
index 0000000..6521ec6
--- /dev/null
@@ -0,0 +1,37 @@
+/* time.c - kernel time functions */
+/*
+ *  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/time.h>
+
+typedef grub_uint64_t (*get_time_ms_func_t) (void);
+
+/* Function pointer to the implementation in use.  */
+static get_time_ms_func_t get_time_ms_func;
+
+grub_uint64_t
+grub_get_time_ms (void)
+{
+  return get_time_ms_func ();
+}
+
+void
+grub_install_get_time_ms (get_time_ms_func_t func)
+{
+  get_time_ms_func = func;
+}
diff --git a/kern/x86_64/dl.c b/kern/x86_64/dl.c
new file mode 100644 (file)
index 0000000..bef3270
--- /dev/null
@@ -0,0 +1,121 @@
+/* dl-x86_64.c - arch-dependent part of loadable module support */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+
+/* Check if EHDR is a valid ELF header.  */
+grub_err_t
+grub_arch_dl_check_header (void *ehdr)
+{
+  Elf64_Ehdr *e = ehdr;
+
+  /* Check the magic numbers.  */
+  if (e->e_ident[EI_CLASS] != ELFCLASS64
+      || e->e_ident[EI_DATA] != ELFDATA2LSB
+      || e->e_machine != EM_X86_64)
+    return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic");
+
+  return GRUB_ERR_NONE;
+}
+
+/* Relocate symbols.  */
+grub_err_t
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
+{
+  Elf64_Ehdr *e = ehdr;
+  Elf64_Shdr *s;
+  Elf64_Sym *symtab;
+  Elf64_Word entsize;
+  unsigned i;
+
+  /* Find a symbol table.  */
+  for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf64_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");
+
+  symtab = (Elf64_Sym *) ((char *) e + s->sh_offset);
+  entsize = s->sh_entsize;
+
+  for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf64_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)
+         {
+           Elf64_Rela *rel, *max;
+
+           for (rel = (Elf64_Rela *) ((char *) e + s->sh_offset),
+                  max = rel + s->sh_size / s->sh_entsize;
+                rel < max;
+                rel++)
+             {
+               Elf64_Word *addr32;
+               Elf64_Xword *addr64;
+               Elf64_Sym *sym;
+
+               if (seg->size < rel->r_offset)
+                 return grub_error (GRUB_ERR_BAD_MODULE,
+                                    "reloc offset is out of the segment");
+
+               addr32 = (Elf64_Word *) ((char *) seg->addr + rel->r_offset);
+               addr64 = (Elf64_Xword *) addr32;
+               sym = (Elf64_Sym *) ((char *) symtab
+                                    + entsize * ELF64_R_SYM (rel->r_info));
+
+               switch (ELF64_R_TYPE (rel->r_info))
+                 {
+                 case R_X86_64_64:
+                   *addr64 = rel->r_addend + sym->st_value;
+                   break;
+
+                 case R_X86_64_PC32:
+                   *addr32 = rel->r_addend + sym->st_value -
+                             (Elf64_Xword) seg->addr - rel->r_offset;
+                   break;
+
+                  case R_X86_64_32:
+                  case R_X86_64_32S:
+                    *addr32 = rel->r_addend + sym->st_value;
+                    break;
+
+                  default:
+                    grub_fatal ("Unrecognized relocation: %d\n", ELF64_R_TYPE (rel->r_info));
+                 }
+             }
+         }
+      }
+
+  return GRUB_ERR_NONE;
+}
diff --git a/kern/x86_64/efi/callwrap.S b/kern/x86_64/efi/callwrap.S
new file mode 100644 (file)
index 0000000..6c390ec
--- /dev/null
@@ -0,0 +1,96 @@
+/* callwrap.S - wrapper for x86_64 efi calls */
+/*
+ *  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/>.
+ */
+
+#include <config.h>
+#include <grub/symbol.h>
+#include <grub/boot.h>
+
+/*
+ * x86_64 uses registry to pass parameters. Unfortunately, gcc and efi use
+ * different call conversion, so we need to do some conversion.
+ *
+ * gcc:
+ *   %rdi,  %esi,  %rdx,  %rcx, %r8, %r9, 8(%rsp), 16(%rsp), ...
+ *
+ * efi:
+ *   %rcx,  %rdx,  %r8,  %r9,  32(%rsp), 40(%rsp), 48(%rsp), ...
+ *
+ */
+
+        .file   "callwrap.S"
+        .text
+
+FUNCTION(efi_wrap_0)
+       subq $40, %rsp
+       call *%rdi
+       addq $40, %rsp
+       ret
+
+FUNCTION(efi_wrap_1)
+       subq $40, %rsp
+       mov  %rsi, %rcx
+       call *%rdi
+       addq $40, %rsp
+       ret
+
+FUNCTION(efi_wrap_2)
+       subq $40, %rsp
+       mov  %rsi, %rcx
+       call *%rdi
+       addq $40, %rsp
+       ret
+
+FUNCTION(efi_wrap_3)
+       subq $40, %rsp
+       mov  %rcx, %r8
+       mov  %rsi, %rcx
+       call *%rdi
+       addq $40, %rsp
+       ret
+
+FUNCTION(efi_wrap_4)
+       subq $40, %rsp
+       mov %r8, %r9
+       mov %rcx, %r8
+       mov %rsi, %rcx
+       call *%rdi
+       addq $40, %rsp
+       ret
+
+FUNCTION(efi_wrap_5)
+       subq $40, %rsp
+       mov %r9, 32(%rsp)
+       mov %r8, %r9
+       mov %rcx, %r8
+       mov %rsi, %rcx
+       call *%rdi
+       addq $40, %rsp
+       ret
+
+FUNCTION(efi_wrap_6)
+       subq $56, %rsp
+       mov 56+8(%rsp), %rax
+       mov %rax, 40(%rsp)
+       mov %r9, (%rsp)
+       mov %r8, %r9
+       mov %rcx, %r8
+       mov %rsi, %rcx
+       call *%rdi
+       addq $56, %rsp
+       ret
diff --git a/kern/x86_64/efi/startup.S b/kern/x86_64/efi/startup.S
new file mode 100644 (file)
index 0000000..2fa6766
--- /dev/null
@@ -0,0 +1,87 @@
+/* startup.S - bootstrap GRUB itself */
+/*
+ *  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/>.
+ */
+
+#include <config.h>
+#include <grub/symbol.h>
+#include <grub/boot.h>
+
+        .file   "startup.S"
+        .text
+        .globl  start, _start
+        .code64
+
+start:
+_start:
+       jmp codestart
+
+        /*
+         *  Compatibility version number
+         *
+         *  These MUST be at byte offset 6 and 7 of the executable
+         *  DO NOT MOVE !!!
+         */
+        . = EXT_C(start) + 0x6
+        .byte   GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
+
+        /*
+         *  This is a special data area 8 bytes from the beginning.
+         */
+
+        . = EXT_C(start) + 0x8
+
+VARIABLE(grub_prefix)
+       /* to be filled by grub-mkimage */
+
+        /*
+         *  Leave some breathing room for the prefix.
+         */
+
+        . = EXT_C(start) + 0x50
+
+codestart:
+
+       movq    %rcx, EXT_C(grub_efi_image_handle)
+       movq    %rdx, EXT_C(grub_efi_system_table)
+
+       call    EXT_C(grub_main)
+       ret
+
+       .code32
+
+FUNCTION(grub_linux_real_boot)
+        /* Turn off PG bit in CR0 and set CR3 to zero.  */
+        movl    %cr0, %eax
+        andl    $0x7FFFFFFF, %eax
+        movl    %eax, %cr0
+
+        /* Setup EFER (Extended Feature Enable Register).  */
+        movl    $0xc0000080, %ecx
+        rdmsr
+
+        /* Disable Long Mode.  */
+        andl    $0xFFFFFEFF, %eax
+
+        /* Make changes effective.  */
+        wrmsr
+
+        /* Disable PAE.  */
+        xorl    %eax, %eax
+        movl    %eax, %cr4
+
+        jmp     *%ebx
diff --git a/lib/LzFind.c b/lib/LzFind.c
new file mode 100644 (file)
index 0000000..cd7a1cb
--- /dev/null
@@ -0,0 +1,774 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (c) 1999-2008 Igor Pavlov
+ *  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/>.
+ */
+
+/*
+ * This code was taken from LZMA SDK 4.58 beta, and was slightly modified
+ * to adapt it to GRUB's requirement.
+ *
+ * See <http://www.7-zip.org>, for more information about LZMA.
+ */
+
+#include <string.h>
+
+#include <grub/lib/LzFind.h>
+#include <grub/lib/LzHash.h>
+
+#define kEmptyHashValue 0
+#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
+#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
+#define kNormalizeMask (~(kNormalizeStepMin - 1))
+#define kMaxHistorySize ((UInt32)3 << 30)
+
+#define kStartMaxLen 3
+
+static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+  if (!p->directInput)
+  {
+    alloc->Free(alloc, p->bufferBase);
+    p->bufferBase = 0;
+  }
+}
+
+/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
+
+static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
+{
+  UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
+  if (p->directInput)
+  {
+    p->blockSize = blockSize;
+    return 1;
+  }
+  if (p->bufferBase == 0 || p->blockSize != blockSize)
+  {
+    LzInWindow_Free(p, alloc);
+    p->blockSize = blockSize;
+    p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);
+  }
+  return (p->bufferBase != 0);
+}
+
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
+Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
+
+UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
+
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
+{
+  p->posLimit -= subValue;
+  p->pos -= subValue;
+  p->streamPos -= subValue;
+}
+
+static void MatchFinder_ReadBlock(CMatchFinder *p)
+{
+  if (p->streamEndWasReached || p->result != SZ_OK)
+    return;
+  for (;;)
+  {
+    Byte *dest = p->buffer + (p->streamPos - p->pos);
+    size_t size = (p->bufferBase + p->blockSize - dest);
+    if (size == 0)
+      return;
+    p->result = p->stream->Read(p->stream, dest, &size);
+    if (p->result != SZ_OK)
+      return;
+    if (size == 0)
+    {
+      p->streamEndWasReached = 1;
+      return;
+    }
+    p->streamPos += (UInt32)size;
+    if (p->streamPos - p->pos > p->keepSizeAfter)
+      return;
+  }
+}
+
+void MatchFinder_MoveBlock(CMatchFinder *p)
+{
+  memmove(p->bufferBase,
+    p->buffer - p->keepSizeBefore,
+    (size_t)(p->streamPos - p->pos + p->keepSizeBefore));
+  p->buffer = p->bufferBase + p->keepSizeBefore;
+}
+
+int MatchFinder_NeedMove(CMatchFinder *p)
+{
+  /* if (p->streamEndWasReached) return 0; */
+  return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
+}
+
+void MatchFinder_ReadIfRequired(CMatchFinder *p)
+{
+  if (p->streamEndWasReached)
+    return;
+  if (p->keepSizeAfter >= p->streamPos - p->pos)
+    MatchFinder_ReadBlock(p);
+}
+
+static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
+{
+  if (MatchFinder_NeedMove(p))
+    MatchFinder_MoveBlock(p);
+  MatchFinder_ReadBlock(p);
+}
+
+static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
+{
+  p->cutValue = 32;
+  p->btMode = 1;
+  p->numHashBytes = 4;
+  /* p->skipModeBits = 0; */
+  p->directInput = 0;
+  p->bigHash = 0;
+}
+
+#define kCrcPoly 0xEDB88320
+
+void MatchFinder_Construct(CMatchFinder *p)
+{
+  UInt32 i;
+  p->bufferBase = 0;
+  p->directInput = 0;
+  p->hash = 0;
+  MatchFinder_SetDefaultSettings(p);
+
+  for (i = 0; i < 256; i++)
+  {
+    UInt32 r = i;
+    int j;
+    for (j = 0; j < 8; j++)
+      r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
+    p->crc[i] = r;
+  }
+}
+
+static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
+{
+  alloc->Free(alloc, p->hash);
+  p->hash = 0;
+}
+
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+  MatchFinder_FreeThisClassMemory(p, alloc);
+  LzInWindow_Free(p, alloc);
+}
+
+static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
+{
+  size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
+  if (sizeInBytes / sizeof(CLzRef) != num)
+    return 0;
+  return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
+}
+
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
+    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+    ISzAlloc *alloc)
+{
+  UInt32 sizeReserv;
+  if (historySize > kMaxHistorySize)
+  {
+    MatchFinder_Free(p, alloc);
+    return 0;
+  }
+  sizeReserv = historySize >> 1;
+  if (historySize > ((UInt32)2 << 30))
+    sizeReserv = historySize >> 2;
+  sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
+
+  p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
+  p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
+  /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
+  if (LzInWindow_Create(p, sizeReserv, alloc))
+  {
+    UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1;
+    UInt32 hs;
+    p->matchMaxLen = matchMaxLen;
+    {
+      p->fixedHashSize = 0;
+      if (p->numHashBytes == 2)
+        hs = (1 << 16) - 1;
+      else
+      {
+        hs = historySize - 1;
+        hs |= (hs >> 1);
+        hs |= (hs >> 2);
+        hs |= (hs >> 4);
+        hs |= (hs >> 8);
+        hs >>= 1;
+        /* hs >>= p->skipModeBits; */
+        hs |= 0xFFFF; /* don't change it! It's required for Deflate */
+        if (hs > (1 << 24))
+        {
+          if (p->numHashBytes == 3)
+            hs = (1 << 24) - 1;
+          else
+            hs >>= 1;
+        }
+      }
+      p->hashMask = hs;
+      hs++;
+      if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
+      if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
+      if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
+      hs += p->fixedHashSize;
+    }
+
+    {
+      UInt32 prevSize = p->hashSizeSum + p->numSons;
+      UInt32 newSize;
+      p->historySize = historySize;
+      p->hashSizeSum = hs;
+      p->cyclicBufferSize = newCyclicBufferSize;
+      p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
+      newSize = p->hashSizeSum + p->numSons;
+      if (p->hash != 0 && prevSize == newSize)
+        return 1;
+      MatchFinder_FreeThisClassMemory(p, alloc);
+      p->hash = AllocRefs(newSize, alloc);
+      if (p->hash != 0)
+      {
+        p->son = p->hash + p->hashSizeSum;
+        return 1;
+      }
+    }
+  }
+  MatchFinder_Free(p, alloc);
+  return 0;
+}
+
+static void MatchFinder_SetLimits(CMatchFinder *p)
+{
+  UInt32 limit = kMaxValForNormalize - p->pos;
+  UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
+  if (limit2 < limit)
+    limit = limit2;
+  limit2 = p->streamPos - p->pos;
+  if (limit2 <= p->keepSizeAfter)
+  {
+    if (limit2 > 0)
+      limit2 = 1;
+  }
+  else
+    limit2 -= p->keepSizeAfter;
+  if (limit2 < limit)
+    limit = limit2;
+  {
+    UInt32 lenLimit = p->streamPos - p->pos;
+    if (lenLimit > p->matchMaxLen)
+      lenLimit = p->matchMaxLen;
+    p->lenLimit = lenLimit;
+  }
+  p->posLimit = p->pos + limit;
+}
+
+void MatchFinder_Init(CMatchFinder *p)
+{
+  UInt32 i;
+  for(i = 0; i < p->hashSizeSum; i++)
+    p->hash[i] = kEmptyHashValue;
+  p->cyclicBufferPos = 0;
+  p->buffer = p->bufferBase;
+  p->pos = p->streamPos = p->cyclicBufferSize;
+  p->result = SZ_OK;
+  p->streamEndWasReached = 0;
+  MatchFinder_ReadBlock(p);
+  MatchFinder_SetLimits(p);
+}
+
+static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
+{
+  return (p->pos - p->historySize - 1) & kNormalizeMask;
+}
+
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
+{
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+  {
+    UInt32 value = items[i];
+    if (value <= subValue)
+      value = kEmptyHashValue;
+    else
+      value -= subValue;
+    items[i] = value;
+  }
+}
+
+static void MatchFinder_Normalize(CMatchFinder *p)
+{
+  UInt32 subValue = MatchFinder_GetSubValue(p);
+  MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
+  MatchFinder_ReduceOffsets(p, subValue);
+}
+
+static void MatchFinder_CheckLimits(CMatchFinder *p)
+{
+  if (p->pos == kMaxValForNormalize)
+    MatchFinder_Normalize(p);
+  if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
+    MatchFinder_CheckAndMoveAndRead(p);
+  if (p->cyclicBufferPos == p->cyclicBufferSize)
+    p->cyclicBufferPos = 0;
+  MatchFinder_SetLimits(p);
+}
+
+static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
+    UInt32 *distances, UInt32 maxLen)
+{
+  son[_cyclicBufferPos] = curMatch;
+  for (;;)
+  {
+    UInt32 delta = pos - curMatch;
+    if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+      return distances;
+    {
+      const Byte *pb = cur - delta;
+      curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
+      if (pb[maxLen] == cur[maxLen] && *pb == *cur)
+      {
+        UInt32 len = 0;
+        while(++len != lenLimit)
+          if (pb[len] != cur[len])
+            break;
+        if (maxLen < len)
+        {
+          *distances++ = maxLen = len;
+          *distances++ = delta - 1;
+          if (len == lenLimit)
+            return distances;
+        }
+      }
+    }
+  }
+}
+
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
+    UInt32 *distances, UInt32 maxLen)
+{
+  CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+  CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
+  UInt32 len0 = 0, len1 = 0;
+  for (;;)
+  {
+    UInt32 delta = pos - curMatch;
+    if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+    {
+      *ptr0 = *ptr1 = kEmptyHashValue;
+      return distances;
+    }
+    {
+      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+      const Byte *pb = cur - delta;
+      UInt32 len = (len0 < len1 ? len0 : len1);
+      if (pb[len] == cur[len])
+      {
+        if (++len != lenLimit && pb[len] == cur[len])
+          while(++len != lenLimit)
+            if (pb[len] != cur[len])
+              break;
+        if (maxLen < len)
+        {
+          *distances++ = maxLen = len;
+          *distances++ = delta - 1;
+          if (len == lenLimit)
+          {
+            *ptr1 = pair[0];
+            *ptr0 = pair[1];
+            return distances;
+          }
+        }
+      }
+      if (pb[len] < cur[len])
+      {
+        *ptr1 = curMatch;
+        ptr1 = pair + 1;
+        curMatch = *ptr1;
+        len1 = len;
+      }
+      else
+      {
+        *ptr0 = curMatch;
+        ptr0 = pair;
+        curMatch = *ptr0;
+        len0 = len;
+      }
+    }
+  }
+}
+
+static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
+{
+  CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+  CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
+  UInt32 len0 = 0, len1 = 0;
+  for (;;)
+  {
+    UInt32 delta = pos - curMatch;
+    if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+    {
+      *ptr0 = *ptr1 = kEmptyHashValue;
+      return;
+    }
+    {
+      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+      const Byte *pb = cur - delta;
+      UInt32 len = (len0 < len1 ? len0 : len1);
+      if (pb[len] == cur[len])
+      {
+        while(++len != lenLimit)
+          if (pb[len] != cur[len])
+            break;
+        {
+          if (len == lenLimit)
+          {
+            *ptr1 = pair[0];
+            *ptr0 = pair[1];
+            return;
+          }
+        }
+      }
+      if (pb[len] < cur[len])
+      {
+        *ptr1 = curMatch;
+        ptr1 = pair + 1;
+        curMatch = *ptr1;
+        len1 = len;
+      }
+      else
+      {
+        *ptr0 = curMatch;
+        ptr0 = pair;
+        curMatch = *ptr0;
+        len0 = len;
+      }
+    }
+  }
+}
+
+#define MOVE_POS \
+  ++p->cyclicBufferPos; \
+  p->buffer++; \
+  if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
+
+#define MOVE_POS_RET MOVE_POS return offset;
+
+static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
+
+#define GET_MATCHES_HEADER2(minLen, ret_op) \
+  UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
+  lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
+  cur = p->buffer;
+
+#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
+#define SKIP_HEADER(minLen)        GET_MATCHES_HEADER2(minLen, continue)
+
+#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
+
+#define GET_MATCHES_FOOTER(offset, maxLen) \
+  offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
+  distances + offset, maxLen) - distances); MOVE_POS_RET;
+
+#define SKIP_FOOTER \
+  SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
+
+static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 offset;
+  GET_MATCHES_HEADER(2)
+  HASH2_CALC;
+  curMatch = p->hash[hashValue];
+  p->hash[hashValue] = p->pos;
+  offset = 0;
+  GET_MATCHES_FOOTER(offset, 1)
+}
+
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 offset;
+  GET_MATCHES_HEADER(3)
+  HASH_ZIP_CALC;
+  curMatch = p->hash[hashValue];
+  p->hash[hashValue] = p->pos;
+  offset = 0;
+  GET_MATCHES_FOOTER(offset, 2)
+}
+
+static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 hash2Value, delta2, maxLen, offset;
+  GET_MATCHES_HEADER(3)
+
+  HASH3_CALC;
+
+  delta2 = p->pos - p->hash[hash2Value];
+  curMatch = p->hash[kFix3HashSize + hashValue];
+
+  p->hash[hash2Value] =
+  p->hash[kFix3HashSize + hashValue] = p->pos;
+
+
+  maxLen = 2;
+  offset = 0;
+  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
+  {
+    for (; maxLen != lenLimit; maxLen++)
+      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+        break;
+    distances[0] = maxLen;
+    distances[1] = delta2 - 1;
+    offset = 2;
+    if (maxLen == lenLimit)
+    {
+      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+      MOVE_POS_RET;
+    }
+  }
+  GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
+  GET_MATCHES_HEADER(4)
+
+  HASH4_CALC;
+
+  delta2 = p->pos - p->hash[                hash2Value];
+  delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
+  curMatch = p->hash[kFix4HashSize + hashValue];
+
+  p->hash[                hash2Value] =
+  p->hash[kFix3HashSize + hash3Value] =
+  p->hash[kFix4HashSize + hashValue] = p->pos;
+
+  maxLen = 1;
+  offset = 0;
+  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
+  {
+    distances[0] = maxLen = 2;
+    distances[1] = delta2 - 1;
+    offset = 2;
+  }
+  if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
+  {
+    maxLen = 3;
+    distances[offset + 1] = delta3 - 1;
+    offset += 2;
+    delta2 = delta3;
+  }
+  if (offset != 0)
+  {
+    for (; maxLen != lenLimit; maxLen++)
+      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+        break;
+    distances[offset - 2] = maxLen;
+    if (maxLen == lenLimit)
+    {
+      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+      MOVE_POS_RET;
+    }
+  }
+  if (maxLen < 3)
+    maxLen = 3;
+  GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
+  GET_MATCHES_HEADER(4)
+
+  HASH4_CALC;
+
+  delta2 = p->pos - p->hash[                hash2Value];
+  delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
+  curMatch = p->hash[kFix4HashSize + hashValue];
+
+  p->hash[                hash2Value] =
+  p->hash[kFix3HashSize + hash3Value] =
+  p->hash[kFix4HashSize + hashValue] = p->pos;
+
+  maxLen = 1;
+  offset = 0;
+  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
+  {
+    distances[0] = maxLen = 2;
+    distances[1] = delta2 - 1;
+    offset = 2;
+  }
+  if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
+  {
+    maxLen = 3;
+    distances[offset + 1] = delta3 - 1;
+    offset += 2;
+    delta2 = delta3;
+  }
+  if (offset != 0)
+  {
+    for (; maxLen != lenLimit; maxLen++)
+      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+        break;
+    distances[offset - 2] = maxLen;
+    if (maxLen == lenLimit)
+    {
+      p->son[p->cyclicBufferPos] = curMatch;
+      MOVE_POS_RET;
+    }
+  }
+  if (maxLen < 3)
+    maxLen = 3;
+  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+    distances + offset, maxLen) - (distances));
+  MOVE_POS_RET
+}
+
+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 offset;
+  GET_MATCHES_HEADER(3)
+  HASH_ZIP_CALC;
+  curMatch = p->hash[hashValue];
+  p->hash[hashValue] = p->pos;
+  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+    distances, 2) - (distances));
+  MOVE_POS_RET
+}
+
+static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    SKIP_HEADER(2)
+    HASH2_CALC;
+    curMatch = p->hash[hashValue];
+    p->hash[hashValue] = p->pos;
+    SKIP_FOOTER
+  }
+  while (--num != 0);
+}
+
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    SKIP_HEADER(3)
+    HASH_ZIP_CALC;
+    curMatch = p->hash[hashValue];
+    p->hash[hashValue] = p->pos;
+    SKIP_FOOTER
+  }
+  while (--num != 0);
+}
+
+static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    UInt32 hash2Value;
+    SKIP_HEADER(3)
+    HASH3_CALC;
+    curMatch = p->hash[kFix3HashSize + hashValue];
+    p->hash[hash2Value] =
+    p->hash[kFix3HashSize + hashValue] = p->pos;
+    SKIP_FOOTER
+  }
+  while (--num != 0);
+}
+
+static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    UInt32 hash2Value, hash3Value;
+    SKIP_HEADER(4)
+    HASH4_CALC;
+    curMatch = p->hash[kFix4HashSize + hashValue];
+    p->hash[                hash2Value] =
+    p->hash[kFix3HashSize + hash3Value] = p->pos;
+    p->hash[kFix4HashSize + hashValue] = p->pos;
+    SKIP_FOOTER
+  }
+  while (--num != 0);
+}
+
+static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    UInt32 hash2Value, hash3Value;
+    SKIP_HEADER(4)
+    HASH4_CALC;
+    curMatch = p->hash[kFix4HashSize + hashValue];
+    p->hash[                hash2Value] =
+    p->hash[kFix3HashSize + hash3Value] =
+    p->hash[kFix4HashSize + hashValue] = p->pos;
+    p->son[p->cyclicBufferPos] = curMatch;
+    MOVE_POS
+  }
+  while (--num != 0);
+}
+
+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    SKIP_HEADER(3)
+    HASH_ZIP_CALC;
+    curMatch = p->hash[hashValue];
+    p->hash[hashValue] = p->pos;
+    p->son[p->cyclicBufferPos] = curMatch;
+    MOVE_POS
+  }
+  while (--num != 0);
+}
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
+{
+  vTable->Init = (Mf_Init_Func)MatchFinder_Init;
+  vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
+  vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
+  vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
+  if (!p->btMode)
+  {
+    vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
+    vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
+  }
+  else if (p->numHashBytes == 2)
+  {
+    vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
+    vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
+  }
+  else if (p->numHashBytes == 3)
+  {
+    vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
+    vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
+  }
+  else
+  {
+    vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
+    vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
+  }
+}
diff --git a/lib/LzmaDec.c b/lib/LzmaDec.c
new file mode 100644 (file)
index 0000000..62ebee6
--- /dev/null
@@ -0,0 +1,1035 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (c) 1999-2008 Igor Pavlov
+ *  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/>.
+ */
+
+/*
+ * This code was taken from LZMA SDK 4.58 beta, and was slightly modified
+ * to adapt it to GRUB's requirement.
+ *
+ * See <http://www.7-zip.org>, for more information about LZMA.
+ */
+
+#include <grub/lib/LzmaDec.h>
+
+#include <string.h>
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_INIT_SIZE 5
+
+#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
+#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
+#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
+  { UPDATE_0(p); i = (i + i); A0; } else \
+  { UPDATE_1(p); i = (i + i) + 1; A1; }
+#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
+
+#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
+#define TREE_DECODE(probs, limit, i) \
+  { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
+
+/* #define _LZMA_SIZE_OPT */
+
+#ifdef _LZMA_SIZE_OPT
+#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
+#else
+#define TREE_6_DECODE(probs, i) \
+  { i = 1; \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  i -= 0x40; }
+#endif
+
+#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define UPDATE_0_CHECK range = bound;
+#define UPDATE_1_CHECK range -= bound; code -= bound;
+#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
+  { UPDATE_0_CHECK; i = (i + i); A0; } else \
+  { UPDATE_1_CHECK; i = (i + i) + 1; A1; }
+#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
+#define TREE_DECODE_CHECK(probs, limit, i) \
+  { i = 1; do { GET_BIT_CHECK(probs + i, i) } while(i < limit); i -= limit; }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+/*
+#define LZMA_STREAM_WAS_FINISHED_ID (-1)
+#define LZMA_SPEC_LEN_OFFSET (-3)
+*/
+
+Byte kLiteralNextStates[kNumStates * 2] =
+{
+  0, 0, 0, 0, 1, 2, 3,  4,  5,  6,  4,  5,
+  7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10
+};
+
+#define LZMA_DIC_MIN (1 << 12)
+
+/* First LZMA-symbol is always decoded.
+And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
+Out:
+  Result:
+    0 - OK
+    1 - Error
+  p->remainLen:
+    < kMatchSpecLenStart : normal remain
+    = kMatchSpecLenStart : finished
+    = kMatchSpecLenStart + 1 : Flush marker
+    = kMatchSpecLenStart + 2 : State Init Marker
+*/
+
+static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+  CLzmaProb *probs = p->probs;
+
+  unsigned state = p->state;
+  UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
+  unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
+  unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
+  unsigned lc = p->prop.lc;
+
+  Byte *dic = p->dic;
+  SizeT dicBufSize = p->dicBufSize;
+  SizeT dicPos = p->dicPos;
+
+  UInt32 processedPos = p->processedPos;
+  UInt32 checkDicSize = p->checkDicSize;
+  unsigned len = 0;
+
+  const Byte *buf = p->buf;
+  UInt32 range = p->range;
+  UInt32 code = p->code;
+
+  do
+  {
+    CLzmaProb *prob;
+    UInt32 bound;
+    unsigned ttt;
+    unsigned posState = processedPos & pbMask;
+
+    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+    IF_BIT_0(prob)
+    {
+      unsigned symbol;
+      UPDATE_0(prob);
+      prob = probs + Literal;
+      if (checkDicSize != 0 || processedPos != 0)
+        prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
+        (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
+
+      if (state < kNumLitStates)
+      {
+        symbol = 1;
+        do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
+      }
+      else
+      {
+        unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+        unsigned offs = 0x100;
+        symbol = 1;
+        do
+        {
+          unsigned bit;
+          CLzmaProb *probLit;
+          matchByte <<= 1;
+          bit = (matchByte & offs);
+          probLit = prob + offs + bit + symbol;
+          GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
+        }
+        while (symbol < 0x100);
+      }
+      dic[dicPos++] = (Byte)symbol;
+      processedPos++;
+
+      state = kLiteralNextStates[state];
+      /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */
+      continue;
+    }
+    else
+    {
+      UPDATE_1(prob);
+      prob = probs + IsRep + state;
+      IF_BIT_0(prob)
+      {
+        UPDATE_0(prob);
+        state += kNumStates;
+        prob = probs + LenCoder;
+      }
+      else
+      {
+        UPDATE_1(prob);
+        if (checkDicSize == 0 && processedPos == 0)
+          return SZ_ERROR_DATA;
+        prob = probs + IsRepG0 + state;
+        IF_BIT_0(prob)
+        {
+          UPDATE_0(prob);
+          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
+          IF_BIT_0(prob)
+          {
+            UPDATE_0(prob);
+            dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+            dicPos++;
+            processedPos++;
+            state = state < kNumLitStates ? 9 : 11;
+            continue;
+          }
+          UPDATE_1(prob);
+        }
+        else
+        {
+          UInt32 distance;
+          UPDATE_1(prob);
+          prob = probs + IsRepG1 + state;
+          IF_BIT_0(prob)
+          {
+            UPDATE_0(prob);
+            distance = rep1;
+          }
+          else
+          {
+            UPDATE_1(prob);
+            prob = probs + IsRepG2 + state;
+            IF_BIT_0(prob)
+            {
+              UPDATE_0(prob);
+              distance = rep2;
+            }
+            else
+            {
+              UPDATE_1(prob);
+              distance = rep3;
+              rep3 = rep2;
+            }
+            rep2 = rep1;
+          }
+          rep1 = rep0;
+          rep0 = distance;
+        }
+        state = state < kNumLitStates ? 8 : 11;
+        prob = probs + RepLenCoder;
+      }
+      {
+        unsigned limit, offset;
+        CLzmaProb *probLen = prob + LenChoice;
+        IF_BIT_0(probLen)
+        {
+          UPDATE_0(probLen);
+          probLen = prob + LenLow + (posState << kLenNumLowBits);
+          offset = 0;
+          limit = (1 << kLenNumLowBits);
+        }
+        else
+        {
+          UPDATE_1(probLen);
+          probLen = prob + LenChoice2;
+          IF_BIT_0(probLen)
+          {
+            UPDATE_0(probLen);
+            probLen = prob + LenMid + (posState << kLenNumMidBits);
+            offset = kLenNumLowSymbols;
+            limit = (1 << kLenNumMidBits);
+          }
+          else
+          {
+            UPDATE_1(probLen);
+            probLen = prob + LenHigh;
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;
+            limit = (1 << kLenNumHighBits);
+          }
+        }
+        TREE_DECODE(probLen, limit, len);
+        len += offset;
+      }
+
+      if (state >= kNumStates)
+      {
+        UInt32 distance;
+        prob = probs + PosSlot +
+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
+        TREE_6_DECODE(prob, distance);
+        if (distance >= kStartPosModelIndex)
+        {
+          unsigned posSlot = (unsigned)distance;
+          int numDirectBits = (int)(((distance >> 1) - 1));
+          distance = (2 | (distance & 1));
+          if (posSlot < kEndPosModelIndex)
+          {
+            distance <<= numDirectBits;
+            prob = probs + SpecPos + distance - posSlot - 1;
+            {
+              UInt32 mask = 1;
+              unsigned i = 1;
+              do
+              {
+                GET_BIT2(prob + i, i, ; , distance |= mask);
+                mask <<= 1;
+              }
+              while(--numDirectBits != 0);
+            }
+          }
+          else
+          {
+            numDirectBits -= kNumAlignBits;
+            do
+            {
+              NORMALIZE
+              range >>= 1;
+
+              {
+                UInt32 t;
+                code -= range;
+                t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
+                distance = (distance << 1) + (t + 1);
+                code += range & t;
+              }
+              /*
+              distance <<= 1;
+              if (code >= range)
+              {
+                code -= range;
+                distance |= 1;
+              }
+              */
+            }
+            while (--numDirectBits != 0);
+            prob = probs + Align;
+            distance <<= kNumAlignBits;
+            {
+              unsigned i = 1;
+              GET_BIT2(prob + i, i, ; , distance |= 1);
+              GET_BIT2(prob + i, i, ; , distance |= 2);
+              GET_BIT2(prob + i, i, ; , distance |= 4);
+              GET_BIT2(prob + i, i, ; , distance |= 8);
+            }
+            if (distance == (UInt32)0xFFFFFFFF)
+            {
+              len += kMatchSpecLenStart;
+              state -= kNumStates;
+              break;
+            }
+          }
+        }
+        rep3 = rep2;
+        rep2 = rep1;
+        rep1 = rep0;
+        rep0 = distance + 1;
+        if (checkDicSize == 0)
+        {
+          if (distance >= processedPos)
+            return SZ_ERROR_DATA;
+        }
+        else if (distance >= checkDicSize)
+          return SZ_ERROR_DATA;
+        state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
+        /* state = kLiteralNextStates[state]; */
+      }
+
+      len += kMatchMinLen;
+
+      {
+        SizeT rem = limit - dicPos;
+        unsigned curLen = ((rem < len) ? (unsigned)rem : len);
+        SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
+
+        processedPos += curLen;
+
+        len -= curLen;
+        if (pos + curLen <= dicBufSize)
+        {
+          Byte *dest = dic + dicPos;
+          ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
+          const Byte *lim = dest + curLen;
+          dicPos += curLen;
+          do
+            *(dest) = (Byte)*(dest + src);
+          while (++dest != lim);
+        }
+        else
+        {
+          do
+          {
+            dic[dicPos++] = dic[pos];
+            if (++pos == dicBufSize)
+              pos = 0;
+          }
+          while (--curLen != 0);
+        }
+      }
+    }
+  }
+  while (dicPos < limit && buf < bufLimit);
+  NORMALIZE;
+  p->buf = buf;
+  p->range = range;
+  p->code = code;
+  p->remainLen = len;
+  p->dicPos = dicPos;
+  p->processedPos = processedPos;
+  p->reps[0] = rep0;
+  p->reps[1] = rep1;
+  p->reps[2] = rep2;
+  p->reps[3] = rep3;
+  p->state = state;
+
+  return SZ_OK;
+}
+
+static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
+{
+  if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
+  {
+    Byte *dic = p->dic;
+    SizeT dicPos = p->dicPos;
+    SizeT dicBufSize = p->dicBufSize;
+    unsigned len = p->remainLen;
+    UInt32 rep0 = p->reps[0];
+    if (limit - dicPos < len)
+      len = (unsigned)(limit - dicPos);
+
+    if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
+      p->checkDicSize = p->prop.dicSize;
+
+    p->processedPos += len;
+    p->remainLen -= len;
+    while (len-- != 0)
+    {
+      dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+      dicPos++;
+    }
+    p->dicPos = dicPos;
+  }
+}
+
+/* LzmaDec_DecodeReal2 decodes LZMA-symbols and sets p->needFlush and p->needInit, if required. */
+
+static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+  do
+  {
+    SizeT limit2 = limit;
+    if (p->checkDicSize == 0)
+    {
+      UInt32 rem = p->prop.dicSize - p->processedPos;
+      if (limit - p->dicPos > rem)
+        limit2 = p->dicPos + rem;
+    }
+    RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
+    if (p->processedPos >= p->prop.dicSize)
+      p->checkDicSize = p->prop.dicSize;
+    LzmaDec_WriteRem(p, limit);
+  }
+  while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
+
+  if (p->remainLen > kMatchSpecLenStart)
+  {
+    p->remainLen = kMatchSpecLenStart;
+  }
+  return 0;
+}
+
+typedef enum
+{
+  DUMMY_ERROR, /* unexpected end of input stream */
+  DUMMY_LIT,
+  DUMMY_MATCH,
+  DUMMY_REP
+} ELzmaDummy;
+
+static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
+{
+  UInt32 range = p->range;
+  UInt32 code = p->code;
+  const Byte *bufLimit = buf + inSize;
+  CLzmaProb *probs = p->probs;
+  unsigned state = p->state;
+  ELzmaDummy res;
+
+  {
+    CLzmaProb *prob;
+    UInt32 bound;
+    unsigned ttt;
+    unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
+
+    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+    IF_BIT_0_CHECK(prob)
+    {
+      UPDATE_0_CHECK
+
+      /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
+
+      prob = probs + Literal;
+      if (p->checkDicSize != 0 || p->processedPos != 0)
+        prob += (LZMA_LIT_SIZE *
+          ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
+          (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
+
+      if (state < kNumLitStates)
+      {
+        unsigned symbol = 1;
+        do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
+      }
+      else
+      {
+        unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
+            ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
+        unsigned offs = 0x100;
+        unsigned symbol = 1;
+        do
+        {
+          unsigned bit;
+          CLzmaProb *probLit;
+          matchByte <<= 1;
+          bit = (matchByte & offs);
+          probLit = prob + offs + bit + symbol;
+          GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
+        }
+        while (symbol < 0x100);
+      }
+      res = DUMMY_LIT;
+    }
+    else
+    {
+      unsigned len;
+      UPDATE_1_CHECK;
+
+      prob = probs + IsRep + state;
+      IF_BIT_0_CHECK(prob)
+      {
+        UPDATE_0_CHECK;
+        state = 0;
+        prob = probs + LenCoder;
+        res = DUMMY_MATCH;
+      }
+      else
+      {
+        UPDATE_1_CHECK;
+        res = DUMMY_REP;
+        prob = probs + IsRepG0 + state;
+        IF_BIT_0_CHECK(prob)
+        {
+          UPDATE_0_CHECK;
+          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
+          IF_BIT_0_CHECK(prob)
+          {
+            UPDATE_0_CHECK;
+            NORMALIZE_CHECK;
+            return DUMMY_REP;
+          }
+          else
+          {
+            UPDATE_1_CHECK;
+          }
+        }
+        else
+        {
+          UPDATE_1_CHECK;
+          prob = probs + IsRepG1 + state;
+          IF_BIT_0_CHECK(prob)
+          {
+            UPDATE_0_CHECK;
+          }
+          else
+          {
+            UPDATE_1_CHECK;
+            prob = probs + IsRepG2 + state;
+            IF_BIT_0_CHECK(prob)
+            {
+              UPDATE_0_CHECK;
+            }
+            else
+            {
+              UPDATE_1_CHECK;
+            }
+          }
+        }
+        state = kNumStates;
+        prob = probs + RepLenCoder;
+      }
+      {
+        unsigned limit, offset;
+        CLzmaProb *probLen = prob + LenChoice;
+        IF_BIT_0_CHECK(probLen)
+        {
+          UPDATE_0_CHECK;
+          probLen = prob + LenLow + (posState << kLenNumLowBits);
+          offset = 0;
+          limit = 1 << kLenNumLowBits;
+        }
+        else
+        {
+          UPDATE_1_CHECK;
+          probLen = prob + LenChoice2;
+          IF_BIT_0_CHECK(probLen)
+          {
+            UPDATE_0_CHECK;
+            probLen = prob + LenMid + (posState << kLenNumMidBits);
+            offset = kLenNumLowSymbols;
+            limit = 1 << kLenNumMidBits;
+          }
+          else
+          {
+            UPDATE_1_CHECK;
+            probLen = prob + LenHigh;
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;
+            limit = 1 << kLenNumHighBits;
+          }
+        }
+        TREE_DECODE_CHECK(probLen, limit, len);
+        len += offset;
+      }
+
+      if (state < 4)
+      {
+        unsigned posSlot;
+        prob = probs + PosSlot +
+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+            kNumPosSlotBits);
+        TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
+        if (posSlot >= kStartPosModelIndex)
+        {
+          int numDirectBits = ((posSlot >> 1) - 1);
+
+          /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
+
+          if (posSlot < kEndPosModelIndex)
+          {
+            prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
+          }
+          else
+          {
+            numDirectBits -= kNumAlignBits;
+            do
+            {
+              NORMALIZE_CHECK
+              range >>= 1;
+              code -= range & (((code - range) >> 31) - 1);
+              /* if (code >= range) code -= range; */
+            }
+            while (--numDirectBits != 0);
+            prob = probs + Align;
+            numDirectBits = kNumAlignBits;
+          }
+          {
+            unsigned i = 1;
+            do
+            {
+              GET_BIT_CHECK(prob + i, i);
+            }
+            while(--numDirectBits != 0);
+          }
+        }
+      }
+    }
+  }
+  NORMALIZE_CHECK;
+  return res;
+}
+
+
+static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
+{
+  p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
+  p->range = 0xFFFFFFFF;
+  p->needFlush = 0;
+}
+
+void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
+{
+  p->needFlush = 1;
+  p->remainLen = 0;
+  p->tempBufSize = 0;
+
+  if (initDic)
+  {
+    p->processedPos = 0;
+    p->checkDicSize = 0;
+    p->needInitState = 1;
+  }
+  if (initState)
+    p->needInitState = 1;
+}
+
+void LzmaDec_Init(CLzmaDec *p)
+{
+  p->dicPos = 0;
+  LzmaDec_InitDicAndState(p, True, True);
+}
+
+static void LzmaDec_InitStateReal(CLzmaDec *p)
+{
+  UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
+  UInt32 i;
+  CLzmaProb *probs = p->probs;
+  for (i = 0; i < numProbs; i++)
+    probs[i] = kBitModelTotal >> 1;
+  p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
+  p->state = 0;
+  p->needInitState = 0;
+}
+
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
+    ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+  SizeT inSize = *srcLen;
+  (*srcLen) = 0;
+  LzmaDec_WriteRem(p, dicLimit);
+
+  *status = LZMA_STATUS_NOT_SPECIFIED;
+
+  while (p->remainLen != kMatchSpecLenStart)
+  {
+      int checkEndMarkNow;
+
+      if (p->needFlush != 0)
+      {
+        for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
+          p->tempBuf[p->tempBufSize++] = *src++;
+        if (p->tempBufSize < RC_INIT_SIZE)
+        {
+          *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+          return SZ_OK;
+        }
+        if (p->tempBuf[0] != 0)
+          return SZ_ERROR_DATA;
+
+        LzmaDec_InitRc(p, p->tempBuf);
+        p->tempBufSize = 0;
+      }
+
+      checkEndMarkNow = 0;
+      if (p->dicPos >= dicLimit)
+      {
+        if (p->remainLen == 0 && p->code == 0)
+        {
+          *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
+          return SZ_OK;
+        }
+        if (finishMode == LZMA_FINISH_ANY)
+        {
+          *status = LZMA_STATUS_NOT_FINISHED;
+          return SZ_OK;
+        }
+        if (p->remainLen != 0)
+        {
+          *status = LZMA_STATUS_NOT_FINISHED;
+          return SZ_ERROR_DATA;
+        }
+        checkEndMarkNow = 1;
+      }
+
+      if (p->needInitState)
+        LzmaDec_InitStateReal(p);
+
+      if (p->tempBufSize == 0)
+      {
+        SizeT processed;
+        const Byte *bufLimit;
+        if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+        {
+          int dummyRes = LzmaDec_TryDummy(p, src, inSize);
+          if (dummyRes == DUMMY_ERROR)
+          {
+            memcpy(p->tempBuf, src, inSize);
+            p->tempBufSize = (unsigned)inSize;
+            (*srcLen) += inSize;
+            *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+            return SZ_OK;
+          }
+          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+          {
+            *status = LZMA_STATUS_NOT_FINISHED;
+            return SZ_ERROR_DATA;
+          }
+          bufLimit = src;
+        }
+        else
+          bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
+        p->buf = src;
+        if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
+          return SZ_ERROR_DATA;
+        processed = p->buf - src;
+        (*srcLen) += processed;
+        src += processed;
+        inSize -= processed;
+      }
+      else
+      {
+        unsigned rem = p->tempBufSize, lookAhead = 0;
+        while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
+          p->tempBuf[rem++] = src[lookAhead++];
+        p->tempBufSize = rem;
+        if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+        {
+          int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
+          if (dummyRes == DUMMY_ERROR)
+          {
+            (*srcLen) += lookAhead;
+            *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+            return SZ_OK;
+          }
+          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+          {
+            *status = LZMA_STATUS_NOT_FINISHED;
+            return SZ_ERROR_DATA;
+          }
+        }
+        p->buf = p->tempBuf;
+        if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
+          return SZ_ERROR_DATA;
+        lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
+        (*srcLen) += lookAhead;
+        src += lookAhead;
+        inSize -= lookAhead;
+        p->tempBufSize = 0;
+      }
+  }
+  if (p->code == 0)
+    *status = LZMA_STATUS_FINISHED_WITH_MARK;
+  return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
+}
+
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+  SizeT outSize = *destLen;
+  SizeT inSize = *srcLen;
+  *srcLen = *destLen = 0;
+  for (;;)
+  {
+    SizeT inSizeCur = inSize, outSizeCur, dicPos;
+    ELzmaFinishMode curFinishMode;
+    SRes res;
+    if (p->dicPos == p->dicBufSize)
+      p->dicPos = 0;
+    dicPos = p->dicPos;
+    if (outSize > p->dicBufSize - dicPos)
+    {
+      outSizeCur = p->dicBufSize;
+      curFinishMode = LZMA_FINISH_ANY;
+    }
+    else
+    {
+      outSizeCur = dicPos + outSize;
+      curFinishMode = finishMode;
+    }
+
+    res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
+    src += inSizeCur;
+    inSize -= inSizeCur;
+    *srcLen += inSizeCur;
+    outSizeCur = p->dicPos - dicPos;
+    memcpy(dest, p->dic + dicPos, outSizeCur);
+    dest += outSizeCur;
+    outSize -= outSizeCur;
+    *destLen += outSizeCur;
+    if (res != 0)
+      return res;
+    if (outSizeCur == 0 || outSize == 0)
+      return SZ_OK;
+  }
+}
+
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
+{
+  alloc->Free(alloc, p->probs);
+  p->probs = 0;
+}
+
+static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
+{
+  alloc->Free(alloc, p->dic);
+  p->dic = 0;
+}
+
+void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
+{
+  LzmaDec_FreeProbs(p, alloc);
+  LzmaDec_FreeDict(p, alloc);
+}
+
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
+{
+  UInt32 dicSize;
+  Byte d;
+
+  if (size < LZMA_PROPS_SIZE)
+    return SZ_ERROR_UNSUPPORTED;
+  else
+    dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
+
+  if (dicSize < LZMA_DIC_MIN)
+    dicSize = LZMA_DIC_MIN;
+  p->dicSize = dicSize;
+
+  d = data[0];
+  if (d >= (9 * 5 * 5))
+    return SZ_ERROR_UNSUPPORTED;
+
+  p->lc = d % 9;
+  d /= 9;
+  p->pb = d / 5;
+  p->lp = d % 5;
+
+  return SZ_OK;
+}
+
+static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
+{
+  UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
+  if (p->probs == 0 || numProbs != p->numProbs)
+  {
+    LzmaDec_FreeProbs(p, alloc);
+    p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
+    p->numProbs = numProbs;
+    if (p->probs == 0)
+      return SZ_ERROR_MEM;
+  }
+  return SZ_OK;
+}
+
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+{
+  CLzmaProps propNew;
+  RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+  p->prop = propNew;
+  return SZ_OK;
+}
+
+SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+{
+  CLzmaProps propNew;
+  SizeT dicBufSize;
+  RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+  dicBufSize = propNew.dicSize;
+  if (p->dic == 0 || dicBufSize != p->dicBufSize)
+  {
+    LzmaDec_FreeDict(p, alloc);
+    p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
+    if (p->dic == 0)
+    {
+      LzmaDec_FreeProbs(p, alloc);
+      return SZ_ERROR_MEM;
+    }
+  }
+  p->dicBufSize = dicBufSize;
+  p->prop = propNew;
+  return SZ_OK;
+}
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+    ELzmaStatus *status, ISzAlloc *alloc)
+{
+  CLzmaDec p;
+  SRes res;
+  SizeT inSize = *srcLen;
+  SizeT outSize = *destLen;
+  *srcLen = *destLen = 0;
+  if (inSize < RC_INIT_SIZE)
+    return SZ_ERROR_INPUT_EOF;
+
+  LzmaDec_Construct(&p);
+  res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
+  if (res != 0)
+    return res;
+  p.dic = dest;
+  p.dicBufSize = outSize;
+
+  LzmaDec_Init(&p);
+
+  *srcLen = inSize;
+  res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
+
+  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
+    res = SZ_ERROR_INPUT_EOF;
+
+  (*destLen) = p.dicPos;
+  LzmaDec_FreeProbs(&p, alloc);
+  return res;
+}
diff --git a/lib/LzmaEnc.c b/lib/LzmaEnc.c
new file mode 100644 (file)
index 0000000..842d43a
--- /dev/null
@@ -0,0 +1,2355 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (c) 1999-2008 Igor Pavlov
+ *  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/>.
+ */
+
+/*
+ * This code was taken from LZMA SDK 4.58 beta, and was slightly modified
+ * to adapt it to GRUB's requirement.
+ *
+ * See <http://www.7-zip.org>, for more information about LZMA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grub/lib/LzmaEnc.h>
+
+#include <grub/lib/LzFind.h>
+#ifdef COMPRESS_MF_MT
+#include <grub/lib/LzFindMt.h>
+#endif
+
+/* #define SHOW_STAT */
+/* #define SHOW_STAT2 */
+
+#ifdef SHOW_STAT
+static int ttt = 0;
+#endif
+
+#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
+
+#define kBlockSize (9 << 10)
+#define kUnpackBlockSize (1 << 18)
+#define kMatchArraySize (1 << 21)
+#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)
+
+#define kNumMaxDirectBits (31)
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+#define kProbInitValue (kBitModelTotal >> 1)
+
+#define kNumMoveReducingBits 4
+#define kNumBitPriceShiftBits 4
+#define kBitPrice (1 << kNumBitPriceShiftBits)
+
+void LzmaEncProps_Init(CLzmaEncProps *p)
+{
+  p->level = 5;
+  p->dictSize = p->mc = 0;
+  p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
+  p->writeEndMark = 0;
+}
+
+void LzmaEncProps_Normalize(CLzmaEncProps *p)
+{
+  int level = p->level;
+  if (level < 0) level = 5;
+  p->level = level;
+  if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
+  if (p->lc < 0) p->lc = 3;
+  if (p->lp < 0) p->lp = 0;
+  if (p->pb < 0) p->pb = 2;
+  if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
+  if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
+  if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
+  if (p->numHashBytes < 0) p->numHashBytes = 4;
+  if (p->mc == 0)  p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
+  if (p->numThreads < 0) p->numThreads = ((p->btMode && p->algo) ? 2 : 1);
+}
+
+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
+{
+  CLzmaEncProps props = *props2;
+  LzmaEncProps_Normalize(&props);
+  return props.dictSize;
+}
+
+/* #define LZMA_LOG_BSR */
+/* Define it for Intel's CPU */
+
+
+#ifdef LZMA_LOG_BSR
+
+#define kDicLogSizeMaxCompress 30
+
+#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }
+
+UInt32 GetPosSlot1(UInt32 pos)
+{
+  UInt32 res;
+  BSR2_RET(pos, res);
+  return res;
+}
+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
+#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
+
+#else
+
+#define kNumLogBits (9 + (int)sizeof(size_t) / 2)
+#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
+
+void LzmaEnc_FastPosInit(Byte *g_FastPos)
+{
+  int c = 2, slotFast;
+  g_FastPos[0] = 0;
+  g_FastPos[1] = 1;
+
+  for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)
+  {
+    UInt32 k = (1 << ((slotFast >> 1) - 1));
+    UInt32 j;
+    for (j = 0; j < k; j++, c++)
+      g_FastPos[c] = (Byte)slotFast;
+  }
+}
+
+#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \
+  (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
+  res = p->g_FastPos[pos >> i] + (i * 2); }
+/*
+#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
+  p->g_FastPos[pos >> 6] + 12 : \
+  p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
+*/
+
+#define GetPosSlot1(pos) p->g_FastPos[pos]
+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
+#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); }
+
+#endif
+
+
+#define LZMA_NUM_REPS 4
+
+typedef unsigned CState;
+
+typedef struct _COptimal
+{
+  UInt32 price;
+
+  CState state;
+  int prev1IsChar;
+  int prev2;
+
+  UInt32 posPrev2;
+  UInt32 backPrev2;
+
+  UInt32 posPrev;
+  UInt32 backPrev;
+  UInt32 backs[LZMA_NUM_REPS];
+} COptimal;
+
+#define kNumOpts (1 << 12)
+
+#define kNumLenToPosStates 4
+#define kNumPosSlotBits 6
+#define kDicLogSizeMin 0
+#define kDicLogSizeMax 32
+#define kDistTableSizeMax (kDicLogSizeMax * 2)
+
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+#define kAlignMask (kAlignTableSize - 1)
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)
+
+#define kNumFullDistances (1 << (kEndPosModelIndex / 2))
+
+#ifdef _LZMA_PROB32
+#define CLzmaProb UInt32
+#else
+#define CLzmaProb UInt16
+#endif
+
+#define LZMA_PB_MAX 4
+#define LZMA_LC_MAX 8
+#define LZMA_LP_MAX 4
+
+#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
+
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
+
+#define LZMA_MATCH_LEN_MIN 2
+#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
+
+#define kNumStates 12
+
+typedef struct
+{
+  CLzmaProb choice;
+  CLzmaProb choice2;
+  CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];
+  CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];
+  CLzmaProb high[kLenNumHighSymbols];
+} CLenEnc;
+
+typedef struct
+{
+  CLenEnc p;
+  UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
+  UInt32 tableSize;
+  UInt32 counters[LZMA_NUM_PB_STATES_MAX];
+} CLenPriceEnc;
+
+typedef struct _CRangeEnc
+{
+  UInt32 range;
+  Byte cache;
+  UInt64 low;
+  UInt64 cacheSize;
+  Byte *buf;
+  Byte *bufLim;
+  Byte *bufBase;
+  ISeqOutStream *outStream;
+  UInt64 processed;
+  SRes res;
+} CRangeEnc;
+
+typedef struct _CSeqInStreamBuf
+{
+  ISeqInStream funcTable;
+  const Byte *data;
+  SizeT rem;
+} CSeqInStreamBuf;
+
+static SRes MyRead(void *pp, void *data, size_t *size)
+{
+  size_t curSize = *size;
+  CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp;
+  if (p->rem < curSize)
+    curSize = p->rem;
+  memcpy(data, p->data, curSize);
+  p->rem -= curSize;
+  p->data += curSize;
+  *size = curSize;
+  return SZ_OK;
+}
+
+typedef struct
+{
+  CLzmaProb *litProbs;
+
+  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
+  CLzmaProb isRep[kNumStates];
+  CLzmaProb isRepG0[kNumStates];
+  CLzmaProb isRepG1[kNumStates];
+  CLzmaProb isRepG2[kNumStates];
+  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
+
+  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
+  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
+  CLzmaProb posAlignEncoder[1 << kNumAlignBits];
+
+  CLenPriceEnc lenEnc;
+  CLenPriceEnc repLenEnc;
+
+  UInt32 reps[LZMA_NUM_REPS];
+  UInt32 state;
+} CSaveState;
+
+typedef struct _CLzmaEnc
+{
+  IMatchFinder matchFinder;
+  void *matchFinderObj;
+
+  #ifdef COMPRESS_MF_MT
+  Bool mtMode;
+  CMatchFinderMt matchFinderMt;
+  #endif
+
+  CMatchFinder matchFinderBase;
+
+  #ifdef COMPRESS_MF_MT
+  Byte pad[128];
+  #endif
+
+  UInt32 optimumEndIndex;
+  UInt32 optimumCurrentIndex;
+
+  Bool longestMatchWasFound;
+  UInt32 longestMatchLength;
+  UInt32 numDistancePairs;
+
+  COptimal opt[kNumOpts];
+
+  #ifndef LZMA_LOG_BSR
+  Byte g_FastPos[1 << kNumLogBits];
+  #endif
+
+  UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
+  UInt32 matchDistances[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
+  UInt32 numFastBytes;
+  UInt32 additionalOffset;
+  UInt32 reps[LZMA_NUM_REPS];
+  UInt32 state;
+
+  UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
+  UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
+  UInt32 alignPrices[kAlignTableSize];
+  UInt32 alignPriceCount;
+
+  UInt32 distTableSize;
+
+  unsigned lc, lp, pb;
+  unsigned lpMask, pbMask;
+
+  CLzmaProb *litProbs;
+
+  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
+  CLzmaProb isRep[kNumStates];
+  CLzmaProb isRepG0[kNumStates];
+  CLzmaProb isRepG1[kNumStates];
+  CLzmaProb isRepG2[kNumStates];
+  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
+
+  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
+  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
+  CLzmaProb posAlignEncoder[1 << kNumAlignBits];
+
+  CLenPriceEnc lenEnc;
+  CLenPriceEnc repLenEnc;
+
+  unsigned lclp;
+
+  Bool fastMode;
+
+  CRangeEnc rc;
+
+  Bool writeEndMark;
+  UInt64 nowPos64;
+  UInt32 matchPriceCount;
+  Bool finished;
+  Bool multiThread;
+
+  SRes result;
+  UInt32 dictSize;
+  UInt32 matchFinderCycles;
+
+  ISeqInStream *inStream;
+  CSeqInStreamBuf seqBufInStream;
+
+  CSaveState saveState;
+} CLzmaEnc;
+
+void LzmaEnc_SaveState(CLzmaEncHandle pp)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  CSaveState *dest = &p->saveState;
+  int i;
+  dest->lenEnc = p->lenEnc;
+  dest->repLenEnc = p->repLenEnc;
+  dest->state = p->state;
+
+  for (i = 0; i < kNumStates; i++)
+  {
+    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
+    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
+  }
+  for (i = 0; i < kNumLenToPosStates; i++)
+    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
+  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
+  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
+  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
+  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
+  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
+  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
+  memcpy(dest->reps, p->reps, sizeof(p->reps));
+  memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));
+}
+
+void LzmaEnc_RestoreState(CLzmaEncHandle pp)
+{
+  CLzmaEnc *dest = (CLzmaEnc *)pp;
+  const CSaveState *p = &dest->saveState;
+  int i;
+  dest->lenEnc = p->lenEnc;
+  dest->repLenEnc = p->repLenEnc;
+  dest->state = p->state;
+
+  for (i = 0; i < kNumStates; i++)
+  {
+    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
+    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
+  }
+  for (i = 0; i < kNumLenToPosStates; i++)
+    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
+  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
+  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
+  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
+  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
+  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
+  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
+  memcpy(dest->reps, p->reps, sizeof(p->reps));
+  memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));
+}
+
+SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  CLzmaEncProps props = *props2;
+  LzmaEncProps_Normalize(&props);
+
+  if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||
+      props.dictSize > (1U << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30))
+    return SZ_ERROR_PARAM;
+  p->dictSize = props.dictSize;
+  p->matchFinderCycles = props.mc;
+  {
+    unsigned fb = props.fb;
+    if (fb < 5)
+      fb = 5;
+    if (fb > LZMA_MATCH_LEN_MAX)
+      fb = LZMA_MATCH_LEN_MAX;
+    p->numFastBytes = fb;
+  }
+  p->lc = props.lc;
+  p->lp = props.lp;
+  p->pb = props.pb;
+  p->fastMode = (props.algo == 0);
+  p->matchFinderBase.btMode = props.btMode;
+  {
+    UInt32 numHashBytes = 4;
+    if (props.btMode)
+    {
+      if (props.numHashBytes < 2)
+        numHashBytes = 2;
+      else if (props.numHashBytes < 4)
+        numHashBytes = props.numHashBytes;
+    }
+    p->matchFinderBase.numHashBytes = numHashBytes;
+  }
+
+  p->matchFinderBase.cutValue = props.mc;
+
+  p->writeEndMark = props.writeEndMark;
+
+  #ifdef COMPRESS_MF_MT
+  /*
+  if (newMultiThread != _multiThread)
+  {
+    ReleaseMatchFinder();
+    _multiThread = newMultiThread;
+  }
+  */
+  p->multiThread = (props.numThreads > 1);
+  #endif
+
+  return SZ_OK;
+}
+
+static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};
+static const int kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
+static const int kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
+static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
+
+/*
+  void UpdateChar() { Index = kLiteralNextStates[Index]; }
+  void UpdateMatch() { Index = kMatchNextStates[Index]; }
+  void UpdateRep() { Index = kRepNextStates[Index]; }
+  void UpdateShortRep() { Index = kShortRepNextStates[Index]; }
+*/
+
+#define IsCharState(s) ((s) < 7)
+
+
+#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
+
+#define kInfinityPrice (1 << 30)
+
+static void RangeEnc_Construct(CRangeEnc *p)
+{
+  p->outStream = 0;
+  p->bufBase = 0;
+}
+
+#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
+
+#define RC_BUF_SIZE (1 << 16)
+static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
+{
+  if (p->bufBase == 0)
+  {
+    p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
+    if (p->bufBase == 0)
+      return 0;
+    p->bufLim = p->bufBase + RC_BUF_SIZE;
+  }
+  return 1;
+}
+
+static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)
+{
+  alloc->Free(alloc, p->bufBase);
+  p->bufBase = 0;
+}
+
+static void RangeEnc_Init(CRangeEnc *p)
+{
+  /* Stream.Init(); */
+  p->low = 0;
+  p->range = 0xFFFFFFFF;
+  p->cacheSize = 1;
+  p->cache = 0;
+
+  p->buf = p->bufBase;
+
+  p->processed = 0;
+  p->res = SZ_OK;
+}
+
+static void RangeEnc_FlushStream(CRangeEnc *p)
+{
+  size_t num;
+  if (p->res != SZ_OK)
+    return;
+  num = p->buf - p->bufBase;
+  if (num != p->outStream->Write(p->outStream, p->bufBase, num))
+    p->res = SZ_ERROR_WRITE;
+  p->processed += num;
+  p->buf = p->bufBase;
+}
+
+static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
+{
+  if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0)
+  {
+    Byte temp = p->cache;
+    do
+    {
+      Byte *buf = p->buf;
+      *buf++ = (Byte)(temp + (Byte)(p->low >> 32));
+      p->buf = buf;
+      if (buf == p->bufLim)
+        RangeEnc_FlushStream(p);
+      temp = 0xFF;
+    }
+    while (--p->cacheSize != 0);
+    p->cache = (Byte)((UInt32)p->low >> 24);
+  }
+  p->cacheSize++;
+  p->low = (UInt32)p->low << 8;
+}
+
+static void RangeEnc_FlushData(CRangeEnc *p)
+{
+  int i;
+  for (i = 0; i < 5; i++)
+    RangeEnc_ShiftLow(p);
+}
+
+static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)
+{
+  do
+  {
+    p->range >>= 1;
+    p->low += p->range & (0 - ((value >> --numBits) & 1));
+    if (p->range < kTopValue)
+    {
+      p->range <<= 8;
+      RangeEnc_ShiftLow(p);
+    }
+  }
+  while (numBits != 0);
+}
+
+static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)
+{
+  UInt32 ttt = *prob;
+  UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;
+  if (symbol == 0)
+  {
+    p->range = newBound;
+    ttt += (kBitModelTotal - ttt) >> kNumMoveBits;
+  }
+  else
+  {
+    p->low += newBound;
+    p->range -= newBound;
+    ttt -= ttt >> kNumMoveBits;
+  }
+  *prob = (CLzmaProb)ttt;
+  if (p->range < kTopValue)
+  {
+    p->range <<= 8;
+    RangeEnc_ShiftLow(p);
+  }
+}
+
+static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
+{
+  symbol |= 0x100;
+  do
+  {
+    RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
+    symbol <<= 1;
+  }
+  while (symbol < 0x10000);
+}
+
+static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
+{
+  UInt32 offs = 0x100;
+  symbol |= 0x100;
+  do
+  {
+    matchByte <<= 1;
+    RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
+    symbol <<= 1;
+    offs &= ~(matchByte ^ symbol);
+  }
+  while (symbol < 0x10000);
+}
+
+void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
+{
+  UInt32 i;
+  for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
+  {
+    const int kCyclesBits = kNumBitPriceShiftBits;
+    UInt32 w = i;
+    UInt32 bitCount = 0;
+    int j;
+    for (j = 0; j < kCyclesBits; j++)
+    {
+      w = w * w;
+      bitCount <<= 1;
+      while (w >= ((UInt32)1 << 16))
+      {
+        w >>= 1;
+        bitCount++;
+      }
+    }
+    ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
+  }
+}
+
+
+#define GET_PRICE(prob, symbol) \
+  p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
+
+#define GET_PRICEa(prob, symbol) \
+  ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
+
+#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
+#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
+
+#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
+#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
+
+static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)
+{
+  UInt32 price = 0;
+  symbol |= 0x100;
+  do
+  {
+    price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);
+    symbol <<= 1;
+  }
+  while (symbol < 0x10000);
+  return price;
+};
+
+static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)
+{
+  UInt32 price = 0;
+  UInt32 offs = 0x100;
+  symbol |= 0x100;
+  do
+  {
+    matchByte <<= 1;
+    price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);
+    symbol <<= 1;
+    offs &= ~(matchByte ^ symbol);
+  }
+  while (symbol < 0x10000);
+  return price;
+};
+
+
+static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
+{
+  UInt32 m = 1;
+  int i;
+  for (i = numBitLevels; i != 0 ;)
+  {
+    UInt32 bit;
+    i--;
+    bit = (symbol >> i) & 1;
+    RangeEnc_EncodeBit(rc, probs + m, bit);
+    m = (m << 1) | bit;
+  }
+};
+
+static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
+{
+  UInt32 m = 1;
+  int i;
+  for (i = 0; i < numBitLevels; i++)
+  {
+    UInt32 bit = symbol & 1;
+    RangeEnc_EncodeBit(rc, probs + m, bit);
+    m = (m << 1) | bit;
+    symbol >>= 1;
+  }
+}
+
+static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
+{
+  UInt32 price = 0;
+  symbol |= (1 << numBitLevels);
+  while (symbol != 1)
+  {
+    price += GET_PRICEa(probs[symbol >> 1], symbol & 1);
+    symbol >>= 1;
+  }
+  return price;
+}
+
+static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
+{
+  UInt32 price = 0;
+  UInt32 m = 1;
+  int i;
+  for (i = numBitLevels; i != 0; i--)
+  {
+    UInt32 bit = symbol & 1;
+    symbol >>= 1;
+    price += GET_PRICEa(probs[m], bit);
+    m = (m << 1) | bit;
+  }
+  return price;
+}
+
+
+static void LenEnc_Init(CLenEnc *p)
+{
+  unsigned i;
+  p->choice = p->choice2 = kProbInitValue;
+  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)
+    p->low[i] = kProbInitValue;
+  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)
+    p->mid[i] = kProbInitValue;
+  for (i = 0; i < kLenNumHighSymbols; i++)
+    p->high[i] = kProbInitValue;
+}
+
+static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)
+{
+  if (symbol < kLenNumLowSymbols)
+  {
+    RangeEnc_EncodeBit(rc, &p->choice, 0);
+    RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
+  }
+  else
+  {
+    RangeEnc_EncodeBit(rc, &p->choice, 1);
+    if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)
+    {
+      RangeEnc_EncodeBit(rc, &p->choice2, 0);
+      RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);
+    }
+    else
+    {
+      RangeEnc_EncodeBit(rc, &p->choice2, 1);
+      RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);
+    }
+  }
+}
+
+static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)
+{
+  UInt32 a0 = GET_PRICE_0a(p->choice);
+  UInt32 a1 = GET_PRICE_1a(p->choice);
+  UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);
+  UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);
+  UInt32 i = 0;
+  for (i = 0; i < kLenNumLowSymbols; i++)
+  {
+    if (i >= numSymbols)
+      return;
+    prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);
+  }
+  for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)
+  {
+    if (i >= numSymbols)
+      return;
+    prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);
+  }
+  for (; i < numSymbols; i++)
+    prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
+}
+
+static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)
+{
+  LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);
+  p->counters[posState] = p->tableSize;
+}
+
+static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)
+{
+  UInt32 posState;
+  for (posState = 0; posState < numPosStates; posState++)
+    LenPriceEnc_UpdateTable(p, posState, ProbPrices);
+}
+
+static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)
+{
+  LenEnc_Encode(&p->p, rc, symbol, posState);
+  if (updatePrice)
+    if (--p->counters[posState] == 0)
+      LenPriceEnc_UpdateTable(p, posState, ProbPrices);
+}
+
+
+
+
+static void MovePos(CLzmaEnc *p, UInt32 num)
+{
+  #ifdef SHOW_STAT
+  ttt += num;
+  printf("\n MovePos %d", num);
+  #endif
+  if (num != 0)
+  {
+    p->additionalOffset += num;
+    p->matchFinder.Skip(p->matchFinderObj, num);
+  }
+}
+
+static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
+{
+  UInt32 lenRes = 0, numDistancePairs;
+  numDistancePairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matchDistances);
+  #ifdef SHOW_STAT
+  printf("\n i = %d numPairs = %d    ", ttt, numDistancePairs / 2);
+  if (ttt >= 61994)
+    ttt = ttt;
+
+  ttt++;
+  {
+    UInt32 i;
+  for (i = 0; i < numDistancePairs; i += 2)
+    printf("%2d %6d   | ", p->matchDistances[i], p->matchDistances[i + 1]);
+  }
+  #endif
+  if (numDistancePairs > 0)
+  {
+    lenRes = p->matchDistances[numDistancePairs - 2];
+    if (lenRes == p->numFastBytes)
+    {
+      UInt32 numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) + 1;
+      const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+      UInt32 distance = p->matchDistances[numDistancePairs - 1] + 1;
+      if (numAvail > LZMA_MATCH_LEN_MAX)
+        numAvail = LZMA_MATCH_LEN_MAX;
+
+      {
+        const Byte *pby2 = pby - distance;
+        for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);
+      }
+    }
+  }
+  p->additionalOffset++;
+  *numDistancePairsRes = numDistancePairs;
+  return lenRes;
+}
+
+
+#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False;
+#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False;
+#define IsShortRep(p) ((p)->backPrev == 0)
+
+static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)
+{
+  return
+    GET_PRICE_0(p->isRepG0[state]) +
+    GET_PRICE_0(p->isRep0Long[state][posState]);
+}
+
+static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)
+{
+  UInt32 price;
+  if (repIndex == 0)
+  {
+    price = GET_PRICE_0(p->isRepG0[state]);
+    price += GET_PRICE_1(p->isRep0Long[state][posState]);
+  }
+  else
+  {
+    price = GET_PRICE_1(p->isRepG0[state]);
+    if (repIndex == 1)
+      price += GET_PRICE_0(p->isRepG1[state]);
+    else
+    {
+      price += GET_PRICE_1(p->isRepG1[state]);
+      price += GET_PRICE(p->isRepG2[state], repIndex - 2);
+    }
+  }
+  return price;
+}
+
+static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)
+{
+  return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +
+    GetPureRepPrice(p, repIndex, state, posState);
+}
+
+static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
+{
+  UInt32 posMem = p->opt[cur].posPrev;
+  UInt32 backMem = p->opt[cur].backPrev;
+  p->optimumEndIndex = cur;
+  do
+  {
+    if (p->opt[cur].prev1IsChar)
+    {
+      MakeAsChar(&p->opt[posMem])
+      p->opt[posMem].posPrev = posMem - 1;
+      if (p->opt[cur].prev2)
+      {
+        p->opt[posMem - 1].prev1IsChar = False;
+        p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;
+        p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;
+      }
+    }
+    {
+      UInt32 posPrev = posMem;
+      UInt32 backCur = backMem;
+
+      backMem = p->opt[posPrev].backPrev;
+      posMem = p->opt[posPrev].posPrev;
+
+      p->opt[posPrev].backPrev = backCur;
+      p->opt[posPrev].posPrev = cur;
+      cur = posPrev;
+    }
+  }
+  while (cur != 0);
+  *backRes = p->opt[0].backPrev;
+  p->optimumCurrentIndex  = p->opt[0].posPrev;
+  return p->optimumCurrentIndex;
+}
+
+#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)
+
+static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
+{
+  UInt32 numAvailableBytes, lenMain, numDistancePairs;
+  const Byte *data;
+  UInt32 reps[LZMA_NUM_REPS];
+  UInt32 repLens[LZMA_NUM_REPS];
+  UInt32 repMaxIndex, i;
+  UInt32 *matchDistances;
+  Byte currentByte, matchByte;
+  UInt32 posState;
+  UInt32 matchPrice, repMatchPrice;
+  UInt32 lenEnd;
+  UInt32 len;
+  UInt32 normalMatchPrice;
+  UInt32 cur;
+  if (p->optimumEndIndex != p->optimumCurrentIndex)
+  {
+    const COptimal *opt = &p->opt[p->optimumCurrentIndex];
+    UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;
+    *backRes = opt->backPrev;
+    p->optimumCurrentIndex = opt->posPrev;
+    return lenRes;
+  }
+  p->optimumCurrentIndex = p->optimumEndIndex = 0;
+
+  numAvailableBytes = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
+
+  if (!p->longestMatchWasFound)
+  {
+    lenMain = ReadMatchDistances(p, &numDistancePairs);
+  }
+  else
+  {
+    lenMain = p->longestMatchLength;
+    numDistancePairs = p->numDistancePairs;
+    p->longestMatchWasFound = False;
+  }
+
+  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+  if (numAvailableBytes < 2)
+  {
+    *backRes = (UInt32)(-1);
+    return 1;
+  }
+  if (numAvailableBytes > LZMA_MATCH_LEN_MAX)
+    numAvailableBytes = LZMA_MATCH_LEN_MAX;
+
+  repMaxIndex = 0;
+  for (i = 0; i < LZMA_NUM_REPS; i++)
+  {
+    UInt32 lenTest;
+    const Byte *data2;
+    reps[i] = p->reps[i];
+    data2 = data - (reps[i] + 1);
+    if (data[0] != data2[0] || data[1] != data2[1])
+    {
+      repLens[i] = 0;
+      continue;
+    }
+    for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++);
+    repLens[i] = lenTest;
+    if (lenTest > repLens[repMaxIndex])
+      repMaxIndex = i;
+  }
+  if (repLens[repMaxIndex] >= p->numFastBytes)
+  {
+    UInt32 lenRes;
+    *backRes = repMaxIndex;
+    lenRes = repLens[repMaxIndex];
+    MovePos(p, lenRes - 1);
+    return lenRes;
+  }
+
+  matchDistances = p->matchDistances;
+  if (lenMain >= p->numFastBytes)
+  {
+    *backRes = matchDistances[numDistancePairs - 1] + LZMA_NUM_REPS;
+    MovePos(p, lenMain - 1);
+    return lenMain;
+  }
+  currentByte = *data;
+  matchByte = *(data - (reps[0] + 1));
+
+  if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
+  {
+    *backRes = (UInt32)-1;
+    return 1;
+  }
+
+  p->opt[0].state = (CState)p->state;
+
+  posState = (position & p->pbMask);
+
+  {
+    const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
+    p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
+        (!IsCharState(p->state) ?
+          LitEnc_GetPriceMatched(probs, currentByte, matchByte, p->ProbPrices) :
+          LitEnc_GetPrice(probs, currentByte, p->ProbPrices));
+  }
+
+  MakeAsChar(&p->opt[1]);
+
+  matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
+  repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
+
+  if (matchByte == currentByte)
+  {
+    UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);
+    if (shortRepPrice < p->opt[1].price)
+    {
+      p->opt[1].price = shortRepPrice;
+      MakeAsShortRep(&p->opt[1]);
+    }
+  }
+  lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);
+
+  if (lenEnd < 2)
+  {
+    *backRes = p->opt[1].backPrev;
+    return 1;
+  }
+
+  p->opt[1].posPrev = 0;
+  for (i = 0; i < LZMA_NUM_REPS; i++)
+    p->opt[0].backs[i] = reps[i];
+
+  len = lenEnd;
+  do
+    p->opt[len--].price = kInfinityPrice;
+  while (len >= 2);
+
+  for (i = 0; i < LZMA_NUM_REPS; i++)
+  {
+    UInt32 repLen = repLens[i];
+    UInt32 price;
+    if (repLen < 2)
+      continue;
+    price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);
+    do
+    {
+      UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];
+      COptimal *opt = &p->opt[repLen];
+      if (curAndLenPrice < opt->price)
+      {
+        opt->price = curAndLenPrice;
+        opt->posPrev = 0;
+        opt->backPrev = i;
+        opt->prev1IsChar = False;
+      }
+    }
+    while (--repLen >= 2);
+  }
+
+  normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
+
+  len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
+  if (len <= lenMain)
+  {
+    UInt32 offs = 0;
+    while (len > matchDistances[offs])
+      offs += 2;
+    for (; ; len++)
+    {
+      COptimal *opt;
+      UInt32 distance = matchDistances[offs + 1];
+
+      UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];
+      UInt32 lenToPosState = GetLenToPosState(len);
+      if (distance < kNumFullDistances)
+        curAndLenPrice += p->distancesPrices[lenToPosState][distance];
+      else
+      {
+        UInt32 slot;
+        GetPosSlot2(distance, slot);
+        curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];
+      }
+      opt = &p->opt[len];
+      if (curAndLenPrice < opt->price)
+      {
+        opt->price = curAndLenPrice;
+        opt->posPrev = 0;
+        opt->backPrev = distance + LZMA_NUM_REPS;
+        opt->prev1IsChar = False;
+      }
+      if (len == matchDistances[offs])
+      {
+        offs += 2;
+        if (offs == numDistancePairs)
+          break;
+      }
+    }
+  }
+
+  cur = 0;
+
+    #ifdef SHOW_STAT2
+    if (position >= 0)
+    {
+      unsigned i;
+      printf("\n pos = %4X", position);
+      for (i = cur; i <= lenEnd; i++)
+      printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);
+    }
+    #endif
+
+  for (;;)
+  {
+    UInt32 numAvailableBytesFull, newLen, numDistancePairs;
+    COptimal *curOpt;
+    UInt32 posPrev;
+    UInt32 state;
+    UInt32 curPrice;
+    Bool nextIsChar;
+    const Byte *data;
+    Byte currentByte, matchByte;
+    UInt32 posState;
+    UInt32 curAnd1Price;
+    COptimal *nextOpt;
+    UInt32 matchPrice, repMatchPrice;
+    UInt32 numAvailableBytes;
+    UInt32 startLen;
+
+    cur++;
+    if (cur == lenEnd)
+      return Backward(p, backRes, cur);
+
+    numAvailableBytesFull = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
+    newLen = ReadMatchDistances(p, &numDistancePairs);
+    if (newLen >= p->numFastBytes)
+    {
+      p->numDistancePairs = numDistancePairs;
+      p->longestMatchLength = newLen;
+      p->longestMatchWasFound = True;
+      return Backward(p, backRes, cur);
+    }
+    position++;
+    curOpt = &p->opt[cur];
+    posPrev = curOpt->posPrev;
+    if (curOpt->prev1IsChar)
+    {
+      posPrev--;
+      if (curOpt->prev2)
+      {
+        state = p->opt[curOpt->posPrev2].state;
+        if (curOpt->backPrev2 < LZMA_NUM_REPS)
+          state = kRepNextStates[state];
+        else
+          state = kMatchNextStates[state];
+      }
+      else
+        state = p->opt[posPrev].state;
+      state = kLiteralNextStates[state];
+    }
+    else
+      state = p->opt[posPrev].state;
+    if (posPrev == cur - 1)
+    {
+      if (IsShortRep(curOpt))
+        state = kShortRepNextStates[state];
+      else
+        state = kLiteralNextStates[state];
+    }
+    else
+    {
+      UInt32 pos;
+      const COptimal *prevOpt;
+      if (curOpt->prev1IsChar && curOpt->prev2)
+      {
+        posPrev = curOpt->posPrev2;
+        pos = curOpt->backPrev2;
+        state = kRepNextStates[state];
+      }
+      else
+      {
+        pos = curOpt->backPrev;
+        if (pos < LZMA_NUM_REPS)
+          state = kRepNextStates[state];
+        else
+          state = kMatchNextStates[state];
+      }
+      prevOpt = &p->opt[posPrev];
+      if (pos < LZMA_NUM_REPS)
+      {
+        UInt32 i;
+        reps[0] = prevOpt->backs[pos];
+        for (i = 1; i <= pos; i++)
+          reps[i] = prevOpt->backs[i - 1];
+        for (; i < LZMA_NUM_REPS; i++)
+          reps[i] = prevOpt->backs[i];
+      }
+      else
+      {
+        UInt32 i;
+        reps[0] = (pos - LZMA_NUM_REPS);
+        for (i = 1; i < LZMA_NUM_REPS; i++)
+          reps[i] = prevOpt->backs[i - 1];
+      }
+    }
+    curOpt->state = (CState)state;
+
+    curOpt->backs[0] = reps[0];
+    curOpt->backs[1] = reps[1];
+    curOpt->backs[2] = reps[2];
+    curOpt->backs[3] = reps[3];
+
+    curPrice = curOpt->price;
+    nextIsChar = False;
+    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+    currentByte = *data;
+    matchByte = *(data - (reps[0] + 1));
+
+    posState = (position & p->pbMask);
+
+    curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
+    {
+      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
+      curAnd1Price +=
+        (!IsCharState(state) ?
+          LitEnc_GetPriceMatched(probs, currentByte, matchByte, p->ProbPrices) :
+          LitEnc_GetPrice(probs, currentByte, p->ProbPrices));
+    }
+
+    nextOpt = &p->opt[cur + 1];
+
+    if (curAnd1Price < nextOpt->price)
+    {
+      nextOpt->price = curAnd1Price;
+      nextOpt->posPrev = cur;
+      MakeAsChar(nextOpt);
+      nextIsChar = True;
+    }
+
+    matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
+    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
+
+    if (matchByte == currentByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))
+    {
+      UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);
+      if (shortRepPrice <= nextOpt->price)
+      {
+        nextOpt->price = shortRepPrice;
+        nextOpt->posPrev = cur;
+        MakeAsShortRep(nextOpt);
+        nextIsChar = True;
+      }
+    }
+
+    {
+      UInt32 temp = kNumOpts - 1 - cur;
+      if (temp <  numAvailableBytesFull)
+        numAvailableBytesFull = temp;
+    }
+    numAvailableBytes = numAvailableBytesFull;
+
+    if (numAvailableBytes < 2)
+      continue;
+    if (numAvailableBytes > p->numFastBytes)
+      numAvailableBytes = p->numFastBytes;
+    if (!nextIsChar && matchByte != currentByte) /* speed optimization */
+    {
+      /* try Literal + rep0 */
+      UInt32 temp;
+      UInt32 lenTest2;
+      const Byte *data2 = data - (reps[0] + 1);
+      UInt32 limit = p->numFastBytes + 1;
+      if (limit > numAvailableBytesFull)
+        limit = numAvailableBytesFull;
+
+      for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);
+      lenTest2 = temp - 1;
+      if (lenTest2 >= 2)
+      {
+        UInt32 state2 = kLiteralNextStates[state];
+        UInt32 posStateNext = (position + 1) & p->pbMask;
+        UInt32 nextRepMatchPrice = curAnd1Price +
+            GET_PRICE_1(p->isMatch[state2][posStateNext]) +
+            GET_PRICE_1(p->isRep[state2]);
+        /* for (; lenTest2 >= 2; lenTest2--) */
+        {
+          UInt32 curAndLenPrice;
+          COptimal *opt;
+          UInt32 offset = cur + 1 + lenTest2;
+          while (lenEnd < offset)
+            p->opt[++lenEnd].price = kInfinityPrice;
+          curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+          opt = &p->opt[offset];
+          if (curAndLenPrice < opt->price)
+          {
+            opt->price = curAndLenPrice;
+            opt->posPrev = cur + 1;
+            opt->backPrev = 0;
+            opt->prev1IsChar = True;
+            opt->prev2 = False;
+          }
+        }
+      }
+    }
+
+    startLen = 2; /* speed optimization */
+    {
+    UInt32 repIndex;
+    for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)
+    {
+      UInt32 lenTest;
+      UInt32 lenTestTemp;
+      UInt32 price;
+      const Byte *data2 = data - (reps[repIndex] + 1);
+      if (data[0] != data2[0] || data[1] != data2[1])
+        continue;
+      for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++);
+      while (lenEnd < cur + lenTest)
+        p->opt[++lenEnd].price = kInfinityPrice;
+      lenTestTemp = lenTest;
+      price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);
+      do
+      {
+        UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];
+        COptimal *opt = &p->opt[cur + lenTest];
+        if (curAndLenPrice < opt->price)
+        {
+          opt->price = curAndLenPrice;
+          opt->posPrev = cur;
+          opt->backPrev = repIndex;
+          opt->prev1IsChar = False;
+        }
+      }
+      while (--lenTest >= 2);
+      lenTest = lenTestTemp;
+
+      if (repIndex == 0)
+        startLen = lenTest + 1;
+
+      /* if (_maxMode) */
+        {
+          UInt32 lenTest2 = lenTest + 1;
+          UInt32 limit = lenTest2 + p->numFastBytes;
+          UInt32 nextRepMatchPrice;
+          if (limit > numAvailableBytesFull)
+            limit = numAvailableBytesFull;
+          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
+          lenTest2 -= lenTest + 1;
+          if (lenTest2 >= 2)
+          {
+            UInt32 state2 = kRepNextStates[state];
+            UInt32 posStateNext = (position + lenTest) & p->pbMask;
+            UInt32 curAndLenCharPrice =
+                price + p->repLenEnc.prices[posState][lenTest - 2] +
+                GET_PRICE_0(p->isMatch[state2][posStateNext]) +
+                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
+                    data[lenTest], data2[lenTest], p->ProbPrices);
+            state2 = kLiteralNextStates[state2];
+            posStateNext = (position + lenTest + 1) & p->pbMask;
+            nextRepMatchPrice = curAndLenCharPrice +
+                GET_PRICE_1(p->isMatch[state2][posStateNext]) +
+                GET_PRICE_1(p->isRep[state2]);
+
+            /* for (; lenTest2 >= 2; lenTest2--) */
+            {
+              UInt32 curAndLenPrice;
+              COptimal *opt;
+              UInt32 offset = cur + lenTest + 1 + lenTest2;
+              while (lenEnd < offset)
+                p->opt[++lenEnd].price = kInfinityPrice;
+              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+              opt = &p->opt[offset];
+              if (curAndLenPrice < opt->price)
+              {
+                opt->price = curAndLenPrice;
+                opt->posPrev = cur + lenTest + 1;
+                opt->backPrev = 0;
+                opt->prev1IsChar = True;
+                opt->prev2 = True;
+                opt->posPrev2 = cur;
+                opt->backPrev2 = repIndex;
+              }
+            }
+          }
+        }
+    }
+    }
+    /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */
+    if (newLen > numAvailableBytes)
+    {
+      newLen = numAvailableBytes;
+      for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2);
+      matchDistances[numDistancePairs] = newLen;
+      numDistancePairs += 2;
+    }
+    if (newLen >= startLen)
+    {
+      UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
+      UInt32 offs, curBack, posSlot;
+      UInt32 lenTest;
+      while (lenEnd < cur + newLen)
+        p->opt[++lenEnd].price = kInfinityPrice;
+
+      offs = 0;
+      while (startLen > matchDistances[offs])
+        offs += 2;
+      curBack = matchDistances[offs + 1];
+      GetPosSlot2(curBack, posSlot);
+      for (lenTest = /*2*/ startLen; ; lenTest++)
+      {
+        UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];
+        UInt32 lenToPosState = GetLenToPosState(lenTest);
+        COptimal *opt;
+        if (curBack < kNumFullDistances)
+          curAndLenPrice += p->distancesPrices[lenToPosState][curBack];
+        else
+          curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];
+
+        opt = &p->opt[cur + lenTest];
+        if (curAndLenPrice < opt->price)
+        {
+          opt->price = curAndLenPrice;
+          opt->posPrev = cur;
+          opt->backPrev = curBack + LZMA_NUM_REPS;
+          opt->prev1IsChar = False;
+        }
+
+        if (/*_maxMode && */lenTest == matchDistances[offs])
+        {
+          /* Try Match + Literal + Rep0 */
+          const Byte *data2 = data - (curBack + 1);
+          UInt32 lenTest2 = lenTest + 1;
+          UInt32 limit = lenTest2 + p->numFastBytes;
+          UInt32 nextRepMatchPrice;
+          if (limit > numAvailableBytesFull)
+            limit = numAvailableBytesFull;
+          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
+          lenTest2 -= lenTest + 1;
+          if (lenTest2 >= 2)
+          {
+            UInt32 state2 = kMatchNextStates[state];
+            UInt32 posStateNext = (position + lenTest) & p->pbMask;
+            UInt32 curAndLenCharPrice = curAndLenPrice +
+                GET_PRICE_0(p->isMatch[state2][posStateNext]) +
+                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
+                    data[lenTest], data2[lenTest], p->ProbPrices);
+            state2 = kLiteralNextStates[state2];
+            posStateNext = (posStateNext + 1) & p->pbMask;
+            nextRepMatchPrice = curAndLenCharPrice +
+                GET_PRICE_1(p->isMatch[state2][posStateNext]) +
+                GET_PRICE_1(p->isRep[state2]);
+
+            /* for (; lenTest2 >= 2; lenTest2--) */
+            {
+              UInt32 offset = cur + lenTest + 1 + lenTest2;
+              UInt32 curAndLenPrice;
+              COptimal *opt;
+              while (lenEnd < offset)
+                p->opt[++lenEnd].price = kInfinityPrice;
+              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+              opt = &p->opt[offset];
+              if (curAndLenPrice < opt->price)
+              {
+                opt->price = curAndLenPrice;
+                opt->posPrev = cur + lenTest + 1;
+                opt->backPrev = 0;
+                opt->prev1IsChar = True;
+                opt->prev2 = True;
+                opt->posPrev2 = cur;
+                opt->backPrev2 = curBack + LZMA_NUM_REPS;
+              }
+            }
+          }
+          offs += 2;
+          if (offs == numDistancePairs)
+            break;
+          curBack = matchDistances[offs + 1];
+          if (curBack >= kNumFullDistances)
+            GetPosSlot2(curBack, posSlot);
+        }
+      }
+    }
+  }
+}
+
+#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
+
+static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
+{
+  UInt32 numAvailableBytes = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
+  UInt32 lenMain, numDistancePairs;
+  const Byte *data;
+  UInt32 repLens[LZMA_NUM_REPS];
+  UInt32 repMaxIndex, i;
+  UInt32 *matchDistances;
+  UInt32 backMain;
+
+  if (!p->longestMatchWasFound)
+  {
+    lenMain = ReadMatchDistances(p, &numDistancePairs);
+  }
+  else
+  {
+    lenMain = p->longestMatchLength;
+    numDistancePairs = p->numDistancePairs;
+    p->longestMatchWasFound = False;
+  }
+
+  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+  if (numAvailableBytes > LZMA_MATCH_LEN_MAX)
+    numAvailableBytes = LZMA_MATCH_LEN_MAX;
+  if (numAvailableBytes < 2)
+  {
+    *backRes = (UInt32)(-1);
+    return 1;
+  }
+
+  repMaxIndex = 0;
+
+  for (i = 0; i < LZMA_NUM_REPS; i++)
+  {
+    const Byte *data2 = data - (p->reps[i] + 1);
+    UInt32 len;
+    if (data[0] != data2[0] || data[1] != data2[1])
+    {
+      repLens[i] = 0;
+      continue;
+    }
+    for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++);
+    if (len >= p->numFastBytes)
+    {
+      *backRes = i;
+      MovePos(p, len - 1);
+      return len;
+    }
+    repLens[i] = len;
+    if (len > repLens[repMaxIndex])
+      repMaxIndex = i;
+  }
+  matchDistances = p->matchDistances;
+  if (lenMain >= p->numFastBytes)
+  {
+    *backRes = matchDistances[numDistancePairs - 1] + LZMA_NUM_REPS;
+    MovePos(p, lenMain - 1);
+    return lenMain;
+  }
+
+  backMain = 0; /* for GCC */
+  if (lenMain >= 2)
+  {
+    backMain = matchDistances[numDistancePairs - 1];
+    while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1)
+    {
+      if (!ChangePair(matchDistances[numDistancePairs - 3], backMain))
+        break;
+      numDistancePairs -= 2;
+      lenMain = matchDistances[numDistancePairs - 2];
+      backMain = matchDistances[numDistancePairs - 1];
+    }
+    if (lenMain == 2 && backMain >= 0x80)
+      lenMain = 1;
+  }
+
+  if (repLens[repMaxIndex] >= 2)
+  {
+    if (repLens[repMaxIndex] + 1 >= lenMain ||
+        (repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9))) ||
+        (repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15))))
+    {
+      UInt32 lenRes;
+      *backRes = repMaxIndex;
+      lenRes = repLens[repMaxIndex];
+      MovePos(p, lenRes - 1);
+      return lenRes;
+    }
+  }
+
+  if (lenMain >= 2 && numAvailableBytes > 2)
+  {
+    UInt32 i;
+    numAvailableBytes = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
+    p->longestMatchLength = ReadMatchDistances(p, &p->numDistancePairs);
+    if (p->longestMatchLength >= 2)
+    {
+      UInt32 newDistance = matchDistances[p->numDistancePairs - 1];
+      if ((p->longestMatchLength >= lenMain && newDistance < backMain) ||
+          (p->longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance)) ||
+          (p->longestMatchLength > lenMain + 1) ||
+          (p->longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain)))
+      {
+        p->longestMatchWasFound = True;
+        *backRes = (UInt32)(-1);
+        return 1;
+      }
+    }
+    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+    for (i = 0; i < LZMA_NUM_REPS; i++)
+    {
+      UInt32 len;
+      const Byte *data2 = data - (p->reps[i] + 1);
+      if (data[1] != data2[1] || data[2] != data2[2])
+      {
+        repLens[i] = 0;
+        continue;
+      }
+      for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++);
+      if (len + 1 >= lenMain)
+      {
+        p->longestMatchWasFound = True;
+        *backRes = (UInt32)(-1);
+        return 1;
+      }
+    }
+    *backRes = backMain + LZMA_NUM_REPS;
+    MovePos(p, lenMain - 2);
+    return lenMain;
+  }
+  *backRes = (UInt32)(-1);
+  return 1;
+}
+
+static void WriteEndMarker(CLzmaEnc *p, UInt32 posState)
+{
+  UInt32 len;
+  RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
+  RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
+  p->state = kMatchNextStates[p->state];
+  len = LZMA_MATCH_LEN_MIN;
+  LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
+  RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);
+  RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);
+  RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
+}
+
+static SRes CheckErrors(CLzmaEnc *p)
+{
+  if (p->result != SZ_OK)
+    return p->result;
+  if (p->rc.res != SZ_OK)
+    p->result = SZ_ERROR_WRITE;
+  if (p->matchFinderBase.result != SZ_OK)
+    p->result = SZ_ERROR_READ;
+  if (p->result != SZ_OK)
+    p->finished = True;
+  return p->result;
+}
+
+static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
+{
+  /* ReleaseMFStream(); */
+  p->finished = True;
+  if (p->writeEndMark)
+    WriteEndMarker(p, nowPos & p->pbMask);
+  RangeEnc_FlushData(&p->rc);
+  RangeEnc_FlushStream(&p->rc);
+  return CheckErrors(p);
+}
+
+static void FillAlignPrices(CLzmaEnc *p)
+{
+  UInt32 i;
+  for (i = 0; i < kAlignTableSize; i++)
+    p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
+  p->alignPriceCount = 0;
+}
+
+static void FillDistancesPrices(CLzmaEnc *p)
+{
+  UInt32 tempPrices[kNumFullDistances];
+  UInt32 i, lenToPosState;
+  for (i = kStartPosModelIndex; i < kNumFullDistances; i++)
+  {
+    UInt32 posSlot = GetPosSlot1(i);
+    UInt32 footerBits = ((posSlot >> 1) - 1);
+    UInt32 base = ((2 | (posSlot & 1)) << footerBits);
+    tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);
+  }
+
+  for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
+  {
+    UInt32 posSlot;
+    const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];
+    UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];
+    for (posSlot = 0; posSlot < p->distTableSize; posSlot++)
+      posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
+    for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)
+      posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
+
+    {
+      UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
+      UInt32 i;
+      for (i = 0; i < kStartPosModelIndex; i++)
+        distancesPrices[i] = posSlotPrices[i];
+      for (; i < kNumFullDistances; i++)
+        distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];
+    }
+  }
+  p->matchPriceCount = 0;
+}
+
+void LzmaEnc_Construct(CLzmaEnc *p)
+{
+  RangeEnc_Construct(&p->rc);
+  MatchFinder_Construct(&p->matchFinderBase);
+  #ifdef COMPRESS_MF_MT
+  MatchFinderMt_Construct(&p->matchFinderMt);
+  p->matchFinderMt.MatchFinder = &p->matchFinderBase;
+  #endif
+
+  {
+    CLzmaEncProps props;
+    LzmaEncProps_Init(&props);
+    LzmaEnc_SetProps(p, &props);
+  }
+
+  #ifndef LZMA_LOG_BSR
+  LzmaEnc_FastPosInit(p->g_FastPos);
+  #endif
+
+  LzmaEnc_InitPriceTables(p->ProbPrices);
+  p->litProbs = 0;
+  p->saveState.litProbs = 0;
+}
+
+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
+{
+  void *p;
+  p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
+  if (p != 0)
+    LzmaEnc_Construct((CLzmaEnc *)p);
+  return p;
+}
+
+void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
+{
+  alloc->Free(alloc, p->litProbs);
+  alloc->Free(alloc, p->saveState.litProbs);
+  p->litProbs = 0;
+  p->saveState.litProbs = 0;
+}
+
+void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  #ifdef COMPRESS_MF_MT
+  MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
+  #endif
+  MatchFinder_Free(&p->matchFinderBase, allocBig);
+  LzmaEnc_FreeLits(p, alloc);
+  RangeEnc_Free(&p->rc, alloc);
+}
+
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
+  alloc->Free(alloc, p);
+}
+
+static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
+{
+  UInt32 nowPos32, startPos32;
+  if (p->inStream != 0)
+  {
+    p->matchFinderBase.stream = p->inStream;
+    p->matchFinder.Init(p->matchFinderObj);
+    p->inStream = 0;
+  }
+
+  if (p->finished)
+    return p->result;
+  RINOK(CheckErrors(p));
+
+  nowPos32 = (UInt32)p->nowPos64;
+  startPos32 = nowPos32;
+
+  if (p->nowPos64 == 0)
+  {
+    UInt32 numDistancePairs;
+    Byte curByte;
+    if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
+      return Flush(p, nowPos32);
+    ReadMatchDistances(p, &numDistancePairs);
+    RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);
+    p->state = kLiteralNextStates[p->state];
+    curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);
+    LitEnc_Encode(&p->rc, p->litProbs, curByte);
+    p->additionalOffset--;
+    nowPos32++;
+  }
+
+  if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
+  for (;;)
+  {
+    UInt32 pos, len, posState;
+
+    if (p->fastMode)
+      len = GetOptimumFast(p, &pos);
+    else
+      len = GetOptimum(p, nowPos32, &pos);
+
+    #ifdef SHOW_STAT2
+    printf("\n pos = %4X,   len = %d   pos = %d", nowPos32, len, pos);
+    #endif
+
+    posState = nowPos32 & p->pbMask;
+    if (len == 1 && pos == 0xFFFFFFFF)
+    {
+      Byte curByte;
+      CLzmaProb *probs;
+      const Byte *data;
+
+      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);
+      data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
+      curByte = *data;
+      probs = LIT_PROBS(nowPos32, *(data - 1));
+      if (IsCharState(p->state))
+        LitEnc_Encode(&p->rc, probs, curByte);
+      else
+        LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));
+      p->state = kLiteralNextStates[p->state];
+    }
+    else
+    {
+      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
+      if (pos < LZMA_NUM_REPS)
+      {
+        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);
+        if (pos == 0)
+        {
+          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);
+          RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));
+        }
+        else
+        {
+          UInt32 distance = p->reps[pos];
+          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);
+          if (pos == 1)
+            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);
+          else
+          {
+            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);
+            RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);
+            if (pos == 3)
+              p->reps[3] = p->reps[2];
+            p->reps[2] = p->reps[1];
+          }
+          p->reps[1] = p->reps[0];
+          p->reps[0] = distance;
+        }
+        if (len == 1)
+          p->state = kShortRepNextStates[p->state];
+        else
+        {
+          LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
+          p->state = kRepNextStates[p->state];
+        }
+      }
+      else
+      {
+        UInt32 posSlot;
+        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
+        p->state = kMatchNextStates[p->state];
+        LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
+        pos -= LZMA_NUM_REPS;
+        GetPosSlot(pos, posSlot);
+        RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
+
+        if (posSlot >= kStartPosModelIndex)
+        {
+          UInt32 footerBits = ((posSlot >> 1) - 1);
+          UInt32 base = ((2 | (posSlot & 1)) << footerBits);
+          UInt32 posReduced = pos - base;
+
+          if (posSlot < kEndPosModelIndex)
+            RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);
+          else
+          {
+            RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
+            RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
+            p->alignPriceCount++;
+          }
+        }
+        p->reps[3] = p->reps[2];
+        p->reps[2] = p->reps[1];
+        p->reps[1] = p->reps[0];
+        p->reps[0] = pos;
+        p->matchPriceCount++;
+      }
+    }
+    p->additionalOffset -= len;
+    nowPos32 += len;
+    if (p->additionalOffset == 0)
+    {
+      UInt32 processed;
+      if (!p->fastMode)
+      {
+        if (p->matchPriceCount >= (1 << 7))
+          FillDistancesPrices(p);
+        if (p->alignPriceCount >= kAlignTableSize)
+          FillAlignPrices(p);
+      }
+      if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
+        break;
+      processed = nowPos32 - startPos32;
+      if (useLimits)
+      {
+        if (processed + kNumOpts + 300 >= maxUnpackSize ||
+            RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)
+          break;
+      }
+      else if (processed >= (1 << 15))
+      {
+        p->nowPos64 += nowPos32 - startPos32;
+        return CheckErrors(p);
+      }
+    }
+  }
+  p->nowPos64 += nowPos32 - startPos32;
+  return Flush(p, nowPos32);
+}
+
+#define kBigHashDicLimit ((UInt32)1 << 24)
+
+static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  UInt32 beforeSize = kNumOpts;
+  Bool btMode;
+  if (!RangeEnc_Alloc(&p->rc, alloc))
+    return SZ_ERROR_MEM;
+  btMode = (p->matchFinderBase.btMode != 0);
+  #ifdef COMPRESS_MF_MT
+  p->mtMode = (p->multiThread && !p->fastMode && btMode);
+  #endif
+
+  {
+    unsigned lclp = p->lc + p->lp;
+    if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)
+    {
+      LzmaEnc_FreeLits(p, alloc);
+      p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
+      p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
+      if (p->litProbs == 0 || p->saveState.litProbs == 0)
+      {
+        LzmaEnc_FreeLits(p, alloc);
+        return SZ_ERROR_MEM;
+      }
+      p->lclp = lclp;
+    }
+  }
+
+  p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);
+
+  if (beforeSize + p->dictSize < keepWindowSize)
+    beforeSize = keepWindowSize - p->dictSize;
+
+  #ifdef COMPRESS_MF_MT
+  if (p->mtMode)
+  {
+    RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));
+    p->matchFinderObj = &p->matchFinderMt;
+    MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
+  }
+  else
+  #endif
+  {
+    if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
+      return SZ_ERROR_MEM;
+    p->matchFinderObj = &p->matchFinderBase;
+    MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
+  }
+  return SZ_OK;
+}
+
+void LzmaEnc_Init(CLzmaEnc *p)
+{
+  UInt32 i;
+  p->state = 0;
+  for(i = 0 ; i < LZMA_NUM_REPS; i++)
+    p->reps[i] = 0;
+
+  RangeEnc_Init(&p->rc);
+
+
+  for (i = 0; i < kNumStates; i++)
+  {
+    UInt32 j;
+    for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
+    {
+      p->isMatch[i][j] = kProbInitValue;
+      p->isRep0Long[i][j] = kProbInitValue;
+    }
+    p->isRep[i] = kProbInitValue;
+    p->isRepG0[i] = kProbInitValue;
+    p->isRepG1[i] = kProbInitValue;
+    p->isRepG2[i] = kProbInitValue;
+  }
+
+  {
+    UInt32 num = 0x300 << (p->lp + p->lc);
+    for (i = 0; i < num; i++)
+      p->litProbs[i] = kProbInitValue;
+  }
+
+  {
+    for (i = 0; i < kNumLenToPosStates; i++)
+    {
+      CLzmaProb *probs = p->posSlotEncoder[i];
+      UInt32 j;
+      for (j = 0; j < (1 << kNumPosSlotBits); j++)
+        probs[j] = kProbInitValue;
+    }
+  }
+  {
+    for(i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
+      p->posEncoders[i] = kProbInitValue;
+  }
+
+  LenEnc_Init(&p->lenEnc.p);
+  LenEnc_Init(&p->repLenEnc.p);
+
+  for (i = 0; i < (1 << kNumAlignBits); i++)
+    p->posAlignEncoder[i] = kProbInitValue;
+
+  p->longestMatchWasFound = False;
+  p->optimumEndIndex = 0;
+  p->optimumCurrentIndex = 0;
+  p->additionalOffset = 0;
+
+  p->pbMask = (1 << p->pb) - 1;
+  p->lpMask = (1 << p->lp) - 1;
+}
+
+void LzmaEnc_InitPrices(CLzmaEnc *p)
+{
+  if (!p->fastMode)
+  {
+    FillDistancesPrices(p);
+    FillAlignPrices(p);
+  }
+
+  p->lenEnc.tableSize =
+  p->repLenEnc.tableSize =
+      p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
+  LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);
+  LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);
+}
+
+static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  UInt32 i;
+  for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)
+    if (p->dictSize <= ((UInt32)1 << i))
+      break;
+  p->distTableSize = i * 2;
+
+  p->finished = False;
+  p->result = SZ_OK;
+  RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
+  LzmaEnc_Init(p);
+  LzmaEnc_InitPrices(p);
+  p->nowPos64 = 0;
+  return SZ_OK;
+}
+
+static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream,
+    ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  p->inStream = inStream;
+  p->rc.outStream = outStream;
+  return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
+}
+
+SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
+    ISeqInStream *inStream, UInt32 keepWindowSize,
+    ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  p->inStream = inStream;
+  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
+}
+
+static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
+{
+  p->seqBufInStream.funcTable.Read = MyRead;
+  p->seqBufInStream.data = src;
+  p->seqBufInStream.rem = srcLen;
+}
+
+SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
+    UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  LzmaEnc_SetInputBuf(p, src, srcLen);
+  p->inStream = &p->seqBufInStream.funcTable;
+  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
+}
+
+void LzmaEnc_Finish(CLzmaEncHandle pp)
+{
+  #ifdef COMPRESS_MF_MT
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  if (p->mtMode)
+    MatchFinderMt_ReleaseStream(&p->matchFinderMt);
+  #else
+  (void)pp;
+  #endif
+}
+
+typedef struct _CSeqOutStreamBuf
+{
+  ISeqOutStream funcTable;
+  Byte *data;
+  SizeT rem;
+  Bool overflow;
+} CSeqOutStreamBuf;
+
+static size_t MyWrite(void *pp, const void *data, size_t size)
+{
+  CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;
+  if (p->rem < size)
+  {
+    size = p->rem;
+    p->overflow = True;
+  }
+  memcpy(p->data, data, size);
+  p->rem -= size;
+  p->data += size;
+  return size;
+}
+
+
+UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
+{
+  const CLzmaEnc *p = (CLzmaEnc *)pp;
+  return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
+}
+
+const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
+{
+  const CLzmaEnc *p = (CLzmaEnc *)pp;
+  return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
+}
+
+SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
+    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  UInt64 nowPos64;
+  SRes res;
+  CSeqOutStreamBuf outStream;
+
+  outStream.funcTable.Write = MyWrite;
+  outStream.data = dest;
+  outStream.rem = *destLen;
+  outStream.overflow = False;
+
+  p->writeEndMark = False;
+  p->finished = False;
+  p->result = SZ_OK;
+
+  if (reInit)
+    LzmaEnc_Init(p);
+  LzmaEnc_InitPrices(p);
+  nowPos64 = p->nowPos64;
+  RangeEnc_Init(&p->rc);
+  p->rc.outStream = &outStream.funcTable;
+
+  res = LzmaEnc_CodeOneBlock(pp, True, desiredPackSize, *unpackSize);
+
+  *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
+  *destLen -= outStream.rem;
+  if (outStream.overflow)
+    return SZ_ERROR_OUTPUT_EOF;
+
+  return res;
+}
+
+SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
+    ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  SRes res = SZ_OK;
+
+  #ifdef COMPRESS_MF_MT
+  Byte allocaDummy[0x300];
+  int i = 0;
+  for (i = 0; i < 16; i++)
+    allocaDummy[i] = (Byte)i;
+  #endif
+
+  RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig));
+
+  for (;;)
+  {
+    res = LzmaEnc_CodeOneBlock(pp, False, 0, 0);
+    if (res != SZ_OK || p->finished != 0)
+      break;
+    if (progress != 0)
+    {
+      res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
+      if (res != SZ_OK)
+      {
+        res = SZ_ERROR_PROGRESS;
+        break;
+      }
+    }
+  }
+  LzmaEnc_Finish(pp);
+  return res;
+}
+
+SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  int i;
+  UInt32 dictSize = p->dictSize;
+  if (*size < LZMA_PROPS_SIZE)
+    return SZ_ERROR_PARAM;
+  *size = LZMA_PROPS_SIZE;
+  props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
+
+  for (i = 11; i <= 30; i++)
+  {
+    if (dictSize <= ((UInt32)2 << i))
+    {
+      dictSize = (2 << i);
+      break;
+    }
+    if (dictSize <= ((UInt32)3 << i))
+    {
+      dictSize = (3 << i);
+      break;
+    }
+  }
+
+  for (i = 0; i < 4; i++)
+    props[1 + i] = (Byte)(dictSize >> (8 * i));
+  return SZ_OK;
+}
+
+SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  SRes res;
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+
+  CSeqOutStreamBuf outStream;
+
+  LzmaEnc_SetInputBuf(p, src, srcLen);
+
+  outStream.funcTable.Write = MyWrite;
+  outStream.data = dest;
+  outStream.rem = *destLen;
+  outStream.overflow = False;
+
+  p->writeEndMark = writeEndMark;
+  res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable,
+      progress, alloc, allocBig);
+
+  *destLen -= outStream.rem;
+  if (outStream.overflow)
+    return SZ_ERROR_OUTPUT_EOF;
+  return res;
+}
+
+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
+  SRes res;
+  if (p == 0)
+    return SZ_ERROR_MEM;
+
+  res = LzmaEnc_SetProps(p, props);
+  if (res == SZ_OK)
+  {
+    res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
+    if (res == SZ_OK)
+      res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
+          writeEndMark, progress, alloc, allocBig);
+  }
+
+  LzmaEnc_Destroy(p, alloc, allocBig);
+  return res;
+}
diff --git a/lib/crc.c b/lib/crc.c
new file mode 100644 (file)
index 0000000..bc0d8aa
--- /dev/null
+++ b/lib/crc.c
@@ -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 crc32_table [256];
+
+static void
+init_crc32_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 = 0x04c11db7;
+  int i, j;
+
+  for(i = 0; i < 256; i++)
+    {
+      crc32_table[i] = reflect(i, 8) << 24;
+      for (j = 0; j < 8; j++)
+        crc32_table[i] = (crc32_table[i] << 1) ^
+            (crc32_table[i] & (1 << 31) ? polynomial : 0);
+      crc32_table[i] = reflect(crc32_table[i], 32);
+    }
+}
+
+grub_uint32_t
+grub_getcrc32 (grub_uint32_t crc, void *buf, int size)
+{
+  int i;
+  grub_uint8_t *data = buf;
+
+  if (! crc32_table[1])
+    init_crc32_table ();
+
+  crc^= 0xffffffff;
+
+  for (i = 0; i < size; i++)
+    {
+      crc = (crc >> 8) ^ crc32_table[(crc & 0xFF) ^ *data];
+      data++;
+    }
+
+  return crc ^ 0xffffffff;
+}
diff --git a/lib/datetime.c b/lib/datetime.c
new file mode 100644 (file)
index 0000000..7215a6a
--- /dev/null
@@ -0,0 +1,49 @@
+/* datetime.c - Module for common datetime 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/lib/datetime.h>
+
+static char *grub_weekday_names[] =
+{
+  "Sunday",
+  "Monday",
+  "Tuesday",
+  "Wednesday",
+  "Thursday",
+  "Friday",
+  "Saturday",
+};
+
+int
+grub_get_weekday (struct grub_datetime *datetime)
+{
+  int a, y, m;
+
+  a = (14 - datetime->month) / 12;
+  y = datetime->year - a;
+  m = datetime->month + 12 * a - 2;
+
+  return (datetime->day + y + y / 4 - y / 100 + y / 400 + (31 * m / 12)) % 7;
+}
+
+char *
+grub_get_weekday_name (struct grub_datetime *datetime)
+{
+  return grub_weekday_names[grub_get_weekday (datetime)];
+}
diff --git a/lib/efi/datetime.c b/lib/efi/datetime.c
new file mode 100644 (file)
index 0000000..9fa72fd
--- /dev/null
@@ -0,0 +1,79 @@
+/* kern/efi/datetime.c - efi datetime 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/symbol.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/lib/datetime.h>
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+  grub_efi_status_t status;
+  struct grub_efi_time efi_time;
+
+  status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
+                       &efi_time, 0);
+
+  if (status)
+    return grub_error (GRUB_ERR_INVALID_COMMAND,
+                       "can\'t get datetime using efi");
+  else
+    {
+      datetime->year = efi_time.year;
+      datetime->month = efi_time.month;
+      datetime->day = efi_time.day;
+      datetime->hour = efi_time.hour;
+      datetime->minute = efi_time.minute;
+      datetime->second = efi_time.second;
+    }
+
+  return 0;
+}
+
+grub_err_t
+grub_set_datetime (struct grub_datetime *datetime)
+{
+  grub_efi_status_t status;
+  struct grub_efi_time efi_time;
+
+  status = efi_call_2 (grub_efi_system_table->runtime_services->get_time,
+                       &efi_time, 0);
+
+  if (status)
+    return grub_error (GRUB_ERR_INVALID_COMMAND,
+                       "can\'t get datetime using efi");
+
+  efi_time.year = datetime->year;
+  efi_time.month = datetime->month;
+  efi_time.day = datetime->day;
+  efi_time.hour = datetime->hour;
+  efi_time.minute = datetime->minute;
+  efi_time.second = datetime->second;
+
+  status = efi_call_1 (grub_efi_system_table->runtime_services->set_time,
+                       &efi_time);
+
+  if (status)
+    return grub_error (GRUB_ERR_INVALID_COMMAND,
+                       "can\'t set datetime using efi");
+
+  return 0;
+}
diff --git a/lib/envblk.c b/lib/envblk.c
new file mode 100644 (file)
index 0000000..6618d97
--- /dev/null
@@ -0,0 +1,156 @@
+/* envblk.c - Common function for environment block.  */
+/*
+ *  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/types.h>
+#include <grub/misc.h>
+#include <grub/lib/envblk.h>
+
+grub_envblk_t
+grub_envblk_find (char *buf)
+{
+  grub_uint32_t *pd;
+  int len;
+
+  pd = (grub_uint32_t *) buf;
+
+  for (len = GRUB_ENVBLK_MAXLEN - 6; len > 0; len -= 4, pd++)
+    if (*pd == GRUB_ENVBLK_SIGNATURE)
+      {
+        grub_envblk_t p;
+
+        p = (grub_envblk_t) pd;
+        if (p->length <= len)
+          return p;
+      }
+
+  return 0;
+}
+
+int
+grub_envblk_insert (grub_envblk_t envblk, char *name, char *value)
+{
+  char *p, *pend;
+  char *found = 0;
+  int nl;
+
+  nl = grub_strlen (name);
+  p = envblk->data;
+  pend = p + envblk->length;
+
+  while (*p)
+    {
+      if ((! found) && (! grub_memcmp (name, p, nl)) && (p[nl] == '='))
+        found = p + nl + 1;
+
+      p += grub_strlen (p) + 1;
+      if (p >= pend)
+        return 1;
+    }
+
+  if (found)
+    {
+      int len1, len2;
+
+      len1 = grub_strlen (found);
+      len2 = grub_strlen (value);
+      if ((p - envblk->data) + 1 - len1 + len2 > envblk->length)
+        return 1;
+
+      grub_memcpy (found + len2 + 1, found + len1 + 1, (p - found) - len1);
+      grub_strcpy (found, value);
+    }
+  else
+    {
+      int len2 = grub_strlen (value);
+
+      if ((p - envblk->data) + nl + 1 + len2 + 2 > envblk->length)
+        return 1;
+
+      grub_strcpy (p, name);
+      p[nl] = '=';
+      grub_strcpy (p + nl + 1, value);
+      p[nl + 1 + len2 + 1] = 0;
+    }
+
+  return 0;
+}
+
+void
+grub_envblk_delete (grub_envblk_t envblk, char *name)
+{
+  char *p, *pend;
+  char *found = 0;
+  int nl;
+
+  nl = grub_strlen (name);
+  p = envblk->data;
+  pend = p + envblk->length;
+
+  while (*p)
+    {
+      if ((! found) && (! grub_memcmp (name, p, nl)) && (p[nl] == '='))
+        found = p;
+
+      p += grub_strlen (p) + 1;
+      if (p >= pend)
+        return;
+    }
+
+  if (found)
+    {
+      int len;
+
+      len = grub_strlen (found);
+      grub_memcpy (found, found + len + 1, (p - found) - len);
+    }
+}
+
+void
+grub_envblk_iterate (grub_envblk_t envblk,
+                     int hook (char *name, char *value))
+{
+  char *p, *pend;
+
+  p = envblk->data;
+  pend = p + envblk->length;
+
+  while (*p)
+    {
+      char *v;
+      int r;
+
+      v = grub_strchr (p, '=');
+      if (v)
+        {
+          *v = 0;
+          r = hook (p, v + 1);
+          *v = '=';
+        }
+      else
+        r = hook (p, "");
+
+      if (r)
+        break;
+
+      p += grub_strlen (p) + 1;
+      if (p >= pend)
+        break;
+    }
+}
diff --git a/lib/hexdump.c b/lib/hexdump.c
new file mode 100644 (file)
index 0000000..c69cb09
--- /dev/null
@@ -0,0 +1,84 @@
+/* hexdump.c - hexdump 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/misc.h>
+#include <grub/lib/hexdump.h>
+
+void
+hexdump (unsigned long bse, char *buf, int len)
+{
+  int pos;
+  char line[80];
+
+  while (len > 0)
+    {
+      int cnt, i;
+
+      pos = grub_sprintf (line, "%08lx  ", bse);
+      cnt = 16;
+      if (cnt > len)
+       cnt = len;
+
+      for (i = 0; i < cnt; i++)
+       {
+         pos += grub_sprintf (&line[pos], "%02x ", (unsigned char) buf[i]);
+         if ((i & 7) == 7)
+           line[pos++] = ' ';
+       }
+
+      for (; i < 16; i++)
+       {
+         pos += grub_sprintf (&line[pos], "   ");
+         if ((i & 7) == 7)
+           line[pos++] = ' ';
+       }
+
+      line[pos++] = '|';
+
+      for (i = 0; i < cnt; i++)
+       line[pos++] = ((buf[i] >= 32) && (buf[i] < 127)) ? buf[i] : '.';
+
+      line[pos++] = '|';
+
+      line[pos] = 0;
+
+      grub_printf ("%s\n", line);
+
+      /* Print only first and last line if more than 3 lines are identical.  */
+      if (len >= 4 * 16
+         && ! grub_memcmp (buf, buf + 1 * 16, 16)
+         && ! grub_memcmp (buf, buf + 2 * 16, 16)
+         && ! grub_memcmp (buf, buf + 3 * 16, 16))
+       {
+         grub_printf ("*\n");
+         do
+           {
+             bse += 16;
+             buf += 16;
+             len -= 16;
+           }
+         while (len >= 3 * 16 && ! grub_memcmp (buf, buf + 2 * 16, 16));
+       }
+
+      bse += 16;
+      buf += 16;
+      len -= cnt;
+    }
+}
diff --git a/lib/i386/datetime.c b/lib/i386/datetime.c
new file mode 100644 (file)
index 0000000..1e59746
--- /dev/null
@@ -0,0 +1,155 @@
+/* kern/i386/datetime.c - x86 CMOS datetime 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/lib/datetime.h>
+#include <grub/i386/cmos.h>
+
+grub_err_t
+grub_get_datetime (struct grub_datetime *datetime)
+{
+  int is_bcd, is_12hour;
+  grub_uint8_t value, flag;
+
+  flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+
+  is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
+
+  value = grub_cmos_read (GRUB_CMOS_INDEX_YEAR);
+  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);
+  if (is_bcd)
+    value = grub_bcd_to_num (value);
+
+  datetime->month = value;
+
+  value = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH);
+  if (is_bcd)
+    value = grub_bcd_to_num (value);
+
+  datetime->day = value;
+
+  is_12hour = ! (flag & GRUB_CMOS_STATUS_B_24HOUR);
+
+  value = grub_cmos_read (GRUB_CMOS_INDEX_HOUR);
+  if (is_12hour)
+    {
+      is_12hour = (value & 0x80);
+
+      value &= 0x7F;
+      value--;
+    }
+
+  if (is_bcd)
+    value = grub_bcd_to_num (value);
+
+  if (is_12hour)
+    value += 12;
+
+  datetime->hour = value;
+
+  value = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE);
+  if (is_bcd)
+    value = grub_bcd_to_num (value);
+
+  datetime->minute = value;
+
+  value = grub_cmos_read (GRUB_CMOS_INDEX_SECOND);
+  if (is_bcd)
+    value = grub_bcd_to_num (value);
+
+  datetime->second = value;
+
+  return 0;
+}
+
+grub_err_t
+grub_set_datetime (struct grub_datetime *datetime)
+{
+  int is_bcd, is_12hour;
+  grub_uint8_t value, flag;
+
+  flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B);
+
+  is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY);
+
+  value = ((datetime->year >= 2000) ? datetime->year - 2000 :
+           datetime->year - 1900);
+
+  if (is_bcd)
+    value = grub_num_to_bcd (value);
+
+  grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value);
+
+  value = datetime->month;
+
+  if (is_bcd)
+    value = grub_num_to_bcd (value);
+
+  grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value);
+
+  value = datetime->day;
+
+  if (is_bcd)
+    value = grub_num_to_bcd (value);
+
+  grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value);
+
+  value = datetime->hour;
+
+  is_12hour = (! (flag & GRUB_CMOS_STATUS_B_24HOUR));
+
+  if (is_12hour)
+    {
+      value++;
+
+      if (value > 12)
+        value -= 12;
+      else
+        is_12hour = 0;
+    }
+
+  if (is_bcd)
+    value = grub_num_to_bcd (value);
+
+  if (is_12hour)
+    value |= 0x80;
+
+  grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value);
+
+  value = datetime->minute;
+
+  if (is_bcd)
+    value = grub_num_to_bcd (value);
+
+  grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value);
+
+  value = datetime->second;
+
+  if (is_bcd)
+    value = grub_num_to_bcd (value);
+
+  grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value);
+
+  return 0;
+}
diff --git a/loader/aout.c b/loader/aout.c
new file mode 100644 (file)
index 0000000..58b3992
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *  Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ *  This program 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.
+ *
+ *  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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/aout.h>
+
+int
+grub_aout_get_type (union grub_aout_header *header)
+{
+  int magic;
+
+  magic = AOUT_GETMAGIC (header->aout32);
+  if ((magic == AOUT32_OMAGIC) || (magic == AOUT32_NMAGIC) ||
+      (magic == AOUT32_ZMAGIC) || (magic == AOUT32_QMAGIC))
+    return AOUT_TYPE_AOUT32;
+  else if ((magic == AOUT64_OMAGIC) || (magic == AOUT64_NMAGIC) ||
+          (magic == AOUT64_ZMAGIC))
+    return AOUT_TYPE_AOUT64;
+  else
+    return AOUT_TYPE_NONE;
+}
+
+grub_err_t
+grub_aout_load (grub_file_t file, int offset,
+                grub_addr_t load_addr,
+               int load_size,
+                grub_addr_t bss_end_addr)
+{
+  if ((grub_file_seek (file, offset)) == (grub_off_t) - 1)
+    return grub_errno;
+
+  if (!load_size)
+    load_size = file->size - offset;
+
+  grub_file_read (file, (char *) load_addr, load_size);
+
+  if (grub_errno)
+    return grub_errno;
+
+  if (bss_end_addr)
+    grub_memset ((char *) load_addr + load_size, 0,
+                 bss_end_addr - load_addr - load_size);
+
+  return GRUB_ERR_NONE;
+}
diff --git a/loader/efi/appleloader.c b/loader/efi/appleloader.c
new file mode 100644 (file)
index 0000000..910a13d
--- /dev/null
@@ -0,0 +1,208 @@
+/* appleloader.c - apple legacy boot loader.  */
+/*
+ *  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/loader.h>
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+
+static grub_dl_t my_mod;
+
+static grub_efi_handle_t image_handle;
+static grub_efi_char16_t *cmdline;
+
+static grub_err_t
+grub_appleloader_unload (void)
+{
+  grub_efi_boot_services_t *b;
+
+  b = grub_efi_system_table->boot_services;
+  efi_call_1 (b->unload_image, image_handle);
+
+  grub_free (cmdline);
+  cmdline = 0;
+
+  grub_dl_unref (my_mod);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_appleloader_boot (void)
+{
+  grub_efi_boot_services_t *b;
+
+  b = grub_efi_system_table->boot_services;
+  efi_call_3 (b->start_image, image_handle, 0, 0);
+
+  grub_appleloader_unload ();
+
+  return grub_errno;
+}
+
+/* early 2006 Core Duo / Core Solo models  */
+static grub_uint8_t devpath_1[] =
+{
+  0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0xFF, 0xFF, 0xF9, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+  0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+  0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+
+/* mid-2006 Mac Pro (and probably other Core 2 models)  */
+static grub_uint8_t devpath_2[] =
+{
+  0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0xFF, 0xFF, 0xF7, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+  0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+  0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+
+/* mid-2007 MBP ("Santa Rosa" based models)  */
+static grub_uint8_t devpath_3[] =
+{
+  0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0xFF, 0xFF, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+  0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+  0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+
+/* early-2008 MBA  */
+static grub_uint8_t devpath_4[] =
+{
+  0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0xFF, 0xFF, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+  0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+  0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+
+struct devdata
+{
+  char *model;
+  grub_efi_device_path_t *devpath;
+};
+
+struct devdata devs[] =
+{
+  {"Core Duo/Solo", (grub_efi_device_path_t *) devpath_1},
+  {"Mac Pro", (grub_efi_device_path_t *) devpath_2},
+  {"MBP", (grub_efi_device_path_t *) devpath_3},
+  {"MBA", (grub_efi_device_path_t *) devpath_4},
+  {NULL, NULL},
+};
+
+static grub_err_t
+grub_cmd_appleloader (struct grub_arg_list *state __attribute__ ((unused)),
+                      int argc, char *argv[])
+{
+  grub_efi_boot_services_t *b;
+  grub_efi_loaded_image_t *loaded_image;
+  struct devdata *pdev;
+
+  grub_dl_ref (my_mod);
+
+  /* Initialize some global variables.  */
+  image_handle = 0;
+
+  b = grub_efi_system_table->boot_services;
+
+  for (pdev = devs ; pdev->devpath ; pdev++)
+    if (efi_call_6 (b->load_image, 0, grub_efi_image_handle, pdev->devpath,
+                    NULL, 0, &image_handle) == GRUB_EFI_SUCCESS)
+      break;
+
+  if (! pdev->devpath)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "can't find model");
+      goto fail;
+    }
+
+  grub_printf ("Model : %s\n", pdev->model);
+
+  loaded_image = grub_efi_get_loaded_image (image_handle);
+  if (! loaded_image)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
+      goto fail;
+    }
+
+  if (argc > 0)
+    {
+      int i, len;
+      grub_efi_char16_t *p16;
+
+      for (i = 0, len = 0; i < argc; i++)
+        len += grub_strlen (argv[i]) + 1;
+
+      len *= sizeof (grub_efi_char16_t);
+      cmdline = p16 = grub_malloc (len);
+      if (! cmdline)
+        goto fail;
+
+      for (i = 0; i < argc; i++)
+        {
+          char *p8;
+
+          p8 = argv[i];
+          while (*p8)
+            *(p16++) = *(p8++);
+
+          *(p16++) = ' ';
+        }
+      *(--p16) = 0;
+
+      loaded_image->load_options = cmdline;
+      loaded_image->load_options_size = len;
+    }
+
+  grub_loader_set (grub_appleloader_boot, grub_appleloader_unload, 0);
+
+  return 0;
+
+ fail:
+
+  grub_dl_unref (my_mod);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(appleloader)
+{
+  grub_register_command ("appleloader", grub_cmd_appleloader,
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "appleloader [OPTS]",
+                        "Boot legacy system.", 0);
+
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI(appleloader)
+{
+  grub_unregister_command ("appleloader");
+}
diff --git a/loader/efi/chainloader.c b/loader/efi/chainloader.c
new file mode 100644 (file)
index 0000000..1ca5f1d
--- /dev/null
@@ -0,0 +1,347 @@
+/* chainloader.c - boot another boot loader */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2004,2006,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/>.
+ */
+
+/* TODO: support load options.  */
+
+#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/mm.h>
+#include <grub/types.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/disk.h>
+#include <grub/efi/chainloader.h>
+
+static grub_dl_t my_mod;
+
+static grub_efi_physical_address_t address;
+static grub_efi_uintn_t pages;
+static grub_efi_device_path_t *file_path;
+static grub_efi_handle_t image_handle;
+static grub_efi_char16_t *cmdline;
+
+static grub_err_t
+grub_chainloader_unload (void)
+{
+  grub_efi_boot_services_t *b;
+  
+  b = grub_efi_system_table->boot_services;
+  efi_call_1 (b->unload_image, image_handle);
+  efi_call_2 (b->free_pages, address, pages);
+
+  grub_free (file_path);
+  grub_free (cmdline);
+  cmdline = 0;
+  
+  grub_dl_unref (my_mod);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+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;
+  
+  b = grub_efi_system_table->boot_services;
+  status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data);
+  if (status != GRUB_EFI_SUCCESS)
+    {
+      if (exit_data)
+       {
+         char *buf;
+         
+         buf = grub_malloc (exit_data_size * 4 + 1);
+         if (buf)
+           {
+             *grub_utf16_to_utf8 ((grub_uint8_t *) buf,
+                                  exit_data, exit_data_size) = 0;
+             
+             grub_error (GRUB_ERR_BAD_OS, buf);
+             grub_free (buf);
+           }
+         else
+           grub_error (GRUB_ERR_BAD_OS, "unknown error");
+       }
+    }
+
+  if (exit_data)
+    efi_call_1 (b->free_pool, exit_data);
+
+  grub_chainloader_unload ();
+  
+  return grub_errno;
+}
+
+static void
+copy_file_path (grub_efi_file_path_device_path_t *fp,
+               const char *str, grub_efi_uint16_t len)
+{
+  grub_efi_char16_t *p;
+  grub_efi_uint16_t size;
+  
+  fp->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE;
+  fp->header.subtype = GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE;
+  size = len * sizeof (grub_efi_char16_t) + sizeof (*fp);
+  fp->header.length[0] = (grub_efi_uint8_t) (size & 0xff);
+  fp->header.length[1] = (grub_efi_uint8_t) (size >> 8);
+  for (p = fp->path_name; len > 0; len--, p++, str++)
+    {
+      /* FIXME: this assumes that the path is in ASCII.  */
+      *p = (grub_efi_char16_t) (*str == '/' ? '\\' : *str);
+    }
+}
+
+static grub_efi_device_path_t *
+make_file_path (grub_efi_device_path_t *dp, const char *filename)
+{
+  char *dir_start;
+  char *dir_end;
+  grub_size_t size;
+  grub_efi_device_path_t *d;
+
+  dir_start = grub_strchr (filename, ')');
+  if (! dir_start)
+    dir_start = (char *) filename;
+  else
+    dir_start++;
+
+  dir_end = grub_strrchr (dir_start, '/');
+  if (! dir_end)
+    {
+      grub_error (GRUB_ERR_BAD_FILENAME, "invalid EFI file path");
+      return 0;
+    }
+  
+  size = 0;
+  d = dp;
+  while (1)
+    {
+      size += GRUB_EFI_DEVICE_PATH_LENGTH (d);
+      if ((GRUB_EFI_END_ENTIRE_DEVICE_PATH (d)))
+       break;
+      d = GRUB_EFI_NEXT_DEVICE_PATH (d);
+    }
+  
+  file_path = grub_malloc (size
+                          + ((grub_strlen (dir_start) + 1)
+                             * sizeof (grub_efi_char16_t))
+                          + sizeof (grub_efi_file_path_device_path_t) * 2);
+  if (! file_path)
+    return 0;
+
+  grub_memcpy (file_path, dp, size);
+  
+  /* Fill the file path for the directory.  */
+  d = (grub_efi_device_path_t *) ((char *) file_path
+                                 + ((char *) d - (char *) dp));
+  grub_efi_print_device_path (d);
+  copy_file_path ((grub_efi_file_path_device_path_t *) d,
+                 dir_start, dir_end - dir_start);
+
+  /* Fill the file path for the file.  */
+  d = GRUB_EFI_NEXT_DEVICE_PATH (d);
+  copy_file_path ((grub_efi_file_path_device_path_t *) d,
+                 dir_end + 1, grub_strlen (dir_end + 1));
+
+  /* Fill the end of device path nodes.  */
+  d = GRUB_EFI_NEXT_DEVICE_PATH (d);
+  d->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+  d->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+  d->length[0] = sizeof (*d);
+  d->length[1] = 0;
+
+  return file_path;
+}
+
+void
+grub_rescue_cmd_chainloader (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  grub_ssize_t size;
+  grub_efi_status_t status;
+  grub_efi_boot_services_t *b;
+  grub_efi_handle_t dev_handle = 0;
+  grub_device_t dev = 0;
+  grub_efi_device_path_t *dp = 0;
+  grub_efi_loaded_image_t *loaded_image;
+  char *filename;
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
+      return;
+    }
+  filename = argv[0];
+  
+  grub_dl_ref (my_mod);
+
+  /* Initialize some global variables.  */
+  address = 0;
+  image_handle = 0;
+  file_path = 0;
+  
+  b = grub_efi_system_table->boot_services;
+
+  file = grub_file_open (filename);
+  if (! file)
+    goto fail;
+
+  /* Get the root device's device path.  */
+  dev = grub_device_open (0);
+  if (! dev)
+    goto fail;
+
+  if (dev->disk)
+    {
+      dev_handle = grub_efidisk_get_device_handle (dev->disk);
+      if (dev_handle)
+       dp = grub_efi_get_device_path (dev_handle);
+    }
+  
+  if (! dev->disk || ! dev_handle || ! dp)
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, "not a valid root device");
+      goto fail;
+    }
+
+  file_path = make_file_path (dp, filename);
+  if (! file_path)
+    goto fail;
+
+  grub_printf ("file path: ");
+  grub_efi_print_device_path (file_path);
+  
+  size = grub_file_size (file);
+  pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12);
+  
+  status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES,
+                             GRUB_EFI_LOADER_CODE,
+                             pages, &address);
+  if (status != GRUB_EFI_SUCCESS)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate %u pages", pages);
+      goto fail;
+    }
+
+  if (grub_file_read (file, (void *) ((grub_addr_t) address), size) != size)
+    {
+      if (grub_errno == GRUB_ERR_NONE)
+       grub_error (GRUB_ERR_BAD_OS, "too small");
+
+      goto fail;
+    }
+
+  status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
+                         (void *) ((grub_addr_t) address), size,
+                         &image_handle);
+  if (status != GRUB_EFI_SUCCESS)
+    {
+      if (status == GRUB_EFI_OUT_OF_RESOURCES)
+       grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
+      else
+       grub_error (GRUB_ERR_BAD_OS, "cannot load image");
+      
+      goto fail;
+    }
+
+  /* LoadImage does not set a device handler when the image is
+     loaded from memory, so it is necessary to set it explicitly here.
+     This is a mess.  */
+  loaded_image = grub_efi_get_loaded_image (image_handle);
+  if (! loaded_image)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
+      goto fail;
+    }
+  loaded_image->device_handle = dev_handle;
+  
+  grub_file_close (file);
+
+  if (argc > 1)
+    {
+      int i, len;
+      grub_efi_char16_t *p16;
+
+      for (i = 1, len = 0; i < argc; i++)
+        len += grub_strlen (argv[i]) + 1;
+
+      len *= sizeof (grub_efi_char16_t);
+      cmdline = p16 = grub_malloc (len);
+      if (! cmdline)
+        goto fail;
+
+      for (i = 1; i < argc; i++)
+        {
+          char *p8;
+
+          p8 = argv[i];
+          while (*p8)
+            *(p16++) = *(p8++);
+
+          *(p16++) = ' ';
+        }
+      *(--p16) = 0;
+
+      loaded_image->load_options = cmdline;
+      loaded_image->load_options_size = len;
+    }
+
+  grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
+  return;
+  
+ fail:
+
+  if (dev)
+    grub_device_close (dev);
+  
+  if (file)
+    grub_file_close (file);
+
+  if (file_path)
+    grub_free (file_path);
+  
+  if (address)
+    efi_call_2 (b->free_pages, address, pages);
+  
+  grub_dl_unref (my_mod);
+}
+
+static const char loader_name[] = "chainloader";
+
+GRUB_MOD_INIT(chainloader)
+{
+  grub_rescue_register_command (loader_name,
+                               grub_rescue_cmd_chainloader,
+                               "load another boot loader");
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI(chainloader)
+{
+  grub_rescue_unregister_command (loader_name);
+}
diff --git a/loader/efi/chainloader_normal.c b/loader/efi/chainloader_normal.c
new file mode 100644 (file)
index 0000000..455669e
--- /dev/null
@@ -0,0 +1,48 @@
+/* chainloader_normal.c - boot another boot loader */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,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/>.
+ */
+
+#include <grub/efi/chainloader.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+
+static grub_err_t
+chainloader_command (struct grub_arg_list *state __attribute__ ((unused)),
+                    int argc, char **args)
+{
+  if (argc == 0)
+    grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
+  else
+    grub_rescue_cmd_chainloader (argc, args);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(chainloader_normal)
+{
+  (void) mod; /* To stop warning.  */
+  grub_register_command ("chainloader", chainloader_command,
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "chainloader FILE",
+                        "Prepare to boot another boot loader.", 0);
+}
+
+GRUB_MOD_FINI(chainloader_normal)
+{
+  grub_unregister_command ("chainloader");
+}
diff --git a/loader/i386/bsd.c b/loader/i386/bsd.c
new file mode 100644 (file)
index 0000000..25d0f59
--- /dev/null
@@ -0,0 +1,773 @@
+/*
+ *  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/loader.h>
+#include <grub/cpu/loader.h>
+#include <grub/cpu/bsd.h>
+#include <grub/machine/init.h>
+#include <grub/machine/memory.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/elfload.h>
+#include <grub/env.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+#include <grub/aout.h>
+
+#define ALIGN_DWORD(a) ALIGN_UP (a, 4)
+#define ALIGN_PAGE(a)  ALIGN_UP (a, 4096)
+
+#define MOD_BUF_ALLOC_UNIT     4096
+
+static int kernel_type;
+static grub_dl_t my_mod;
+static grub_addr_t entry, kern_start, kern_end;
+static grub_uint32_t bootflags;
+static char *mod_buf;
+static grub_uint32_t mod_buf_len, mod_buf_max;
+static int is_elf_kernel;
+
+static const char freebsd_opts[] = "DhaCcdgmnpqrsv";
+static const grub_uint32_t freebsd_flags[] =
+{
+  FREEBSD_RB_DUAL, FREEBSD_RB_SERIAL, FREEBSD_RB_ASKNAME,
+  FREEBSD_RB_CDROM, FREEBSD_RB_CONFIG, FREEBSD_RB_KDB,
+  FREEBSD_RB_GDB, FREEBSD_RB_MUTE, FREEBSD_RB_NOINTR,
+  FREEBSD_RB_PAUSE, FREEBSD_RB_QUIET, FREEBSD_RB_DFLTROOT,
+  FREEBSD_RB_SINGLE, FREEBSD_RB_VERBOSE
+};
+
+static const char openbsd_opts[] = "abcsd";
+static const grub_uint32_t openbsd_flags[] =
+{
+  OPENBSD_RB_ASKNAME, OPENBSD_RB_HALT, OPENBSD_RB_CONFIG,
+  OPENBSD_RB_SINGLE, OPENBSD_RB_KDB
+};
+
+static const char netbsd_opts[] = "abcdmqsvxz";
+static const grub_uint32_t netbsd_flags[] =
+{
+  NETBSD_RB_ASKNAME, NETBSD_RB_HALT, NETBSD_RB_USERCONFIG,
+  NETBSD_RB_KDB, NETBSD_RB_MINIROOT, NETBSD_AB_QUIET,
+  NETBSD_RB_SINGLE, NETBSD_AB_VERBOSE, NETBSD_AB_DEBUG,
+  NETBSD_AB_SILENT
+};
+
+static void
+grub_bsd_get_device (grub_uint32_t * biosdev,
+                    grub_uint32_t * unit,
+                    grub_uint32_t * slice, grub_uint32_t * part)
+{
+  char *p;
+
+  *biosdev = *unit = *slice = *part = 0;
+  p = grub_env_get ("root");
+  if ((p) && ((p[0] == 'h') || (p[0] == 'f')) && (p[1] == 'd') &&
+      (p[2] >= '0') && (p[2] <= '9'))
+    {
+      if (p[0] == 'h')
+       *biosdev = 0x80;
+
+      *unit = grub_strtoul (p + 2, &p, 0);
+      *biosdev += *unit;
+
+      if ((p) && (p[0] == ','))
+       {
+         if ((p[1] >= '0') && (p[1] <= '9'))
+           {
+             *slice = grub_strtoul (p + 1, &p, 0);
+
+             if ((p) && (p[0] == ','))
+               p++;
+           }
+
+         if ((p[0] >= 'a') && (p[0] <= 'z'))
+           *part = p[0] - 'a';
+       }
+    }
+}
+
+static grub_err_t
+grub_freebsd_add_meta (grub_uint32_t type, void *data, grub_uint32_t len)
+{
+  if (mod_buf_max < mod_buf_len + len + 8)
+    {
+      char *new_buf;
+
+      do
+       {
+         mod_buf_max += MOD_BUF_ALLOC_UNIT;
+       }
+      while (mod_buf_max < mod_buf_len + len + 8);
+
+      new_buf = grub_malloc (mod_buf_max);
+      if (!new_buf)
+       return grub_errno;
+
+      grub_memcpy (new_buf, mod_buf, mod_buf_len);
+      grub_free (mod_buf);
+
+      mod_buf = new_buf;
+    }
+
+  *((grub_uint32_t *) (mod_buf + mod_buf_len)) = type;
+  *((grub_uint32_t *) (mod_buf + mod_buf_len + 4)) = len;
+  mod_buf_len += 8;
+
+  if (len)
+    grub_memcpy (mod_buf + mod_buf_len, data, len);
+
+  mod_buf_len = ALIGN_DWORD (mod_buf_len + len);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_freebsd_add_meta_module (int is_kern, int argc, char **argv,
+                             grub_addr_t addr, grub_uint32_t size)
+{
+  char *name, *type;
+
+  name = grub_strrchr (argv[0], '/');
+  if (name)
+    name++;
+  else
+    name = argv[0];
+
+  if (grub_freebsd_add_meta (FREEBSD_MODINFO_NAME, name,
+                            grub_strlen (name) + 1))
+    return grub_errno;
+
+  argc--;
+  argv++;
+
+  if ((argc) && (!grub_memcmp (argv[0], "type=", 5)))
+    {
+      type = &argv[0][5];
+      argc--;
+      argv++;
+    }
+  else
+    type = (is_kern) ? FREEBSD_MODTYPE_KERNEL : FREEBSD_MODTYPE_RAW;
+
+  if ((grub_freebsd_add_meta (FREEBSD_MODINFO_TYPE, type,
+                             grub_strlen (type) + 1)) ||
+      (grub_freebsd_add_meta (FREEBSD_MODINFO_ADDR, &addr, sizeof (addr))) ||
+      (grub_freebsd_add_meta (FREEBSD_MODINFO_SIZE, &size, sizeof (size))))
+    return grub_errno;
+
+  if (argc)
+    {
+      int i, n;
+
+      n = 0;
+      for (i = 0; i < argc; i++)
+       {
+         n += grub_strlen (argv[i]) + 1;
+       }
+
+      if (n)
+       {
+         char cmdline[n], *p;
+
+         p = cmdline;
+         for (i = 0; i < argc; i++)
+           {
+             grub_strcpy (p, argv[i]);
+             p += grub_strlen (argv[i]);
+             *(p++) = ' ';
+           }
+         *p = 0;
+
+         if (grub_freebsd_add_meta (FREEBSD_MODINFO_ARGS, cmdline, n))
+           return grub_errno;
+       }
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_freebsd_list_modules (void)
+{
+  grub_uint32_t pos = 0;
+
+  grub_printf ("  %-18s  %-18s%14s%14s\n", "name", "type", "addr", "size");
+  while (pos < mod_buf_len)
+    {
+      grub_uint32_t type, size;
+
+      type = *((grub_uint32_t *) (mod_buf + pos));
+      size = *((grub_uint32_t *) (mod_buf + pos + 4));
+      pos += 8;
+      switch (type)
+       {
+       case FREEBSD_MODINFO_NAME:
+       case FREEBSD_MODINFO_TYPE:
+         grub_printf ("  %-18s", mod_buf + pos);
+         break;
+       case FREEBSD_MODINFO_ADDR:
+         {
+           grub_addr_t addr;
+
+           addr = *((grub_addr_t *) (mod_buf + pos));
+           grub_printf ("    0x%08x", addr);
+           break;
+         }
+       case FREEBSD_MODINFO_SIZE:
+         {
+           grub_uint32_t len;
+
+           len = *((grub_uint32_t *) (mod_buf + pos));
+           grub_printf ("    0x%08x\n", len);
+         }
+       }
+
+      pos = ALIGN_DWORD (pos + size);
+    }
+}
+
+static grub_err_t
+grub_freebsd_boot (void)
+{
+  struct grub_freebsd_bootinfo bi;
+  char *p;
+  grub_uint32_t bootdev, biosdev, unit, slice, part;
+
+  auto int iterate_env (struct grub_env_var *var);
+  int iterate_env (struct grub_env_var *var)
+  {
+    if ((!grub_memcmp (var->name, "FreeBSD.", 8)) && (var->name[8]))
+      {
+       grub_strcpy (p, &var->name[8]);
+       p += grub_strlen (p);
+       *(p++) = '=';
+       grub_strcpy (p, var->value);
+       p += grub_strlen (p) + 1;
+      }
+
+    return 0;
+  }
+
+  grub_memset (&bi, 0, sizeof (bi));
+  bi.bi_version = FREEBSD_BOOTINFO_VERSION;
+  bi.bi_size = sizeof (bi);
+
+  grub_bsd_get_device (&biosdev, &unit, &slice, &part);
+  bootdev = (FREEBSD_B_DEVMAGIC + ((slice + 1) << FREEBSD_B_SLICESHIFT) +
+            (unit << FREEBSD_B_UNITSHIFT) + (part << FREEBSD_B_PARTSHIFT));
+
+  bi.bi_bios_dev = biosdev;
+
+  p = (char *) kern_end;
+
+  grub_env_iterate (iterate_env);
+
+  if (p != (char *) kern_end)
+    {
+      *(p++) = 0;
+
+      bi.bi_envp = kern_end;
+      kern_end = ALIGN_PAGE ((grub_uint32_t) p);
+    }
+
+  if (is_elf_kernel)
+    {
+      if (grub_freebsd_add_meta (FREEBSD_MODINFO_END, 0, 0))
+       return grub_errno;
+
+      grub_memcpy ((char *) kern_end, mod_buf, mod_buf_len);
+      bi.bi_modulep = kern_end;
+
+      kern_end = ALIGN_PAGE (kern_end + mod_buf_len);
+    }
+
+  bi.bi_kernend = kern_end;
+
+  grub_unix_real_boot (entry, bootflags | FREEBSD_RB_BOOTINFO, bootdev,
+                      0, 0, 0, &bi, bi.bi_modulep, kern_end);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_openbsd_boot (void)
+{
+  char *buf = (char *) GRUB_BSD_TEMP_BUFFER;
+  struct grub_machine_mmap_entry mmap;
+  struct grub_openbsd_bios_mmap *pm;
+  struct grub_openbsd_bootargs *pa;
+  grub_uint32_t bootdev, biosdev, unit, slice, part, cont;
+
+  pa = (struct grub_openbsd_bootargs *) buf;
+
+  pa->ba_type = OPENBSD_BOOTARG_MMAP;
+  pm = (struct grub_openbsd_bios_mmap *) (pa + 1);
+  cont = grub_get_mmap_entry (&mmap, 0);
+  if (mmap.size)
+    do
+      {
+       pm->addr = mmap.addr;
+       pm->len = mmap.len;
+       pm->type = mmap.type;
+       pm++;
+
+       if (!cont)
+         break;
+
+       cont = grub_get_mmap_entry (&mmap, cont);
+      }
+    while (mmap.size);
+
+  pa->ba_size = (char *) pm - (char *) pa;
+  pa->ba_next = (struct grub_openbsd_bootargs *) pm;
+  pa = pa->ba_next;
+  pa->ba_type = OPENBSD_BOOTARG_END;
+  pa++;
+
+  grub_bsd_get_device (&biosdev, &unit, &slice, &part);
+  bootdev = (OPENBSD_B_DEVMAGIC + (unit << OPENBSD_B_UNITSHIFT) +
+            (part << OPENBSD_B_PARTSHIFT));
+
+  grub_unix_real_boot (entry, bootflags, bootdev, OPENBSD_BOOTARG_APIVER,
+                      0, grub_upper_mem >> 10, grub_lower_mem >> 10,
+                      (char *) pa - buf, buf);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_netbsd_boot (void)
+{
+  struct grub_netbsd_btinfo_rootdevice *rootdev;
+  struct grub_netbsd_bootinfo *bootinfo;
+  grub_uint32_t biosdev, unit, slice, part;
+
+  grub_bsd_get_device (&biosdev, &unit, &slice, &part);
+
+  rootdev = (struct grub_netbsd_btinfo_rootdevice *) GRUB_BSD_TEMP_BUFFER;
+
+  rootdev->common.len = sizeof (struct grub_netbsd_btinfo_rootdevice);
+  rootdev->common.type = NETBSD_BTINFO_ROOTDEVICE;
+  grub_sprintf (rootdev->devname, "%cd%d%c", (biosdev & 0x80) ? 'w' : 'f',
+               unit, 'a' + part);
+
+  bootinfo = (struct grub_netbsd_bootinfo *) (rootdev + 1);
+  bootinfo->bi_count = 1;
+  bootinfo->bi_data[0] = rootdev;
+
+  grub_unix_real_boot (entry, bootflags, 0, bootinfo,
+                      0, grub_upper_mem >> 10, grub_lower_mem >> 10);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_unload (void)
+{
+  if (mod_buf)
+    {
+      grub_free (mod_buf);
+      mod_buf = 0;
+      mod_buf_max = 0;
+    }
+
+  kernel_type = KERNEL_TYPE_NONE;
+  grub_dl_unref (my_mod);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_load_aout (grub_file_t file)
+{
+  grub_addr_t load_addr, bss_end_addr;
+  int ofs, align_page;
+  union grub_aout_header ah;
+
+  if ((grub_file_seek (file, 0)) == (grub_off_t) - 1)
+    return grub_errno;
+
+  if (grub_file_read (file, (char *) &ah, sizeof (ah)) != sizeof (ah))
+    return grub_error (GRUB_ERR_READ_ERROR, "cannot read the a.out header");
+
+  if (grub_aout_get_type (&ah) != AOUT_TYPE_AOUT32)
+    return grub_error (GRUB_ERR_BAD_OS, "invalid a.out header");
+
+  entry = ah.aout32.a_entry & 0xFFFFFF;
+
+  if (AOUT_GETMAGIC (ah.aout32) == AOUT32_ZMAGIC)
+    {
+      load_addr = entry;
+      ofs = 0x1000;
+      align_page = 0;
+    }
+  else
+    {
+      load_addr = entry & 0xF00000;
+      ofs = sizeof (struct grub_aout32_header);
+      align_page = 1;
+    }
+
+  if (load_addr < 0x100000)
+    return grub_error (GRUB_ERR_BAD_OS, "load address below 1M");
+
+  kern_start = load_addr;
+  kern_end = load_addr + ah.aout32.a_text + ah.aout32.a_data;
+  if (align_page)
+    kern_end = ALIGN_PAGE (kern_end);
+
+  if (ah.aout32.a_bss)
+    {
+      kern_end += ah.aout32.a_bss;
+      if (align_page)
+       kern_end = ALIGN_PAGE (kern_end);
+
+      bss_end_addr = kern_end;
+    }
+  else
+    bss_end_addr = 0;
+
+  return grub_aout_load (file, ofs, load_addr,
+                        ah.aout32.a_text + ah.aout32.a_data, bss_end_addr);
+}
+
+static grub_err_t
+grub_bsd_elf32_hook (Elf32_Phdr * phdr, grub_addr_t * addr)
+{
+  Elf32_Addr paddr;
+
+  phdr->p_paddr &= 0xFFFFFF;
+  paddr = phdr->p_paddr;
+
+  if ((paddr < grub_os_area_addr)
+      || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size))
+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "Address 0x%x is out of range",
+                      paddr);
+
+  if ((!kern_start) || (paddr < kern_start))
+    kern_start = paddr;
+
+  if (paddr + phdr->p_memsz > kern_end)
+    kern_end = paddr + phdr->p_memsz;
+
+  *addr = paddr;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_bsd_load_elf (grub_elf_t elf)
+{
+  kern_start = kern_end = 0;
+
+  if (grub_elf_is_elf32 (elf))
+    {
+      entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF;
+      return grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0);
+    }
+  else
+    return grub_error (GRUB_ERR_BAD_OS, "invalid elf");
+}
+
+static grub_err_t
+grub_bsd_load (int argc, char *argv[])
+{
+  grub_file_t file;
+  grub_elf_t elf;
+
+  grub_dl_ref (my_mod);
+
+  grub_loader_unset ();
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if (!file)
+    goto fail;
+
+  elf = grub_elf_file (file);
+  if (elf)
+    {
+      is_elf_kernel = 1;
+      grub_bsd_load_elf (elf);
+      grub_elf_close (elf);
+    }
+  else
+    {
+      is_elf_kernel = 0;
+      grub_errno = 0;
+      grub_bsd_load_aout (file);
+      grub_file_close (file);
+    }
+
+fail:
+
+  if (grub_errno != GRUB_ERR_NONE)
+    grub_dl_unref (my_mod);
+
+  return grub_errno;
+}
+
+static grub_uint32_t
+grub_bsd_parse_flags (char *str, const char *opts,
+                     const grub_uint32_t * flags)
+{
+  grub_uint32_t result = 0;
+
+  while (*str)
+    {
+      const char *po;
+      const grub_uint32_t *pf;
+
+      po = opts;
+      pf = flags;
+      while (*po)
+       {
+         if (*str == *po)
+           {
+             result |= *pf;
+             break;
+           }
+         po++;
+         pf++;
+       }
+      str++;
+    }
+
+  return result;
+}
+
+void
+grub_rescue_cmd_freebsd (int argc, char *argv[])
+{
+  kernel_type = KERNEL_TYPE_FREEBSD;
+  bootflags = ((argc <= 1) ? 0 :
+              grub_bsd_parse_flags (argv[1], freebsd_opts, freebsd_flags));
+
+  if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
+    {
+      kern_end = ALIGN_PAGE (kern_end);
+      if ((is_elf_kernel) &&
+         (grub_freebsd_add_meta_module (1, argc, argv, kern_start,
+                                        kern_end - kern_start)))
+       return;
+      grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 1);
+    }
+}
+
+void
+grub_rescue_cmd_openbsd (int argc, char *argv[])
+{
+  kernel_type = KERNEL_TYPE_OPENBSD;
+  bootflags = ((argc <= 1) ? 0 :
+              grub_bsd_parse_flags (argv[1], openbsd_opts, openbsd_flags));
+
+  if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
+    grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 1);
+}
+
+void
+grub_rescue_cmd_netbsd (int argc, char *argv[])
+{
+  kernel_type = KERNEL_TYPE_NETBSD;
+  bootflags = ((argc <= 1) ? 0 :
+              grub_bsd_parse_flags (argv[1], netbsd_opts, netbsd_flags));
+
+  if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
+    grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 1);
+}
+
+void
+grub_rescue_cmd_freebsd_loadenv (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  char *buf = 0, *curr, *next;
+  int len;
+
+  if (kernel_type != KERNEL_TYPE_FREEBSD)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "only freebsd support environment");
+      return;
+    }
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no filename");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if ((!file) || (!file->size))
+    goto fail;
+
+  len = file->size;
+  buf = grub_malloc (len + 1);
+  if (!buf)
+    goto fail;
+
+  if (grub_file_read (file, buf, len) != len)
+    goto fail;
+
+  buf[len] = 0;
+
+  next = buf;
+  while (next)
+    {
+      char *p;
+
+      curr = next;
+      next = grub_strchr (curr, '\n');
+      if (next)
+       {
+
+         p = next - 1;
+         while (p > curr)
+           {
+             if ((*p != '\r') && (*p != ' ') && (*p != '\t'))
+               break;
+             p--;
+           }
+
+         if ((p > curr) && (*p == '"'))
+           p--;
+
+         *(p + 1) = 0;
+         next++;
+       }
+
+      if (*curr == '#')
+       continue;
+
+      p = grub_strchr (curr, '=');
+      if (!p)
+       continue;
+
+      *(p++) = 0;
+
+      if (*curr)
+       {
+         char name[grub_strlen (curr) + 8 + 1];
+
+         if (*p == '"')
+           p++;
+
+         grub_sprintf (name, "FreeBSD.%s", curr);
+         if (grub_env_set (name, p))
+           goto fail;
+       }
+    }
+
+fail:
+  grub_free (buf);
+
+  if (file)
+    grub_file_close (file);
+}
+
+void
+grub_rescue_cmd_freebsd_module (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+
+  if (kernel_type != KERNEL_TYPE_FREEBSD)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "only freebsd support module");
+      return;
+    }
+
+  if (!is_elf_kernel)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "only elf kernel support module");
+      return;
+    }
+
+  /* List the current modules if no parameter.  */
+  if (!argc)
+    {
+      grub_freebsd_list_modules ();
+      return;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if ((!file) || (!file->size))
+    goto fail;
+
+  if (kern_end + file->size > grub_os_area_addr + grub_os_area_size)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "Not enough memory for the module");
+      goto fail;
+    }
+
+  grub_file_read (file, (char *) kern_end, file->size);
+  if ((!grub_errno) &&
+      (!grub_freebsd_add_meta_module (0, argc, argv, kern_end, file->size)))
+    kern_end = ALIGN_PAGE (kern_end + file->size);
+
+fail:
+  if (file)
+    grub_file_close (file);
+}
+
+GRUB_MOD_INIT (bsd)
+{
+  grub_rescue_register_command ("freebsd",
+                               grub_rescue_cmd_freebsd,
+                               "load freebsd kernel");
+  grub_rescue_register_command ("openbsd",
+                               grub_rescue_cmd_openbsd,
+                               "load openbsd kernel");
+  grub_rescue_register_command ("netbsd",
+                               grub_rescue_cmd_netbsd, "load netbsd kernel");
+
+  grub_rescue_register_command ("freebsd_loadenv",
+                               grub_rescue_cmd_freebsd_loadenv,
+                               "load freebsd env");
+  grub_rescue_register_command ("freebsd_module",
+                               grub_rescue_cmd_freebsd_module,
+                               "load freebsd module");
+
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI (bsd)
+{
+  grub_rescue_unregister_command ("freebsd");
+  grub_rescue_unregister_command ("openbsd");
+  grub_rescue_unregister_command ("netbsd");
+
+  grub_rescue_unregister_command ("freebsd_loadenv");
+  grub_rescue_unregister_command ("freebsd_module");
+
+  if (mod_buf)
+    {
+      grub_free (mod_buf);
+      mod_buf = 0;
+      mod_buf_max = 0;
+    }
+}
diff --git a/loader/i386/bsd_normal.c b/loader/i386/bsd_normal.c
new file mode 100644 (file)
index 0000000..73b39a6
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ *  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/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/aout.h>
+#include <grub/cpu/bsd.h>
+
+static grub_err_t
+grub_normal_freebsd_command (struct grub_arg_list *state
+                            __attribute__ ((unused)), int argc, char **args)
+{
+  grub_rescue_cmd_freebsd (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_openbsd_command (struct grub_arg_list *state
+                            __attribute__ ((unused)), int argc, char **args)
+{
+  grub_rescue_cmd_openbsd (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_netbsd_command (struct grub_arg_list *state
+                           __attribute__ ((unused)), int argc, char **args)
+{
+  grub_rescue_cmd_netbsd (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_freebsd_loadenv_command (struct grub_arg_list *state
+                                    __attribute__ ((unused)), int argc,
+                                    char **args)
+{
+  grub_rescue_cmd_freebsd_loadenv (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_freebsd_module_command (struct grub_arg_list *state
+                                   __attribute__ ((unused)), int argc,
+                                   char **args)
+{
+  grub_rescue_cmd_freebsd_module (argc, args);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT (bsd_normal)
+{
+  (void) mod;                  /* To stop warning.  */
+  grub_register_command ("freebsd", grub_normal_freebsd_command,
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "freebsd FILE [OPTS] [ARGS...]",
+                        "Load freebsd kernel.", 0);
+  grub_register_command ("openbsd", grub_normal_openbsd_command,
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "openbsd FILE [OPTS]", "Load openbsd kernel.", 0);
+  grub_register_command ("netbsd", grub_normal_netbsd_command,
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "netbsd FILE [OPTS]", "Load netbsd kernel.", 0);
+
+  grub_register_command ("freebsd_loadenv",
+                        grub_normal_freebsd_loadenv_command,
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "freebsd_loadenv FILE", "Load freebsd env.", 0);
+  grub_register_command ("freebsd_module",
+                        grub_normal_freebsd_module_command,
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "freebsd_module [FILE [type=module_type] [ARGS...]]",
+                        "Load freebsd module.", 0);
+}
+
+GRUB_MOD_FINI (bsd_normal)
+{
+  grub_unregister_command ("freebsd");
+  grub_unregister_command ("openbsd");
+  grub_unregister_command ("netbsd");
+
+  grub_unregister_command ("freebsd_loadenv");
+  grub_unregister_command ("freebsd_module");
+}
diff --git a/loader/i386/efi/linux.c b/loader/i386/efi/linux.c
new file mode 100644 (file)
index 0000000..50e1ff1
--- /dev/null
@@ -0,0 +1,972 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/term.h>
+#include <grub/cpu/linux.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/uga_draw.h>
+#include <grub/pci.h>
+
+#define GRUB_LINUX_CL_OFFSET           0x1000
+#define GRUB_LINUX_CL_END_OFFSET       0x2000
+
+#define NEXT_MEMORY_DESCRIPTOR(desc, size)      \
+  ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
+
+static grub_dl_t my_mod;
+
+static grub_size_t linux_mem_size;
+static int loaded;
+static void *real_mode_mem;
+static void *prot_mode_mem;
+static void *initrd_mem;
+static grub_efi_uintn_t real_mode_pages;
+static grub_efi_uintn_t prot_mode_pages;
+static grub_efi_uintn_t initrd_pages;
+static void *mmap_buf;
+
+static grub_uint8_t gdt[] __attribute__ ((aligned(16))) =
+  {
+    /* NULL.  */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    /* Reserved.  */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    /* Code segment.  */
+    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00,
+    /* Data segment.  */
+    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00
+  };
+
+struct gdt_descriptor
+{
+  grub_uint16_t limit;
+  void *base;
+} __attribute__ ((packed));
+
+static struct gdt_descriptor gdt_desc =
+  {
+    sizeof (gdt) - 1,
+    gdt
+  };
+
+struct idt_descriptor
+{
+  grub_uint16_t limit;
+  void *base;
+} __attribute__ ((packed));
+
+static struct idt_descriptor idt_desc =
+  {
+    0,
+    0
+  };
+
+static inline grub_size_t
+page_align (grub_size_t size)
+{
+  return (size + (1 << 12) - 1) & (~((1 << 12) - 1));
+}
+
+/* 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 (real_mode_mem)
+    {
+      grub_efi_free_pages ((grub_addr_t) real_mode_mem, real_mode_pages);
+      real_mode_mem = 0;
+    }
+
+  if (prot_mode_mem)
+    {
+      grub_efi_free_pages ((grub_addr_t) prot_mode_mem, prot_mode_pages);
+      prot_mode_mem = 0;
+    }
+  
+  if (initrd_mem)
+    {
+      grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages);
+      initrd_mem = 0;
+    }
+}
+
+/* Allocate pages for the real mode code and the protected mode code
+   for linux as well as a memory map buffer.  */
+static int
+allocate_pages (grub_size_t prot_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;
+  grub_size_t real_size;
+  
+  /* Make sure that each size is aligned to a page boundary.  */
+  real_size = GRUB_LINUX_CL_END_OFFSET;
+  prot_size = page_align (prot_size);
+  mmap_size = find_mmap_size ();
+
+  grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n",
+               (unsigned) real_size, (unsigned) prot_size, (unsigned) mmap_size);
+  
+  /* Calculate the number of pages; Combine the real mode code with
+     the memory map buffer for simplicity.  */
+  real_mode_pages = ((real_size + mmap_size) >> 12);
+  prot_mode_pages = (prot_size >> 12);
+  
+  /* Initialize the memory pointers with NULL for convenience.  */
+  real_mode_mem = 0;
+  prot_mode_mem = 0;
+  
+  /* 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))
+    {
+      /* Probably it is better to put the real mode code in the traditional
+        space for safety.  */
+      if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
+         && desc->physical_start <= 0x90000
+         && desc->num_pages >= real_mode_pages)
+       {
+         grub_efi_physical_address_t physical_end;
+         grub_efi_physical_address_t addr;
+         
+         physical_end = desc->physical_start + (desc->num_pages << 12);
+         if (physical_end > 0x90000)
+           physical_end = 0x90000;
+
+         grub_dprintf ("linux", "physical_start = %x, physical_end = %x\n",
+                       (unsigned) desc->physical_start,
+                       (unsigned) physical_end);
+         addr = physical_end - real_size - mmap_size;
+         if (addr < 0x10000)
+           continue;
+
+         grub_dprintf ("linux", "trying to allocate %u pages at %lx\n",
+                       (unsigned) real_mode_pages, (unsigned long) addr);
+         real_mode_mem = grub_efi_allocate_pages (addr, real_mode_pages);
+         if (! real_mode_mem)
+           grub_fatal ("cannot allocate pages");
+         
+         desc->num_pages -= real_mode_pages;
+         break;
+       }
+    }
+
+  if (! real_mode_mem)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
+      goto fail;
+    }
+
+  mmap_buf = (void *) ((char *) real_mode_mem + real_size);
+             
+  /* Next, find free pages for the protected mode code.  */
+  /* XXX what happens if anything is using this address?  */
+  prot_mode_mem = grub_efi_allocate_pages (0x100000, prot_mode_pages);
+  if (! prot_mode_mem)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY,
+                 "cannot allocate protected mode pages");
+      goto fail;
+    }
+
+  grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, "
+                "prot_mode_mem = %lx, prot_mode_pages = %x\n",
+                (unsigned long) real_mode_mem, (unsigned) real_mode_pages,
+                (unsigned long) prot_mode_mem, (unsigned) prot_mode_pages);
+
+  grub_free (mmap);
+  return 1;
+
+ fail:
+  grub_free (mmap);
+  free_pages ();
+  return 0;
+}
+
+static void
+grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num,
+                      grub_uint64_t start, grub_uint64_t size,
+                      grub_uint32_t type)
+{
+  int n = *e820_num;
+
+  if (n >= GRUB_E820_MAX_ENTRY)
+    grub_fatal ("Too many e820 memory map entries");
+
+  if ((n > 0) && (e820_map[n - 1].addr + e820_map[n - 1].size == start) &&
+      (e820_map[n - 1].type == type))
+      e820_map[n - 1].size += size;
+  else
+    {
+      e820_map[n].addr = start;
+      e820_map[n].size = size;
+      e820_map[n].type = type;
+      (*e820_num)++;
+    }
+}
+
+#ifdef __x86_64__
+struct
+{
+  grub_uint32_t kernel_entry;
+  grub_uint32_t kernel_cs;
+} jumpvector;
+#endif
+
+static grub_err_t
+grub_linux_boot (void)
+{
+  struct linux_kernel_params *params;
+  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 *desc;
+  int e820_num;
+  
+  params = real_mode_mem;
+
+  grub_dprintf ("linux", "code32_start = %x, idt_desc = %lx, gdt_desc = %lx\n",
+               (unsigned) params->code32_start,
+                (unsigned long) &(idt_desc.limit),
+               (unsigned long) &(gdt_desc.limit));
+  grub_dprintf ("linux", "idt = %x:%lx, gdt = %x:%lx\n",
+               (unsigned) idt_desc.limit, (unsigned long) idt_desc.base,
+               (unsigned) gdt_desc.limit, (unsigned long) gdt_desc.base);
+
+  mmap_size = find_mmap_size ();
+  if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
+                              &desc_size, &desc_version) <= 0)
+    grub_fatal ("cannot get memory map");
+
+  e820_num = 0;
+  for (desc = mmap_buf;
+       desc < NEXT_MEMORY_DESCRIPTOR (mmap_buf, mmap_size);
+       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+    {
+      switch (desc->type)
+        {
+        case GRUB_EFI_ACPI_RECLAIM_MEMORY:
+          grub_e820_add_region (params->e820_map, &e820_num,
+                                desc->physical_start,
+                                desc->num_pages << 12,
+                                GRUB_E820_ACPI);
+          break;
+
+        case GRUB_EFI_ACPI_MEMORY_NVS:
+          grub_e820_add_region (params->e820_map, &e820_num,
+                                desc->physical_start,
+                                desc->num_pages << 12,
+                                GRUB_E820_NVS);
+          break;
+
+        case GRUB_EFI_RUNTIME_SERVICES_CODE:
+          grub_e820_add_region (params->e820_map, &e820_num,
+                                desc->physical_start,
+                                desc->num_pages << 12,
+                                GRUB_E820_EXEC_CODE);
+          break;
+
+        case GRUB_EFI_LOADER_CODE:
+        case GRUB_EFI_LOADER_DATA:
+        case GRUB_EFI_BOOT_SERVICES_CODE:
+        case GRUB_EFI_BOOT_SERVICES_DATA:
+        case GRUB_EFI_CONVENTIONAL_MEMORY:
+          {
+            grub_uint64_t start, size, end;
+
+            start = desc->physical_start;
+            size = desc->num_pages << 12;
+            end = start + size;
+
+            /* Skip A0000 - 100000 region.  */
+            if ((start < 0x100000ULL) && (end > 0xA0000ULL))
+              {
+                if (start < 0xA0000ULL)
+                  {
+                    grub_e820_add_region (params->e820_map, &e820_num,
+                                          start,
+                                          0xA0000ULL - start,
+                                          GRUB_E820_RAM);
+                  }
+
+                if (end <= 0x100000ULL)
+                  continue;
+
+                start = 0x100000ULL;
+                size = end - start;
+              }
+
+            grub_e820_add_region (params->e820_map, &e820_num,
+                                  start, size, GRUB_E820_RAM);
+            break;
+          }
+
+        default:
+          grub_e820_add_region (params->e820_map, &e820_num,
+                                desc->physical_start,
+                                desc->num_pages << 12,
+                                GRUB_E820_RESERVED);
+        }
+    }
+
+  params->mmap_size = e820_num;
+
+  if (! grub_efi_exit_boot_services (map_key))
+     grub_fatal ("cannot exit boot services");
+
+  /* Note that no boot services are available from here.  */
+
+  /* Pass EFI parameters.  */
+  if (grub_le_to_cpu16 (params->version) >= 0x0206)
+    {
+      params->v0206.efi_mem_desc_size = desc_size;
+      params->v0206.efi_mem_desc_version = desc_version;
+      params->v0206.efi_mmap = (grub_uint32_t) (unsigned long) mmap_buf;
+      params->v0206.efi_mmap_size = mmap_size;
+#ifdef __x86_64__
+      params->v0206.efi_mmap_hi = (grub_uint32_t) ((grub_uint64_t) mmap_buf >> 32);
+#endif
+    }
+  else if (grub_le_to_cpu16 (params->version) >= 0x0204)
+    {
+      params->v0204.efi_mem_desc_size = desc_size;
+      params->v0204.efi_mem_desc_version = desc_version;
+      params->v0204.efi_mmap = (grub_uint32_t) (unsigned long) mmap_buf;
+      params->v0204.efi_mmap_size = mmap_size;
+    }
+
+  /* Hardware interrupts are not safe any longer.  */
+  asm volatile ("cli" : : );
+  
+  /* Load the IDT and the GDT for the bootstrap.  */
+  asm volatile ("lidt %0" : : "m" (idt_desc));
+  asm volatile ("lgdt %0" : : "m" (gdt_desc));
+
+#ifdef __x86_64__
+
+  jumpvector.kernel_entry = (grub_uint64_t) grub_linux_real_boot;
+  jumpvector.kernel_cs = 0x10;
+
+  asm volatile ( "mov %0, %%rbx" : : "m" (params->code32_start));
+  asm volatile ( "mov %0, %%rsi" : : "m" (real_mode_mem));
+
+  asm volatile ( "ljmp *%0" : : "m" (jumpvector));
+
+#else
+
+  /* Pass parameters.  */
+  asm volatile ("movl %0, %%ecx" : : "m" (params->code32_start));
+  asm volatile ("movl %0, %%esi" : : "m" (real_mode_mem));
+
+  asm volatile ("xorl %%ebx, %%ebx" : : );
+
+  /* Enter Linux.  */
+  asm volatile ("jmp *%%ecx" : : );
+  
+#endif
+
+  /* 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;
+}
+
+grub_uint64_t video_base;
+
+static int
+grub_find_video_card (int bus, int dev, int func,
+                      grub_pci_id_t pciid __attribute__ ((unused)))
+{
+  grub_pci_address_t addr;
+
+  addr = grub_pci_make_address (bus, dev, func, 2);
+
+  if (grub_pci_read (addr) >> 24 == 0x3)
+    {
+      int i;
+
+      addr = grub_pci_make_address (bus, dev, func, 4);
+      for (i = 0; i < 6; i++, addr += 4)
+        {
+          grub_uint32_t base, type;
+
+          base = grub_pci_read (addr);
+
+          if ((base == 0) || (base == 0xffffffff) ||
+              (base & GRUB_PCI_ADDR_SPACE_IO))
+            continue;
+
+          type = base & GRUB_PCI_ADDR_MEM_TYPE_MASK;
+          if (! (addr & GRUB_PCI_ADDR_MEM_PREFETCH))
+            {
+              if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
+                {
+                  i++;
+                  addr +=4 ;
+                }
+              continue;
+            }
+
+          base &= GRUB_PCI_ADDR_MEM_MASK;
+          if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
+            {
+              if (i == 5)
+                break;
+
+              video_base = grub_pci_read (addr + 4);
+              video_base <<= 32;
+            }
+
+          video_base |= base;
+
+          return 1;
+        }
+    }
+
+  return 0;
+}
+
+static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID;
+
+static int
+grub_linux_setup_video (struct linux_kernel_params *params)
+{
+  grub_efi_uga_draw_protocol_t *c;
+  grub_uint32_t width, height, depth, rate;
+
+  c = grub_efi_locate_protocol (&uga_draw_guid, 0);
+  if (! c)
+    return 1;
+
+  if (efi_call_5 (c->get_mode, c, &width, &height, &depth, &rate))
+    return 1;
+
+  grub_printf ("Video mode: %ux%u-%u@%u\n", width, height, depth, rate);
+
+  video_base = 0;
+  grub_pci_iterate (grub_find_video_card);
+
+  if (! video_base)
+    {
+      grub_printf ("Can\'t find frame buffer address\n");
+      return 1;
+    }
+
+  grub_printf ("Video frame buffer: %llx\n", (unsigned long long) video_base);
+
+  params->lfb_width = width;
+  params->lfb_height = height;
+  params->lfb_depth = depth;
+
+  /* FIXME: shouldn't use fixed value.  */
+  params->lfb_line_len = 8192;
+
+  params->lfb_base = video_base;
+  params->lfb_size = (params->lfb_line_len * params->lfb_height + 65535) >> 16;
+
+  params->red_mask_size = 8;
+  params->red_field_pos = 16;
+  params->green_mask_size = 8;
+  params->green_field_pos = 8;
+  params->blue_mask_size = 8;
+  params->blue_field_pos = 0;
+  params->reserved_mask_size = 8;
+  params->reserved_field_pos = 24;
+
+  return 0;
+}
+
+void
+grub_rescue_cmd_linux (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  struct linux_kernel_header lh;
+  struct linux_kernel_params *params;
+  grub_uint8_t setup_sects;
+  grub_size_t real_size, prot_size;
+  grub_ssize_t len;
+  int i;
+  char *dest;
+  int video_type;
+
+  grub_dl_ref (my_mod);
+  
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
+      goto fail;
+    }
+
+  file = grub_file_open (argv[0]);
+  if (! file)
+    goto fail;
+
+  if (grub_file_read (file, (char *) &lh, sizeof (lh)) != sizeof (lh))
+    {
+      grub_error (GRUB_ERR_READ_ERROR, "cannot read the linux header");
+      goto fail;
+    }
+
+  if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
+    {
+      grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
+      goto fail;
+    }
+
+  if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "too many setup sectors");
+      goto fail;
+    }
+
+  /* EFI support is quite new, so reject old versions.  */
+  if (lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE)
+      || grub_le_to_cpu16 (lh.version) < 0x0203)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "too old version");
+      goto fail;
+    }
+
+  /* I'm not sure how to support zImage on EFI.  */
+  if (! (lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL))
+    {
+      grub_error (GRUB_ERR_BAD_OS, "zImage is not supported");
+      goto fail;
+    }
+
+  setup_sects = lh.setup_sects;
+  
+  /* If SETUP_SECTS is not set, set it to the default (4).  */
+  if (! setup_sects)
+    setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
+
+  real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
+  prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
+  
+  if (! allocate_pages (prot_size))
+    goto fail;
+  
+  params = (struct linux_kernel_params *) real_mode_mem;
+  grub_memset (params, 0, GRUB_LINUX_CL_END_OFFSET);
+  grub_memcpy (&params->setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
+
+  params->ps_mouse = params->padding10 =  0;
+
+  len = 0x400 - sizeof (lh);
+  if (grub_file_read (file, (char *) real_mode_mem + sizeof (lh), len) != len)
+    {
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+
+  /* XXX Linux assumes that only elilo can boot Linux on EFI!!!  */
+  params->type_of_loader = (LINUX_LOADER_ID_ELILO << 4);
+
+  params->cl_magic = GRUB_LINUX_CL_MAGIC;
+  params->cl_offset = 0x1000;
+  params->cmd_line_ptr = (unsigned long) real_mode_mem + 0x1000;
+  params->ramdisk_image = 0;
+  params->ramdisk_size = 0;
+
+  params->heap_end_ptr = GRUB_LINUX_HEAP_END_OFFSET;
+  params->loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP;
+
+  /* These are not needed to be precise, because Linux uses these values
+     only to raise an error when the decompression code cannot find good
+     space.  */
+  params->ext_mem = ((32 * 0x100000) >> 10);
+  params->alt_mem = ((32 * 0x100000) >> 10);
+  
+  params->video_cursor_x = grub_getxy () >> 8;
+  params->video_cursor_y = grub_getxy () & 0xff;
+  params->video_page = 0; /* ??? */
+  params->video_mode = grub_efi_system_table->con_out->mode->mode;
+  params->video_width = (grub_getwh () >> 8);
+  params->video_ega_bx = 0;
+  params->video_height = (grub_getwh () & 0xff);
+  params->have_vga = 0;
+  params->font_size = 16; /* XXX */
+
+  if (grub_le_to_cpu16 (params->version) >= 0x0206)
+    {
+      params->v0206.efi_signature = GRUB_LINUX_EFI_SIGNATURE;
+      params->v0206.efi_system_table = (grub_uint32_t) (unsigned long) grub_efi_system_table;
+#ifdef __x86_64__
+      params->v0206.efi_system_table_hi = (grub_uint32_t) ((grub_uint64_t) grub_efi_system_table >> 32);
+#endif
+    }
+  else if (grub_le_to_cpu16 (params->version) >= 0x0204)
+    {
+      params->v0204.efi_signature = GRUB_LINUX_EFI_SIGNATURE_0204;
+      params->v0204.efi_system_table = (grub_uint32_t) (unsigned long) grub_efi_system_table;
+    }
+
+#if 0
+  /* The structure is zeroed already.  */
+
+  /* No VBE on EFI.  */
+  params->lfb_width = 0;
+  params->lfb_height = 0;
+  params->lfb_depth = 0;
+  params->lfb_base = 0;
+  params->lfb_size = 0;
+  params->lfb_line_len = 0;
+  params->red_mask_size = 0;
+  params->red_field_pos = 0;
+  params->green_mask_size = 0;
+  params->green_field_pos = 0;
+  params->blue_mask_size = 0;
+  params->blue_field_pos = 0;
+  params->reserved_mask_size = 0;
+  params->reserved_field_pos = 0;
+  params->vesapm_segment = 0;
+  params->vesapm_offset = 0;
+  params->lfb_pages = 0;
+  params->vesa_attrib = 0;
+
+  /* No APM on EFI.  */
+  params->apm_version = 0;
+  params->apm_code_segment = 0;
+  params->apm_entry = 0;
+  params->apm_16bit_code_segment = 0;
+  params->apm_data_segment = 0;
+  params->apm_flags = 0;
+  params->apm_code_len = 0;
+  params->apm_data_len = 0;
+
+  /* XXX is there any way to use SpeedStep on EFI?  */
+  params->ist_signature = 0;
+  params->ist_command = 0;
+  params->ist_event = 0;
+  params->ist_perf_level = 0;
+
+  /* Let the kernel probe the information.  */
+  grub_memset (params->hd0_drive_info, 0, sizeof (params->hd0_drive_info));
+  grub_memset (params->hd1_drive_info, 0, sizeof (params->hd1_drive_info));
+
+  /* No MCA on EFI.  */
+  params->rom_config_len = 0;
+
+  /* No need to fake the BIOS's memory map.  */
+  params->mmap_size = 0;
+
+  /* Let the kernel probe the information.  */
+  params->ps_mouse = 0;
+
+  /* Clear padding for future compatibility.  */
+  grub_memset (params->padding1, 0, sizeof (params->padding1));
+  grub_memset (params->padding2, 0, sizeof (params->padding2));
+  grub_memset (params->padding3, 0, sizeof (params->padding3));
+  grub_memset (params->padding4, 0, sizeof (params->padding4));
+  grub_memset (params->padding5, 0, sizeof (params->padding5));
+  grub_memset (params->padding6, 0, sizeof (params->padding6));
+  grub_memset (params->padding7, 0, sizeof (params->padding7));
+  grub_memset (params->padding8, 0, sizeof (params->padding8));
+  grub_memset (params->padding9, 0, sizeof (params->padding9));
+  
+#endif
+
+  /* The other EFI parameters are filled when booting.  */
+
+  grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
+
+  /* XXX there is no way to know if the kernel really supports EFI.  */
+  grub_printf ("   [Linux-bzImage, setup=0x%x, size=0x%x]\n",
+              (unsigned) real_size, (unsigned) prot_size);
+
+  /* Detect explicitly specified memory size, if any.  */
+  linux_mem_size = 0;
+  video_type = 0;
+  for (i = 1; i < argc; i++)
+    if (grub_memcmp (argv[i], "mem=", 4) == 0)
+      {
+       char *val = argv[i] + 4;
+         
+       linux_mem_size = grub_strtoul (val, &val, 0);
+       
+       if (grub_errno)
+         {
+           grub_errno = GRUB_ERR_NONE;
+           linux_mem_size = 0;
+         }
+       else
+         {
+           int shift = 0;
+           
+           switch (grub_tolower (val[0]))
+             {
+             case 'g':
+               shift += 10;
+             case 'm':
+               shift += 10;
+             case 'k':
+               shift += 10;
+             default:
+               break;
+             }
+
+           /* Check an overflow.  */
+           if (linux_mem_size > (~0UL >> shift))
+             linux_mem_size = 0;
+           else
+             linux_mem_size <<= shift;
+         }
+      }
+    else if (grub_memcmp (argv[i], "video=", 6) == 0)
+      {
+        if (grub_memcmp (&argv[i][6], "vesafb", 6) == 0)
+          video_type = GRUB_VIDEO_TYPE_VLFB;
+        else if (grub_memcmp (&argv[i][6], "efifb", 5) == 0)
+          video_type = GRUB_VIDEO_TYPE_EFI;
+      }
+
+  if (video_type)
+    {
+      if (!  grub_linux_setup_video (params))
+        params->have_vga = video_type;
+    }
+
+  /* Specify the boot file.  */
+  dest = grub_stpcpy ((char *) real_mode_mem + GRUB_LINUX_CL_OFFSET,
+                     "BOOT_IMAGE=");
+  dest = grub_stpcpy (dest, argv[0]);
+  
+  /* Copy kernel parameters.  */
+  for (i = 1;
+       i < argc
+        && dest + grub_strlen (argv[i]) + 1 < ((char *) real_mode_mem
+                                               + GRUB_LINUX_CL_END_OFFSET);
+       i++)
+    {
+      *dest++ = ' ';
+      dest = grub_stpcpy (dest, argv[i]);
+    }
+
+  len = prot_size;
+  if (grub_file_read (file, (char *) GRUB_LINUX_BZIMAGE_ADDR, len) != len)
+    grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+
+  if (grub_errno == GRUB_ERR_NONE)
+    {
+      grub_loader_set (grub_linux_boot, grub_linux_unload, 1);
+      loaded = 1;
+    }
+
+ fail:
+  
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_dl_unref (my_mod);
+      loaded = 0;
+    }
+}
+
+void
+grub_rescue_cmd_initrd (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  grub_ssize_t size;
+  grub_addr_t addr_min, addr_max;
+  grub_addr_t addr;
+  grub_efi_uintn_t mmap_size;
+  grub_efi_memory_descriptor_t *desc;
+  grub_efi_uintn_t desc_size;
+  struct linux_kernel_header *lh;
+  
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "No module 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;
+
+  size = grub_file_size (file);
+  initrd_pages = (page_align (size) >> 12);
+
+  lh = (struct linux_kernel_header *) real_mode_mem;
+  
+  addr_max = (grub_cpu_to_le32 (lh->initrd_addr_max) << 10);
+  if (linux_mem_size != 0 && linux_mem_size < addr_max)
+    addr_max = linux_mem_size;
+  
+  /* Linux 2.3.xx has a bug in the memory range check, so avoid
+     the last page.
+     Linux 2.2.xx has a bug in the memory range check, which is
+     worse than that of Linux 2.3.xx, so avoid the last 64kb.  */
+  addr_max -= 0x10000;
+
+  /* Usually, the compression ratio is about 50%.  */
+  addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12)
+             + page_align (size);
+  
+  /* Find the highest address to put the initrd.  */
+  mmap_size = find_mmap_size ();
+  if (grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0) <= 0)
+    grub_fatal ("cannot get memory map");
+
+  addr = 0;
+  for (desc = mmap_buf;
+       desc < NEXT_MEMORY_DESCRIPTOR (mmap_buf, mmap_size);
+       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+    {
+      if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
+         && desc->num_pages >= initrd_pages)
+       {
+         grub_efi_physical_address_t physical_end;
+         
+         physical_end = desc->physical_start + (desc->num_pages << 12);
+         if (physical_end > addr_max)
+           physical_end = addr_max;
+
+          if (physical_end < addr_min)
+            continue;
+
+         if (physical_end > addr)
+           addr = physical_end - page_align (size);
+       }
+    }
+
+  if (addr == 0)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, "no free pages available");
+      goto fail;
+    }
+  
+  initrd_mem = grub_efi_allocate_pages (addr, initrd_pages);
+  if (! initrd_mem)
+    grub_fatal ("cannot allocate pages");
+  
+  if (grub_file_read (file, initrd_mem, size) != size)
+    {
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+
+  grub_printf ("   [Initrd, addr=0x%x, size=0x%x]\n",
+              (unsigned) addr, (unsigned) size);
+  
+  lh->ramdisk_image = addr;
+  lh->ramdisk_size = size;
+  lh->root_dev = 0x0100; /* XXX */
+  
+ fail:
+  if (file)
+    grub_file_close (file);
+}
+
+
+GRUB_MOD_INIT(linux)
+{
+  grub_rescue_register_command ("linux",
+                               grub_rescue_cmd_linux,
+                               "load linux");
+  grub_rescue_register_command ("initrd",
+                               grub_rescue_cmd_initrd,
+                               "load initrd");
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI(linux)
+{
+  grub_rescue_unregister_command ("linux");
+  grub_rescue_unregister_command ("initrd");
+}
diff --git a/loader/i386/ieee1275/linux.c b/loader/i386/ieee1275/linux.c
new file mode 100644 (file)
index 0000000..d01349b
--- /dev/null
@@ -0,0 +1,283 @@
+/* linux.c - boot Linux zImage or bzImage */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,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/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/machine/memory.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/disk.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/rescue.h>
+#include <grub/mm.h>
+#include <grub/dl.h>
+#include <grub/env.h>
+#include <grub/term.h>
+#include <grub/cpu/linux.h>
+#include <grub/ieee1275/ieee1275.h>
+
+#define GRUB_OFW_LINUX_PARAMS_ADDR     0x90000
+#define GRUB_OFW_LINUX_KERNEL_ADDR     0x100000
+#define GRUB_OFW_LINUX_INITRD_ADDR     0x800000
+
+#define GRUB_OFW_LINUX_CL_OFFSET       0x1e00
+#define GRUB_OFW_LINUX_CL_LENGTH       0x100
+
+static grub_dl_t my_mod;
+
+static grub_size_t kernel_size;
+static char *kernel_addr, *kernel_cmdline;
+static grub_size_t initrd_size;
+
+static grub_err_t
+grub_linux_unload (void)
+{
+  grub_free (kernel_cmdline);
+  grub_free (kernel_addr);
+  kernel_cmdline = 0;
+  kernel_addr = 0;
+  initrd_size = 0;
+
+  grub_dl_unref (my_mod);
+
+  return GRUB_ERR_NONE;
+}
+
+/*
+static int
+grub_ieee1275_debug (void)
+{
+  struct enter_args
+  {
+    struct grub_ieee1275_common_hdr common;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "enter", 0, 0);
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  return 0;
+}
+*/
+
+static grub_err_t
+grub_linux_boot (void)
+{
+  struct linux_kernel_params *params;
+  struct linux_kernel_header *lh;
+  char *prot_code;
+  char *bootpath;
+  grub_ssize_t len;
+
+  bootpath = grub_env_get ("root");
+  if (bootpath)
+    grub_ieee1275_set_property (grub_ieee1275_chosen,
+                                "bootpath", bootpath,
+                                grub_strlen (bootpath) + 1,
+                                &len);
+
+  params = (struct linux_kernel_params *) GRUB_OFW_LINUX_PARAMS_ADDR;
+  lh = (struct linux_kernel_header *) params;
+
+  grub_memset ((char *) params, 0, GRUB_OFW_LINUX_CL_OFFSET);
+
+  params->alt_mem = grub_upper_mem >> 10;
+  params->ext_mem = params->alt_mem;
+
+  lh->cmd_line_ptr = (char *)
+        (GRUB_OFW_LINUX_PARAMS_ADDR + GRUB_OFW_LINUX_CL_OFFSET);
+
+  params->cl_magic = GRUB_LINUX_CL_MAGIC;
+  params->cl_offset = GRUB_OFW_LINUX_CL_OFFSET;
+
+  params->video_width = (grub_getwh () >> 8);
+  params->video_height = (grub_getwh () & 0xff);
+  params->font_size = 16;
+
+  params->ofw_signature = GRUB_LINUX_OFW_SIGNATURE;
+  params->ofw_num_items = 1;
+  params->ofw_cif_handler = (grub_uint32_t) grub_ieee1275_entry_fn;
+  params->ofw_idt = 0;
+
+  if (initrd_size)
+    {
+      lh->type_of_loader = 1;
+      lh->ramdisk_image = GRUB_OFW_LINUX_INITRD_ADDR;
+      lh->ramdisk_size = initrd_size;
+    }
+
+  if (kernel_cmdline)
+    grub_strcpy (lh->cmd_line_ptr, kernel_cmdline);
+
+  prot_code = (char *) GRUB_OFW_LINUX_KERNEL_ADDR;
+  grub_memcpy (prot_code, kernel_addr, kernel_size);
+
+  asm volatile ("movl %0, %%esi" : : "m" (params));
+  asm volatile ("movl %%esi, %%esp" : : );
+  asm volatile ("movl %0, %%ecx" : : "m" (prot_code));
+  asm volatile ("xorl %%ebx, %%ebx" : : );
+  asm volatile ("jmp *%%ecx" : : );
+
+  return GRUB_ERR_NONE;
+}
+
+void
+grub_rescue_cmd_linux (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  struct linux_kernel_header lh;
+  grub_uint8_t setup_sects;
+  grub_size_t real_size, prot_size;
+  int i;
+  char *dest;
+
+  grub_dl_ref (my_mod);
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
+      goto fail;
+    }
+
+  file = grub_file_open (argv[0]);
+  if (! file)
+    goto fail;
+
+  if (grub_file_read (file, (char *) &lh, sizeof (lh)) != sizeof (lh))
+    {
+      grub_error (GRUB_ERR_READ_ERROR, "cannot read the linux header");
+      goto fail;
+    }
+
+  if ((lh.boot_flag != grub_cpu_to_le16 (0xaa55)) ||
+      (lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE)))
+    {
+      grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
+      goto fail;
+    }
+
+  setup_sects = lh.setup_sects;
+  if (! setup_sects)
+    setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
+
+  real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
+  prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
+
+  grub_printf ("   [Linux-%s, setup=0x%x, size=0x%x]\n",
+               "bzImage", real_size, prot_size);
+
+  grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
+  if (grub_errno)
+    goto fail;
+
+  kernel_cmdline = grub_malloc (GRUB_OFW_LINUX_CL_LENGTH);
+  if (! kernel_cmdline)
+    goto fail;
+
+  dest = kernel_cmdline;
+  for (i = 1;
+       i < argc
+       && dest + grub_strlen (argv[i]) + 1 < (kernel_cmdline
+                                              + GRUB_OFW_LINUX_CL_LENGTH);
+       i++)
+    {
+      *dest++ = ' ';
+      dest = grub_stpcpy (dest, argv[i]);
+    }
+
+  kernel_addr = grub_malloc (prot_size);
+  if (! kernel_addr)
+    goto fail;
+
+  kernel_size = prot_size;
+  if (grub_file_read (file, kernel_addr, prot_size) != (int) prot_size)
+    grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+
+  if (grub_errno == GRUB_ERR_NONE)
+    grub_loader_set (grub_linux_boot, grub_linux_unload, 1);
+
+fail:
+
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_free (kernel_cmdline);
+      grub_free (kernel_addr);
+      kernel_cmdline = 0;
+      kernel_addr = 0;
+
+      grub_dl_unref (my_mod);
+    }
+}
+
+void
+grub_rescue_cmd_initrd (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified");
+      goto fail;
+    }
+
+  if (! kernel_addr)
+    {
+      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;
+
+  initrd_size = grub_file_size (file);
+  if (grub_file_read (file, (char *) GRUB_OFW_LINUX_INITRD_ADDR,
+                      initrd_size) != (int) initrd_size)
+    {
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+
+fail:
+  if (file)
+    grub_file_close (file);
+}
+
+GRUB_MOD_INIT(linux)
+{
+  grub_rescue_register_command ("linux",
+                               grub_rescue_cmd_linux,
+                               "load linux");
+  grub_rescue_register_command ("initrd",
+                               grub_rescue_cmd_initrd,
+                               "load initrd");
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI(linux)
+{
+  grub_rescue_unregister_command ("linux");
+  grub_rescue_unregister_command ("initrd");
+}
diff --git a/loader/i386/linux.c b/loader/i386/linux.c
new file mode 100644 (file)
index 0000000..a5fbf04
--- /dev/null
@@ -0,0 +1,606 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/machine.h>
+#include <grub/machine/memory.h>
+#include <grub/machine/loader.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/term.h>
+#include <grub/cpu/linux.h>
+
+#define GRUB_LINUX_CL_OFFSET           0x1000
+#define GRUB_LINUX_CL_END_OFFSET       0x2000
+
+static grub_dl_t my_mod;
+
+static grub_size_t linux_mem_size;
+static int loaded;
+static void *real_mode_mem;
+static void *prot_mode_mem;
+static void *initrd_mem;
+static grub_uint32_t real_mode_pages;
+static grub_uint32_t prot_mode_pages;
+static grub_uint32_t initrd_pages;
+
+static grub_uint8_t gdt[] __attribute__ ((aligned(16))) =
+  {
+    /* NULL.  */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    /* Reserved.  */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    /* Code segment.  */
+    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00,
+    /* Data segment.  */
+    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00
+  };
+
+struct gdt_descriptor
+{
+  grub_uint16_t limit;
+  void *base;
+} __attribute__ ((packed));
+
+static struct gdt_descriptor gdt_desc =
+  {
+    sizeof (gdt) - 1,
+    gdt
+  };
+
+struct idt_descriptor
+{
+  grub_uint16_t limit;
+  void *base;
+} __attribute__ ((packed));
+
+static struct idt_descriptor idt_desc =
+  {
+    0,
+    0
+  };
+
+static inline grub_size_t
+page_align (grub_size_t size)
+{
+  return (size + (1 << 12) - 1) & (~((1 << 12) - 1));
+}
+
+/* Find the optimal number of pages for the memory map. */
+static grub_size_t
+find_mmap_size (void)
+{
+  grub_size_t count = 0, mmap_size;
+
+  auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)),
+                            grub_uint64_t size __attribute__ ((unused)),
+                            grub_uint32_t type __attribute__ ((unused)))
+    {
+      count++;
+      return 0;
+    }
+  
+  grub_machine_mmap_iterate (hook);
+  
+  mmap_size = count * sizeof (struct grub_e820_mmap);
+
+  /* Increase the size a bit for safety, because GRUB allocates more on
+     later.  */
+  mmap_size += (1 << 12);
+  
+  return page_align (mmap_size);
+}
+
+static void
+free_pages (void)
+{
+  real_mode_mem = prot_mode_mem = initrd_mem = 0;
+}
+
+/* Allocate pages for the real mode code and the protected mode code
+   for linux as well as a memory map buffer.  */
+static int
+allocate_pages (grub_size_t prot_size)
+{
+  grub_size_t real_size, mmap_size;
+
+  /* Make sure that each size is aligned to a page boundary.  */
+  real_size = GRUB_LINUX_CL_END_OFFSET;
+  prot_size = page_align (prot_size);
+  mmap_size = find_mmap_size ();
+
+  grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n",
+               (unsigned) real_size, (unsigned) prot_size, (unsigned) mmap_size);
+  
+  /* Calculate the number of pages; Combine the real mode code with
+     the memory map buffer for simplicity.  */
+  real_mode_pages = ((real_size + mmap_size) >> 12);
+  prot_mode_pages = (prot_size >> 12);
+  
+  /* Initialize the memory pointers with NULL for convenience.  */
+  real_mode_mem = 0;
+  prot_mode_mem = 0;
+  
+#ifdef GRUB_MACHINE_PCBIOS
+#error i386-pc port adds lower memory to heap, which collides with `real_mode_mem' allocation below
+#endif
+
+  auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
+    {
+      /* We must put real mode code in the traditional space.  */
+
+      if (type == GRUB_MACHINE_MEMORY_AVAILABLE
+         && addr <= 0x90000)
+       {
+         if (addr < 0x10000)
+           {
+             size += addr - 0x10000;
+             addr = 0x10000;
+           }
+
+         if (addr + size > 0x90000)
+           size = 0x90000 - addr;
+
+         if (real_size + mmap_size > size)
+           return 0;
+
+         real_mode_mem = (void *) ((addr + size) - (real_size + mmap_size));
+         return 1;
+       }
+
+      return 0;
+    }
+  grub_machine_mmap_iterate (hook);
+  if (! real_mode_mem)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
+      goto fail;
+    }
+
+  prot_mode_mem = (void *) 0x100000;
+
+  grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, "
+                "prot_mode_mem = %lx, prot_mode_pages = %x\n",
+                (unsigned long) real_mode_mem, (unsigned) real_mode_pages,
+                (unsigned long) prot_mode_mem, (unsigned) prot_mode_pages);
+
+  return 1;
+
+ fail:
+  free_pages ();
+  return 0;
+}
+
+static void
+grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num,
+                      grub_uint64_t start, grub_uint64_t size,
+                      grub_uint32_t type)
+{
+  int n = *e820_num;
+
+  if (n >= GRUB_E820_MAX_ENTRY)
+    grub_fatal ("Too many e820 memory map entries");
+
+  if ((n > 0) && (e820_map[n - 1].addr + e820_map[n - 1].size == start) &&
+      (e820_map[n - 1].type == type))
+      e820_map[n - 1].size += size;
+  else
+    {
+      e820_map[n].addr = start;
+      e820_map[n].size = size;
+      e820_map[n].type = type;
+      (*e820_num)++;
+    }
+}
+
+#ifdef __x86_64__
+struct
+{
+  grub_uint32_t kernel_entry;
+  grub_uint32_t kernel_cs;
+} jumpvector;
+#endif
+
+static grub_err_t
+grub_linux32_boot (void)
+{
+  struct linux_kernel_params *params;
+  int e820_num;
+  
+  params = real_mode_mem;
+
+  grub_dprintf ("linux", "code32_start = %x, idt_desc = %lx, gdt_desc = %lx\n",
+               (unsigned) params->code32_start,
+                (unsigned long) &(idt_desc.limit),
+               (unsigned long) &(gdt_desc.limit));
+  grub_dprintf ("linux", "idt = %x:%lx, gdt = %x:%lx\n",
+               (unsigned) idt_desc.limit, (unsigned long) idt_desc.base,
+               (unsigned) gdt_desc.limit, (unsigned long) gdt_desc.base);
+
+  auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
+    {
+      switch (type)
+        {
+        case GRUB_MACHINE_MEMORY_AVAILABLE:
+         grub_e820_add_region (params->e820_map, &e820_num,
+                               addr, size, GRUB_E820_RAM);
+         break;
+
+        default:
+          grub_e820_add_region (params->e820_map, &e820_num,
+                                addr, size, GRUB_E820_RESERVED);
+        }
+      return 0;
+    }
+
+  e820_num = 0;
+  grub_machine_mmap_iterate (hook);
+  params->mmap_size = e820_num;
+
+  /* Hardware interrupts are not safe any longer.  */
+  asm volatile ("cli" : : );
+  
+  /* Load the IDT and the GDT for the bootstrap.  */
+  asm volatile ("lidt %0" : : "m" (idt_desc));
+  asm volatile ("lgdt %0" : : "m" (gdt_desc));
+
+#ifdef __x86_64__
+
+  jumpvector.kernel_entry = (grub_uint64_t) grub_linux_real_boot;
+  jumpvector.kernel_cs = 0x10;
+
+  asm volatile ( "mov %0, %%rbx" : : "m" (params->code32_start));
+  asm volatile ( "mov %0, %%rsi" : : "m" (real_mode_mem));
+
+  asm volatile ( "ljmp *%0" : : "m" (jumpvector));
+
+#else
+
+  /* Pass parameters.  */
+  asm volatile ("movl %0, %%ecx" : : "m" (params->code32_start));
+  asm volatile ("movl %0, %%esi" : : "m" (real_mode_mem));
+
+  asm volatile ("xorl %%ebx, %%ebx" : : );
+
+  /* Enter Linux.  */
+  asm volatile ("jmp *%%ecx" : : );
+  
+#endif
+
+  /* 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;
+}
+
+void
+grub_rescue_cmd_linux (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  struct linux_kernel_header lh;
+  struct linux_kernel_params *params;
+  grub_uint8_t setup_sects;
+  grub_size_t real_size, prot_size;
+  grub_ssize_t len;
+  int i;
+  char *dest;
+  int video_type;
+
+  grub_dl_ref (my_mod);
+  
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
+      goto fail;
+    }
+
+  file = grub_file_open (argv[0]);
+  if (! file)
+    goto fail;
+
+  if (grub_file_read (file, (char *) &lh, sizeof (lh)) != sizeof (lh))
+    {
+      grub_error (GRUB_ERR_READ_ERROR, "cannot read the linux header");
+      goto fail;
+    }
+
+  if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
+    {
+      grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
+      goto fail;
+    }
+
+  if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "too many setup sectors");
+      goto fail;
+    }
+
+  /* FIXME: Is 2.02 recent enough for 32-bit boot?  */
+  if (lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE)
+      || grub_le_to_cpu16 (lh.version) < 0x0203)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "too old version");
+      goto fail;
+    }
+
+  /* zImage doesn't support 32-bit boot.  */
+  if (! (lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL))
+    {
+      grub_error (GRUB_ERR_BAD_OS, "zImage is not supported");
+      goto fail;
+    }
+
+  setup_sects = lh.setup_sects;
+  
+  /* If SETUP_SECTS is not set, set it to the default (4).  */
+  if (! setup_sects)
+    setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
+
+  real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
+  prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
+  
+  if (! allocate_pages (prot_size))
+    goto fail;
+  
+  params = (struct linux_kernel_params *) real_mode_mem;
+  grub_memset (params, 0, GRUB_LINUX_CL_END_OFFSET);
+  grub_memcpy (&params->setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
+
+  params->ps_mouse = params->padding10 =  0;
+
+  len = 0x400 - sizeof (lh);
+  if (grub_file_read (file, (char *) real_mode_mem + sizeof (lh), len) != len)
+    {
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+
+  params->type_of_loader = (LINUX_LOADER_ID_GRUB << 4);
+
+  params->cl_magic = GRUB_LINUX_CL_MAGIC;
+  params->cl_offset = 0x1000;
+  params->cmd_line_ptr = (unsigned long) real_mode_mem + 0x1000;
+  params->ramdisk_image = 0;
+  params->ramdisk_size = 0;
+
+  params->heap_end_ptr = GRUB_LINUX_HEAP_END_OFFSET;
+  params->loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP;
+
+  /* These are not needed to be precise, because Linux uses these values
+     only to raise an error when the decompression code cannot find good
+     space.  */
+  params->ext_mem = ((32 * 0x100000) >> 10);
+  params->alt_mem = ((32 * 0x100000) >> 10);
+  
+  params->video_cursor_x = grub_getxy () >> 8;
+  params->video_cursor_y = grub_getxy () & 0xff;
+  params->video_page = 0; /* ??? */
+  params->video_mode = 0;
+  params->video_width = (grub_getwh () >> 8);
+  params->video_ega_bx = 0;
+  params->video_height = (grub_getwh () & 0xff);
+  params->have_vga = 0;
+  params->font_size = 16; /* XXX */
+
+  /* The other parameters are filled when booting.  */
+
+  grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
+
+  grub_printf ("   [Linux-bzImage, setup=0x%x, size=0x%x]\n",
+              (unsigned) real_size, (unsigned) prot_size);
+
+  /* Detect explicitly specified memory size, if any.  */
+  linux_mem_size = 0;
+  video_type = 0;
+  for (i = 1; i < argc; i++)
+    if (grub_memcmp (argv[i], "mem=", 4) == 0)
+      {
+       char *val = argv[i] + 4;
+         
+       linux_mem_size = grub_strtoul (val, &val, 0);
+       
+       if (grub_errno)
+         {
+           grub_errno = GRUB_ERR_NONE;
+           linux_mem_size = 0;
+         }
+       else
+         {
+           int shift = 0;
+           
+           switch (grub_tolower (val[0]))
+             {
+             case 'g':
+               shift += 10;
+             case 'm':
+               shift += 10;
+             case 'k':
+               shift += 10;
+             default:
+               break;
+             }
+
+           /* Check an overflow.  */
+           if (linux_mem_size > (~0UL >> shift))
+             linux_mem_size = 0;
+           else
+             linux_mem_size <<= shift;
+         }
+      }
+  
+  /* Specify the boot file.  */
+  dest = grub_stpcpy ((char *) real_mode_mem + GRUB_LINUX_CL_OFFSET,
+                     "BOOT_IMAGE=");
+  dest = grub_stpcpy (dest, argv[0]);
+  
+  /* Copy kernel parameters.  */
+  for (i = 1;
+       i < argc
+        && dest + grub_strlen (argv[i]) + 1 < ((char *) real_mode_mem
+                                               + GRUB_LINUX_CL_END_OFFSET);
+       i++)
+    {
+      *dest++ = ' ';
+      dest = grub_stpcpy (dest, argv[i]);
+    }
+
+  len = prot_size;
+  if (grub_file_read (file, (char *) GRUB_LINUX_BZIMAGE_ADDR, len) != len)
+    grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+
+  if (grub_errno == GRUB_ERR_NONE)
+    {
+      grub_loader_set (grub_linux32_boot, grub_linux_unload, 1);
+      loaded = 1;
+    }
+
+ fail:
+  
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_dl_unref (my_mod);
+      loaded = 0;
+    }
+}
+
+void
+grub_rescue_cmd_initrd (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  grub_ssize_t size;
+  grub_addr_t addr_min, addr_max;
+  grub_addr_t addr;
+  struct linux_kernel_header *lh;
+  
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "No module 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;
+
+  size = grub_file_size (file);
+  initrd_pages = (page_align (size) >> 12);
+
+  lh = (struct linux_kernel_header *) real_mode_mem;
+
+  /* Get the highest address available for the initrd.  */
+  if (grub_le_to_cpu16 (lh->version) >= 0x0203)
+    {
+      addr_max = grub_cpu_to_le32 (lh->initrd_addr_max);
+
+      /* XXX in reality, Linux specifies a bogus value, so
+        it is necessary to make sure that ADDR_MAX does not exceed
+        0x3fffffff.  */
+      if (addr_max > GRUB_LINUX_INITRD_MAX_ADDRESS)
+       addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
+    }
+  else
+    addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
+  
+  if (linux_mem_size != 0 && linux_mem_size < addr_max)
+    addr_max = linux_mem_size;
+  
+  /* Linux 2.3.xx has a bug in the memory range check, so avoid
+     the last page.
+     Linux 2.2.xx has a bug in the memory range check, which is
+     worse than that of Linux 2.3.xx, so avoid the last 64kb.  */
+  addr_max -= 0x10000;
+
+  /* Usually, the compression ratio is about 50%.  */
+  addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12)
+             + page_align (size);
+  
+  if (addr_max > grub_os_area_addr + grub_os_area_size)
+    addr_max = grub_os_area_addr + grub_os_area_size;
+
+  /* Put the initrd as high as possible, 4KiB aligned.  */
+  addr = (addr_max - size) & ~0xFFF;
+
+  if (addr < addr_min)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "The initrd is too big");
+      goto fail;
+    }
+  
+  initrd_mem = (void *) addr;
+  
+  if (grub_file_read (file, initrd_mem, size) != size)
+    {
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+
+  grub_printf ("   [Initrd, addr=0x%x, size=0x%x]\n",
+              (unsigned) addr, (unsigned) size);
+  
+  lh->ramdisk_image = addr;
+  lh->ramdisk_size = size;
+  lh->root_dev = 0x0100; /* XXX */
+  
+ fail:
+  if (file)
+    grub_file_close (file);
+}
+
+
+GRUB_MOD_INIT(linux)
+{
+  grub_rescue_register_command ("linux",
+                               grub_rescue_cmd_linux,
+                               "load linux");
+  grub_rescue_register_command ("initrd",
+                               grub_rescue_cmd_initrd,
+                               "load initrd");
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI(linux)
+{
+  grub_rescue_unregister_command ("linux");
+  grub_rescue_unregister_command ("initrd");
+}
diff --git a/loader/i386/pc/chainloader.c b/loader/i386/pc/chainloader.c
new file mode 100644 (file)
index 0000000..825dbb3
--- /dev/null
@@ -0,0 +1,164 @@
+/* chainloader.c - boot another boot loader */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2004,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/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/machine/chainloader.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/machine/init.h>
+#include <grub/partition.h>
+#include <grub/machine/memory.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+
+static grub_dl_t my_mod;
+static int boot_drive;
+static void *boot_part_addr;
+
+static grub_err_t
+grub_chainloader_boot (void)
+{
+  grub_chainloader_real_boot (boot_drive, boot_part_addr);
+
+  /* Never reach here.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_chainloader_unload (void)
+{
+  grub_dl_unref (my_mod);
+  return GRUB_ERR_NONE;
+}
+
+void
+grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags)
+{
+  grub_file_t file = 0;
+  grub_uint16_t signature;
+  grub_device_t dev;
+  int drive = -1;
+  void *part_addr = 0;
+
+  grub_dl_ref (my_mod);
+  
+  file = grub_file_open (filename);
+  if (! file)
+    goto fail;
+
+  /* Read the first block.  */
+  if (grub_file_read (file, (char *) 0x7C00, GRUB_DISK_SECTOR_SIZE)
+      != GRUB_DISK_SECTOR_SIZE)
+    {
+      if (grub_errno == GRUB_ERR_NONE)
+       grub_error (GRUB_ERR_BAD_OS, "too small");
+
+      goto fail;
+    }
+
+  /* Check the signature.  */
+  signature = *((grub_uint16_t *) (0x7C00 + GRUB_DISK_SECTOR_SIZE - 2));
+  if (signature != grub_le_to_cpu16 (0xaa55)
+      && ! (flags & GRUB_CHAINLOADER_FORCE))
+    {
+      grub_error (GRUB_ERR_BAD_OS, "invalid signature");
+      goto fail;
+    }
+
+  grub_file_close (file);
+
+  /* Obtain the partition table from the root device.  */
+  dev = grub_device_open (0);
+  if (dev)
+    {
+      grub_disk_t disk = dev->disk;
+      
+      if (disk)
+       {
+         grub_partition_t p = disk->partition;
+         
+         /* In i386-pc, the id is equal to the BIOS drive number.  */
+         drive = (int) disk->id;
+
+         if (p)
+           {
+             grub_disk_read (disk, p->offset, 446, 64,
+                             (char *) GRUB_MEMORY_MACHINE_PART_TABLE_ADDR);
+             part_addr = (void *) (GRUB_MEMORY_MACHINE_PART_TABLE_ADDR
+                                   + (p->index << 4));
+           }
+       }
+
+      grub_device_close (dev);
+    }
+  
+  /* Ignore errors. Perhaps it's not fatal.  */
+  grub_errno = GRUB_ERR_NONE;
+
+  boot_drive = drive;
+  boot_part_addr = part_addr;
+  
+  grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 1);
+  return;
+  
+ fail:
+
+  if (file)
+    grub_file_close (file);
+  
+  grub_dl_unref (my_mod);
+}
+
+static void
+grub_rescue_cmd_chainloader (int argc, char *argv[])
+{
+  grub_chainloader_flags_t flags = 0;
+
+  if (argc > 0 && grub_strcmp (argv[0], "--force") == 0)
+    {
+      flags |= GRUB_CHAINLOADER_FORCE;
+      argc--;
+      argv++;
+    }
+  
+  if (argc == 0)
+    grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
+  else
+    grub_chainloader_cmd (argv[0], flags);
+}
+
+static const char loader_name[] = "chainloader";
+
+GRUB_MOD_INIT(chainloader)
+{
+  grub_rescue_register_command (loader_name,
+                               grub_rescue_cmd_chainloader,
+                               "load another boot loader");
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI(chainloader)
+{
+  grub_rescue_unregister_command (loader_name);
+}
diff --git a/loader/i386/pc/chainloader_normal.c b/loader/i386/pc/chainloader_normal.c
new file mode 100644 (file)
index 0000000..106cd56
--- /dev/null
@@ -0,0 +1,56 @@
+/* chainloader_normal.c - boot another boot loader */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,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/>.
+ */
+
+#include <grub/machine/chainloader.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+
+static const struct grub_arg_option options[] =
+  {
+    {"force", 'f', 0, "skip bootsector magic number test", 0, 0},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+static grub_err_t
+chainloader_command (struct grub_arg_list *state,
+                    int argc, char **args)
+{
+  grub_chainloader_flags_t flags = state[0].set ? GRUB_CHAINLOADER_FORCE : 0;
+  
+  if (argc == 0)
+    grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
+  else
+    grub_chainloader_cmd (args[0], flags);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(chainloader_normal)
+{
+  (void) mod; /* To stop warning.  */
+  grub_register_command ("chainloader", chainloader_command,
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "chainloader [-f] FILE",
+                        "Prepare to boot another boot loader.", options);
+}
+
+GRUB_MOD_FINI(chainloader_normal)
+{
+  grub_unregister_command ("chainloader");
+}
diff --git a/loader/i386/pc/linux.c b/loader/i386/pc/linux.c
new file mode 100644 (file)
index 0000000..d34b5d7
--- /dev/null
@@ -0,0 +1,389 @@
+/* linux.c - boot Linux zImage or bzImage */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,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/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/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/machine/init.h>
+#include <grub/machine/memory.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/cpu/linux.h>
+
+#define GRUB_LINUX_CL_OFFSET           0x9000
+#define GRUB_LINUX_CL_END_OFFSET       0x90FF
+
+static grub_dl_t my_mod;
+
+static grub_size_t linux_mem_size;
+static int loaded;
+
+static grub_err_t
+grub_linux_unload (void)
+{
+  grub_dl_unref (my_mod);
+  loaded = 0;
+  return GRUB_ERR_NONE;
+}
+
+void
+grub_rescue_cmd_linux (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  struct linux_kernel_header lh;
+  grub_uint8_t setup_sects;
+  grub_size_t real_size, prot_size;
+  grub_ssize_t len;
+  int i;
+  char *dest;
+
+  grub_dl_ref (my_mod);
+  
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
+      goto fail;
+    }
+
+  file = grub_file_open (argv[0]);
+  if (! file)
+    goto fail;
+
+  if ((grub_size_t) grub_file_size (file) > grub_os_area_size)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "too big kernel (0x%x > 0x%x)",
+                 (grub_size_t) grub_file_size (file),
+                 grub_os_area_size);
+      goto fail;
+    }
+
+  if (grub_file_read (file, (char *) &lh, sizeof (lh)) != sizeof (lh))
+    {
+      grub_error (GRUB_ERR_READ_ERROR, "cannot read the linux header");
+      goto fail;
+    }
+
+  if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
+    {
+      grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
+      goto fail;
+    }
+
+  if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "too many setup sectors");
+      goto fail;
+    }
+
+  grub_linux_is_bzimage = 0;
+  setup_sects = lh.setup_sects;
+  linux_mem_size = 0;
+  
+  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;
+      
+      /* Put the real mode part at as a high location as possible.  */
+      grub_linux_real_addr = (char *) (grub_lower_mem
+                                      - GRUB_LINUX_SETUP_MOVE_SIZE);
+      /* But it must not exceed the traditional area.  */
+      if (grub_linux_real_addr > (char *) GRUB_LINUX_OLD_REAL_MODE_ADDR)
+       grub_linux_real_addr = (char *) GRUB_LINUX_OLD_REAL_MODE_ADDR;
+      
+      if (grub_le_to_cpu16 (lh.version) >= 0x0201)
+       {
+         lh.heap_end_ptr = grub_cpu_to_le16 (GRUB_LINUX_HEAP_END_OFFSET);
+         lh.loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP;
+       }
+      
+      if (grub_le_to_cpu16 (lh.version) >= 0x0202)
+       lh.cmd_line_ptr = grub_linux_real_addr + GRUB_LINUX_CL_OFFSET;
+      else
+       {
+         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);
+       }
+    }
+  else
+    {
+      /* Your kernel is quite old...  */
+      lh.cl_magic = grub_cpu_to_le16 (GRUB_LINUX_CL_MAGIC);
+      lh.cl_offset = grub_cpu_to_le16 (GRUB_LINUX_CL_OFFSET);
+      
+      setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
+      
+      grub_linux_real_addr = (char *) GRUB_LINUX_OLD_REAL_MODE_ADDR;
+    }
+  
+  /* If SETUP_SECTS is not set, set it to the default (4).  */
+  if (! setup_sects)
+    setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
+  
+  real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
+  prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
+  
+  grub_linux_tmp_addr = (char *) GRUB_LINUX_BZIMAGE_ADDR + prot_size;
+
+  if (! grub_linux_is_bzimage
+      && ((char *) GRUB_LINUX_ZIMAGE_ADDR + prot_size > grub_linux_real_addr))
+    {
+      grub_error (GRUB_ERR_BAD_OS, "too big zImage (0x%x > 0x%x), use bzImage instead",
+                 (char *) GRUB_LINUX_ZIMAGE_ADDR + prot_size,
+                 (grub_size_t) grub_linux_real_addr);
+      goto fail;
+    }
+  
+  if (grub_linux_real_addr + GRUB_LINUX_SETUP_MOVE_SIZE
+      > (char *) grub_lower_mem)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE,
+                "too small lower memory (0x%x > 0x%x)",
+                grub_linux_real_addr + GRUB_LINUX_SETUP_MOVE_SIZE,
+                (char *) grub_lower_mem);
+      goto fail;
+    }
+
+  grub_printf ("   [Linux-%s, setup=0x%x, size=0x%x]\n",
+              grub_linux_is_bzimage ? "bzImage" : "zImage", real_size, prot_size);
+
+  for (i = 1; i < argc; i++)
+    if (grub_memcmp (argv[i], "vga=", 4) == 0)
+      {
+       /* Video mode selection support.  */
+       grub_uint16_t vid_mode;
+       char *val = argv[i] + 4;
+
+       if (grub_strcmp (val, "normal") == 0)
+         vid_mode = GRUB_LINUX_VID_MODE_NORMAL;
+       else if (grub_strcmp (val, "ext") == 0)
+         vid_mode = GRUB_LINUX_VID_MODE_EXTENDED;
+       else if (grub_strcmp (val, "ask") == 0)
+         vid_mode = GRUB_LINUX_VID_MODE_ASK;
+       else
+         vid_mode = (grub_uint16_t) grub_strtoul (val, 0, 0);
+
+       if (grub_errno)
+         goto fail;
+
+       lh.vid_mode = grub_cpu_to_le16 (vid_mode);
+      }
+    else if (grub_memcmp (argv[i], "mem=", 4) == 0)
+      {
+       char *val = argv[i] + 4;
+         
+       linux_mem_size = grub_strtoul (val, &val, 0);
+       
+       if (grub_errno)
+         {
+           grub_errno = GRUB_ERR_NONE;
+           linux_mem_size = 0;
+         }
+       else
+         {
+           int shift = 0;
+           
+           switch (grub_tolower (val[0]))
+             {
+             case 'g':
+               shift += 10;
+             case 'm':
+               shift += 10;
+             case 'k':
+               shift += 10;
+             default:
+               break;
+             }
+
+           /* Check an overflow.  */
+           if (linux_mem_size > (~0UL >> shift))
+             linux_mem_size = 0;
+           else
+             linux_mem_size <<= shift;
+         }
+      }
+
+  /* Put the real mode code at the temporary address.  */
+  grub_memmove (grub_linux_tmp_addr, &lh, sizeof (lh));
+
+  len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh);
+  if (grub_file_read (file, grub_linux_tmp_addr + sizeof (lh), len) != len)
+    {
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+
+  if (lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE)
+      || grub_le_to_cpu16 (lh.version) < 0x0200)
+    /* Clear the heap space.  */
+    grub_memset (grub_linux_tmp_addr
+                + ((setup_sects + 1) << GRUB_DISK_SECTOR_BITS),
+                0,
+                ((GRUB_LINUX_MAX_SETUP_SECTS - setup_sects - 1)
+                 << GRUB_DISK_SECTOR_BITS));
+
+  /* Specify the boot file.  */
+  dest = grub_stpcpy (grub_linux_tmp_addr + GRUB_LINUX_CL_OFFSET,
+                     "BOOT_IMAGE=");
+  dest = grub_stpcpy (dest, argv[0]);
+  
+  /* Copy kernel parameters.  */
+  for (i = 1;
+       i < argc
+        && dest + grub_strlen (argv[i]) + 1 < (grub_linux_tmp_addr
+                                               + GRUB_LINUX_CL_END_OFFSET);
+       i++)
+    {
+      *dest++ = ' ';
+      dest = grub_stpcpy (dest, argv[i]);
+    }
+
+  len = prot_size;
+  if (grub_file_read (file, (char *) GRUB_LINUX_BZIMAGE_ADDR, len) != len)
+    grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+  if (grub_errno == GRUB_ERR_NONE)
+    {
+      grub_linux_prot_size = prot_size;
+      grub_loader_set (grub_linux_boot, grub_linux_unload, 1);
+      loaded = 1;
+    }
+
+ fail:
+  
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_dl_unref (my_mod);
+      loaded = 0;
+    }
+}
+
+void
+grub_rescue_cmd_initrd (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  grub_ssize_t size;
+  grub_addr_t addr_max, addr_min, addr;
+  struct linux_kernel_header *lh;
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified");
+      goto fail;
+    }
+  
+  if (!loaded)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "You need to load the kernel first.");
+      goto fail;
+    }
+
+  lh = (struct linux_kernel_header *) grub_linux_tmp_addr;
+
+  if (!(lh->header == grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE)
+       && grub_le_to_cpu16 (lh->version) >= 0x0200))
+    {
+      grub_error (GRUB_ERR_BAD_OS, "The kernel is too old for initrd.");
+      goto fail;
+    }
+
+  /* Get the highest address available for the initrd.  */
+  if (grub_le_to_cpu16 (lh->version) >= 0x0203)
+    {
+      addr_max = grub_cpu_to_le32 (lh->initrd_addr_max);
+
+      /* XXX in reality, Linux specifies a bogus value, so
+        it is necessary to make sure that ADDR_MAX does not exceed
+        0x3fffffff.  */
+      if (addr_max > GRUB_LINUX_INITRD_MAX_ADDRESS)
+       addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
+    }
+  else
+    addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
+
+  if (linux_mem_size != 0 && linux_mem_size < addr_max)
+    addr_max = linux_mem_size;
+
+  /* Linux 2.3.xx has a bug in the memory range check, so avoid
+     the last page.
+     Linux 2.2.xx has a bug in the memory range check, which is
+     worse than that of Linux 2.3.xx, so avoid the last 64kb.  */
+  addr_max -= 0x10000;
+
+  if (addr_max > grub_os_area_addr + grub_os_area_size)
+    addr_max = grub_os_area_addr + grub_os_area_size;
+
+  addr_min = (grub_addr_t) grub_linux_tmp_addr + GRUB_LINUX_CL_END_OFFSET;
+
+  file = grub_file_open (argv[0]);
+  if (!file)
+    goto fail;
+
+  size = grub_file_size (file);
+
+  /* Put the initrd as high as possible, 4KiB aligned.  */
+  addr = (addr_max - size) & ~0xFFF;
+
+  if (addr < addr_min)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "The initrd is too big");
+      goto fail;
+    }
+
+  if (grub_file_read (file, (void *)addr, size) != size)
+    {
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+
+  lh->ramdisk_image = addr;
+  lh->ramdisk_size = size;
+  
+ fail:
+  if (file)
+    grub_file_close (file);
+}
+
+
+GRUB_MOD_INIT(linux)
+{
+  grub_rescue_register_command ("linux",
+                               grub_rescue_cmd_linux,
+                               "load linux");
+  grub_rescue_register_command ("initrd",
+                               grub_rescue_cmd_initrd,
+                               "load initrd");
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI(linux)
+{
+  grub_rescue_unregister_command ("linux");
+  grub_rescue_unregister_command ("initrd");
+}
diff --git a/loader/i386/pc/multiboot.c b/loader/i386/pc/multiboot.c
new file mode 100644 (file)
index 0000000..c0d1fe1
--- /dev/null
@@ -0,0 +1,628 @@
+/* multiboot.c - boot a multiboot OS image. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,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/>.
+ */
+
+/*
+ *  FIXME: The following features from the Multiboot specification still
+ *         need to be implemented:
+ *  - VBE support
+ *  - symbol table
+ *  - drives table
+ *  - ROM configuration table
+ *  - APM table
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/multiboot.h>
+#include <grub/machine/init.h>
+#include <grub/machine/memory.h>
+#include <grub/elf.h>
+#include <grub/aout.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+#include <grub/env.h>
+
+extern grub_dl_t my_mod;
+static struct grub_multiboot_info *mbi;
+static grub_addr_t entry;
+
+static char *playground = NULL;
+
+static grub_err_t
+grub_multiboot_boot (void)
+{
+  grub_multiboot_real_boot (entry, mbi);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_multiboot_unload (void)
+{
+  if (mbi)
+    {
+      unsigned int i;
+      for (i = 0; i < mbi->mods_count; i++)
+       {
+         grub_free ((void *)
+                    ((struct grub_mod_list *) mbi->mods_addr)[i].mod_start);
+         grub_free ((void *)
+                    ((struct grub_mod_list *) mbi->mods_addr)[i].cmdline);
+       }
+      grub_free ((void *) mbi->mods_addr);
+      grub_free ((void *) mbi->cmdline);
+      grub_free (mbi);
+    }
+  
+  mbi = 0;
+  grub_dl_unref (my_mod);
+
+  return GRUB_ERR_NONE;
+}
+
+/* Return the length of the Multiboot mmap that will be needed to allocate
+   our platform's map.  */
+static grub_uint32_t
+grub_get_multiboot_mmap_len (void)
+{
+  grub_size_t count = 0;
+
+  auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)),
+                            grub_uint64_t size __attribute__ ((unused)),
+                            grub_uint32_t type __attribute__ ((unused)))
+    {
+      count++;
+      return 0;
+    }
+  
+  grub_machine_mmap_iterate (hook);
+  
+  return count * sizeof (struct grub_multiboot_mmap_entry);
+}
+
+/* Fill previously allocated Multiboot mmap.  */
+static void
+grub_fill_multiboot_mmap (struct grub_multiboot_mmap_entry *first_entry)
+{
+  struct grub_multiboot_mmap_entry *mmap_entry = (struct grub_multiboot_mmap_entry *) first_entry;
+
+  auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+  int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
+    {
+      mmap_entry->addr = addr;
+      mmap_entry->len = size;
+      mmap_entry->type = type;
+      mmap_entry->size = sizeof (struct grub_multiboot_mmap_entry) - sizeof (mmap_entry->size);
+      mmap_entry++;
+
+      return 0;
+    }
+
+  grub_machine_mmap_iterate (hook);
+}
+
+/* Check if BUFFER contains ELF32.  */
+static int
+grub_multiboot_is_elf32 (void *buffer)
+{
+  Elf32_Ehdr *ehdr = (Elf32_Ehdr *) buffer;
+
+  return ehdr->e_ident[EI_CLASS] == ELFCLASS32;
+}
+
+static grub_err_t
+grub_multiboot_load_elf32 (grub_file_t file, void *buffer)
+{
+  Elf32_Ehdr *ehdr = (Elf32_Ehdr *) buffer;
+  char *phdr_base;
+  int lowest_segment = 0, highest_segment = 0;
+  int i;
+
+  if (ehdr->e_ident[EI_CLASS] != ELFCLASS32)
+    return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class");
+
+  if (grub_dl_check_header (ehdr, sizeof(Elf32_Ehdr)))
+    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 > MULTIBOOT_SEARCH)
+    return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
+
+  phdr_base = (char *) buffer + ehdr->e_phoff;
+#define phdr(i)                        ((Elf32_Phdr *) (phdr_base + (i) * ehdr->e_phentsize))
+
+  for (i = 0; i < ehdr->e_phnum; i++)
+    if (phdr(i)->p_type == PT_LOAD && phdr(i)->p_filesz != 0)
+      {
+       if (phdr(i)->p_paddr < phdr(lowest_segment)->p_paddr)
+         lowest_segment = i;
+       if (phdr(i)->p_paddr > phdr(highest_segment)->p_paddr)
+         highest_segment = i;
+      }
+  grub_multiboot_payload_size += (phdr(highest_segment)->p_paddr + phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr;
+  grub_multiboot_payload_dest = phdr(lowest_segment)->p_paddr;
+
+  playground = grub_malloc (RELOCATOR_SIZEOF(forward) + grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
+  if (! playground)
+    return grub_errno;
+
+  grub_multiboot_payload_orig = (long) playground + RELOCATOR_SIZEOF(forward);
+
+  /* Load every loadable segment in memory.  */
+  for (i = 0; i < ehdr->e_phnum; i++)
+    {
+      if (phdr(i)->p_type == PT_LOAD && phdr(i)->p_filesz != 0)
+        {
+         char *load_this_module_at = (char *) (grub_multiboot_payload_orig + (phdr(i)->p_paddr - phdr(lowest_segment)->p_paddr));
+
+         grub_dprintf ("multiboot_loader", "segment %d: paddr=%p, memsz=0x%x\n",
+                       i, (void *) phdr(i)->p_paddr, phdr(i)->p_memsz);
+
+         if (grub_file_seek (file, (grub_off_t) phdr(i)->p_offset)
+             == (grub_off_t) -1)
+           return grub_error (GRUB_ERR_BAD_OS,
+                              "invalid offset in program header");
+
+          if (grub_file_read (file, load_this_module_at, phdr(i)->p_filesz)
+              != (grub_ssize_t) phdr(i)->p_filesz)
+           return grub_error (GRUB_ERR_BAD_OS,
+                              "couldn't read segment from file");
+
+          if (phdr(i)->p_filesz < phdr(i)->p_memsz)
+            grub_memset (load_this_module_at + phdr(i)->p_filesz, 0,
+                        phdr(i)->p_memsz - phdr(i)->p_filesz);
+        }
+    }
+
+  grub_multiboot_payload_entry_offset = ehdr->e_entry - phdr(lowest_segment)->p_vaddr;
+
+#undef phdr
+
+  return grub_errno;
+}
+
+/* Check if BUFFER contains ELF64.  */
+static int
+grub_multiboot_is_elf64 (void *buffer)
+{
+  Elf64_Ehdr *ehdr = (Elf64_Ehdr *) buffer;
+
+  return ehdr->e_ident[EI_CLASS] == ELFCLASS64;
+}
+
+static grub_err_t
+grub_multiboot_load_elf64 (grub_file_t file, void *buffer)
+{
+  Elf64_Ehdr *ehdr = (Elf64_Ehdr *) buffer;
+  char *phdr_base;
+  grub_addr_t physical_entry_addr = 0;
+  int i;
+
+  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_X86_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 > MULTIBOOT_SEARCH)
+    return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
+
+  /* We still in 32-bit mode */
+  if (ehdr->e_entry > 0xffffffff)
+    return grub_error (GRUB_ERR_BAD_OS, "invalid entry point for ELF64");
+
+  entry = ehdr->e_entry;
+
+  phdr_base = (char *) buffer + ehdr->e_phoff;
+#define phdr(i)                        ((Elf64_Phdr *) (phdr_base + (i) * ehdr->e_phentsize))
+
+  /* Load every loadable segment in memory.  */
+  for (i = 0; i < ehdr->e_phnum; i++)
+    {
+      if (phdr(i)->p_type == PT_LOAD)
+        {
+          /* The segment should fit in the area reserved for the OS.  */
+          if (phdr(i)->p_paddr < (grub_uint64_t) grub_os_area_addr)
+           return grub_error (GRUB_ERR_BAD_OS,
+                              "segment doesn't fit in memory reserved for the OS (0x%lx < 0x%lx)",
+                              phdr(i)->p_paddr, (grub_uint64_t) grub_os_area_addr);
+          if (phdr(i)->p_paddr + phdr(i)->p_memsz
+                 > (grub_uint64_t) grub_os_area_addr + (grub_uint64_t) grub_os_area_size)
+           return grub_error (GRUB_ERR_BAD_OS,
+                              "segment doesn't fit in memory reserved for the OS (0x%lx > 0x%lx)",
+                              phdr(i)->p_paddr + phdr(i)->p_memsz,
+                              (grub_uint64_t) grub_os_area_addr + (grub_uint64_t) grub_os_area_size);
+
+         if (grub_file_seek (file, (grub_off_t) phdr(i)->p_offset)
+             == (grub_off_t) -1)
+           return grub_error (GRUB_ERR_BAD_OS,
+                              "invalid offset in program header");
+
+         if (grub_file_read (file, (void *) ((grub_uint32_t) phdr(i)->p_paddr),
+                             phdr(i)->p_filesz)
+              != (grub_ssize_t) phdr(i)->p_filesz)
+           return grub_error (GRUB_ERR_BAD_OS,
+                              "couldn't read segment from file");
+
+          if (phdr(i)->p_filesz < phdr(i)->p_memsz)
+           grub_memset (((char *) ((grub_uint32_t) phdr(i)->p_paddr)
+                         + phdr(i)->p_filesz),
+                        0,
+                        phdr(i)->p_memsz - phdr(i)->p_filesz);
+
+         if ((entry >= phdr(i)->p_vaddr) &&
+             (entry < phdr(i)->p_vaddr + phdr(i)->p_memsz))
+           physical_entry_addr = entry + phdr(i)->p_paddr - phdr(i)->p_vaddr;
+        }
+    }
+#undef phdr
+
+  if (physical_entry_addr)
+    entry = physical_entry_addr;
+
+  return grub_errno;
+}
+
+/* Load ELF32 or ELF64.  */
+static grub_err_t
+grub_multiboot_load_elf (grub_file_t file, void *buffer)
+{
+  if (grub_multiboot_is_elf32 (buffer))
+    return grub_multiboot_load_elf32 (file, buffer);
+  else if (grub_multiboot_is_elf64 (buffer))
+    return grub_multiboot_load_elf64 (file, buffer);
+
+  return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class");
+}
+
+static int
+grub_multiboot_get_bootdev (grub_uint32_t *bootdev)
+{
+  char *p;
+
+  p = grub_env_get ("root");
+  if ((p) && ((p[0] == 'h') || (p[0] == 'f')) && (p[1] == 'd') &&
+      (p[2] >= '0') && (p[2] <= '9'))
+    {
+      grub_uint32_t bd;
+
+      bd = (p[0] == 'h') ? 0x80 : 0;
+      bd += grub_strtoul (p + 2, &p, 0);
+      bd <<= 24;
+
+      if ((p) && (p[0] == ','))
+       {
+         if ((p[1] >= '0') && (p[1] <= '9'))
+           {
+
+             bd += ((grub_strtoul (p + 1, &p, 0) - 1) & 0xFF) << 16;
+
+             if ((p) && (p[0] == ','))
+               p++;
+           }
+          else
+            bd += 0xFF0000;
+
+         if ((p[0] >= 'a') && (p[0] <= 'z'))
+            bd += (p[0] - 'a') << 8;
+          else
+            bd += 0xFF00;
+       }
+      else
+        bd += 0xFFFF00;
+
+      bd += 0xFF;
+
+      *bootdev = bd;
+      return 1;
+    }
+
+  return 0;
+}
+
+void
+grub_multiboot (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  char buffer[MULTIBOOT_SEARCH], *cmdline = 0, *p;
+  struct grub_multiboot_header *header;
+  grub_ssize_t len;
+  int i;
+
+  grub_loader_unset ();
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "No kernel specified");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if (! file)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "Couldn't open file");
+      goto fail;
+    }
+
+  len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
+  if (len < 32)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "File too small");
+      goto fail;
+    }
+
+  /* Look for the multiboot header in the buffer.  The header should
+     be at least 12 bytes and aligned on a 4-byte boundary.  */
+  for (header = (struct grub_multiboot_header *) buffer;
+       ((char *) header <= buffer + len - 12) || (header = 0);
+       header = (struct grub_multiboot_header *) ((char *) header + 4))
+    {
+      if (header->magic == MULTIBOOT_MAGIC
+         && !(header->magic + header->flags + header->checksum))
+       break;
+    }
+
+  if (header == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "No multiboot header found");
+      goto fail;
+    }
+
+  if (header->flags & MULTIBOOT_UNSUPPORTED)
+    {
+      grub_error (GRUB_ERR_UNKNOWN_OS,
+                 "Unsupported flag: 0x%x", header->flags);
+      goto fail;
+    }
+
+  if (playground)
+    {
+      grub_free (playground);
+      playground = NULL;
+    }
+
+  mbi = grub_malloc (sizeof (struct grub_multiboot_info));
+  if (! mbi)
+    goto fail;
+
+  grub_memset (mbi, 0, sizeof (struct grub_multiboot_info));
+
+  mbi->mmap_length = grub_get_multiboot_mmap_len ();
+  grub_multiboot_payload_size = mbi->mmap_length;
+
+  if (header->flags & MULTIBOOT_AOUT_KLUDGE)
+    {
+      int offset = ((char *) header - buffer -
+                   (header->header_addr - header->load_addr));
+      int load_size = ((header->load_end_addr == 0) ? file->size - offset :
+                      header->load_end_addr - header->load_addr);
+
+      if (header->bss_end_addr)
+       grub_multiboot_payload_size += (header->bss_end_addr - header->load_addr);
+      else
+       grub_multiboot_payload_size += load_size;
+      grub_multiboot_payload_dest = header->load_addr;
+
+      playground = grub_malloc (RELOCATOR_SIZEOF(forward) + grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
+      if (! playground)
+       goto fail;
+
+      grub_multiboot_payload_orig = (long) playground + RELOCATOR_SIZEOF(forward);
+
+      if ((grub_file_seek (file, offset)) == (grub_off_t) - 1)
+       goto fail;
+
+      grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size);
+      if (grub_errno)
+       goto fail;
+      
+      if (header->bss_end_addr)
+       grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
+                    header->bss_end_addr - header->load_addr - load_size);
+      
+      grub_multiboot_payload_entry_offset = header->entry_addr - header->load_addr;
+
+    }
+  else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
+    goto fail;
+
+      
+  grub_fill_multiboot_mmap ((struct grub_multiboot_mmap_entry *) (grub_multiboot_payload_orig
+                                                                 + grub_multiboot_payload_size
+                                                                 - mbi->mmap_length));
+
+  /* FIXME: grub_uint32_t will break for addresses above 4 GiB, but is mandated
+     by the spec.  Is there something we can do about it?  */
+  mbi->mmap_addr = grub_multiboot_payload_dest + grub_multiboot_payload_size - mbi->mmap_length;
+  mbi->flags |= MULTIBOOT_INFO_MEM_MAP;
+
+  if (grub_multiboot_payload_dest >= grub_multiboot_payload_orig)
+    {
+      grub_memmove (playground, &grub_multiboot_forward_relocator, RELOCATOR_SIZEOF(forward));
+      entry = (grub_addr_t) playground;
+    }
+  else
+    {
+      grub_memmove ((char *) (grub_multiboot_payload_orig + grub_multiboot_payload_size),
+                   &grub_multiboot_backward_relocator, RELOCATOR_SIZEOF(backward));
+      entry = (grub_addr_t) grub_multiboot_payload_orig + grub_multiboot_payload_size;
+    }
+  
+  grub_dprintf ("multiboot_loader", "dest=%p, size=0x%x, entry_offset=0x%x\n",
+               (void *) grub_multiboot_payload_dest,
+               grub_multiboot_payload_size,
+               grub_multiboot_payload_entry_offset);
+
+  /* Convert from bytes to kilobytes.  */
+  mbi->mem_lower = grub_lower_mem / 1024;
+  mbi->mem_upper = grub_upper_mem / 1024;
+  mbi->flags |= MULTIBOOT_INFO_MEMORY;
+
+  for (i = 0, len = 0; i < argc; i++)
+    len += grub_strlen (argv[i]) + 1;
+
+  cmdline = p = grub_malloc (len);
+  if (! cmdline)
+    goto fail;
+
+  for (i = 0; i < argc; i++)
+    {
+      p = grub_stpcpy (p, argv[i]);
+      *(p++) = ' ';
+    }
+
+  /* Remove the space after the last word.  */
+  *(--p) = '\0';
+
+  mbi->flags |= MULTIBOOT_INFO_CMDLINE;
+  mbi->cmdline = (grub_uint32_t) cmdline;
+
+  mbi->flags |= MULTIBOOT_INFO_BOOT_LOADER_NAME;
+  mbi->boot_loader_name = (grub_uint32_t) grub_strdup (PACKAGE_STRING);
+
+  if (grub_multiboot_get_bootdev (&mbi->boot_device))
+    mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
+
+  grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 1);
+
+ fail:
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_free (cmdline);
+      grub_free (mbi);
+      grub_dl_unref (my_mod);
+    }
+}
+
+
+void
+grub_module  (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  grub_ssize_t size, len = 0;
+  char *module = 0, *cmdline = 0, *p;
+  int i;
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified");
+      goto fail;
+    }
+
+  if (!mbi)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT,
+                 "You need to load the multiboot kernel first");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if (! file)
+    goto fail;
+
+  size = grub_file_size (file);
+  module = grub_memalign (MULTIBOOT_MOD_ALIGN, size);
+  if (! module)
+    goto fail;
+
+  if (grub_file_read (file, module, size) != size)
+    {
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+
+  for (i = 0; i < argc; i++)
+    len += grub_strlen (argv[i]) + 1;
+
+  cmdline = p = grub_malloc (len);
+  if (! cmdline)
+    goto fail;
+
+  for (i = 0; i < argc; i++)
+    {
+      p = grub_stpcpy (p, argv[i]);
+      *(p++) = ' ';
+    }
+
+  /* Remove the space after the last word.  */
+  *(--p) = '\0';
+
+  if (mbi->flags & MULTIBOOT_INFO_MODS)
+    {
+      struct grub_mod_list *modlist = (struct grub_mod_list *) mbi->mods_addr;
+
+      modlist = grub_realloc (modlist, (mbi->mods_count + 1)
+                                      * sizeof (struct grub_mod_list));
+      if (! modlist)
+       goto fail;
+      mbi->mods_addr = (grub_uint32_t) modlist;
+      modlist += mbi->mods_count;
+      modlist->mod_start = (grub_uint32_t) module;
+      modlist->mod_end = (grub_uint32_t) module + size;
+      modlist->cmdline = (grub_uint32_t) cmdline;
+      modlist->pad = 0;
+      mbi->mods_count++;
+    }
+  else
+    {
+      struct grub_mod_list *modlist = grub_malloc (sizeof (struct grub_mod_list));
+      if (! modlist)
+       goto fail;
+      modlist->mod_start = (grub_uint32_t) module;
+      modlist->mod_end = (grub_uint32_t) module + size;
+      modlist->cmdline = (grub_uint32_t) cmdline;
+      modlist->pad = 0;
+      mbi->mods_count = 1;
+      mbi->mods_addr = (grub_uint32_t) modlist;
+      mbi->flags |= MULTIBOOT_INFO_MODS;
+    }
+
+ fail:
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_free (module);
+      grub_free (cmdline);
+    }
+}
diff --git a/loader/i386/pc/multiboot2.c b/loader/i386/pc/multiboot2.c
new file mode 100644 (file)
index 0000000..d5fe8e3
--- /dev/null
@@ -0,0 +1,101 @@
+/* multiboot2.c - boot a multiboot 2 OS image. */
+/*
+ *  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/>.
+ */
+
+#include <multiboot2.h>
+#include <grub/multiboot2.h>
+#include <grub/elf.h>
+#include <grub/err.h>
+#include <grub/machine/loader.h>
+#include <grub/mm.h>
+
+grub_err_t
+grub_mb2_arch_elf32_hook (Elf32_Phdr *phdr, UNUSED grub_addr_t *addr)
+{
+  Elf32_Addr paddr = phdr->p_paddr;
+
+  if ((paddr < grub_os_area_addr)
+      || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size))
+    return grub_error(GRUB_ERR_OUT_OF_RANGE,"Address 0x%x is out of range", 
+                      paddr);
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_mb2_arch_elf64_hook (Elf64_Phdr *phdr, UNUSED grub_addr_t *addr)
+{
+  Elf64_Addr paddr = phdr->p_paddr;
+
+  if ((paddr < grub_os_area_addr)
+      || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size))
+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "Address 0x%x is out of range",
+                      paddr);
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_mb2_arch_module_alloc (grub_size_t size, grub_addr_t *addr)
+{
+  grub_addr_t modaddr;
+
+  modaddr = (grub_addr_t) grub_memalign (MULTIBOOT2_MOD_ALIGN, size);
+  if (! modaddr)
+    return grub_errno;
+
+  *addr = modaddr;
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_mb2_arch_module_free (grub_addr_t addr, UNUSED grub_size_t size)
+{
+  grub_free((void *) addr);
+  return GRUB_ERR_NONE;
+}
+
+void
+grub_mb2_arch_boot (grub_addr_t entry, void *tags)
+{
+  grub_multiboot2_real_boot (entry, tags);
+}
+
+void
+grub_mb2_arch_unload (struct multiboot_tag_header *tags)
+{
+   struct multiboot_tag_header *tag;
+   
+   /* Free all module memory in the tag list.  */
+   for_each_tag (tag, tags)
+     {
+       if (tag->key == MULTIBOOT2_TAG_MODULE)
+         {
+           struct multiboot_tag_module *module =
+              (struct multiboot_tag_module *) tag;
+           grub_free((void *) module->addr);
+         }
+     }
+}
+
+grub_err_t
+grub_mb2_tags_arch_create (void)
+{
+  /* XXX Create boot device et al. */
+  return GRUB_ERR_NONE;
+}
diff --git a/loader/i386/pc/multiboot_normal.c b/loader/i386/pc/multiboot_normal.c
new file mode 100644 (file)
index 0000000..b80568f
--- /dev/null
@@ -0,0 +1,60 @@
+/* multiboot_normal.c - boot another boot loader */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/machine/loader.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+
+static grub_err_t
+grub_normal_cmd_multiboot (struct grub_arg_list *state __attribute__ ((unused)),
+                          int argc, char **args)
+{
+  grub_rescue_cmd_multiboot (argc, args);
+  return grub_errno;
+}
+
+
+static grub_err_t
+grub_normal_cmd_module (struct grub_arg_list *state __attribute__ ((unused)),
+                       int argc, char **args)
+{
+  grub_rescue_cmd_module (argc, args);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(multiboot_normal)
+{
+  (void) mod; /* To stop warning.  */
+  grub_register_command ("multiboot", grub_normal_cmd_multiboot,
+                        GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE,
+                        "multiboot FILE [ARGS...]",
+                        "Load a Multiboot kernel.", 0);
+  
+  grub_register_command ("module", grub_normal_cmd_module,
+                        GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE,
+                        "module FILE [ARGS...]",
+                        "Load a Multiboot module.", 0);
+}
+
+GRUB_MOD_FINI(multiboot_normal)
+{
+  grub_unregister_command ("multiboot");
+  grub_unregister_command ("module");
+}
diff --git a/loader/ieee1275/multiboot2.c b/loader/ieee1275/multiboot2.c
new file mode 100644 (file)
index 0000000..c253fc9
--- /dev/null
@@ -0,0 +1,126 @@
+/* multiboot.c - boot a multiboot 2 OS image. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <multiboot2.h>
+#include <grub/loader.h>
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/multiboot2.h>
+#include <grub/err.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/machine/kernel.h>
+#include <grub/machine/loader.h>
+
+typedef void (*kernel_entry_t) (unsigned long, void *, int (void *),
+                                unsigned long, unsigned long);
+
+/* Claim the memory occupied by the multiboot kernel.  */
+grub_err_t
+grub_mb2_arch_elf32_hook (Elf32_Phdr *phdr, UNUSED grub_addr_t *addr)
+{
+  int rc;
+
+  rc = grub_claimmap (phdr->p_paddr, phdr->p_memsz);
+  if (rc)
+    return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Couldn't claim %x - %x",
+                     phdr->p_paddr, phdr->p_paddr + phdr->p_memsz);
+
+  grub_dprintf ("loader", "Loading segment at 0x%x - 0x%x\n", phdr->p_paddr,
+               phdr->p_paddr + phdr->p_memsz);
+
+  return GRUB_ERR_NONE;
+}
+
+/* Claim the memory occupied by the multiboot kernel.  */
+grub_err_t
+grub_mb2_arch_elf64_hook (Elf64_Phdr *phdr, UNUSED grub_addr_t *addr)
+{
+  int rc;
+
+  rc = grub_claimmap (phdr->p_paddr, phdr->p_memsz);
+  if (rc)
+    return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Couldn't claim 0x%lx - 0x%lx",
+                     phdr->p_paddr, phdr->p_paddr + phdr->p_memsz);
+
+  grub_dprintf ("loader", "Loading segment at 0x%lx - 0x%lx\n",
+               (unsigned long) phdr->p_paddr,
+               (unsigned long) (phdr->p_paddr + phdr->p_memsz));
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_mb2_arch_module_alloc (grub_size_t size, grub_addr_t *addr)
+{
+  int rc;
+
+  /* XXX Will need to map on some firmwares.  */
+  rc = grub_ieee1275_claim (0, size, MULTIBOOT2_MOD_ALIGN, addr);
+  if (rc)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+                      "Firmware couldn't allocate memory (size 0x%lx)", size);
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_mb2_arch_module_free (grub_addr_t addr, grub_size_t size)
+{
+  grub_ieee1275_release (addr, size);
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_mb2_tags_arch_create (void)
+{
+  /* Nothing special.  */
+  return GRUB_ERR_NONE;
+}
+
+/* Release the memory we claimed from Open Firmware above.  */
+void
+grub_mb2_arch_unload (struct multiboot_tag_header *tags)
+{
+  struct multiboot_tag_header *tag;
+
+  /* Free all module memory in the tag list.  */
+  for_each_tag (tag, tags)
+    {
+      if (tag->key == MULTIBOOT2_TAG_MODULE)
+       {
+         struct multiboot_tag_module *module =
+             (struct multiboot_tag_module *) tag;
+         grub_ieee1275_release (module->addr, module->size);
+       }
+    }
+}
+
+void
+grub_mb2_arch_boot (grub_addr_t entry_addr, void *tags)
+{
+#if defined(__powerpc__)
+  kernel_entry_t entry = (kernel_entry_t) entry_addr;
+  entry (MULTIBOOT2_BOOTLOADER_MAGIC, tags, grub_ieee1275_entry_fn, 0, 0);
+#elif defined(__i386__)
+  grub_multiboot2_real_boot (entry_addr, tags);
+#else
+#error
+#endif
+}
diff --git a/loader/linux_normal.c b/loader/linux_normal.c
new file mode 100644 (file)
index 0000000..0d7231e
--- /dev/null
@@ -0,0 +1,60 @@
+/* linux_normal.c - boot linux */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,2005,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/>.
+ */
+
+#include <grub/machine/loader.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+
+static grub_err_t
+grub_normal_linux_command (struct grub_arg_list *state __attribute__ ((unused)),
+                          int argc, char **args)
+{
+  grub_rescue_cmd_linux (argc, args);
+  return grub_errno;
+}
+
+
+static grub_err_t
+grub_normal_initrd_command (struct grub_arg_list *state __attribute__ ((unused)),
+                           int argc, char **args)
+{
+  grub_rescue_cmd_initrd (argc, args);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(linux_normal)
+{
+  (void) mod; /* To stop warning.  */
+  grub_register_command ("linux", grub_normal_linux_command,
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "linux FILE [ARGS...]",
+                        "Load a linux kernel.", 0);
+  
+  grub_register_command ("initrd", grub_normal_initrd_command,
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "initrd FILE",
+                        "Load an initrd.", 0);
+}
+
+GRUB_MOD_FINI(linux_normal)
+{
+  grub_unregister_command ("linux");
+  grub_unregister_command ("initrd");
+}
diff --git a/loader/multiboot2.c b/loader/multiboot2.c
new file mode 100644 (file)
index 0000000..2fb56bf
--- /dev/null
@@ -0,0 +1,461 @@
+/* multiboot2.c - boot a multiboot 2 OS image. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <multiboot2.h>
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/multiboot2.h>
+#include <grub/elfload.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+
+static grub_addr_t entry;
+extern grub_dl_t my_mod;
+
+static char *grub_mb2_tags;
+static char *grub_mb2_tags_pos;
+static grub_size_t grub_mb2_tags_len;
+static int grub_mb2_tags_count;
+
+static void
+grub_mb2_tags_free (void)
+{
+  grub_dprintf ("loader", "Freeing all tags...\n");
+  grub_free (grub_mb2_tags);
+  grub_mb2_tags = 0;
+  grub_mb2_tags_pos = 0;
+  grub_mb2_tags_len = 0;
+  grub_mb2_tags_count = 0;
+}
+
+grub_err_t
+grub_mb2_tag_alloc (grub_addr_t *addr, int key, grub_size_t len)
+{
+  struct multiboot_tag_header *tag;
+  grub_size_t used;
+  grub_size_t needed;
+
+  grub_dprintf ("loader", "Allocating tag: key 0x%x, size 0x%lx.\n",
+               key, (unsigned long) len);
+
+  used = grub_mb2_tags_pos - grub_mb2_tags;
+  len = ALIGN_UP (len, sizeof (multiboot_word));
+
+  needed = used + len;
+
+  if (needed > grub_mb2_tags_len)
+    {
+      /* Allocate new buffer.  */
+      grub_size_t newsize = needed * 2;
+      char *newarea;
+
+      grub_dprintf ("loader", "Reallocating tag buffer (new size 0x%lx).\n",
+                   (unsigned long) newsize);
+
+      newarea = grub_malloc (newsize);
+      if (! newarea)
+       return grub_errno;
+      grub_memcpy (newarea, grub_mb2_tags, grub_mb2_tags_len);
+      grub_free (grub_mb2_tags);
+
+      grub_mb2_tags_len = newsize;
+      grub_mb2_tags = newarea;
+      grub_mb2_tags_pos = newarea + used;
+    }
+
+  tag = (struct multiboot_tag_header *) grub_mb2_tags_pos;
+  grub_mb2_tags_pos += len;
+
+  tag->key = key;
+  tag->len = len;
+
+  if (addr)
+    *addr = (grub_addr_t) tag;
+
+  grub_mb2_tags_count++;
+
+  grub_dprintf ("loader", "Allocated tag %u at %p.\n", grub_mb2_tags_count, tag);
+
+  return 0;
+}
+
+static grub_err_t
+grub_mb2_tag_start_create (void)
+{
+  return grub_mb2_tag_alloc (0, MULTIBOOT2_TAG_START,
+                           sizeof (struct multiboot_tag_start));
+}
+
+static grub_err_t
+grub_mb2_tag_name_create (void)
+{
+  struct multiboot_tag_name *name;
+  grub_addr_t name_addr;
+  grub_err_t err;
+  const char *grub_version = PACKAGE_STRING;
+
+  err = grub_mb2_tag_alloc (&name_addr, MULTIBOOT2_TAG_NAME,
+                          sizeof (struct multiboot_tag_name) +
+                          sizeof (grub_version) + 1);
+  if (err)
+    return err;
+
+  name = (struct multiboot_tag_name *) name_addr;
+  grub_strcpy (name->name, grub_version);
+
+  return GRUB_ERR_NONE;
+}
+
+typedef grub_err_t (*tag_create_t) (void);
+static tag_create_t grub_mb2_tag_creators[] = {
+  grub_mb2_tag_start_create,
+  grub_mb2_tag_name_create,
+  grub_mb2_tags_arch_create,
+  0,
+};
+
+static grub_err_t
+grub_mb2_tags_create (void)
+{
+  tag_create_t *creator;
+  grub_err_t err;
+
+  for (creator = grub_mb2_tag_creators; *creator != 0; creator++)
+    {
+      err = (*creator) ();
+      if (err)
+       goto error;
+    }
+
+  return GRUB_ERR_NONE;
+
+error:
+  grub_error_push ();
+  grub_mb2_tags_free ();
+  grub_error_pop ();
+  return err;
+}
+
+static grub_err_t
+grub_mb2_tags_finish (void)
+{
+  struct multiboot_tag_start *start;
+  grub_err_t err;
+
+  /* Create the `end' tag.  */
+  err = grub_mb2_tag_alloc (0, MULTIBOOT2_TAG_END,
+                          sizeof (struct multiboot_tag_end));
+  if (err)
+    goto error;
+
+  /* We created the `start' tag first.  Update it now.  */
+  start = (struct multiboot_tag_start *) grub_mb2_tags;
+  start->size = grub_mb2_tags_pos - grub_mb2_tags;
+  return GRUB_ERR_NONE;
+
+error:
+  grub_error_push ();
+  grub_mb2_tags_free ();
+  grub_error_pop ();
+  return err;
+}
+
+static grub_err_t
+grub_mb2_boot (void)
+{
+  grub_mb2_tags_finish ();
+
+  grub_dprintf ("loader", "Tags at %p\n", grub_mb2_tags);
+  grub_mb2_arch_boot (entry, grub_mb2_tags);
+
+  /* Not reached.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_mb2_unload (void)
+{
+  struct multiboot_tag_header *tag;
+  struct multiboot_tag_header *tags =
+    (struct multiboot_tag_header *) grub_mb2_tags;
+
+  /* Free all module memory in the tag list.  */
+  for_each_tag (tag, tags)
+    {
+      if (tag->key == MULTIBOOT2_TAG_MODULE)
+       {
+         struct multiboot_tag_module *module =
+             (struct multiboot_tag_module *) tag;
+         grub_free ((void *) module->addr);
+       }
+    }
+
+  /* Allow architecture to un-reserve memory.  */
+  grub_mb2_arch_unload (tags);
+
+  /* Free the tags themselves.  */
+  grub_mb2_tags_free ();
+
+  grub_dl_unref (my_mod);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_mb2_load_other (UNUSED grub_file_t file, UNUSED void *buffer)
+{
+  /* XXX Create module tag here.  */
+  return grub_error (GRUB_ERR_UNKNOWN_OS, "currently only ELF is supported");
+}
+
+/* Create the tag containing the cmdline and the address of the module data.  */
+static grub_err_t
+grub_mb2_tag_module_create (grub_addr_t modaddr, grub_size_t modsize,
+                           char *type, int key, int argc, char *argv[])
+{
+  struct multiboot_tag_module *module;
+  grub_ssize_t argslen = 0;
+  grub_err_t err;
+  char *p;
+  grub_addr_t module_addr;
+  int i;
+
+  /* Allocate enough space for the arguments and spaces between them.  */
+  for (i = 0; i < argc; i++)
+    argslen += grub_strlen (argv[i]) + 1;
+
+  /* Note: includes implicit 1-byte cmdline.  */
+  err = grub_mb2_tag_alloc (&module_addr, key,
+                          sizeof (struct multiboot_tag_module) + argslen);
+  if (err)
+    return grub_errno;
+
+  module = (struct multiboot_tag_module *) module_addr;
+  module->addr = modaddr;
+  module->size = modsize;
+  grub_strcpy(module->type, type);
+
+  /* Fill in the command line.  */
+  p = module->cmdline;
+  for (i = 0; i < argc; i++)
+    {
+      p = grub_stpcpy (p, argv[i]);
+      *p++ = ' ';
+    }
+  module->cmdline[argslen] = '\0';
+
+  return GRUB_ERR_NONE;
+}
+
+/* Load ELF32 or ELF64.  */
+static grub_err_t
+grub_mb2_load_elf (grub_elf_t elf, int argc, char *argv[])
+{
+  grub_addr_t kern_base;
+  grub_size_t kern_size;
+  grub_err_t err;
+
+  if (grub_elf_is_elf32 (elf))
+    {
+      entry = elf->ehdr.ehdr32.e_entry;
+      err = grub_elf32_load (elf, grub_mb2_arch_elf32_hook, &kern_base,
+                            &kern_size);
+    }
+  else if (grub_elf_is_elf64 (elf))
+    {
+      entry = elf->ehdr.ehdr64.e_entry;
+      err = grub_elf64_load (elf, grub_mb2_arch_elf64_hook, &kern_base,
+                            &kern_size);
+    }
+  else
+    err = grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class");
+
+  if (err)
+    goto fail;
+
+  grub_dprintf ("loader", "Entry point is 0x%lx.\n", (unsigned long) entry);
+
+  grub_mb2_tag_module_create (kern_base, kern_size, "kernel",
+                            MULTIBOOT2_TAG_MODULE, argc, argv);
+
+fail:
+  return err;
+}
+
+void
+grub_multiboot2 (int argc, char *argv[])
+{
+  char *buffer;
+  grub_file_t file = 0;
+  grub_elf_t elf = 0;
+  struct multiboot_header *header = 0;
+  char *p;
+  grub_ssize_t len;
+  grub_err_t err;
+  int header_found = 0;
+
+  grub_loader_unset ();
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "No kernel specified");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if (! file)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "Couldn't open file");
+      goto fail;
+    }
+
+  buffer = grub_malloc (MULTIBOOT2_HEADER_SEARCH);
+  if (! buffer)
+    return;
+
+  len = grub_file_read (file, buffer, MULTIBOOT2_HEADER_SEARCH);
+  if (len < 32)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "File too small");
+      goto fail;
+    }
+
+  /* Look for the multiboot header in the buffer.  The header should
+     be at least 8 bytes and aligned on a 8-byte boundary.  */
+  for (p = buffer; p <= buffer + len - 8; p += 8)
+    {
+      header = (struct multiboot_header *) p;
+      if (header->magic == MULTIBOOT2_HEADER_MAGIC)
+       {
+         header_found = 1;
+         break;
+       }
+    }
+
+  if (! header_found)
+    grub_dprintf ("loader", "No multiboot 2 header found.\n");
+
+
+  /* Create the basic tags.  */
+  grub_dprintf ("loader", "Creating multiboot 2 tags\n");
+  grub_mb2_tags_create ();
+
+  /* Load the kernel and create its tag.  */
+  elf = grub_elf_file (file);
+  if (elf)
+    {
+      grub_dprintf ("loader", "Loading ELF multiboot 2 file.\n");
+      err = grub_mb2_load_elf (elf, argc-1, &argv[1]);
+      grub_elf_close (elf);
+    }
+  else
+    {
+      grub_errno = 0;
+      grub_dprintf ("loader", "Loading non-ELF multiboot 2 file.\n");
+
+      if (header)
+       err = grub_mb2_load_other (file, header);
+      else
+       err = grub_error (GRUB_ERR_BAD_OS,
+                         "Need multiboot 2 header to load non-ELF files.");
+      grub_file_close (file);
+    }
+
+  grub_free (buffer);
+
+  if (err)
+    goto fail;
+
+  /* Good to go.  */
+  grub_loader_set (grub_mb2_boot, grub_mb2_unload, 1);
+  return;
+
+fail:
+  grub_mb2_tags_free ();
+  grub_dl_unref (my_mod);
+}
+
+void
+grub_module2 (int argc, char *argv[])
+{
+  grub_file_t file;
+  grub_addr_t modaddr = 0;
+  grub_ssize_t modsize = 0;
+  grub_err_t err;
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified");
+      return;
+    }
+
+  if (argc == 1)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "No module type specified");
+      return;
+    }
+
+  if (entry == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT,
+                 "You need to load the multiboot kernel first");
+      return;
+    }
+
+  /* Load module data.  */
+  file = grub_gzfile_open (argv[0], 1);
+  if (! file)
+    goto out;
+
+  modsize = grub_file_size (file);
+  err = grub_mb2_arch_module_alloc (modsize, &modaddr);
+  if (err)
+    goto out;
+
+  grub_dprintf ("loader", "Loading module at 0x%x - 0x%x\n", modaddr,
+               modaddr + modsize);
+  if (grub_file_read (file, (char *) modaddr, modsize) != modsize)
+    {
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto out;
+    }
+
+  /* Create the module tag.  */
+  err = grub_mb2_tag_module_create (modaddr, modsize,
+                                  argv[1], MULTIBOOT2_TAG_MODULE,
+                                  argc-2, &argv[2]);
+  if (err)
+    goto out;
+
+out:
+  grub_error_push ();
+
+  if (file)
+    grub_file_close (file);
+
+  if (modaddr)
+    grub_mb2_arch_module_free (modaddr, modsize);
+
+  grub_error_pop ();
+}
diff --git a/loader/multiboot_loader.c b/loader/multiboot_loader.c
new file mode 100644 (file)
index 0000000..abcad9b
--- /dev/null
@@ -0,0 +1,203 @@
+/* multiboot_loader.c - boot multiboot 1 or 2 OS image */
+/*
+ *  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/>.
+ */
+
+#include <multiboot2.h>
+#include <grub/machine/machine.h>
+#include <grub/multiboot_loader.h>
+#include <grub/multiboot.h>
+#include <grub/multiboot2.h>
+#include <grub/elf.h>
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+
+grub_dl_t my_mod;
+
+/* This tracks which version of multiboot to use when using
+ * the module command. By default use multiboot version 1.
+ * values:
+ *      1 - Multiboot version 1 
+ *      2 - Multiboot version 2
+ */
+
+static unsigned int module_version_status = 1; 
+
+static int
+find_multi_boot1_header (grub_file_t file)
+{
+  struct grub_multiboot_header *header;
+  char buffer[MULTIBOOT_SEARCH];
+  int found_status = 0;
+  grub_ssize_t len;
+  len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
+  if (len < 32)
+    return found_status;
+
+  /* Look for the multiboot header in the buffer.  The header should
+     be at least 12 bytes and aligned on a 4-byte boundary.  */
+  for (header = (struct grub_multiboot_header *) buffer;
+      ((char *) header <= buffer + len - 12) || (header = 0);
+      header = (struct grub_multiboot_header *) ((char *) header + 4))
+    {
+      if (header->magic == MULTIBOOT_MAGIC
+          && !(header->magic + header->flags + header->checksum))
+        {
+           found_status = 1;
+           break;
+        }
+     }
+
+   return found_status;
+}
+
+static int
+find_multi_boot2_header (grub_file_t file)
+{
+  struct multiboot_header *header;
+  char buffer[MULTIBOOT_SEARCH];
+  int found_status = 0;
+  grub_ssize_t len;
+  len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
+  if (len < 32)
+    return found_status;
+
+  /* Look for the multiboot header in the buffer.  The header should
+     be at least 8 bytes and aligned on a 8-byte boundary.  */
+  for (header = (struct multiboot_header *) buffer;
+      ((char *) header <= buffer + len - 8) || (header = 0);
+      header = (struct multiboot_header *) ((char *) header + 8))
+    {
+      if (header->magic == MULTIBOOT2_HEADER_MAGIC)
+        {
+           found_status = 1;
+           break;
+        }
+     }
+
+   return found_status;
+}
+
+void
+grub_rescue_cmd_multiboot_loader (int argc, char *argv[])
+{
+  
+  grub_file_t file = 0;
+  int header_multi_ver_found = 0;
+
+  grub_dl_ref (my_mod);
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "No kernel specified");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if (! file)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "Couldn't open file");
+      goto fail;
+    }
+
+  /* find which header is in the file */
+  if (find_multi_boot1_header (file))
+    header_multi_ver_found = 1;
+  else if (find_multi_boot2_header (file))
+    header_multi_ver_found = 2;
+  else
+    {
+      grub_error (GRUB_ERR_BAD_OS, "Multiboot header not found");
+      goto fail;
+    }
+
+   /* close file before calling functions */
+   if (file)
+     grub_file_close (file);
+
+   /* Launch multi boot with header */
+
+   /* XXX Find a better way to identify this. 
+      This is for i386-pc */
+#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_LINUXBIOS)
+  if (header_multi_ver_found == 1)
+    {
+      grub_dprintf ("multiboot_loader",
+           "Launching multiboot 1 grub_multiboot() function\n");
+      grub_multiboot (argc, argv);     
+      module_version_status = 1;
+    }
+#endif
+  if (header_multi_ver_found == 0 || header_multi_ver_found == 2)
+    {
+      grub_dprintf ("multiboot_loader",
+           "Launching multiboot 2 grub_multiboot2() function\n");
+      grub_multiboot2 (argc, argv);
+      module_version_status = 2;
+    }
+
+   return;
+
+fail:
+  if (file)
+     grub_file_close (file);
+
+  grub_dl_unref (my_mod);
+}
+
+void
+grub_rescue_cmd_module_loader (int argc, char *argv[])
+{
+
+#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_LINUXBIOS)
+  if (module_version_status == 1)
+    {
+      grub_dprintf("multiboot_loader",
+           "Launching multiboot 1 grub_module() function\n");
+      grub_module (argc, argv);
+    }
+#endif
+  if (module_version_status == 2)
+    {
+      grub_dprintf("multiboot_loader",
+          "Launching multiboot 2 grub_module2() function\n");
+      grub_module2 (argc, argv);
+    }
+}
+
+GRUB_MOD_INIT(multiboot)
+{
+  grub_rescue_register_command ("multiboot", grub_rescue_cmd_multiboot_loader,
+                               "load a multiboot kernel");
+  grub_rescue_register_command ("module", grub_rescue_cmd_module_loader,
+                               "load a multiboot module");
+
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI(multiboot)
+{
+  grub_rescue_unregister_command ("multiboot");
+  grub_rescue_unregister_command ("module");
+}
diff --git a/loader/multiboot_loader_normal.c b/loader/multiboot_loader_normal.c
new file mode 100644 (file)
index 0000000..4a1a029
--- /dev/null
@@ -0,0 +1,61 @@
+/* multiboot_loader_normal.c - boot another boot loader */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/multiboot_loader.h>
+
+static grub_err_t
+grub_normal_cmd_multiboot (struct grub_arg_list *state __attribute__ ((unused)),
+                          int argc, char **args)
+{
+  grub_rescue_cmd_multiboot_loader (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_cmd_module (struct grub_arg_list *state __attribute__ ((unused)),
+                       int argc, char **args)
+{
+  grub_rescue_cmd_module_loader (argc, args);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(multiboot_loader_normal)
+{
+  (void) mod; /* To stop warning.  */
+  grub_register_command ("multiboot", grub_normal_cmd_multiboot,
+                         GRUB_COMMAND_FLAG_BOTH
+                         | GRUB_COMMAND_FLAG_NO_ARG_PARSE,
+                         "multiboot FILE [ARGS...]",
+                         "Load a Multiboot kernel.", 0);
+
+  grub_register_command ("module", grub_normal_cmd_module,
+                        GRUB_COMMAND_FLAG_BOTH
+                         | GRUB_COMMAND_FLAG_NO_ARG_PARSE,
+                         "module FILE [ARGS...]",
+                         "Load a Multiboot module.", 0);
+}
+
+GRUB_MOD_FINI(multiboot_loader_normal)
+{
+  grub_unregister_command ("multiboot");
+  grub_unregister_command ("module");
+}
diff --git a/loader/powerpc/ieee1275/linux.c b/loader/powerpc/ieee1275/linux.c
new file mode 100644 (file)
index 0000000..3b85341
--- /dev/null
@@ -0,0 +1,343 @@
+/* linux.c - boot Linux */
+/*
+ *  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/>.
+ */
+
+#include <grub/elf.h>
+#include <grub/elfload.h>
+#include <grub/loader.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/rescue.h>
+#include <grub/misc.h>
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/machine/loader.h>
+
+#define ELF32_LOADMASK (0xc0000000UL)
+#define ELF64_LOADMASK (0xc000000000000000ULL)
+
+static grub_dl_t my_mod;
+
+static int loaded;
+
+static grub_addr_t initrd_addr;
+static grub_size_t initrd_size;
+
+static grub_addr_t linux_addr;
+static grub_size_t linux_size;
+
+static char *linux_args;
+
+typedef void (*kernel_entry_t) (void *, unsigned long, int (void *),
+                               unsigned long, unsigned long);
+
+static grub_err_t
+grub_linux_boot (void)
+{
+  kernel_entry_t linuxmain;
+  grub_ssize_t actual;
+
+  /* Set the command line arguments.  */
+  grub_ieee1275_set_property (grub_ieee1275_chosen, "bootargs", linux_args,
+                             grub_strlen (linux_args) + 1, &actual);
+
+  grub_dprintf ("loader", "Entry point: 0x%x\n", linux_addr);
+  grub_dprintf ("loader", "Initrd at: 0x%x, size 0x%x\n", initrd_addr,
+               initrd_size);
+  grub_dprintf ("loader", "Boot arguments: %s\n", linux_args);
+  grub_dprintf ("loader", "Jumping to Linux...\n");
+
+  /* Boot the kernel.  */
+  linuxmain = (kernel_entry_t) linux_addr;
+  linuxmain ((void *) initrd_addr, initrd_size, grub_ieee1275_entry_fn, 0, 0);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_linux_release_mem (void)
+{
+  grub_free (linux_args);
+  linux_args = 0;
+
+  if (linux_addr && grub_ieee1275_release (linux_addr, linux_size))
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Can not release memory");
+
+  if (initrd_addr && grub_ieee1275_release (initrd_addr, initrd_size))
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Can not release memory");
+
+  linux_addr = 0;
+  initrd_addr = 0;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_linux_unload (void)
+{
+  grub_err_t err;
+
+  err = grub_linux_release_mem ();
+  grub_dl_unref (my_mod);
+
+  loaded = 0;
+
+  return err;
+}
+
+static grub_err_t
+grub_linux_load32 (grub_elf_t elf)
+{
+  Elf32_Addr entry;
+  int found_addr = 0;
+
+  /* Linux's entry point incorrectly contains a virtual address.  */
+  entry = elf->ehdr.ehdr32.e_entry & ~ELF32_LOADMASK;
+  if (entry == 0)
+    entry = 0x01400000;
+
+  linux_size = grub_elf32_size (elf);
+  if (linux_size == 0)
+    return grub_errno;
+  /* Pad it; the kernel scribbles over memory beyond its load address.  */
+  linux_size += 0x100000;
+
+  /* On some systems, firmware occupies the memory we're trying to use.
+   * Happily, Linux can be loaded anywhere (it relocates itself).  Iterate
+   * until we find an open area.  */
+  for (linux_addr = entry; linux_addr < entry + 200 * 0x100000; linux_addr += 0x100000)
+    {
+      grub_dprintf ("loader", "Attempting to claim at 0x%x, size 0x%x.\n",
+                   linux_addr, linux_size);
+      found_addr = grub_claimmap (linux_addr, linux_size);
+      if (found_addr != -1)
+       break;
+    }
+  if (found_addr == -1)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Could not claim memory.");
+
+  /* Now load the segments into the area we claimed.  */
+  auto grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr);
+  grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr)
+    {
+      /* Linux's program headers incorrectly contain virtual addresses.
+       * Translate those to physical, and offset to the area we claimed.  */
+      *addr = (phdr->p_paddr & ~ELF32_LOADMASK) + linux_addr;
+      return 0;
+    }
+  return grub_elf32_load (elf, offset_phdr, 0, 0);
+}
+
+static grub_err_t
+grub_linux_load64 (grub_elf_t elf)
+{
+  Elf64_Addr entry;
+  int found_addr = 0;
+
+  /* Linux's entry point incorrectly contains a virtual address.  */
+  entry = elf->ehdr.ehdr64.e_entry & ~ELF64_LOADMASK;
+  if (entry == 0)
+    entry = 0x01400000;
+
+  linux_size = grub_elf64_size (elf);
+  if (linux_size == 0)
+    return grub_errno;
+  /* Pad it; the kernel scribbles over memory beyond its load address.  */
+  linux_size += 0x100000;
+
+  /* On some systems, firmware occupies the memory we're trying to use.
+   * Happily, Linux can be loaded anywhere (it relocates itself).  Iterate
+   * until we find an open area.  */
+  for (linux_addr = entry; linux_addr < entry + 200 * 0x100000; linux_addr += 0x100000)
+    {
+      grub_dprintf ("loader", "Attempting to claim at 0x%x, size 0x%x.\n",
+                   linux_addr, linux_size);
+      found_addr = grub_claimmap (linux_addr, linux_size);
+      if (found_addr != -1)
+       break;
+    }
+  if (found_addr == -1)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Could not claim memory.");
+
+  /* Now load the segments into the area we claimed.  */
+  auto grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr);
+  grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr)
+    {
+      /* Linux's program headers incorrectly contain virtual addresses.
+       * Translate those to physical, and offset to the area we claimed.  */
+      *addr = (phdr->p_paddr & ~ELF64_LOADMASK) + linux_addr;
+      return 0;
+    }
+  return grub_elf64_load (elf, offset_phdr, 0, 0);
+}
+
+void
+grub_rescue_cmd_linux (int argc, char *argv[])
+{
+  grub_elf_t elf = 0;
+  int i;
+  int size;
+  char *dest;
+
+  grub_dl_ref (my_mod);
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
+      goto out;
+    }
+
+  elf = grub_elf_open (argv[0]);
+  if (! elf)
+    goto out;
+
+  if (elf->ehdr.ehdr32.e_type != ET_EXEC)
+    {
+      grub_error (GRUB_ERR_UNKNOWN_OS,
+                 "This ELF file is not of the right type\n");
+      goto out;
+    }
+
+  /* Release the previously used memory.  */
+  grub_loader_unset ();
+
+  if (grub_elf_is_elf32 (elf))
+    grub_linux_load32 (elf);
+  else
+  if (grub_elf_is_elf64 (elf))
+    grub_linux_load64 (elf);
+  else
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "Unknown ELF class");
+      goto out;
+    }
+
+  size = sizeof ("BOOT_IMAGE=") + grub_strlen (argv[0]);
+  for (i = 0; i < argc; i++)
+    size += grub_strlen (argv[i]) + 1;
+
+  linux_args = grub_malloc (size);
+  if (! linux_args)
+    goto out;
+
+  /* Specify the boot file.  */
+  dest = grub_stpcpy (linux_args, "BOOT_IMAGE=");
+  dest = grub_stpcpy (dest, argv[0]);
+  
+  for (i = 1; i < argc; i++)
+    {
+      *dest++ = ' ';
+      dest = grub_stpcpy (dest, argv[i]);
+    }
+
+out:
+
+  if (elf)
+    grub_elf_close (elf);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_linux_release_mem ();
+      grub_dl_unref (my_mod);
+      loaded = 0;
+    }
+  else
+    {
+      grub_loader_set (grub_linux_boot, grub_linux_unload, 1);
+      initrd_addr = 0;
+      loaded = 1;
+    }
+}
+
+void
+grub_rescue_cmd_initrd (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  grub_ssize_t size;
+  grub_addr_t first_addr;
+  grub_addr_t addr;
+  int found_addr = 0;
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no initrd 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;
+
+  first_addr = linux_addr + linux_size;
+  size = grub_file_size (file);
+
+  /* Attempt to claim at a series of addresses until successful in
+     the same way that grub_rescue_cmd_linux does.  */
+  for (addr = first_addr; addr < first_addr + 200 * 0x100000; addr += 0x100000) 
+    {
+      grub_dprintf ("loader", "Attempting to claim at 0x%x, size 0x%x.\n", 
+                   addr, size);
+      found_addr = grub_claimmap (addr, size);
+      if (found_addr != -1)
+       break;
+    }
+
+  if (found_addr == -1)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, "Can not claim memory");
+      goto fail;
+    }
+
+  grub_dprintf ("loader", "Loading initrd at 0x%x, size 0x%x\n", addr, size);
+
+  if (grub_file_read (file, (void *) addr, size) != size)
+    {
+      grub_ieee1275_release (addr, size);
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+
+  initrd_addr = addr;
+  initrd_size = size;
+
+ fail:
+  if (file)
+    grub_file_close (file);
+}
+
+
+\f
+GRUB_MOD_INIT(linux)
+{
+  grub_rescue_register_command ("linux", grub_rescue_cmd_linux,
+                               "load a linux kernel");
+  grub_rescue_register_command ("initrd", grub_rescue_cmd_initrd,
+                               "load an initrd");
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI(linux)
+{
+  grub_rescue_unregister_command ("linux");
+  grub_rescue_unregister_command ("initrd");
+}
diff --git a/loader/powerpc/ieee1275/linux_normal.c b/loader/powerpc/ieee1275/linux_normal.c
new file mode 100644 (file)
index 0000000..619eb33
--- /dev/null
@@ -0,0 +1,60 @@
+/* linux_normal.c - boot Linux */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/machine/loader.h>
+
+static const struct grub_arg_option options[] =
+  {
+    {0, 0, 0, 0, 0, 0}
+  };
+
+static grub_err_t
+grub_cmd_linux (struct grub_arg_list *state  __attribute__ ((unused)),
+               int argc, char **args)
+{
+  grub_rescue_cmd_linux (argc, args);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_initrd (struct grub_arg_list *state  __attribute__ ((unused)),
+                int argc, char **args)
+{
+  grub_rescue_cmd_initrd (argc, args);
+  return GRUB_ERR_NONE;
+}
+
+GRUB_MOD_INIT(linux_normal)
+{
+  (void) mod;
+  grub_register_command ("linux", grub_cmd_linux, GRUB_COMMAND_FLAG_BOTH,
+                        "linux [KERNELARGS...]",
+                        "Loads linux", options);
+  grub_register_command ("initrd", grub_cmd_initrd, GRUB_COMMAND_FLAG_BOTH,
+                        "initrd FILE",
+                        "Loads initrd", options);
+}
+
+GRUB_MOD_FINI(linux_normal)
+{
+  grub_unregister_command ("linux");
+  grub_unregister_command ("initrd");
+}
diff --git a/mkinstalldirs b/mkinstalldirs
new file mode 100755 (executable)
index 0000000..ef7e16f
--- /dev/null
@@ -0,0 +1,161 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+
+scriptversion=2006-05-11.19
+
+# Original author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain.
+#
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+nl='
+'
+IFS=" ""       $nl"
+errstatus=0
+dirmode=
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ...
+
+Create each directory DIR (with mode MODE, if specified), including all
+leading file name components.
+
+Report bugs to <bug-automake@gnu.org>."
+
+# process command line arguments
+while test $# -gt 0 ; do
+  case $1 in
+    -h | --help | --h*)         # -h for help
+      echo "$usage"
+      exit $?
+      ;;
+    -m)                         # -m PERM arg
+      shift
+      test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
+      dirmode=$1
+      shift
+      ;;
+    --version)
+      echo "$0 $scriptversion"
+      exit $?
+      ;;
+    --)                         # stop option processing
+      shift
+      break
+      ;;
+    -*)                         # unknown option
+      echo "$usage" 1>&2
+      exit 1
+      ;;
+    *)                          # first non-opt arg
+      break
+      ;;
+  esac
+done
+
+for file
+do
+  if test -d "$file"; then
+    shift
+  else
+    break
+  fi
+done
+
+case $# in
+  0) exit 0 ;;
+esac
+
+# Solaris 8's mkdir -p isn't thread-safe.  If you mkdir -p a/b and
+# mkdir -p a/c at the same time, both will detect that a is missing,
+# one will create a, then the other will try to create a and die with
+# a "File exists" error.  This is a problem when calling mkinstalldirs
+# from a parallel make.  We use --version in the probe to restrict
+# ourselves to GNU mkdir, which is thread-safe.
+case $dirmode in
+  '')
+    if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+      echo "mkdir -p -- $*"
+      exec mkdir -p -- "$@"
+    else
+      # On NextStep and OpenStep, the `mkdir' command does not
+      # recognize any option.  It will interpret all options as
+      # directories to create, and then abort because `.' already
+      # exists.
+      test -d ./-p && rmdir ./-p
+      test -d ./--version && rmdir ./--version
+    fi
+    ;;
+  *)
+    if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 &&
+       test ! -d ./--version; then
+      echo "mkdir -m $dirmode -p -- $*"
+      exec mkdir -m "$dirmode" -p -- "$@"
+    else
+      # Clean up after NextStep and OpenStep mkdir.
+      for d in ./-m ./-p ./--version "./$dirmode";
+      do
+        test -d $d && rmdir $d
+      done
+    fi
+    ;;
+esac
+
+for file
+do
+  case $file in
+    /*) pathcomp=/ ;;
+    *)  pathcomp= ;;
+  esac
+  oIFS=$IFS
+  IFS=/
+  set fnord $file
+  shift
+  IFS=$oIFS
+
+  for d
+  do
+    test "x$d" = x && continue
+
+    pathcomp=$pathcomp$d
+    case $pathcomp in
+      -*) pathcomp=./$pathcomp ;;
+    esac
+
+    if test ! -d "$pathcomp"; then
+      echo "mkdir $pathcomp"
+
+      mkdir "$pathcomp" || lasterr=$?
+
+      if test ! -d "$pathcomp"; then
+       errstatus=$lasterr
+      else
+       if test ! -z "$dirmode"; then
+         echo "chmod $dirmode $pathcomp"
+         lasterr=
+         chmod "$dirmode" "$pathcomp" || lasterr=$?
+
+         if test ! -z "$lasterr"; then
+           errstatus=$lasterr
+         fi
+       fi
+      fi
+    fi
+
+    pathcomp=$pathcomp/
+  done
+done
+
+exit $errstatus
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/normal/arg.c b/normal/arg.c
new file mode 100644 (file)
index 0000000..52c11d3
--- /dev/null
@@ -0,0 +1,419 @@
+/* arg.c - argument parser */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,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/>.
+ */
+
+#include <grub/arg.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/term.h>
+
+/* Built-in parser for default options.  */
+#define SHORT_ARG_HELP -100
+#define SHORT_ARG_USAGE        -101
+
+static const struct grub_arg_option help_options[] =
+  {
+    {"help", SHORT_ARG_HELP, 0,
+     "display this help and exit", 0, ARG_TYPE_NONE},
+    {"usage", SHORT_ARG_USAGE, 0,
+     "display the usage of this command and exit", 0, ARG_TYPE_NONE},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+static struct grub_arg_option *
+find_short (const struct grub_arg_option *options, char c)
+{
+  struct grub_arg_option *found = 0;
+  auto struct grub_arg_option *fnd_short (const struct grub_arg_option *opt);
+
+  struct grub_arg_option *fnd_short (const struct grub_arg_option *opt)
+    {
+      while (opt->doc)
+       {
+         if (opt->shortarg == c)
+           return (struct grub_arg_option *) opt;
+         opt++;
+       }
+      return 0;
+    }
+
+  if (options)
+    found = fnd_short (options);
+  
+  if (! found)
+    {
+      switch (c)
+       {
+       case 'h':
+         found = (struct grub_arg_option *) help_options;
+         break;
+
+       case 'u':
+         found = (struct grub_arg_option *) (help_options + 1);
+         break;
+
+       default:
+         break;
+       }
+    }
+    
+  return found;
+}
+
+static char *
+find_long_option (char *s)
+{
+  char *argpos = grub_strchr (s, '=');
+
+  if (argpos)
+    {
+      *argpos = '\0';
+      return ++argpos;
+    }
+  return 0;
+}
+
+static struct grub_arg_option *
+find_long (const struct grub_arg_option *options, char *s)
+{
+  struct grub_arg_option *found = 0;
+  auto struct grub_arg_option *fnd_long (const struct grub_arg_option *opt);
+
+  struct grub_arg_option *fnd_long (const struct grub_arg_option *opt)
+    {
+      while (opt->doc)
+       {
+         if (opt->longarg && ! grub_strcmp (opt->longarg, s))
+           return (struct grub_arg_option *) opt;
+         opt++;
+       }
+      return 0;
+    }
+
+  if (options)
+    found = fnd_long (options);
+  
+  if (! found)
+    found = fnd_long (help_options);
+    
+  return found;
+}
+
+static void
+show_usage (grub_command_t cmd)
+{
+  grub_printf ("Usage: %s\n", cmd->summary);
+}
+
+void
+grub_arg_show_help (grub_command_t cmd)
+{
+  auto void showargs (const struct grub_arg_option *opt);
+  int h_is_used = 0;
+  int u_is_used = 0;
+  
+  auto void showargs (const struct grub_arg_option *opt)
+    {
+      for (; opt->doc; opt++)
+       {
+         int spacing = 20;
+         
+         if (opt->shortarg && grub_isgraph (opt->shortarg))
+           grub_printf ("-%c%c ", opt->shortarg, opt->longarg ? ',':' ');
+         else if (opt->shortarg == SHORT_ARG_HELP && ! h_is_used)
+           grub_printf ("-h, ");
+         else if (opt->shortarg == SHORT_ARG_USAGE && ! u_is_used)
+           grub_printf ("-u, ");
+         else
+           grub_printf ("    ");
+         
+         if (opt->longarg)
+           {
+             grub_printf ("--%s", opt->longarg);
+             spacing -= grub_strlen (opt->longarg) + 2;
+             
+             if (opt->arg)
+               {
+                 grub_printf ("=%s", opt->arg);
+                 spacing -= grub_strlen (opt->arg) + 1;
+               }
+           }
+
+         const char *doc = opt->doc;
+         for (;;)
+           {
+             while (spacing-- > 0)
+               grub_putchar (' ');
+
+             while (*doc && *doc != '\n')
+               grub_putchar (*doc++);
+             grub_putchar ('\n');
+
+             if (! *doc)
+               break;
+             doc++;
+             spacing = 4 + 20;
+           }
+
+         switch (opt->shortarg)
+           {
+           case 'h':
+             h_is_used = 1;
+             break;
+
+           case 'u':
+             u_is_used = 1;
+             break;
+
+           default:
+             break;
+           }
+       }
+    }  
+
+  show_usage (cmd);
+  grub_printf ("%s\n\n", cmd->description);
+  if (cmd->options)
+    showargs (cmd->options);
+  showargs (help_options);
+#if 0
+  grub_printf ("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT);
+#endif
+}
+
+
+static int
+parse_option (grub_command_t cmd, int key, char *arg, struct grub_arg_list *usr)
+{
+  switch (key)
+    {
+    case SHORT_ARG_HELP:
+      grub_arg_show_help (cmd);
+      return -1;
+      
+    case SHORT_ARG_USAGE:
+      show_usage (cmd);
+      return -1;
+
+    default:
+      {
+       int found = -1;
+       int i = 0;
+       const struct grub_arg_option *opt = cmd->options;
+
+       while (opt->doc)
+         {
+           if (opt->shortarg && key == opt->shortarg)
+             {
+               found = i;
+               break;
+             }
+           opt++;
+           i++;
+         }
+       
+       if (found == -1)
+         return -1;
+
+       usr[found].set = 1;
+       usr[found].arg = arg;
+      }
+    }
+  
+  return 0;
+}
+
+int
+grub_arg_parse (grub_command_t cmd, int argc, char **argv,
+               struct grub_arg_list *usr, char ***args, int *argnum)
+{
+  int curarg;
+  char *longarg = 0;
+  int complete = 0;
+  char **argl = 0;
+  int num = 0;
+  auto grub_err_t add_arg (char *s);
+
+  grub_err_t add_arg (char *s)
+    {
+      argl = grub_realloc (argl, (++num) * sizeof (char *));
+      if (! argl)
+       return grub_errno;
+      argl[num - 1] = s;
+      return 0;
+    }
+
+
+  for (curarg = 0; curarg < argc; curarg++)
+    {
+      char *arg = argv[curarg];
+      struct grub_arg_option *opt;
+      char *option = 0;
+
+      /* No option is used.  */
+      if (arg[0] != '-' || grub_strlen (arg) == 1)
+       {
+         if (add_arg (arg) != 0)
+           goto fail;
+  
+         continue;
+       }
+
+      /* One or more short options.  */
+      if (arg[1] != '-')
+       {
+         char *curshort = arg + 1;
+
+         while (1)
+           {
+             opt = find_short (cmd->options, *curshort);
+             if (! opt)
+               {
+                 grub_error (GRUB_ERR_BAD_ARGUMENT,
+                             "Unknown argument `-%c'\n", *curshort);
+                 goto fail;
+               }
+             
+             curshort++;
+
+             /* Parse all arguments here except the last one because
+                it can have an argument value.  */
+             if (*curshort)
+               {
+                 if (parse_option (cmd, opt->shortarg, 0, usr) || grub_errno)
+                   goto fail;
+               }
+             else
+               {
+                 if (opt->type != ARG_TYPE_NONE)
+                   {
+                     if (curarg + 1 < argc)
+                       {
+                         char *nextarg = argv[curarg + 1];
+                         if (!(opt->flags & GRUB_ARG_OPTION_OPTIONAL) 
+                             || (grub_strlen (nextarg) < 2 || nextarg[0] != '-'))
+                           option = argv[++curarg];
+                       }
+                   }
+                 break;
+               }
+           }
+         
+       }
+      else /* The argument starts with "--".  */
+       {
+         /* If the argument "--" is used just pass the other
+            arguments.  */
+         if (grub_strlen (arg) == 2)
+           {
+             for (curarg++; curarg < argc; curarg++)
+               if (add_arg (argv[curarg]) != 0)
+                 goto fail;
+             break;
+           }
+
+         longarg = (char *) grub_strdup (arg);
+         if (! longarg)
+           goto fail;
+
+         option = find_long_option (longarg);
+         arg = longarg;
+
+         opt = find_long (cmd->options, arg + 2);
+         if (! opt)
+           {
+             grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown argument `%s'\n", arg);
+             goto fail;
+           }
+       }
+
+      if (! (opt->type == ARG_TYPE_NONE 
+            || (! option && (opt->flags & GRUB_ARG_OPTION_OPTIONAL))))
+       {
+         if (! option)
+           {
+             grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                         "Missing mandatory option for `%s'\n", opt->longarg);
+             goto fail;
+           }
+         
+         switch (opt->type)
+           {
+           case ARG_TYPE_NONE:
+             /* This will never happen.  */
+             break;
+             
+           case ARG_TYPE_STRING:
+                 /* No need to do anything.  */
+             break;
+             
+           case ARG_TYPE_INT:
+             {
+               char *tail;
+               
+               grub_strtoul (option, &tail, 0);
+               if (tail == 0 || tail == option || *tail != '\0' || grub_errno)
+                 {
+                   grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                               "The argument `%s' requires an integer.", 
+                               arg);
+
+                   goto fail;
+                 }
+               break;
+             }
+             
+           case ARG_TYPE_DEVICE:
+           case ARG_TYPE_DIR:
+           case ARG_TYPE_FILE:
+           case ARG_TYPE_PATHNAME:
+             /* XXX: Not implemented.  */
+             break;
+           }
+         if (parse_option (cmd, opt->shortarg, option, usr) || grub_errno)
+           goto fail;
+       }
+      else
+       {
+         if (option)
+           {
+             grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                         "A value was assigned to the argument `%s' while it "
+                         "doesn't require an argument\n", arg);
+             goto fail;
+           }
+
+         if (parse_option (cmd, opt->shortarg, 0, usr) || grub_errno)
+           goto fail;
+       }
+      grub_free (longarg);
+      longarg = 0;
+    }      
+
+  complete = 1;
+
+  *args = argl;
+  *argnum = num;
+
+ fail:
+  grub_free (longarg);
+  return complete;
+}
diff --git a/normal/cmdline.c b/normal/cmdline.c
new file mode 100644 (file)
index 0000000..8ca83f6
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/misc.h>
+#include <grub/term.h>
+#include <grub/err.h>
+#include <grub/types.h>
+#include <grub/mm.h>
+#include <grub/partition.h>
+#include <grub/disk.h>
+#include <grub/file.h>
+#include <grub/env.h>
+
+static char *kill_buf;
+
+static int hist_size;
+static char **hist_lines = 0;
+static int hist_pos = 0;
+static int hist_end = 0;
+static int hist_used = 0;
+
+grub_err_t
+grub_set_history (int newsize)
+{
+  char **old_hist_lines = hist_lines;
+  hist_lines = grub_malloc (sizeof (char *) * newsize);
+
+  /* Copy the old lines into the new buffer.  */
+  if (old_hist_lines)
+    {
+      /* Remove the lines that don't fit in the new buffer.  */
+      if (newsize < hist_used)
+       {
+         int i;
+         int delsize = hist_used - newsize;
+         hist_used = newsize;
+
+         for (i = 1; i <= delsize; i++)
+           {
+             int pos = hist_end - i;
+             if (pos < 0)
+               pos += hist_size;
+             grub_free (old_hist_lines[pos]);
+           }
+
+         hist_end -= delsize;
+         if (hist_end < 0)
+           hist_end += hist_size;
+       }
+
+      if (hist_pos < hist_end)
+       grub_memmove (hist_lines, old_hist_lines + hist_pos,
+                     (hist_end - hist_pos) * sizeof (char *));
+      else if (hist_used)
+       {
+         /* Copy the older part.  */
+         grub_memmove (hist_lines, old_hist_lines + hist_pos,
+                       (hist_size - hist_pos) * sizeof (char *));
+         
+         /* Copy the newer part. */
+         grub_memmove (hist_lines + hist_size - hist_pos, old_hist_lines,
+                       hist_end * sizeof (char *));
+       }
+    }
+
+  grub_free (old_hist_lines);
+
+  hist_size = newsize;
+  hist_pos = 0;
+  hist_end = hist_used;
+  return 0;
+}
+
+/* Get the entry POS from the history where `0' is the newest
+   entry.  */
+static char *
+grub_history_get (int pos)
+{
+  pos = (hist_pos + pos) % hist_size;
+  return hist_lines[pos];
+}
+
+
+/* Insert a new history line S on the top of the history.  */
+static void
+grub_history_add (char *s)
+{
+  /* Remove the oldest entry in the history to make room for a new
+     entry.  */
+  if (hist_used + 1 > hist_size)
+    {
+      hist_end--;
+      if (hist_end < 0)
+       hist_end = hist_size + hist_end;
+
+      grub_free (hist_lines[hist_end]);
+    }
+  else
+    hist_used++;
+
+  /* Move to the next position.  */
+  hist_pos--;
+  if (hist_pos < 0)
+    hist_pos = hist_size + hist_pos;
+
+  /* Insert into history.  */
+  hist_lines[hist_pos] = grub_strdup (s);
+}
+
+/* Replace the history entry on position POS with the string S.  */
+static void
+grub_history_replace (int pos, char *s)
+{
+  pos = (hist_pos + pos) % hist_size;
+  grub_free (hist_lines[pos]);
+  hist_lines[pos] = grub_strdup (s);
+}
+
+void
+grub_cmdline_run (int nested)
+{
+  grub_normal_init_page ();
+  grub_setcursor (1);
+  
+  grub_printf ("\
+ [ Minimal BASH-like line editing is supported. For the first word, TAB\n\
+   lists possible command completions. Anywhere else TAB lists possible\n\
+   device/file completions.%s ]\n\n",
+              nested ? " ESC at any time exits." : "");
+  
+  while (1)
+    {
+      static char cmdline[GRUB_MAX_CMDLINE];
+
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+      cmdline[0] = '\0';
+      
+      if (! grub_cmdline_get ("grub> ", cmdline, sizeof (cmdline), 0, 1)
+         && nested)
+       return;
+
+      if (! *cmdline)
+       continue;
+
+      grub_command_execute (cmdline, 1);
+    }
+}
+
+/* A completion hook to print items.  */
+static void
+print_completion (const char *item, grub_completion_type_t type, int count)
+{
+  if (count == 0)
+    {
+      /* If this is the first time, print a label.  */
+      const char *what;
+
+      switch (type)
+       {
+       case GRUB_COMPLETION_TYPE_COMMAND:
+         what = "commands";
+         break;
+       case GRUB_COMPLETION_TYPE_DEVICE:
+         what = "devices";
+         break;
+       case GRUB_COMPLETION_TYPE_FILE:
+         what = "files";
+         break;
+       case GRUB_COMPLETION_TYPE_PARTITION:
+         what = "partitions";
+         break;
+       case GRUB_COMPLETION_TYPE_ARGUMENT:
+         what = "arguments";
+         break;
+       default:
+         what = "things";
+         break;
+       }
+           
+      grub_printf ("\nPossible %s are:\n", what);
+    }
+
+  if (type == GRUB_COMPLETION_TYPE_PARTITION)
+    {
+      grub_normal_print_device_info (item);
+      grub_errno = GRUB_ERR_NONE;
+    }
+  else
+    grub_printf (" %s", item);
+}
+
+/* Get a command-line. If ECHO_CHAR is not zero, echo it instead of input
+   characters. If READLINE is non-zero, readline-like key bindings are
+   available. If ESC is pushed, return zero, otherwise return non-zero.  */
+/* FIXME: The dumb interface is not supported yet.  */
+int
+grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
+                 int echo_char, int readline)
+{
+  unsigned xpos, ypos, ystart;
+  grub_size_t lpos, llen;
+  grub_size_t plen;
+  char buf[max_len];
+  int key;
+  int histpos = 0;
+  auto void cl_insert (const char *str);
+  auto void cl_delete (unsigned len);
+  auto void cl_print (int pos, int c);
+  auto void cl_set_pos (void);
+
+  void cl_set_pos (void)
+    {
+      xpos = (plen + lpos) % 79;
+      ypos = ystart + (plen + lpos) / 79;
+      grub_gotoxy (xpos, ypos);
+      
+      grub_refresh ();
+    }
+  
+  void cl_print (int pos, int c)
+    {
+      char *p;
+
+      for (p = buf + pos; *p; p++)
+       {
+         if (xpos++ > 78)
+           {
+             grub_putchar ('\n');
+             
+             xpos = 1;
+             if (ypos == (unsigned) (grub_getxy () & 0xFF))
+               ystart--;
+             else
+               ypos++;
+           }
+
+         if (c)
+           grub_putchar (c);
+         else
+           grub_putchar (*p);
+       }
+    }
+  
+  void cl_insert (const char *str)
+    {
+      grub_size_t len = grub_strlen (str);
+
+      if (len + llen < max_len)
+       {
+         grub_memmove (buf + lpos + len, buf + lpos, llen - lpos + 1);
+         grub_memmove (buf + lpos, str, len);
+
+         llen += len;
+         lpos += len;
+         cl_print (lpos - len, echo_char);
+         cl_set_pos ();
+       }
+      
+      grub_refresh ();
+    }
+
+  void cl_delete (unsigned len)
+    {
+      if (lpos + len <= llen)
+       {
+         grub_size_t saved_lpos = lpos;
+
+         lpos = llen - len;
+         cl_set_pos ();
+         cl_print (lpos, ' ');
+         lpos = saved_lpos;
+         cl_set_pos ();
+         
+         grub_memmove (buf + lpos, buf + lpos + len, llen - lpos + 1);
+         llen -= len;
+         cl_print (lpos, echo_char);
+         cl_set_pos ();
+       }
+      
+      grub_refresh ();
+    }
+  
+  plen = grub_strlen (prompt);
+  lpos = llen = 0;
+  buf[0] = '\0';
+
+  if ((grub_getxy () >> 8) != 0)
+    grub_putchar ('\n');
+  
+  grub_printf (prompt);
+  
+  xpos = plen;
+  ystart = ypos = (grub_getxy () & 0xFF);
+  
+  cl_insert (cmdline);
+
+  if (hist_used == 0)
+    grub_history_add (buf);
+
+  while ((key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && key != '\r')
+    {
+      if (readline)
+       {
+         switch (key)
+           {
+           case 1:     /* Ctrl-a */
+             lpos = 0;
+             cl_set_pos ();
+             break;
+
+           case 2:     /* Ctrl-b */
+             if (lpos > 0)
+               {
+                 lpos--;
+                 cl_set_pos ();
+               }
+             break;
+
+           case 5:     /* Ctrl-e */
+             lpos = llen;
+             cl_set_pos ();
+             break;
+
+           case 6:     /* Ctrl-f */
+             if (lpos < llen)
+               {
+                 lpos++;
+                 cl_set_pos ();
+               }
+             break;
+
+           case 9:     /* Ctrl-i or TAB */
+             {
+               char *insert;
+               int restore;
+               
+               /* Backup the next character and make it 0 so it will
+                  be easy to use string functions.  */
+               char backup = buf[lpos];
+               buf[lpos] = '\0';
+               
+
+               insert = grub_normal_do_completion (buf, &restore,
+                                                   print_completion);
+               /* Restore the original string.  */
+               buf[lpos] = backup;
+               
+               if (restore)
+                 {
+                   /* Restore the prompt.  */
+                   grub_printf ("\n%s%s", prompt, buf);
+                   xpos = plen;
+                   ystart = ypos = (grub_getxy () & 0xFF);
+                 }
+
+               if (insert)
+                 {
+                   cl_insert (insert);
+                   grub_free (insert);
+                 }
+             }
+             break;
+
+           case 11:    /* Ctrl-k */
+             if (lpos < llen)
+               {
+                 if (kill_buf)
+                   grub_free (kill_buf);
+
+                 kill_buf = grub_strdup (buf + lpos);
+                 grub_errno = GRUB_ERR_NONE;
+
+                 cl_delete (llen - lpos);
+               }
+             break;
+
+           case 14:    /* Ctrl-n */
+             {
+               char *hist;
+
+               lpos = 0;
+
+               if (histpos > 0)
+                 {
+                   grub_history_replace (histpos, buf);
+                   histpos--;
+                 }
+
+               cl_delete (llen);
+               hist = grub_history_get (histpos);
+               cl_insert (hist);
+
+               break;
+             }
+           case 16:    /* Ctrl-p */
+             {
+               char *hist;
+
+               lpos = 0;
+
+               if (histpos < hist_used - 1)
+                 {
+                   grub_history_replace (histpos, buf);
+                   histpos++;
+                 }
+
+               cl_delete (llen);
+               hist = grub_history_get (histpos);
+
+               cl_insert (hist);
+             }
+             break;
+
+           case 21:    /* Ctrl-u */
+             if (lpos > 0)
+               {
+                 grub_size_t n = lpos;
+                 
+                 if (kill_buf)
+                   grub_free (kill_buf);
+
+                 kill_buf = grub_malloc (n + 1);
+                 grub_errno = GRUB_ERR_NONE;
+                 if (kill_buf)
+                   {
+                     grub_memcpy (kill_buf, buf, n);
+                     kill_buf[n] = '\0';
+                   }
+
+                 lpos = 0;
+                 cl_set_pos ();
+                 cl_delete (n);
+               }
+             break;
+
+           case 25:    /* Ctrl-y */
+             if (kill_buf)
+               cl_insert (kill_buf);
+             break;
+           }
+       }
+
+      switch (key)
+       {
+       case '\e':
+         return 0;
+
+       case '\b':
+         if (lpos > 0)
+           {
+             lpos--;
+             cl_set_pos ();
+           }
+          else
+            break;
+         /* fall through */
+         
+       case 4: /* Ctrl-d */
+         if (lpos < llen)
+           cl_delete (1);
+         break;
+
+       default:
+         if (grub_isprint (key))
+           {
+             char str[2];
+
+             str[0] = key;
+             str[1] = '\0';
+             cl_insert (str);
+           }
+         break;
+       }
+    }
+
+  grub_putchar ('\n');
+  grub_refresh ();
+
+  /* If ECHO_CHAR is NUL, remove leading spaces.  */
+  lpos = 0;
+  if (! echo_char)
+    while (buf[lpos] == ' ')
+      lpos++;
+
+  histpos = 0;
+  if (grub_strlen (buf) > 0)
+    {
+      grub_history_replace (histpos, buf);
+      grub_history_add ("");
+    }
+  
+  grub_memcpy (cmdline, buf + lpos, llen - lpos + 1);
+
+  return 1;
+}
diff --git a/normal/color.c b/normal/color.c
new file mode 100644 (file)
index 0000000..340e43a
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,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/misc.h>
+#include <grub/mm.h>
+#include <grub/normal.h>
+#include <grub/term.h>
+
+/* Borrowed from GRUB Legacy */
+static char *color_list[16] =
+{
+  "black",
+  "blue",
+  "green",
+  "cyan",
+  "red",
+  "magenta",
+  "brown",
+  "light-gray",
+  "dark-gray",
+  "light-blue",
+  "light-green",
+  "light-cyan",
+  "light-red",
+  "light-magenta",
+  "yellow",
+  "white"
+};
+
+static int
+parse_color_name (grub_uint8_t *ret, char *name)
+{
+  grub_uint8_t i;
+  for (i = 0; i < sizeof (color_list) / sizeof (*color_list); i++)
+    if (! grub_strcmp (name, color_list[i]))
+      {
+        *ret = i;
+        return 0;
+      }
+  return -1;
+}
+
+void
+grub_parse_color_name_pair (grub_uint8_t *ret, const char *name)
+{
+  grub_uint8_t fg, bg;
+  char *fg_name, *bg_name;
+
+  /* nothing specified by user */
+  if (name == NULL)
+    return;
+
+  fg_name = grub_strdup (name);
+  if (fg_name == NULL)
+    {
+      /* "out of memory" message was printed by grub_strdup() */
+      grub_wait_after_message ();
+      return;
+    }
+
+  bg_name = grub_strchr (fg_name, '/');
+  if (bg_name == NULL)
+    {
+      grub_printf ("Warning: syntax error (missing slash) in `%s'\n", fg_name);
+      grub_wait_after_message ();
+      goto free_and_return;
+    }
+
+  *(bg_name++) = '\0';
+
+  if (parse_color_name (&fg, fg_name) == -1)
+    {
+      grub_printf ("Warning: invalid foreground color `%s'\n", fg_name);
+      grub_wait_after_message ();
+      goto free_and_return;
+    }
+  if (parse_color_name (&bg, bg_name) == -1)
+    {
+      grub_printf ("Warning: invalid background color `%s'\n", bg_name);
+      grub_wait_after_message ();
+      goto free_and_return;
+    }
+
+  *ret = (bg << 4) | fg;
+
+free_and_return:
+  grub_free (fg_name);
+}
+
+/* Replace default `normal' colors with the ones specified by user (if any).  */
+char *
+grub_env_write_color_normal (struct grub_env_var *var __attribute__ ((unused)),
+                            const char *val)
+{
+  grub_uint8_t color_normal, color_highlight;
+
+  /* Use old settings in case grub_parse_color_name_pair() has no effect.  */
+  grub_getcolor (&color_normal, &color_highlight);
+
+  grub_parse_color_name_pair (&color_normal, val);
+
+  /* Reloads terminal `normal' and `highlight' colors.  */
+  grub_setcolor (color_normal, color_highlight);
+
+  /* Propagates `normal' color to terminal current color.  */
+  grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+
+  return grub_strdup (val);
+}
+
+/* Replace default `highlight' colors with the ones specified by user (if any).  */
+char *
+grub_env_write_color_highlight (struct grub_env_var *var __attribute__ ((unused)),
+                               const char *val)
+{
+  grub_uint8_t color_normal, color_highlight;
+
+  /* Use old settings in case grub_parse_color_name_pair() has no effect.  */
+  grub_getcolor (&color_normal, &color_highlight);
+
+  grub_parse_color_name_pair (&color_highlight, val);
+
+  /* Reloads terminal `normal' and `highlight' colors.  */
+  grub_setcolor (color_normal, color_highlight);
+
+  /* Propagates `normal' color to terminal current color.
+     Note: Using GRUB_TERM_COLOR_NORMAL here rather than
+     GRUB_TERM_COLOR_HIGHLIGHT is intentional.  We don't want to switch
+     to highlight state just because color was reloaded.  */
+  grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+
+  return grub_strdup (val);
+}
diff --git a/normal/command.c b/normal/command.c
new file mode 100644 (file)
index 0000000..6ca56da
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2005,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/term.h>
+#include <grub/env.h>
+#include <grub/dl.h>
+#include <grub/parser.h>
+#include <grub/script.h>
+
+static grub_command_t grub_command_list;
+
+grub_command_t
+grub_register_command (const char *name,
+                      grub_err_t (*func) (struct grub_arg_list *state,
+                                          int argc, char **args),
+                      unsigned flags,
+                      const char *summary,
+                      const char *description,
+                      const struct grub_arg_option *options)
+{
+  grub_command_t cmd, *p;
+
+  cmd = (grub_command_t) grub_malloc (sizeof (*cmd));
+  if (! cmd)
+    return 0;
+
+  cmd->name = grub_strdup (name);
+  if (! cmd->name)
+    {
+      grub_free (cmd);
+      return 0;
+    }
+  
+  cmd->func = func;
+  cmd->flags = flags;
+  cmd->summary = summary;
+  cmd->description = description;
+  cmd->options = options;
+  cmd->module_name = 0;
+
+  /* Keep the list sorted for simplicity.  */
+  p = &grub_command_list;
+  while (*p)
+    {
+      if (grub_strcmp ((*p)->name, name) >= 0)
+       break;
+
+      p = &((*p)->next);
+    }
+
+  if (*p && grub_strcmp ((*p)->name, name) == 0)
+    {
+      grub_command_t q;
+
+      q = *p;
+      if (q->flags & GRUB_COMMAND_FLAG_NOT_LOADED)
+       {
+         q->func = cmd->func;
+         q->flags = cmd->flags;
+         q->summary = cmd->summary;
+         q->description = cmd->description;
+         q->options = cmd->options;
+         grub_free (cmd->name);
+         grub_free (cmd->module_name);
+         grub_free (cmd);
+         cmd = q;
+       }
+      else
+       {
+         grub_free (cmd->name);
+         grub_free (cmd);
+         cmd = 0;
+       }
+    }
+  else
+    {
+      cmd->next = *p;
+      *p = cmd;
+    }
+
+  return cmd;
+}
+
+void
+grub_unregister_command (const char *name)
+{
+  grub_command_t *p, q;
+
+  for (p = &grub_command_list, q = *p; q; p = &(q->next), q = q->next)
+    if (grub_strcmp (name, q->name) == 0)
+      {
+        *p = q->next;
+       grub_free (q->name);
+       grub_free (q->module_name);
+        grub_free (q);
+        break;
+      }
+}
+
+grub_command_t
+grub_command_find (char *cmdline)
+{
+  char *first_space;
+  grub_command_t cmd;
+  int count = 0;
+  
+  first_space = grub_strchr (cmdline, ' ');
+  if (first_space)
+    *first_space = '\0';
+
+ again:
+  
+  for (cmd = grub_command_list; cmd; cmd = cmd->next)
+    if (grub_strcmp (cmdline, cmd->name) == 0)
+      break;
+
+  if (! cmd)
+    grub_error (GRUB_ERR_UNKNOWN_COMMAND, "unknown command `%s'", cmdline);
+  else if (cmd->flags & GRUB_COMMAND_FLAG_NOT_LOADED)
+    {
+      /* Automatically load the command.  */
+      if (count == 0)
+       {
+         grub_dl_t mod;
+         char *module_name;
+
+         module_name = grub_strdup (cmd->module_name);
+         if (module_name)
+           {
+             mod = grub_dl_load (module_name);
+             if (mod)
+               {
+                 grub_dl_ref (mod);
+                 count++;
+                 grub_free (module_name);
+                 goto again;
+               }
+
+             grub_free (module_name);
+           }
+       }
+
+      /* This module seems broken.  */
+      grub_unregister_command (cmdline);
+      grub_error (GRUB_ERR_UNKNOWN_COMMAND, "unknown command `%s'", cmdline);
+      cmd = 0;
+    }
+  
+  if (first_space)
+    *first_space = ' ';
+
+  return cmd;
+}
+
+int
+grub_iterate_commands (int (*iterate) (grub_command_t))
+{
+  grub_command_t cmd;
+  
+  for (cmd = grub_command_list; cmd; cmd = cmd->next)
+    if (iterate (cmd))
+      return 1;
+  
+  return 0;
+}
+
+int
+grub_command_execute (char *cmdline, int interactive)
+{
+  auto grub_err_t cmdline_get (char **s);
+  grub_err_t cmdline_get (char **s)
+    {
+      *s = grub_malloc (GRUB_MAX_CMDLINE);
+      *s[0] = '\0';
+      return grub_cmdline_get (">", *s, GRUB_MAX_CMDLINE, 0, 1);
+    }
+
+  grub_err_t ret = 0;
+  char *pager;
+  struct grub_script *parsed_script;
+  
+  /* Enable the pager if the environment pager is set to 1.  */
+  if (interactive)
+    pager = grub_env_get ("pager");
+  else
+    pager = NULL;
+  if (pager && (! grub_strcmp (pager, "1")))
+    grub_set_more (1);
+
+  /* Parse the script.  */
+  parsed_script = grub_script_parse (cmdline, cmdline_get);
+
+  if (parsed_script)
+    {
+      /* Execute the command(s).  */
+      grub_script_execute (parsed_script);
+
+      /* The parsed script was executed, throw it away.  */
+      grub_script_free (parsed_script);
+    }
+
+  if (pager && (! grub_strcmp (pager, "1")))
+    grub_set_more (0);
+
+  return ret;
+}
+
+static grub_err_t
+rescue_command (struct grub_arg_list *state __attribute__ ((unused)),
+               int argc __attribute__ ((unused)),
+               char **args __attribute__ ((unused)))
+{
+  grub_longjmp (grub_exit_env, 0);
+
+  /* Never reach here.  */
+  return 0;
+}
+
+
+static grub_err_t
+set_command (struct grub_arg_list *state __attribute__ ((unused)),
+            int argc, char **args)
+{
+  char *var;
+  char *val;
+
+  auto int print_env (struct grub_env_var *env);
+  int print_env (struct grub_env_var *env)
+    {
+      grub_printf ("%s=%s\n", env->name, env->value);
+      return 0;
+    }
+  
+  if (! argc)
+    {
+      grub_env_iterate (print_env);
+      return 0;
+    }
+  
+  var = args[0];
+  val = grub_strchr (var, '=');
+  if (! val)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "not an assignment");
+      return grub_errno;
+    }
+  
+  val[0] = 0;
+  grub_env_set (var, val + 1);
+  val[0] = '=';
+  return 0;
+}
+
+static grub_err_t
+unset_command (struct grub_arg_list *state __attribute__ ((unused)),
+              int argc, char **args)
+{
+  if (argc < 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                      "no environment variable specified");
+
+  grub_env_unset (args[0]);
+  return 0;
+}
+
+static grub_err_t
+export_command (struct grub_arg_list *state __attribute__ ((unused)),
+               int argc, char **args)
+{
+  if (argc < 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                      "no environment variable specified");
+
+  grub_env_export (args[0]);
+  return 0;
+}
+
+static grub_err_t
+insmod_command (struct grub_arg_list *state __attribute__ ((unused)),
+               int argc, char **args)
+{
+  char *p;
+  grub_dl_t mod;
+  
+  if (argc == 0)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
+
+  p = grub_strchr (args[0], '/');
+  if (! p)
+    mod = grub_dl_load (args[0]);
+  else
+    mod = grub_dl_load_file (args[0]);
+
+  if (mod)
+    grub_dl_ref (mod);
+
+  return 0;
+}
+
+static grub_err_t
+rmmod_command (struct grub_arg_list *state __attribute__ ((unused)),
+               int argc, char **args)
+{
+  grub_dl_t mod;
+  
+  if (argc == 0)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
+  
+  mod = grub_dl_get (args[0]);
+  if (! mod)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such module");
+
+  if (! grub_dl_unref (mod))
+    grub_dl_unload (mod);
+
+  return 0;
+}
+
+static grub_err_t
+lsmod_command (struct grub_arg_list *state __attribute__ ((unused)),
+              int argc __attribute__ ((unused)),
+              char **args __attribute__ ((unused)))
+{
+  auto int print_module (grub_dl_t mod);
+
+  int print_module (grub_dl_t mod)
+    {
+      grub_dl_dep_t dep;
+      
+      grub_printf ("%s\t%d\t\t", mod->name, mod->ref_count);
+      for (dep = mod->dep; dep; dep = dep->next)
+       {
+         if (dep != mod->dep)
+           grub_putchar (',');
+
+         grub_printf ("%s", dep->mod->name);
+       }
+      grub_putchar ('\n');
+      grub_refresh ();
+
+      return 0;
+    }
+
+  grub_printf ("Name\tRef Count\tDependencies\n");
+  grub_dl_iterate (print_module);
+  return 0;
+}
+
+void
+grub_command_init (void)
+{
+  grub_register_command ("rescue", rescue_command, GRUB_COMMAND_FLAG_BOTH,
+                        "rescue", "Go back to the rescue mode.", 0);
+
+  grub_register_command ("set", set_command, GRUB_COMMAND_FLAG_BOTH,
+                        "set [ENVVAR=VALUE]",
+                        "Set an environment variable.", 0);
+
+  grub_register_command ("unset", unset_command, GRUB_COMMAND_FLAG_BOTH,
+                        "unset ENVVAR", "Remove an environment variable.", 0);
+
+  grub_register_command ("export", export_command, GRUB_COMMAND_FLAG_BOTH,
+                        "export ENVVAR", "Export a variable.", 0);
+
+  grub_register_command ("insmod", insmod_command, GRUB_COMMAND_FLAG_BOTH,
+                        "insmod MODULE",
+                        "Insert a module. The argument can be a file or a module name.",
+                        0);
+
+  grub_register_command ("rmmod", rmmod_command, GRUB_COMMAND_FLAG_BOTH,
+                        "rmmod MODULE", "Remove a module.", 0);
+
+  grub_register_command ("lsmod", lsmod_command, GRUB_COMMAND_FLAG_BOTH,
+                        "lsmod", "Show loaded modules.", 0);
+}
diff --git a/normal/completion.c b/normal/completion.c
new file mode 100644 (file)
index 0000000..fb38f28
--- /dev/null
@@ -0,0 +1,493 @@
+/* completion.c - complete a command, a disk, a partition or a file */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/partition.h>
+#include <grub/disk.h>
+#include <grub/file.h>
+#include <grub/parser.h>
+
+/* The current word.  */
+static char *current_word;
+
+/* The matched string.  */
+static char *match;
+
+/* The count of candidates.  */
+static int num_found;
+
+/* The string to be appended.  */
+static const char *suffix;
+
+/* The callback function to print items.  */
+static void (*print_func) (const char *, grub_completion_type_t, int);
+
+/* The state the command line is in.  */
+static grub_parser_state_t cmdline_state;
+\f
+
+/* Add a string to the list of possible completions. COMPLETION is the
+   string that should be added. EXTRA will be appended if COMPLETION
+   matches uniquely. The type TYPE specifies what kind of data is added.  */
+static int
+add_completion (const char *completion, const char *extra,
+               grub_completion_type_t type)
+{
+  if (grub_strncmp (current_word, completion, grub_strlen (current_word)) == 0)
+    {
+      num_found++;
+
+      switch (num_found)
+       {
+       case 1:
+         match = grub_strdup (completion);
+         if (! match)
+           return 1;
+         suffix = extra;
+         break;
+
+       case 2:
+         if (print_func)
+           print_func (match, type, 0);
+         
+         /* Fall through.  */
+
+       default:
+         {
+           char *s = match;
+           const char *t = completion;
+
+           if (print_func)
+             print_func (completion, type, num_found - 1);
+                           
+           /* Detect the matched portion.  */
+           while (*s && *t && *s == *t)
+             {
+               s++;
+               t++;
+             }
+
+           *s = '\0';
+         }
+         break;
+       }
+    }
+      
+  return 0;
+}
+
+static int
+iterate_partition (grub_disk_t disk, const grub_partition_t p)
+{
+  const char *disk_name = disk->name;
+  char *partition_name = grub_partition_get_name (p);
+  char *name;
+  int ret;
+  
+  if (! partition_name)
+    return 1;
+
+  name = grub_malloc (grub_strlen (disk_name) + 1
+                     + grub_strlen (partition_name) + 1);
+  if (! name)
+    {
+      grub_free (partition_name);
+      return 1;
+    }
+
+  grub_sprintf (name, "%s,%s", disk_name, partition_name);
+  grub_free (partition_name);
+  
+  ret = add_completion (name, ")", GRUB_COMPLETION_TYPE_PARTITION);
+  grub_free (name);
+  return ret;
+}
+
+static int
+iterate_dir (const char *filename, int dir)
+{
+  if (! dir)
+    {
+      const char *prefix;
+      if (cmdline_state == GRUB_PARSER_STATE_DQUOTE)
+       prefix = "\" ";
+      else if (cmdline_state == GRUB_PARSER_STATE_QUOTE)
+       prefix = "\' ";
+      else
+       prefix = " ";
+
+      if (add_completion (filename, prefix, GRUB_COMPLETION_TYPE_FILE))
+       return 1;
+    }
+  else if (grub_strcmp (filename, ".") && grub_strcmp (filename, ".."))
+    {
+      char fname[grub_strlen (filename) + 2];
+
+      grub_sprintf (fname, "%s/", filename);
+      if (add_completion (fname, "", GRUB_COMPLETION_TYPE_FILE))
+       return 1;
+    }
+  
+  return 0;
+}
+
+static int
+iterate_dev (const char *devname)
+{
+  grub_device_t dev;
+  
+  /* Complete the partition part.  */
+  dev = grub_device_open (devname);
+  
+  if (dev)
+    {
+      if (dev->disk && dev->disk->has_partitions)
+       {
+         if (add_completion (devname, ",", GRUB_COMPLETION_TYPE_DEVICE))
+           return 1;
+       }
+      else
+       {
+         if (add_completion (devname, ")", GRUB_COMPLETION_TYPE_DEVICE))
+           return 1;
+       }
+    }
+  
+  grub_errno = GRUB_ERR_NONE;
+  return 0;
+}
+
+static int
+iterate_command (grub_command_t cmd)
+{
+  if (grub_command_find (cmd->name))
+    {
+      if (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE)
+       {
+         if (add_completion (cmd->name, " ", GRUB_COMPLETION_TYPE_COMMAND))
+           return 1;
+       }
+    }
+  
+  return 0;
+}
+
+/* Complete a device.  */
+static int
+complete_device (void)
+{
+  /* Check if this is a device or a partition.  */
+  char *p = grub_strchr (++current_word, ',');
+  grub_device_t dev;
+  
+  if (! p)
+    {
+      /* Complete the disk part.  */
+      if (grub_disk_dev_iterate (iterate_dev))
+       return 1;
+    }
+  else
+    {
+      /* Complete the partition part.  */
+      *p = '\0';
+      dev = grub_device_open (current_word);
+      *p = ',';
+      grub_errno = GRUB_ERR_NONE;
+      
+      if (dev)
+       {
+         if (dev->disk && dev->disk->has_partitions)
+           {
+             if (grub_partition_iterate (dev->disk, iterate_partition))
+               {
+                 grub_device_close (dev);
+                 return 1;
+               }
+           }
+         
+         grub_device_close (dev);
+       }
+      else
+       return 1;
+    }
+
+  return 0;
+}
+
+/* Complete a file.  */
+static int
+complete_file (void)
+{
+  char *device;
+  char *dir;
+  char *last_dir;
+  grub_fs_t fs;
+  grub_device_t dev;
+  int ret = 0;
+  
+  device = grub_file_get_device_name (current_word);
+  if (grub_errno != GRUB_ERR_NONE)
+    return 1;
+  
+  dev = grub_device_open (device);
+  if (! dev)
+    {
+      ret = 1;
+      goto fail;
+    }
+  
+  fs = grub_fs_probe (dev);
+  if (! fs)
+    {
+      ret = 1;
+      goto fail;
+    }
+
+  dir = grub_strchr (current_word, '/');
+  last_dir = grub_strrchr (current_word, '/');
+  if (dir)
+    {
+      char *dirfile;
+      
+      current_word = last_dir + 1;
+      
+      dir = grub_strdup (dir);
+      if (! dir)
+       {
+         ret = 1;
+         goto fail;
+       }
+      
+      /* Cut away the filename part.  */
+      dirfile = grub_strrchr (dir, '/');
+      dirfile[1] = '\0';
+      
+      /* Iterate the directory.  */
+      (fs->dir) (dev, dir, iterate_dir);
+      
+      grub_free (dir);
+      
+      if (grub_errno)
+       {
+         ret = 1;
+         goto fail;
+       }
+    }
+  else
+    {
+      current_word += grub_strlen (current_word);
+      match = grub_strdup ("/");
+      if (! match)
+       {
+         ret = 1;
+         goto fail;
+       }
+      
+      suffix = "";
+      num_found = 1;
+    }
+
+ fail:
+  if (dev)
+    grub_device_close (dev);
+  grub_free (device);
+  return ret;
+}
+
+/* Complete an argument.  */
+static int
+complete_arguments (char *command)
+{
+  grub_command_t cmd;
+  const struct grub_arg_option *option;
+  char shortarg[] = "- ";
+
+  cmd = grub_command_find (command); 
+
+  if (!cmd || !cmd->options)
+    return 0;
+
+  if (add_completion ("-u", " ", GRUB_COMPLETION_TYPE_ARGUMENT))
+    return 1;
+
+  /* Add the short arguments.  */
+  for (option = cmd->options; option->doc; option++)
+    {
+      if (! option->shortarg)
+       continue;
+
+      shortarg[1] = option->shortarg;
+      if (add_completion (shortarg, " ", GRUB_COMPLETION_TYPE_ARGUMENT))
+       return 1;
+
+    }
+
+  /* First add the built-in arguments.  */
+  if (add_completion ("--help", " ", GRUB_COMPLETION_TYPE_ARGUMENT))
+    return 1;
+  if (add_completion ("--usage", " ", GRUB_COMPLETION_TYPE_ARGUMENT))
+    return 1;
+
+  /* Add the long arguments.  */
+  for (option = cmd->options; option->doc; option++)
+    {
+      char *longarg;
+      if (!option->longarg)
+       continue;
+
+      longarg = grub_malloc (grub_strlen (option->longarg));
+      grub_sprintf (longarg, "--%s", option->longarg);
+
+      if (add_completion (longarg, " ", GRUB_COMPLETION_TYPE_ARGUMENT))
+       {
+         grub_free (longarg);
+         return 1;
+       }
+      grub_free (longarg);
+    }
+
+  return 0;
+}
+
+
+static grub_parser_state_t
+get_state (const char *cmdline)
+{
+  grub_parser_state_t state = GRUB_PARSER_STATE_TEXT;
+  char use;
+
+  while (*cmdline)
+    state = grub_parser_cmdline_state (state, *(cmdline++), &use);
+  return state;
+}
+
+
+/* Try to complete the string in BUF. Return the characters that
+   should be added to the string.  This command outputs the possible
+   completions by calling HOOK, in that case set RESTORE to 1 so the
+   caller can restore the prompt.  */
+char *
+grub_normal_do_completion (char *buf, int *restore,
+                          void (*hook) (const char *, grub_completion_type_t, int))
+{
+  int argc;
+  char **argv;
+
+  /* Initialize variables.  */
+  match = 0;
+  num_found = 0;
+  suffix = "";
+  print_func = hook;
+
+  *restore = 1;
+
+  if (grub_parser_split_cmdline (buf, 0, &argc, &argv))
+    return 0;
+
+  current_word = argv[argc];
+
+  /* Determine the state the command line is in, depending on the
+     state, it can be determined how to complete.  */
+  cmdline_state = get_state (buf);
+
+  if (argc == 0)
+    {
+      /* Complete a command.  */
+      if (grub_iterate_commands (iterate_command))
+       goto fail;
+    }
+  else if (*current_word == '-')
+    {
+      if (complete_arguments (buf))
+       goto fail;
+    }
+  else if (*current_word == '(' && ! grub_strchr (current_word, ')'))
+    {
+      /* Complete a device.  */
+      if (complete_device ())
+           goto fail;
+    }
+  else
+    {
+      /* Complete a file.  */
+      if (complete_file ())
+       goto fail;
+    }
+
+  /* If more than one match is found those matches will be printed and
+     the prompt should be restored.  */
+  if (num_found > 1)
+    *restore = 1;
+  else
+    *restore = 0;
+
+  /* Return the part that matches.  */
+  if (match)
+    {
+      char *ret;
+      char *escstr;
+      char *newstr;
+      int current_len;
+      int match_len;
+      int spaces = 0;
+
+      current_len = grub_strlen (current_word);
+      match_len = grub_strlen (match);
+
+      /* Count the number of spaces that have to be escaped.  XXX:
+        More than just spaces have to be escaped.  */
+      for (escstr = match + current_len; *escstr; escstr++)
+       if (*escstr == ' ')
+         spaces++;
+
+      ret = grub_malloc (match_len - current_len + grub_strlen (suffix) + spaces + 1);
+      newstr = ret;
+      for (escstr = match + current_len; *escstr; escstr++)
+       {
+         if (*escstr == ' ' && cmdline_state != GRUB_PARSER_STATE_QUOTE
+             && cmdline_state != GRUB_PARSER_STATE_QUOTE)
+           *(newstr++) = '\\';
+         *(newstr++) = *escstr;
+       }
+      *newstr = '\0';
+
+      if (num_found == 1)
+       grub_strcat (ret, suffix);
+      
+      if (*ret == '\0')
+       {
+         grub_free (ret);
+          goto fail;
+       }
+      
+      grub_free (argv[0]);
+      grub_free (match);
+      return ret;
+    }
+
+ fail:
+  grub_free (argv[0]);
+  grub_free (match);
+  grub_errno = GRUB_ERR_NONE;
+
+  return 0;
+}
diff --git a/normal/execute.c b/normal/execute.c
new file mode 100644 (file)
index 0000000..35b7a4b
--- /dev/null
@@ -0,0 +1,275 @@
+/* execute.c -- Execute a GRUB script.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/normal.h>
+#include <grub/arg.h>
+#include <grub/env.h>
+#include <grub/script.h>
+
+static grub_err_t
+grub_script_execute_cmd (struct grub_script_cmd *cmd)
+{
+  if (cmd == 0)
+    return 0;
+
+  return cmd->exec (cmd);
+}
+
+/* Parse ARG and return the textual representation.  Add strings are
+   concatenated and all values of the variables are filled in.  */
+static char *
+grub_script_execute_argument_to_string (struct grub_script_arg *arg)
+{
+  int size = 0;
+  char *val;
+  char *chararg;
+  struct grub_script_arg *argi;
+
+  /* First determine the size of the argument.  */
+  for (argi = arg; argi; argi = argi->next)
+    {
+      if (argi->type == 1)
+       {
+         val = grub_env_get (argi->str);
+         if (val)
+           size += grub_strlen (val);
+       }
+      else
+       size += grub_strlen (argi->str);
+    }
+
+  /* Create the argument.  */
+  chararg = grub_malloc (size + 1);
+  if (! chararg)
+    return 0;
+
+  *chararg = '\0';
+  /* First determine the size of the argument.  */
+  for (argi = arg; argi; argi = argi->next)
+    {
+      if (argi->type == 1)
+       {
+         val = grub_env_get (argi->str);
+         if (val)
+           grub_strcat (chararg, val);
+       }
+      else
+       grub_strcat (chararg, argi->str);
+    }
+
+  return chararg;
+}
+
+/* Execute a single command line.  */
+grub_err_t
+grub_script_execute_cmdline (struct grub_script_cmd *cmd)
+{
+  struct grub_script_cmdline *cmdline = (struct grub_script_cmdline *) cmd;
+  struct grub_script_arglist *arglist;
+  char **args = 0;
+  int i = 0;
+  grub_command_t grubcmd;
+  struct grub_arg_list *state;
+  struct grub_arg_option *parser;
+  int maxargs = 0;
+  char **parsed_arglist;
+  int numargs;
+  grub_err_t ret = 0;
+  int argcount = 0;
+  grub_script_function_t func = 0;
+  char errnobuf[6];
+
+  /* Lookup the command.  */
+  grubcmd = grub_command_find (cmdline->cmdname);
+  if (! grubcmd)
+    {
+      /* Ignore errors.  */
+      grub_errno = GRUB_ERR_NONE;
+
+      /* It's not a GRUB command, try all functions.  */
+      func = grub_script_function_find (cmdline->cmdname);
+      if (! func)
+       {
+         /* As a last resort, try if it is an assignment.  */
+         char *assign = grub_strdup (cmdline->cmdname);
+         char *eq = grub_strchr (assign, '=');
+
+         if (eq)
+           {
+             /* Create two strings and set the variable.  */
+             *eq = '\0';
+             eq++;
+             grub_env_set (assign, eq);
+
+             /* This was set because the command was not found.  */
+             grub_errno = GRUB_ERR_NONE;
+           }
+         grub_free (assign);
+         return 0;
+       }
+    }
+
+  if (cmdline->arglist)
+    {
+      argcount = cmdline->arglist->argcount;
+
+      /* Create argv from the arguments.  */
+      args = grub_malloc (sizeof (char *) * argcount);
+      for (arglist = cmdline->arglist; arglist; arglist = arglist->next)
+       {
+         char *str;
+         str = grub_script_execute_argument_to_string (arglist->arg);
+         args[i++] = str;
+       }
+    }
+
+  /* Execute the GRUB command or function.  */
+  if (grubcmd)
+    {
+      /* Count the amount of options the command has.  */
+      parser = (struct grub_arg_option *) grubcmd->options;
+      while (parser && (parser++)->doc)
+       maxargs++;
+
+      /* Set up the option state.  */
+      state = grub_malloc (sizeof (struct grub_arg_list) * maxargs);
+      grub_memset (state, 0, sizeof (struct grub_arg_list) * maxargs);
+
+      /* Start the command.  */
+      if (! (grubcmd->flags & GRUB_COMMAND_FLAG_NO_ARG_PARSE))
+       {
+         if (grub_arg_parse (grubcmd, argcount, args, state, &parsed_arglist, &numargs))
+           ret = (grubcmd->func) (state, numargs, parsed_arglist);
+       }
+      else
+       ret = (grubcmd->func) (state, argcount, args);
+
+      grub_free (state);
+    }
+  else
+    ret = grub_script_function_call (func, argcount, args);
+
+  /* Free arguments.  */
+  for (i = 0; i < argcount; i++)
+    grub_free (args[i]);
+  grub_free (args);
+
+  grub_sprintf (errnobuf, "%d", ret);
+  grub_env_set ("?", errnobuf);
+
+  return ret;
+}
+
+/* Execute a block of one or more commands.  */
+grub_err_t
+grub_script_execute_cmdblock (struct grub_script_cmd *cmd)
+{
+  struct grub_script_cmdblock *cmdblock = (struct grub_script_cmdblock *) cmd;
+
+  /* Loop over every command and execute it.  */
+  for (cmd = cmdblock->cmdlist; cmd; cmd = cmd->next)
+    grub_script_execute_cmd (cmd);
+
+  return 0;
+}
+
+/* Execute an if statement.  */
+grub_err_t
+grub_script_execute_cmdif (struct grub_script_cmd *cmd)
+{
+  struct grub_script_cmdif *cmdif = (struct grub_script_cmdif *) cmd;
+  char *result;
+
+  /* Check if the commands results in a true or a false.  The value is
+     read from the env variable `?'.  */
+  grub_script_execute_cmd (cmdif->exec_to_evaluate);
+  result = grub_env_get ("?");
+
+  /* Execute the `if' or the `else' part depending on the value of
+     `?'.  */
+  if (result && ! grub_strcmp (result, "0"))
+    return grub_script_execute_cmd (cmdif->exec_on_true);
+  else
+    return grub_script_execute_cmd (cmdif->exec_on_false);
+}
+
+/* Execute the menu entry generate statement.  */
+grub_err_t
+grub_script_execute_menuentry (struct grub_script_cmd *cmd)
+{
+  struct grub_script_cmd_menuentry *cmd_menuentry;
+  struct grub_script_arglist *arglist;
+  struct grub_script *script;
+  char **args = 0;
+  int argcount = 0;
+  int i = 0;
+
+  cmd_menuentry = (struct grub_script_cmd_menuentry *) cmd;
+
+  if (cmd_menuentry->arglist)
+    {
+      argcount = cmd_menuentry->arglist->argcount;
+
+      /* Create argv from the arguments.  */
+      args = grub_malloc (sizeof (char *) * argcount);
+
+      if (! args)
+       {
+         return grub_errno;
+       }
+
+      for (arglist = cmd_menuentry->arglist; arglist; arglist = arglist->next)
+       {
+         char *str;
+         str = grub_script_execute_argument_to_string (arglist->arg);
+         args[i++] = str;
+       }
+    }
+
+  /* Parse the menu entry *again*.  */
+  script = grub_script_parse ((char *) cmd_menuentry->sourcecode, 0);
+
+  /* Add new menu entry.  */
+  if (script)
+    {
+      grub_normal_menu_addentry (argcount, (const char **)args,
+                                script, cmd_menuentry->sourcecode);
+    }
+
+  /* Free arguments.  */
+  for (i = 0; i < argcount; i++)
+    grub_free (args[i]);
+  grub_free (args);
+
+  return grub_errno;
+}
+
+
+
+/* Execute any GRUB pre-parsed command or script.  */
+grub_err_t
+grub_script_execute (struct grub_script *script)
+{
+  if (script == 0)
+    return 0;
+
+  return grub_script_execute_cmd (script->cmd);
+}
diff --git a/normal/function.c b/normal/function.c
new file mode 100644 (file)
index 0000000..4c08d15
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/script.h>
+#include <grub/parser.h>
+#include <grub/mm.h>
+
+static grub_script_function_t grub_script_function_list;
+
+grub_script_function_t
+grub_script_function_create (char *functionname, struct grub_script *cmd)
+{
+  grub_script_function_t func;
+  grub_script_function_t *p;
+  
+  func = (grub_script_function_t) grub_malloc (sizeof (*func));
+  if (! func)
+    return 0;
+
+  func->name = grub_strdup (functionname);
+  if (! func->name)
+    {
+      grub_free (func);
+      return 0;
+    }
+  
+  func->func = cmd;
+
+  /* Keep the list sorted for simplicity.  */
+  p = &grub_script_function_list;
+  while (*p)
+    {
+      if (grub_strcmp ((*p)->name, functionname) >= 0)
+       break;
+
+      p = &((*p)->next);
+    }
+
+  /* If the function already exists, overwrite the old function.  */
+  if (*p && grub_strcmp ((*p)->name, functionname) == 0)
+    {
+      grub_script_function_t q;
+
+      q = *p;
+      grub_script_free (q->func);
+      q->func = cmd;
+      grub_free (func);
+      func = q;
+    }
+  else
+    {
+      func->next = *p;
+      *p = func;
+    }
+
+  return func;
+}
+
+void
+grub_script_function_remove (const char *name)
+{
+  grub_script_function_t *p, q;
+
+  for (p = &grub_script_function_list, q = *p; q; p = &(q->next), q = q->next)
+    if (grub_strcmp (name, q->name) == 0)
+      {
+        *p = q->next;
+       grub_free (q->name);
+       grub_script_free (q->func);
+        grub_free (q);
+        break;
+      }
+}
+
+grub_script_function_t
+grub_script_function_find (char *functionname)
+{
+  grub_script_function_t func;
+
+  for (func = grub_script_function_list; func; func = func->next)
+    if (grub_strcmp (functionname, func->name) == 0)
+      break;
+
+  if (! func)
+    grub_error (GRUB_ERR_UNKNOWN_COMMAND, "unknown command `%s'", functionname);
+
+  return func;
+}
+
+int
+grub_script_function_iterate (int (*iterate) (grub_script_function_t))
+{
+  grub_script_function_t func;
+  
+  for (func = grub_script_function_list; func; func = func->next)
+    if (iterate (func))
+      return 1;
+  
+  return 0;
+}
+
+int
+grub_script_function_call (grub_script_function_t func,
+                          int argc __attribute__((unused)),
+                          char **args __attribute__((unused)))
+{
+  /* XXX: Arguments are not supported yet.  */
+  return grub_script_execute (func->func);
+}
diff --git a/normal/i386/setjmp.S b/normal/i386/setjmp.S
new file mode 100644 (file)
index 0000000..ba38bd2
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,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/>.
+ */
+
+#include <grub/symbol.h>
+
+       .file   "setjmp.S"
+       
+       .text
+       
+/*
+ * int grub_setjmp (grub_jmp_buf env)
+ */
+FUNCTION(grub_setjmp)
+       movl    %ebx, 0(%eax)   /* EBX */
+       movl    %esi, 4(%eax)   /* ESI */
+       movl    %edi, 8(%eax)   /* EDI */
+       movl    %ebp, 12(%eax)  /* EBP */
+       popl    %ecx
+       movl    %esp, 16(%eax)  /* ESP */
+       movl    %ecx, 20(%eax)  /* EIP */
+       xorl    %eax, %eax
+       jmp     *%ecx
+
+               
+/*
+ * int grub_longjmp (grub_jmp_buf env, int val)
+ */
+FUNCTION(grub_longjmp)
+       movl    0(%eax), %ebx
+       movl    4(%eax), %esi
+       movl    8(%eax), %edi
+       movl    12(%eax), %ebp
+       movl    16(%eax), %esp
+       movl    20(%eax), %ecx
+
+       movl    %edx, %eax
+       testl   %eax, %eax
+       jnz     1f
+       incl    %eax
+1:     jmp     *%ecx
+       
diff --git a/normal/lexer.c b/normal/lexer.c
new file mode 100644 (file)
index 0000000..f500374
--- /dev/null
@@ -0,0 +1,364 @@
+/* lexer.c - The scripting lexer.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2006,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/>.
+ */
+
+#include <grub/parser.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/script.h>
+
+#include "grub_script.tab.h"
+
+static int
+check_varstate (grub_parser_state_t state)
+{
+  return (state == GRUB_PARSER_STATE_VARNAME
+         || state == GRUB_PARSER_STATE_VAR
+         || state == GRUB_PARSER_STATE_QVAR
+         || state == GRUB_PARSER_STATE_VARNAME2
+         || state == GRUB_PARSER_STATE_QVARNAME
+         || state == GRUB_PARSER_STATE_QVARNAME2);
+}
+
+static int
+check_textstate (grub_parser_state_t state)
+{
+  return (state == GRUB_PARSER_STATE_TEXT
+         || state == GRUB_PARSER_STATE_QUOTE
+         || state == GRUB_PARSER_STATE_DQUOTE);
+}
+
+struct grub_lexer_param *
+grub_script_lexer_init (char *script, grub_err_t (*getline) (char **))
+{
+  struct grub_lexer_param *param;
+
+  param = grub_malloc (sizeof (*param));
+  if (! param)
+    return 0;
+
+  param->state = GRUB_PARSER_STATE_TEXT;
+  param->getline = getline;
+  param->refs = 0;
+  param->done = 0;
+  param->newscript = 0;
+  param->script = script;
+  param->record = 0;
+  param->recording = 0;
+  param->recordpos = 0;
+  param->recordlen = 0;
+
+  return param;
+}
+
+void
+grub_script_lexer_ref (struct grub_lexer_param *state)
+{
+  state->refs++;
+}
+
+void
+grub_script_lexer_deref (struct grub_lexer_param *state)
+{
+  state->refs--;
+}
+
+/* Start recording all characters passing through the lexer.  */
+void
+grub_script_lexer_record_start (struct grub_lexer_param *state)
+{
+  state->record = 1;
+  state->recordlen = 100;
+  state->recording = grub_malloc (state->recordlen);
+  state->recordpos = 0;
+}
+
+char *
+grub_script_lexer_record_stop (struct grub_lexer_param *state)
+{
+  state->record = 0;
+
+  /* Delete the last character, it is a `}'.  */
+  if (state->recordpos > 0)
+    {
+      if (state->recording[--state->recordpos] != '}')
+       {
+         grub_printf ("Internal error while parsing menu entry");
+         for (;;); /* XXX */
+       }
+      state->recording[state->recordpos] = '\0';
+    }
+
+  return state->recording;
+}
+
+/* When recording is enabled, record the character C as the next item
+   in the character stream.  */
+static void
+recordchar (struct grub_lexer_param *state, char c)
+{
+  if (state->recordpos == state->recordlen)
+    {
+      char *old = state->recording;
+      state->recordlen += 100;
+      state->recording = grub_realloc (state->recording, state->recordlen);
+      if (! state->recording)
+       {
+         grub_free (old);
+         state->record = 0;
+       }
+    }
+  state->recording[state->recordpos++] = c;
+}
+
+/* Fetch the next character for the lexer.  */
+static void
+nextchar (struct grub_lexer_param *state)
+{
+  if (state->record)
+    recordchar (state, *state->script);
+  state->script++;
+}
+
+int
+grub_script_yylex2 (union YYSTYPE *yylval,
+                   struct grub_parser_param *parsestate);
+
+int
+grub_script_yylex (union YYSTYPE *yylval, struct grub_parser_param *parsestate)
+{
+  int r = -1;
+
+  while (r == -1)
+    {
+      r = grub_script_yylex2 (yylval, parsestate);
+      if (r == ' ')
+       r = -1;
+    }
+  return r;
+}
+
+int
+grub_script_yylex2 (union YYSTYPE *yylval, struct grub_parser_param *parsestate)
+{
+  grub_parser_state_t newstate;
+  char use;
+  char *buffer;
+  char *bp;
+  struct grub_lexer_param *state = parsestate->lexerstate;
+
+  if (state->done)
+    return 0;
+
+  if (! *state->script)
+    {
+      /* Check if more tokens are requested by the parser.  */
+      if ((state->refs
+          || state->state == GRUB_PARSER_STATE_ESC)
+         && state->getline)
+       {
+         while (!state->script || ! grub_strlen (state->script))
+           {
+             grub_free (state->newscript);
+             state->newscript = 0;
+             state->getline (&state->newscript);
+             state->script = state->newscript;
+             if (! state->script)
+               return 0;
+           }
+         grub_dprintf ("scripting", "token=`\\n'\n");
+         recordchar (state, '\n');
+         if (state->state != GRUB_PARSER_STATE_ESC)
+           return '\n';
+       }
+      else
+       {
+         grub_free (state->newscript);
+         state->newscript = 0;
+         state->done = 1;
+         grub_dprintf ("scripting", "token=`\\n'\n");
+         return '\n';
+       }
+    }
+
+  newstate = grub_parser_cmdline_state (state->state, *state->script, &use);
+
+  /* Check if it is a text.  */
+  if (check_textstate (newstate))
+    {
+      /* In case the string is not quoted, this can be a one char
+        length symbol.  */
+      if (newstate == GRUB_PARSER_STATE_TEXT)
+       {
+         switch (*state->script)
+           {
+           case ' ':
+             while (*state->script)
+               {
+                 newstate = grub_parser_cmdline_state (state->state,
+                                                       *state->script, &use);
+                 if (! (state->state == GRUB_PARSER_STATE_TEXT
+                        && *state->script == ' '))
+                   {
+                     grub_dprintf ("scripting", "token=` '\n");
+                     return ' ';
+                   }
+                 state->state = newstate;
+                 nextchar (state);
+               }
+             grub_dprintf ("scripting", "token=` '\n");
+             return ' ';
+           case '{':
+           case '}':
+           case ';':
+           case '\n':
+             {
+               char c;
+               grub_dprintf ("scripting", "token=`%c'\n", *state->script);
+               c = *state->script;;
+               nextchar (state);
+               return c;
+             }
+           }
+       }
+
+      /* XXX: Use a better size.  */
+      buffer = grub_script_malloc (parsestate, 2048);
+      if (! buffer)
+       return 0;
+
+      bp = buffer;
+
+      /* Read one token, possible quoted.  */
+      while (*state->script)
+       {
+         newstate = grub_parser_cmdline_state (state->state,
+                                               *state->script, &use);
+
+         /* Check if a variable name starts.  */
+         if (check_varstate (newstate))
+           break;
+
+         /* If the string is not quoted or escaped, stop processing
+            when a special token was found.  It will be recognized
+            next time when this function is called.  */
+         if (newstate == GRUB_PARSER_STATE_TEXT
+             && state->state != GRUB_PARSER_STATE_ESC)
+           {
+             int breakout = 0;
+
+             switch (use)
+               {
+               case ' ':
+               case '{':
+               case '}':
+               case ';':
+               case '\n':
+                 breakout = 1;
+               }
+             if (breakout)
+               break;
+             *(bp++) = use;
+           }
+         else if (use)
+           *(bp++) = use;
+
+         state->state = newstate;
+         nextchar (state);
+       }
+
+      /* A string of text was read in.  */
+      *bp = '\0';
+      grub_dprintf ("scripting", "token=`%s'\n", buffer);
+      yylval->string = buffer;
+
+      /* Detect some special tokens.  */
+      if (! grub_strcmp (buffer, "while"))
+       return GRUB_PARSER_TOKEN_WHILE;
+      else if (! grub_strcmp (buffer, "if"))
+       return GRUB_PARSER_TOKEN_IF;
+      else if (! grub_strcmp (buffer, "function"))
+       return GRUB_PARSER_TOKEN_FUNCTION;
+      else if (! grub_strcmp (buffer, "menuentry"))
+       return GRUB_PARSER_TOKEN_MENUENTRY;
+      else if (! grub_strcmp (buffer, "@"))
+       return GRUB_PARSER_TOKEN_MENUENTRY;
+      else if (! grub_strcmp (buffer, "else"))
+       return GRUB_PARSER_TOKEN_ELSE;
+      else if (! grub_strcmp (buffer, "then"))
+       return GRUB_PARSER_TOKEN_THEN;
+      else if (! grub_strcmp (buffer, "fi"))
+       return GRUB_PARSER_TOKEN_FI;
+      else
+       return GRUB_PARSER_TOKEN_NAME;
+    }
+  else if (newstate == GRUB_PARSER_STATE_VAR
+          || newstate == GRUB_PARSER_STATE_QVAR)
+    {
+      /* XXX: Use a better size.  */
+      buffer = grub_script_malloc (parsestate, 2096);
+      if (! buffer)
+       return 0;
+
+      bp = buffer;
+
+      /* This is a variable, read the variable name.  */
+      while (*state->script)
+       {
+         newstate = grub_parser_cmdline_state (state->state,
+                                               *state->script, &use);
+
+         /* Check if this character is not part of the variable name
+            anymore.  */
+         if (! (check_varstate (newstate)))
+           {
+             if (state->state == GRUB_PARSER_STATE_VARNAME2
+                 || state->state == GRUB_PARSER_STATE_QVARNAME2)
+               nextchar (state);
+             state->state = newstate;
+             break;
+           }
+
+         if (use)
+           *(bp++) = use;
+         nextchar (state);
+         state->state = newstate;
+       }
+
+      *bp = '\0';
+      state->state = newstate;
+      yylval->string = buffer;
+      grub_dprintf ("scripting", "vartoken=`%s'\n", buffer);
+
+      return GRUB_PARSER_TOKEN_VAR;
+    }
+  else
+    {
+      /* There is either text or a variable name.  In the case you
+        arrive here there is a serious problem with the lexer.  */
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "Internal error\n");
+      return 0;
+    }
+}
+
+void
+grub_script_yyerror (struct grub_parser_param *lex __attribute__ ((unused)),
+                    char const *err)
+{
+  grub_printf ("%s\n", err);
+}
diff --git a/normal/main.c b/normal/main.c
new file mode 100644 (file)
index 0000000..a0c0135
--- /dev/null
@@ -0,0 +1,648 @@
+/* main.c - the normal mode main routine */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2000,2001,2002,2003,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/>.
+ */
+
+#include <grub/kernel.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/rescue.h>
+#include <grub/misc.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/term.h>
+#include <grub/env.h>
+#include <grub/parser.h>
+#include <grub/script.h>
+#include <grub/menu_viewer.h>
+
+grub_jmp_buf grub_exit_env;
+
+static grub_fs_module_list_t fs_module_list = 0;
+
+#define GRUB_DEFAULT_HISTORY_SIZE      50
+
+/* Read a line from the file FILE.  */
+static char *
+get_line (grub_file_t file)
+{
+  char c;
+  int pos = 0;
+  int literal = 0;
+  int comment = 0;
+  char *cmdline;
+  int max_len = 64;
+
+  /* Initially locate some space.  */
+  cmdline = grub_malloc (max_len);
+  if (! cmdline)
+    return 0;
+
+  while (1)
+    {
+      if (grub_file_read (file, &c, 1) != 1)
+       break;
+
+      /* Skip all carriage returns.  */
+      if (c == '\r')
+       continue;
+
+      /* Replace tabs with spaces.  */
+      if (c == '\t')
+       c = ' ';
+
+      /* The previous is a backslash, then...  */
+      if (literal)
+       {
+         /* If it is a newline, replace it with a space and continue.  */
+         if (c == '\n')
+           {
+             c = ' ';
+
+             /* Go back to overwrite the backslash.  */
+             if (pos > 0)
+               pos--;
+           }
+
+         literal = 0;
+       }
+
+      if (c == '\\')
+       literal = 1;
+
+      if (comment)
+       {
+         if (c == '\n')
+           comment = 0;
+       }
+      else if (pos == 0)
+       {
+         if (c == '#')
+           comment = 1;
+         else if (! grub_isspace (c))
+           cmdline[pos++] = c;
+       }
+      else
+       {
+         if (pos >= max_len)
+           {
+             char *old_cmdline = cmdline;
+             max_len = max_len * 2;
+             cmdline = grub_realloc (cmdline, max_len);
+             if (! cmdline)
+               {
+                 grub_free (old_cmdline);
+                 return 0;
+               }
+           }
+
+         if (c == '\n')
+           break;
+
+         cmdline[pos++] = c;
+       }
+    }
+
+  cmdline[pos] = '\0';
+
+  /* If the buffer is empty, don't return anything at all.  */
+  if (pos == 0)
+    {
+      grub_free (cmdline);
+      cmdline = 0;
+    }
+  
+  return cmdline;
+}
+
+static void
+free_menu (grub_menu_t menu)
+{
+  grub_menu_entry_t entry = menu->entry_list;
+
+  while (entry)
+    {
+      grub_menu_entry_t next_entry = entry->next;
+
+      grub_script_free (entry->commands);
+      grub_free ((void *) entry->title);
+      grub_free ((void *) entry->sourcecode);
+      entry = next_entry;
+    }
+
+  grub_free (menu);
+  grub_env_unset_data_slot ("menu");
+}
+
+static void
+free_menu_entry_classes (struct grub_menu_entry_class *head)
+{
+  /* Free all the classes.  */
+  while (head)
+    {
+      struct grub_menu_entry_class *next;
+
+      grub_free (head->name);
+      next = head->next;
+      grub_free (head);
+      head = next;
+    }
+}
+
+grub_err_t
+grub_normal_menu_addentry (int argc, const char **args, struct grub_script *script,
+                          const char *sourcecode)
+{
+  const char *menutitle = 0;
+  const char *menusourcecode;
+  grub_menu_t menu;
+  grub_menu_entry_t *last;
+  int failed = 0;
+  int i;
+  struct grub_menu_entry_class *classes_head;  /* Dummy head node for list.  */
+  struct grub_menu_entry_class *classes_tail;
+
+  /* Allocate dummy head node for class list.  */
+  classes_head = grub_malloc (sizeof (struct grub_menu_entry_class));
+  if (! classes_head)
+    return grub_errno;
+  classes_head->name = 0;
+  classes_head->next = 0;
+  classes_tail = classes_head;
+
+  menu = grub_env_get_data_slot("menu");
+  if (! menu)
+    return grub_error (GRUB_ERR_MENU, "no menu context");
+
+  last = &menu->entry_list;
+
+  menusourcecode = grub_strdup (sourcecode);
+  if (! menusourcecode)
+    return grub_errno;
+
+  /* Parse menu arguments.  */
+  for (i = 0; i < argc; i++)
+    {
+      /* Capture arguments.  */
+      if (grub_strncmp ("--", args[i], 2) == 0)
+       {
+         const char *arg = &args[i][2];
+
+         /* Handle menu class.  */
+         if (grub_strcmp(arg, "class") == 0)
+           {
+             char *class_name;
+             struct grub_menu_entry_class *new_class;
+
+             i++;
+             class_name = grub_strdup (args[i]);
+             if (! class_name)
+               {
+                 failed = 1;
+                 break;
+               }
+
+             /* Create a new class and add it at the tail of the list.  */
+             new_class = grub_malloc (sizeof (struct grub_menu_entry_class));
+             if (! new_class)
+               {
+                 grub_free (class_name);
+                 failed = 1;
+                 break;
+               }
+             /* Fill in the new class node.  */
+             new_class->name = class_name;
+             new_class->next = 0;
+             /* Link the tail to it, and make it the new tail.  */
+             classes_tail->next = new_class;
+             classes_tail = new_class;
+             continue;
+           }
+         else
+           {
+             /* Handle invalid argument.  */
+             failed = 1;
+             grub_error (GRUB_ERR_MENU, "invalid argument for menuentry: %s", args[i]);
+             break;
+           }
+       }
+
+      /* Capture title.  */
+      if (! menutitle)
+       {
+         menutitle = grub_strdup (args[i]);
+       }
+      else
+       {
+         failed = 1;
+         grub_error (GRUB_ERR_MENU, "too many titles for menuentry: %s", args[i]);
+         break;
+       }
+    }
+
+  /* Validate arguments.  */
+  if ((! failed) && (! menutitle))
+    {
+      grub_error (GRUB_ERR_MENU, "menuentry is missing title");
+      failed = 1;
+    }
+
+  /* If argument parsing failed, free any allocated resources.  */
+  if (failed)
+    {
+      free_menu_entry_classes (classes_head);
+      grub_free ((void *) menutitle);
+      grub_free ((void *) menusourcecode);
+
+      /* Here we assume that grub_error has been used to specify failure details.  */
+      return grub_errno;
+    }
+
+  /* Add the menu entry at the end of the list.  */
+  while (*last)
+    last = &(*last)->next;
+
+  *last = grub_malloc (sizeof (**last));
+  if (! *last)
+    {
+      free_menu_entry_classes (classes_head);
+      grub_free ((void *) menutitle);
+      grub_free ((void *) menusourcecode);
+      return grub_errno;
+    }
+
+  (*last)->commands = script;
+  (*last)->title = menutitle;
+  (*last)->classes = classes_head;
+  (*last)->next = 0;
+  (*last)->sourcecode = menusourcecode;
+
+  menu->size++;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_menu_t
+read_config_file (const char *config, int nested)
+{
+  grub_file_t file;
+  auto grub_err_t getline (char **line);
+  int currline = 0;
+  int errors = 0;
+  
+  grub_err_t getline (char **line)
+    {
+      currline++;
+
+      *line = get_line (file);
+      if (! *line)
+       return grub_errno;
+
+      return GRUB_ERR_NONE;
+    }
+
+  grub_menu_t newmenu;
+
+  newmenu = grub_env_get_data_slot ("menu");
+
+  if (nested || ! newmenu)
+    {
+      newmenu = grub_malloc (sizeof (*newmenu));
+      if (! newmenu)
+       return 0;
+      newmenu->size = 0;
+      newmenu->entry_list = 0;
+    }
+
+  /* Try to open the config file.  */
+  file = grub_file_open (config);
+  if (! file)
+    return 0;
+
+  grub_env_set_data_slot ("menu", newmenu);
+
+  while (1)
+    {
+      struct grub_script *parsed_script;
+      int startline;
+      char *cmdline;
+
+      cmdline = get_line (file);
+      if (!cmdline)
+       break;
+
+      startline = ++currline;
+
+      /* Execute the script, line for line.  */
+      parsed_script = grub_script_parse (cmdline, getline);
+
+      grub_free (cmdline);
+
+      if (! parsed_script)
+       {
+         grub_printf ("(line %d-%d)\n", startline, currline);
+         errors++;
+         continue;
+       }
+
+      /* Execute the command(s).  */
+      grub_script_execute (parsed_script);
+
+      /* Ignore errors.  */
+      grub_errno = GRUB_ERR_NONE;
+
+      /* The parsed script was executed, throw it away.  */
+      grub_script_free (parsed_script);
+    }
+
+  grub_file_close (file);
+
+  if (errors > 0)
+    grub_wait_after_message ();
+
+  return newmenu;
+}
+
+/* This starts the normal mode.  */
+void
+grub_enter_normal_mode (const char *config)
+{
+  if (grub_setjmp (grub_exit_env) == 0)
+    grub_normal_execute (config, 0);
+}
+
+/* Initialize the screen.  */
+void
+grub_normal_init_page (void)
+{
+  grub_cls ();
+  grub_printf ("\n\
+                         GNU GRUB  version %s\n\n",
+              PACKAGE_VERSION);
+}
+
+/* Read the file command.lst for auto-loading.  */
+static void
+read_command_list (void)
+{
+  const char *prefix;
+  
+  prefix = grub_env_get ("prefix");
+  if (prefix)
+    {
+      char *filename;
+
+      filename = grub_malloc (grub_strlen (prefix) + sizeof ("/command.lst"));
+      if (filename)
+       {
+         grub_file_t file;
+         
+         grub_sprintf (filename, "%s/command.lst", prefix);
+         file = grub_file_open (filename);
+         if (file)
+           {
+             while (1)
+               {
+                 char *p;
+                 grub_command_t cmd;
+                 char *buf = get_line (file);
+
+                 if (! buf)
+                   break;
+                 
+                 if (! grub_isgraph (buf[0]))
+                   continue;
+
+                 p = grub_strchr (buf, ':');
+                 if (! p)
+                   continue;
+
+                 *p = '\0';
+                 while (*++p == ' ')
+                   ;
+
+                 if (! grub_isgraph (*p))
+                   continue;
+
+                 cmd = grub_register_command (buf, 0,
+                                              GRUB_COMMAND_FLAG_NOT_LOADED,
+                                              0, 0, 0);
+                 if (! cmd)
+                   {
+                     grub_free (buf);
+                     continue;
+                   }
+
+                 cmd->module_name = grub_strdup (p);
+                 if (! cmd->module_name)
+                   grub_unregister_command (buf);
+                 grub_free (buf);
+               }
+
+             grub_file_close (file);
+           }
+
+         grub_free (filename);
+       }
+    }
+
+  /* Ignore errors.  */
+  grub_errno = GRUB_ERR_NONE;
+}
+
+/* The auto-loading hook for filesystems.  */
+static int
+autoload_fs_module (void)
+{
+  grub_fs_module_list_t p;
+
+  while ((p = fs_module_list) != 0)
+    {
+      if (! grub_dl_get (p->name) && grub_dl_load (p->name))
+       return 1;
+
+      fs_module_list = p->next;
+      grub_free (p->name);
+      grub_free (p);
+    }
+
+  return 0;
+}
+
+/* Read the file fs.lst for auto-loading.  */
+static void
+read_fs_list (void)
+{
+  const char *prefix;
+  
+  prefix = grub_env_get ("prefix");
+  if (prefix)
+    {
+      char *filename;
+
+      filename = grub_malloc (grub_strlen (prefix) + sizeof ("/fs.lst"));
+      if (filename)
+       {
+         grub_file_t file;
+         
+         grub_sprintf (filename, "%s/fs.lst", prefix);
+         file = grub_file_open (filename);
+         if (file)
+           {
+             while (1)
+               {
+                 char *buf;
+                 char *p;
+                 char *q;
+                 grub_fs_module_list_t fs_mod;
+                 
+                 buf = get_line (file);
+                 if (! buf)
+                   break;
+
+                 p = buf;
+                 q = buf + grub_strlen (buf) - 1;
+
+                 /* Ignore space.  */
+                 while (grub_isspace (*p))
+                   p++;
+
+                 while (p < q && grub_isspace (*q))
+                   *q-- = '\0';
+
+                 /* If the line is empty, skip it.  */
+                 if (p >= q)
+                   continue;
+
+                 fs_mod = grub_malloc (sizeof (*fs_mod));
+                 if (! fs_mod)
+                   continue;
+
+                 fs_mod->name = grub_strdup (p);
+                 if (! fs_mod->name)
+                   {
+                     grub_free (fs_mod);
+                     continue;
+                   }
+
+                 fs_mod->next = fs_module_list;
+                 fs_module_list = fs_mod;
+               }
+
+             grub_file_close (file);
+           }
+
+         grub_free (filename);
+       }
+    }
+
+  /* Ignore errors.  */
+  grub_errno = GRUB_ERR_NONE;
+
+  /* Set the hook.  */
+  grub_fs_autoload_hook = autoload_fs_module;
+}
+
+/* Read the config file CONFIG and execute the menu interface or
+   the command-line interface.  */
+void
+grub_normal_execute (const char *config, int nested)
+{
+  grub_menu_t menu = 0;
+
+  read_command_list ();
+  read_fs_list ();
+  
+  if (config)
+    {
+      menu = read_config_file (config, nested);
+
+      /* Ignore any error.  */
+      grub_errno = GRUB_ERR_NONE;
+    }
+
+  if (menu && menu->size)
+    {
+      grub_menu_viewer_show_menu (menu, nested);
+      if (nested)
+       free_menu (menu);
+    }
+  else
+    grub_cmdline_run (nested);
+}
+
+/* Enter normal mode from rescue mode.  */
+static void
+grub_rescue_cmd_normal (int argc, char *argv[])
+{
+  if (argc == 0)
+    {
+      /* Guess the config filename. It is necessary to make CONFIG static,
+        so that it won't get broken by longjmp.  */
+      static char *config;
+      const char *prefix;
+      
+      prefix = grub_env_get ("prefix");
+      if (prefix)
+       {
+         config = grub_malloc (grub_strlen (prefix) + sizeof ("/grub.cfg"));
+         if (! config)
+           return;
+
+         grub_sprintf (config, "%s/grub.cfg", prefix);
+         grub_enter_normal_mode (config);
+         grub_free (config);
+       }
+      else
+       grub_enter_normal_mode (0);
+    }
+  else
+    grub_enter_normal_mode (argv[0]);
+}
+
+GRUB_MOD_INIT(normal)
+{
+  /* Normal mode shouldn't be unloaded.  */
+  if (mod)
+    grub_dl_ref (mod);
+
+  grub_menu_viewer_register (&grub_normal_text_menu_viewer);
+
+  grub_set_history (GRUB_DEFAULT_HISTORY_SIZE);
+
+  /* Register a command "normal" for the rescue mode.  */
+  grub_rescue_register_command ("normal", grub_rescue_cmd_normal,
+                               "enter normal mode");
+
+  /* Reload terminal colors when these variables are written to.  */
+  grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal);
+  grub_register_variable_hook ("color_highlight", NULL, grub_env_write_color_highlight);
+
+  /* Preserve hooks after context changes.  */
+  grub_env_export ("color_normal");
+  grub_env_export ("color_highlight");
+
+  /* This registers some built-in commands.  */
+  grub_command_init ();
+}
+
+GRUB_MOD_FINI(normal)
+{
+  grub_set_history (0);
+  grub_rescue_unregister_command ("normal");
+}
+
diff --git a/normal/menu.c b/normal/menu.c
new file mode 100644 (file)
index 0000000..df26209
--- /dev/null
@@ -0,0 +1,166 @@
+/* menu.c - General supporting functionality for menus.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/misc.h>
+#include <grub/loader.h>
+#include <grub/mm.h>
+#include <grub/time.h>
+#include <grub/env.h>
+#include <grub/script.h>
+#include <grub/menu_viewer.h>
+
+/* Get a menu entry by its index in the entry list.  */
+grub_menu_entry_t
+grub_menu_get_entry (grub_menu_t menu, int no)
+{
+  grub_menu_entry_t e;
+
+  for (e = menu->entry_list; e && no > 0; e = e->next, no--)
+    ;
+
+  return e;
+}
+
+/* Return the current timeout. If the variable "timeout" is not set or
+   invalid, return -1.  */
+int
+grub_menu_get_timeout (void)
+{
+  char *val;
+  int timeout;
+
+  val = grub_env_get ("timeout");
+  if (! val)
+    return -1;
+
+  grub_error_push ();
+
+  timeout = (int) grub_strtoul (val, 0, 0);
+
+  /* If the value is invalid, unset the variable.  */
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_env_unset ("timeout");
+      grub_errno = GRUB_ERR_NONE;
+      timeout = -1;
+    }
+
+  grub_error_pop ();
+
+  return timeout;
+}
+
+/* Set current timeout in the variable "timeout".  */
+void
+grub_menu_set_timeout (int timeout)
+{
+  /* Ignore TIMEOUT if it is zero, because it will be unset really soon.  */
+  if (timeout > 0)
+    {
+      char buf[16];
+
+      grub_sprintf (buf, "%d", timeout);
+      grub_env_set ("timeout", buf);
+    }
+}
+
+/* Get the first entry number from the value of the environment variable NAME,
+   which is a space-separated list of nonnegative integers.  The entry number
+   which is returned is stripped from the value of NAME.  If no entry number
+   can be found, -1 is returned.  */
+static int
+get_and_remove_first_entry_number (const char *name)
+{
+  char *val;
+  char *tail;
+  int entry;
+
+  val = grub_env_get (name);
+  if (! val)
+    return -1;
+
+  grub_error_push ();
+
+  entry = (int) grub_strtoul (val, &tail, 0);
+
+  if (grub_errno == GRUB_ERR_NONE)
+    {
+      /* Skip whitespace to find the next digit.  */
+      while (*tail && grub_isspace (*tail))
+       tail++;
+      grub_env_set (name, tail);
+    }
+  else
+    {
+      grub_env_unset (name);
+      grub_errno = GRUB_ERR_NONE;
+      entry = -1;
+    }
+
+  grub_error_pop ();
+
+  return entry;
+}
+
+/* Run a menu entry.  */
+void
+grub_menu_execute_entry(grub_menu_entry_t entry)
+{
+  grub_script_execute (entry->commands);
+
+  if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
+    /* Implicit execution of boot, only if something is loaded.  */
+    grub_command_execute ("boot", 0);
+}
+
+/* Execute ENTRY from the menu MENU, falling back to entries specified
+   in the environment variable "fallback" if it fails.  CALLBACK is a
+   pointer to a struct of function pointers which are used to allow the
+   caller provide feedback to the user.  */
+void
+grub_menu_execute_with_fallback (grub_menu_t menu,
+                                grub_menu_entry_t entry,
+                                grub_menu_execute_callback_t callback,
+                                void *callback_data)
+{
+  int fallback_entry;
+
+  callback->notify_booting (entry, callback_data);
+
+  grub_menu_execute_entry (entry);
+
+  /* Deal with fallback entries.  */
+  while ((fallback_entry = get_and_remove_first_entry_number ("fallback"))
+        >= 0)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+
+      entry = grub_menu_get_entry (menu, fallback_entry);
+      callback->notify_fallback (entry, callback_data);
+      grub_menu_execute_entry (entry);
+      /* If the function call to execute the entry returns at all, then this is
+        taken to indicate a boot failure.  For menu entries that do something
+        other than actually boot an operating system, this could assume
+        incorrectly that something failed.  */
+    }
+
+  callback->notify_failure (callback_data);
+}
diff --git a/normal/menu_entry.c b/normal/menu_entry.c
new file mode 100644 (file)
index 0000000..a9c1788
--- /dev/null
@@ -0,0 +1,1186 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2006,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/loader.h>
+#include <grub/script.h>
+
+enum update_mode
+  {
+    NO_LINE,
+    SINGLE_LINE,
+    ALL_LINES
+  };
+
+struct line
+{
+  /* The line buffer.  */
+  char *buf;
+  /* The length of the line.  */
+  int len;
+  /* The maximum length of the line.  */
+  int max_len;
+};
+
+struct screen
+{
+  /* The array of lines.  */
+  struct line *lines;
+  /* The number of lines.  */
+  int num_lines;
+  /* The current column.  */
+  int column;
+  /* The real column.  */
+  int real_column;
+  /* The current line.  */
+  int line;
+  /* The X coordinate.  */
+  int x;
+  /* The Y coordinate.  */
+  int y;
+  /* The kill buffer.  */
+  char *killed_text;
+  /* The flag of a completion window.  */
+  int completion_shown;
+};
+
+/* Used for storing completion items temporarily.  */
+static struct line completion_buffer;
+
+/* Initialize a line.  */
+static int
+init_line (struct line *linep)
+{
+  linep->len = 0;
+  linep->max_len = 80; /* XXX */
+  linep->buf = grub_malloc (linep->max_len);
+  if (! linep->buf)
+    return 0;
+
+  return 1;
+}
+
+/* Allocate extra space if necessary.  */
+static int
+ensure_space (struct line *linep, int extra)
+{
+  if (linep->max_len < linep->len + extra)
+    {
+      linep->max_len = linep->len + extra + 80; /* XXX */
+      linep->buf = grub_realloc (linep->buf, linep->max_len + 1);
+      if (! linep->buf)
+       return 0;
+    }
+
+  return 1;
+}
+
+/* Return the number of lines occupied by this line on the screen.  */
+static int
+get_logical_num_lines (struct line *linep)
+{
+  return (linep->len / GRUB_TERM_ENTRY_WIDTH) + 1;
+}
+
+/* Print a line.  */
+static void
+print_line (struct line *linep, int offset, int start, int y)
+{
+  int i;
+  char *p;
+  
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + start + 1,
+              y + GRUB_TERM_FIRST_ENTRY_Y);
+
+  for (p = linep->buf + offset + start, i = start;
+       i < GRUB_TERM_ENTRY_WIDTH && offset + i < linep->len;
+       p++, i++)
+    grub_putchar (*p);
+
+  for (; i < GRUB_TERM_ENTRY_WIDTH; i++)
+    grub_putchar (' ');
+
+  if (linep->len >= offset + GRUB_TERM_ENTRY_WIDTH)
+    grub_putchar ('\\');
+  else
+    grub_putchar (' ');
+}
+
+/* Print an empty line.  */
+static void
+print_empty_line (int y)
+{
+  int i;
+  
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1,
+              y + GRUB_TERM_FIRST_ENTRY_Y);
+
+  for (i = 0; i < GRUB_TERM_ENTRY_WIDTH + 1; i++)
+    grub_putchar (' ');
+}
+
+/* Print an up arrow.  */
+static void
+print_up (int flag)
+{
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
+              GRUB_TERM_FIRST_ENTRY_Y);
+  
+  if (flag)
+    grub_putcode (GRUB_TERM_DISP_UP);
+  else
+    grub_putchar (' ');
+}
+         
+/* Print a down arrow.  */
+static void
+print_down (int flag)
+{
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
+              GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES);
+  
+  if (flag)
+    grub_putcode (GRUB_TERM_DISP_DOWN);
+  else
+    grub_putchar (' ');
+}
+         
+/* Draw the lines of the screen SCREEN.  */
+static void
+update_screen (struct screen *screen, int region_start, int region_column,
+              int up, int down, enum update_mode mode)
+{
+  int up_flag = 0;
+  int down_flag = 0;
+  int y;
+  int i;
+  struct line *linep;
+  
+  /* Check if scrolling is necessary.  */
+  if (screen->y < 0 || screen->y >= GRUB_TERM_NUM_ENTRIES)
+    {
+      if (screen->y < 0)
+       screen->y = 0;
+      else
+       screen->y = GRUB_TERM_NUM_ENTRIES - 1;
+      
+      region_start = 0;
+      region_column = 0;
+      up = 1;
+      down = 1;
+      mode = ALL_LINES;
+    }
+
+  if (mode != NO_LINE)
+    {
+      /* Draw lines. This code is tricky, because this must calculate logical
+        positions.  */
+      y = screen->y - screen->column / GRUB_TERM_ENTRY_WIDTH;
+      i = screen->line;
+      linep = screen->lines + i;
+      while (y > 0)
+       {
+          i--;
+          linep--;
+          y -= get_logical_num_lines (linep);
+       }
+      
+      if (y < 0 || i > 0)
+       up_flag = 1;
+      
+      do
+       {
+         int column;
+         
+         for (column = 0;
+              column <= linep->len && y < GRUB_TERM_NUM_ENTRIES;
+              column += GRUB_TERM_ENTRY_WIDTH, y++)
+           {
+             if (y < 0)
+               continue;
+             
+             if (i == region_start)
+               {
+                 if (region_column >= column
+                     && region_column < column + GRUB_TERM_ENTRY_WIDTH)
+                   print_line (linep, column, region_column - column, y);
+                 else if (region_column < column)
+                   print_line (linep, column, 0, y);
+               }
+             else if (i > region_start && mode == ALL_LINES)
+               print_line (linep, column, 0, y);
+           }
+         
+         if (y == GRUB_TERM_NUM_ENTRIES)
+           {
+             if (column <= linep->len || i + 1 < screen->num_lines)
+               down_flag = 1;
+           }
+         
+         linep++;
+         i++;
+
+         if (mode == ALL_LINES && i == screen->num_lines)
+           for (; y < GRUB_TERM_NUM_ENTRIES; y++)
+             print_empty_line (y);
+                 
+       }
+      while (y < GRUB_TERM_NUM_ENTRIES);
+      
+      /* Draw up and down arrows.  */
+      if (up)
+       print_up (up_flag);
+      if (down)
+       print_down (down_flag);
+    }
+  
+  /* Place the cursor.  */
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1 + screen->x,
+              GRUB_TERM_FIRST_ENTRY_Y + screen->y);
+  
+  grub_refresh ();
+}
+
+/* Insert the string S into the screen SCREEN. This updates the cursor
+   position and redraw the screen. Return zero if fails.  */
+static int
+insert_string (struct screen *screen, char *s, int update)
+{
+  int region_start = screen->num_lines;
+  int region_column = 0;
+  int down = 0;
+  enum update_mode mode = NO_LINE;
+
+  while (*s)
+    {
+      if (*s == '\n')
+       {
+         /* LF is special because it creates a new line.  */
+         struct line *current_linep;
+         struct line *next_linep;
+         int size;
+         
+         /* Make a new line.  */
+         screen->num_lines++;
+         screen->lines = grub_realloc (screen->lines,
+                                       screen->num_lines
+                                       * sizeof (struct line));
+         if (! screen->lines)
+           return 0;
+
+         /* Scroll down. */
+         grub_memmove (screen->lines + screen->line + 2,
+                       screen->lines + screen->line + 1,
+                       ((screen->num_lines - screen->line - 2)
+                        * sizeof (struct line)));
+
+         if (! init_line (screen->lines + screen->line + 1))
+           return 0;
+         
+         /* Fold the line.  */
+         current_linep = screen->lines + screen->line;
+         next_linep = current_linep + 1;
+         size = current_linep->len - screen->column;
+             
+         if (! ensure_space (next_linep, size))
+           return 0;
+         
+         grub_memmove (next_linep->buf,
+                       current_linep->buf + screen->column,
+                       size);
+         current_linep->len = screen->column;
+         next_linep->len = size;
+
+         /* Update a dirty region.  */
+         if (region_start > screen->line)
+           {
+             region_start = screen->line;
+             region_column = screen->column;
+           }
+
+         mode = ALL_LINES;
+         down = 1; /* XXX not optimal.  */
+         
+         /* Move the cursor.  */
+         screen->column = screen->real_column = 0;
+         screen->line++;
+         screen->x = 0;
+         screen->y++;
+
+         s++;
+       }
+      else
+       {
+         /* All but LF.  */
+         char *p;
+         struct line *current_linep;
+         int size;
+         int orig_num, new_num;
+
+         /* Find a string delimited by LF.  */
+         p = grub_strchr (s, '\n');
+         if (! p)
+           p = s + grub_strlen (s);
+
+         /* Insert the string.  */
+         current_linep = screen->lines + screen->line;
+         size = p - s;
+         if (! ensure_space (current_linep, size))
+           return 0;
+
+         grub_memmove (current_linep->buf + screen->column + size,
+                       current_linep->buf + screen->column,
+                       current_linep->len - screen->column);
+         grub_memmove (current_linep->buf + screen->column,
+                       s,
+                       size);
+         orig_num = get_logical_num_lines (current_linep);
+         current_linep->len += size;
+         new_num = get_logical_num_lines (current_linep);
+
+         /* Update the dirty region.  */
+         if (region_start > screen->line)
+           {
+             region_start = screen->line;
+             region_column = screen->column;
+           }
+         
+         if (orig_num != new_num)
+           {
+             mode = ALL_LINES;
+             down = 1; /* XXX not optimal.  */
+           }
+         else if (mode != ALL_LINES)
+           mode = SINGLE_LINE;
+
+         /* Move the cursor.  */
+         screen->column += size;
+         screen->real_column = screen->column;
+         screen->x += size;
+         screen->y += screen->x / GRUB_TERM_ENTRY_WIDTH;
+         screen->x %= GRUB_TERM_ENTRY_WIDTH;
+         
+         s = p;
+       }
+    }
+
+  if (update)
+    update_screen (screen, region_start, region_column, 0, down, mode);
+  
+  return 1;
+}
+
+/* Release the resource allocated for SCREEN.  */
+static void
+destroy_screen (struct screen *screen)
+{
+  int i;
+
+  if (screen->lines)
+    for (i = 0; i < screen->num_lines; i++)
+      {
+       struct line *linep = screen->lines + i;
+       
+       if (linep)
+         grub_free (linep->buf);
+      }
+
+  grub_free (screen->killed_text);
+  grub_free (screen->lines);
+  grub_free (screen);
+}
+
+/* Make a new screen.  */
+static struct screen *
+make_screen (grub_menu_entry_t entry)
+{
+  struct screen *screen;
+
+  /* Initialize the screen.  */
+  screen = grub_malloc (sizeof (*screen));
+  if (! screen)
+    return 0;
+
+  screen->num_lines = 1;
+  screen->column = 0;
+  screen->real_column = 0;
+  screen->line = 0;
+  screen->x = 0;
+  screen->y = 0;
+  screen->killed_text = 0;
+  screen->completion_shown = 0;
+  screen->lines = grub_malloc (sizeof (struct line));
+  if (! screen->lines)
+    goto fail;
+
+  /* Initialize the first line which must be always present.  */
+  if (! init_line (screen->lines))
+    goto fail;
+
+  insert_string (screen, (char *) entry->sourcecode, 0);
+
+  /* Reset the cursor position.  */
+  screen->column = 0;
+  screen->real_column = 0;
+  screen->line = 0;
+  screen->x = 0;
+  screen->y = 0;
+
+  return screen;
+
+ fail:
+  destroy_screen (screen);
+  return 0;
+}
+
+static int
+forward_char (struct screen *screen, int update)
+{
+  struct line *linep;
+  
+  linep = screen->lines + screen->line;
+  if (screen->column < linep->len)
+    {
+      screen->column++;
+      screen->x++;
+      if (screen->x == GRUB_TERM_ENTRY_WIDTH)
+       {
+         screen->x = 0;
+         screen->y++;
+       }
+    }
+  else if (screen->num_lines > screen->line + 1)
+    {
+      screen->column = 0;
+      screen->line++;
+      screen->x = 0;
+      screen->y++;
+    }
+
+  screen->real_column = screen->column;
+
+  if (update)
+    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+  return 1;
+}
+
+static int
+backward_char (struct screen *screen, int update)
+{
+  if (screen->column > 0)
+    {
+      screen->column--;
+      screen->x--;
+      if (screen->x == -1)
+       {
+         screen->x = GRUB_TERM_ENTRY_WIDTH - 1;
+         screen->y--;
+       }
+    }
+  else if (screen->line > 0)
+    {
+      struct line *linep;
+      
+      screen->line--;
+      linep = screen->lines + screen->line;
+      screen->column = linep->len;
+      screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
+      screen->y--;
+    }
+
+  screen->real_column = screen->column;
+
+  if (update)
+    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+  
+  return 1;
+}
+
+static int
+previous_line (struct screen *screen, int update)
+{
+  if (screen->line > 0)
+    {
+      struct line *linep;
+      int dy;
+      
+      /* How many physical lines from the current position
+        to the first physical line?  */
+      dy = screen->column / GRUB_TERM_ENTRY_WIDTH;
+      
+      screen->line--;
+      
+      linep = screen->lines + screen->line;
+      if (linep->len < screen->real_column)
+       screen->column = linep->len;
+      else
+       screen->column = screen->real_column;
+      
+      /* How many physical lines from the current position
+        to the last physical line?  */
+      dy += (linep->len / GRUB_TERM_ENTRY_WIDTH
+            - screen->column / GRUB_TERM_ENTRY_WIDTH);
+      
+      screen->y -= dy + 1;
+      screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
+    }
+  else
+    {
+      screen->y -= screen->column / GRUB_TERM_ENTRY_WIDTH;
+      screen->column = 0;
+      screen->x = 0;
+    }
+
+  if (update)
+    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+  
+  return 1;
+}
+
+static int
+next_line (struct screen *screen, int update)
+{
+  if (screen->line < screen->num_lines - 1)
+    {
+      struct line *linep;
+      int dy;
+      
+      /* How many physical lines from the current position
+        to the last physical line?  */
+      linep = screen->lines + screen->line;
+      dy = (linep->len / GRUB_TERM_ENTRY_WIDTH
+           - screen->column / GRUB_TERM_ENTRY_WIDTH);
+      
+      screen->line++;
+      
+      linep++;
+      if (linep->len < screen->real_column)
+       screen->column = linep->len;
+      else
+       screen->column = screen->real_column;
+      
+      /* How many physical lines from the current position
+        to the first physical line?  */
+      dy += screen->column / GRUB_TERM_ENTRY_WIDTH;
+      
+      screen->y += dy + 1;
+      screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
+    }
+  else
+    {
+      struct line *linep;
+
+      linep = screen->lines + screen->line;
+      screen->y += (linep->len / GRUB_TERM_ENTRY_WIDTH
+                   - screen->column / GRUB_TERM_ENTRY_WIDTH);
+      screen->column = linep->len;
+      screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
+    }
+
+  if (update)
+    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+  
+  return 1;
+}
+
+static int
+beginning_of_line (struct screen *screen, int update)
+{
+  screen->y -= screen->column / GRUB_TERM_ENTRY_WIDTH;
+  screen->column = screen->real_column = 0;
+  screen->x = 0;
+
+  if (update)
+    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+  
+  return 1;
+}
+
+static int
+end_of_line (struct screen *screen, int update)
+{
+  struct line *linep;
+  
+  linep = screen->lines + screen->line;
+  screen->y += (linep->len / GRUB_TERM_ENTRY_WIDTH
+               - screen->column / GRUB_TERM_ENTRY_WIDTH);
+  screen->column = screen->real_column = linep->len;
+  screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
+
+  if (update)
+    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+  
+  return 1;
+}
+
+static int
+delete_char (struct screen *screen, int update)
+{
+  struct line *linep;
+  enum update_mode mode = NO_LINE;
+  int start = screen->num_lines;
+  int column = 0;
+  int down = 0;
+  
+  linep = screen->lines + screen->line;
+  if (linep->len > screen->column)
+    {
+      int orig_num, new_num;
+
+      orig_num = get_logical_num_lines (linep);
+      
+      grub_memmove (linep->buf + screen->column,
+                   linep->buf + screen->column + 1,
+                   linep->len - screen->column - 1);
+      linep->len--;
+
+      new_num = get_logical_num_lines (linep);
+
+      if (orig_num != new_num)
+       mode = ALL_LINES;
+      else
+       mode = SINGLE_LINE;
+
+      start = screen->line;
+      column = screen->column;
+    }
+  else if (screen->num_lines > screen->line + 1)
+    {
+      struct line *next_linep;
+
+      next_linep = linep + 1;
+      if (! ensure_space (linep, next_linep->len))
+       return 0;
+
+      grub_memmove (linep->buf + linep->len, next_linep->buf, next_linep->len);
+      linep->len += next_linep->len;
+
+      grub_free (next_linep->buf);
+      grub_memmove (next_linep,
+                   next_linep + 1,
+                   (screen->num_lines - screen->line - 2)
+                   * sizeof (struct line));
+      screen->num_lines--;
+      
+      mode = ALL_LINES;
+      start = screen->line;
+      column = screen->column;
+      down = 1;
+    }
+
+  screen->real_column = screen->column;
+
+  if (update)
+    update_screen (screen, start, column, 0, down, mode);
+
+  return 1;
+}
+
+static int
+backward_delete_char (struct screen *screen, int update)
+{
+  int saved_column;
+  int saved_line;
+
+  saved_column = screen->column;
+  saved_line = screen->line;
+  
+  if (! backward_char (screen, 0))
+    return 0;
+
+  if (saved_column != screen->column || saved_line != screen->line)
+    if (! delete_char (screen, update))
+      return 0;
+
+  return 1;
+}
+
+static int
+kill_line (struct screen *screen, int continuous, int update)
+{
+  struct line *linep;
+  char *p;
+  int size;
+  int offset;
+  
+  p = screen->killed_text;
+  if (! continuous && p)
+    p[0] = '\0';
+  
+  linep = screen->lines + screen->line;
+  size = linep->len - screen->column;
+  
+  if (p)
+    offset = grub_strlen (p);
+  else
+    offset = 0;
+      
+  if (size > 0)
+    {
+      enum update_mode mode = SINGLE_LINE;
+      int down = 0;
+      int orig_num, new_num;
+      
+      p = grub_realloc (p, offset + size + 1);
+      if (! p)
+       return 0;
+
+      grub_memmove (p + offset, linep->buf + screen->column, size);
+      p[offset + size - 1] = '\0';
+
+      screen->killed_text = p;
+      
+      orig_num = get_logical_num_lines (linep);
+      linep->len = screen->column;
+      new_num = get_logical_num_lines (linep);
+
+      if (orig_num != new_num)
+       {
+         mode = ALL_LINES;
+         down = 1;
+       }
+
+      if (update)
+       update_screen (screen, screen->line, screen->column, 0, down, mode);
+    }
+  else if (screen->line + 1 < screen->num_lines)
+    {
+      p = grub_realloc (p, offset + 1 + 1);
+      if (! p)
+       return 0;
+
+      p[offset] = '\n';
+      p[offset + 1] = '\0';
+
+      screen->killed_text = p;
+      
+      return delete_char (screen, update);
+    }
+    
+  return 1;
+}
+
+static int
+yank (struct screen *screen, int update)
+{
+  if (screen->killed_text)
+    return insert_string (screen, screen->killed_text, update);
+
+  return 1;
+}
+
+static int
+open_line (struct screen *screen, int update)
+{
+  int saved_y = screen->y;
+  
+  if (! insert_string (screen, "\n", 0))
+    return 0;
+
+  if (! backward_char (screen, 0))
+    return 0;
+
+  screen->y = saved_y;
+
+  if (update)
+    update_screen (screen, screen->line, screen->column, 0, 1, ALL_LINES);
+
+  return 1;
+}
+
+/* A completion hook to print items.  */
+static void
+store_completion (const char *item, grub_completion_type_t type, int count)
+{
+  char *p;
+  
+  if (count == 0)
+    {
+      /* If this is the first time, print a label.  */
+      const char *what;
+
+      switch (type)
+       {
+       case GRUB_COMPLETION_TYPE_COMMAND:
+         what = "commands";
+         break;
+       case GRUB_COMPLETION_TYPE_DEVICE:
+         what = "devices";
+         break;
+       case GRUB_COMPLETION_TYPE_FILE:
+         what = "files";
+         break;
+       case GRUB_COMPLETION_TYPE_PARTITION:
+         what = "partitions";
+         break;
+       case GRUB_COMPLETION_TYPE_ARGUMENT:
+         what = "arguments";
+         break;
+       default:
+         what = "things";
+         break;
+       }
+           
+      grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
+      grub_printf ("   Possible %s are:\n    ", what);
+    }
+
+  /* Make sure that the completion buffer has enough room.  */
+  if (completion_buffer.max_len < (completion_buffer.len
+                                  + (int) grub_strlen (item) + 1 + 1))
+    {
+      grub_size_t new_len;
+      
+      new_len = completion_buffer.len + grub_strlen (item) + 80;
+      p = grub_realloc (completion_buffer.buf, new_len);
+      if (! p)
+       {
+         /* Possibly not fatal.  */
+         grub_errno = GRUB_ERR_NONE;
+         return;
+       }
+      p[completion_buffer.len] = 0;
+      completion_buffer.buf = p;
+      completion_buffer.max_len = new_len;
+    }
+
+  p = completion_buffer.buf + completion_buffer.len;
+  if (completion_buffer.len != 0)
+    {
+      *p++ = ' ';
+      completion_buffer.len++;
+    }
+  grub_strcpy (p, item);
+  completion_buffer.len += grub_strlen (item);
+}
+
+static int
+complete (struct screen *screen, int continuous, int update)
+{
+  grub_uint16_t pos;
+  char saved_char;
+  struct line *linep;
+  int restore;
+  char *insert;
+  static int count = -1;
+
+  if (continuous)
+    count++;
+  else
+    count = 0;
+  
+  pos = grub_getxy ();
+  grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
+  
+  completion_buffer.buf = 0;
+  completion_buffer.len = 0;
+  completion_buffer.max_len = 0;
+
+  linep = screen->lines + screen->line;
+  saved_char = linep->buf[screen->column];
+  linep->buf[screen->column] = '\0';
+
+  insert = grub_normal_do_completion (linep->buf, &restore, store_completion);
+
+  linep->buf[screen->column] = saved_char;
+  
+  if (restore)
+    {
+      char *p = completion_buffer.buf;
+
+      screen->completion_shown = 1;
+      
+      if (p)
+       {
+         int num_sections = ((completion_buffer.len + GRUB_TERM_WIDTH - 8 - 1)
+                             / (GRUB_TERM_WIDTH - 8));
+         char *endp;
+
+         p += (count % num_sections) * (GRUB_TERM_WIDTH - 8);
+         endp = p + (GRUB_TERM_WIDTH - 8);
+
+         if (p != completion_buffer.buf)
+           grub_putcode (GRUB_TERM_DISP_LEFT);
+         else
+           grub_putchar (' ');
+         
+         while (*p && p < endp)
+           grub_putchar (*p++);
+         
+         if (*p)
+           grub_putcode (GRUB_TERM_DISP_RIGHT);
+       }
+    }
+
+  grub_gotoxy (pos >> 8, pos & 0xFF);
+  
+  if (insert)
+    {
+      insert_string (screen, insert, update);
+      count = -1;
+      grub_free (insert);
+    }
+  else if (update)
+    grub_refresh ();
+    
+  grub_free (completion_buffer.buf);
+  return 1;
+}
+
+/* Clear displayed completions.  */
+static void
+clear_completions (void)
+{
+  grub_uint16_t pos;
+  int i, j;
+  
+  pos = grub_getxy ();
+  grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
+  
+  for (i = 0; i < 2; i++)
+    {
+      for (j = 0; j < GRUB_TERM_WIDTH - 1; j++)
+       grub_putchar (' ');
+      grub_putchar ('\n');
+    }
+  
+  grub_gotoxy (pos >> 8, pos & 0xFF);
+  grub_refresh ();
+}
+
+/* Execute the command list in the screen SCREEN.  */
+static int
+run (struct screen *screen)
+{
+  struct grub_script *parsed_script = 0;
+  int currline = 0;
+  char *nextline;
+
+  auto grub_err_t editor_getline (char **line);
+  grub_err_t editor_getline (char **line)
+    {
+      struct line *linep = screen->lines + currline;
+      char *p;
+
+      if (currline > screen->num_lines)
+       {
+         *line = 0;
+         return 0;
+       }
+
+      /* Trim down space characters.  */
+      for (p = linep->buf + linep->len - 1;
+          p >= linep->buf && grub_isspace (*p);
+          p--)
+       ;
+      *++p = '\0';
+
+      linep->len = p - linep->buf;
+      for (p = linep->buf; grub_isspace (*p); p++)
+       ;
+      *line = grub_strdup (p);
+      currline++;
+      return 0;
+    }
+  
+  grub_cls ();
+  grub_printf ("  Booting a command list\n\n");
+
+
+  /* Execute the script, line for line.  */
+  while (currline < screen->num_lines)
+    {
+      editor_getline (&nextline);
+      parsed_script = grub_script_parse (nextline, editor_getline);
+      if (parsed_script)
+       {
+         /* Execute the command(s).  */
+         grub_script_execute (parsed_script);
+         
+         /* The parsed script was executed, throw it away.  */
+         grub_script_free (parsed_script);
+       }
+      else
+       break;
+    }
+
+  if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
+    /* Implicit execution of boot, only if something is loaded.  */
+    grub_command_execute ("boot", 0);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+      grub_wait_after_message ();
+    }
+
+  return 1;
+}
+
+/* Edit a menu entry with an Emacs-like interface.  */
+void
+grub_menu_entry_run (grub_menu_entry_t entry)
+{
+  struct screen *screen;
+  int prev_c;
+  
+  screen = make_screen (entry);
+  if (! screen)
+    return;
+
+ refresh:
+  /* Draw the screen.  */
+  grub_menu_init_page (0, 1);
+  update_screen (screen, 0, 0, 1, 1, ALL_LINES);
+  grub_setcursor (1);
+  prev_c = '\0';
+  
+  while (1)
+    {
+      int c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
+
+      if (screen->completion_shown)
+       {
+         clear_completions ();
+         screen->completion_shown = 0;
+       }
+      
+      switch (c)
+       {
+       case 16: /* C-p */
+         if (! previous_line (screen, 1))
+           goto fail;
+         break;
+
+       case 14: /* C-n */
+         if (! next_line (screen, 1))
+           goto fail;
+         break;
+
+       case 6: /* C-f */
+         if (! forward_char (screen, 1))
+           goto fail;
+         break;
+         
+       case 2: /* C-b */
+         if (! backward_char (screen, 1))
+           goto fail;
+         break;
+
+       case 1: /* C-a */
+         if (! beginning_of_line (screen, 1))
+           goto fail;
+         break;
+
+       case 5: /* C-e */
+         if (! end_of_line (screen, 1))
+           goto fail;
+         break;
+         
+       case '\t': /* C-i */
+         if (! complete (screen, prev_c == c, 1))
+           goto fail;
+         break;
+         
+       case 4: /* C-d */
+         if (! delete_char (screen, 1))
+           goto fail;
+         break;
+
+       case 8: /* C-h */
+         if (! backward_delete_char (screen, 1))
+           goto fail;
+         break;
+         
+       case 11: /* C-k */
+         if (! kill_line (screen, prev_c == c, 1))
+           goto fail;
+         break;
+         
+       case 21: /* C-u */
+         /* FIXME: What behavior is good for this key?  */
+         break;
+         
+       case 25: /* C-y */
+         if (! yank (screen, 1))
+           goto fail;
+         break;
+
+       case 12: /* C-l */
+         /* FIXME: centering.  */
+         goto refresh;
+         
+       case 15: /* C-o */
+         if (! open_line (screen, 1))
+           goto fail;
+         break;
+
+       case '\n':
+       case '\r':
+         if (! insert_string (screen, "\n", 1))
+           goto fail;
+         break;
+
+       case '\e':
+         destroy_screen (screen);
+         return;
+         
+       case 3: /* C-c */
+         grub_cmdline_run (1);
+         goto refresh;
+         
+       case 24: /* C-x */
+         if (! run (screen))
+           goto fail;
+         goto refresh;
+
+       case 18: /* C-r */
+       case 19: /* C-s */
+       case 20: /* C-t */
+         /* FIXME */
+         break;
+         
+       default:
+         if (grub_isprint (c))
+           {
+             char buf[2];
+
+             buf[0] = c;
+             buf[1] = '\0';
+             if (! insert_string (screen, buf, 1))
+               goto fail;
+           }
+         break;
+       }
+
+      prev_c = c;
+    }
+
+ fail:
+  destroy_screen (screen);
+  
+  grub_cls ();
+  grub_print_error ();
+  grub_errno = GRUB_ERR_NONE;
+  grub_printf ("\nPress any key to continue...");
+  (void) grub_getkey ();
+}
diff --git a/normal/menu_text.c b/normal/menu_text.c
new file mode 100644 (file)
index 0000000..cb22982
--- /dev/null
@@ -0,0 +1,600 @@
+/* menu_text.c - Basic text menu implementation.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/loader.h>
+#include <grub/mm.h>
+#include <grub/time.h>
+#include <grub/env.h>
+#include <grub/script.h>
+#include <grub/menu_viewer.h>
+
+/* Time to delay after displaying an error message about a default/fallback
+   entry failing to boot.  */
+#define DEFAULT_ENTRY_ERROR_DELAY_MS  2500
+
+static grub_uint8_t grub_color_menu_normal;
+static grub_uint8_t grub_color_menu_highlight;
+
+/* Wait until the user pushes any key so that the user
+   can see what happened.  */
+void
+grub_wait_after_message (void)
+{
+  grub_printf ("\nPress any key to continue...");
+  (void) grub_getkey ();
+}
+
+static void
+draw_border (void)
+{
+  unsigned i;
+
+  grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+
+  grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y);
+  grub_putcode (GRUB_TERM_DISP_UL);
+  for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++)
+    grub_putcode (GRUB_TERM_DISP_HLINE);
+  grub_putcode (GRUB_TERM_DISP_UR);
+
+  for (i = 0; i < (unsigned) GRUB_TERM_NUM_ENTRIES; i++)
+    {
+      grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1);
+      grub_putcode (GRUB_TERM_DISP_VLINE);
+      grub_gotoxy (GRUB_TERM_MARGIN + GRUB_TERM_BORDER_WIDTH - 1,
+                  GRUB_TERM_TOP_BORDER_Y + i + 1);
+      grub_putcode (GRUB_TERM_DISP_VLINE);
+    }
+
+  grub_gotoxy (GRUB_TERM_MARGIN,
+              GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES + 1);
+  grub_putcode (GRUB_TERM_DISP_LL);
+  for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++)
+    grub_putcode (GRUB_TERM_DISP_HLINE);
+  grub_putcode (GRUB_TERM_DISP_LR);
+
+  grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+
+  grub_gotoxy (GRUB_TERM_MARGIN,
+              (GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES
+               + GRUB_TERM_MARGIN + 1));
+}
+
+static void
+print_message (int nested, int edit)
+{
+  grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+
+  if (edit)
+    {
+      grub_printf ("\n\
+      Minimum Emacs-like screen editing is supported. TAB lists\n\
+      completions. Press Ctrl-x to boot, Ctrl-c for a command-line\n\
+      or ESC to return menu.");
+    }
+  else
+    {
+      grub_printf ("\n\
+      Use the %C and %C keys to select which entry is highlighted.\n",
+                  (grub_uint32_t) GRUB_TERM_DISP_UP, (grub_uint32_t) GRUB_TERM_DISP_DOWN);
+      grub_printf ("\
+      Press enter to boot the selected OS, \'e\' to edit the\n\
+      commands before booting or \'c\' for a command-line.");
+      if (nested)
+       grub_printf ("\n\
+      ESC to return previous menu.");
+    }
+}
+
+static void
+print_entry (int y, int highlight, grub_menu_entry_t entry)
+{
+  int x;
+  const char *title;
+  grub_size_t title_len;
+  grub_ssize_t len;
+  grub_uint32_t *unicode_title;
+  grub_ssize_t i;
+  grub_uint8_t old_color_normal, old_color_highlight;
+
+  title = entry ? entry->title : "";
+  title_len = grub_strlen (title);
+  unicode_title = grub_malloc (title_len * sizeof (*unicode_title));
+  if (! unicode_title)
+    /* XXX How to show this error?  */
+    return;
+
+  len = grub_utf8_to_ucs4 (unicode_title, title_len,
+                           (grub_uint8_t *) title, -1, 0);
+  if (len < 0)
+    {
+      /* It is an invalid sequence.  */
+      grub_free (unicode_title);
+      return;
+    }
+
+  grub_getcolor (&old_color_normal, &old_color_highlight);
+  grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight);
+  grub_setcolorstate (highlight
+                     ? GRUB_TERM_COLOR_HIGHLIGHT
+                     : GRUB_TERM_COLOR_NORMAL);
+
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN, y);
+
+  for (x = GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1, i = 0;
+       x < GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH - GRUB_TERM_MARGIN;
+       i++)
+    {
+      if (i < len
+         && x <= (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH
+                  - GRUB_TERM_MARGIN - 1))
+       {
+         grub_ssize_t width;
+
+         width = grub_getcharwidth (unicode_title[i]);
+
+         if (x + width > (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH
+                          - GRUB_TERM_MARGIN - 1))
+           grub_putcode (GRUB_TERM_DISP_RIGHT);
+         else
+           grub_putcode (unicode_title[i]);
+
+         x += width;
+       }
+      else
+       {
+         grub_putchar (' ');
+         x++;
+       }
+    }
+  grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+  grub_putchar (' ');
+
+  grub_gotoxy (GRUB_TERM_CURSOR_X, y);
+
+  grub_setcolor (old_color_normal, old_color_highlight);
+  grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+  grub_free (unicode_title);
+}
+
+static void
+print_entries (grub_menu_t menu, int first, int offset)
+{
+  grub_menu_entry_t e;
+  int i;
+
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
+              GRUB_TERM_FIRST_ENTRY_Y);
+
+  if (first)
+    grub_putcode (GRUB_TERM_DISP_UP);
+  else
+    grub_putchar (' ');
+
+  e = grub_menu_get_entry (menu, first);
+
+  for (i = 0; i < GRUB_TERM_NUM_ENTRIES; i++)
+    {
+      print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, offset == i, e);
+      if (e)
+       e = e->next;
+    }
+
+  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
+              GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES);
+
+  if (e)
+    grub_putcode (GRUB_TERM_DISP_DOWN);
+  else
+    grub_putchar (' ');
+
+  grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
+}
+
+/* Initialize the screen.  If NESTED is non-zero, assume that this menu
+   is run from another menu or a command-line. If EDIT is non-zero, show
+   a message for the menu entry editor.  */
+void
+grub_menu_init_page (int nested, int edit)
+{
+  grub_uint8_t old_color_normal, old_color_highlight;
+
+  grub_getcolor (&old_color_normal, &old_color_highlight);
+
+  /* By default, use the same colors for the menu.  */
+  grub_color_menu_normal = old_color_normal;
+  grub_color_menu_highlight = old_color_highlight;
+
+  /* Then give user a chance to replace them.  */
+  grub_parse_color_name_pair (&grub_color_menu_normal, grub_env_get ("menu_color_normal"));
+  grub_parse_color_name_pair (&grub_color_menu_highlight, grub_env_get ("menu_color_highlight"));
+
+  grub_normal_init_page ();
+  grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight);
+  draw_border ();
+  grub_setcolor (old_color_normal, old_color_highlight);
+  print_message (nested, edit);
+}
+
+/* Get the entry number from the variable NAME.  */
+static int
+get_entry_number (const char *name)
+{
+  char *val;
+  int entry;
+
+  val = grub_env_get (name);
+  if (! val)
+    return -1;
+
+  grub_error_push ();
+
+  entry = (int) grub_strtoul (val, 0, 0);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_errno = GRUB_ERR_NONE;
+      entry = -1;
+    }
+
+  grub_error_pop ();
+
+  return entry;
+}
+
+static void
+print_timeout (int timeout, int offset, int second_stage)
+{
+  /* NOTE: Do not remove the trailing space characters.
+     They are required to clear the line.  */
+  char *msg = "   The highlighted entry will be booted automatically in %ds.    ";
+  char *msg_end = grub_strchr (msg, '%');
+
+  grub_gotoxy (second_stage ? (msg_end - msg) : 0, GRUB_TERM_HEIGHT - 3);
+  grub_printf (second_stage ? msg_end : msg, timeout);
+  grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
+  grub_refresh ();
+};
+
+/* Show the menu and handle menu entry selection.  Returns the menu entry
+   index that should be executed or -1 if no entry should be executed (e.g.,
+   Esc pressed to exit a sub-menu or switching menu viewers).
+   If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu
+   entry to be executed is a result of an automatic default selection because
+   of the timeout.  */
+static int
+run_menu (grub_menu_t menu, int nested, int *auto_boot)
+{
+  int first, offset;
+  grub_uint64_t saved_time;
+  int default_entry;
+  int timeout;
+
+  first = 0;
+
+  default_entry = get_entry_number ("default");
+
+  /* If DEFAULT_ENTRY is not within the menu entries, fall back to
+     the first entry.  */
+  if (default_entry < 0 || default_entry >= menu->size)
+    default_entry = 0;
+
+  /* If timeout is 0, drawing is pointless (and ugly).  */
+  if (grub_menu_get_timeout () == 0)
+    {
+      *auto_boot = 1;
+      return default_entry;
+    }
+
+  offset = default_entry;
+  if (offset > GRUB_TERM_NUM_ENTRIES - 1)
+    {
+      first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
+      offset = GRUB_TERM_NUM_ENTRIES - 1;
+    }
+
+  /* Initialize the time.  */
+  saved_time = grub_get_time_ms ();
+
+ refresh:
+  grub_setcursor (0);
+  grub_menu_init_page (nested, 0);
+  print_entries (menu, first, offset);
+  grub_refresh ();
+
+  timeout = grub_menu_get_timeout ();
+
+  if (timeout > 0)
+    print_timeout (timeout, offset, 0);
+
+  while (1)
+    {
+      int c;
+      timeout = grub_menu_get_timeout ();
+
+      if (timeout > 0)
+       {
+         grub_uint64_t current_time;
+
+         current_time = grub_get_time_ms ();
+         if (current_time - saved_time >= 1000)
+           {
+             timeout--;
+             grub_menu_set_timeout (timeout);
+             saved_time = current_time;
+             print_timeout (timeout, offset, 1);
+           }
+       }
+
+      if (timeout == 0)
+       {
+         grub_env_unset ("timeout");
+          *auto_boot = 1;
+         return default_entry;
+       }
+
+      if (grub_checkkey () >= 0 || timeout < 0)
+       {
+         c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
+
+         if (timeout >= 0)
+           {
+             grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
+              grub_printf ("\
+                                                                        ");
+             grub_env_unset ("timeout");
+             grub_env_unset ("fallback");
+             grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
+           }
+
+         switch (c)
+           {
+           case GRUB_TERM_HOME:
+             first = 0;
+             offset = 0;
+             print_entries (menu, first, offset);
+             break;
+
+           case GRUB_TERM_END:
+             offset = menu->size - 1;
+             if (offset > GRUB_TERM_NUM_ENTRIES - 1)
+               {
+                 first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
+                 offset = GRUB_TERM_NUM_ENTRIES - 1;
+               }
+               print_entries (menu, first, offset);
+             break;
+
+           case GRUB_TERM_UP:
+           case '^':
+             if (offset > 0)
+               {
+                 print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
+                              grub_menu_get_entry (menu, first + offset));
+                 offset--;
+                 print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
+                              grub_menu_get_entry (menu, first + offset));
+               }
+             else if (first > 0)
+               {
+                 first--;
+                 print_entries (menu, first, offset);
+               }
+             break;
+
+           case GRUB_TERM_DOWN:
+           case 'v':
+             if (menu->size > first + offset + 1)
+               {
+                 if (offset < GRUB_TERM_NUM_ENTRIES - 1)
+                   {
+                     print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
+                                  grub_menu_get_entry (menu, first + offset));
+                     offset++;
+                     print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
+                                  grub_menu_get_entry (menu, first + offset));
+                   }
+                 else
+                   {
+                     first++;
+                     print_entries (menu, first, offset);
+                   }
+               }
+             break;
+
+           case GRUB_TERM_PPAGE:
+             if (first == 0)
+               {
+                 offset = 0;
+               }
+             else
+               {
+                 first -= GRUB_TERM_NUM_ENTRIES;
+
+                 if (first < 0)
+                   {
+                     offset += first;
+                     first = 0;
+                   }
+               }
+             print_entries (menu, first, offset);
+             break;
+
+           case GRUB_TERM_NPAGE:
+             if (offset == 0)
+               {
+                 offset += GRUB_TERM_NUM_ENTRIES - 1;
+                 if (first + offset >= menu->size)
+                   {
+                     offset = menu->size - first - 1;
+                   }
+               }
+             else
+               {
+                 first += GRUB_TERM_NUM_ENTRIES;
+
+                 if (first + offset >= menu->size)
+                   {
+                     first -= GRUB_TERM_NUM_ENTRIES;
+                     offset += GRUB_TERM_NUM_ENTRIES;
+
+                     if (offset > menu->size - 1 ||
+                         offset > GRUB_TERM_NUM_ENTRIES - 1)
+                       {
+                         offset = menu->size - first - 1;
+                       }
+                     if (offset > GRUB_TERM_NUM_ENTRIES)
+                       {
+                         first += offset - GRUB_TERM_NUM_ENTRIES + 1;
+                         offset = GRUB_TERM_NUM_ENTRIES - 1;
+                       }
+                   }
+               }
+             print_entries (menu, first, offset);
+             break;
+
+           case '\n':
+           case '\r':
+           case 6:
+             grub_setcursor (1);
+              *auto_boot = 0;
+             return first + offset;
+
+           case '\e':
+             if (nested)
+               {
+                 grub_setcursor (1);
+                 return -1;
+               }
+             break;
+
+           case 'c':
+             grub_cmdline_run (1);
+             goto refresh;
+
+           case 'e':
+               {
+                 grub_menu_entry_t e = grub_menu_get_entry (menu, first + offset);
+                 if (e)
+                   grub_menu_entry_run (e);
+               }
+             goto refresh;
+
+           default:
+             break;
+           }
+
+         grub_refresh ();
+       }
+    }
+
+  /* Never reach here.  */
+  return -1;
+}
+
+/* Callback invoked immediately before a menu entry is executed.  */
+static void
+notify_booting (grub_menu_entry_t entry,
+               void *userdata __attribute__((unused)))
+{
+  grub_printf ("  Booting \'%s\'\n\n", entry->title);
+}
+
+/* Callback invoked when a default menu entry executed because of a timeout
+   has failed and an attempt will be made to execute the next fallback
+   entry, ENTRY.  */
+static void
+notify_fallback (grub_menu_entry_t entry,
+                void *userdata __attribute__((unused)))
+{
+  grub_printf ("\n  Falling back to \'%s\'\n\n", entry->title);
+  grub_millisleep (DEFAULT_ENTRY_ERROR_DELAY_MS);
+}
+
+/* Callback invoked when a menu entry has failed and there is no remaining
+   fallback entry to attempt.  */
+static void
+notify_execution_failure (void *userdata __attribute__((unused)))
+{
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_print_error ();
+      grub_errno = GRUB_ERR_NONE;
+    }
+  grub_printf ("\n  Failed to boot default entries.\n");
+  grub_wait_after_message ();
+}
+
+/* Callbacks used by the text menu to provide user feedback when menu entries
+   are executed.  */
+static struct grub_menu_execute_callback execution_callback =
+{
+  .notify_booting = notify_booting,
+  .notify_fallback = notify_fallback,
+  .notify_failure = notify_execution_failure
+};
+
+static grub_err_t
+show_text_menu (grub_menu_t menu, int nested)
+{
+  while (1)
+    {
+      int boot_entry;
+      grub_menu_entry_t e;
+      int auto_boot;
+
+      boot_entry = run_menu (menu, nested, &auto_boot);
+      if (boot_entry < 0)
+       break;
+
+      e = grub_menu_get_entry (menu, boot_entry);
+      if (! e)
+       continue; /* Menu is empty.  */
+
+      grub_cls ();
+      grub_setcursor (1);
+
+      if (auto_boot)
+        {
+          grub_menu_execute_with_fallback (menu, e, &execution_callback, 0);
+        }
+      else
+        {
+          grub_errno = GRUB_ERR_NONE;
+          grub_menu_execute_entry (e);
+          if (grub_errno != GRUB_ERR_NONE)
+            {
+              grub_print_error ();
+              grub_errno = GRUB_ERR_NONE;
+              grub_wait_after_message ();
+            }
+        }
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+struct grub_menu_viewer grub_normal_text_menu_viewer =
+{
+  .name = "text",
+  .show_menu = show_text_menu
+};
diff --git a/normal/menu_viewer.c b/normal/menu_viewer.c
new file mode 100644 (file)
index 0000000..f7047c7
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *  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/mm.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/menu_viewer.h>
+#include <grub/menu.h>
+
+/* The list of menu viewers.  */
+static grub_menu_viewer_t menu_viewer_list;
+
+void
+grub_menu_viewer_register (grub_menu_viewer_t viewer)
+{
+  viewer->next = menu_viewer_list;
+  menu_viewer_list = viewer;
+}
+
+static grub_menu_viewer_t get_current_menu_viewer (void)
+{
+  const char *selected_name = grub_env_get ("menuviewer");
+
+  /* If none selected, pick the last registered one. */
+  if (selected_name == 0)
+    return menu_viewer_list;
+
+  grub_menu_viewer_t cur;
+  for (cur = menu_viewer_list; cur; cur = cur->next)
+    {
+      if (grub_strcmp (cur->name, selected_name) == 0)
+        return cur;
+    }
+
+  /* Fall back to the first entry (or null).  */
+  return menu_viewer_list;
+}
+
+grub_err_t
+grub_menu_viewer_show_menu (grub_menu_t menu, int nested)
+{
+  grub_menu_viewer_t cur = get_current_menu_viewer ();
+  if (!cur) 
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "No menu viewer available.");
+
+  return cur->show_menu (menu, nested);
+}
+
diff --git a/normal/misc.c b/normal/misc.c
new file mode 100644 (file)
index 0000000..e47ff87
--- /dev/null
@@ -0,0 +1,89 @@
+/* misc.c - miscellaneous functions */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,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/>.
+ */
+
+#include <grub/normal.h>
+#include <grub/disk.h>
+#include <grub/fs.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+
+/* Print the information on the device NAME.  */
+grub_err_t
+grub_normal_print_device_info (const char *name)
+{
+  grub_device_t dev;
+  char *p;
+
+  p = grub_strchr (name, ',');
+  if (p)
+    grub_printf ("\tPartition %s: ", name);
+  else
+    grub_printf ("Device %s: ", name);
+  
+  dev = grub_device_open (name);
+  if (! dev)
+    grub_printf ("Filesystem cannot be accessed");
+  else if (dev->disk)
+    {
+      grub_fs_t fs;
+
+      fs = grub_fs_probe (dev);
+      /* Ignore all errors.  */
+      grub_errno = 0;
+
+      if (fs)
+       {
+         grub_printf ("Filesystem type %s", fs->name);
+         if (fs->label)
+           {
+             char *label;
+             (fs->label) (dev, &label);
+             if (grub_errno == GRUB_ERR_NONE)
+               {
+                 if (label && grub_strlen (label))
+                   grub_printf (", Label %s", label);
+                 grub_free (label);
+               }
+             grub_errno = GRUB_ERR_NONE;
+           }
+         if (fs->uuid)
+           {
+             char *uuid;
+             (fs->uuid) (dev, &uuid);
+             if (grub_errno == GRUB_ERR_NONE)
+               {
+                 if (uuid && grub_strlen (uuid))
+                   grub_printf (", UUID %s", uuid);
+                 grub_free (uuid);
+               }
+             grub_errno = GRUB_ERR_NONE;
+           }
+       }
+      else if (! dev->disk->has_partitions || dev->disk->partition)
+       grub_printf ("Unknown filesystem");
+      else
+       grub_printf ("Partition table");
+         
+      grub_device_close (dev);
+    }
+
+  grub_printf ("\n");
+  return grub_errno;
+}
diff --git a/normal/parser.y b/normal/parser.y
new file mode 100644 (file)
index 0000000..eaf400b
--- /dev/null
@@ -0,0 +1,238 @@
+/* parser.y - The scripting parser.  */
+/*
+ *  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/>.
+ */
+
+%{
+#include <grub/script.h>
+#include <grub/mm.h>
+
+#define YYFREE         grub_free
+#define YYMALLOC       grub_malloc
+#define YYLTYPE_IS_TRIVIAL      0
+#define YYENABLE_NLS   0
+
+%}
+
+%union {
+  struct grub_script_cmd *cmd;
+  struct grub_script_arglist *arglist;
+  struct grub_script_arg *arg;
+  char *string;
+}
+
+%token GRUB_PARSER_TOKEN_IF            "if"
+%token GRUB_PARSER_TOKEN_WHILE         "while"
+%token GRUB_PARSER_TOKEN_FUNCTION      "function"
+%token GRUB_PARSER_TOKEN_MENUENTRY     "menuentry"
+%token GRUB_PARSER_TOKEN_ELSE          "else"
+%token GRUB_PARSER_TOKEN_THEN          "then"
+%token GRUB_PARSER_TOKEN_FI            "fi"
+%token GRUB_PARSER_TOKEN_NAME
+%token GRUB_PARSER_TOKEN_VAR
+%type <cmd> script_init script grubcmd command commands commandblock menuentry if
+%type <arglist> arguments;
+%type <arg> argument;
+%type <string> "if" "while" "function" "else" "then" "fi"
+%type <string> text GRUB_PARSER_TOKEN_NAME GRUB_PARSER_TOKEN_VAR
+
+%pure-parser
+%lex-param { struct grub_parser_param *state };
+%parse-param { struct grub_parser_param *state };
+
+%%
+/* It should be possible to do this in a clean way...  */
+script_init:   { state->err = 0; } script
+                 {
+                   state->parsed = $2;
+                 }
+;
+
+script:                commands { $$ = $1; }
+               | function '\n' { $$ = 0; }
+               | menuentry '\n' { $$ = $1; }
+;
+
+delimiter:     '\n'
+               | ';'
+               | delimiter '\n'
+;
+
+newlines:      /* Empty */
+               | newlines '\n'
+;
+
+/* Some tokens are both used as token or as plain text.  XXX: Add all
+   tokens without causing conflicts.  */
+text:          GRUB_PARSER_TOKEN_NAME
+                 {
+                   $$ = $1;
+                 }
+               | "if"
+                 {
+                   $$ = $1;
+                 }
+               | "while"
+                 {
+                   $$ = $1;
+                 }
+;
+
+/* An argument can consist of some static text mixed with variables,
+   for example: `foo${bar}baz'.  */
+argument:      GRUB_PARSER_TOKEN_VAR
+                 {
+                   $$ = grub_script_arg_add (state, 0, GRUB_SCRIPT_ARG_TYPE_VAR, $1);
+                 }
+               | text
+                 {
+                   $$ = grub_script_arg_add (state, 0, GRUB_SCRIPT_ARG_TYPE_STR, $1);
+                 }
+/* XXX: Currently disabled to simplify the parser.  This should be
+   parsed by yet another parser for readability.  */
+/*             | argument GRUB_PARSER_TOKEN_VAR */
+/*               { */
+/*                 $$ = grub_script_arg_add ($1, GRUB_SCRIPT_ARG_TYPE_VAR, $2); */
+/*               } */
+/*             | argument text */
+/*               { */
+/*                 $$ = grub_script_arg_add ($1, GRUB_SCRIPT_ARG_TYPE_STR, $2); */
+/*               } */
+;
+
+arguments:     argument
+                 {
+                   $$ = grub_script_add_arglist (state, 0, $1);
+                 }
+               | arguments argument
+                 {
+                   $$ = grub_script_add_arglist (state, $1, $2);
+                 }
+;
+
+grubcmd:       GRUB_PARSER_TOKEN_NAME arguments
+                 {
+                   $$ = grub_script_create_cmdline (state, $1, $2);
+                 }
+               | GRUB_PARSER_TOKEN_NAME
+                 {
+                   $$ = grub_script_create_cmdline (state, $1, 0);
+                 }
+;
+
+/* A single command.  */
+command:       grubcmd delimiter { $$ = $1; }
+               | if delimiter  { $$ = $1; }
+               | commandblock delimiter { $$ = $1; }
+               | error delimiter
+                 {
+                   $$ = 0;
+                   yyerror (state, "Incorrect command");
+                   state->err = 1;
+                   yyerrok;
+                 }
+;
+
+/* A block of commands.  */
+commands:      command
+                 {
+                   $$ = grub_script_add_cmd (state, 0, $1);
+                 }
+               | command commands
+                 {
+                   struct grub_script_cmdblock *cmd;
+                   cmd = (struct grub_script_cmdblock *) $2;
+                   $$ = grub_script_add_cmd (state, cmd, $1);
+                 }
+;
+
+/* A function.  Carefully save the memory that is allocated.  Don't
+   change any stuff because it might seem like a fun thing to do!
+   Special care was take to make sure the mid-rule actions are
+   executed on the right moment.  So the `commands' rule should be
+   recognized after executing the `grub_script_mem_record; and before
+   `grub_script_mem_record_stop'.  */
+function:      "function" GRUB_PARSER_TOKEN_NAME
+                 { 
+                   grub_script_lexer_ref (state->lexerstate);
+                 } newlines '{'
+                 { 
+                   /* The first part of the function was recognized.
+                      Now start recording the memory usage to store
+                      this function.  */
+                   state->func_mem = grub_script_mem_record (state);
+                 } newlines commands '}'
+                 {
+                   struct grub_script *script;
+
+                   /* All the memory usage for parsing this function
+                      was recorded.  */
+                   state->func_mem = grub_script_mem_record_stop (state,
+                                                                  state->func_mem);
+                   script = grub_script_create ($8, state->func_mem);
+                   if (script)
+                     grub_script_function_create ($2, script);
+                   grub_script_lexer_deref (state->lexerstate);
+                 }
+;
+
+/* Carefully designed, together with `menuentry' so everything happens
+   just in the expected order.  */
+commandblock:  '{'
+                 {
+                   grub_script_lexer_ref (state->lexerstate);
+                 }
+                newlines commands '}'
+                  {
+                   grub_script_lexer_deref (state->lexerstate);
+                   $$ = $4;
+                 }
+;
+
+/* A menu entry.  Carefully save the memory that is allocated.  */
+menuentry:     "menuentry" arguments
+                 {
+                   grub_script_lexer_ref (state->lexerstate);
+                 } newlines '{'
+                 {
+                   grub_script_lexer_record_start (state->lexerstate);
+                 } newlines commands '}'
+                 {
+                   char *menu_entry;
+                   menu_entry = grub_script_lexer_record_stop (state->lexerstate);
+                   grub_script_lexer_deref (state->lexerstate);
+                   $$ = grub_script_create_cmdmenu (state, $2, menu_entry, 0);
+                 }
+;
+
+/* The first part of the if statement.  It's used to switch the lexer
+   to a state in which it demands more tokens.  */
+if_statement:  "if" { grub_script_lexer_ref (state->lexerstate); }
+;
+
+/* The if statement.  */
+if:             if_statement commands "then" newlines commands "fi"
+                 {
+                   $$ = grub_script_create_cmdif (state, $2, $5, 0);
+                   grub_script_lexer_deref (state->lexerstate);
+                 }
+                | if_statement commands "then" newlines commands "else" newlines commands  "fi"
+                 {
+                   $$ = grub_script_create_cmdif (state, $2, $5, $8);
+                   grub_script_lexer_deref (state->lexerstate);
+                 }
+;
diff --git a/normal/powerpc/setjmp.S b/normal/powerpc/setjmp.S
new file mode 100644 (file)
index 0000000..25cbaa3
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,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/>.
+ */
+
+#include <grub/symbol.h>
+
+       .file   "setjmp.S"
+
+       .text
+
+/*
+ * int grub_setjmp (grub_jmp_buf env)
+ */
+FUNCTION(grub_setjmp)
+       stw     1, 0(3)
+       stw     14, 4(3)
+       stw     15, 8(3)
+       stw     16, 12(3)
+       stw     17, 16(3)
+       stw     18, 20(3)
+       stw     19, 24(3)
+       stw     20, 28(3)
+       stw     21, 32(3)
+       stw     22, 36(3)
+       stw     23, 40(3)
+       stw     24, 44(3)
+       stw     25, 48(3)
+       stw     26, 52(3)
+       stw     27, 56(3)
+       stw     28, 60(3)
+       stw     29, 64(3)
+       stw     30, 68(3)
+       mflr    4
+       stw     4, 72(3)
+       mfcr    4
+       stw     4, 76(3)
+       li      3, 0
+       blr
+
+/*
+ * int grub_longjmp (grub_jmp_buf env, int val)
+ */
+FUNCTION(grub_longjmp)
+       lwz     1, 0(3)
+       lwz     14, 4(3)
+       lwz     15, 8(3)
+       lwz     16, 12(3)
+       lwz     17, 16(3)
+       lwz     18, 20(3)
+       lwz     19, 24(3)
+       lwz     20, 28(3)
+       lwz     21, 32(3)
+       lwz     22, 36(3)
+       lwz     23, 40(3)
+       lwz     24, 44(3)
+       lwz     25, 48(3)
+       lwz     26, 52(3)
+       lwz     27, 56(3)
+       lwz     28, 60(3)
+       lwz     29, 64(3)
+       lwz     30, 68(3)
+       lwz     5, 72(3)
+       mtlr    5
+       lwz     5, 76(3)
+       mtcr    5
+       mr.     3, 4
+       bne     1f
+       li      3, 1
+1:     blr
+
diff --git a/normal/script.c b/normal/script.c
new file mode 100644 (file)
index 0000000..0d5d5a8
--- /dev/null
@@ -0,0 +1,348 @@
+/* script.c -- Functions to create an in memory description of the script. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2006,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/misc.h>
+#include <grub/script.h>
+#include <grub/parser.h>
+#include <grub/mm.h>
+
+/* It is not possible to deallocate the memory when a syntax error was
+   found.  Because of that it is required to keep track of all memory
+   allocations.  The memory is freed in case of an error, or
+   assigned to the parsed script when parsing was successful.  */
+
+/* XXX */
+
+/* In case of the normal malloc, some additional bytes are allocated
+   for this datastructure.  All reserved memory is stored in a linked
+   list so it can be easily freed.  The original memory can be found
+   from &mem.  */
+struct grub_script_mem
+{
+  struct grub_script_mem *next;
+  char mem;
+};
+
+/* Return malloc'ed memory and keep track of the allocation.  */
+void *
+grub_script_malloc (struct grub_parser_param *state, grub_size_t size)
+{
+  struct grub_script_mem *mem;
+  mem = (struct grub_script_mem *) grub_malloc (size + sizeof (*mem)
+                                               - sizeof (char));
+
+  grub_dprintf ("scripting", "malloc %p\n", mem);
+  mem->next = state->memused;
+  state->memused = mem;
+  return (void *) &mem->mem;
+}
+
+/* Free all memory described by MEM.  */
+static void
+grub_script_mem_free (struct grub_script_mem *mem)
+{
+  struct grub_script_mem *memfree;
+
+  while (mem)
+    {
+      memfree = mem->next;
+      grub_dprintf ("scripting", "free %p\n", mem);
+      grub_free (mem);
+      mem = memfree;
+    }
+}
+
+/* Start recording memory usage.  Returns the memory that should be
+   restored when calling stop.  */
+struct grub_script_mem *
+grub_script_mem_record (struct grub_parser_param *state)
+{
+  struct grub_script_mem *mem = state->memused;
+  state->memused = 0;
+
+  return mem;
+}
+
+/* Stop recording memory usage.  Restore previous recordings using
+   RESTORE.  Return the recorded memory.  */
+struct grub_script_mem *
+grub_script_mem_record_stop (struct grub_parser_param *state,
+                            struct grub_script_mem *restore)
+{
+  struct grub_script_mem *mem = state->memused;
+  state->memused = restore;
+  return mem;
+}
+
+/* Free the memory reserved for CMD and all of it's children.  */
+void
+grub_script_free (struct grub_script *script)
+{
+  if (! script)
+    return;
+  grub_script_mem_free (script->mem);
+  grub_free (script);
+}
+
+\f
+
+/* Extend the argument arg with a variable or string of text.  If ARG
+   is zero a new list is created.  */
+struct grub_script_arg *
+grub_script_arg_add (struct grub_parser_param *state, struct grub_script_arg *arg,
+                    grub_script_arg_type_t type, char *str)
+{
+  struct grub_script_arg *argpart;
+  struct grub_script_arg *ll;
+  
+  argpart = (struct grub_script_arg *) grub_script_malloc (state, sizeof (*arg));
+  argpart->type = type;
+  argpart->str = str;
+  argpart->next = 0;
+
+  if (! arg)
+    return argpart;
+
+  for (ll = arg; ll->next; ll = ll->next);
+  ll->next = argpart;
+      
+  return arg;
+}
+
+/* Add the argument ARG to the end of the argument list LIST.  If LIST
+   is zero, a new list will be created.  */
+struct grub_script_arglist *
+grub_script_add_arglist (struct grub_parser_param *state,
+                        struct grub_script_arglist *list, struct grub_script_arg *arg)
+{
+  struct grub_script_arglist *link;
+  struct grub_script_arglist *ll;
+
+  grub_dprintf ("scripting", "arglist\n");
+
+  link = (struct grub_script_arglist *) grub_script_malloc (state, sizeof (*link));
+  link->next = 0;
+  link->arg = arg;
+  link->argcount = 0;
+
+  if (! list)
+    {
+      link->argcount++;
+      return link;
+    }
+
+  list->argcount++;
+
+  /* Look up the last link in the chain.  */
+  for (ll = list; ll->next; ll = ll->next);
+  ll->next = link;
+
+  return list;
+}
+
+/* Create a command that describes a single command line.  CMDLINE
+   contains the name of the command that should be executed.  ARGLIST
+   holds all arguments for this command.  */
+struct grub_script_cmd *
+grub_script_create_cmdline (struct grub_parser_param *state,
+                           char *cmdname, struct grub_script_arglist *arglist)
+{
+  struct grub_script_cmdline *cmd;
+
+  grub_dprintf ("scripting", "cmdline\n");
+
+  cmd = grub_script_malloc (state, sizeof (*cmd));
+  cmd->cmd.exec = grub_script_execute_cmdline;
+  cmd->cmd.next = 0;
+  cmd->arglist = arglist;
+  cmd->cmdname = cmdname;
+
+  return (struct grub_script_cmd *) cmd;
+}
+
+/* Create a command that functions as an if statement.  If BOOL is
+   evaluated to true (the value is returned in envvar '?'), the
+   interpreter will run the command TRUE, otherwise the interpreter
+   runs the command FALSE.  */
+struct grub_script_cmd *
+grub_script_create_cmdif (struct grub_parser_param *state,
+                         struct grub_script_cmd *exec_to_evaluate,
+                         struct grub_script_cmd *exec_on_true,
+                         struct grub_script_cmd *exec_on_false)
+{
+  struct grub_script_cmdif *cmd;
+
+  grub_dprintf ("scripting", "cmdif\n");
+
+  cmd = grub_script_malloc (state, sizeof (*cmd));
+  cmd->cmd.exec = grub_script_execute_cmdif;
+  cmd->cmd.next = 0;
+  cmd->exec_to_evaluate = exec_to_evaluate;
+  cmd->exec_on_true = exec_on_true;
+  cmd->exec_on_false = exec_on_false;
+
+  return (struct grub_script_cmd *) cmd;
+}
+
+/* Create a command that adds a menu entry to the menu.  Title is an
+   argument that is parsed to generate a string that can be used as
+   the title.  The sourcecode for this entry is passed in SOURCECODE.
+   The options for this entry are passed in OPTIONS.  */
+struct grub_script_cmd *
+grub_script_create_cmdmenu (struct grub_parser_param *state,
+                           struct grub_script_arglist *arglist,
+                           char *sourcecode,
+                           int options)
+{
+  struct grub_script_cmd_menuentry *cmd;
+  int i;
+
+  /* Skip leading newlines to make the sourcecode better readable when
+     using the editor.  */
+  while (*sourcecode == '\n')
+    sourcecode++;
+
+  /* Having trailing returns can some some annoying conflicts, remove
+     them.  XXX: Can the parser be improved to handle this?  */
+  for (i = grub_strlen (sourcecode) - 1; i > 0; i--)
+    {
+      if (sourcecode[i] != '\n')
+       break;
+      sourcecode[i] = '\0';
+    }
+
+  cmd = grub_script_malloc (state, sizeof (*cmd));
+  cmd->cmd.exec = grub_script_execute_menuentry;
+  cmd->cmd.next = 0;
+  /* XXX: Check if this memory is properly freed.  */
+  cmd->sourcecode = sourcecode;
+  cmd->arglist = arglist;
+  cmd->options = options;
+
+  return (struct grub_script_cmd *) cmd;
+}
+
+/* Create a block of commands.  CMD contains the command that should
+   be added at the end of CMDBLOCK's list.  If CMDBLOCK is zero, a new
+   cmdblock will be created.  */
+struct grub_script_cmd *
+grub_script_add_cmd (struct grub_parser_param *state,
+                    struct grub_script_cmdblock *cmdblock,
+                    struct grub_script_cmd *cmd)
+{
+  grub_dprintf ("scripting", "cmdblock\n");
+
+  if (! cmd)
+    return (struct grub_script_cmd *) cmdblock;
+
+  if (! cmdblock)
+    {
+      cmdblock = (struct grub_script_cmdblock *) grub_script_malloc (state,
+                                                                    sizeof (*cmdblock));
+      cmdblock->cmd.exec = grub_script_execute_cmdblock;
+      cmdblock->cmd.next = 0;
+      cmdblock->cmdlist = cmd;
+      cmd->next = 0;
+    }
+  else
+    {
+      cmd->next = cmdblock->cmdlist;
+      cmdblock->cmdlist = cmd;
+    }
+
+  return (struct grub_script_cmd *) cmdblock;
+}
+
+\f
+
+struct grub_script *
+grub_script_create (struct grub_script_cmd *cmd, struct grub_script_mem *mem)
+{
+  struct grub_script *parsed;
+
+  parsed = grub_malloc (sizeof (*parsed));
+  if (! parsed)
+    {
+      grub_script_mem_free (mem);
+      grub_free (cmd);
+
+      return 0;
+    }
+
+  parsed->mem = mem;
+  parsed->cmd = cmd;
+
+  return parsed;
+}
+
+/* Parse the script passed in SCRIPT and return the parsed
+   datastructure that is ready to be interpreted.  */
+struct grub_script *
+grub_script_parse (char *script, grub_err_t (*getline) (char **))
+{
+  struct grub_script *parsed;
+  struct grub_script_mem *membackup;
+  struct grub_lexer_param *lexstate;
+  struct grub_parser_param *parsestate;
+
+  parsed = grub_malloc (sizeof (*parsed));
+  if (! parsed)
+    return 0;
+
+  parsestate = grub_malloc (sizeof (*parsestate));
+  if (! parsestate)
+    return 0;
+
+  parsestate->err = 0;
+  parsestate->func_mem = 0;
+  parsestate->memused = 0;
+  parsestate->parsed = 0;
+
+  /* Initialize the lexer.  */
+  lexstate = grub_script_lexer_init (script, getline);
+  if (! lexstate)
+    {
+      grub_free (parsed);
+      grub_free (parsestate);
+      return 0;
+    }
+
+  parsestate->lexerstate = lexstate;
+
+  membackup = grub_script_mem_record (parsestate);
+
+  /* Parse the script.  */
+  if (grub_script_yyparse (parsestate) || parsestate->err)
+    {
+      struct grub_script_mem *memfree;
+      memfree = grub_script_mem_record_stop (parsestate, membackup);
+      grub_script_mem_free (memfree);
+      grub_free (lexstate);
+      grub_free (parsestate);
+      return 0;
+    }
+
+  parsed->mem = grub_script_mem_record_stop (parsestate, membackup);
+  parsed->cmd = parsestate->parsed;
+
+  grub_free (lexstate);
+  grub_free (parsestate);
+
+  return parsed;
+}
diff --git a/normal/sparc64/setjmp.S b/normal/sparc64/setjmp.S
new file mode 100644 (file)
index 0000000..b1a9b6e
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/symbol.h>
+
+        .file   "setjmp.S"
+
+        .text
+
+/*
+ * int grub_setjmp (grub_jmp_buf env)
+ */
+FUNCTION(grub_setjmp)
+        ret
+         nop
+
+/*
+ * int grub_longjmp (grub_jmp_buf env, int val)
+ */
+FUNCTION(grub_longjmp)
+        ret
+         nop
+
diff --git a/normal/x86_64/setjmp.S b/normal/x86_64/setjmp.S
new file mode 100644 (file)
index 0000000..621b09b
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,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/>.
+ */
+
+#include <grub/symbol.h>
+
+       .file   "setjmp.S"
+
+       .text
+
+/*
+ *  jmp_buf:
+ *   rbx rsp rbp r12 r13 r14 r15 rip
+ *   0   8   16  24  32  40  48  56
+ */
+
+/*
+ * int grub_setjmp (grub_jmp_buf env)
+ */
+FUNCTION(grub_setjmp)
+       pop     %rsi            /* Return address, and adjust the stack */
+       xorq    %rax, %rax
+       movq    %rbx, 0(%rdi)   /* RBX */
+       movq    %rsp, 8(%rdi)   /* RSP */
+       push    %rsi
+       movq    %rbp, 16(%rdi)  /* RBP */
+       movq    %r12, 24(%rdi)  /* R12 */
+       movq    %r13, 32(%rdi)  /* R13 */
+       movq    %r14, 40(%rdi)  /* R14 */
+       movq    %r15, 48(%rdi)  /* R15 */
+       movq    %rsi, 56(%rdi)  /* RSI */
+       ret
+
+/*
+ * int grub_longjmp (grub_jmp_buf env, int val)
+ */
+FUNCTION(grub_longjmp)
+       movl    %esi, %eax
+       orl     %eax, %eax
+       jnz     1f
+       incl    %eax
+1:
+
+       movq    (%rdi), %rbx
+       movq    8(%rdi), %rsp
+       movq    16(%rdi), %rbp
+       movq    24(%rdi), %r12
+       movq    32(%rdi), %r13
+       movq    40(%rdi), %r14
+       movq    48(%rdi), %r15
+       jmp     *56(%rdi)
diff --git a/partmap/acorn.c b/partmap/acorn.c
new file mode 100644 (file)
index 0000000..9db5e0e
--- /dev/null
@@ -0,0 +1,206 @@
+/* acorn.c - Read Linux/ADFS partition tables.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/disk.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/partition.h>
+#include <grub/acorn_filecore.h>
+
+#define LINUX_NATIVE_MAGIC grub_cpu_to_le32 (0xdeafa1de)
+#define LINUX_SWAP_MAGIC   grub_cpu_to_le32 (0xdeafab1e)
+#define LINUX_MAP_ENTRIES  (512 / 12)
+
+#define NONADFS_PARTITION_TYPE_LINUX 9
+#define NONADFS_PARTITION_TYPE_MASK 15
+
+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;
+} __attribute__ ((packed, aligned));
+
+struct linux_part
+{
+  grub_uint32_t magic;
+  grub_uint32_t start;
+  grub_uint32_t size;
+};
+
+static struct grub_partition_map grub_acorn_partition_map;
+
+static grub_err_t
+acorn_partition_map_find (grub_disk_t disk, struct linux_part *m,
+                         grub_disk_addr_t *sector)
+{
+  struct grub_acorn_boot_block boot;
+  grub_err_t err;
+  unsigned int checksum = 0;
+  unsigned int heads;
+  unsigned int sectors_per_cylinder;
+  int i;
+
+  err = grub_disk_read (disk, 0xC00 / GRUB_DISK_SECTOR_SIZE, 0,
+                       sizeof (struct grub_acorn_boot_block),
+                       (char *) &boot);
+  if (err)
+    return err;
+
+  if ((boot.flags & NONADFS_PARTITION_TYPE_MASK) != NONADFS_PARTITION_TYPE_LINUX)
+    goto fail;
+
+  for (i = 0; i != 0x1ff; ++i)
+    checksum = (checksum & 0xff) + (checksum >> 8) + boot.misc[i];
+
+  if ((grub_uint8_t) checksum != boot.checksum)
+    goto fail;
+
+  heads = (boot.disc_record.heads
+                   + ((boot.disc_record.lowsector >> 6) & 1));
+  sectors_per_cylinder = boot.disc_record.secspertrack * heads;
+  *sector = grub_le_to_cpu16 (boot.start_cylinder) * sectors_per_cylinder;
+
+  return grub_disk_read (disk, *sector, 0,
+                        sizeof (struct linux_part) * LINUX_MAP_ENTRIES,
+                        (char *) m);
+
+fail:
+  return grub_error (GRUB_ERR_BAD_PART_TABLE,
+                    "Linux/ADFS partition map not found.");
+
+}
+
+
+static grub_err_t
+acorn_partition_map_iterate (grub_disk_t disk,
+                            int (*hook) (grub_disk_t disk,
+                                         const grub_partition_t partition))
+{
+  struct grub_partition part;
+  struct grub_disk raw;
+  struct linux_part map[LINUX_MAP_ENTRIES];
+  int i;
+  grub_disk_addr_t sector;
+  grub_err_t err;
+
+  /* Enforce raw disk access.  */
+  raw = *disk;
+  raw.partition = 0;
+
+  err = acorn_partition_map_find (&raw, map, &sector);
+  if (err)
+    return err;
+
+  part.partmap = &grub_acorn_partition_map;
+
+  for (i = 0; i != LINUX_MAP_ENTRIES; ++i)
+    {
+      if (map[i].magic != LINUX_NATIVE_MAGIC
+         && map[i].magic != LINUX_SWAP_MAGIC)
+       return GRUB_ERR_NONE;
+
+      part.start = sector + map[i].start;
+      part.len = map[i].size;
+      part.offset = 6;
+      part.index = i;
+
+      if (hook (disk, &part))
+       return grub_errno;
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+
+static grub_partition_t
+acorn_partition_map_probe (grub_disk_t disk, const char *str)
+{
+  struct linux_part map[LINUX_MAP_ENTRIES];
+  struct grub_disk raw = *disk;
+  unsigned long partnum = grub_strtoul (str, 0, 10) - 1;
+  grub_disk_addr_t sector;
+  grub_err_t err;
+  grub_partition_t p;
+  
+  /* Enforce raw disk access.  */
+  raw.partition = 0;
+
+  /* Get the partition number.  */
+  if (partnum > LINUX_MAP_ENTRIES)
+    goto fail;
+
+  err = acorn_partition_map_find (&raw, map, &sector);
+  if (err)
+    return 0;
+
+  if (map[partnum].magic != LINUX_NATIVE_MAGIC
+      && map[partnum].magic != LINUX_SWAP_MAGIC)
+    goto fail;
+
+  p = grub_malloc (sizeof (struct grub_partition));
+  if (! p)
+    return 0;
+
+  p->start = sector + map[partnum].start;
+  p->len = map[partnum].size;
+  p->offset = 6;
+  p->index = partnum;
+  return p;
+
+fail:
+  grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
+  return 0;
+}
+
+
+static char *
+acorn_partition_map_get_name (const grub_partition_t p)
+{
+  char *name;
+
+  name = grub_malloc (13);
+  if (! name)
+    return 0;
+
+  grub_sprintf (name, "%d", p->index + 1);
+  return name;
+}
+\f
+
+/* Partition map type.  */
+static struct grub_partition_map grub_acorn_partition_map =
+{
+  .name = "Linux/ADFS partition map",
+  .iterate = acorn_partition_map_iterate,
+  .probe = acorn_partition_map_probe,
+  .get_name = acorn_partition_map_get_name
+};
+
+GRUB_MOD_INIT(acorn_partition_map)
+{
+  grub_partition_map_register (&grub_acorn_partition_map);
+}
+
+GRUB_MOD_FINI(acorn_partition_map)
+{
+  grub_partition_map_unregister (&grub_acorn_partition_map);
+}
diff --git a/partmap/amiga.c b/partmap/amiga.c
new file mode 100644 (file)
index 0000000..fde3011
--- /dev/null
@@ -0,0 +1,222 @@
+/* amiga.c - Read amiga partition tables (RDB).  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2004,2005,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/>.
+ */
+
+#include <grub/disk.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/partition.h>
+#include <grub/dl.h>
+
+struct grub_amiga_rdsk
+{
+  /* "RDSK".  */
+  grub_uint8_t magic[4];
+  grub_uint32_t size;
+  grub_int32_t checksum;
+  grub_uint32_t scsihost;
+  grub_uint32_t blksz;
+  grub_uint32_t flags;
+  grub_uint32_t badblcklst;
+  grub_uint32_t partitionlst;
+  grub_uint32_t fslst;
+  
+  /* The other information is not important for us.  */
+} __attribute__ ((packed));
+
+struct grub_amiga_partition
+{
+  /* "PART".  */
+  grub_uint8_t magic[4];
+  grub_int32_t size;
+  grub_int32_t checksum;
+  grub_uint32_t scsihost;
+  grub_uint32_t next;
+  grub_uint32_t flags;
+  grub_uint32_t unused1[2];
+  grub_uint32_t devflags;
+  grub_uint8_t namelen;
+  grub_uint8_t name[31];
+  grub_uint32_t unused2[15];
+
+  grub_uint32_t unused3[3];
+  grub_uint32_t heads;
+  grub_uint32_t unused4;
+  grub_uint32_t block_per_track;
+  grub_uint32_t unused5[3];
+  grub_uint32_t lowcyl;
+  grub_uint32_t highcyl;
+  
+  grub_uint32_t firstcyl;
+} __attribute__ ((packed));
+
+static struct grub_partition_map grub_amiga_partition_map;
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+\f
+
+static grub_err_t
+amiga_partition_map_iterate (grub_disk_t disk,
+                            int (*hook) (grub_disk_t disk,
+                                         const grub_partition_t partition))
+{
+  struct grub_partition part;
+  struct grub_amiga_rdsk rdsk;
+  struct grub_disk raw;
+  int partno = 0;
+  int next = -1;
+  unsigned pos;
+  
+  /* Enforce raw disk access.  */
+  raw = *disk;
+  raw.partition = 0;
+  
+  /* The RDSK block is one of the first 15 blocks.  */
+  for (pos = 0; pos < 15; pos++)
+    {
+      /* Read the RDSK block which is a descriptor for the entire disk.  */
+      if (grub_disk_read (&raw, pos, 0, sizeof (rdsk), (char *) &rdsk))
+       return grub_errno;
+      
+      if (grub_strcmp ((char *) rdsk.magic, "RDSK") == 0)
+       {
+         /* Found the first PART block.  */
+         next = grub_be_to_cpu32 (rdsk.partitionlst);
+         break;
+       }
+    }
+
+  if (next == -1)
+    return grub_error (GRUB_ERR_BAD_PART_TABLE,
+                      "Amiga partition map not found.");
+  
+  /* The end of the partition list is marked using "-1".  */
+  while (next != -1)
+    {
+      struct grub_amiga_partition apart;
+     
+      /* Read the RDSK block which is a descriptor for the entire disk.  */
+      if (grub_disk_read (&raw, next, 0, sizeof (apart), (char *) &apart))
+       return grub_errno;
+      
+      /* Calculate the first block and the size of the partition.  */
+      part.start = (grub_be_to_cpu32 (apart.lowcyl) 
+                   * grub_be_to_cpu32 (apart.heads)
+                   * grub_be_to_cpu32 (apart.block_per_track));
+      part.len = ((grub_be_to_cpu32 (apart.highcyl)
+                  - grub_be_to_cpu32 (apart.lowcyl) + 1)
+                 * grub_be_to_cpu32 (apart.heads)
+                 * grub_be_to_cpu32 (apart.block_per_track));
+      
+      part.offset = (grub_off_t) next * 512;
+      part.index = partno;
+      part.partmap = &grub_amiga_partition_map;
+      
+      if (hook (disk, &part))
+       return grub_errno;
+      
+      next = grub_be_to_cpu32 (apart.next);
+      partno++;
+    }
+  
+  return 0;
+}
+
+
+static grub_partition_t
+amiga_partition_map_probe (grub_disk_t disk, const char *str)
+{
+  grub_partition_t p = 0;
+  int partnum = 0;
+  char *s = (char *) str;
+
+  auto int find_func (grub_disk_t d, const grub_partition_t partition);
+    
+  int find_func (grub_disk_t d __attribute__ ((unused)),
+                const grub_partition_t partition)
+    {
+      if (partnum == partition->index)
+       {
+         p = (grub_partition_t) grub_malloc (sizeof (*p));
+         if (! p)
+           return 1;
+         
+         grub_memcpy (p, partition, sizeof (*p));
+         return 1;
+       }
+      
+      return 0;
+    }
+  
+  /* Get the partition number.  */
+  partnum = grub_strtoul (s, 0, 10) - 1;
+  if (grub_errno)
+    {
+      grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
+      return 0;
+    }
+
+  if (amiga_partition_map_iterate (disk, find_func))
+    goto fail;
+
+  return p;
+
+ fail:
+  grub_free (p);
+  return 0;
+}
+
+
+static char *
+amiga_partition_map_get_name (const grub_partition_t p)
+{
+  char *name;
+
+  name = grub_malloc (13);
+  if (! name)
+    return 0;
+
+  grub_sprintf (name, "%d", p->index + 1);
+  return name;
+}
+
+\f
+/* Partition map type.  */
+static struct grub_partition_map grub_amiga_partition_map =
+  {
+    .name = "amiga_partition_map",
+    .iterate = amiga_partition_map_iterate,
+    .probe = amiga_partition_map_probe,
+    .get_name = amiga_partition_map_get_name
+  };
+
+GRUB_MOD_INIT(amiga_partition_map)
+{
+  grub_partition_map_register (&grub_amiga_partition_map);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(amiga_partition_map)
+{
+  grub_partition_map_unregister (&grub_amiga_partition_map);
+}
diff --git a/partmap/apple.c b/partmap/apple.c
new file mode 100644 (file)
index 0000000..d6ddc0b
--- /dev/null
@@ -0,0 +1,259 @@
+/* apple.c - Read macintosh partition tables.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2004,2005,2006,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/>.
+ */
+
+#include <grub/disk.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/partition.h>
+
+#define GRUB_APPLE_HEADER_MAGIC        0x4552
+#define GRUB_APPLE_PART_MAGIC  0x504D
+
+struct grub_apple_header
+{
+  /* The magic number to identify the partition map, it should have
+     the value `0x4552'.  */
+  grub_uint16_t magic;
+};
+
+struct grub_apple_part
+{
+  /* The magic number to identify this as a partition, it should have
+     the value `0x504D'.  */
+  grub_uint16_t magic;
+
+  /* Reserved.  */
+  grub_uint16_t reserved;
+
+  /* The size of the partition map in blocks.  */
+  grub_uint32_t partmap_size;
+
+  /* The first physical block of the partition.  */
+  grub_uint32_t first_phys_block;
+
+  /* The amount of blocks.  */
+  grub_uint32_t blockcnt;
+
+  /* The partition name.  */
+  char partname[32];
+
+  /* The partition type.  */
+  char parttype[32];
+
+  /* The first datablock of the partition.  */
+  grub_uint32_t datablocks_first;
+
+  /* The amount datablocks.  */
+  grub_uint32_t datablocks_count;
+
+  /* The status of the partition. (???)  */
+  grub_uint32_t status;
+
+  /* The first block on which the bootcode can be found.  */
+  grub_uint32_t bootcode_pos;
+
+  /* The size of the bootcode in bytes.  */
+  grub_uint32_t bootcode_size;
+
+  /* The load address of the bootcode.  */
+  grub_uint32_t bootcode_loadaddr;
+
+  /* Reserved.  */
+  grub_uint32_t reserved2;
+  
+  /* The entrypoint of the bootcode.  */
+  grub_uint32_t bootcode_entrypoint;
+
+  /* Reserved.  */
+  grub_uint32_t reserved3;
+
+  /* A checksum of the bootcode.  */
+  grub_uint32_t bootcode_checksum;
+
+  /* The processor type.  */
+  char processor[16];
+
+  /* Padding.  */
+  grub_uint16_t pad[187];
+};
+
+static struct grub_partition_map grub_apple_partition_map;
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+\f
+
+static grub_err_t
+apple_partition_map_iterate (grub_disk_t disk,
+                            int (*hook) (grub_disk_t disk,
+                                         const grub_partition_t partition))
+{
+  struct grub_partition part;
+  struct grub_apple_header aheader;
+  struct grub_apple_part apart;
+  struct grub_disk raw;
+  int partno = 0;
+  unsigned pos = GRUB_DISK_SECTOR_SIZE;
+
+  /* Enforce raw disk access.  */
+  raw = *disk;
+  raw.partition = 0;
+
+  part.partmap = &grub_apple_partition_map;
+
+  if (grub_disk_read (&raw, 0, 0, sizeof (aheader), (char *) &aheader))
+    return grub_errno;
+
+  if (grub_be_to_cpu16 (aheader.magic) != GRUB_APPLE_HEADER_MAGIC)
+    {
+      grub_dprintf ("partition",
+                   "bad magic (found 0x%x; wanted 0x%x\n",
+                   grub_be_to_cpu16 (aheader.magic),
+                   GRUB_APPLE_HEADER_MAGIC);
+      goto fail;
+    }
+
+  for (;;)
+    {
+      if (grub_disk_read (&raw, pos / GRUB_DISK_SECTOR_SIZE,
+                         pos % GRUB_DISK_SECTOR_SIZE,
+                         sizeof (struct grub_apple_part),  (char *) &apart))
+       return grub_errno;
+
+      if (grub_be_to_cpu16 (apart.magic) != GRUB_APPLE_PART_MAGIC)
+       {
+         grub_dprintf ("partition",
+                       "partition %d: bad magic (found 0x%x; wanted 0x%x\n",
+                       partno, grub_be_to_cpu16 (apart.magic),
+                       GRUB_APPLE_PART_MAGIC);
+         break;
+       }
+
+      part.start = grub_be_to_cpu32 (apart.first_phys_block);
+      part.len = grub_be_to_cpu32 (apart.blockcnt);
+      part.offset = pos;
+      part.index = partno;
+
+      grub_dprintf ("partition",
+                   "partition %d: name %s, type %s, start 0x%x, len 0x%x\n",
+                   partno, apart.partname, apart.parttype,
+                   grub_be_to_cpu32 (apart.first_phys_block),
+                   grub_be_to_cpu32 (apart.blockcnt));
+
+      if (hook (disk, &part))
+       return grub_errno;
+
+      if (grub_be_to_cpu32 (apart.first_phys_block)
+         == GRUB_DISK_SECTOR_SIZE * 2)
+       return 0;
+
+      pos += sizeof (struct grub_apple_part);
+      partno++;
+    }
+
+  if (pos != GRUB_DISK_SECTOR_SIZE)
+    return 0;
+
+ fail:
+  return grub_error (GRUB_ERR_BAD_PART_TABLE,
+                    "Apple partition map not found.");
+}
+
+
+static grub_partition_t
+apple_partition_map_probe (grub_disk_t disk, const char *str)
+{
+  grub_partition_t p = 0;
+  int partnum = 0;
+  char *s = (char *) str;
+
+  auto int find_func (grub_disk_t d, const grub_partition_t partition);
+  
+  int find_func (grub_disk_t d __attribute__ ((unused)),
+                const grub_partition_t partition)
+    {
+      if (partnum == partition->index)
+       {
+         p = (grub_partition_t) grub_malloc (sizeof (*p));
+         if (! p)
+           return 1;
+         
+         grub_memcpy (p, partition, sizeof (*p));
+         return 1;
+       }
+      
+      return 0;
+    }
+  
+  /* Get the partition number.  */
+  partnum = grub_strtoul (s, 0, 10) - 1;
+  if (grub_errno)
+    {
+      grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
+      return 0;
+    }
+  
+  if (apple_partition_map_iterate (disk, find_func))
+    goto fail;
+
+  return p;
+
+ fail:
+  grub_free (p);
+  return 0;
+}
+
+
+static char *
+apple_partition_map_get_name (const grub_partition_t p)
+{
+  char *name;
+
+  name = grub_malloc (13);
+  if (! name)
+    return 0;
+
+  grub_sprintf (name, "%d", p->index + 1);
+  return name;
+}
+
+\f
+/* Partition map type.  */
+static struct grub_partition_map grub_apple_partition_map =
+  {
+    .name = "apple_partition_map",
+    .iterate = apple_partition_map_iterate,
+    .probe = apple_partition_map_probe,
+    .get_name = apple_partition_map_get_name
+  };
+
+GRUB_MOD_INIT(apple_partition_map)
+{
+  grub_partition_map_register (&grub_apple_partition_map);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(apple_partition_map)
+{
+  grub_partition_map_unregister (&grub_apple_partition_map);
+}
+
diff --git a/partmap/gpt.c b/partmap/gpt.c
new file mode 100644 (file)
index 0000000..683fcba
--- /dev/null
@@ -0,0 +1,200 @@
+/* gpt.c - Read GUID Partition Tables (GPT).  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,2006,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/>.
+ */
+
+#include <grub/disk.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/partition.h>
+#include <grub/dl.h>
+#include <grub/pc_partition.h>
+#include <grub/gpt_partition.h>
+
+static grub_uint8_t grub_gpt_magic[8] =
+  {
+    0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54
+  };
+
+static const grub_gpt_part_type_t grub_gpt_partition_type_empty = GRUB_GPT_PARTITION_TYPE_EMPTY;
+
+static struct grub_partition_map grub_gpt_partition_map;
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+\f
+
+static grub_err_t
+gpt_partition_map_iterate (grub_disk_t disk,
+                          int (*hook) (grub_disk_t disk,
+                                       const grub_partition_t partition))
+{
+  struct grub_partition part;
+  struct grub_gpt_header gpt;
+  struct grub_gpt_partentry entry;
+  struct grub_disk raw;
+  struct grub_pc_partition_mbr mbr;
+  grub_uint64_t entries;
+  unsigned int i;
+  int last_offset = 0;
+
+  /* Enforce raw disk access.  */
+  raw = *disk;
+  raw.partition = 0;
+
+  /* Read the protective MBR.  */
+  if (grub_disk_read (&raw, 0, 0, sizeof (mbr), (char *) &mbr))
+    return grub_errno;
+
+  /* Check if it is valid.  */
+  if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
+    return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
+
+  /* Make sure the MBR is a protective MBR and not a normal MBR.  */
+  if (mbr.entries[0].type != GRUB_PC_PARTITION_TYPE_GPT_DISK)
+    return grub_error (GRUB_ERR_BAD_PART_TABLE, "no GPT partition map found");
+
+  /* Read the GPT header.  */
+  if (grub_disk_read (&raw, 1, 0, sizeof (gpt), (char *) &gpt))
+    return grub_errno;
+
+  if (grub_memcmp (gpt.magic, grub_gpt_magic, sizeof (grub_gpt_magic)))
+    return grub_error (GRUB_ERR_BAD_PART_TABLE, "no valid GPT header");
+
+  grub_dprintf ("gpt", "Read a valid GPT header\n");
+
+  entries = grub_le_to_cpu64 (gpt.partitions);
+  for (i = 0; i < grub_le_to_cpu32 (gpt.maxpart); i++)
+    {
+      if (grub_disk_read (&raw, entries, last_offset,
+                         sizeof (entry), (char *) &entry))
+       return grub_errno;
+
+      if (grub_memcmp (&grub_gpt_partition_type_empty, &entry.type,
+                      sizeof (grub_gpt_partition_type_empty)))
+       {
+         /* Calculate the first block and the size of the partition.  */
+         part.start = grub_le_to_cpu64 (entry.start);
+         part.len = (grub_le_to_cpu64 (entry.end)
+                     - grub_le_to_cpu64 (entry.start) + 1);
+         part.offset = entries;
+         part.index = i;
+         part.partmap = &grub_gpt_partition_map;
+         part.data = &entry;
+
+         grub_dprintf ("gpt", "GPT entry %d: start=%lld, length=%lld\n", i,
+                       (unsigned long long) part.start,
+                       (unsigned long long) part.len);
+
+         if (hook (disk, &part))
+           return 1;
+       }
+
+      last_offset += grub_le_to_cpu32 (gpt.partentry_size);
+      if (last_offset == GRUB_DISK_SECTOR_SIZE)
+       {
+         last_offset = 0;
+         entries++;
+       }
+    }
+
+  return 0;
+}
+
+
+static grub_partition_t
+gpt_partition_map_probe (grub_disk_t disk, const char *str)
+{
+  grub_partition_t p = 0;
+  int partnum = 0;
+  char *s = (char *) str;
+
+  auto int find_func (grub_disk_t d, const grub_partition_t partition);
+    
+  int find_func (grub_disk_t d __attribute__ ((unused)),
+                const grub_partition_t partition)
+    {
+      if (partnum == partition->index)
+       {
+         p = (grub_partition_t) grub_malloc (sizeof (*p));
+         if (! p)
+           return 1;
+         
+         grub_memcpy (p, partition, sizeof (*p));
+         return 1;
+       }
+      
+      return 0;
+    }
+  
+  /* Get the partition number.  */
+  partnum = grub_strtoul (s, 0, 10) - 1;
+  if (grub_errno)
+    {
+      grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
+      return 0;
+    }
+
+  gpt_partition_map_iterate (disk, find_func);
+  if (grub_errno)
+    goto fail;
+
+  return p;
+
+ fail:
+  grub_free (p);
+  return 0;
+}
+
+
+static char *
+gpt_partition_map_get_name (const grub_partition_t p)
+{
+  char *name;
+
+  name = grub_malloc (13);
+  if (! name)
+    return 0;
+
+  grub_sprintf (name, "%d", p->index + 1);
+  return name;
+}
+
+\f
+/* Partition map type.  */
+static struct grub_partition_map grub_gpt_partition_map =
+  {
+    .name = "gpt_partition_map",
+    .iterate = gpt_partition_map_iterate,
+    .probe = gpt_partition_map_probe,
+    .get_name = gpt_partition_map_get_name
+  };
+
+GRUB_MOD_INIT(gpt_partition_map)
+{
+  grub_partition_map_register (&grub_gpt_partition_map);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(gpt_partition_map)
+{
+  grub_partition_map_unregister (&grub_gpt_partition_map);
+}
diff --git a/partmap/pc.c b/partmap/pc.c
new file mode 100644 (file)
index 0000000..419775a
--- /dev/null
@@ -0,0 +1,320 @@
+/* pc.c - Read PC style partition tables.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2004,2005,2006,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/>.
+ */
+
+#include <grub/partition.h>
+#include <grub/pc_partition.h>
+#include <grub/disk.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/dl.h>
+
+static struct grub_partition_map grub_pc_partition_map;
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+\f
+
+/* Parse the partition representation in STR and return a partition.  */
+static grub_partition_t
+grub_partition_parse (const char *str)
+{
+  grub_partition_t p;
+  struct grub_pc_partition *pcdata;
+  
+  char *s = (char *) str;
+  
+  p = (grub_partition_t) grub_malloc (sizeof (*p));
+  if (! p)
+    return 0;
+  
+  pcdata = (struct grub_pc_partition *) grub_malloc (sizeof (*pcdata));
+  if (! pcdata)
+    goto fail;
+  
+  p->data = pcdata;
+  p->partmap = &grub_pc_partition_map;
+  
+  /* Initialize some of the fields with invalid values.  */
+  pcdata->bsd_part = pcdata->dos_type = pcdata->bsd_type = p->index = -1;
+
+  /* Get the DOS partition number. The number is counted from one for
+     the user interface, and from zero internally.  */
+  pcdata->dos_part = grub_strtoul (s, &s, 0) - 1;
+  
+  if (grub_errno)
+    {
+      /* Not found. Maybe only a BSD label is specified.  */
+      pcdata->dos_part = -1;
+      grub_errno = GRUB_ERR_NONE;
+    }
+  else if (*s == ',')
+    s++;
+
+  if (*s)
+    {
+      if (*s >= 'a' && *s <= 'h')
+       {
+         pcdata->bsd_part = *s - 'a';
+         s++;
+       }
+
+      if (*s)
+       goto fail;
+    }
+
+  if (pcdata->dos_part == -1 && pcdata->bsd_part == -1)
+    goto fail;
+
+  return p;
+  
+ fail:
+  grub_free (p);
+  grub_free (pcdata);
+  grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
+  return 0;
+}
+
+static grub_err_t
+pc_partition_map_iterate (grub_disk_t disk,
+                         int (*hook) (grub_disk_t disk,
+                                      const grub_partition_t partition))
+{
+  struct grub_partition p;
+  struct grub_pc_partition pcdata;
+  struct grub_pc_partition_mbr mbr;
+  struct grub_pc_partition_disk_label label;
+  struct grub_disk raw;
+
+  /* Enforce raw disk access.  */
+  raw = *disk;
+  raw.partition = 0;
+  
+  p.offset = 0;
+  pcdata.ext_offset = 0;
+  pcdata.dos_part = -1;
+  p.data = &pcdata;
+  p.partmap = &grub_pc_partition_map;
+  
+  while (1)
+    {
+      int i;
+      struct grub_pc_partition_entry *e;
+      
+      /* Read the MBR.  */
+      if (grub_disk_read (&raw, p.offset, 0, sizeof (mbr), (char *) &mbr))
+       goto finish;
+
+      /* Check if it is valid.  */
+      if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
+       return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
+
+      /* Analyze DOS partitions.  */
+      for (p.index = 0; p.index < 4; p.index++)
+       {
+         e = mbr.entries + p.index;
+         
+         p.start = p.offset + grub_le_to_cpu32 (e->start);
+         p.len = grub_le_to_cpu32 (e->length);
+         pcdata.bsd_part = -1;
+         pcdata.dos_type = e->type;
+         pcdata.bsd_type = -1;
+
+         grub_dprintf ("partition",
+                       "partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx\n",
+                       p.index, e->flag, pcdata.dos_type,
+                       (unsigned long long) p.start,
+                       (unsigned long long) p.len);
+
+         /* If this is a GPT partition, this MBR is just a dummy.  */
+         if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && p.index == 0)
+           return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr");
+
+         /* If this partition is a normal one, call the hook.  */
+         if (! grub_pc_partition_is_empty (e->type)
+             && ! grub_pc_partition_is_extended (e->type))
+           {
+             pcdata.dos_part++;
+             
+             if (hook (disk, &p))
+               return 1;
+
+             /* Check if this is a BSD partition.  */
+             if (grub_pc_partition_is_bsd (e->type))
+               {
+                 /* Check if the BSD label is within the DOS partition.  */
+                 if (p.len <= GRUB_PC_PARTITION_BSD_LABEL_SECTOR)
+                   return grub_error (GRUB_ERR_BAD_PART_TABLE,
+                                      "no space for disk label");
+
+                 /* Read the BSD label.  */
+                 if (grub_disk_read (&raw,
+                                     (p.start
+                                      + GRUB_PC_PARTITION_BSD_LABEL_SECTOR),
+                                     0,
+                                     sizeof (label),
+                                     (char *) &label))
+                   goto finish;
+
+                 /* Check if it is valid.  */
+                 if (label.magic
+                     != grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC))
+                   return grub_error (GRUB_ERR_BAD_PART_TABLE,
+                                      "invalid disk label magic 0x%x",
+                                      label.magic);
+
+                 for (pcdata.bsd_part = 0;
+                      pcdata.bsd_part < grub_cpu_to_le16 (label.num_partitions);
+                      pcdata.bsd_part++)
+                   {
+                     struct grub_pc_partition_bsd_entry *be
+                       = label.entries + pcdata.bsd_part;
+
+                     p.start = grub_le_to_cpu32 (be->offset);
+                     p.len = grub_le_to_cpu32 (be->size);
+                     pcdata.bsd_type = be->fs_type;
+                     
+                     if (be->fs_type != GRUB_PC_PARTITION_BSD_TYPE_UNUSED)
+                       if (hook (disk, &p))
+                         return 1;
+                   }
+               }
+           }
+         else if (pcdata.dos_part < 4)
+           /* If this partition is a logical one, shouldn't increase the
+              partition number.  */
+           pcdata.dos_part++;
+       }
+
+      /* Find an extended partition.  */
+      for (i = 0; i < 4; i++)
+       {
+         e = mbr.entries + i;
+         
+         if (grub_pc_partition_is_extended (e->type))
+           {
+             p.offset = pcdata.ext_offset + grub_le_to_cpu32 (e->start);
+             if (! pcdata.ext_offset)
+               pcdata.ext_offset = p.offset;
+
+             break;
+           }
+       }
+
+      /* If no extended partition, the end.  */
+      if (i == 4)
+       break;
+    }
+
+ finish:
+  return grub_errno;
+}
+
+
+static grub_partition_t
+pc_partition_map_probe (grub_disk_t disk, const char *str)
+{
+  grub_partition_t p;
+  struct grub_pc_partition *pcdata;
+  
+  auto int find_func (grub_disk_t d, const grub_partition_t partition);
+
+  int find_func (grub_disk_t d __attribute__ ((unused)),
+                const grub_partition_t partition)
+    {
+      struct grub_pc_partition *partdata = partition->data;
+
+      if ((pcdata->dos_part == partdata->dos_part || pcdata->dos_part == -1)
+         && pcdata->bsd_part == partdata->bsd_part)
+       {
+         grub_memcpy (p, partition, sizeof (*p));
+         p->data = pcdata;
+         grub_memcpy (pcdata, partdata, sizeof (*pcdata));
+         return 1;
+       }
+      
+      return 0;
+    }
+  
+  p = grub_partition_parse (str);
+  if (! p)
+    return 0;
+  
+  pcdata = p->data;
+  pc_partition_map_iterate (disk, find_func);
+  if (grub_errno)
+    goto fail;
+
+  if (p->index < 0)
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, "no such partition");
+      goto fail;
+    }
+
+  return p;
+
+ fail:
+  grub_free (p);
+  grub_free (pcdata);
+  return 0;
+}
+
+
+static char *
+pc_partition_map_get_name (const grub_partition_t p)
+{
+  char *name;
+  struct grub_pc_partition *pcdata = p->data;
+  
+  name = grub_malloc (13);
+  if (! name)
+    return 0;
+
+  if (pcdata->bsd_part < 0)
+    grub_sprintf (name, "%d", pcdata->dos_part + 1);
+  else if (pcdata->dos_part < 0)
+    grub_sprintf (name, "%c", pcdata->bsd_part + 'a');
+  else
+    grub_sprintf (name, "%d,%c", pcdata->dos_part + 1, pcdata->bsd_part + 'a');
+
+  return name;
+}
+
+\f
+/* Partition map type.  */
+static struct grub_partition_map grub_pc_partition_map =
+  {
+    .name = "pc_partition_map",
+    .iterate = pc_partition_map_iterate,
+    .probe = pc_partition_map_probe,
+    .get_name = pc_partition_map_get_name
+  };
+
+GRUB_MOD_INIT(pc_partition_map)
+{
+  grub_partition_map_register (&grub_pc_partition_map);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(pc_partition_map)
+{
+  grub_partition_map_unregister (&grub_pc_partition_map);
+}
diff --git a/partmap/sun.c b/partmap/sun.c
new file mode 100644 (file)
index 0000000..b05a2e2
--- /dev/null
@@ -0,0 +1,223 @@
+/* sun.c - Read SUN style partition tables.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2005,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/>.
+ */
+
+#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>
+
+#define GRUB_PARTMAP_SUN_MAGIC 0xDABE
+#define GRUB_PARTMAP_SUN_MAX_PARTS 8
+#define GRUB_PARTMAP_SUN_WHOLE_DISK_ID 0x05
+
+struct grub_sun_partition_info
+{
+  grub_uint8_t spare1;
+  grub_uint8_t id;
+  grub_uint8_t spare2;
+  grub_uint8_t flags;
+} __attribute__ ((packed));
+
+struct grub_sun_partition_descriptor
+{
+  grub_uint32_t start_cylinder;
+  grub_uint32_t num_sectors;
+} __attribute__ ((packed));
+
+struct grub_sun_block
+{
+  grub_uint8_t  info[128];      /* Informative text string.  */
+  grub_uint8_t  spare0[14];
+  struct grub_sun_partition_info infos[8];
+  grub_uint8_t  spare1[246];    /* Boot information etc.  */
+  grub_uint16_t  rspeed;        /* Disk rotational speed.  */
+  grub_uint16_t  pcylcount;     /* Physical cylinder count.  */
+  grub_uint16_t  sparecyl;      /* extra sects per cylinder.  */
+  grub_uint8_t  spare2[4];      /* More magic...  */
+  grub_uint16_t  ilfact;        /* Interleave factor.  */
+  grub_uint16_t  ncyl;          /* Data cylinder count.  */
+  grub_uint16_t  nacyl;         /* Alt. cylinder count.  */
+  grub_uint16_t  ntrks;         /* Tracks per cylinder.  */
+  grub_uint16_t  nsect;         /* Sectors per track.  */
+  grub_uint8_t  spare3[4];      /* Even more magic...  */
+  struct grub_sun_partition_descriptor partitions[8];
+  grub_uint16_t  magic;         /* Magic number.  */
+  grub_uint16_t  csum;          /* Label xor'd checksum.  */
+} __attribute__ ((packed));
+
+static struct grub_partition_map grub_sun_partition_map;
+
+#ifndef GRUB_UTIL
+static grub_dl_t my_mod;
+#endif
+
+/* Verify checksum (true=ok).  */
+static int
+grub_sun_is_valid (struct grub_sun_block *label)
+{
+  grub_uint16_t *pos;
+  grub_uint16_t sum = 0;
+  
+  for (pos = (grub_uint16_t *) label;
+       pos < (grub_uint16_t *) (label + 1);
+       pos++)
+    sum ^= *pos;
+  
+  return ! sum;
+}
+
+static grub_err_t
+sun_partition_map_iterate (grub_disk_t disk,
+                           int (*hook) (grub_disk_t disk,
+                                       const grub_partition_t partition))
+{
+  grub_partition_t p;
+  struct grub_disk raw;
+  struct grub_sun_block block;
+  int partnum;
+  
+  raw = *disk;
+  raw.partition = 0;
+  
+  p = (grub_partition_t) grub_malloc (sizeof (struct grub_partition));
+  if (! p)
+    return grub_errno;
+
+  p->offset = 0;
+  p->data = 0;
+  p->partmap = &grub_sun_partition_map;
+  if (grub_disk_read (&raw, 0, 0, sizeof (struct grub_sun_block),
+                     (char *) &block) == GRUB_ERR_NONE)
+    {
+      if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic))
+       grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table");
+      
+      if (! grub_sun_is_valid (&block))
+       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 < GRUB_PARTMAP_SUN_MAX_PARTS; partnum++)
+       {
+         struct grub_sun_partition_descriptor *desc;
+         
+         if (block.infos[partnum].id == 0
+             || block.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID)
+           continue;
+
+         desc = &block.partitions[partnum];
+         p->start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder)
+                     * grub_be_to_cpu16 (block.ntrks)
+                     * grub_be_to_cpu16 (block.nsect));
+         p->len = grub_be_to_cpu32 (desc->num_sectors);
+         p->index = partnum;
+         if (p->len)
+           {
+             if (hook (disk, p))
+               partnum = GRUB_PARTMAP_SUN_MAX_PARTS;
+           }
+       }
+    }
+  
+  grub_free (p);
+
+  return grub_errno;
+}
+
+static grub_partition_t
+sun_partition_map_probe (grub_disk_t disk, const char *str)
+{
+  grub_partition_t p = 0;
+  int partnum = 0;
+  char *s = (char *) str;
+
+  auto int find_func (grub_disk_t d, const grub_partition_t partition);
+  
+  int find_func (grub_disk_t d __attribute__ ((unused)),
+                const grub_partition_t partition)
+    {
+      if (partnum == partition->index)
+        {
+          p = (grub_partition_t) grub_malloc (sizeof (*p));
+          if (p)
+            grub_memcpy (p, partition, sizeof (*p));
+         
+          return 1;
+        }
+      
+      return 0;
+    }
+
+  grub_errno = GRUB_ERR_NONE;
+  partnum = grub_strtoul (s, 0, 10) - 1;
+  if (grub_errno == GRUB_ERR_NONE)
+    {
+      if (sun_partition_map_iterate (disk, find_func))
+        {
+          grub_free (p);
+          p = 0;
+        }
+    }
+  else
+    {
+      grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
+      p = 0;
+    }
+  
+  return p;
+}
+
+static char *
+sun_partition_map_get_name (const grub_partition_t p)
+{
+  char *name;
+  
+  name = grub_malloc (13);
+  if (name)
+    grub_sprintf (name, "%d", p->index + 1);
+  
+  return name;
+}
+
+/* Partition map type.  */
+static struct grub_partition_map grub_sun_partition_map =
+  {
+    .name = "sun_partition_map",
+    .iterate = sun_partition_map_iterate,
+    .probe = sun_partition_map_probe,
+    .get_name = sun_partition_map_get_name
+  };
+
+GRUB_MOD_INIT(sun_partition_map)
+{
+  grub_partition_map_register (&grub_sun_partition_map);
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+}
+
+GRUB_MOD_FINI(sun_partition_map)
+{
+  grub_partition_map_unregister (&grub_sun_partition_map);
+}
+
diff --git a/stamp-h.in b/stamp-h.in
new file mode 100644 (file)
index 0000000..9788f70
--- /dev/null
@@ -0,0 +1 @@
+timestamp
diff --git a/term/efi/console.c b/term/efi/console.c
new file mode 100644 (file)
index 0000000..0bf2449
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/api.h>
+#include <grub/efi/console.h>
+
+static grub_uint8_t
+grub_console_standard_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_YELLOW,
+                                                 GRUB_EFI_BACKGROUND_BLACK);
+static grub_uint8_t
+grub_console_normal_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_LIGHTGRAY,
+                                               GRUB_EFI_BACKGROUND_BLACK);
+static grub_uint8_t
+grub_console_highlight_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_BLACK,
+                                                  GRUB_EFI_BACKGROUND_LIGHTGRAY);
+
+static int read_key = -1;
+
+static grub_uint32_t
+map_char (grub_uint32_t c)
+{
+  if (c > 0x7f)
+    {
+      /* Map some unicode characters to the EFI character.  */
+      switch (c)
+       {
+       case 0x2190:    /* left arrow */
+         c = 0x25c4;
+         break;
+       case 0x2191:    /* up arrow */
+         c = 0x25b2;
+         break;
+       case 0x2192:    /* right arrow */
+         c = 0x25ba;
+         break;
+       case 0x2193:    /* down arrow */
+         c = 0x25bc;
+         break;
+       case 0x2501:    /* horizontal line */
+         c = 0x2500;
+         break;
+       case 0x2503:    /* vertical line */
+         c = 0x2502;
+         break;
+       case 0x250F:    /* upper-left corner */
+         c = 0x250c;
+         break;
+       case 0x2513:    /* upper-right corner */
+         c = 0x2510;
+         break;
+       case 0x2517:    /* lower-left corner */
+         c = 0x2514;
+         break;
+       case 0x251B:    /* lower-right corner */
+         c = 0x2518;
+         break;
+
+       default:
+         c = '?';
+         break;
+       }
+    }
+
+  return c;
+}
+
+static void
+grub_console_putchar (grub_uint32_t c)
+{
+  grub_efi_char16_t str[2];
+  grub_efi_simple_text_output_interface_t *o;
+  
+  o = grub_efi_system_table->con_out;
+  
+  /* For now, do not try to use a surrogate pair.  */
+  if (c > 0xffff)
+    c = '?';
+
+  str[0] = (grub_efi_char16_t)  map_char (c & 0xffff);
+  str[1] = 0;
+
+  /* Should this test be cached?  */
+  if (c > 0x7f && efi_call_2 (o->test_string, o, str) != GRUB_EFI_SUCCESS)
+    return;
+  
+  efi_call_2 (o->output_string, o, str);
+}
+
+static grub_ssize_t
+grub_console_getcharwidth (grub_uint32_t c __attribute__ ((unused)))
+{
+  /* For now, every printable character has the width 1.  */
+  return 1;
+}
+
+static int
+grub_console_checkkey (void)
+{
+  grub_efi_simple_input_interface_t *i;
+  grub_efi_input_key_t key;
+  grub_efi_status_t status;
+  
+  if (read_key >= 0)
+    return 1;
+
+  i = grub_efi_system_table->con_in;
+  status = efi_call_2 (i->read_key_stroke, i, &key);
+#if 0
+  switch (status)
+    {
+    case GRUB_EFI_SUCCESS:
+      {
+       grub_uint16_t xy;
+       
+       xy = grub_getxy ();
+       grub_gotoxy (0, 0);
+       grub_printf ("scan_code=%x,unicode_char=%x  ",
+                    (unsigned) key.scan_code,
+                    (unsigned) key.unicode_char);
+       grub_gotoxy (xy >> 8, xy & 0xff);
+      }
+      break;
+
+    case GRUB_EFI_NOT_READY:
+      //grub_printf ("not ready   ");
+      break;
+
+    default:
+      //grub_printf ("device error   ");
+      break;
+    }
+#endif
+  
+  if (status == GRUB_EFI_SUCCESS)
+    {
+      switch (key.scan_code)
+       {
+       case 0x00:
+         read_key = key.unicode_char;
+         break;
+       case 0x01:
+         read_key = 16;
+         break;
+       case 0x02:
+         read_key = 14;
+         break;
+       case 0x03:
+         read_key = 6;
+         break;
+       case 0x04:
+         read_key = 2;
+         break;
+       case 0x05:
+         read_key = 1;
+         break;
+       case 0x06:
+         read_key = 5;
+         break;
+       case 0x07:
+         break;
+       case 0x08:
+         read_key = 4;
+         break;
+       case 0x09:
+         break;
+       case 0x0a:
+         break;
+       case 0x0b:
+         read_key = 24;
+         break;
+       case 0x0c:
+         read_key = 1;
+         break;
+       case 0x0d:
+         read_key = 5;
+         break;
+       case 0x17:
+         read_key = '\e';
+         break;
+       default:
+         break;
+       }
+    }
+
+  return read_key;
+}
+
+static int
+grub_console_getkey (void)
+{
+  grub_efi_simple_input_interface_t *i;
+  grub_efi_boot_services_t *b;
+  grub_efi_uintn_t index;
+  grub_efi_status_t status;
+  int key;
+
+  if (read_key >= 0)
+    {
+      key = read_key;
+      read_key = -1;
+      return key;
+    }
+
+  i = grub_efi_system_table->con_in;
+  b = grub_efi_system_table->boot_services;
+
+  do
+    {
+      status = efi_call_3 (b->wait_for_event, 1, &(i->wait_for_key), &index);
+      if (status != GRUB_EFI_SUCCESS)
+        return -1;
+      
+      grub_console_checkkey ();
+    }
+  while (read_key < 0);
+  
+  key = read_key;
+  read_key = -1;
+  return key;
+}
+
+static grub_uint16_t
+grub_console_getwh (void)
+{
+  grub_efi_simple_text_output_interface_t *o;
+  grub_efi_uintn_t columns, rows;
+  
+  o = grub_efi_system_table->con_out;
+  if (efi_call_4 (o->query_mode, o, o->mode->mode, &columns, &rows) != GRUB_EFI_SUCCESS)
+    {
+      /* Why does this fail?  */
+      columns = 80;
+      rows = 25;
+    }
+
+  return ((columns << 8) | rows);
+}
+
+static grub_uint16_t
+grub_console_getxy (void)
+{
+  grub_efi_simple_text_output_interface_t *o;
+  
+  o = grub_efi_system_table->con_out;
+  return ((o->mode->cursor_column << 8) | o->mode->cursor_row);
+}
+
+static void
+grub_console_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+  grub_efi_simple_text_output_interface_t *o;
+  
+  o = grub_efi_system_table->con_out;
+  efi_call_3 (o->set_cursor_position, o, x, y);
+}
+
+static void
+grub_console_cls (void)
+{
+  grub_efi_simple_text_output_interface_t *o;
+  grub_efi_int32_t orig_attr;
+  
+  o = grub_efi_system_table->con_out;
+  orig_attr = o->mode->attribute;
+  efi_call_2 (o->set_attributes, o, GRUB_EFI_BACKGROUND_BLACK);
+  efi_call_1 (o->clear_screen, o);
+  efi_call_2 (o->set_attributes, o, orig_attr);
+}
+
+static void
+grub_console_setcolorstate (grub_term_color_state state)
+{
+  grub_efi_simple_text_output_interface_t *o;
+
+  o = grub_efi_system_table->con_out;
+
+  switch (state) {
+    case GRUB_TERM_COLOR_STANDARD:
+      efi_call_2 (o->set_attributes, o, grub_console_standard_color);
+      break;
+    case GRUB_TERM_COLOR_NORMAL:
+      efi_call_2 (o->set_attributes, o, grub_console_normal_color);
+      break;
+    case GRUB_TERM_COLOR_HIGHLIGHT:
+      efi_call_2 (o->set_attributes, o, grub_console_highlight_color);
+      break;
+    default:
+      break;
+  }
+}
+
+static void
+grub_console_setcolor (grub_uint8_t normal_color, grub_uint8_t highlight_color)
+{
+  grub_console_normal_color = normal_color;
+  grub_console_highlight_color = highlight_color;
+}
+
+static void
+grub_console_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_color)
+{
+  *normal_color = grub_console_normal_color;
+  *highlight_color = grub_console_highlight_color;
+}
+
+static void
+grub_console_setcursor (int on)
+{
+  grub_efi_simple_text_output_interface_t *o;
+
+  o = grub_efi_system_table->con_out;
+  efi_call_2 (o->enable_cursor, o, on);
+}
+
+static struct grub_term_input grub_console_term_input =
+  {
+    .name = "console",
+    .checkkey = grub_console_checkkey,
+    .getkey = grub_console_getkey,
+  };
+
+static struct grub_term_output grub_console_term_output =
+  {
+    .name = "console",
+    .putchar = grub_console_putchar,
+    .getcharwidth = grub_console_getcharwidth,
+    .getwh = grub_console_getwh,
+    .getxy = grub_console_getxy,
+    .gotoxy = grub_console_gotoxy,
+    .cls = grub_console_cls,
+    .setcolorstate = grub_console_setcolorstate,
+    .setcolor = grub_console_setcolor,
+    .getcolor = grub_console_getcolor,
+    .setcursor = grub_console_setcursor,
+    .flags = 0,
+  };
+
+void
+grub_console_init (void)
+{
+  /* FIXME: it is necessary to consider the case where no console control
+     is present but the default is already in text mode.  */
+  if (! grub_efi_set_text_mode (1))
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, "cannot set text mode");
+      return;
+    }
+
+  grub_term_register_input (&grub_console_term_input);
+  grub_term_register_output (&grub_console_term_output);
+}
+
+void
+grub_console_fini (void)
+{
+  grub_term_unregister_input (&grub_console_term_input);
+  grub_term_unregister_output (&grub_console_term_output);
+}
diff --git a/term/gfxterm.c b/term/gfxterm.c
new file mode 100644 (file)
index 0000000..abb1b9e
--- /dev/null
@@ -0,0 +1,1181 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/term.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/font.h>
+#include <grub/arg.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+#include <grub/video.h>
+#include <grub/bitmap.h>
+
+#define DEFAULT_VIDEO_WIDTH    640
+#define DEFAULT_VIDEO_HEIGHT   480
+#define DEFAULT_VIDEO_FLAGS    0
+
+#define DEFAULT_BORDER_WIDTH   10
+
+#define DEFAULT_STANDARD_COLOR  0x07
+#define DEFAULT_NORMAL_COLOR    0x07
+#define DEFAULT_HIGHLIGHT_COLOR 0x70
+
+struct grub_dirty_region
+{
+  int top_left_x;
+  int top_left_y;
+  int bottom_right_x;
+  int bottom_right_y;
+};
+
+struct grub_colored_char
+{
+  /* An Unicode codepoint.  */
+  grub_uint32_t code;
+
+  /* Color values.  */
+  grub_video_color_t fg_color;
+  grub_video_color_t bg_color;
+
+  /* The width of this character minus one.  */
+  unsigned char width;
+
+  /* The column index of this character.  */
+  unsigned char index;
+};
+
+struct grub_virtual_screen
+{
+  /* Dimensions of the virtual screen in pixels.  */
+  unsigned int width;
+  unsigned int height;
+
+  /* Offset in the display in pixels.  */
+  unsigned int offset_x;
+  unsigned int offset_y;
+
+  /* TTY Character sizes in pixes.  */
+  unsigned int normal_char_width;
+  unsigned int normal_char_height;
+
+  /* Virtual screen TTY size in characters.  */
+  unsigned int columns;
+  unsigned int rows;
+
+  /* Current cursor location in characters.  */
+  unsigned int cursor_x;
+  unsigned int cursor_y;
+
+  /* Current cursor state. */
+  int cursor_state;
+
+  /* Font settings. */
+  grub_font_t font;
+
+  /* Terminal color settings.  */
+  grub_uint8_t standard_color_setting;
+  grub_uint8_t normal_color_setting;
+  grub_uint8_t highlight_color_setting;
+  grub_uint8_t term_color;
+  
+  /* Color settings.  */
+  grub_video_color_t fg_color;
+  grub_video_color_t bg_color;
+
+  /* Text buffer for virtual screen.  Contains (columns * rows) number
+     of entries.  */
+  struct grub_colored_char *text_buffer;
+};
+
+static struct grub_virtual_screen virtual_screen;
+
+static grub_dl_t my_mod;
+static struct grub_video_mode_info mode_info;
+
+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 struct grub_dirty_region dirty_region;
+
+static void dirty_region_reset (void);
+
+static int dirty_region_is_empty (void);
+
+static void dirty_region_add (int x, int y, 
+                              unsigned int width, unsigned int height);
+
+static unsigned int calculate_normal_character_width (grub_font_t font);
+
+static unsigned char calculate_character_width (struct grub_font_glyph *glyph);
+
+static void
+set_term_color (grub_uint8_t term_color)
+{
+  struct grub_video_render_target *old_target;
+
+  /* Save previous target and switch to text layer.  */
+  grub_video_get_active_render_target (&old_target);
+  grub_video_set_active_render_target (text_layer);
+
+  /* Map terminal color to text layer compatible video colors.  */
+  virtual_screen.fg_color = grub_video_map_color(term_color & 0x0f);
+  
+  /* Special case: use black as transparent color.  */
+  if (((term_color >> 4) & 0x0f) == 0)
+    {
+      virtual_screen.bg_color = grub_video_map_rgba(0, 0, 0, 0);
+    } 
+  else
+    {
+      virtual_screen.bg_color = grub_video_map_color((term_color >> 4) & 0x0f);
+    }
+
+  /* Restore previous target.  */
+  grub_video_set_active_render_target (old_target);
+}
+
+static void
+grub_virtual_screen_free (void)
+{
+  /* If virtual screen has been allocated, free it.  */
+  if (virtual_screen.text_buffer != 0)
+    grub_free (virtual_screen.text_buffer);
+
+  /* Reset virtual screen data.  */
+  grub_memset (&virtual_screen, 0, sizeof (virtual_screen));
+
+  /* Free render targets.  */
+  grub_video_delete_render_target (text_layer);
+  text_layer = 0;
+}
+
+static grub_err_t
+grub_virtual_screen_setup (unsigned int x, unsigned int y,
+                           unsigned int width, unsigned int height,
+                           const char *font_name)
+{
+  /* Free old virtual screen.  */
+  grub_virtual_screen_free ();
+
+  /* Initialize with default data.  */
+  virtual_screen.font = grub_font_get (font_name);
+  if (!virtual_screen.font)
+    return grub_error (GRUB_ERR_BAD_FONT,
+                       "No font loaded.");
+  virtual_screen.width = width;
+  virtual_screen.height = height;
+  virtual_screen.offset_x = x;
+  virtual_screen.offset_y = y;
+  virtual_screen.normal_char_width =
+    calculate_normal_character_width (virtual_screen.font);
+  virtual_screen.normal_char_height =
+    grub_font_get_max_char_height (virtual_screen.font);
+  virtual_screen.cursor_x = 0;
+  virtual_screen.cursor_y = 0;
+  virtual_screen.cursor_state = 1;
+
+  /* Calculate size of text buffer.  */
+  virtual_screen.columns = virtual_screen.width / virtual_screen.normal_char_width;
+  virtual_screen.rows = virtual_screen.height / virtual_screen.normal_char_height;
+
+  /* Allocate memory for text buffer.  */
+  virtual_screen.text_buffer =
+    (struct grub_colored_char *) grub_malloc (virtual_screen.columns
+                                              * virtual_screen.rows
+                                              * sizeof (*virtual_screen.text_buffer));
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* Create new render target for text layer.  */
+  grub_video_create_render_target (&text_layer,
+                                   virtual_screen.width,
+                                   virtual_screen.height,
+                                   GRUB_VIDEO_MODE_TYPE_RGB
+                                   | GRUB_VIDEO_MODE_TYPE_ALPHA);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* As we want to have colors compatible with rendering target,
+     we can only have those after mode is initialized.  */
+  grub_video_set_active_render_target (text_layer);
+
+  virtual_screen.standard_color_setting = DEFAULT_STANDARD_COLOR;
+  virtual_screen.normal_color_setting = DEFAULT_NORMAL_COLOR;
+  virtual_screen.highlight_color_setting = DEFAULT_HIGHLIGHT_COLOR;
+  
+  virtual_screen.term_color = virtual_screen.normal_color_setting;
+  
+  set_term_color (virtual_screen.term_color);
+
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_gfxterm_init (void)
+{
+  char *font_name;
+  char *modevar;
+  int width = DEFAULT_VIDEO_WIDTH;
+  int height = DEFAULT_VIDEO_HEIGHT;
+  int depth = -1;
+  int flags = DEFAULT_VIDEO_FLAGS;
+  grub_video_color_t color;
+
+  /* Select the font to use. */
+  font_name = grub_env_get ("gfxterm_font");
+  if (! font_name)
+    font_name = "";   /* Allow fallback to any font. */
+
+  /* Parse gfxmode environment variable if set.  */
+  modevar = grub_env_get ("gfxmode");
+  if (modevar)
+    {
+      char *tmp;
+      char *next_mode;
+      char *current_mode;
+      char *param;
+      char *value;
+      int mode_found = 0;
+
+      /* Take copy of env.var. as we don't want to modify that.  */
+      tmp = grub_strdup (modevar);
+      modevar = tmp;
+
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;
+        
+      /* Initialize next mode.  */
+      next_mode = modevar;
+      
+      /* Loop until all modes has been tested out.  */
+      while (next_mode != NULL)
+        {
+          /* Use last next_mode as current mode.  */
+          tmp = next_mode;
+          
+          /* Reset video mode settings.  */
+          width = DEFAULT_VIDEO_WIDTH;
+          height = DEFAULT_VIDEO_HEIGHT;
+          depth = -1;
+          flags = DEFAULT_VIDEO_FLAGS;
+        
+          /* Save position of next mode and separate modes.  */
+          next_mode = grub_strchr(next_mode, ';');
+          if (next_mode)
+            {
+              *next_mode = 0;
+              next_mode++;
+            }
+
+          /* Skip whitespace.  */
+          while (grub_isspace (*tmp))
+            tmp++;
+
+          /* Initialize token holders.  */
+          current_mode = tmp;
+          param = tmp;
+          value = NULL;
+
+          /* Parse <width>x<height>[x<depth>]*/
+
+          /* Find width value.  */
+          value = param;
+          param = grub_strchr(param, 'x');
+          if (param == NULL)
+            {
+              grub_err_t rc;
+              
+              /* First setup error message.  */
+              rc = grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                               "Invalid mode: %s\n",
+                               current_mode);
+              
+              /* Free memory before returning.  */
+              grub_free (modevar);
+              
+              return rc;
+            }
+
+          *param = 0;
+          param++;
+
+          width = grub_strtoul (value, 0, 0);
+          if (grub_errno != GRUB_ERR_NONE)
+            {
+              grub_err_t rc;
+              
+              /* First setup error message.  */
+              rc = grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                               "Invalid mode: %s\n",
+                               current_mode);
+              
+              /* Free memory before returning.  */
+              grub_free (modevar);
+              
+              return rc;
+            }
+
+          /* Find height value.  */
+          value = param;
+          param = grub_strchr(param, 'x');
+          if (param == NULL)
+            {
+              height = grub_strtoul (value, 0, 0);
+              if (grub_errno != GRUB_ERR_NONE)
+                {
+                  grub_err_t rc;
+                  
+                  /* First setup error message.  */
+                  rc = grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                                   "Invalid mode: %s\n",
+                                   current_mode);
+                                   
+                  /* Free memory before returning.  */
+                  grub_free (modevar);
+                  
+                  return rc;
+                }
+            }
+          else
+            {
+              /* We have optional color depth value.  */
+              *param = 0;
+              param++;
+
+              height = grub_strtoul (value, 0, 0);
+              if (grub_errno != GRUB_ERR_NONE)
+                {
+                  grub_err_t rc;
+                  
+                  /* First setup error message.  */
+                  rc = grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                                   "Invalid mode: %s\n",
+                                   current_mode);
+                                   
+                  /* Free memory before returning.  */
+                  grub_free (modevar);
+                  
+                  return rc;
+                }
+
+              /* Convert color depth value.  */
+              value = param;
+              depth = grub_strtoul (value, 0, 0);
+              if (grub_errno != GRUB_ERR_NONE)
+                {
+                  grub_err_t rc;
+                  
+                  /* First setup error message.  */
+                  rc = grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                                   "Invalid mode: %s\n",
+                                   current_mode);
+                                   
+                  /* Free memory before returning.  */
+                  grub_free (modevar);
+                  
+                  return rc;
+                }
+            }
+          
+          /* Try out video mode.  */
+          
+          /* If we have 8 or less bits, then assume that it is indexed color mode.  */
+          if ((depth <= 8) && (depth != -1))
+            flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+
+          /* We have more than 8 bits, then assume that it is RGB color mode.  */
+          if (depth > 8)
+            flags |= GRUB_VIDEO_MODE_TYPE_RGB;
+
+          /* If user requested specific depth, forward that information to driver.  */
+          if (depth != -1)
+            flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
+                     & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
+
+          /* Try to initialize requested mode.  Ignore any errors.  */
+          grub_error_push ();
+          if (grub_video_setup (width, height, flags) != GRUB_ERR_NONE)
+            {
+              grub_error_pop ();
+              continue;
+            }
+            
+          /* Figure out what mode we ended up.  */
+          if (grub_video_get_info (&mode_info) != GRUB_ERR_NONE)
+            {
+              /* Couldn't get video mode info, restore old mode and continue to next one.  */
+              grub_error_pop ();
+              
+              grub_video_restore ();
+              continue;
+            }
+          
+          /* Restore state of error stack.  */
+          grub_error_pop ();
+          
+          /* Mode found!  Exit loop.  */
+          mode_found = 1;
+          break;
+        }
+
+      /* Free memory.  */
+      grub_free (modevar);
+      
+      if (!mode_found)
+        return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                           "No suitable mode found.");
+    }
+  else
+    {
+      /* No gfxmode variable set, use defaults.  */
+      
+      /* If we have 8 or less bits, then assume that it is indexed color mode.  */
+      if ((depth <= 8) && (depth != -1))
+        flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+
+      /* We have more than 8 bits, then assume that it is RGB color mode.  */
+      if (depth > 8)
+        flags |= GRUB_VIDEO_MODE_TYPE_RGB;
+
+      /* If user requested specific depth, forward that information to driver.  */
+      if (depth != -1)
+        flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
+                 & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
+
+      /* Initialize user requested mode.  */
+      if (grub_video_setup (width, height, flags) != GRUB_ERR_NONE)
+        return grub_errno;
+
+      /* Figure out what mode we ended up.  */
+      if (grub_video_get_info (&mode_info) != GRUB_ERR_NONE)
+        {
+          grub_video_restore ();
+          return grub_errno;
+        }
+    }
+
+  /* Make sure screen is black.  */
+  color = grub_video_map_rgb (0, 0, 0);
+  grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
+  bitmap = 0;
+
+  /* Leave borders for virtual screen.  */
+  width = mode_info.width - (2 * DEFAULT_BORDER_WIDTH);
+  height = mode_info.height - (2 * DEFAULT_BORDER_WIDTH);
+
+  /* Create virtual screen.  */
+  if (grub_virtual_screen_setup (DEFAULT_BORDER_WIDTH, DEFAULT_BORDER_WIDTH,
+                                 width, height, font_name) != GRUB_ERR_NONE)
+    {
+      grub_video_restore ();
+      return grub_errno;
+    }
+
+  /* Mark whole screen as dirty.  */
+  dirty_region_reset ();
+  dirty_region_add (0, 0, mode_info.width, mode_info.height);
+
+  return (grub_errno = GRUB_ERR_NONE);
+}
+
+static grub_err_t
+grub_gfxterm_fini (void)
+{
+  if (bitmap)
+    {
+      grub_video_bitmap_destroy (bitmap);
+      bitmap = 0;
+    }
+
+  grub_virtual_screen_free ();
+
+  grub_video_restore ();
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+redraw_screen_rect (unsigned int x, unsigned int y, 
+                    unsigned int width, unsigned int height)
+{
+  grub_video_color_t color;
+
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+
+  if (bitmap)
+    {
+      /* Render bitmap as background.  */
+      grub_video_blit_bitmap (bitmap, GRUB_VIDEO_BLIT_REPLACE, x, y, 
+                              x, y, 
+                              width, height);
+      
+      /* If bitmap is smaller than requested blit area, use background 
+         color.  */
+      color = virtual_screen.bg_color;
+
+      /* Fill right side of the bitmap if needed.  */
+      if ((x + width >= bitmap_width) && (y < bitmap_height))
+        {
+          int w = (x + width) - bitmap_width;
+          int h = height;
+          unsigned int tx = x;
+
+          if (y + height >= bitmap_height)
+            {
+              h = bitmap_height - y;
+            }
+          
+          if (bitmap_width > tx)
+            {
+              tx = bitmap_width;
+            }
+          
+          /* Render background layer.  */
+          grub_video_fill_rect (color, tx, y, w, h);        
+        }
+      
+      /* Fill bottom side of the bitmap if needed.  */
+      if (y + height >= bitmap_height)
+        {
+          int h = (y + height) - bitmap_height;
+          unsigned int ty = y;
+          
+          if (bitmap_height > ty)
+            {
+              ty = bitmap_height;
+            }
+          
+          /* 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;
+      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);      
+    }
+}
+
+static void
+dirty_region_reset (void)
+{
+  dirty_region.top_left_x = -1;
+  dirty_region.top_left_y = -1;
+  dirty_region.bottom_right_x = -1;
+  dirty_region.bottom_right_y = -1;
+}
+
+static int
+dirty_region_is_empty (void)
+{
+  if ((dirty_region.top_left_x == -1)
+      || (dirty_region.top_left_y == -1)
+      || (dirty_region.bottom_right_x == -1)
+      || (dirty_region.bottom_right_y == -1))
+    return 1;
+  return 0;
+}
+
+static void
+dirty_region_add (int x, int y, unsigned int width, unsigned int height)
+{
+  if ((width == 0) || (height == 0))
+    return;
+
+  if (dirty_region_is_empty ())
+    {
+      dirty_region.top_left_x = x;
+      dirty_region.top_left_y = y;
+      dirty_region.bottom_right_x = x + width - 1;
+      dirty_region.bottom_right_y = y + height - 1;
+    } 
+  else
+    {
+      if (x < dirty_region.top_left_x)
+        dirty_region.top_left_x = x;
+      if (y < dirty_region.top_left_y)
+        dirty_region.top_left_y = y;
+      if ((x + (int)width - 1) > dirty_region.bottom_right_x)
+        dirty_region.bottom_right_x = x + width - 1;
+      if ((y + (int)height - 1) > dirty_region.bottom_right_y)
+        dirty_region.bottom_right_y = y + height - 1;
+    }
+} 
+
+static void
+dirty_region_add_virtualscreen (void)
+{
+  /* Mark virtual screen as dirty.  */
+  dirty_region_add (virtual_screen.offset_x, virtual_screen.offset_y,
+                    virtual_screen.width, virtual_screen.height);
+}
+
+
+static void
+dirty_region_redraw (void)
+{
+  int x;
+  int y;
+  int width;
+  int height;
+
+  if (dirty_region_is_empty ())
+    return;
+
+  x = dirty_region.top_left_x;
+  y = dirty_region.top_left_y;
+
+  width = dirty_region.bottom_right_x - x + 1;
+  height = dirty_region.bottom_right_y - y + 1;
+
+  redraw_screen_rect (x, y, width, height);
+
+  dirty_region_reset ();
+}
+
+static void
+write_char (void)
+{
+  struct grub_colored_char *p;
+  struct grub_font_glyph *glyph;
+  grub_video_color_t color;
+  grub_video_color_t bgcolor;
+  unsigned int x;
+  unsigned int y;
+  int ascent;
+  unsigned int height;
+  unsigned int width;
+
+  /* Find out active character.  */
+  p = (virtual_screen.text_buffer
+       + virtual_screen.cursor_x
+       + (virtual_screen.cursor_y * virtual_screen.columns));
+
+  p -= p->index;
+
+  /* Get glyph for character.  */
+  glyph = grub_font_get_glyph (virtual_screen.font, p->code);
+  ascent = grub_font_get_ascent (virtual_screen.font);
+  
+  width = virtual_screen.normal_char_width * calculate_character_width(glyph);
+  height = virtual_screen.normal_char_height;
+  
+  color = p->fg_color;
+  bgcolor = p->bg_color;
+
+  x = virtual_screen.cursor_x * virtual_screen.normal_char_width;
+  y = virtual_screen.cursor_y * virtual_screen.normal_char_height;
+
+  /* Render glyph to text layer.  */
+  grub_video_set_active_render_target (text_layer);
+  grub_video_fill_rect (bgcolor, x, y, width, height);
+  grub_font_draw_glyph (glyph, color, x, y + ascent);
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+  /* Mark character to be drawn.  */
+  dirty_region_add (virtual_screen.offset_x + x, virtual_screen.offset_y + y,
+                    width, height);
+}
+
+static void
+draw_cursor (int show)
+{
+  unsigned int x;
+  unsigned int y;
+  unsigned int width;
+  unsigned int height;
+  grub_video_color_t color;
+
+  /* Determine cursor properties and position on text layer. */
+  x = virtual_screen.cursor_x * virtual_screen.normal_char_width;
+  y = (virtual_screen.cursor_y * virtual_screen.normal_char_height
+       + grub_font_get_ascent (virtual_screen.font));
+  width = virtual_screen.normal_char_width;
+  height = 2;
+
+  if (show)
+    {
+      color = virtual_screen.fg_color;
+    }
+  else
+    {
+      color = virtual_screen.bg_color;
+      y = virtual_screen.cursor_y * virtual_screen.normal_char_height;
+      height = virtual_screen.normal_char_height;
+    }
+
+  /* Render cursor to text layer.  */
+  grub_video_set_active_render_target (text_layer);
+  grub_video_fill_rect (color, x, y, width, height);
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+  /* Mark cursor to be redrawn.  */
+  dirty_region_add (virtual_screen.offset_x + x, virtual_screen.offset_y + y,
+                    width, height);
+}
+
+static void
+scroll_up (void)
+{
+  unsigned int i;
+  grub_video_color_t color;
+
+  /* If we don't have background bitmap, remove cursor. */
+  if (!bitmap)
+    {
+      /* Remove cursor.  */
+      draw_cursor (0);
+
+      /* Redraw only changed regions.  */
+      dirty_region_redraw ();
+    }
+  
+  /* Scroll text buffer with one line to up.  */
+  grub_memmove (virtual_screen.text_buffer,
+                virtual_screen.text_buffer + virtual_screen.columns,
+                sizeof (*virtual_screen.text_buffer)
+                * virtual_screen.columns
+                * (virtual_screen.rows - 1));
+
+  /* Clear last line in text buffer.  */
+  for (i = virtual_screen.columns * (virtual_screen.rows - 1);
+       i < virtual_screen.columns * virtual_screen.rows;
+       i++)
+    {
+      virtual_screen.text_buffer[i].code = ' ';
+      virtual_screen.text_buffer[i].fg_color = virtual_screen.fg_color;
+      virtual_screen.text_buffer[i].bg_color = virtual_screen.bg_color;
+      virtual_screen.text_buffer[i].width = 0;
+      virtual_screen.text_buffer[i].index = 0;
+    }
+
+  /* Scroll physical screen.  */
+  grub_video_set_active_render_target (text_layer);
+  color = virtual_screen.bg_color;
+  grub_video_scroll (color, 0, -virtual_screen.normal_char_height);
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+  
+  /* If we have bitmap, re-draw screen, otherwise scroll physical screen too.  */
+  if (bitmap)
+    {
+      /* Mark virtual screen to be redrawn.  */
+      dirty_region_add_virtualscreen ();
+    }
+  else
+    {      
+      /* Clear new border area.  */
+      grub_video_fill_rect (color,
+                            virtual_screen.offset_x, virtual_screen.offset_y,
+                            virtual_screen.width, virtual_screen.normal_char_height);
+
+      /* Scroll physical screen.  */
+      grub_video_scroll (color, 0, -virtual_screen.normal_char_height);
+
+      /* Draw cursor if visible.  */
+      if (virtual_screen.cursor_state)
+       draw_cursor (1);
+    }
+}
+
+static void
+grub_gfxterm_putchar (grub_uint32_t c)
+{
+  if (c == '\a')
+    /* FIXME */
+    return;
+
+  if (c == '\b' || c == '\n' || c == '\r')
+    {
+      /* Erase current cursor, if any.  */
+      if (virtual_screen.cursor_state)
+       draw_cursor (0);
+
+      switch (c)
+        {
+        case '\b':
+          if (virtual_screen.cursor_x > 0)
+            virtual_screen.cursor_x--;
+          break;
+
+        case '\n':
+          if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
+            scroll_up ();
+          else
+            virtual_screen.cursor_y++;
+          break;
+
+        case '\r':
+          virtual_screen.cursor_x = 0;
+          break;
+        }
+
+      /* Redraw cursor if visible.  */
+      if (virtual_screen.cursor_state)
+       draw_cursor (1);
+    }
+  else
+    {
+      struct grub_font_glyph *glyph;
+      struct grub_colored_char *p;
+      unsigned char char_width;
+
+      /* Erase current cursor, if any.  */
+      if (virtual_screen.cursor_state)
+       draw_cursor (0);
+
+      /* Get properties of the character.  */
+      glyph = grub_font_get_glyph (virtual_screen.font, c);
+
+      /* Calculate actual character width for glyph. This is number of
+         times of normal_font_width.  */
+      char_width = calculate_character_width(glyph);
+
+      /* If we are about to exceed line length, wrap to next line.  */
+      if (virtual_screen.cursor_x + char_width > virtual_screen.columns)
+        grub_putchar ('\n');
+
+      /* Find position on virtual screen, and fill information.  */
+      p = (virtual_screen.text_buffer +
+           virtual_screen.cursor_x +
+           virtual_screen.cursor_y * virtual_screen.columns);
+      p->code = c;
+      p->fg_color = virtual_screen.fg_color;
+      p->bg_color = virtual_screen.bg_color;
+      p->width = char_width - 1;
+      p->index = 0;
+
+      /* If we have large glyph, add fixup info.  */
+      if (char_width > 1)
+        {
+          unsigned i;
+
+          for (i = 1; i < char_width; i++)
+            {
+              p[i].code = ' ';
+              p[i].width = char_width - 1;
+              p[i].index = i;
+            }
+        }
+
+      /* Draw glyph.  */
+      write_char ();
+
+      /* Make sure we scroll screen when needed and wrap line correctly.  */
+      virtual_screen.cursor_x += char_width;
+      if (virtual_screen.cursor_x >= virtual_screen.columns)
+        {
+          virtual_screen.cursor_x = 0;
+
+          if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
+            scroll_up ();
+          else
+            virtual_screen.cursor_y++;
+        }
+
+      /* Draw cursor if visible.  */
+      if (virtual_screen.cursor_state)
+       draw_cursor (1);
+    }
+}
+
+/* Use ASCII characters to determine normal character width.  */
+static unsigned int
+calculate_normal_character_width (grub_font_t font)
+{
+  struct grub_font_glyph *glyph;
+  unsigned int width = 0;
+  unsigned int i;
+
+  /* Get properties of every printable ASCII character.  */
+  for (i = 32; i < 127; i++)
+    {
+      glyph = grub_font_get_glyph (font, i);
+
+      /* Skip unknown characters.  Should never happen on normal conditions.  */
+      if (! glyph)
+       continue;
+
+      if (glyph->device_width > width)
+       width = glyph->device_width;
+    }
+
+  return width;
+}
+
+static unsigned char
+calculate_character_width (struct grub_font_glyph *glyph)
+{
+  if (! glyph || glyph->device_width == 0)
+    return 1;
+
+  return (glyph->device_width
+          + (virtual_screen.normal_char_width - 1))
+         / virtual_screen.normal_char_width;
+}
+
+static grub_ssize_t
+grub_gfxterm_getcharwidth (grub_uint32_t c)
+{
+  struct grub_font_glyph *glyph;
+  unsigned char char_width;
+
+  /* Get properties of the character.  */
+  glyph = grub_font_get_glyph (virtual_screen.font, c);
+
+  /* Calculate actual character width for glyph.  */
+  char_width = calculate_character_width (glyph);
+
+  return char_width;
+}
+
+static grub_uint16_t
+grub_virtual_screen_getwh (void)
+{
+  return (virtual_screen.columns << 8) | virtual_screen.rows;
+}
+
+static grub_uint16_t
+grub_virtual_screen_getxy (void)
+{
+  return ((virtual_screen.cursor_x << 8) | virtual_screen.cursor_y);
+}
+
+static void
+grub_gfxterm_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+  if (x >= virtual_screen.columns)
+    x = virtual_screen.columns - 1;
+
+  if (y >= virtual_screen.rows)
+    y = virtual_screen.rows - 1;
+
+  /* Erase current cursor, if any.  */
+  if (virtual_screen.cursor_state)
+    draw_cursor (0);
+
+  virtual_screen.cursor_x = x;
+  virtual_screen.cursor_y = y;
+
+  /* Draw cursor if visible.  */
+  if (virtual_screen.cursor_state)
+    draw_cursor (1);
+}
+
+static void
+grub_virtual_screen_cls (void)
+{
+  grub_uint32_t i;
+
+  for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++)
+    {
+      virtual_screen.text_buffer[i].code = ' ';
+      virtual_screen.text_buffer[i].fg_color = virtual_screen.fg_color;
+      virtual_screen.text_buffer[i].bg_color = virtual_screen.bg_color;
+      virtual_screen.text_buffer[i].width = 0;
+      virtual_screen.text_buffer[i].index = 0;
+    }
+
+  virtual_screen.cursor_x = virtual_screen.cursor_y = 0;
+}
+
+static void
+grub_gfxterm_cls (void)
+{
+  grub_video_color_t color;
+
+  /* Clear virtual screen.  */
+  grub_virtual_screen_cls ();
+
+  /* Clear text layer.  */
+  grub_video_set_active_render_target (text_layer);
+  color = virtual_screen.bg_color;
+  grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
+  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
+
+  /* Mark virtual screen to be redrawn.  */
+  dirty_region_add_virtualscreen ();
+}
+
+static void
+grub_virtual_screen_setcolorstate (grub_term_color_state state)
+{
+  switch (state)
+    {
+    case GRUB_TERM_COLOR_STANDARD:
+      virtual_screen.term_color = virtual_screen.standard_color_setting;
+      break;
+      
+    case GRUB_TERM_COLOR_NORMAL:
+      virtual_screen.term_color = virtual_screen.normal_color_setting;
+      break;
+      
+    case GRUB_TERM_COLOR_HIGHLIGHT:
+      virtual_screen.term_color = virtual_screen.highlight_color_setting;
+      break;
+      
+    default:
+      break;
+    }
+
+  /* Change color to virtual terminal.  */
+  set_term_color (virtual_screen.term_color);
+}
+
+static void
+grub_virtual_screen_setcolor (grub_uint8_t normal_color,
+                              grub_uint8_t highlight_color)
+{
+  virtual_screen.normal_color_setting = normal_color;
+  virtual_screen.highlight_color_setting = highlight_color;
+}
+
+static void
+grub_virtual_screen_getcolor (grub_uint8_t *normal_color,
+                              grub_uint8_t *highlight_color)
+{
+  *normal_color = virtual_screen.normal_color_setting;
+  *highlight_color = virtual_screen.highlight_color_setting;
+}
+
+static void
+grub_gfxterm_setcursor (int on)
+{
+  if (virtual_screen.cursor_state != on)
+    {
+      if (virtual_screen.cursor_state)
+       draw_cursor (0);
+      else
+       draw_cursor (1);
+
+      virtual_screen.cursor_state = on;
+    }
+}
+
+static void
+grub_gfxterm_refresh (void)
+{
+  /* Redraw only changed regions.  */
+  dirty_region_redraw ();
+}
+
+static grub_err_t
+grub_gfxterm_background_image_cmd (struct grub_arg_list *state __attribute__ ((unused)),
+                                   int argc,
+                                   char **args)
+{
+  /* Check that we have video adapter active.  */
+  if (grub_video_get_info(NULL) != 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_reset ();
+      dirty_region_add (0, 0, mode_info.width, mode_info.height);
+    }
+
+  /* If filename was provided, try to load that.  */
+  if (argc >= 1)
+    {
+    /* Try to load new one.  */
+    grub_video_bitmap_load (&bitmap, args[0]);    
+    if (grub_errno != GRUB_ERR_NONE)
+      return grub_errno;
+
+    /* If bitmap was loaded correctly, display it.  */
+    if (bitmap)
+      {
+        /* Determine bitmap dimensions.  */
+        bitmap_width = grub_video_bitmap_get_width (bitmap);
+        bitmap_height = grub_video_bitmap_get_width (bitmap);
+        
+        /* Mark whole screen as dirty.  */
+        dirty_region_reset ();
+        dirty_region_add (0, 0, mode_info.width, mode_info.height);
+      }
+    }
+  
+  /* All was ok.  */
+  grub_errno = GRUB_ERR_NONE;
+  return grub_errno;
+}
+
+static struct grub_term_output grub_video_term =
+  {
+    .name = "gfxterm",
+    .init = grub_gfxterm_init,
+    .fini = grub_gfxterm_fini,
+    .putchar = grub_gfxterm_putchar,
+    .getcharwidth = grub_gfxterm_getcharwidth,
+    .getwh = grub_virtual_screen_getwh,
+    .getxy = grub_virtual_screen_getxy,
+    .gotoxy = grub_gfxterm_gotoxy,
+    .cls = grub_gfxterm_cls,
+    .setcolorstate = grub_virtual_screen_setcolorstate,
+    .setcolor = grub_virtual_screen_setcolor,
+    .getcolor = grub_virtual_screen_getcolor,
+    .setcursor = grub_gfxterm_setcursor,
+    .refresh = grub_gfxterm_refresh,
+    .flags = 0,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(term_gfxterm)
+{
+  my_mod = mod;
+  grub_term_register_output (&grub_video_term);
+
+  grub_register_command ("background_image",
+                         grub_gfxterm_background_image_cmd,
+                         GRUB_COMMAND_FLAG_BOTH,
+                         "background_image",
+                         "Load background image for active terminal",
+                         0);
+}
+
+GRUB_MOD_FINI(term_gfxterm)
+{
+  grub_unregister_command ("bgimage");
+  grub_term_unregister_output (&grub_video_term);
+}
diff --git a/term/i386/pc/at_keyboard.c b/term/i386/pc/at_keyboard.c
new file mode 100644 (file)
index 0000000..ff5246d
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ *  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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/i386/pc/console.h>
+#include <grub/i386/at_keyboard.h>
+#include <grub/i386/io.h>
+#include <grub/misc.h>
+#include <grub/term.h>
+
+static short at_keyboard_status = 0;
+
+#define KEYBOARD_STATUS_SHIFT_L                (1 << 0)
+#define KEYBOARD_STATUS_SHIFT_R                (1 << 1)
+#define KEYBOARD_STATUS_ALT_L          (1 << 2)
+#define KEYBOARD_STATUS_ALT_R          (1 << 3)
+#define KEYBOARD_STATUS_CTRL_L         (1 << 4)
+#define KEYBOARD_STATUS_CTRL_R         (1 << 5)
+#define KEYBOARD_STATUS_CAPS_LOCK      (1 << 6)
+
+static char keyboard_map[128] =
+{
+  '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6',
+  '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB,
+  'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
+  'o', 'p', '[', ']', '\n', '\0', 'a', 's',
+  'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
+  '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v',
+  'b', 'n', 'm', ',', '.', '/', '\0', '*',
+  '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0',
+  '\0', '\0', '\0', '\0', '\0', '\0', '\0', GRUB_TERM_HOME,
+  GRUB_TERM_UP, GRUB_TERM_NPAGE, '-', GRUB_TERM_LEFT, '\0', GRUB_TERM_RIGHT, '+', GRUB_TERM_END,
+  GRUB_TERM_DOWN, GRUB_TERM_PPAGE, '\0', GRUB_TERM_DC, '\0', '\0', '\0', '\0',
+  '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+  '\0', '\0', '\0', '\0', '\0', OLPC_UP, OLPC_DOWN, OLPC_LEFT,
+  OLPC_RIGHT
+};
+
+static char keyboard_map_shift[128] =
+{
+  '\0', '\0', '!', '@', '#', '$', '%', '^',
+  '&', '*', '(', ')', '_', '+', '\0', '\0',
+  'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
+  'O', 'P', '{', '}', '\n', '\0', 'A', 'S',
+  'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
+  '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V',
+  'B', 'N', 'M', '<', '>', '?'
+};
+
+static grub_uint8_t grub_keyboard_controller_orig;
+
+static void
+grub_keyboard_controller_write (grub_uint8_t c)
+{
+  while (! KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS)));
+  grub_outb (KEYBOARD_COMMAND_WRITE, KEYBOARD_REG_STATUS);
+  grub_outb (c, KEYBOARD_REG_DATA);
+}
+
+static grub_uint8_t
+grub_keyboard_controller_read (void)
+{
+  while (! KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS)));
+  grub_outb (KEYBOARD_COMMAND_READ, KEYBOARD_REG_STATUS);
+  return grub_inb (KEYBOARD_REG_DATA);
+}
+
+/* FIXME: This should become an interrupt service routine.  For now
+   it's just used to catch events from control keys.  */
+static void
+grub_keyboard_isr (char key)
+{
+  char is_make = KEYBOARD_ISMAKE (key);
+  key = KEYBOARD_SCANCODE (key);
+  if (is_make)
+    switch (key)
+      {
+       case SHIFT_L:
+         at_keyboard_status |= KEYBOARD_STATUS_SHIFT_L;
+         break;
+       case SHIFT_R:
+         at_keyboard_status |= KEYBOARD_STATUS_SHIFT_R;
+         break;
+       case CTRL:
+         at_keyboard_status |= KEYBOARD_STATUS_CTRL_L;
+         break;
+       case ALT:
+         at_keyboard_status |= KEYBOARD_STATUS_ALT_L;
+         break;
+       default:
+         /* Skip grub_dprintf.  */
+         return;
+      }
+  else
+    switch (key)
+      {
+       case SHIFT_L:
+         at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_L;
+         break;
+       case SHIFT_R:
+         at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_R;
+         break;
+       case CTRL:
+         at_keyboard_status &= ~KEYBOARD_STATUS_CTRL_L;
+         break;
+       case ALT:
+         at_keyboard_status &= ~KEYBOARD_STATUS_ALT_L;
+         break;
+       default:
+         /* Skip grub_dprintf.  */
+         return;
+      }
+#ifdef DEBUG_AT_KEYBOARD
+  grub_dprintf ("atkeyb", "Control key 0x%0x was %s\n", key, is_make ? "pressed" : "unpressed");
+#endif
+}
+
+/* If there is a raw key pending, return it; otherwise return -1.  */
+static int
+grub_keyboard_getkey (void)
+{
+  grub_uint8_t key;
+  if (KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)))
+    return -1;
+  key = grub_inb (KEYBOARD_REG_DATA);
+  /* FIXME */ grub_keyboard_isr (key);
+  if (! KEYBOARD_ISMAKE (key))
+    return -1;
+  return (KEYBOARD_SCANCODE (key));
+}
+
+/* If there is a character pending, return it; otherwise return -1.  */
+static int
+grub_at_keyboard_checkkey (void)
+{
+  int code, key;
+  code = grub_keyboard_getkey ();
+  if (code == -1)
+    return -1;
+#ifdef DEBUG_AT_KEYBOARD
+  grub_dprintf ("atkeyb", "Detected key 0x%x\n", key);
+#endif
+  switch (code)
+    {
+      case CAPS_LOCK:
+       at_keyboard_status ^= KEYBOARD_STATUS_CAPS_LOCK;
+       /* Caps lock sends scan code twice.  Get the second one and discard it.  */
+       while (grub_keyboard_getkey () == -1);
+#ifdef DEBUG_AT_KEYBOARD
+       grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK));
+#endif
+       key = -1;
+       break;
+      default:
+       if (at_keyboard_status & (KEYBOARD_STATUS_CTRL_L | KEYBOARD_STATUS_CTRL_R))
+         key = keyboard_map[code] - 'a' + 1;
+       else if ((at_keyboard_status & (KEYBOARD_STATUS_SHIFT_L | KEYBOARD_STATUS_SHIFT_R))
+           && keyboard_map_shift[code])
+         key = keyboard_map_shift[code];
+       else
+         key = keyboard_map[code];
+
+       if (key == 0)
+         grub_dprintf ("atkeyb", "Unknown key 0x%x detected\n", code);
+
+       if (at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK)
+         {
+           if ((key >= 'a') && (key <= 'z'))
+             key += 'A' - 'a';
+           else if ((key >= 'A') && (key <= 'Z'))
+             key += 'a' - 'A';
+         }
+    }
+  return (int) key;
+}
+
+static int
+grub_at_keyboard_getkey (void)
+{
+  int key;
+  do
+    {
+      key = grub_at_keyboard_checkkey ();
+    } while (key == -1);
+  return key;
+}
+
+static grub_err_t
+grub_keyboard_controller_init (void)
+{
+  grub_keyboard_controller_orig = grub_keyboard_controller_read ();
+  grub_keyboard_controller_write (grub_keyboard_controller_orig | KEYBOARD_SCANCODE_SET1);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_keyboard_controller_fini (void)
+{
+  grub_keyboard_controller_write (grub_keyboard_controller_orig);
+  return GRUB_ERR_NONE;
+}
+
+static struct grub_term_input grub_at_keyboard_term =
+  {
+    .name = "at_keyboard",
+    .init = grub_keyboard_controller_init,
+    .fini = grub_keyboard_controller_fini,
+    .checkkey = grub_at_keyboard_checkkey,
+    .getkey = grub_at_keyboard_getkey,
+  };
+
+GRUB_MOD_INIT(at_keyboard)
+{
+  grub_term_register_input (&grub_at_keyboard_term);
+}
+
+GRUB_MOD_FINI(at_keyboard)
+{
+  grub_term_unregister_input (&grub_at_keyboard_term);
+}
diff --git a/term/i386/pc/console.c b/term/i386/pc/console.c
new file mode 100644 (file)
index 0000000..6c6be46
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2005,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/>.
+ */
+
+#include <grub/machine/console.h>
+#include <grub/term.h>
+#include <grub/types.h>
+
+static struct grub_term_input grub_console_term_input =
+  {
+    .name = "console",
+    .checkkey = grub_console_checkkey,
+    .getkey = grub_console_getkey,
+  };
+
+static struct grub_term_output grub_console_term_output =
+  {
+    .name = "console",
+    .putchar = grub_console_putchar,
+    .getcharwidth = grub_console_getcharwidth,
+    .getwh = grub_console_getwh,
+    .getxy = grub_console_getxy,
+    .gotoxy = grub_console_gotoxy,
+    .cls = grub_console_cls,
+    .setcolorstate = grub_console_setcolorstate,
+    .setcolor = grub_console_setcolor,
+    .getcolor = grub_console_getcolor,
+    .setcursor = grub_console_setcursor,
+    .flags = 0,
+  };
+
+void
+grub_console_init (void)
+{
+  grub_term_register_output (&grub_console_term_output);
+  grub_term_register_input (&grub_console_term_input);
+}
+
+void
+grub_console_fini (void)
+{
+  /* This is to make sure the console is restored to text mode before
+     we boot.  */
+  grub_term_set_current_output (&grub_console_term_output);
+
+  grub_term_unregister_input (&grub_console_term_input);
+  grub_term_unregister_output (&grub_console_term_output);
+}
diff --git a/term/i386/pc/serial.c b/term/i386/pc/serial.c
new file mode 100644 (file)
index 0000000..03a46ba
--- /dev/null
@@ -0,0 +1,627 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2000,2001,2002,2003,2004,2005,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/>.
+ */
+
+#include <grub/machine/machine.h>
+#include <grub/machine/serial.h>
+#include <grub/machine/console.h>
+#include <grub/term.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/arg.h>
+#include <grub/terminfo.h>
+#include <grub/cpu/io.h>
+
+#define TEXT_WIDTH     80
+#define TEXT_HEIGHT    25
+
+static unsigned int xpos, ypos;
+static unsigned int keep_track = 1;
+static unsigned int registered = 0;
+
+/* An input buffer.  */
+static char input_buf[8];
+static unsigned int npending = 0;
+
+/* Argument options.  */
+static const struct grub_arg_option options[] =
+{
+  {"unit",   'u', 0, "Set the serial unit",             0, ARG_TYPE_INT},
+  {"port",   'p', 0, "Set the serial port address",     0, ARG_TYPE_STRING},
+  {"speed",  's', 0, "Set the serial port speed",       0, ARG_TYPE_INT},
+  {"word",   'w', 0, "Set the serial port word length", 0, ARG_TYPE_INT},
+  {"parity", 'r', 0, "Set the serial port parity",      0, ARG_TYPE_STRING},
+  {"stop",   't', 0, "Set the serial port stop bits",   0, ARG_TYPE_INT},
+  {0, 0, 0, 0, 0, 0}
+};
+
+/* Serial port settings.  */
+struct serial_port
+{
+  unsigned short port;
+  unsigned short divisor;
+  unsigned short word_len;
+  unsigned int   parity;
+  unsigned short stop_bits;
+};
+
+/* Serial port settings.  */
+static struct serial_port serial_settings;
+
+#ifdef GRUB_MACHINE_PCBIOS
+/* The BIOS data area.  */
+static const unsigned short *serial_hw_io_addr = (const unsigned short *) 0x0400;
+#define GRUB_SERIAL_PORT_NUM 4
+#else
+static const unsigned short serial_hw_io_addr[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
+#define GRUB_SERIAL_PORT_NUM (sizeof(serial_hw_io_addr)/sizeof(serial_hw_io_addr[0]))
+#endif
+
+/* Return the port number for the UNITth serial device.  */
+static inline unsigned short
+serial_hw_get_port (const unsigned int unit)
+{
+  if (unit < GRUB_SERIAL_PORT_NUM)
+    return serial_hw_io_addr[unit];
+  else
+    return 0;
+}
+
+/* Fetch a key.  */
+static int
+serial_hw_fetch (void)
+{
+  if (grub_inb (serial_settings.port + UART_LSR) & UART_DATA_READY)
+    return grub_inb (serial_settings.port + UART_RX);
+
+  return -1;
+}
+
+/* Put a character.  */
+static void
+serial_hw_put (const int c)
+{
+  unsigned int timeout = 100000;
+
+  /* Wait until the transmitter holding register is empty.  */
+  while ((grub_inb (serial_settings.port + UART_LSR) & UART_EMPTY_TRANSMITTER) == 0)
+    {
+      if (--timeout == 0)
+        /* There is something wrong. But what can I do?  */
+        return;
+    }
+
+  grub_outb (c, serial_settings.port + UART_TX);
+}
+
+static void
+serial_translate_key_sequence (void)
+{
+  static struct
+  {
+    char key;
+    char ascii;
+  }
+  three_code_table[] =
+    {
+      {'A', 16},
+      {'B', 14},
+      {'C', 6},
+      {'D', 2},
+      {'F', 5},
+      {'H', 1},
+      {'4', 4}
+    };
+  
+  static struct
+  {
+      short key;
+      char ascii;
+  }
+  four_code_table[] =
+    {
+      {('1' | ('~' << 8)), 1},
+      {('3' | ('~' << 8)), 4},
+      {('5' | ('~' << 8)), 7},
+      {('6' | ('~' << 8)), 3}
+    };
+
+  /* The buffer must start with "ESC [".  */
+  if (*((unsigned short *) input_buf) != ('\e' | ('[' << 8)))
+    return;
+
+  if (npending >= 3)
+    {
+      unsigned int i;
+      
+      for (i = 0;
+          i < sizeof (three_code_table) / sizeof (three_code_table[0]);
+          i++)
+       if (three_code_table[i].key == input_buf[2])
+         {
+           input_buf[0] = three_code_table[i].ascii;
+           npending -= 2;
+           grub_memmove (input_buf + 1, input_buf + 3, npending - 1);
+           return;
+         }
+    }
+
+  if (npending >= 4)
+    {
+      unsigned int i;
+      short key = *((short *) (input_buf + 2));
+      
+      for (i = 0;
+          i < sizeof (four_code_table) / sizeof (four_code_table[0]);
+          i++)
+       if (four_code_table[i].key == key)
+         {
+           input_buf[0] = four_code_table[i].ascii;
+           npending -= 3;
+           grub_memmove (input_buf + 1, input_buf + 4, npending - 1);
+           return;
+         }
+    }
+}
+
+static int
+fill_input_buf (const int nowait)
+{
+  int i;
+
+  for (i = 0; i < 10000 && npending < sizeof (input_buf); i++)
+    {
+      int c;
+      
+      c = serial_hw_fetch ();
+      if (c >= 0)
+       {
+         input_buf[npending++] = c;
+         
+         /* Reset the counter to zero, to wait for the same interval.  */
+         i = 0;
+       }
+      
+      if (nowait)
+       break;
+    }
+
+  /* Translate some key sequences.  */
+  serial_translate_key_sequence ();
+
+  return npending;
+}
+
+/* Convert speed to divisor.  */
+static unsigned short
+serial_get_divisor (unsigned int speed)
+{
+  unsigned int i;
+
+  /* The structure for speed vs. divisor.  */
+  struct divisor
+  {
+    unsigned int speed;
+    unsigned short div;
+  };
+
+  /* The table which lists common configurations.  */
+  /* 1843200 / (speed * 16)  */
+  static struct divisor divisor_tab[] =
+    {
+      { 2400,   0x0030 },
+      { 4800,   0x0018 },
+      { 9600,   0x000C },
+      { 19200,  0x0006 },
+      { 38400,  0x0003 },
+      { 57600,  0x0002 },
+      { 115200, 0x0001 }
+    };
+
+  /* Set the baud rate.  */
+  for (i = 0; i < sizeof (divisor_tab) / sizeof (divisor_tab[0]); i++)
+    if (divisor_tab[i].speed == speed)
+      return divisor_tab[i].div;
+  return 0;
+}
+
+/* The serial version of checkkey.  */
+static int
+grub_serial_checkkey (void)
+{
+  if (fill_input_buf (1))
+    return input_buf[0];
+  else
+    return -1;
+}
+
+/* The serial version of getkey.  */
+static int
+grub_serial_getkey (void)
+{
+  int c;
+
+  while (! fill_input_buf (0))
+    ;
+
+  c = input_buf[0];
+  grub_memmove (input_buf, input_buf + 1, --npending);
+
+  return c;
+}
+
+/* Initialize a serial device. PORT is the port number for a serial device.
+   SPEED is a DTE-DTE speed which must be one of these: 2400, 4800, 9600,
+   19200, 38400, 57600 and 115200. WORD_LEN is the word length to be used
+   for the device. Likewise, PARITY is the type of the parity and
+   STOP_BIT_LEN is the length of the stop bit. The possible values for
+   WORD_LEN, PARITY and STOP_BIT_LEN are defined in the header file as
+   macros.  */
+static grub_err_t
+serial_hw_init (void)
+{
+  unsigned char status = 0;
+
+  /* Turn off the interrupt.  */
+  grub_outb (0, serial_settings.port + UART_IER);
+
+  /* Set DLAB.  */
+  grub_outb (UART_DLAB, serial_settings.port + UART_LCR);
+
+  /* Set the baud rate.  */
+  grub_outb (serial_settings.divisor & 0xFF, serial_settings.port + UART_DLL);
+  grub_outb (serial_settings.divisor >> 8, serial_settings.port + UART_DLH);
+
+  /* Set the line status.  */
+  status |= (serial_settings.parity
+            | serial_settings.word_len
+            | serial_settings.stop_bits);
+  grub_outb (status, serial_settings.port + UART_LCR);
+
+  /* Enable the FIFO.  */
+  grub_outb (UART_ENABLE_FIFO, serial_settings.port + UART_FCR);
+
+  /* Turn on DTR, RTS, and OUT2.  */
+  grub_outb (UART_ENABLE_MODEM, serial_settings.port + UART_MCR);
+
+  /* Drain the input buffer.  */
+  while (grub_serial_checkkey () != -1)
+    (void) grub_serial_getkey ();
+
+  /*  FIXME: should check if the serial terminal was found.  */
+
+  return GRUB_ERR_NONE;
+}
+
+/* The serial version of putchar.  */
+static void
+grub_serial_putchar (grub_uint32_t c)
+{
+  /* Keep track of the cursor.  */
+  if (keep_track)
+    {
+      /* The serial terminal does not have VGA fonts.  */
+      if (c > 0x7F)
+       {
+         /* Better than nothing.  */
+         switch (c)
+           {
+           case GRUB_TERM_DISP_LEFT:
+             c = '<';
+             break;
+             
+           case GRUB_TERM_DISP_UP:
+             c = '^';
+             break;
+             
+           case GRUB_TERM_DISP_RIGHT:
+             c = '>';
+             break;
+             
+           case GRUB_TERM_DISP_DOWN:
+             c = 'v';
+             break;
+             
+           case GRUB_TERM_DISP_HLINE:
+             c = '-';
+             break;
+             
+           case GRUB_TERM_DISP_VLINE:
+             c = '|';
+             break;
+             
+           case GRUB_TERM_DISP_UL:
+           case GRUB_TERM_DISP_UR:
+           case GRUB_TERM_DISP_LL:
+           case GRUB_TERM_DISP_LR:
+             c = '+';
+             break;
+             
+           default:
+             c = '?';
+             break;
+           }
+       }
+      
+      switch (c)
+       {
+       case '\a':
+         break;
+         
+       case '\b':
+       case 127:
+         if (xpos > 0)
+           xpos--;
+         break;
+         
+       case '\n':
+         if (ypos < TEXT_HEIGHT)
+           ypos++;
+         break;
+         
+       case '\r':
+         xpos = 0;
+         break;
+         
+       default:
+         if (xpos >= TEXT_WIDTH)
+           {
+             grub_putchar ('\r');
+             grub_putchar ('\n');
+           }
+         xpos++;
+         break;
+       }
+    }
+  
+  serial_hw_put (c);
+}
+
+static grub_ssize_t
+grub_serial_getcharwidth (grub_uint32_t c __attribute__ ((unused)))
+{
+  return 1;
+}
+
+static grub_uint16_t
+grub_serial_getwh (void)
+{
+  return (TEXT_WIDTH << 8) | TEXT_HEIGHT;
+}
+
+static grub_uint16_t
+grub_serial_getxy (void)
+{
+  return ((xpos << 8) | ypos);
+}
+
+static void
+grub_serial_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+  if (x > TEXT_WIDTH || y > TEXT_HEIGHT)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)", x, y);
+    }
+  else
+    {
+      keep_track = 0;
+      grub_terminfo_gotoxy (x, y);
+      keep_track = 1;
+      
+      xpos = x;
+      ypos = y;
+    }
+}
+
+static void
+grub_serial_cls (void)
+{
+  keep_track = 0;
+  grub_terminfo_cls ();
+  keep_track = 1;
+
+  xpos = ypos = 0;
+}
+
+static void
+grub_serial_setcolorstate (const grub_term_color_state state)
+{
+  keep_track = 0;
+  switch (state)
+    {
+    case GRUB_TERM_COLOR_STANDARD:
+    case GRUB_TERM_COLOR_NORMAL:
+      grub_terminfo_reverse_video_off ();
+      break;
+    case GRUB_TERM_COLOR_HIGHLIGHT:
+      grub_terminfo_reverse_video_on ();
+      break;
+    default:
+      break;
+    }
+  keep_track = 1;
+}
+
+static void
+grub_serial_setcursor (const int on)
+{
+  if (on)
+    grub_terminfo_cursor_on ();
+  else
+    grub_terminfo_cursor_off ();
+}
+
+static struct grub_term_input grub_serial_term_input =
+{
+  .name = "serial",
+  .checkkey = grub_serial_checkkey,
+  .getkey = grub_serial_getkey,
+};
+
+static struct grub_term_output grub_serial_term_output =
+{
+  .name = "serial",
+  .putchar = grub_serial_putchar,
+  .getcharwidth = grub_serial_getcharwidth,
+  .getwh = grub_serial_getwh,
+  .getxy = grub_serial_getxy,
+  .gotoxy = grub_serial_gotoxy,
+  .cls = grub_serial_cls,
+  .setcolorstate = grub_serial_setcolorstate,
+  .setcursor = grub_serial_setcursor,
+  .flags = 0,
+};
+
+\f
+
+static grub_err_t
+grub_cmd_serial (struct grub_arg_list *state,
+                 int argc __attribute__ ((unused)),
+                char **args __attribute__ ((unused)))
+{
+  struct serial_port backup_settings = serial_settings;
+  grub_err_t hwiniterr;
+
+  if (state[0].set)
+    {
+      unsigned int unit;
+
+      unit = grub_strtoul (state[0].arg, 0, 0);
+      serial_settings.port = serial_hw_get_port (unit);
+      if (!serial_settings.port)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad unit number.");
+    }
+  
+  if (state[1].set)
+    serial_settings.port = (unsigned short) grub_strtoul (state[1].arg, 0, 0);
+  
+  if (state[2].set)
+    {
+      unsigned long speed;
+
+      speed = grub_strtoul (state[2].arg, 0, 0);
+      serial_settings.divisor = serial_get_divisor ((unsigned int) speed);
+      if (serial_settings.divisor == 0)
+       {
+         serial_settings = backup_settings;
+         return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed");
+       }
+    }
+  
+  if (state[3].set)
+    {
+      if (! grub_strcmp (state[3].arg, "5"))
+       serial_settings.word_len = UART_5BITS_WORD;
+      else if (! grub_strcmp (state[3].arg, "6"))
+       serial_settings.word_len = UART_6BITS_WORD;
+      else if (! grub_strcmp (state[3].arg, "7"))
+       serial_settings.word_len = UART_7BITS_WORD;
+      else if (! grub_strcmp (state[3].arg, "8"))
+       serial_settings.word_len = UART_8BITS_WORD;
+      else
+       {
+         serial_settings = backup_settings;
+         return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad word length");
+       }
+    }
+  
+  if (state[4].set)
+    {
+      if (! grub_strcmp (state[4].arg, "no"))
+       serial_settings.parity = UART_NO_PARITY;
+      else if (! grub_strcmp (state[4].arg, "odd"))
+       serial_settings.parity = UART_ODD_PARITY;
+      else if (! grub_strcmp (state[4].arg, "even"))
+       serial_settings.parity = UART_EVEN_PARITY;
+      else
+       {
+         serial_settings = backup_settings;
+         return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad parity");
+       }
+    }
+  
+  if (state[5].set)
+    {
+      if (! grub_strcmp (state[5].arg, "1"))
+       serial_settings.stop_bits = UART_1_STOP_BIT;
+      else if (! grub_strcmp (state[5].arg, "2"))
+       serial_settings.stop_bits = UART_2_STOP_BITS;
+      else
+       {
+         serial_settings = backup_settings;
+         return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad number of stop bits");
+       }
+    }
+
+  /* Initialize with new settings.  */
+  hwiniterr = serial_hw_init ();
+  
+  if (hwiniterr == GRUB_ERR_NONE)
+    {
+      /* Register terminal if not yet registered.  */
+      if (registered == 0)
+       {
+         grub_term_register_input (&grub_serial_term_input);
+         grub_term_register_output (&grub_serial_term_output);
+         registered = 1;
+       }
+    }
+  else
+    {
+      /* Initialization with new settings failed.  */
+      if (registered == 1)
+       {
+         /* If the terminal is registered, attempt to restore previous
+            settings.  */
+         serial_settings = backup_settings;
+         if (serial_hw_init () != GRUB_ERR_NONE)
+           {
+             /* If unable to restore settings, unregister terminal.  */
+             grub_term_unregister_input (&grub_serial_term_input);
+             grub_term_unregister_output (&grub_serial_term_output);
+             registered = 0;
+           }
+       }
+    }
+  
+  return hwiniterr;
+}
+
+GRUB_MOD_INIT(serial)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("serial", grub_cmd_serial, GRUB_COMMAND_FLAG_BOTH,
+                         "serial [OPTIONS...]", "Configure serial port.", options);
+  /* Set default settings.  */
+  serial_settings.port      = serial_hw_get_port (0);
+  serial_settings.divisor   = serial_get_divisor (9600);
+  serial_settings.word_len  = UART_8BITS_WORD;
+  serial_settings.parity    = UART_NO_PARITY;
+  serial_settings.stop_bits = UART_1_STOP_BIT;
+}
+
+GRUB_MOD_FINI(serial)
+{
+  grub_unregister_command ("serial");
+  if (registered == 1)         /* Unregister terminal only if registered. */
+    {
+      grub_term_unregister_input (&grub_serial_term_input);
+      grub_term_unregister_output (&grub_serial_term_output);
+    }
+}
diff --git a/term/i386/pc/vesafb.c b/term/i386/pc/vesafb.c
new file mode 100644 (file)
index 0000000..7305954
--- /dev/null
@@ -0,0 +1,609 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+// TODO: Deprecated and broken. Scheduled for removal as there is VBE driver in Video subsystem.
+
+#include <grub/machine/memory.h>
+#include <grub/machine/vga.h>
+#include <grub/machine/vbe.h>
+#include <grub/machine/console.h>
+#include <grub/term.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/font.h>
+#include <grub/arg.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+
+#define DEFAULT_CHAR_WIDTH  8
+#define DEFAULT_CHAR_HEIGHT 16
+
+#define DEFAULT_FG_COLOR    0xa
+#define DEFAULT_BG_COLOR    0x0
+
+struct grub_colored_char
+{
+  /* An Unicode codepoint.  */
+  grub_uint32_t code;
+
+  /* Color indexes.  */
+  unsigned char fg_color;
+  unsigned char bg_color;
+
+  /* The width of this character minus one.  */
+  unsigned char width;
+
+  /* The column index of this character.  */
+  unsigned char index;
+};
+
+struct grub_virtual_screen
+{
+  /* Dimensions of the virtual screen.  */
+  grub_uint32_t width;
+  grub_uint32_t height;
+
+  /* Offset in the display.  */
+  grub_uint32_t offset_x;
+  grub_uint32_t offset_y;
+
+  /* TTY Character sizes.  */
+  grub_uint32_t char_width;
+  grub_uint32_t char_height;
+
+  /* Virtual screen TTY size.  */
+  grub_uint32_t columns;
+  grub_uint32_t rows;
+
+  /* Current cursor details.  */
+  grub_uint32_t cursor_x;
+  grub_uint32_t cursor_y;
+  grub_uint8_t cursor_state;
+  grub_uint8_t fg_color;
+  grub_uint8_t bg_color;
+
+  /* Text buffer for virtual screen. Contains (columns * rows) number
+     of entries.  */
+  struct grub_colored_char *text_buffer;
+};
+
+/* Make seure text buffer is not marked as allocated.  */
+static struct grub_virtual_screen virtual_screen =
+  {
+    .text_buffer = 0
+  };
+
+static grub_dl_t my_mod;
+static unsigned char *vga_font = 0;
+static grub_uint32_t old_mode = 0;
+
+static struct grub_vbe_mode_info_block mode_info;
+static grub_uint8_t *framebuffer = 0;
+static grub_uint32_t bytes_per_scan_line = 0;
+
+static void
+grub_virtual_screen_free (void)
+{
+  /* If virtual screen has been allocated, free it.  */
+  if (virtual_screen.text_buffer != 0)
+    grub_free (virtual_screen.text_buffer);
+
+  /* Reset virtual screen data.  */
+  grub_memset (&virtual_screen, 0, sizeof (virtual_screen));
+}
+
+static grub_err_t
+grub_virtual_screen_setup (grub_uint32_t width,
+                          grub_uint32_t height)
+{
+  /* Free old virtual screen.  */
+  grub_virtual_screen_free ();
+
+  /* Initialize with default data.  */
+  virtual_screen.width = width;
+  virtual_screen.height = height;
+  virtual_screen.offset_x = 0;
+  virtual_screen.offset_y = 0;
+  virtual_screen.char_width = DEFAULT_CHAR_WIDTH;
+  virtual_screen.char_height = DEFAULT_CHAR_HEIGHT;
+  virtual_screen.cursor_x = 0;
+  virtual_screen.cursor_y = 0;
+  virtual_screen.cursor_state = 1;
+  virtual_screen.fg_color = DEFAULT_FG_COLOR;
+  virtual_screen.bg_color = DEFAULT_BG_COLOR;
+
+  /* Calculate size of text buffer.  */
+  virtual_screen.columns = virtual_screen.width / virtual_screen.char_width;
+  virtual_screen.rows = virtual_screen.height / virtual_screen.char_height;
+
+  /* Allocate memory for text buffer.  */
+  virtual_screen.text_buffer =
+    (struct grub_colored_char *) grub_malloc (virtual_screen.columns
+                                             * virtual_screen.rows
+                                             * sizeof (*virtual_screen.text_buffer));
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_vesafb_mod_init (void)
+{
+  grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE;
+  struct grub_vbe_info_block controller_info;
+  char *modevar;
+
+  /* Use fonts from VGA bios.  */
+  vga_font = grub_vga_get_font ();
+
+  /* Check if we have VESA BIOS installed.  */
+  if (grub_vbe_probe (&controller_info) != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* Check existence of vbe_mode environment variable.  */
+  modevar = grub_env_get ("vbe_mode");
+
+  if (modevar != 0)
+    {
+      unsigned long value;
+
+      value = grub_strtoul (modevar, 0, 0);
+      if (grub_errno == GRUB_ERR_NONE)
+       use_mode = value;
+    }
+
+  /* Store initial video mode.  */
+  if (grub_vbe_get_video_mode (&old_mode) != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* Setup desired graphics mode.  */
+  if (grub_vbe_set_video_mode (use_mode, &mode_info) != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* Determine framebuffer and bytes per scan line.  */
+  framebuffer = (grub_uint8_t *) mode_info.phys_base_addr;
+
+  if (controller_info.version >= 0x300)
+    bytes_per_scan_line = mode_info.lin_bytes_per_scan_line;
+  else
+    bytes_per_scan_line = mode_info.bytes_per_scan_line;
+
+  /* Create virtual screen.  */
+  if (grub_virtual_screen_setup (mode_info.x_resolution,
+                                mode_info.y_resolution) != GRUB_ERR_NONE)
+    {
+      grub_vbe_set_video_mode (old_mode, 0);
+      return grub_errno;
+    }
+
+  /* Make sure frame buffer is black.  */
+  grub_memset (framebuffer,
+              0,
+              bytes_per_scan_line * mode_info.y_resolution);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_vesafb_mod_fini (void)
+{
+  grub_virtual_screen_free ();
+
+  grub_vbe_set_video_mode (old_mode, 0);
+
+  return GRUB_ERR_NONE;
+}
+
+static int
+grub_virtual_screen_get_glyph (grub_uint32_t code,
+                              unsigned char bitmap[32],
+                              unsigned *width)
+{
+  if (code > 0x7f)
+    {
+      /* Map some unicode characters to the VGA font, if possible.  */
+      switch (code)
+       {
+       case 0x2190:    /* left arrow */
+         code = 0x1b;
+         break;
+       case 0x2191:    /* up arrow */
+         code = 0x18;
+         break;
+       case 0x2192:    /* right arrow */
+         code = 0x1a;
+         break;
+       case 0x2193:    /* down arrow */
+         code = 0x19;
+         break;
+       case 0x2501:    /* horizontal line */
+         code = 0xc4;
+         break;
+       case 0x2503:    /* vertical line */
+         code = 0xb3;
+         break;
+       case 0x250F:    /* upper-left corner */
+         code = 0xda;
+         break;
+       case 0x2513:    /* upper-right corner */
+         code = 0xbf;
+         break;
+       case 0x2517:    /* lower-left corner */
+         code = 0xc0;
+         break;
+       case 0x251B:    /* lower-right corner */
+         code = 0xd9;
+         break;
+
+       default:
+         return grub_font_get_glyph_any (code, bitmap, width);
+       }
+    }
+
+  /* TODO This is wrong for the new font module.  Should it be fixed?  */
+  if (bitmap)
+    grub_memcpy (bitmap,
+                vga_font + code * virtual_screen.char_height,
+                virtual_screen.char_height);
+  *width = 1;
+  return 1;
+}
+
+static void
+grub_virtual_screen_invalidate_char (struct grub_colored_char *p)
+{
+  p->code = 0xFFFF;
+  
+  if (p->width)
+    {
+      struct grub_colored_char *q;
+
+      for (q = p + 1; q <= p + p->width; q++)
+       {
+         q->code = 0xFFFF;
+         q->width = 0;
+         q->index = 0;
+       }
+    }
+
+  p->width = 0;
+}
+
+static void
+write_char (void)
+{
+  struct grub_colored_char *p;
+  unsigned char bitmap[32];
+  unsigned width;
+  unsigned y;
+  unsigned offset;
+
+  p = (virtual_screen.text_buffer
+       + virtual_screen.cursor_x
+       + (virtual_screen.cursor_y * virtual_screen.columns));
+
+  p -= p->index;
+
+  if (! grub_virtual_screen_get_glyph (p->code, bitmap, &width))
+    {
+      grub_virtual_screen_invalidate_char (p);
+      width = 0;
+    }
+
+  for (y = 0, offset = 0;
+       y < virtual_screen.char_height;
+       y++, offset++)
+    {
+      unsigned i;
+
+      for (i = 0;
+          (i < width * virtual_screen.char_width) && (offset < 32);
+          i++)
+       {
+         unsigned char color;
+
+         if (bitmap[offset] & (1 << (8-i)))
+           {
+             color = p->fg_color;
+           }
+         else
+           {
+             color = p->bg_color;
+           }
+
+          grub_vbe_set_pixel_index(i + (virtual_screen.cursor_x
+                                        * virtual_screen.char_width),
+                                   y + (virtual_screen.cursor_y
+                                        * virtual_screen.char_height),
+                                   color);
+       }
+    }
+}
+
+static void
+write_cursor (void)
+{
+  grub_uint32_t x;
+  grub_uint32_t y;
+
+  for (y = ((virtual_screen.cursor_y + 1) * virtual_screen.char_height) - 3;
+       y < ((virtual_screen.cursor_y + 1) * virtual_screen.char_height) - 1;
+       y++)
+    {
+      for (x = virtual_screen.cursor_x * virtual_screen.char_width;
+          x < (virtual_screen.cursor_x + 1) * virtual_screen.char_width;
+          x++)
+       {
+         grub_vbe_set_pixel_index(x, y, 10);
+       }
+    }
+}
+
+static void
+scroll_up (void)
+{
+  grub_uint32_t i;
+
+  /* Scroll text buffer with one line to up.  */
+  grub_memmove (virtual_screen.text_buffer,
+               virtual_screen.text_buffer + virtual_screen.columns,
+                sizeof (*virtual_screen.text_buffer)
+                * virtual_screen.columns
+                * (virtual_screen.rows - 1));
+
+  /* Clear last line in text buffer.  */
+  for (i = virtual_screen.columns * (virtual_screen.rows - 1);
+       i < virtual_screen.columns * virtual_screen.rows;
+       i++)
+    {
+      virtual_screen.text_buffer[i].code = ' ';
+      virtual_screen.text_buffer[i].fg_color = 0;
+      virtual_screen.text_buffer[i].bg_color = 0;
+      virtual_screen.text_buffer[i].width = 0;
+      virtual_screen.text_buffer[i].index = 0;
+    }
+
+  /* Scroll framebuffer with one line to up.  */
+  grub_memmove (framebuffer,
+                framebuffer
+                + bytes_per_scan_line * virtual_screen.char_height,
+                bytes_per_scan_line
+                * (mode_info.y_resolution - virtual_screen.char_height));
+
+  /* Clear last line in framebuffer.  */
+  grub_memset (framebuffer
+               + (bytes_per_scan_line
+                  * (mode_info.y_resolution - virtual_screen.char_height)),
+               0,
+               bytes_per_scan_line * virtual_screen.char_height);
+}
+
+static void
+grub_vesafb_putchar (grub_uint32_t c)
+{
+  if (c == '\a')
+    /* FIXME */
+    return;
+
+  if (c == '\b' || c == '\n' || c == '\r')
+    {
+      /* Erase current cursor, if any.  */
+      if (virtual_screen.cursor_state)
+       write_char ();
+
+      switch (c)
+       {
+       case '\b':
+         if (virtual_screen.cursor_x > 0)
+           virtual_screen.cursor_x--;
+         break;
+         
+       case '\n':
+         if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
+           scroll_up ();
+         else
+           virtual_screen.cursor_y++;
+         break;
+         
+       case '\r':
+         virtual_screen.cursor_x = 0;
+         break;
+       }
+
+      if (virtual_screen.cursor_state)
+       write_cursor ();
+    }
+  else
+    {
+      unsigned width;
+      struct grub_colored_char *p;
+      
+      grub_virtual_screen_get_glyph (c, 0, &width);
+
+      if (virtual_screen.cursor_x + width > virtual_screen.columns)
+       grub_putchar ('\n');
+
+      p = (virtual_screen.text_buffer +
+          virtual_screen.cursor_x +
+          virtual_screen.cursor_y * virtual_screen.columns);
+      p->code = c;
+      p->fg_color = virtual_screen.fg_color;
+      p->bg_color = virtual_screen.bg_color;
+      p->width = width - 1;
+      p->index = 0;
+
+      if (width > 1)
+       {
+         unsigned i;
+
+         for (i = 1; i < width; i++)
+           {
+             p[i].code = ' ';
+             p[i].width = width - 1;
+             p[i].index = i;
+           }
+       }
+         
+      write_char ();
+  
+      virtual_screen.cursor_x += width;
+      if (virtual_screen.cursor_x >= virtual_screen.columns)
+       {
+         virtual_screen.cursor_x = 0;
+         
+         if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
+           scroll_up ();
+         else
+           virtual_screen.cursor_y++;
+       }
+
+      if (virtual_screen.cursor_state)
+       write_cursor ();
+    }
+}
+
+static grub_ssize_t
+grub_vesafb_getcharwidth (grub_uint32_t c)
+{
+  unsigned width;
+  
+  if (! grub_virtual_screen_get_glyph (c, 0, &width))
+    return 0;
+
+  return width;
+}
+
+static grub_uint16_t
+grub_virtual_screen_getwh (void)
+{
+  return (virtual_screen.columns << 8) | virtual_screen.rows;
+}
+
+static grub_uint16_t
+grub_virtual_screen_getxy (void)
+{
+  return ((virtual_screen.cursor_x << 8) | virtual_screen.cursor_y);
+}
+
+static void
+grub_vesafb_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+  if (x >= virtual_screen.columns || y >= virtual_screen.rows)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)",
+                 (unsigned) x, (unsigned) y);
+      return;
+    }
+
+  if (virtual_screen.cursor_state)
+    write_char ();
+
+  virtual_screen.cursor_x = x;
+  virtual_screen.cursor_y = y;
+
+  if (virtual_screen.cursor_state)
+    write_cursor ();
+}
+
+static void
+grub_virtual_screen_cls (void)
+{
+  grub_uint32_t i;
+
+  for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++)
+    {
+      virtual_screen.text_buffer[i].code = ' ';
+      virtual_screen.text_buffer[i].fg_color = 0;
+      virtual_screen.text_buffer[i].bg_color = 0;
+      virtual_screen.text_buffer[i].width = 0;
+      virtual_screen.text_buffer[i].index = 0;
+    }
+
+  virtual_screen.cursor_x = virtual_screen.cursor_y = 0;
+}
+
+static void
+grub_vesafb_cls (void)
+{
+  grub_virtual_screen_cls ();
+
+  grub_memset (framebuffer,
+               0, 
+              mode_info.y_resolution * bytes_per_scan_line);
+}
+
+static void
+grub_virtual_screen_setcolorstate (grub_term_color_state state)
+{
+  switch (state)
+    {
+    case GRUB_TERM_COLOR_STANDARD:
+    case GRUB_TERM_COLOR_NORMAL:
+      virtual_screen.fg_color = DEFAULT_FG_COLOR;
+      virtual_screen.bg_color = DEFAULT_BG_COLOR;
+      break;
+    case GRUB_TERM_COLOR_HIGHLIGHT:
+      virtual_screen.fg_color = DEFAULT_BG_COLOR;
+      virtual_screen.bg_color = DEFAULT_FG_COLOR;
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+grub_vesafb_setcursor (int on)
+{
+  if (virtual_screen.cursor_state != on)
+    {
+      if (virtual_screen.cursor_state)
+       write_char ();
+      else
+       write_cursor ();
+
+      virtual_screen.cursor_state = on;
+    }
+}
+
+static struct grub_term_output grub_vesafb_term =
+  {
+    .name = "vesafb",
+    .init = grub_vesafb_mod_init,
+    .fini = grub_vesafb_mod_fini,
+    .putchar = grub_vesafb_putchar,
+    .getcharwidth = grub_vesafb_getcharwidth,
+    .getwh = grub_virtual_screen_getwh,
+    .getxy = grub_virtual_screen_getxy,
+    .gotoxy = grub_vesafb_gotoxy,
+    .cls = grub_vesafb_cls,
+    .setcolorstate = grub_virtual_screen_setcolorstate,
+    .setcursor = grub_vesafb_setcursor,
+    .flags = 0,
+  };
+
+GRUB_MOD_INIT(vesafb)
+{
+  my_mod = mod;
+  grub_term_register_output (&grub_vesafb_term);
+}
+
+GRUB_MOD_FINI(vesafb)
+{
+  grub_term_unregister_output (&grub_vesafb_term);
+}
diff --git a/term/i386/pc/vga.c b/term/i386/pc/vga.c
new file mode 100644 (file)
index 0000000..d32c86e
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ *  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/>.
+ */
+
+// TODO: Deprecated and broken. Needs to be converted to Video Driver!
+
+#include <grub/machine/vga.h>
+#include <grub/machine/console.h>
+#include <grub/cpu/io.h>
+#include <grub/term.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/font.h>
+#include <grub/arg.h>
+
+#define DEBUG_VGA      0
+
+#define VGA_WIDTH      640
+#define VGA_HEIGHT     350
+#define CHAR_WIDTH     8
+#define CHAR_HEIGHT    16
+#define TEXT_WIDTH     (VGA_WIDTH / CHAR_WIDTH)
+#define TEXT_HEIGHT    (VGA_HEIGHT / CHAR_HEIGHT)
+#define VGA_MEM                ((grub_uint8_t *) GRUB_MEMORY_MACHINE_VGA_ADDR)
+#define PAGE_OFFSET(x) ((x) * (VGA_WIDTH * VGA_HEIGHT / 8))
+
+#define DEFAULT_FG_COLOR       0xa
+#define DEFAULT_BG_COLOR       0x0
+
+struct colored_char
+{
+  /* An Unicode codepoint.  */
+  grub_uint32_t code;
+
+  /* Color indexes.  */
+  unsigned char fg_color;
+  unsigned char bg_color;
+
+  /* The width of this character minus one.  */
+  unsigned char width;
+
+  /* The column index of this character.  */
+  unsigned char index;
+};
+
+static grub_dl_t my_mod;
+static unsigned char text_mode;
+static unsigned xpos, ypos;
+static int cursor_state;
+static unsigned char fg_color, bg_color;
+static struct colored_char text_buf[TEXT_WIDTH * TEXT_HEIGHT];
+static unsigned char saved_map_mask;
+static int page = 0;
+static grub_font_t font = 0;
+
+#define SEQUENCER_ADDR_PORT    0x3C4
+#define SEQUENCER_DATA_PORT    0x3C5
+#define MAP_MASK_REGISTER      0x02
+
+#define CRTC_ADDR_PORT         0x3D4
+#define CRTC_DATA_PORT         0x3D5
+#define START_ADDR_HIGH_REGISTER 0x0C
+#define START_ADDR_LOW_REGISTER        0x0D
+
+#define GRAPHICS_ADDR_PORT     0x3CE
+#define GRAPHICS_DATA_PORT     0x3CF
+#define READ_MAP_REGISTER      0x04
+
+#define INPUT_STATUS1_REGISTER 0x3DA
+#define INPUT_STATUS1_VERTR_BIT 0x08
+
+static inline void
+wait_vretrace (void)
+{
+  /* Wait until there is a vertical retrace.  */
+  while (! (grub_inb (INPUT_STATUS1_REGISTER) & INPUT_STATUS1_VERTR_BIT));
+}
+
+/* Get Map Mask Register.  */
+static unsigned char
+get_map_mask (void)
+{
+  unsigned char old_addr;
+  unsigned char old_data;
+  
+  old_addr = grub_inb (SEQUENCER_ADDR_PORT);
+  grub_outb (MAP_MASK_REGISTER, SEQUENCER_ADDR_PORT);
+  
+  old_data = grub_inb (SEQUENCER_DATA_PORT);
+  
+  grub_outb (old_addr, SEQUENCER_ADDR_PORT);
+
+  return old_data;
+}
+
+/* Set Map Mask Register.  */
+static void
+set_map_mask (unsigned char mask)
+{
+  unsigned char old_addr;
+  
+  old_addr = grub_inb (SEQUENCER_ADDR_PORT);
+  grub_outb (MAP_MASK_REGISTER, SEQUENCER_ADDR_PORT);
+  
+  grub_outb (mask, SEQUENCER_DATA_PORT);
+  
+  grub_outb (old_addr, SEQUENCER_ADDR_PORT);
+}
+
+/* Set Read Map Register.  */
+static void
+set_read_map (unsigned char map)
+{
+  unsigned char old_addr;
+  
+  old_addr = grub_inb (GRAPHICS_ADDR_PORT);
+
+  grub_outb (READ_MAP_REGISTER, GRAPHICS_ADDR_PORT);
+  grub_outb (map, GRAPHICS_DATA_PORT);
+
+  grub_outb (old_addr, GRAPHICS_ADDR_PORT);
+}
+
+/* Set start address.  */
+static void
+set_start_address (unsigned int start)
+{
+  unsigned char old_addr;
+  
+  old_addr = grub_inb (CRTC_ADDR_PORT);
+  
+  grub_outb (START_ADDR_LOW_REGISTER, CRTC_ADDR_PORT);
+  grub_outb (start & 0xFF, CRTC_DATA_PORT);
+  
+  grub_outb (START_ADDR_HIGH_REGISTER, CRTC_ADDR_PORT);
+  grub_outb (start >> 8, CRTC_DATA_PORT);
+
+  grub_outb (old_addr, CRTC_ADDR_PORT);
+}
+
+static grub_err_t
+grub_vga_mod_init (void)
+{
+  text_mode = grub_vga_set_mode (0x10);
+  cursor_state = 1;
+  fg_color = DEFAULT_FG_COLOR;
+  bg_color = DEFAULT_BG_COLOR;
+  saved_map_mask = get_map_mask ();
+  set_map_mask (0x0f);
+  set_start_address (PAGE_OFFSET (page));
+  font = grub_font_get ("");  /* Choose any font, for now. */
+  if (!font)
+    return grub_error (GRUB_ERR_BAD_FONT, "No font loaded.");
+  
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_vga_mod_fini (void)
+{
+  set_map_mask (saved_map_mask);
+  grub_vga_set_mode (text_mode);
+  return GRUB_ERR_NONE;
+}
+
+static int
+check_vga_mem (void *p)
+{
+  return (p >= (void *) (VGA_MEM + PAGE_OFFSET (page))
+         && p <= (void *) (VGA_MEM + PAGE_OFFSET (page)
+                           + VGA_WIDTH * VGA_HEIGHT / 8));
+}
+
+static void
+write_char (void)
+{
+  struct colored_char *p = text_buf + xpos + ypos * TEXT_WIDTH;
+  struct grub_font_glyph *glyph;
+  unsigned char *mem_base;
+  unsigned plane;
+
+  mem_base = (VGA_MEM + xpos + 
+             ypos * CHAR_HEIGHT * TEXT_WIDTH + PAGE_OFFSET (page)) - p->index;
+  p -= p->index;
+
+  /* Get glyph for character.  */
+  glyph = grub_font_get_glyph (font, p->code);
+  
+  for (plane = 0x01; plane <= 0x08; plane <<= 1)
+    {
+      unsigned y;
+      unsigned offset;
+      unsigned char *mem;
+
+      set_map_mask (plane);
+
+      for (y = 0, offset = 0, mem = mem_base;
+          y < CHAR_HEIGHT;
+          y++, mem += TEXT_WIDTH)
+       {
+          /* TODO Re-implement glyph drawing for vga module.  */
+#if 0
+         unsigned i;
+
+          unsigned char_width = 1; /* TODO Figure out wide characters.  */
+         for (i = 0; i < char_width && offset < 32; i++)
+           {
+             unsigned char fg_mask, bg_mask;
+             
+             fg_mask = (p->fg_color & plane) ? glyph->bitmap[offset] : 0;
+             bg_mask = (p->bg_color & plane) ? ~(glyph->bitmap[offset]) : 0;
+             offset++;
+
+             if (check_vga_mem (mem + i))
+               mem[i] = (fg_mask | bg_mask);
+           }
+#endif /* 0 */ 
+       }
+    }
+
+  set_map_mask (0x0f);
+}
+
+static void
+write_cursor (void)
+{
+  unsigned char *mem = (VGA_MEM + PAGE_OFFSET (page) + xpos
+                       + (ypos * CHAR_HEIGHT + CHAR_HEIGHT - 3) * TEXT_WIDTH);
+  if (check_vga_mem (mem))
+    *mem = 0xff;
+  
+  mem += TEXT_WIDTH;
+  if (check_vga_mem (mem))
+    *mem = 0xff;
+}
+
+static void
+scroll_up (void)
+{
+  unsigned i;
+  unsigned plane;
+  
+  /* Do all the work in the other page.  */
+  grub_memmove (text_buf, text_buf + TEXT_WIDTH,
+               sizeof (struct colored_char) * TEXT_WIDTH * (TEXT_HEIGHT - 1));
+      
+  for (i = TEXT_WIDTH * (TEXT_HEIGHT - 1); i < TEXT_WIDTH * TEXT_HEIGHT; i++)
+    {
+      text_buf[i].code = ' ';
+      text_buf[i].fg_color = 0;
+      text_buf[i].bg_color = 0;
+      text_buf[i].width = 0;
+      text_buf[i].index = 0;
+    }
+
+  for (plane = 1; plane <= 4; plane++)
+    {
+      set_read_map (plane);
+      set_map_mask (1 << plane);
+      grub_memmove (VGA_MEM + PAGE_OFFSET (1 - page), VGA_MEM
+                   + PAGE_OFFSET (page) + VGA_WIDTH * CHAR_HEIGHT / 8,
+                   VGA_WIDTH * (VGA_HEIGHT - CHAR_HEIGHT) / 8);
+    }
+
+  set_map_mask (0x0f);
+  grub_memset (VGA_MEM + PAGE_OFFSET (1 - page)
+              + VGA_WIDTH * (VGA_HEIGHT - CHAR_HEIGHT) / 8, 0,
+              VGA_WIDTH * CHAR_HEIGHT / 8);
+  
+  /* Activate the other page.  */
+  page = 1 - page;
+  wait_vretrace ();
+  set_start_address (PAGE_OFFSET (page));
+}
+
+static void
+grub_vga_putchar (grub_uint32_t c)
+{
+#if DEBUG_VGA
+  static int show = 1;
+#endif
+  
+  if (c == '\a')
+    /* FIXME */
+    return;
+
+  if (c == '\b' || c == '\n' || c == '\r')
+    {
+      /* Erase current cursor, if any.  */
+      if (cursor_state)
+       write_char ();
+  
+      switch (c)
+       {
+       case '\b':
+         if (xpos > 0)
+           xpos--;
+         break;
+         
+       case '\n':
+         if (ypos >= TEXT_HEIGHT - 1)
+           scroll_up ();
+         else
+           ypos++;
+         break;
+         
+       case '\r':
+         xpos = 0;
+         break;
+       }
+
+      if (cursor_state)
+       write_cursor ();
+    }
+  else
+    {
+      struct grub_font_glyph *glyph;
+      struct colored_char *p;
+      unsigned char_width = 1;
+      
+      glyph = grub_font_get_glyph(font, c);
+
+      if (xpos + char_width > TEXT_WIDTH)
+       grub_putchar ('\n');
+
+      p = text_buf + xpos + ypos * TEXT_WIDTH;
+      p->code = c;
+      p->fg_color = fg_color;
+      p->bg_color = bg_color;
+      p->width = char_width - 1;
+      p->index = 0;
+
+      if (char_width > 1)
+       {
+         unsigned i;
+
+         for (i = 1; i < char_width; i++)
+           {
+             p[i].code = ' ';
+             p[i].width = char_width - 1;
+             p[i].index = i;
+           }
+       }
+         
+      write_char ();
+  
+      xpos += char_width;
+      if (xpos >= TEXT_WIDTH)
+       {
+         xpos = 0;
+         
+         if (ypos >= TEXT_HEIGHT - 1)
+           scroll_up ();
+         else
+           ypos++;
+       }
+
+      if (cursor_state)
+       write_cursor ();
+    }
+
+#if DEBUG_VGA
+  if (show)
+    {
+      grub_uint16_t pos = grub_getxy ();
+
+      show = 0;
+      grub_gotoxy (0, 0);
+      grub_printf ("[%u:%u]", (unsigned) (pos >> 8), (unsigned) (pos & 0xff));
+      grub_gotoxy (pos >> 8, pos & 0xff);
+      show = 1;
+    }
+#endif
+}
+
+static grub_ssize_t
+grub_vga_getcharwidth (grub_uint32_t c)
+{
+#if 0
+  struct grub_font_glyph glyph;
+  
+  glyph = grub_font_get_glyph (c);
+  
+  return glyph.char_width;
+#else
+  (void) c;   /* Prevent warning.  */
+  return 1;   /* TODO Fix wide characters?  */
+#endif
+}
+
+static grub_uint16_t
+grub_vga_getwh (void)
+{
+  return (TEXT_WIDTH << 8) | TEXT_HEIGHT;
+}
+
+static grub_uint16_t
+grub_vga_getxy (void)
+{
+  return ((xpos << 8) | ypos);
+}
+
+static void
+grub_vga_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+  if (x >= TEXT_WIDTH || y >= TEXT_HEIGHT)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)",
+                 (unsigned) x, (unsigned) y);
+      return;
+    }
+
+  if (cursor_state)
+    write_char ();
+
+  xpos = x;
+  ypos = y;
+
+  if (cursor_state)
+    write_cursor ();
+}
+
+static void
+grub_vga_cls (void)
+{
+  unsigned i;
+
+  wait_vretrace ();
+  for (i = 0; i < TEXT_WIDTH * TEXT_HEIGHT; i++)
+    {
+      text_buf[i].code = ' ';
+      text_buf[i].fg_color = 0;
+      text_buf[i].bg_color = 0;
+      text_buf[i].width = 0;
+      text_buf[i].index = 0;
+    }
+
+  grub_memset (VGA_MEM + PAGE_OFFSET (page), 0, VGA_WIDTH * VGA_HEIGHT / 8);
+
+  xpos = ypos = 0;
+}
+
+static void
+grub_vga_setcolorstate (grub_term_color_state state)
+{
+  switch (state)
+    {
+    case GRUB_TERM_COLOR_STANDARD:
+    case GRUB_TERM_COLOR_NORMAL:
+      fg_color = DEFAULT_FG_COLOR;
+      bg_color = DEFAULT_BG_COLOR;
+      break;
+    case GRUB_TERM_COLOR_HIGHLIGHT:
+      fg_color = DEFAULT_BG_COLOR;
+      bg_color = DEFAULT_FG_COLOR;
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+grub_vga_setcursor (int on)
+{
+  if (cursor_state != on)
+    {
+      if (cursor_state)
+       write_char ();
+      else
+       write_cursor ();
+
+      cursor_state = on;
+    }
+}
+
+static struct grub_term_output grub_vga_term =
+  {
+    .name = "vga",
+    .init = grub_vga_mod_init,
+    .fini = grub_vga_mod_fini,
+    .putchar = grub_vga_putchar,
+    .getcharwidth = grub_vga_getcharwidth,
+    .getwh = grub_vga_getwh,
+    .getxy = grub_vga_getxy,
+    .gotoxy = grub_vga_gotoxy,
+    .cls = grub_vga_cls,
+    .setcolorstate = grub_vga_setcolorstate,
+    .setcursor = grub_vga_setcursor,
+    .flags = 0,
+  };
+
+GRUB_MOD_INIT(vga)
+{
+#ifndef GRUB_UTIL
+  my_mod = mod;
+#endif
+  grub_term_register_output (&grub_vga_term);
+}
+
+GRUB_MOD_FINI(vga)
+{
+  grub_term_unregister_output (&grub_vga_term);
+}
diff --git a/term/i386/pc/vga_text.c b/term/i386/pc/vga_text.c
new file mode 100644 (file)
index 0000000..e067ed6
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ *  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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/i386/vga_common.h>
+#include <grub/i386/io.h>
+#include <grub/types.h>
+
+#define COLS   80
+#define ROWS   25
+
+static int grub_curr_x, grub_curr_y;
+
+#define VGA_TEXT_SCREEN                0xb8000
+
+#define CRTC_ADDR_PORT         0x3D4
+#define CRTC_DATA_PORT         0x3D5
+
+#define CRTC_CURSOR            0x0a
+#define CRTC_CURSOR_ADDR_HIGH  0x0e
+#define CRTC_CURSOR_ADDR_LOW   0x0f
+
+#define CRTC_CURSOR_DISABLE    (1 << 5)
+
+static void
+screen_write_char (int x, int y, short c)
+{
+  ((short *) VGA_TEXT_SCREEN)[y * COLS + x] = c;
+}
+
+static short
+screen_read_char (int x, int y)
+{
+  return ((short *) VGA_TEXT_SCREEN)[y * COLS + x];
+}
+
+static void
+update_cursor (void)
+{
+  unsigned int pos = grub_curr_y * COLS + grub_curr_x;
+  grub_outb (CRTC_CURSOR_ADDR_HIGH, CRTC_ADDR_PORT);
+  grub_outb (pos >> 8, CRTC_DATA_PORT);
+  grub_outb (CRTC_CURSOR_ADDR_LOW, CRTC_ADDR_PORT);
+  grub_outb (pos & 0xFF, CRTC_DATA_PORT);
+}
+
+static void
+inc_y (void)
+{
+  grub_curr_x = 0;
+  if (grub_curr_y < ROWS - 1)
+    grub_curr_y++;
+  else
+    {
+      int x, y;
+      for (y = 0; y < ROWS; y++)
+        for (x = 0; x < COLS; x++)
+          screen_write_char (x, y, screen_read_char (x, y + 1));
+    }
+}
+
+static void
+inc_x (void)
+{
+  if (grub_curr_x >= COLS - 2)
+    inc_y ();
+  else
+    grub_curr_x++;
+}
+
+void
+grub_console_real_putchar (int c)
+{
+  switch (c)
+    {
+      case '\b':
+       if (grub_curr_x != 0)
+         screen_write_char (grub_curr_x--, grub_curr_y, ' ');
+       break;
+      case '\n':
+       inc_y ();
+       break;
+      case '\r':
+       grub_curr_x = 0;
+       break;
+      default:
+       screen_write_char (grub_curr_x,
+                          grub_curr_y, c | (grub_console_cur_color << 8));
+       inc_x ();
+    }
+
+  update_cursor ();
+}
+
+static grub_uint16_t
+grub_vga_text_getxy (void)
+{
+  return (grub_curr_x << 8) | grub_curr_y;
+}
+
+static void
+grub_vga_text_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+  grub_curr_x = x;
+  grub_curr_y = y;
+  update_cursor ();
+}
+
+static void
+grub_vga_text_cls (void)
+{
+  int i;
+  for (i = 0; i < ROWS * COLS; i++)
+    ((short *) VGA_TEXT_SCREEN)[i] = ' ' | (grub_console_cur_color << 8);
+  grub_vga_text_gotoxy (0, 0);
+}
+
+static void
+grub_vga_text_setcursor (int on)
+{
+  grub_uint8_t old;
+  grub_outb (CRTC_CURSOR, CRTC_ADDR_PORT);
+  old = grub_inb (CRTC_DATA_PORT);
+  if (on)
+    grub_outb (old & ~CRTC_CURSOR_DISABLE, CRTC_DATA_PORT);
+  else
+    grub_outb (old | CRTC_CURSOR_DISABLE, CRTC_DATA_PORT);
+}
+
+static grub_err_t
+grub_vga_text_init_fini (void)
+{
+  grub_vga_text_cls ();
+  return 0;
+}
+
+static struct grub_term_output grub_vga_text_term =
+  {
+    .name = "vga_text",
+    .init = grub_vga_text_init_fini,
+    .fini = grub_vga_text_init_fini,
+    .putchar = grub_console_putchar,
+    .getcharwidth = grub_console_getcharwidth,
+    .getwh = grub_console_getwh,
+    .getxy = grub_vga_text_getxy,
+    .gotoxy = grub_vga_text_gotoxy,
+    .cls = grub_vga_text_cls,
+    .setcolorstate = grub_console_setcolorstate,
+    .setcolor = grub_console_setcolor,
+    .getcolor = grub_console_getcolor,
+    .setcursor = grub_vga_text_setcursor,
+  };
+
+GRUB_MOD_INIT(vga_text)
+{
+  grub_term_register_output (&grub_vga_text_term);
+}
+
+GRUB_MOD_FINI(vga_text)
+{
+  grub_term_unregister_output (&grub_vga_text_term);
+}
diff --git a/term/i386/vga_common.c b/term/i386/vga_common.c
new file mode 100644 (file)
index 0000000..131b43a
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2005,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/>.
+ */
+
+#include <grub/i386/vga_common.h>
+#include <grub/term.h>
+#include <grub/types.h>
+
+grub_uint8_t grub_console_cur_color = 0x7;
+static grub_uint8_t grub_console_standard_color = 0x7;
+static grub_uint8_t grub_console_normal_color = 0x7;
+static grub_uint8_t grub_console_highlight_color = 0x70;
+
+static grub_uint32_t
+map_char (grub_uint32_t c)
+{
+  if (c > 0x7f)
+    {
+      /* Map some unicode characters to the VGA font, if possible.  */
+      switch (c)
+       {
+       case 0x2190:    /* left arrow */
+         c = 0x1b;
+         break;
+       case 0x2191:    /* up arrow */
+         c = 0x18;
+         break;
+       case 0x2192:    /* right arrow */
+         c = 0x1a;
+         break;
+       case 0x2193:    /* down arrow */
+         c = 0x19;
+         break;
+       case 0x2501:    /* horizontal line */
+         c = 0xc4;
+         break;
+       case 0x2503:    /* vertical line */
+         c = 0xb3;
+         break;
+       case 0x250F:    /* upper-left corner */
+         c = 0xda;
+         break;
+       case 0x2513:    /* upper-right corner */
+         c = 0xbf;
+         break;
+       case 0x2517:    /* lower-left corner */
+         c = 0xc0;
+         break;
+       case 0x251B:    /* lower-right corner */
+         c = 0xd9;
+         break;
+
+       default:
+         c = '?';
+         break;
+       }
+    }
+
+  return c;
+}
+
+void
+grub_console_putchar (grub_uint32_t c)
+{
+  grub_console_real_putchar (map_char (c));
+}
+
+grub_ssize_t
+grub_console_getcharwidth (grub_uint32_t c __attribute__ ((unused)))
+{
+  /* For now, every printable character has the width 1.  */
+  return 1;
+}
+
+grub_uint16_t
+grub_console_getwh (void)
+{
+  return (80 << 8) | 25;
+}
+
+void
+grub_console_setcolorstate (grub_term_color_state state)
+{
+  switch (state) {
+    case GRUB_TERM_COLOR_STANDARD:
+      grub_console_cur_color = grub_console_standard_color;
+      break;
+    case GRUB_TERM_COLOR_NORMAL:
+      grub_console_cur_color = grub_console_normal_color;
+      break;
+    case GRUB_TERM_COLOR_HIGHLIGHT:
+      grub_console_cur_color = grub_console_highlight_color;
+      break;
+    default:
+      break;
+  }
+}
+
+void
+grub_console_setcolor (grub_uint8_t normal_color, grub_uint8_t highlight_color)
+{
+  grub_console_normal_color = normal_color;
+  grub_console_highlight_color = highlight_color;
+}
+
+void
+grub_console_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_color)
+{
+  *normal_color = grub_console_normal_color;
+  *highlight_color = grub_console_highlight_color;
+}
diff --git a/term/ieee1275/ofconsole.c b/term/ieee1275/ofconsole.c
new file mode 100644 (file)
index 0000000..70fda9a
--- /dev/null
@@ -0,0 +1,432 @@
+/*  ofconsole.c -- Open Firmware console for GRUB.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,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/>.
+ */
+
+#include <grub/term.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/machine/console.h>
+#include <grub/ieee1275/ieee1275.h>
+
+static grub_ieee1275_ihandle_t stdout_ihandle;
+static grub_ieee1275_ihandle_t stdin_ihandle;
+
+static grub_uint8_t grub_ofconsole_width;
+static grub_uint8_t grub_ofconsole_height;
+
+static int grub_curr_x;
+static int grub_curr_y;
+
+static int grub_keybuf;
+static int grub_buflen;
+
+struct color
+{
+  int red;
+  int green;
+  int blue;
+};
+
+#define        MAX 0xff
+static struct color colors[8] =
+  {
+    { 0,   0,   0},
+    { MAX, 0,   0},
+    { 0,   MAX, 0},
+    { MAX, MAX, 0},
+    { 0,   0,   MAX},
+    { MAX, 0,   MAX},
+    { 0,   MAX, MAX},
+    { MAX, MAX, MAX}
+  };
+
+static grub_uint8_t grub_ofconsole_normal_color = 0x7;
+static grub_uint8_t grub_ofconsole_highlight_color = 0x70;
+
+/* Write control characters to the console.  */
+static void
+grub_ofconsole_writeesc (const char *str)
+{
+  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_ANSI))
+    return;
+
+  while (*str)
+    {
+      char chr = *(str++);
+      grub_ieee1275_write (stdout_ihandle, &chr, 1, 0);
+    }
+  
+}
+
+static void
+grub_ofconsole_putchar (grub_uint32_t c)
+{
+  char chr = c;
+  if (c == '\n')
+    {
+      grub_curr_y++;
+      grub_curr_x = 0;
+    }
+  else
+    {
+      grub_curr_x++;
+      if (grub_curr_x > grub_ofconsole_width)
+        {
+          grub_putcode ('\n');
+          grub_curr_x++;
+        }
+    }
+  grub_ieee1275_write (stdout_ihandle, &chr, 1, 0);
+}
+
+static grub_ssize_t
+grub_ofconsole_getcharwidth (grub_uint32_t c __attribute__((unused)))
+{
+  return 1;
+}
+
+static void
+grub_ofconsole_setcolorstate (grub_term_color_state state)
+{
+  char setcol[20];
+  int fg;
+  int bg;
+
+  switch (state)
+    {
+    case GRUB_TERM_COLOR_STANDARD:
+    case GRUB_TERM_COLOR_NORMAL:
+      fg = grub_ofconsole_normal_color & 0x0f;
+      bg = grub_ofconsole_normal_color >> 4;
+      break;
+    case GRUB_TERM_COLOR_HIGHLIGHT:
+      fg = grub_ofconsole_highlight_color & 0x0f;
+      bg = grub_ofconsole_highlight_color >> 4;
+      break;
+    default:
+      return;
+    }
+
+  grub_sprintf (setcol, "\e[3%dm\e[4%dm", fg, bg);
+  grub_ofconsole_writeesc (setcol);
+}
+
+static void
+grub_ofconsole_setcolor (grub_uint8_t normal_color,
+                        grub_uint8_t highlight_color)
+{
+  grub_ofconsole_normal_color = normal_color;
+  grub_ofconsole_highlight_color = highlight_color;
+}
+
+static void
+grub_ofconsole_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_color)
+{
+  *normal_color = grub_ofconsole_normal_color;
+  *highlight_color = grub_ofconsole_highlight_color;
+}
+
+static int
+grub_ofconsole_readkey (int *key)
+{
+  char c;
+  grub_ssize_t actual = 0;
+
+  grub_ieee1275_read (stdin_ihandle, &c, 1, &actual);
+
+  if (actual > 0 && c == '\e')
+    {
+      grub_ieee1275_read (stdin_ihandle, &c, 1, &actual);
+      if (actual <= 0)
+       {
+         *key = '\e';
+         return 1;
+       }
+      
+      if (c != 91)
+       return 0;
+      
+      grub_ieee1275_read (stdin_ihandle, &c, 1, &actual);
+      if (actual <= 0)
+       return 0;
+      
+      switch (c)
+       {
+       case 65:
+         /* Up: Ctrl-p.  */
+         c = 16; 
+         break;
+       case 66:
+         /* Down: Ctrl-n.  */
+         c = 14;
+         break;
+       case 67:
+         /* Right: Ctrl-f.  */
+         c = 6;
+         break;
+       case 68:
+         /* Left: Ctrl-b.  */
+         c = 2;
+         break;
+       }
+    }
+  
+  *key = c;
+  return actual > 0;
+}
+
+static int
+grub_ofconsole_checkkey (void)
+{
+  int key;
+  int read;
+  
+  if (grub_buflen)
+    return 1;
+
+  read = grub_ofconsole_readkey (&key);
+  if (read)
+    {
+      grub_keybuf = key;
+      grub_buflen = 1;
+      return 1;
+    }
+    
+  return -1;
+}
+
+static int
+grub_ofconsole_getkey (void)
+{
+  int key;
+
+  if (grub_buflen)
+    {
+      grub_buflen  =0;
+      return grub_keybuf;
+    }
+
+  while (! grub_ofconsole_readkey (&key));
+  
+  return key;
+}
+
+static grub_uint16_t
+grub_ofconsole_getxy (void)
+{
+  return ((grub_curr_x - 1) << 8) | grub_curr_y;
+}
+
+static grub_uint16_t
+grub_ofconsole_getwh (void)
+{
+  grub_ieee1275_ihandle_t options;
+  char *val;
+  grub_ssize_t lval;
+
+  if (grub_ofconsole_width && grub_ofconsole_height)
+    return (grub_ofconsole_width << 8) | grub_ofconsole_height;
+
+  if (! grub_ieee1275_finddevice ("/options", &options)
+      && options != (grub_ieee1275_ihandle_t) -1)
+    {
+      if (! grub_ieee1275_get_property_length (options, "screen-#columns",
+                                              &lval) && lval != -1)
+       {
+         val = grub_malloc (lval);
+         if (val)
+           {
+             if (! grub_ieee1275_get_property (options, "screen-#columns",
+                                               val, lval, 0))
+               grub_ofconsole_width = (grub_uint8_t) grub_strtoul (val, 0, 10);
+
+             grub_free (val);
+           }
+       }
+      if (! grub_ieee1275_get_property_length (options, "screen-#rows",
+                                              &lval) && lval != -1)
+       {
+         val = grub_malloc (lval);
+         if (val)
+           {
+             if (! grub_ieee1275_get_property (options, "screen-#rows",
+                                               val, lval, 0))
+               grub_ofconsole_height = (grub_uint8_t) grub_strtoul (val, 0, 10);
+
+             grub_free (val);
+           }
+       }
+    }
+
+  /* Use a small console by default.  */
+  if (! grub_ofconsole_width)
+    grub_ofconsole_width = 80;
+  if (! grub_ofconsole_height)
+    grub_ofconsole_height = 24;
+
+  return (grub_ofconsole_width << 8) | grub_ofconsole_height;
+}
+
+static void
+grub_ofconsole_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+  char s[11]; /* 5 + 3 + 3.  */
+
+  if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_ANSI))
+    {
+      grub_curr_x = x;
+      grub_curr_y = y;
+
+      grub_sprintf (s, "\e[%d;%dH", y + 1, x + 1);
+      grub_ofconsole_writeesc (s);
+    }
+  else
+    {
+      if ((y == grub_curr_y) && (x == grub_curr_x - 1))
+        {
+          char chr;
+
+          chr = '\b';
+          grub_ieee1275_write (stdout_ihandle, &chr, 1, 0);
+        }
+
+      grub_curr_x = x;
+      grub_curr_y = y;
+    }
+}
+
+static void
+grub_ofconsole_cls (void)
+{
+  /* Clear the screen.  Using serial console, screen(1) only recognizes the
+   * ANSI escape sequence.  Using video console, Apple Open Firmware (version
+   * 3.1.1) only recognizes the literal ^L.  So use both.  */
+  grub_ofconsole_writeesc ("\f\e[2J");
+  grub_gotoxy (0, 0);
+}
+
+static void
+grub_ofconsole_setcursor (int on)
+{
+  /* Understood by the Open Firmware flavour in OLPC.  */
+  if (on)
+    grub_ieee1275_interpret ("cursor-on", 0);
+  else
+    grub_ieee1275_interpret ("cursor-off", 0);
+}
+
+static void
+grub_ofconsole_refresh (void)
+{
+  /* Do nothing, the current console state is ok.  */
+}
+
+static grub_err_t
+grub_ofconsole_init_input (void)
+{
+  grub_ssize_t actual;
+
+  if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen, "stdin", &stdin_ihandle,
+                                         sizeof stdin_ihandle, &actual)
+      || actual != sizeof stdin_ihandle)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Cannot find stdin");
+
+  return 0;
+}
+
+static grub_err_t
+grub_ofconsole_init_output (void)
+{
+  grub_ssize_t actual;
+  int col;
+
+  /* The latest PowerMacs don't actually initialize the screen for us, so we
+   * use this trick to re-open the output device (but we avoid doing this on
+   * platforms where it's known to be broken). */
+  if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_OUTPUT))
+    grub_ieee1275_interpret ("output-device output", 0);
+
+  if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen, "stdout", &stdout_ihandle,
+                                         sizeof stdout_ihandle, &actual)
+      || actual != sizeof stdout_ihandle)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Cannot find stdout");
+
+  /* Initialize colors.  */
+  if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_SET_COLORS))
+    {
+      for (col = 0; col < 7; col++)
+       grub_ieee1275_set_color (stdout_ihandle, col, colors[col].red,
+                                colors[col].green, colors[col].blue);
+
+    /* Set the right fg and bg colors.  */
+      grub_ofconsole_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+    }
+
+  return 0;
+}
+
+static grub_err_t
+grub_ofconsole_fini (void)
+{
+  return 0;
+}
+
+
+\f
+static struct grub_term_input grub_ofconsole_term_input =
+  {
+    .name = "ofconsole",
+    .init = grub_ofconsole_init_input,
+    .fini = grub_ofconsole_fini,
+    .checkkey = grub_ofconsole_checkkey,
+    .getkey = grub_ofconsole_getkey,
+  };
+
+static struct grub_term_output grub_ofconsole_term_output =
+  {
+    .name = "ofconsole",
+    .init = grub_ofconsole_init_output,
+    .fini = grub_ofconsole_fini,
+    .putchar = grub_ofconsole_putchar,
+    .getcharwidth = grub_ofconsole_getcharwidth,
+    .getxy = grub_ofconsole_getxy,
+    .getwh = grub_ofconsole_getwh,
+    .gotoxy = grub_ofconsole_gotoxy,
+    .cls = grub_ofconsole_cls,
+    .setcolorstate = grub_ofconsole_setcolorstate,
+    .setcolor = grub_ofconsole_setcolor,
+    .getcolor = grub_ofconsole_getcolor,
+    .setcursor = grub_ofconsole_setcursor,
+    .refresh = grub_ofconsole_refresh,
+    .flags = 0,
+  };
+
+void
+grub_console_init (void)
+{
+  grub_term_register_input (&grub_ofconsole_term_input);
+  grub_term_register_output (&grub_ofconsole_term_output);
+}
+
+void
+grub_console_fini (void)
+{
+  grub_term_unregister_input (&grub_ofconsole_term_input);
+  grub_term_unregister_output (&grub_ofconsole_term_output);
+}
diff --git a/term/terminfo.c b/term/terminfo.c
new file mode 100644 (file)
index 0000000..5cbbe16
--- /dev/null
@@ -0,0 +1,187 @@
+/* terminfo.c - simple terminfo module */
+/*
+ *  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/>.
+ */
+
+/*
+ * This file contains various functions dealing with different
+ * terminal capabilities. For example, vt52 and vt100.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/term.h>
+#include <grub/terminfo.h>
+#include <grub/tparm.h>
+
+struct terminfo
+{
+  char *name;
+
+  char *gotoxy;
+  char *cls;
+  char *reverse_video_on;
+  char *reverse_video_off;
+  char *cursor_on;
+  char *cursor_off;
+};
+
+static struct terminfo term;
+
+/* Get current terminfo name.  */
+char *
+grub_terminfo_get_current (void)
+{
+  return term.name;
+}
+
+/* Free *PTR and set *PTR to NULL, to prevent double-free.  */
+static void
+grub_terminfo_free (char **ptr)
+{
+  grub_free (*ptr);
+  *ptr = 0;
+}
+
+/* Set current terminfo type.  */
+grub_err_t
+grub_terminfo_set_current (const char *str)
+{
+  /* TODO
+   * Lookup user specified terminfo type. If found, set term variables
+   * as appropriate. Otherwise return an error.
+   *
+   * How should this be done?
+   *  a. A static table included in this module.
+   *     - I do not like this idea.
+   *  b. A table stored in the configuration directory.
+   *     - Users must convert their terminfo settings if we have not already.
+   *  c. Look for terminfo files in the configuration directory.
+   *     - /usr/share/terminfo is 6.3M on my system.
+   *     - /usr/share/terminfo is not on most users boot partition.
+   *     + Copying the terminfo files you want to use to the grub
+   *       configuration directory is easier then (b).
+   *  d. Your idea here.
+   */
+
+  /* Free previously allocated memory.  */
+  grub_terminfo_free (&term.name);
+  grub_terminfo_free (&term.gotoxy);
+  grub_terminfo_free (&term.cls);
+  grub_terminfo_free (&term.reverse_video_on);
+  grub_terminfo_free (&term.reverse_video_off);
+  grub_terminfo_free (&term.cursor_on);
+  grub_terminfo_free (&term.cursor_off);
+  
+  if (grub_strcmp ("vt100", str) == 0)
+    {
+      term.name              = grub_strdup ("vt100");
+      term.gotoxy            = grub_strdup ("\e[%i%p1%d;%p2%dH");
+      term.cls               = grub_strdup ("\e[H\e[J");
+      term.reverse_video_on  = grub_strdup ("\e[7m");
+      term.reverse_video_off = grub_strdup ("\e[m");
+      term.cursor_on         = grub_strdup ("\e[?25h");
+      term.cursor_off        = grub_strdup ("\e[?25l");
+      return grub_errno;
+    }
+  
+  return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminfo type.");
+}
+
+/* Wrapper for grub_putchar to write strings.  */
+static void
+putstr (const char *str)
+{
+  while (*str)
+    grub_putchar (*str++);
+}
+
+/* Move the cursor to the given position starting with "0".  */
+void
+grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+  putstr (grub_terminfo_tparm (term.gotoxy, y, x));
+}
+
+/* Clear the screen.  */
+void
+grub_terminfo_cls (void)
+{
+  putstr (grub_terminfo_tparm (term.cls));
+}
+
+/* Set reverse video mode on.  */
+void
+grub_terminfo_reverse_video_on (void)
+{
+  putstr (grub_terminfo_tparm (term.reverse_video_on));
+}
+
+/* Set reverse video mode off.  */
+void
+grub_terminfo_reverse_video_off (void)
+{
+  putstr (grub_terminfo_tparm (term.reverse_video_off));
+}
+
+/* Show cursor.  */
+void
+grub_terminfo_cursor_on (void)
+{
+  putstr (grub_terminfo_tparm (term.cursor_on));
+}
+
+/* Hide cursor.  */
+void
+grub_terminfo_cursor_off (void)
+{
+  putstr (grub_terminfo_tparm (term.cursor_off));
+}
+
+/* GRUB Command.  */
+
+static grub_err_t
+grub_cmd_terminfo (struct grub_arg_list *state __attribute__ ((unused)),
+               int argc, char **args)
+{
+  if (argc == 0)
+  {
+    grub_printf ("Current terminfo type: %s\n", grub_terminfo_get_current());
+    return GRUB_ERR_NONE;
+  }
+  else if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many parameters.");
+  else
+    return grub_terminfo_set_current (args[0]);
+}
+
+GRUB_MOD_INIT(terminfo)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("terminfo", grub_cmd_terminfo, GRUB_COMMAND_FLAG_BOTH,
+                        "terminfo [TERM]", "Set terminfo type.", 0);
+  grub_terminfo_set_current ("vt100");
+}
+
+GRUB_MOD_FINI(terminfo)
+{
+  grub_unregister_command ("terminfo");
+}
diff --git a/term/tparm.c b/term/tparm.c
new file mode 100644 (file)
index 0000000..b634dba
--- /dev/null
@@ -0,0 +1,768 @@
+/****************************************************************************
+ * Copyright (c) 1998-2003,2004,2005 Free Software Foundation, Inc.         *
+ *                                                                          *
+ * Permission is hereby granted, free of charge, to any person obtaining a  *
+ * copy of this software and associated documentation files (the            *
+ * "Software"), to deal in the Software without restriction, including      *
+ * without limitation the rights to use, copy, modify, merge, publish,      *
+ * distribute, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/**********************************************************************
+ * This code is a modification of lib_tparm.c found in ncurses-5.2. The
+ * modification are for use in grub by replacing all libc function through
+ * special grub functions. This also meant to delete all dynamic memory
+ * allocation and replace it by a number of fixed buffers.
+ *
+ * Modifications by Tilmann Bubeck <t.bubeck@reinform.de> 2002
+ *
+ * Resync with ncurses-5.4 by Omniflux <omniflux+devel@omniflux.com> 2005
+ **********************************************************************/
+
+/****************************************************************************
+ *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
+ *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
+ *     and: Thomas E. Dickey, 1996 on                                       *
+ ****************************************************************************/
+
+/*
+ *     tparm.c
+ *
+ */
+
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/tparm.h>
+
+/*
+ * Common/troublesome character definitions
+ */
+typedef char grub_bool_t;
+#ifndef FALSE
+# define FALSE (0)
+#endif
+#ifndef TRUE
+# define TRUE (!FALSE)
+#endif
+
+#define NUM_PARM 9
+#define NUM_VARS 26
+#define STACKSIZE 20
+#define MAX_FORMAT_LEN 256
+
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#define isdigit(c) ((c) >= '0' && (c) <= '9')
+#define isUPPER(c) ((c) >= 'A' && (c) <= 'Z')
+#define isLOWER(c) ((c) >= 'a' && (c) <= 'z')
+
+#define UChar(c) ((unsigned char)(c))
+
+//MODULE_ID("$Id: tparm.c 1665 2008-07-02 00:54:18Z proski $")
+
+/*
+ *     char *
+ *     tparm(string, ...)
+ *
+ *     Substitute the given parameters into the given string by the following
+ *     rules (taken from terminfo(5)):
+ *
+ *          Cursor addressing and other strings  requiring  parame-
+ *     ters in the terminal are described by a parameterized string
+ *     capability, with like escapes %x in  it.   For  example,  to
+ *     address  the  cursor, the cup capability is given, using two
+ *     parameters: the row and column to  address  to.   (Rows  and
+ *     columns  are  numbered  from  zero and refer to the physical
+ *     screen visible to the user, not to any  unseen  memory.)  If
+ *     the terminal has memory relative cursor addressing, that can
+ *     be indicated by
+ *
+ *          The parameter mechanism uses  a  stack  and  special  %
+ *     codes  to manipulate it.  Typically a sequence will push one
+ *     of the parameters onto the stack and then print it  in  some
+ *     format.  Often more complex operations are necessary.
+ *
+ *          The % encodings have the following meanings:
+ *
+ *          %%        outputs `%'
+ *          %c        print pop() like %c in printf()
+ *          %s        print pop() like %s in printf()
+ *           %[[:]flags][width[.precision]][doxXs]
+ *                     as in printf, flags are [-+#] and space
+ *                     The ':' is used to avoid making %+ or %-
+ *                     patterns (see below).
+ *
+ *          %p[1-9]   push ith parm
+ *          %P[a-z]   set dynamic variable [a-z] to pop()
+ *          %g[a-z]   get dynamic variable [a-z] and push it
+ *          %P[A-Z]   set static variable [A-Z] to pop()
+ *          %g[A-Z]   get static variable [A-Z] and push it
+ *          %l        push strlen(pop)
+ *          %'c'      push char constant c
+ *          %{nn}     push integer constant nn
+ *
+ *          %+ %- %* %/ %m
+ *                    arithmetic (%m is mod): push(pop() op pop())
+ *          %& %| %^  bit operations: push(pop() op pop())
+ *          %= %> %<  logical operations: push(pop() op pop())
+ *          %A %O     logical and & or operations for conditionals
+ *          %! %~     unary operations push(op pop())
+ *          %i        add 1 to first two parms (for ANSI terminals)
+ *
+ *          %? expr %t thenpart %e elsepart %;
+ *                    if-then-else, %e elsepart is optional.
+ *                    else-if's are possible ala Algol 68:
+ *                    %? c1 %t b1 %e c2 %t b2 %e c3 %t b3 %e c4 %t b4 %e b5 %;
+ *
+ *     For those of the above operators which are binary and not commutative,
+ *     the stack works in the usual way, with
+ *                     %gx %gy %m
+ *     resulting in x mod y, not the reverse.
+ */
+
+typedef struct {
+    union {
+       int num;
+       char *str;
+    } data;
+    grub_bool_t num_type;
+} stack_frame;
+
+static stack_frame stack[STACKSIZE];
+static int stack_ptr;
+static const char *tparam_base = "";
+
+static char *out_buff;
+static grub_size_t out_size;
+static grub_size_t out_used;
+
+static char *fmt_buff;
+static grub_size_t fmt_size;
+
+static inline void
+get_space(grub_size_t need)
+{
+    need += out_used;
+    if (need > out_size) {
+       out_size = need * 2;
+       out_buff = grub_realloc(out_buff, out_size*sizeof(char));
+       /* FIX ME! handle out_buff == 0.  */
+    }
+}
+
+static inline void
+save_text(const char *fmt, const char *s, int len)
+{
+    grub_size_t s_len = grub_strlen(s);
+    if (len > (int) s_len)
+       s_len = len;
+
+    get_space(s_len + 1);
+
+    (void) grub_sprintf(out_buff + out_used, fmt, s);
+    out_used += grub_strlen(out_buff + out_used);
+}
+
+static inline void
+save_number(const char *fmt, int number, int len)
+{
+    if (len < 30)
+       len = 30;               /* actually log10(MAX_INT)+1 */
+
+    get_space((unsigned) len + 1);
+
+    (void) grub_sprintf(out_buff + out_used, fmt, number);
+    out_used += grub_strlen(out_buff + out_used);
+}
+
+static inline void
+save_char(int c)
+{
+    if (c == 0)
+       c = 0200;
+    get_space(1);
+    out_buff[out_used++] = c;
+}
+
+static inline void
+npush(int x)
+{
+    if (stack_ptr < STACKSIZE) {
+       stack[stack_ptr].num_type = TRUE;
+       stack[stack_ptr].data.num = x;
+       stack_ptr++;
+    }
+}
+
+static inline int
+npop(void)
+{
+    int result = 0;
+    if (stack_ptr > 0) {
+       stack_ptr--;
+       if (stack[stack_ptr].num_type)
+           result = stack[stack_ptr].data.num;
+    }
+    return result;
+}
+
+static inline void
+spush(char *x)
+{
+    if (stack_ptr < STACKSIZE) {
+       stack[stack_ptr].num_type = FALSE;
+       stack[stack_ptr].data.str = x;
+       stack_ptr++;
+    }
+}
+
+static inline char *
+spop(void)
+{
+    static char dummy[] = "";  /* avoid const-cast */
+    char *result = dummy;
+    if (stack_ptr > 0) {
+       stack_ptr--;
+       if (!stack[stack_ptr].num_type && stack[stack_ptr].data.str != 0)
+           result = stack[stack_ptr].data.str;
+    }
+    return result;
+}
+
+static inline const char *
+parse_format(const char *s, char *format, int *len)
+{
+    *len = 0;
+    if (format != 0) {
+       grub_bool_t done = FALSE;
+       grub_bool_t allowminus = FALSE;
+       grub_bool_t dot = FALSE;
+       grub_bool_t err = FALSE;
+       char *fmt = format;
+       int my_width = 0;
+       int my_prec = 0;
+       int value = 0;
+
+       *len = 0;
+       *format++ = '%';
+       while (*s != '\0' && !done) {
+           switch (*s) {
+           case 'c':           /* FALLTHRU */
+           case 'd':           /* FALLTHRU */
+           case 'o':           /* FALLTHRU */
+           case 'x':           /* FALLTHRU */
+           case 'X':           /* FALLTHRU */
+           case 's':
+               *format++ = *s;
+               done = TRUE;
+               break;
+           case '.':
+               *format++ = *s++;
+               if (dot) {
+                   err = TRUE;
+               } else {        /* value before '.' is the width */
+                   dot = TRUE;
+                   my_width = value;
+               }
+               value = 0;
+               break;
+           case '#':
+               *format++ = *s++;
+               break;
+           case ' ':
+               *format++ = *s++;
+               break;
+           case ':':
+               s++;
+               allowminus = TRUE;
+               break;
+           case '-':
+               if (allowminus) {
+                   *format++ = *s++;
+               } else {
+                   done = TRUE;
+               }
+               break;
+           default:
+               if (isdigit(UChar(*s))) {
+                   value = (value * 10) + (*s - '0');
+                   if (value > 10000)
+                       err = TRUE;
+                   *format++ = *s++;
+               } else {
+                   done = TRUE;
+               }
+           }
+       }
+
+       /*
+        * If we found an error, ignore (and remove) the flags.
+        */
+       if (err) {
+           my_width = my_prec = value = 0;
+           format = fmt;
+           *format++ = '%';
+           *format++ = *s;
+       }
+
+       /*
+        * Any value after '.' is the precision.  If we did not see '.', then
+        * the value is the width.
+        */
+       if (dot)
+           my_prec = value;
+       else
+           my_width = value;
+
+       *format = '\0';
+       /* return maximum string length in print */
+       *len = (my_width > my_prec) ? my_width : my_prec;
+    }
+    return s;
+}
+
+/*
+ * Analyze the string to see how many parameters we need from the varargs list,
+ * and what their types are.  We will only accept string parameters if they
+ * appear as a %l or %s format following an explicit parameter reference (e.g.,
+ * %p2%s).  All other parameters are numbers.
+ *
+ * 'number' counts coarsely the number of pop's we see in the string, and
+ * 'popcount' shows the highest parameter number in the string.  We would like
+ * to simply use the latter count, but if we are reading termcap strings, there
+ * may be cases that we cannot see the explicit parameter numbers.
+ */
+static inline int
+analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount)
+{
+    grub_size_t len2;
+    int i;
+    int lastpop = -1;
+    int len;
+    int number = 0;
+    const char *cp = string;
+    static char dummy[] = "";
+
+    *popcount = 0;
+
+    if (cp == 0)
+       return 0;
+
+    if ((len2 = grub_strlen(cp)) > fmt_size) {
+       fmt_size = len2 + fmt_size + 2;
+       if ((fmt_buff = grub_realloc(fmt_buff, fmt_size*sizeof(char))) == 0)
+             return 0;
+    }
+
+    grub_memset(p_is_s, 0, sizeof(p_is_s[0]) * NUM_PARM);
+
+    while ((cp - string) < (int) len2) {
+       if (*cp == '%') {
+           cp++;
+           cp = parse_format(cp, fmt_buff, &len);
+           switch (*cp) {
+           default:
+               break;
+
+           case 'd':           /* FALLTHRU */
+           case 'o':           /* FALLTHRU */
+           case 'x':           /* FALLTHRU */
+           case 'X':           /* FALLTHRU */
+           case 'c':           /* FALLTHRU */
+               if (lastpop <= 0)
+                   number++;
+               lastpop = -1;
+               break;
+
+           case 'l':
+           case 's':
+               if (lastpop > 0)
+                   p_is_s[lastpop - 1] = dummy;
+               ++number;
+               break;
+
+           case 'p':
+               cp++;
+               i = (UChar(*cp) - '0');
+               if (i >= 0 && i <= NUM_PARM) {
+                   lastpop = i;
+                   if (lastpop > *popcount)
+                       *popcount = lastpop;
+               }
+               break;
+
+           case 'P':
+               ++number;
+               ++cp;
+               break;
+
+           case 'g':
+               cp++;
+               break;
+
+           case '\'':
+               cp += 2;
+               lastpop = -1;
+               break;
+
+           case '{':
+               cp++;
+               while (isdigit(UChar(*cp))) {
+                   cp++;
+               }
+               break;
+
+           case '+':
+           case '-':
+           case '*':
+           case '/':
+           case 'm':
+           case 'A':
+           case 'O':
+           case '&':
+           case '|':
+           case '^':
+           case '=':
+           case '<':
+           case '>':
+               lastpop = -1;
+               number += 2;
+               break;
+
+           case '!':
+           case '~':
+               lastpop = -1;
+               ++number;
+               break;
+
+           case 'i':
+               /* will add 1 to first (usually two) parameters */
+               break;
+           }
+       }
+       if (*cp != '\0')
+           cp++;
+    }
+
+    if (number > NUM_PARM)
+       number = NUM_PARM;
+    return number;
+}
+
+static inline char *
+tparam_internal(const char *string, va_list ap)
+{
+    char *p_is_s[NUM_PARM];
+    long param[NUM_PARM];
+    int popcount;
+    int number;
+    int len;
+    int level;
+    int x, y;
+    int i;
+    const char *cp = string;
+    grub_size_t len2;
+    static int dynamic_var[NUM_VARS];
+    static int static_vars[NUM_VARS];
+
+    if (cp == 0)
+       return 0;
+
+    out_used = out_size = fmt_size = 0;
+
+    len2 = (int) grub_strlen(cp);
+
+    /*
+     * Find the highest parameter-number referred to in the format string.
+     * Use this value to limit the number of arguments copied from the
+     * variable-length argument list.
+     */
+    number = analyze(cp, p_is_s, &popcount);
+    if (fmt_buff == 0)
+       return 0;
+
+    for (i = 0; i < max(popcount, number); i++) {
+       /*
+        * A few caps (such as plab_norm) have string-valued parms.
+        * We'll have to assume that the caller knows the difference, since
+        * a char* and an int may not be the same size on the stack.
+        */
+       if (p_is_s[i] != 0) {
+           p_is_s[i] = va_arg(ap, char *);
+       } else {
+           param[i] = va_arg(ap, long int);
+       }
+    }
+
+    /*
+     * This is a termcap compatibility hack.  If there are no explicit pop
+     * operations in the string, load the stack in such a way that
+     * successive pops will grab successive parameters.  That will make
+     * the expansion of (for example) \E[%d;%dH work correctly in termcap
+     * style, which means tparam() will expand termcap strings OK.
+     */
+    stack_ptr = 0;
+    if (popcount == 0) {
+       popcount = number;
+       for (i = number - 1; i >= 0; i--)
+           npush(param[i]);
+    }
+
+    while ((cp - string) < (int) len2) {
+       if (*cp != '%') {
+           save_char(UChar(*cp));
+       } else {
+           tparam_base = cp++;
+           cp = parse_format(cp, fmt_buff, &len);
+           switch (*cp) {
+           default:
+               break;
+           case '%':
+               save_char('%');
+               break;
+
+           case 'd':           /* FALLTHRU */
+           case 'o':           /* FALLTHRU */
+           case 'x':           /* FALLTHRU */
+           case 'X':           /* FALLTHRU */
+               save_number(fmt_buff, npop(), len);
+               break;
+
+           case 'c':           /* FALLTHRU */
+               save_char(npop());
+               break;
+
+           case 'l':
+               save_number("%d", (int) grub_strlen(spop()), 0);
+               break;
+
+           case 's':
+               save_text(fmt_buff, spop(), len);
+               break;
+
+           case 'p':
+               cp++;
+               i = (UChar(*cp) - '1');
+               if (i >= 0 && i < NUM_PARM) {
+                   if (p_is_s[i])
+                       spush(p_is_s[i]);
+                   else
+                       npush(param[i]);
+               }
+               break;
+
+           case 'P':
+               cp++;
+               if (isUPPER(*cp)) {
+                   i = (UChar(*cp) - 'A');
+                   static_vars[i] = npop();
+               } else if (isLOWER(*cp)) {
+                   i = (UChar(*cp) - 'a');
+                   dynamic_var[i] = npop();
+               }
+               break;
+
+           case 'g':
+               cp++;
+               if (isUPPER(*cp)) {
+                   i = (UChar(*cp) - 'A');
+                   npush(static_vars[i]);
+               } else if (isLOWER(*cp)) {
+                   i = (UChar(*cp) - 'a');
+                   npush(dynamic_var[i]);
+               }
+               break;
+
+           case '\'':
+               cp++;
+               npush(UChar(*cp));
+               cp++;
+               break;
+
+           case '{':
+               number = 0;
+               cp++;
+               while (isdigit(UChar(*cp))) {
+                   number = (number * 10) + (UChar(*cp) - '0');
+                   cp++;
+               }
+               npush(number);
+               break;
+
+           case '+':
+               npush(npop() + npop());
+               break;
+
+           case '-':
+               y = npop();
+               x = npop();
+               npush(x - y);
+               break;
+
+           case '*':
+               npush(npop() * npop());
+               break;
+
+           case '/':
+               y = npop();
+               x = npop();
+               npush(y ? (x / y) : 0);
+               break;
+
+           case 'm':
+               y = npop();
+               x = npop();
+               npush(y ? (x % y) : 0);
+               break;
+
+           case 'A':
+               npush(npop() && npop());
+               break;
+
+           case 'O':
+               npush(npop() || npop());
+               break;
+
+           case '&':
+               npush(npop() & npop());
+               break;
+
+           case '|':
+               npush(npop() | npop());
+               break;
+
+           case '^':
+               npush(npop() ^ npop());
+               break;
+
+           case '=':
+               y = npop();
+               x = npop();
+               npush(x == y);
+               break;
+
+           case '<':
+               y = npop();
+               x = npop();
+               npush(x < y);
+               break;
+
+           case '>':
+               y = npop();
+               x = npop();
+               npush(x > y);
+               break;
+
+           case '!':
+               npush(!npop());
+               break;
+
+           case '~':
+               npush(~npop());
+               break;
+
+           case 'i':
+               if (p_is_s[0] == 0)
+                   param[0]++;
+               if (p_is_s[1] == 0)
+                   param[1]++;
+               break;
+
+           case '?':
+               break;
+
+           case 't':
+               x = npop();
+               if (!x) {
+                   /* scan forward for %e or %; at level zero */
+                   cp++;
+                   level = 0;
+                   while (*cp) {
+                       if (*cp == '%') {
+                           cp++;
+                           if (*cp == '?')
+                               level++;
+                           else if (*cp == ';') {
+                               if (level > 0)
+                                   level--;
+                               else
+                                   break;
+                           } else if (*cp == 'e' && level == 0)
+                               break;
+                       }
+
+                       if (*cp)
+                           cp++;
+                   }
+               }
+               break;
+
+           case 'e':
+               /* scan forward for a %; at level zero */
+               cp++;
+               level = 0;
+               while (*cp) {
+                   if (*cp == '%') {
+                       cp++;
+                       if (*cp == '?')
+                           level++;
+                       else if (*cp == ';') {
+                           if (level > 0)
+                               level--;
+                           else
+                               break;
+                       }
+                   }
+
+                   if (*cp)
+                       cp++;
+               }
+               break;
+
+           case ';':
+               break;
+
+           }                   /* endswitch (*cp) */
+       }                       /* endelse (*cp == '%') */
+
+       if (*cp == '\0')
+           break;
+
+       cp++;
+    }                          /* endwhile (*cp) */
+
+    get_space(1);
+    out_buff[out_used] = '\0';
+
+    return (out_buff);
+}
+
+char *
+grub_terminfo_tparm (const char *string, ...)
+{
+    va_list ap;
+    char *result;
+
+    va_start (ap, string);
+    result = tparam_internal (string, ap);
+    va_end (ap);
+    return result;
+}
diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c
new file mode 100644 (file)
index 0000000..07f7d08
--- /dev/null
@@ -0,0 +1,257 @@
+/* Support for the HID Boot Protocol.  */
+/*
+ *  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/term.h>
+#include <grub/machine/machine.h>
+#include <grub/machine/console.h>
+#include <grub/time.h>
+#include <grub/cpu/io.h>
+#include <grub/misc.h>
+#include <grub/term.h>
+#include <grub/usb.h>
+#include <grub/dl.h>
+#include <grub/time.h>
+
+\f
+static char keyboard_map[128] =
+  {
+    '\0', '\0', '\0', '\0', 'a', 'b', 'c', 'd',
+    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+    'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+    'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
+    '3', '4', '5', '6', '7', '8', '9', '0',
+    '\n', GRUB_TERM_ESC, GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, ' ', '-', '=', '[',
+    ']', '\\', '#', ';', '\'', '`', ',', '.',
+    '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+    '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+    '\0', '\0', GRUB_TERM_HOME, GRUB_TERM_PPAGE, GRUB_TERM_DC, GRUB_TERM_END, GRUB_TERM_NPAGE, GRUB_TERM_RIGHT,
+    GRUB_TERM_LEFT, GRUB_TERM_DOWN, GRUB_TERM_UP
+  };
+
+static char keyboard_map_shift[128] =
+  {
+    '\0', '\0', '\0', '\0', 'A', 'B', 'C', 'D',
+    'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+    'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+    'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@',
+    '#', '$', '%', '^', '&', '*', '(', ')',
+    '\n', '\0', '\0', '\0', ' ', '_', '+', '{',
+    '}', '|', '#', ':', '"', '`', '<', '>',
+    '?'
+  };
+
+static grub_usb_device_t usbdev;
+
+static void
+grub_usb_hid (void)
+{
+  struct grub_usb_desc_device *descdev;
+
+  auto int usb_iterate (grub_usb_device_t dev);
+  int usb_iterate (grub_usb_device_t dev)
+    {
+      descdev = &dev->descdev;
+      
+      grub_dprintf ("usb_keyboard", "%x %x %x\n",
+                  descdev->class, descdev->subclass, descdev->protocol);
+
+#if 0
+      if (descdev->class != 0x09
+         || descdev->subclass == 0x01
+         || descdev->protocol != 0x02)
+       return 0;
+#endif
+
+      if (descdev->class != 0 || descdev->subclass != 0 || descdev->protocol != 0)
+       return 0;
+
+      grub_printf ("HID found!\n");
+
+      usbdev = dev;
+
+      return 1;
+    }
+  grub_usb_iterate (usb_iterate);
+
+  /* Place the device in boot mode.  */
+  grub_usb_control_msg (usbdev, 0x21, 0x0B, 0, 0, 0, 0);
+
+  /* Reports everytime an event occurs and not more often than that.  */
+  grub_usb_control_msg (usbdev, 0x21, 0x0A, 0<<8, 0, 0, 0);
+}
+
+static grub_err_t
+grub_usb_keyboard_getreport (grub_usb_device_t dev, unsigned char *report)
+{
+  return grub_usb_control_msg (dev, (1 << 7) | (1 << 5) | 1, 0x01, 0, 0,
+                              8, (char *) report);
+}
+
+\f
+
+static int
+grub_usb_keyboard_checkkey (void)
+{
+  unsigned char data[8];
+  int key;
+  int i;
+  grub_err_t err;
+
+  data[2] = 0;
+  for (i = 0; i < 50; i++)
+    {
+      /* Get_Report.  */
+      err = grub_usb_keyboard_getreport (usbdev, data);
+
+      if (! err && data[2])
+       break;
+    }
+
+  if (err || !data[2])
+    return -1;
+
+  grub_dprintf ("usb_keyboard",
+               "report: 0x%02x 0x%02x 0x%02x 0x%02x"
+               " 0x%02x 0x%02x 0x%02x 0x%02x\n",
+               data[0], data[1], data[2], data[3],
+               data[4], data[5], data[6], data[7]);
+
+  /* Check if the Control or Shift key was pressed.  */
+  if (data[0] & 0x01 || data[0] & 0x10)
+    key = keyboard_map[data[2]] - 'a' + 1;
+  else if (data[0] & 0x02 || data[0] & 0x20)
+    key = keyboard_map_shift[data[2]];
+  else
+    key = keyboard_map[data[2]];
+
+  if (key == 0)
+    grub_printf ("Unknown key 0x%x detected\n", data[2]);
+
+#if 0
+  /* Wait until the key is released.  */
+  while (!err && data[2])
+    {
+      err = grub_usb_control_msg (usbdev, (1 << 7) | (1 << 5) | 1, 0x01, 0, 0,
+                                 sizeof (data), (char *) data);
+      grub_dprintf ("usb_keyboard",
+                   "report2: 0x%02x 0x%02x 0x%02x 0x%02x"
+                   " 0x%02x 0x%02x 0x%02x 0x%02x\n",
+                   data[0], data[1], data[2], data[3],
+                   data[4], data[5], data[6], data[7]);
+    }
+#endif
+
+  grub_errno = GRUB_ERR_NONE;
+
+  return key;
+}
+
+typedef enum
+{
+  GRUB_HIDBOOT_REPEAT_NONE,
+  GRUB_HIDBOOT_REPEAT_FIRST,
+  GRUB_HIDBOOT_REPEAT
+} grub_usb_keyboard_repeat_t;
+
+static int
+grub_usb_keyboard_getkey (void)
+{
+  int key;
+  int key_release;
+  grub_err_t err;
+  unsigned char data[8];
+  grub_uint64_t currtime;
+  int timeout;
+  static grub_usb_keyboard_repeat_t repeat = GRUB_HIDBOOT_REPEAT_NONE;
+
+ again:
+
+  do
+    {
+      key = grub_usb_keyboard_checkkey ();
+    } while (key == -1);
+
+  data[2] = !0; /* Or whatever.  */
+  err = 0;
+
+  switch (repeat)
+    {
+    case GRUB_HIDBOOT_REPEAT_NONE:
+      timeout = 100;
+      break;
+    case GRUB_HIDBOOT_REPEAT_FIRST:
+      timeout = 500;
+      break;
+    case GRUB_HIDBOOT_REPEAT:
+      timeout = 50;
+      break;
+    }
+
+  /* Wait until the key is released.  */
+  currtime = grub_get_time_ms ();
+  while (!err && data[2])
+    {
+      /* Implement a timeout.  */
+      if (grub_get_time_ms () > currtime + timeout)
+       {
+         if (repeat == 0)
+           repeat = 1;
+         else
+           repeat = 2;
+
+         grub_errno = GRUB_ERR_NONE;
+         return key;
+       }
+
+      err = grub_usb_keyboard_getreport (usbdev, data);
+    }
+
+  if (repeat)
+    {
+      repeat = 0;
+      goto again;
+    }
+
+  repeat = 0;
+
+  grub_errno = GRUB_ERR_NONE;
+
+  return key;
+}
+
+static struct grub_term_input grub_usb_keyboard_term =
+  {
+    .name = "usb_keyboard",
+    .checkkey = grub_usb_keyboard_checkkey,
+    .getkey = grub_usb_keyboard_getkey,
+    .next = 0
+  };
+
+GRUB_MOD_INIT(usb_keyboard)
+{
+  (void) mod;                  /* To stop warning. */
+
+  grub_usb_hid ();
+  grub_term_register_input (&grub_usb_keyboard_term);
+}
+
+GRUB_MOD_FINI(usb_keyboard)
+{
+  grub_term_unregister_input (&grub_usb_keyboard_term);
+}
diff --git a/util/console.c b/util/console.c
new file mode 100644 (file)
index 0000000..718afc1
--- /dev/null
@@ -0,0 +1,387 @@
+/*  console.c -- Ncurses console for GRUB.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2005,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/>.
+ */
+
+#include <config.h>
+
+#if defined(HAVE_NCURSES_CURSES_H)
+# include <ncurses/curses.h>
+#elif defined(HAVE_NCURSES_H)
+# include <ncurses.h>
+#elif defined(HAVE_CURSES_H)
+# include <curses.h>
+#endif
+
+/* For compatibility.  */
+#ifndef A_NORMAL
+# define A_NORMAL      0
+#endif /* ! A_NORMAL */
+#ifndef A_STANDOUT
+# define A_STANDOUT    0
+#endif /* ! A_STANDOUT */
+
+#include <grub/machine/console.h>
+#include <grub/term.h>
+#include <grub/types.h>
+
+static int grub_console_attr = A_NORMAL;
+
+grub_uint8_t grub_console_cur_color = 7;
+
+static grub_uint8_t grub_console_standard_color = 0x7;
+static grub_uint8_t grub_console_normal_color = 0x7;
+static grub_uint8_t grub_console_highlight_color = 0x70;
+
+#define NUM_COLORS     8
+
+static grub_uint8_t color_map[NUM_COLORS] =
+{
+  COLOR_BLACK,
+  COLOR_BLUE,
+  COLOR_GREEN,
+  COLOR_CYAN,
+  COLOR_RED,
+  COLOR_MAGENTA,
+  COLOR_YELLOW,
+  COLOR_WHITE
+};
+
+static int use_color;
+
+static void
+grub_ncurses_putchar (grub_uint32_t c)
+{
+  /* Better than nothing.  */
+  switch (c)
+    {
+    case GRUB_TERM_DISP_LEFT:
+      c = '<';
+      break;
+
+    case GRUB_TERM_DISP_UP:
+      c = '^';
+      break;
+
+    case GRUB_TERM_DISP_RIGHT:
+      c = '>';
+      break;
+
+    case GRUB_TERM_DISP_DOWN:
+      c = 'v';
+      break;
+
+    case GRUB_TERM_DISP_HLINE:
+      c = '-';
+      break;
+
+    case GRUB_TERM_DISP_VLINE:
+      c = '|';
+      break;
+
+    case GRUB_TERM_DISP_UL:
+    case GRUB_TERM_DISP_UR:
+    case GRUB_TERM_DISP_LL:
+    case GRUB_TERM_DISP_LR:
+      c = '+';
+      break;
+
+    default:
+      /* ncurses does not support Unicode.  */
+      if (c > 0x7f)
+       c = '?';
+      break;
+    }
+  
+  addch (c | grub_console_attr);
+}
+
+static grub_ssize_t
+grub_ncurses_getcharwidth (grub_uint32_t code __attribute__ ((unused)))
+{
+  return 1;
+}
+
+static void
+grub_ncurses_setcolorstate (grub_term_color_state state)
+{
+  switch (state) 
+    {
+    case GRUB_TERM_COLOR_STANDARD:
+      grub_console_cur_color = grub_console_standard_color;
+      grub_console_attr = A_NORMAL;
+      break;
+    case GRUB_TERM_COLOR_NORMAL:
+      grub_console_cur_color = grub_console_normal_color;
+      grub_console_attr = A_NORMAL;
+      break;
+    case GRUB_TERM_COLOR_HIGHLIGHT:
+      grub_console_cur_color = grub_console_highlight_color;
+      grub_console_attr = A_STANDOUT;
+      break;
+    default:
+      break;
+    }
+
+  if (use_color)
+    {
+      grub_uint8_t fg, bg;
+
+      fg = (grub_console_cur_color & 7);
+      bg = (grub_console_cur_color >> 4) & 7;
+
+      grub_console_attr = (grub_console_cur_color & 8) ? A_BOLD : A_NORMAL;
+      color_set ((bg << 3) + fg, 0);
+    }
+}
+
+/* XXX: This function is never called.  */
+static void
+grub_ncurses_setcolor (grub_uint8_t normal_color, grub_uint8_t highlight_color)
+{
+  grub_console_normal_color = normal_color;
+  grub_console_highlight_color = highlight_color;
+}
+
+static void
+grub_ncurses_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_color)
+{
+  *normal_color = grub_console_normal_color;
+  *highlight_color = grub_console_highlight_color;
+}
+
+static int saved_char = ERR;
+
+static int
+grub_ncurses_checkkey (void)
+{
+  int c;
+  
+  /* Check for SAVED_CHAR. This should not be true, because this
+     means checkkey is called twice continuously.  */
+  if (saved_char != ERR)
+    return saved_char;
+  
+  wtimeout (stdscr, 100);
+  c = getch ();
+  /* If C is not ERR, then put it back in the input queue.  */
+  if (c != ERR)
+    {
+      saved_char = c;
+      return c;
+    }
+
+  return -1;
+}
+
+static int
+grub_ncurses_getkey (void)
+{
+  int c;
+  
+  /* If checkkey has already got a character, then return it.  */
+  if (saved_char != ERR)
+    {
+      c = saved_char;
+      saved_char = ERR;
+    }
+  else
+    {
+      wtimeout (stdscr, -1);
+      c = getch ();
+    }
+
+  switch (c)
+    {
+    case KEY_LEFT:
+      c = 2;
+      break;
+
+    case KEY_RIGHT:
+      c = 6;
+      break;
+      
+    case KEY_UP:
+      c = 16;
+      break;
+
+    case KEY_DOWN:
+      c = 14;
+      break;
+
+    case KEY_IC:
+      c = 24;
+      break;
+
+    case KEY_DC:
+      c = 4;
+      break;
+
+    case KEY_BACKSPACE:
+      /* XXX: For some reason ncurses on xterm does not return
+        KEY_BACKSPACE.  */
+    case 127: 
+      c = 8;
+      break;
+
+    case KEY_HOME:
+      c = 1;
+      break;
+
+    case KEY_END:
+      c = 5;
+      break;
+
+    case KEY_NPAGE:
+      c = 3;
+      break;
+
+    case KEY_PPAGE:
+      c = 7;
+      break;
+    }
+
+  return c;
+}
+
+static grub_uint16_t
+grub_ncurses_getxy (void)
+{
+  int x;
+  int y;
+
+  getyx (stdscr, y, x);
+
+  return (x << 8) | y;
+}
+
+static grub_uint16_t
+grub_ncurses_getwh (void)
+{
+  int x;
+  int y;
+
+  getmaxyx (stdscr, y, x);
+
+  return (x << 8) | y;
+}
+
+static void
+grub_ncurses_gotoxy (grub_uint8_t x, grub_uint8_t y)
+{
+  move (y, x);
+}
+
+static void
+grub_ncurses_cls (void)
+{
+  clear ();
+  refresh ();
+}
+
+static void
+grub_ncurses_setcursor (int on)
+{
+  curs_set (on ? 1 : 0);
+}
+
+static void
+grub_ncurses_refresh (void)
+{
+  refresh ();
+}
+
+static grub_err_t
+grub_ncurses_init (void)
+{
+  initscr ();
+  raw ();
+  noecho ();
+  scrollok (stdscr, TRUE);
+
+  nonl ();
+  intrflush (stdscr, FALSE);
+  keypad (stdscr, TRUE);
+
+  if (has_colors ())
+    {
+      start_color ();
+
+      if ((COLORS >= NUM_COLORS) && (COLOR_PAIRS >= NUM_COLORS * NUM_COLORS))
+        {
+          int i, j, n;
+
+          n = 0;
+          for (i = 0; i < NUM_COLORS; i++)
+            for (j = 0; j < NUM_COLORS; j++)
+              init_pair(n++, color_map[j], color_map[i]);
+
+          use_color = 1;
+        }
+    }
+
+  return 0;
+}
+
+static grub_err_t
+grub_ncurses_fini (void)
+{
+  endwin ();
+  return 0;
+}
+
+\f
+static struct grub_term_input grub_ncurses_term_input =
+  {
+    .name = "console",
+    .checkkey = grub_ncurses_checkkey,
+    .getkey = grub_ncurses_getkey,
+  };
+
+static struct grub_term_output grub_ncurses_term_output =
+  {
+    .name = "console",
+    .init = grub_ncurses_init,
+    .fini = grub_ncurses_fini,
+    .putchar = grub_ncurses_putchar,
+    .getcharwidth = grub_ncurses_getcharwidth,
+    .getxy = grub_ncurses_getxy,
+    .getwh = grub_ncurses_getwh,
+    .gotoxy = grub_ncurses_gotoxy,
+    .cls = grub_ncurses_cls,
+    .setcolorstate = grub_ncurses_setcolorstate,
+    .setcolor = grub_ncurses_setcolor,
+    .getcolor = grub_ncurses_getcolor,
+    .setcursor = grub_ncurses_setcursor,
+    .refresh = grub_ncurses_refresh,
+    .flags = 0,
+  };
+
+void
+grub_console_init (void)
+{
+  grub_term_register_output (&grub_ncurses_term_output);
+  grub_term_register_input (&grub_ncurses_term_input);
+  grub_term_set_current_output (&grub_ncurses_term_output);
+  grub_term_set_current_input (&grub_ncurses_term_input);
+}
+
+void
+grub_console_fini (void)
+{
+  grub_ncurses_fini ();
+}
diff --git a/util/elf/grub-mkimage.c b/util/elf/grub-mkimage.c
new file mode 100644 (file)
index 0000000..f841035
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,2005,2006,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/>.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/util/misc.h>
+#include <grub/util/resolve.h>
+#include <grub/kernel.h>
+#include <grub/cpu/kernel.h>
+
+#define GRUB_IEEE1275_NOTE_NAME "PowerPC"
+#define GRUB_IEEE1275_NOTE_TYPE 0x1275
+
+/* These structures are defined according to the CHRP binding to IEEE1275,
+   "Client Program Format" section.  */
+
+struct grub_ieee1275_note_hdr
+{
+  grub_uint32_t namesz;
+  grub_uint32_t descsz;
+  grub_uint32_t type;
+  char name[sizeof (GRUB_IEEE1275_NOTE_NAME)];
+};
+
+struct grub_ieee1275_note_desc
+{
+  grub_uint32_t real_mode;
+  grub_uint32_t real_base;
+  grub_uint32_t real_size;
+  grub_uint32_t virt_base;
+  grub_uint32_t virt_size;
+  grub_uint32_t load_base;
+};
+
+struct grub_ieee1275_note
+{
+  struct grub_ieee1275_note_hdr header;
+  struct grub_ieee1275_note_desc descriptor;
+};
+
+void
+load_note (Elf32_Phdr *phdr, FILE *out)
+{
+  struct grub_ieee1275_note note;
+  int note_size = sizeof (struct grub_ieee1275_note);
+
+  grub_util_info ("adding CHRP NOTE segment");
+
+  note.header.namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME));
+  note.header.descsz = grub_host_to_target32 (note_size);
+  note.header.type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE);
+  strcpy (note.header.name, GRUB_IEEE1275_NOTE_NAME);
+  note.descriptor.real_mode = grub_host_to_target32 (0xffffffff);
+  note.descriptor.real_base = grub_host_to_target32 (0x00c00000);
+  note.descriptor.real_size = grub_host_to_target32 (0xffffffff);
+  note.descriptor.virt_base = grub_host_to_target32 (0xffffffff);
+  note.descriptor.virt_size = grub_host_to_target32 (0xffffffff);
+  note.descriptor.load_base = grub_host_to_target32 (0x00004000);
+
+  /* Write the note data to the new segment.  */
+  grub_util_write_image_at (&note, note_size,
+                           grub_target_to_host32 (phdr->p_offset), out);
+
+  /* Fill in the rest of the segment header.  */
+  phdr->p_type = grub_host_to_target32 (PT_NOTE);
+  phdr->p_flags = grub_host_to_target32 (PF_R);
+  phdr->p_align = grub_host_to_target32 (GRUB_TARGET_SIZEOF_LONG);
+  phdr->p_vaddr = 0;
+  phdr->p_paddr = 0;
+  phdr->p_filesz = grub_host_to_target32 (note_size);
+  phdr->p_memsz = 0;
+}
+
+void
+load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir,
+             char *mods[], FILE *out, char *memdisk_path)
+{
+  char *module_img;
+  struct grub_util_path_list *path_list;
+  struct grub_util_path_list *p;
+  struct grub_module_info *modinfo;
+  size_t offset;
+  size_t total_module_size;
+  size_t memdisk_size = 0;
+
+  path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
+
+  offset = sizeof (struct grub_module_info);
+  total_module_size = sizeof (struct grub_module_info);
+
+  if (memdisk_path)
+    {
+      memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512);
+      grub_util_info ("the size of memory disk is 0x%x", memdisk_size);
+      total_module_size += memdisk_size + sizeof (struct grub_module_header);
+    }
+
+  for (p = path_list; p; p = p->next)
+    {
+      total_module_size += (grub_util_get_image_size (p->name)
+         + sizeof (struct grub_module_header));
+    }
+
+  grub_util_info ("the total module size is 0x%x", total_module_size);
+
+  module_img = xmalloc (total_module_size);
+  modinfo = (struct grub_module_info *) module_img;
+  modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
+  modinfo->offset = grub_host_to_target32 (sizeof (struct grub_module_info));
+  modinfo->size = grub_host_to_target32 (total_module_size);
+
+  /* Load all the modules, with headers, into module_img.  */
+  for (p = path_list; p; p = p->next)
+    {
+      struct grub_module_header *header;
+      size_t mod_size;
+
+      grub_util_info ("adding module %s", p->name);
+
+      mod_size = grub_util_get_image_size (p->name);
+
+      header = (struct grub_module_header *) (module_img + offset);
+      header->type = grub_host_to_target32 (OBJ_TYPE_ELF);
+      header->size = grub_host_to_target32 (mod_size + sizeof (*header));
+
+      grub_util_load_image (p->name, module_img + offset + sizeof (*header));
+
+      offset += sizeof (*header) + mod_size;
+    }
+
+  if (memdisk_path)
+    {
+      struct grub_module_header *header;
+
+      header = (struct grub_module_header *) (module_img + offset);
+      header->type = grub_cpu_to_le32 (OBJ_TYPE_MEMDISK);
+      header->size = grub_cpu_to_le32 (memdisk_size + sizeof (*header));
+      offset += sizeof (*header);
+
+      grub_util_load_image (memdisk_path, module_img + offset);
+      offset += memdisk_size;
+    }
+
+
+  /* Write the module data to the new segment.  */
+  grub_util_write_image_at (module_img, total_module_size,
+                           grub_host_to_target32 (phdr->p_offset), out);
+
+  /* Fill in the rest of the segment header.  */
+  phdr->p_type = grub_host_to_target32 (PT_LOAD);
+  phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
+  phdr->p_align = grub_host_to_target32 (GRUB_TARGET_SIZEOF_LONG);
+  phdr->p_vaddr = grub_host_to_target32 (modbase);
+  phdr->p_paddr = grub_host_to_target32 (modbase);
+  phdr->p_filesz = grub_host_to_target32 (total_module_size);
+  phdr->p_memsz = grub_host_to_target32 (total_module_size);
+}
+
+void
+add_segments (char *dir, char *prefix, FILE *out, int chrp, char *mods[], char *memdisk_path)
+{
+  Elf32_Ehdr ehdr;
+  Elf32_Phdr *phdrs = NULL;
+  Elf32_Phdr *phdr;
+  FILE *in;
+  char *kernel_path;
+  grub_addr_t grub_end = 0;
+  off_t offset, first_segment;
+  int i, phdr_size;
+
+  /* Read ELF header.  */
+  kernel_path = grub_util_get_path (dir, "kernel.elf");
+  in = fopen (kernel_path, "rb");
+  if (! in)
+    grub_util_error ("cannot open %s", kernel_path);
+
+  grub_util_read_at (&ehdr, sizeof (ehdr), 0, in);
+
+  offset = ALIGN_UP (sizeof (ehdr), GRUB_TARGET_SIZEOF_LONG);
+  ehdr.e_phoff = grub_host_to_target32 (offset);
+
+  phdr_size = (grub_target_to_host16 (ehdr.e_phentsize) *
+               grub_target_to_host16 (ehdr.e_phnum));
+
+  if (mods[0] != NULL)
+    phdr_size += grub_target_to_host16 (ehdr.e_phentsize);
+
+  if (chrp)
+    phdr_size += grub_target_to_host16 (ehdr.e_phentsize);
+
+  phdrs = xmalloc (phdr_size);
+  offset += ALIGN_UP (phdr_size, GRUB_TARGET_SIZEOF_LONG);
+
+  first_segment = offset;
+
+  /* Copy all existing segments.  */
+  for (i = 0; i < grub_target_to_host16 (ehdr.e_phnum); i++)
+    {
+      char *segment_img;
+      grub_size_t segment_end;
+
+      phdr = phdrs + i;
+
+      /* Read segment header.  */
+      grub_util_read_at (phdr, sizeof (Elf32_Phdr),
+                        (grub_target_to_host32 (ehdr.e_phoff)
+                         + (i * grub_target_to_host16 (ehdr.e_phentsize))),
+                        in);
+      grub_util_info ("copying segment %d, type %d", i,
+                     grub_target_to_host32 (phdr->p_type));
+
+      /* Locate _end.  */
+      segment_end = grub_target_to_host32 (phdr->p_paddr)
+                   + grub_target_to_host32 (phdr->p_memsz);
+      grub_util_info ("segment %u end 0x%lx", i, segment_end);
+      if (segment_end > grub_end)
+       grub_end = segment_end;
+
+      /* Read segment data and write it to new file.  */
+      segment_img = xmalloc (grub_target_to_host32 (phdr->p_filesz));
+
+      grub_util_read_at (segment_img, grub_target_to_host32 (phdr->p_filesz),
+                        grub_target_to_host32 (phdr->p_offset), in);
+
+      phdr->p_offset = grub_host_to_target32 (offset);
+      grub_util_write_image_at (segment_img, grub_target_to_host32 (phdr->p_filesz),
+                               offset, out);
+      offset += ALIGN_UP (grub_target_to_host32 (phdr->p_filesz),
+                         GRUB_TARGET_SIZEOF_LONG);
+
+      free (segment_img);
+    }
+
+  if (mods[0] != NULL)
+    {
+      grub_addr_t modbase;
+
+      /* Place modules just after grub segment.  */
+      modbase = ALIGN_UP(grub_end + GRUB_MOD_GAP, GRUB_MOD_ALIGN);
+
+      /* Construct new segment header for modules.  */
+      phdr = phdrs + grub_target_to_host16 (ehdr.e_phnum);
+      ehdr.e_phnum = grub_host_to_target16 (grub_target_to_host16 (ehdr.e_phnum) + 1);
+
+      /* Fill in p_offset so the callees know where to write.  */
+      phdr->p_offset = grub_host_to_target32 (ALIGN_UP (grub_util_get_fp_size (out),
+                                                       GRUB_TARGET_SIZEOF_LONG));
+
+      load_modules (modbase, phdr, dir, mods, out, memdisk_path);
+    }
+
+  if (chrp)
+    {
+      /* Construct new segment header for the CHRP note.  */
+      phdr = phdrs + grub_target_to_host16 (ehdr.e_phnum);
+      ehdr.e_phnum = grub_host_to_target16 (grub_target_to_host16 (ehdr.e_phnum) + 1);
+
+      /* Fill in p_offset so the callees know where to write.  */
+      phdr->p_offset = grub_host_to_target32 (ALIGN_UP (grub_util_get_fp_size (out),
+                                                       GRUB_TARGET_SIZEOF_LONG));
+
+      load_note (phdr, out);
+    }
+
+  /* Don't bother preserving the section headers.  */
+  ehdr.e_shoff = 0;
+  ehdr.e_shnum = 0;
+  ehdr.e_shstrndx = 0;
+
+  /* Write entire segment table to the file.  */
+  grub_util_write_image_at (phdrs, phdr_size, grub_target_to_host32 (ehdr.e_phoff), out);
+
+  /* Write ELF header.  */
+  grub_util_write_image_at (&ehdr, sizeof (ehdr), 0, out);
+
+  if (prefix)
+    {
+      if (GRUB_KERNEL_CPU_PREFIX + strlen (prefix) + 1 > GRUB_KERNEL_CPU_DATA_END)
+        grub_util_error ("prefix too long");
+      grub_util_write_image_at (prefix, strlen (prefix) + 1, first_segment + GRUB_KERNEL_CPU_PREFIX, out);
+    }
+
+  free (phdrs);
+  free (kernel_path);
+}
+
+static struct option options[] =
+  {
+    {"directory", required_argument, 0, 'd'},
+    {"prefix", required_argument, 0, 'p'},
+    {"memdisk", required_argument, 0, 'm'},
+    {"output", required_argument, 0, 'o'},
+    {"help", no_argument, 0, 'h'},
+    {"note", no_argument, 0, 'n'},
+    {"version", no_argument, 0, 'V'},
+    {"verbose", no_argument, 0, 'v'},
+    { 0, 0, 0, 0 },
+  };
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr, "Try ``grub-mkimage --help'' for more information.\n");
+  else
+    printf ("\
+Usage: grub-mkimage -o FILE [OPTION]... [MODULES]\n\
+\n\
+Make a bootable image of GRUB.\n\
+\n\
+-d, --directory=DIR     use images and modules under DIR [default=%s]\n\
+-p, --prefix=DIR        set grub_prefix directory\n\
+-m, --memdisk=FILE      embed FILE as a memdisk image\n\
+-o, --output=FILE       output a generated image to FILE\n\
+-h, --help              display this message and exit\n\
+-n, --note              add NOTE segment for CHRP Open Firmware\n\
+-V, --version           print version information and exit\n\
+-v, --verbose           print verbose messages\n\
+\n\
+Report bugs to <%s>.\n\
+", GRUB_LIBDIR, PACKAGE_BUGREPORT);
+
+  exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+  FILE *fp;
+  char *output = NULL;
+  char *dir = NULL;
+  char *prefix = NULL;
+  char *memdisk = NULL;
+  int chrp = 0;
+
+  progname = "grub-mkimage";
+
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "d:p:m:o:hVvn", options, 0);
+      if (c == -1)
+       break;
+
+      switch (c)
+       {
+         case 'd':
+           if (dir)
+             free (dir);
+           dir = xstrdup (optarg);
+           break;
+         case 'p':
+           if (prefix)
+             free (prefix);
+           prefix = xstrdup (optarg);
+           break;
+         case 'm':
+           if (memdisk)
+             free (memdisk);
+           memdisk = xstrdup (optarg);
+
+           if (prefix)
+             free (prefix);
+           prefix = xstrdup ("(memdisk)/boot/grub");
+
+           break;
+         case 'h':
+           usage (0);
+           break;
+         case 'n':
+           chrp = 1;
+           break;
+         case 'o':
+           if (output)
+             free (output);
+           output = xstrdup (optarg);
+           break;
+         case 'V':
+           printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+           return 0;
+         case 'v':
+           verbosity++;
+           break;
+         default:
+           usage (1);
+           break;
+       }
+  }
+
+  if (!output)
+    usage (1);
+
+  fp = fopen (output, "wb");
+  if (! fp)
+    grub_util_error ("cannot open %s", output);
+
+  add_segments (dir ? : GRUB_LIBDIR, prefix, fp, chrp, argv + optind, memdisk);
+
+  fclose (fp);
+
+  return 0;
+}
diff --git a/util/getroot.c b/util/getroot.c
new file mode 100644 (file)
index 0000000..e88354e
--- /dev/null
@@ -0,0 +1,521 @@
+/* getroot.c - Get root device */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2006,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/>.
+ */
+
+#include <config.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+
+#ifdef __CYGWIN__
+# include <sys/fcntl.h>
+# include <sys/cygwin.h>
+# include <limits.h>
+# define DEV_CYGDRIVE_MAJOR 98
+#endif
+
+#include <grub/util/misc.h>
+#include <grub/util/hostdisk.h>
+#include <grub/util/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 __CYGWIN__
+/* Convert POSIX path to Win32 path,
+   remove drive letter, replace backslashes.  */
+static char *
+get_win32_path (const char *path)
+{
+  char winpath[PATH_MAX];
+  cygwin_conv_to_full_win32_path (path, winpath);
+
+  int len = strlen (winpath);
+  if (len > 2 && winpath[1] == ':')
+    {
+      len -= 2;
+      memmove (winpath, winpath + 2, len + 1);
+    }
+
+  int i;
+  for (i = 0; i < len; i++)
+    if (winpath[i] == '\\')
+      winpath[i] = '/';
+  return xstrdup (winpath);
+}
+#endif
+
+char *
+grub_get_prefix (const char *dir)
+{
+  char *saved_cwd;
+  char *abs_dir, *prev_dir;
+  char *prefix;
+  struct stat st, prev_st;
+  
+  /* Save the current directory.  */
+  saved_cwd = xgetcwd ();
+
+  if (chdir (dir) < 0)
+    grub_util_error ("Cannot change directory to `%s'", dir);
+
+  abs_dir = xgetcwd ();
+  strip_extra_slashes (abs_dir);
+  prev_dir = xstrdup (abs_dir);
+  
+  if (stat (".", &prev_st) < 0)
+    grub_util_error ("Cannot stat `%s'", dir);
+
+  if (! S_ISDIR (prev_st.st_mode))
+    grub_util_error ("`%s' is not a directory", dir);
+
+  while (1)
+    {
+      if (chdir ("..") < 0)
+       grub_util_error ("Cannot change directory to the parent");
+
+      if (stat (".", &st) < 0)
+       grub_util_error ("Cannot stat current directory");
+
+      if (! S_ISDIR (st.st_mode))
+       grub_util_error ("Current directory is not a directory???");
+
+      if (prev_st.st_dev != st.st_dev || prev_st.st_ino == st.st_ino)
+       break;
+
+      free (prev_dir);
+      prev_dir = xgetcwd ();
+      prev_st = st;
+    }
+
+  strip_extra_slashes (prev_dir);
+  prefix = xmalloc (strlen (abs_dir) - strlen (prev_dir) + 2);
+  prefix[0] = '/';
+  strcpy (prefix + 1, abs_dir + strlen (prev_dir));
+  strip_extra_slashes (prefix);
+
+  if (chdir (saved_cwd) < 0)
+    grub_util_error ("Cannot change directory to `%s'", dir);
+
+#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 prefix = %s", prefix);
+      char * wprefix = get_win32_path (prefix);
+      free (prefix);
+      prefix = wprefix;
+    }
+#endif
+
+  free (saved_cwd);
+  free (abs_dir);
+  free (prev_dir);
+
+  grub_util_info ("prefix = %s", prefix);
+  return prefix;
+}
+
+#ifdef __MINGW32__
+
+static char *
+find_root_device (const char *dir __attribute__ ((unused)),
+                  dev_t dev __attribute__ ((unused)))
+{
+  return 0;
+}
+
+#elif ! defined(__CYGWIN__)
+
+static char *
+find_root_device (const char *dir, dev_t dev)
+{
+  DIR *dp;
+  char *saved_cwd;
+  struct dirent *ent;
+  
+  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))
+       /* Don't follow symbolic links.  */
+       continue;
+      
+      if (S_ISDIR (st.st_mode))
+       {
+         /* Find it recursively.  */
+         char *res;
+
+         res = find_root_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 (S_ISBLK (st.st_mode) && st.st_rdev == dev)
+       {
+#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;
+
+         cwd = xgetcwd ();
+         res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 2);
+         sprintf (res, "%s/%s", 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;
+}
+
+static char *
+find_cygwin_root_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 find_root_device () does not work.
+     Search the partion 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)
+{
+  struct stat st;
+  char *os_dev;
+  
+  if (stat (dir, &st) < 0)
+    grub_util_error ("Cannot stat `%s'", dir);
+
+#ifdef __CYGWIN__
+  /* Cygwin specific function.  */
+  os_dev = find_cygwin_root_device (dir, st.st_dev);
+
+#else
+
+  /* This might be truly slow, but is there any better way?  */
+  os_dev = find_root_device ("/dev", st.st_dev);
+#endif
+
+  return os_dev;
+}
+
+int
+grub_util_get_dev_abstraction (const char *os_dev)
+{
+#ifdef __linux__
+  /* Check for LVM.  */
+  if (!strncmp (os_dev, "/dev/mapper/", 12))
+    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;
+}
+
+char *
+grub_util_get_grub_dev (const char *os_dev)
+{
+  char *grub_dev;
+
+  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 = ',';
+
+         asprintf (&grub_dev, "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 = ',';
+
+         asprintf (&grub_dev, "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 = ',';
+
+         asprintf (&grub_dev, "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 = ',';
+
+         asprintf (&grub_dev, "md%s", p);
+         free (p);
+       }
+      else
+       grub_util_error ("Unknown kind of RAID device `%s'", os_dev);
+      
+      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;
+}
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
new file mode 100644 (file)
index 0000000..475d12d
--- /dev/null
@@ -0,0 +1,269 @@
+/* grub-editenv.c - tool to edit environment block.  */
+/*
+ *  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/types.h>
+#include <grub/util/misc.h>
+#include <grub/lib/envblk.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+void
+grub_putchar (int c)
+{
+  putchar (c);
+}
+
+void
+grub_refresh (void)
+{
+  fflush (stdout);
+}
+
+void *
+grub_term_get_current_input (void)
+{
+  return 0;
+}
+
+void *
+grub_term_get_current_output (void)
+{
+  return 0;
+}
+
+int
+grub_getkey (void)
+{
+  return 0;
+}
+
+char *
+grub_env_get (const char *name __attribute__ ((unused)))
+{
+  return NULL;
+}
+
+static struct option options[] = {
+  {"help", no_argument, 0, 'h'},
+  {"version", no_argument, 0, 'V'},
+  {"verbose", no_argument, 0, 'v'},
+  {0, 0, 0, 0}
+};
+
+char buffer[GRUB_ENVBLK_MAXLEN];
+grub_envblk_t envblk;
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr, "Try ``grub-editenv --help'' for more information.\n");
+  else
+    printf ("\
+Usage: grub-editenv [OPTIONS] FILENAME COMMAND\n\
+\n\
+Tool to edit environment block.\n\
+\nCommands:\n\
+  create                    create a blank environment block file\n\
+  info                      show information about the environment block\n\
+  list                      list the current variables\n\
+  set [name=value] ...      change/delete variables\n\
+  clear                     delete all variables\n\
+\nOptions:\n\
+  -h, --help                display this message and exit\n\
+  -V, --version             print version information and exit\n\
+  -v, --verbose             print verbose messages\n\
+\n\
+Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
+
+  exit (status);
+}
+
+int
+create_envblk_file (char *name)
+{
+  FILE *f;
+  grub_envblk_t p;
+
+  f = fopen (name, "wb");
+  if (! f)
+    return 1;
+
+  /* Just in case OS don't save 0s.  */
+  memset (buffer, -1, sizeof (buffer));
+
+  p = (grub_envblk_t) &buffer[0];
+  p->signature = GRUB_ENVBLK_SIGNATURE;
+  p->length = sizeof (buffer) - sizeof (struct grub_envblk);
+  p->data[0] = p->data[1] = 0;
+
+  fwrite (buffer, sizeof (buffer), 1, f);
+
+  fclose (f);
+  return 0;
+}
+
+FILE *
+open_envblk_file (char *name)
+{
+  FILE *f;
+
+  f = fopen (name, "r+b");
+  if (! f)
+    grub_util_error ("Can\'t open file %s", name);
+
+  if (fread (buffer, 1, sizeof (buffer), f) != sizeof (buffer))
+    grub_util_error ("The envblk file is too short");
+
+  envblk = grub_envblk_find (buffer);
+  if (! envblk)
+    grub_util_error ("Can\'t find environment block");
+
+  return f;
+}
+
+static void
+cmd_info (void)
+{
+  printf ("Envblk offset: %ld\n", (long) (envblk->data - buffer));
+  printf ("Envblk length: %d\n", envblk->length);
+}
+
+static void
+cmd_list (void)
+{
+  auto int hook (char *name, char *value);
+  int hook (char *name, char *value)
+    {
+      printf ("%s=%s\n", name, value);
+      return 0;
+    }
+
+  grub_envblk_iterate (envblk, hook);
+}
+
+static void
+cmd_set (int argc, char *argv[])
+{
+  while (argc)
+    {
+      char *p;
+
+      p = strchr (argv[0], '=');
+      if (! p)
+        grub_util_error ("Invalid parameter");
+
+      *(p++) = 0;
+
+      if (*p)
+        {
+          if (grub_envblk_insert (envblk, argv[0], p))
+            grub_util_error ("Environment block too small");
+        }
+      else
+        grub_envblk_delete (envblk, argv[0]);
+
+      argc--;
+      argv++;
+    }
+}
+
+static void
+cmd_clear (void)
+{
+  envblk->data[0] = envblk->data[1] = 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+  FILE *f;
+
+  progname = "grub-editenv";
+
+  /* Check for options.  */
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "hVv", options, 0);
+
+      if (c == -1)
+       break;
+      else
+       switch (c)
+         {
+         case 'h':
+           usage (0);
+           break;
+
+         case 'V':
+           printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
+           return 0;
+
+         case 'v':
+           verbosity++;
+           break;
+
+         default:
+           usage (1);
+           break;
+         }
+    }
+
+  /* Obtain PATH.  */
+  if (optind >= argc)
+    {
+      fprintf (stderr, "Filename not specified.\n");
+      usage (1);
+    }
+
+  if (optind + 1 >= argc)
+    {
+      fprintf (stderr, "Command not specified.\n");
+      usage (1);
+    }
+
+  if (! strcmp (argv[optind + 1], "create"))
+    return create_envblk_file (argv[optind]);
+
+  f = open_envblk_file (argv[optind]);
+
+  optind++;
+  if (! strcmp (argv[optind], "info"))
+    cmd_info ();
+  else if (! strcmp (argv[optind], "list"))
+    cmd_list ();
+  else
+    {
+      if (! strcmp (argv[optind], "set"))
+        cmd_set (argc - optind - 1, argv + optind + 1);
+      else if (! strcmp (argv[optind], "clear"))
+        cmd_clear ();
+
+      fseeko (f, 0, SEEK_SET);
+      fwrite (buffer, sizeof (buffer), 1, f);
+    }
+  fclose (f);
+
+  return 0;
+}
diff --git a/util/grub-emu.c b/util/grub-emu.c
new file mode 100644 (file)
index 0000000..59392fe
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,2006,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/>.
+ */
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <getopt.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <grub/mm.h>
+#include <grub/setjmp.h>
+#include <grub/fs.h>
+#include <grub/util/hostdisk.h>
+#include <grub/dl.h>
+#include <grub/machine/console.h>
+#include <grub/util/misc.h>
+#include <grub/kernel.h>
+#include <grub/normal.h>
+#include <grub/util/getroot.h>
+#include <grub/env.h>
+#include <grub/partition.h>
+
+#include <grub_emu_init.h>
+
+/* Used for going back to the main function.  */
+jmp_buf main_env;
+
+/* Store the prefix specified by an argument.  */
+static char *prefix = 0;
+
+grub_addr_t
+grub_arch_modules_addr (void)
+{
+  return 0;
+}
+
+grub_err_t
+grub_arch_dl_check_header (void *ehdr)
+{
+  (void) ehdr;
+
+  return GRUB_ERR_BAD_MODULE;
+}
+
+grub_err_t
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
+{
+  (void) mod;
+  (void) ehdr;
+
+  return GRUB_ERR_BAD_MODULE;
+}
+
+void
+grub_machine_init (void)
+{
+}
+
+void
+grub_machine_set_prefix (void)
+{
+  grub_env_set ("prefix", prefix);
+  free (prefix);
+  prefix = 0;
+}
+
+void
+grub_machine_fini (void)
+{
+  grub_console_fini ();
+}
+\f
+
+static struct option options[] =
+  {
+    {"root-device", required_argument, 0, 'r'},
+    {"device-map", required_argument, 0, 'm'},
+    {"directory", required_argument, 0, 'd'},
+    {"hold", optional_argument, 0, 'H'},
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+    {"verbose", no_argument, 0, 'v'},
+    { 0, 0, 0, 0 }
+  };
+
+static int 
+usage (int status)
+{
+  if (status)
+    fprintf (stderr,
+            "Try ``grub-emu --help'' for more information.\n");
+  else
+    printf (
+      "Usage: grub-emu [OPTION]...\n"
+      "\n"
+      "GRUB emulator.\n"
+      "\n"
+      "  -r, --root-device=DEV     use DEV as the root device [default=guessed]\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"
+      "  -H, --hold[=SECONDS]      wait until a debugger will attach\n"
+      "  -h, --help                display this message and exit\n"
+      "  -V, --version             print version information and exit\n"
+      "\n"
+      "Report bugs to <%s>.\n", DEFAULT_DEVICE_MAP, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT);
+  return status;
+}
+\f
+
+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;
+  
+  progname = "grub-emu";
+
+  while ((opt = getopt_long (argc, argv, "r:d:m:vH:hV", options, 0)) != -1)
+    switch (opt)
+      {
+      case 'r':
+        root_dev = optarg;
+        break;
+      case 'd':
+        dir = optarg;
+        break;
+      case 'm':
+        dev_map = optarg;
+        break;
+      case 'v':
+        verbosity++;
+        break;
+      case 'H':
+        hold = (optarg ? atoi (optarg) : -1);
+        break;
+      case 'h':
+        return usage (0);
+      case 'V':
+        printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
+        return 0;
+      default:
+        return usage (1);
+      }
+
+  if (optind < argc)
+    {
+      fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind]);
+      return usage (1);
+    }
+
+  /* Wait until the ARGS.HOLD variable is cleared by an attached debugger. */
+  if (hold && verbosity > 0)
+    printf ("Run \"gdb %s %d\", and set ARGS.HOLD to zero.\n",
+            progname, (int) getpid ());
+  while (hold)
+    {
+      if (hold > 0)
+        hold--;
+
+      sleep (1);
+    }
+  
+  signal (SIGINT, SIG_IGN);
+  grub_console_init ();
+
+  /* XXX: This is a bit unportable.  */
+  grub_util_biosdisk_init (dev_map);
+
+#if HAVE_USB_H
+  grub_libusb_init ();
+#endif
+
+  grub_init_all ();
+
+  /* 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.\n", 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''.");
+       }
+    }
+
+  dir = grub_get_prefix (dir);
+  prefix = xmalloc (strlen (root_dev) + 2 + strlen (dir) + 1);
+  sprintf (prefix, "(%s)%s", root_dev, dir);
+  free (dir);
+  
+  /* Start GRUB!  */
+  if (setjmp (main_env) == 0)
+    grub_main ();
+
+  grub_fini_all ();
+
+  grub_machine_fini ();
+  
+  return 0;
+}
diff --git a/util/grub-fstest.c b/util/grub-fstest.c
new file mode 100644 (file)
index 0000000..ca25425
--- /dev/null
@@ -0,0 +1,622 @@
+/* grub-fstest.c - debug tool for filesystem driver */
+/*
+ *  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/types.h>
+#include <grub/util/misc.h>
+#include <grub/misc.h>
+#include <grub/device.h>
+#include <grub/disk.h>
+#include <grub/file.h>
+#include <grub/fs.h>
+#include <grub/env.h>
+#include <grub/term.h>
+#include <grub/mm.h>
+#include <grub/normal.h>
+#include <grub/raid.h>
+#include <grub/lib/hexdump.h>
+#include <grub/lib/crc.h>
+
+#include <grub_fstest_init.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+void
+grub_putchar (int c)
+{
+  putchar (c);
+}
+
+int
+grub_getkey (void)
+{
+  return -1;
+}
+
+grub_term_input_t
+grub_term_get_current_input (void)
+{
+  return 0;
+}
+
+grub_term_output_t
+grub_term_get_current_output (void)
+{
+  return 0;
+}
+
+void
+grub_refresh (void)
+{
+  fflush (stdout);
+}
+
+static struct grub_command cmd_loopback;
+static struct grub_command cmd_blocklist;
+static struct grub_command cmd_ls;
+
+grub_command_t
+grub_register_command (const char *name,
+                      grub_err_t (*func) (struct grub_arg_list * state,
+                                          int argc, char **args),
+                      unsigned flags,
+                      const char *summary __attribute__ ((unused)),
+                      const char *description __attribute__ ((unused)),
+                      const struct grub_arg_option *options)
+{
+  grub_command_t cmd = 0;
+
+  if (!grub_strcmp (name, "loopback"))
+    cmd = &cmd_loopback;
+  else if (!grub_strcmp (name, "blocklist"))
+    cmd = &cmd_blocklist;
+  else if (!grub_strcmp (name, "ls"))
+    cmd = &cmd_ls;
+
+  if (cmd)
+    {
+      cmd->func = func;
+      cmd->flags = flags;
+      cmd->options = options;
+    }
+  return NULL;
+}
+
+static grub_err_t
+execute_command (grub_command_t cmd, int n, char **args)
+{
+  int maxargs = 0;
+  grub_err_t ret = 0;
+  struct grub_arg_list *state;
+  struct grub_arg_option *parser;
+  char **parsed_arglist;
+  int numargs;
+
+  /* Count the amount of options the command has.  */
+  parser = (struct grub_arg_option *) cmd->options;
+  while (parser && (parser++)->doc)
+    maxargs++;
+
+  /* Set up the option state.  */
+  state = grub_malloc (sizeof (struct grub_arg_list) * maxargs);
+  grub_memset (state, 0, sizeof (struct grub_arg_list) * maxargs);
+
+  /* Start the command.  */
+  if (!(cmd->flags & GRUB_COMMAND_FLAG_NO_ARG_PARSE))
+    {
+      if (grub_arg_parse (cmd, n, args, state, &parsed_arglist, &numargs))
+       ret = (cmd->func) (state, numargs, parsed_arglist);
+    }
+  else
+    ret = (cmd->func) (state, n, args);
+
+  grub_free (state);
+
+  return ret;
+}
+
+void
+grub_unregister_command (const char *name __attribute__ ((unused)))
+{
+}
+
+#define CMD_LS          1
+#define CMD_CP          2
+#define CMD_CMP         3
+#define CMD_HEX         4
+#define CMD_CRC         6
+#define CMD_BLOCKLIST   7
+
+#define BUF_SIZE  32256
+
+static grub_off_t skip, leng;
+
+static void
+read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len))
+{
+  static char buf[BUF_SIZE];
+  grub_file_t file;
+  grub_off_t ofs, len;
+
+  if ((pathname[0] == '-') && (pathname[1] == 0))
+    {
+      grub_device_t dev;
+
+      dev = grub_device_open (0);
+      if ((! dev) || (! dev->disk))
+        grub_util_error ("Can\'t open device.");
+
+      grub_util_info ("total sectors : %lld.",
+                      (unsigned long long) dev->disk->total_sectors);
+
+      if (! leng)
+        leng = (dev->disk->total_sectors << GRUB_DISK_SECTOR_BITS) - skip;
+
+      while (leng)
+        {
+          grub_size_t len;
+
+          len = (leng > BUF_SIZE) ? BUF_SIZE : leng;
+
+          if (grub_disk_read (dev->disk, 0, skip, len, buf))
+            grub_util_error ("Disk read fails at offset %lld, length %d.",
+                             skip, len);
+
+          if (hook (skip, buf, len))
+            break;
+
+          skip += len;
+          leng -= len;
+        }
+
+      grub_device_close (dev);
+      return;
+    }
+
+  file = grub_file_open (pathname);
+  if (!file)
+    {
+      grub_util_error ("cannot open file %s.", pathname);
+      return;
+    }
+
+  grub_util_info ("file size : %lld.", (unsigned long long) file->size);
+
+  if (skip > file->size)
+    {
+      grub_util_error ("invalid skip value %d.");
+      return;
+    }
+
+  ofs = skip;
+  len = file->size - skip;
+  if ((leng) && (leng < len))
+    len = leng;
+
+  file->offset = skip;
+
+  while (len)
+    {
+      grub_ssize_t sz;
+
+      sz = grub_file_read (file, buf, (len > BUF_SIZE) ? BUF_SIZE : len);
+      if (sz < 0)
+       {
+         grub_util_error ("read error at offset %llu.", ofs);
+         break;
+       }
+
+      if ((sz == 0) || (hook (ofs, buf, sz)))
+       break;
+
+      ofs += sz;
+      len -= sz;
+    }
+
+  grub_file_close (file);
+}
+
+static void
+cmd_cp (char *src, char *dest)
+{
+  FILE *ff;
+
+  auto int cp_hook (grub_off_t ofs, char *buf, int len);
+  int cp_hook (grub_off_t ofs, char *buf, int len)
+  {
+    (void) ofs;
+
+    if ((int) fwrite (buf, 1, len, ff) != len)
+      {
+       grub_util_error ("write error.");
+       return 1;
+      }
+
+    return 0;
+  }
+
+  ff = fopen (dest, "wb");
+  if (ff == NULL)
+    {
+      grub_util_error ("open error.");
+      return;
+    }
+  read_file (src, cp_hook);
+  fclose (ff);
+}
+
+static void
+cmd_cmp (char *src, char *dest)
+{
+  FILE *ff;
+  static char buf_1[BUF_SIZE];
+
+  auto int cmp_hook (grub_off_t ofs, char *buf, int len);
+  int cmp_hook (grub_off_t ofs, char *buf, int len)
+  {
+    if ((int) fread (buf_1, 1, len, ff) != len)
+      {
+       grub_util_error ("read error at offset %llu.", ofs);
+       return 1;
+      }
+
+    if (grub_memcmp (buf, buf_1, len))
+      {
+       int i;
+
+       for (i = 0; i < len; i++, ofs++)
+         if (buf_1[i] != buf[i])
+           {
+             grub_util_error ("compare fail at offset %llu.", ofs);
+             return 1;
+           }
+      }
+    return 0;
+  }
+
+  ff = fopen (dest, "rb");
+  if (ff == NULL)
+    {
+      grub_util_error ("open error.");
+      return;
+    }
+
+  if ((skip) && (fseeko (ff, skip, SEEK_SET)))
+    grub_util_error ("seek error.");
+
+  read_file (src, cmp_hook);
+  fclose (ff);
+}
+
+static void
+cmd_hex (char *pathname)
+{
+  auto int hex_hook (grub_off_t ofs, char *buf, int len);
+  int hex_hook (grub_off_t ofs, char *buf, int len)
+  {
+    hexdump (ofs, buf, len);
+    return 0;
+  }
+
+  read_file (pathname, hex_hook);
+}
+
+static void
+cmd_crc (char *pathname)
+{
+  grub_uint32_t crc = 0;
+
+  auto int crc_hook (grub_off_t ofs, char *buf, int len);
+  int crc_hook (grub_off_t ofs, char *buf, int len)
+  {
+    (void) ofs;
+
+    crc = grub_getcrc32 (crc, buf, len);
+    return 0;
+  }
+
+  read_file (pathname, crc_hook);
+  printf ("%08x\n", crc);
+}
+
+static void
+fstest (char **images, int num_disks, int cmd, int n, char **args)
+{
+  char host_file[128];
+  char loop_name[8];
+  char *argv[3] = { "-p", loop_name, host_file};
+  int i;
+
+  for (i = 0; i < num_disks; i++)
+    {
+      if (grub_strlen (images[i]) + 7 > sizeof (host_file))
+        grub_util_error ("Pathname %s too long.", images[i]);
+
+      grub_sprintf (loop_name, "loop%d", i);
+      grub_sprintf (host_file, "(host)%s", images[i]);
+
+      if (execute_command (&cmd_loopback, 3, argv))
+        grub_util_error ("loopback command fails.");
+    }
+
+  grub_raid_rescan ();
+  switch (cmd)
+    {
+    case CMD_LS:
+      execute_command (&cmd_ls, n, args);
+      break;
+    case CMD_CP:
+      cmd_cp (args[0], args[1]);
+      break;
+    case CMD_CMP:
+      cmd_cmp (args[0], args[1]);
+      break;
+    case CMD_HEX:
+      cmd_hex (args[0]);
+      break;
+    case CMD_CRC:
+      cmd_crc (args[0]);
+      break;
+    case CMD_BLOCKLIST:
+      execute_command (&cmd_blocklist, n, args);
+      grub_printf ("\n");
+    }
+
+  argv[0] = "-d";
+
+  for (i = 0; i < num_disks; i++)
+    {
+      grub_sprintf (loop_name, "loop%d", i);
+      execute_command (&cmd_loopback, 2, argv);
+    }
+}
+
+static struct option options[] = {
+  {"root", required_argument, 0, 'r'},
+  {"skip", required_argument, 0, 's'},
+  {"length", required_argument, 0, 'n'},
+  {"diskcount", required_argument, 0, 'c'},
+  {"debug", required_argument, 0, 'd'},
+  {"help", no_argument, 0, 'h'},
+  {"version", no_argument, 0, 'V'},
+  {"verbose", no_argument, 0, 'v'},
+  {0, 0, 0, 0}
+};
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr, "Try ``grub-fstest --help'' for more information.\n");
+  else
+    printf ("\
+Usage: grub-fstest [OPTION]... IMAGE_PATH COMMANDS\n\
+\n\
+Debug tool for filesystem driver.\n\
+\nCommands:\n\
+  ls PATH                   list files in PATH\n\
+  cp FILE LOCAL             copy FILE to local file LOCAL\n\
+  cmp FILE LOCAL            compare FILE with local file LOCAL\n\
+  hex FILE                  Hex dump FILE\n\
+  crc FILE                  Get crc32 checksum of FILE\n\
+  blocklist FILE            display blocklist of FILE\n\
+\nOptions:\n\
+  -r, --root=DEVICE_NAME    set root device\n\
+  -s, --skip=N              skip N bytes from output file\n\
+  -n, --length=N            handle N bytes in output file\n\
+  -c, --diskcount=N         N input files\n\
+  -d, --debug=S             Set debug environment variable\n\
+  -h, --help                display this message and exit\n\
+  -V, --version             print version information and exit\n\
+  -v, --verbose             print verbose messages\n\
+\n\
+Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
+
+  exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+  char *debug_str = 0, *root = 0, *default_root, *alloc_root;
+  int i, cmd, num_opts, image_index, num_disks = 1;
+
+  progname = "grub-fstest";
+
+  /* Find the first non option entry.  */
+  for (num_opts = 1; num_opts < argc; num_opts++)
+    if (argv[num_opts][0] == '-')
+      {
+        if ((argv[num_opts][2] == 0) && (num_opts < argc - 1) &&
+            ((argv[num_opts][1] == 'r') ||
+             (argv[num_opts][1] == 's') ||
+             (argv[num_opts][1] == 'n') ||
+             (argv[num_opts][1] == 'c') ||
+             (argv[num_opts][1] == 'd')))
+            num_opts++;
+      }
+    else
+      break;
+
+  /* Check for options.  */
+  while (1)
+    {
+      int c = getopt_long (num_opts, argv, "r:s:n:c:d:hVv", options, 0);
+      char *p;
+
+      if (c == -1)
+       break;
+      else
+       switch (c)
+         {
+         case 'r':
+           root = optarg;
+           break;
+
+         case 's':
+           skip = grub_strtoul (optarg, &p, 0);
+            if (*p == 's')
+              skip <<= GRUB_DISK_SECTOR_BITS;
+           break;
+
+         case 'n':
+           leng = grub_strtoul (optarg, &p, 0);
+            if (*p == 's')
+              leng <<= GRUB_DISK_SECTOR_BITS;
+           break;
+
+          case 'c':
+            num_disks = grub_strtoul (optarg, NULL, 0);
+            if (num_disks < 1)
+              {
+                fprintf (stderr, "Invalid disk count.\n");
+                usage (1);
+              }
+            break;
+
+          case 'd':
+            debug_str = optarg;
+            break;
+
+         case 'h':
+           usage (0);
+           break;
+
+         case 'V':
+           printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
+           return 0;
+
+         case 'v':
+           verbosity++;
+           break;
+
+         default:
+           usage (1);
+           break;
+         }
+    }
+
+  /* Obtain PATH.  */
+  if (optind + num_disks - 1 >= argc)
+    {
+      fprintf (stderr, "Not enough pathname.\n");
+      usage (1);
+    }
+
+  image_index = optind;
+  for (i = 0; i < num_disks; i++, optind++)
+    if (argv[optind][0] != '/')
+      {
+        fprintf (stderr, "Must use absolute path.\n");
+        usage (1);
+      }
+
+  cmd = 0;
+  if (optind < argc)
+    {
+      int nparm = 0;
+
+      if (!grub_strcmp (argv[optind], "ls"))
+        {
+          cmd = CMD_LS;
+        }
+      else if (!grub_strcmp (argv[optind], "cp"))
+       {
+         cmd = CMD_CP;
+          nparm = 2;
+       }
+      else if (!grub_strcmp (argv[optind], "cmp"))
+       {
+         cmd = CMD_CMP;
+          nparm = 2;
+       }
+      else if (!grub_strcmp (argv[optind], "hex"))
+       {
+         cmd = CMD_HEX;
+          nparm = 1;
+       }
+      else if (!grub_strcmp (argv[optind], "crc"))
+       {
+         cmd = CMD_CRC;
+          nparm = 1;
+       }
+      else if (!grub_strcmp (argv[optind], "blocklist"))
+       {
+         cmd = CMD_BLOCKLIST;
+          nparm = 1;
+       }
+      else
+       {
+         fprintf (stderr, "Invalid command %s.\n", argv[optind]);
+         usage (1);
+       }
+
+      if (optind + 1 + nparm > argc)
+       {
+         fprintf (stderr, "Invalid parameter for command %s.\n",
+                  argv[optind]);
+         usage (1);
+       }
+
+      optind++;
+    }
+  else
+    {
+      fprintf (stderr, "No command is specified.\n");
+      usage (1);
+    }
+
+  /* Initialize all modules. */
+  grub_init_all ();
+
+  if (debug_str)
+    grub_env_set ("debug", debug_str);
+
+  default_root = (num_disks == 1) ? "loop0" : "md0";
+  alloc_root = 0;
+  if (root)
+    {
+      if ((*root >= '0') && (*root <= '9'))
+        {
+          alloc_root = xmalloc (strlen (default_root) + strlen (root) + 2);
+
+          sprintf (alloc_root, "%s,%s", default_root, root);
+          root = alloc_root;
+        }
+    }
+  else
+    root = default_root;
+
+  grub_env_set ("root", root);
+
+  if (alloc_root)
+    free (alloc_root);
+
+  /* Do it.  */
+  fstest (argv + image_index, num_disks, cmd, argc - optind, argv + optind);
+
+  /* Free resources.  */
+  grub_fini_all ();
+
+  return 0;
+}
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
new file mode 100644 (file)
index 0000000..2d7510f
--- /dev/null
@@ -0,0 +1,217 @@
+#! /bin/sh -e
+
+# Generate grub.cfg by inspecting /boot contents.
+# Copyright (C) 2006,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/>.
+
+transform="@program_transform_name@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+sbindir=@sbindir@
+libdir=@libdir@
+sysconfdir=@sysconfdir@
+grub_prefix=`echo /boot/grub | sed ${transform}`
+grub_cfg=""
+grub_mkconfig_dir=${sysconfdir}/grub.d
+
+grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}`
+grub_probe=${sbindir}/`echo grub-probe | sed ${transform}`
+
+# Usage: usage
+# Print the usage.
+usage () {
+    cat <<EOF
+Usage: $0 [OPTION]
+Generate a grub config file
+
+  -o, --output=FILE       output generated config to FILE [default=stdout]
+  -h, --help              print this message and exit
+  -v, --version           print the version information and exit
+
+Report bugs to <bug-grub@gnu.org>.
+EOF
+}
+
+# Check the arguments.
+for option in "$@"; do
+    case "$option" in
+    -h | --help)
+       usage
+       exit 0 ;;
+    -v | --version)
+       echo "$0 (GNU GRUB ${PACKAGE_VERSION})"
+       exit 0 ;;
+    -o)
+       shift
+       grub_cfg=$1
+       ;;
+    --output=)
+       grub_cfg=`echo "$option" | sed 's/--output=//'`
+       ;;      
+    -*)
+       echo "Unrecognized option \`$option'" 1>&2
+       usage
+       exit 1
+       ;;
+    esac
+done
+
+. ${libdir}/grub/grub-mkconfig_lib
+
+if [ "x$EUID" = "x" ] ; then
+  EUID=`id -u`
+fi
+
+if [ "$EUID" != 0 ] ; then
+  root=f
+  case "`uname 2>/dev/null`" in
+    CYGWIN*)
+      # Cygwin: Assume root if member of admin group
+      for g in `id -G 2>/dev/null` ; do
+       case $g in
+         0|544) root=t ;;
+       esac
+      done ;;
+  esac
+  if [ $root != t ] ; then
+    echo "$0: You must run this as root" >&2
+    exit 1
+  fi
+fi
+
+set $grub_mkdevicemap dummy
+if test -f "$1"; then
+    :
+else
+    echo "$1: Not found." 1>&2
+    exit 1
+fi
+
+set $grub_probe dummy
+if test -f "$1"; then
+    :
+else
+    echo "$1: Not found." 1>&2
+    exit 1
+fi
+
+mkdir -p ${grub_prefix}
+
+if test -e ${grub_prefix}/device.map ; then : ; else
+  grub-mkdevicemap
+fi
+
+# Device containing our userland.  Typically used for root= parameter.
+GRUB_DEVICE="`${grub_probe} --target=device /`"
+GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true
+
+# Device containing our /boot partition.  Usually the same as GRUB_DEVICE.
+GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`"
+GRUB_DEVICE_BOOT_UUID="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_uuid 2> /dev/null`" || true
+
+# Filesystem for the device containing our userland.  Used for stuff like
+# choosing Hurd filesystem module.
+GRUB_FS="`${grub_probe} --target=fs / 2> /dev/null || echo unknown`"
+
+if test -f ${sysconfdir}/default/grub ; then
+  . ${sysconfdir}/default/grub
+fi
+
+# XXX: should this be deprecated at some point?
+if [ "x${GRUB_TERMINAL}" != "x" ] ; then
+  GRUB_TERMINAL_INPUT="${GRUB_TERMINAL}"
+  GRUB_TERMINAL_OUTPUT="${GRUB_TERMINAL}"
+fi
+
+case x${GRUB_TERMINAL_OUTPUT} in
+  x)
+    # If this platform supports gfxterm, try to use it.
+    if test -e ${grub_prefix}/gfxterm.mod ; then
+      GRUB_TERMINAL_OUTPUT=gfxterm
+    fi
+  ;;
+  xconsole | xserial | xofconsole | xgfxterm) ;;
+  *) echo "Invalid output terminal \"${GRUB_TERMINAL_OUTPUT}\"" >&2 ; exit 1 ;;
+esac
+
+# check for terminals that require fonts
+case ${GRUB_TERMINAL_OUTPUT} in
+  gfxterm)
+    if path=`font_path` ; then
+      GRUB_FONT_PATH="${path}"
+    else
+      # fallback to the native terminal for this platform
+      unset GRUB_TERMINAL_OUTPUT
+    fi
+  ;;
+esac
+
+# does our terminal support utf-8 ?
+case ${GRUB_TERMINAL_OUTPUT} in
+  gfxterm) ;;
+  *)
+    # make sure all our children behave in conformance with ascii..
+    export LANG=C
+  ;;
+esac
+
+# These are defined in this script, export them here so that user can
+# override them.
+export GRUB_DEVICE GRUB_DEVICE_UUID GRUB_DEVICE_BOOT GRUB_DEVICE_BOOT_UUID GRUB_FS GRUB_FONT_PATH GRUB_PRELOAD_MODULES
+
+# These are optional, user-defined variables.
+export GRUB_DEFAULT GRUB_TIMEOUT GRUB_DISTRIBUTOR GRUB_CMDLINE_LINUX GRUB_CMDLINE_LINUX_DEFAULT GRUB_TERMINAL_OUTPUT GRUB_SERIAL_COMMAND GRUB_DISABLE_LINUX_UUID GRUB_GFXMODE
+
+if test "x${grub_cfg}" != "x"; then
+  rm -f ${grub_cfg}.new
+  exec > ${grub_cfg}.new
+
+  # Allow this to fail, since /boot/grub/ might need to be fatfs to support some
+  # firmware implementations (e.g. OFW or EFI).
+  chmod 444 ${grub_cfg}.new || true
+fi
+echo "Generating grub.cfg ..." >&2
+
+cat << EOF
+#
+# DO NOT EDIT THIS FILE
+#
+# It is automatically generated by $0 using templates
+# from ${update_grub_dir} and settings from ${sysconfdir}/default/grub
+#
+EOF
+
+for i in ${grub_mkconfig_dir}/* ; do
+  case "$i" in
+    # emacsen backup files. FIXME: support other editors
+    *~) ;;
+    *)
+      if grub_file_is_not_garbage "$i" && test -x "$i" ; then
+        echo
+        echo "### BEGIN $i ###"
+        "$i"
+        echo "### END $i ###"
+      fi
+    ;;
+  esac
+done
+
+if test "x${grub_cfg}" != "x" ; then
+  # none of the children aborted with error, install the new grub.cfg
+  mv -f ${grub_cfg}.new ${grub_cfg}
+fi
+
+echo "done" >&2
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
new file mode 100644 (file)
index 0000000..0c5c456
--- /dev/null
@@ -0,0 +1,178 @@
+# Helper library for grub-mkconfig
+# 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/>.
+
+transform="@program_transform_name@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+datarootdir=@datarootdir@
+datadir=@datadir@
+sbindir=@sbindir@
+pkgdatadir=${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"`
+
+grub_probe=${sbindir}/`echo grub-probe | sed ${transform}`
+
+grub_warn ()
+{
+  echo "Warning: $@" >&2
+}
+
+make_system_path_relative_to_its_root ()
+{
+  path=$1
+  # abort if file doesn't exist
+  if test -e $path ; then : ;else
+    return 1
+  fi
+
+  # canonicalize
+  if path=`readlink -f $path` ; then : ; else
+    return 1
+  fi
+
+  # if not a directory, climb up to the directory containing it
+  if test -d $path ; then
+    dir=$path
+  else
+    dir=`echo $path | sed -e "s,/[^/]*$,,g"`
+  fi
+
+  num=`stat -c %d $dir`
+
+  # this loop sets $dir to the root directory of the filesystem we're inspecting
+  while : ; do
+    parent=`readlink -f $dir/..`
+    if [ "x`stat -c %d $parent`" = "x$num" ] ; then : ; else
+      # $parent is another filesystem; we found it.
+      break
+    fi
+    if [ "x$dir" = "x/" ] ; then
+      # / is our root.
+      break
+    fi
+    dir=$parent
+  done
+
+  # This function never prints trailing slashes (so that its output can be
+  # appended a slash unconditionally).  Each slash in $dir is considered a
+  # preceding slash, and therefore the root directory is an empty string.
+  if [ "$dir" = "/" ] ; then
+    dir=""
+  fi
+
+  # XXX: This fails if $dir contains ','.
+  path=`echo "$path" | sed -e "s,^$dir,,g"` || return 1
+
+  case "`uname 2>/dev/null`" in
+    CYGWIN*)
+      # Cygwin: Check if regular or emulated mount.
+      if [ -z "$dir" ] || [ "`stat -c %D "$dir/.."`" != 620000 ] ; then
+        # Reached some mount point not below /cygdrive.
+        # GRUB does not know Cygwin's emulated mounts,
+        # convert to Win32 path and remove drive letter.
+        path=`cygpath -m "$path" | sed -n 's,^[A-Za-z]:,,p'`
+        test ! -z "$path" || return 1
+      fi ;;
+  esac
+
+  echo "$path"
+}
+
+is_path_readable_by_grub ()
+{
+  path=$1
+
+  # abort if path doesn't exist
+  if test -e $path ; then : ;else
+    return 1
+  fi
+
+  # abort if file is in a filesystem we can't read
+  if ${grub_probe} -t fs $path > /dev/null 2>&1 ; then : ; else
+    return 1
+  fi
+
+  return 0
+}
+
+convert_system_path_to_grub_path ()
+{
+  path=$1
+
+  grub_warn "convert_system_path_to_grub_path() is deprecated.  Use prepare_grub_to_access_device() instead."
+
+  # abort if GRUB can't access the path
+  if is_path_readable_by_grub ${path} ; then : ; else
+    return 1
+  fi
+
+  if drive=`${grub_probe} -t drive $path` ; then : ; else
+    return 1
+  fi
+
+  if relative_path=`make_system_path_relative_to_its_root $path` ; then : ; else
+    return 1
+  fi
+
+  echo ${drive}${relative_path}
+}
+
+prepare_grub_to_access_device ()
+{
+  device=$1
+
+  # Abstraction modules aren't auto-loaded.
+  abstraction="`${grub_probe} --device ${device} --target=abstraction`"
+  if [ "x${abstraction}" = "x" ] ; then : ; else
+    echo "insmod ${abstraction}"
+  fi
+
+  # If there's a filesystem UUID that GRUB is capable of identifying, use it;
+  # otherwise set root as per value in device.map.
+  echo "set root=`${grub_probe} --device ${device} --target=drive`"
+  if fs_uuid="`${grub_probe} --device ${device} --target=fs_uuid 2> /dev/null`" ; then
+    echo "search --fs-uuid --set ${fs_uuid}"
+  fi
+}
+
+font_path ()
+{
+  for dir in ${pkgdatadir} /boot/grub /usr/share/grub ; do
+    # FIXME: We prefer ascii because loading complete fonts is too slow (and
+    # we don't yet provide the gettext magic that would make unicode useful).
+    for basename in ascii unicode unifont ; do
+      path="${dir}/${basename}.pf2"
+      if is_path_readable_by_grub ${path} > /dev/null ; then
+        echo "${path}"
+        return 0
+      fi
+    done
+  done
+
+  return 1
+}
+
+grub_file_is_not_garbage ()
+{
+  if test -f "$1" ; then
+    case "$1" in
+      *.dpkg-dist|*.dpkg-old|*.dpkg-tmp) return 1 ;; # debian dpkg
+    esac
+  else
+    return 1
+  fi
+  return 0
+}
diff --git a/util/grub-mkdevicemap.c b/util/grub-mkdevicemap.c
new file mode 100644 (file)
index 0000000..fa8b158
--- /dev/null
@@ -0,0 +1,728 @@
+/* grub-mkdevicemap.c - make a device map file automatically */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,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/>.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#include <grub/util/misc.h>
+
+#define _GNU_SOURCE    1
+#include <getopt.h>
+
+#ifdef __linux__
+# if !defined(__GLIBC__) || \
+        ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
+/* Maybe libc doesn't have large file support.  */
+#  include <linux/unistd.h>     /* _llseek */
+# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
+# include <sys/ioctl.h>                /* ioctl */
+# ifndef HDIO_GETGEO
+#  define HDIO_GETGEO  0x0301  /* get device geometry */
+/* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is
+   defined.  */
+struct hd_geometry
+{
+  unsigned char heads;
+  unsigned char sectors;
+  unsigned short cylinders;
+  unsigned long start;
+};
+# endif /* ! HDIO_GETGEO */
+# ifndef FLOPPY_MAJOR
+#  define FLOPPY_MAJOR 2       /* the major number for floppy */
+# endif /* ! FLOPPY_MAJOR */
+# ifndef MAJOR
+#  define MAJOR(dev)   \
+  ({ \
+     unsigned long long __dev = (dev); \
+     (unsigned) ((__dev >> 8) & 0xfff) \
+                 | ((unsigned int) (__dev >> 32) & ~0xfff); \
+  })
+# endif /* ! MAJOR */
+# ifndef CDROM_GET_CAPABILITY
+#  define CDROM_GET_CAPABILITY 0x5331  /* get capabilities */
+# endif /* ! CDROM_GET_CAPABILITY */
+# ifndef BLKGETSIZE
+#  define BLKGETSIZE   _IO(0x12,96)    /* return device size */
+# endif /* ! BLKGETSIZE */
+#endif /* __linux__ */
+
+/* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with
+   kFreeBSD-based non-FreeBSD systems (e.g. GNU/kFreeBSD) */
+#if defined(__FreeBSD__) && ! defined(__FreeBSD_kernel__)
+# define __FreeBSD_kernel__
+#endif
+#ifdef __FreeBSD_kernel__
+  /* Obtain version of kFreeBSD headers */
+# include <osreldate.h>
+# ifndef __FreeBSD_kernel_version
+#  define __FreeBSD_kernel_version __FreeBSD_version
+# endif
+
+  /* Runtime detection of kernel */
+# include <sys/utsname.h>
+int
+get_kfreebsd_version (void)
+{
+  struct utsname uts;
+  int major;
+  int minor;
+  int v[2];
+
+  uname (&uts);
+  sscanf (uts.release, "%d.%d", &major, &minor);
+
+  if (major >= 9)
+    major = 9;
+  if (major >= 5)
+    {
+      v[0] = minor/10; v[1] = minor%10;
+    }
+  else
+    {
+      v[0] = minor%10; v[1] = minor/10;
+    }
+  return major*100000+v[0]*10000+v[1]*1000;
+}
+#endif /* __FreeBSD_kernel__ */
+
+#if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
+# include <sys/ioctl.h>                /* ioctl */
+# include <sys/disklabel.h>
+# include <sys/cdio.h>         /* CDIOCCLRDEBUG */
+# if defined(__FreeBSD_kernel__)
+#  include <sys/param.h>
+#  if __FreeBSD_kernel_version >= 500040
+#   include <sys/disk.h>
+#  endif
+# endif /* __FreeBSD_kernel__ */
+#endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
+
+#ifdef HAVE_OPENDISK
+# include <util.h>
+#endif /* HAVE_OPENDISK */
+
+#ifdef __linux__
+/* Check if we have devfs support.  */
+static int
+have_devfs (void)
+{
+  struct stat st;
+  return stat ("/dev/.devfsd", &st) == 0;
+}
+#endif /* __linux__ */
+
+/* These three functions are quite different among OSes.  */
+static void
+get_floppy_disk_name (char *name, int unit)
+{
+#if defined(__linux__)
+  /* GNU/Linux */
+  if (have_devfs ())
+    sprintf (name, "/dev/floppy/%d", unit);
+  else
+    sprintf (name, "/dev/fd%d", unit);
+#elif defined(__GNU__)
+  /* GNU/Hurd */
+  sprintf (name, "/dev/fd%d", unit);
+#elif defined(__FreeBSD_kernel__)
+  /* kFreeBSD */
+  if (get_kfreebsd_version () >= 400000)
+    sprintf (name, "/dev/fd%d", unit);
+  else
+    sprintf (name, "/dev/rfd%d", unit);
+#elif defined(__NetBSD__)
+  /* NetBSD */
+  /* opendisk() doesn't work for floppies.  */
+  sprintf (name, "/dev/rfd%da", unit);
+#elif defined(__OpenBSD__)
+  /* OpenBSD */
+  sprintf (name, "/dev/rfd%dc", unit);
+#elif defined(__QNXNTO__)
+  /* QNX RTP */
+  sprintf (name, "/dev/fd%d", unit);
+#elif defined(__CYGWIN__)
+  /* Cygwin */
+  sprintf (name, "/dev/fd%d", unit);
+#elif defined(__MINGW32__)
+  (void) unit;
+  *name = 0;
+#else
+# warning "BIOS floppy drives cannot be guessed in your operating system."
+  /* Set NAME to a bogus string.  */
+  *name = 0;
+#endif
+}
+
+static void
+get_ide_disk_name (char *name, int unit)
+{
+#if defined(__linux__)
+  /* GNU/Linux */
+  sprintf (name, "/dev/hd%c", unit + 'a');
+#elif defined(__GNU__)
+  /* GNU/Hurd */
+  sprintf (name, "/dev/hd%d", unit);
+#elif defined(__FreeBSD_kernel__)
+  /* kFreeBSD */
+  if (get_kfreebsd_version () >= 400000)
+    sprintf (name, "/dev/ad%d", unit);
+  else
+    sprintf (name, "/dev/rwd%d", unit);
+#elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
+  /* NetBSD */
+  char shortname[16];
+  int fd;
+  
+  sprintf (shortname, "wd%d", unit);
+  fd = opendisk (shortname, O_RDONLY, name,
+                16,    /* length of NAME */
+                0      /* char device */
+                );
+  close (fd);
+#elif defined(__OpenBSD__)
+  /* OpenBSD */
+  sprintf (name, "/dev/rwd%dc", unit);
+#elif defined(__QNXNTO__)
+  /* QNX RTP */
+  /* Actually, QNX RTP doesn't distinguish IDE from SCSI, so this could
+     contain SCSI disks.  */
+  sprintf (name, "/dev/hd%d", unit);
+#elif defined(__CYGWIN__)
+  /* Cygwin emulates all disks as /dev/sdX.  */
+  (void) unit;
+  *name = 0;
+#elif defined(__MINGW32__)
+  sprintf (name, "//./PHYSICALDRIVE%d", unit);
+#else
+# warning "BIOS IDE drives cannot be guessed in your operating system."
+  /* Set NAME to a bogus string.  */
+  *name = 0;
+#endif
+}
+
+static void
+get_scsi_disk_name (char *name, int unit)
+{
+#if defined(__linux__)
+  /* GNU/Linux */
+  sprintf (name, "/dev/sd%c", unit + 'a');
+#elif defined(__GNU__)
+  /* GNU/Hurd */
+  sprintf (name, "/dev/sd%d", unit);
+#elif defined(__FreeBSD_kernel__)
+  /* kFreeBSD */
+  if (get_kfreebsd_version () >= 400000)
+    sprintf (name, "/dev/da%d", unit);
+  else
+    sprintf (name, "/dev/rda%d", unit);
+#elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
+  /* NetBSD */
+  char shortname[16];
+  int fd;
+  
+  sprintf (shortname, "sd%d", unit);
+  fd = opendisk (shortname, O_RDONLY, name,
+                16,    /* length of NAME */
+                0      /* char device */
+                );
+  close (fd);
+#elif defined(__OpenBSD__)
+  /* OpenBSD */
+  sprintf (name, "/dev/rsd%dc", unit);
+#elif defined(__QNXNTO__)
+  /* QNX RTP */
+  /* QNX RTP doesn't distinguish SCSI from IDE, so it is better to
+     disable the detection of SCSI disks here.  */
+  *name = 0;
+#elif defined(__CYGWIN__)
+  /* Cygwin emulates all disks as /dev/sdX.  */
+  sprintf (name, "/dev/sd%c", unit + 'a');
+#elif defined(__MINGW32__)
+  (void) unit;
+  *name = 0;
+#else
+# warning "BIOS SCSI drives cannot be guessed in your operating system."
+  /* Set NAME to a bogus string.  */
+  *name = 0;
+#endif
+}
+
+#ifdef __linux__
+static void
+get_virtio_disk_name (char *name, int unit)
+{
+  sprintf (name, "/dev/vd%c", unit + 'a');
+}
+
+static void
+get_dac960_disk_name (char *name, int controller, int drive)
+{
+  sprintf (name, "/dev/rd/c%dd%d", controller, drive);
+}
+
+static void
+get_ataraid_disk_name (char *name, int unit)
+{
+  sprintf (name, "/dev/ataraid/d%c", unit + '0');
+}
+
+static void
+get_i2o_disk_name (char *name, char unit)
+{
+  sprintf (name, "/dev/i2o/hd%c", unit);
+}
+
+static void
+get_cciss_disk_name (char *name, int controller, int drive)
+{
+  sprintf (name, "/dev/cciss/c%dd%d", controller, drive);
+}
+
+static void
+get_ida_disk_name (char *name, int controller, int drive)
+{
+  sprintf (name, "/dev/ida/c%dd%d", controller, drive);
+}
+
+static void
+get_mmc_disk_name (char *name, int unit)
+{
+  sprintf (name, "/dev/mmcblk%d", unit);
+}
+
+static void
+get_xvd_disk_name (char *name, int unit)
+{
+  sprintf (name, "/dev/xvd%c", unit + 'a');
+}
+#endif
+
+/* Check if DEVICE can be read. If an error occurs, return zero,
+   otherwise return non-zero.  */
+static int
+check_device (const char *device)
+{
+  char buf[512];
+  FILE *fp;
+
+  /* If DEVICE is empty, just return error.  */
+  if (*device == 0)
+    return 0;
+  
+  fp = fopen (device, "r");
+  if (! fp)
+    {
+      switch (errno)
+       {
+#ifdef ENOMEDIUM
+       case ENOMEDIUM:
+# if 0
+         /* At the moment, this finds only CDROMs, which can't be
+            read anyway, so leave it out. Code should be
+            reactivated if `removable disks' and CDROMs are
+            supported.  */
+         /* Accept it, it may be inserted.  */
+         return 1;
+# endif
+         break;
+#endif /* ENOMEDIUM */
+       default:
+         /* Break case and leave.  */
+         break;
+       }
+      /* Error opening the device.  */
+      return 0;
+    }
+  
+  /* Make sure CD-ROMs don't get assigned a BIOS disk number 
+     before SCSI disks!  */
+#ifdef __linux__
+# ifdef CDROM_GET_CAPABILITY
+  if (ioctl (fileno (fp), CDROM_GET_CAPABILITY, 0) >= 0)
+    return 0;
+# else /* ! CDROM_GET_CAPABILITY */
+  /* Check if DEVICE is a CD-ROM drive by the HDIO_GETGEO ioctl.  */
+  {
+    struct hd_geometry hdg;
+    struct stat st;
+
+    if (fstat (fileno (fp), &st))
+      return 0;
+
+    /* If it is a block device and isn't a floppy, check if HDIO_GETGEO
+       succeeds.  */
+    if (S_ISBLK (st.st_mode)
+       && MAJOR (st.st_rdev) != FLOPPY_MAJOR
+       && ioctl (fileno (fp), HDIO_GETGEO, &hdg))
+      return 0;
+  }
+# endif /* ! CDROM_GET_CAPABILITY */
+#endif /* __linux__ */
+
+#if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
+# ifdef CDIOCCLRDEBUG
+  if (ioctl (fileno (fp), CDIOCCLRDEBUG, 0) >= 0)
+    return 0;
+# endif /* CDIOCCLRDEBUG */
+#endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
+  
+  /* Attempt to read the first sector.  */
+  if (fread (buf, 1, 512, fp) != 512)
+    {
+      fclose (fp);
+      return 0;
+    }
+  
+  fclose (fp);
+  return 1;
+}
+
+static void
+make_device_map (const char *device_map, int floppy_disks)
+{
+  FILE *fp;
+  int num_hd = 0;
+  int i;
+
+  if (strcmp (device_map, "-") == 0)
+    fp = stdout;
+  else
+    fp = fopen (device_map, "w");
+  
+  if (! fp)
+    grub_util_error ("cannot open %s", device_map);
+
+  /* Floppies.  */
+  for (i = 0; i < floppy_disks; i++)
+    {
+      char name[16];
+      struct stat st;
+      
+      get_floppy_disk_name (name, i);
+      if (stat (name, &st) < 0)
+       break;
+      /* In floppies, write the map, whether check_device succeeds
+        or not, because the user just may not insert floppies.  */
+      if (fp)
+       fprintf (fp, "(fd%d)\t%s\n", i, name);
+    }
+  
+#ifdef __linux__
+  if (have_devfs ())
+    {
+      while (1)
+       {
+         char discn[32];
+         char name[PATH_MAX];
+         struct stat st;
+
+         /* Linux creates symlinks "/dev/discs/discN" for convenience.
+            The way to number disks is the same as GRUB's.  */
+         sprintf (discn, "/dev/discs/disc%d", num_hd);
+         if (stat (discn, &st) < 0)
+           break;
+         
+         if (realpath (discn, name))
+           {
+             strcat (name, "/disc");
+             fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
+           }
+         
+         num_hd++;
+       }
+      
+      goto finish;
+    }
+#endif /* __linux__ */
+    
+  /* IDE disks.  */
+  for (i = 0; i < 20; i++)
+    {
+      char name[16];
+      
+      get_ide_disk_name (name, i);
+      if (check_device (name))
+       {
+         fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
+         num_hd++;
+       }
+    }
+  
+#ifdef __linux__
+  /* Virtio disks.  */
+  for (i = 0; i < 20; i++)
+    {
+      char name[16];
+      
+      get_virtio_disk_name (name, i);
+      if (check_device (name))
+       {
+         fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
+         num_hd++;
+       }
+    }
+  
+  /* ATARAID disks.  */
+  for (i = 0; i < 8; i++)
+    {
+      char name[20];
+
+      get_ataraid_disk_name (name, i);
+      if (check_device (name))
+       {
+         fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
+          num_hd++;
+        }
+    }
+
+  /* Xen virtual block devices.  */
+  for (i = 0; i < 16; i++)
+    {
+      char name[16];
+
+      get_xvd_disk_name (name, i);
+      if (check_device (name))
+       {
+         fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
+         num_hd++;
+       }
+    }
+#endif /* __linux__ */
+
+  /* The rest is SCSI disks.  */
+  for (i = 0; i < 16; i++)
+    {
+      char name[16];
+      
+      get_scsi_disk_name (name, i);
+      if (check_device (name))
+       {
+         fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
+         num_hd++;
+       }
+    }
+  
+#ifdef __linux__
+  /* This is for DAC960 - we have
+     /dev/rd/c<controller>d<logical drive>p<partition>.
+     
+     DAC960 driver currently supports up to 8 controllers, 32 logical
+     drives, and 7 partitions.  */
+  {
+    int controller, drive;
+    
+    for (controller = 0; controller < 8; controller++)
+      {
+       for (drive = 0; drive < 15; drive++)
+         {
+           char name[24];
+           
+           get_dac960_disk_name (name, controller, drive);
+           if (check_device (name))
+             {
+               fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
+               num_hd++;
+             }
+         }
+      }
+  }
+    
+  /* This is for CCISS - we have
+     /dev/cciss/c<controller>d<logical drive>p<partition>.  */
+  {
+    int controller, drive;
+    
+    for (controller = 0; controller < 3; controller++)
+      {
+       for (drive = 0; drive < 10; drive++)
+         {
+           char name[24];
+           
+           get_cciss_disk_name (name, controller, drive);
+           if (check_device (name))
+             {
+               fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
+               num_hd++;
+             }
+         }
+      }
+  }
+
+  /* This is for Compaq Intelligent Drive Array - we have
+     /dev/ida/c<controller>d<logical drive>p<partition>.  */
+  {
+    int controller, drive;
+    
+    for (controller = 0; controller < 3; controller++)
+      {
+       for (drive = 0; drive < 10; drive++)
+         {
+           char name[24];
+           
+           get_ida_disk_name (name, controller, drive);
+           if (check_device (name))
+             {
+               fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
+               num_hd++;
+             }
+         }
+      }
+  }
+    
+  /* This is for I2O - we have /dev/i2o/hd<logical drive><partition> */
+  {
+    char unit;
+
+    for (unit = 'a'; unit < 'f'; unit++)
+      {
+       char name[24];
+    
+       get_i2o_disk_name (name, unit);
+       if (check_device (name))
+         {
+           fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
+           num_hd++;
+         }
+      }
+  }
+
+  /* MultiMediaCard (MMC).  */
+  for (i = 0; i < 10; i++)
+    {
+      char name[16];
+      
+      get_mmc_disk_name (name, i);
+      if (check_device (name))
+       {
+         fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
+         num_hd++;
+       }
+    }
+
+ finish:
+#endif /* __linux__ */
+
+  if (fp != stdout)
+    fclose (fp);
+}
+
+static struct option options[] =
+  {
+    {"device-map", required_argument, 0, 'm'},
+    {"probe-second-floppy", no_argument, 0, 's'},
+    {"no-floppy", no_argument, 0, 'n'},
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+    {"verbose", no_argument, 0, 'v'},
+    {0, 0, 0, 0}
+  };
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr,
+            "Try ``grub-mkdevicemap --help'' for more information.\n");
+  else
+    printf ("\
+Usage: grub-mkdevicemap [OPTION]...\n\
+\n\
+Generate a device map file automatically.\n\
+\n\
+  -n, --no-floppy           do not probe any floppy drive\n\
+  -s, --probe-second-floppy probe the second floppy drive\n\
+  -m, --device-map=FILE     use FILE as the device map [default=%s]\n\
+  -h, --help                display this message and exit\n\
+  -V, --version             print version information and exit\n\
+  -v, --verbose             print verbose messages\n\
+\n\
+Report bugs to <%s>.\n\
+",
+           DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
+  
+  exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+  char *dev_map = 0;
+  int floppy_disks = 1;
+  
+  progname = "grub-mkdevicemap";
+  
+  /* Check for options.  */
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "snm:r:hVv", options, 0);
+      
+      if (c == -1)
+       break;
+      else
+       switch (c)
+         {
+         case 'm':
+           if (dev_map)
+             free (dev_map);
+
+           dev_map = xstrdup (optarg);
+           break;
+
+         case 'n':
+           floppy_disks = 0;
+           break;
+
+         case 's':
+           floppy_disks = 2;
+           break;
+           
+         case 'h':
+           usage (0);
+           break;
+
+         case 'V':
+           printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
+           return 0;
+
+         case 'v':
+           verbosity++;
+           break;
+
+         default:
+           usage (1);
+           break;
+         }
+    }
+
+  make_device_map (dev_map ? : DEFAULT_DEVICE_MAP, floppy_disks);
+
+  free (dev_map);
+  
+  return 0;
+}
diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c
new file mode 100644 (file)
index 0000000..cfd6f9d
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+ *  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 <config.h>
+#include <grub/types.h>
+#include <grub/util/misc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include <freetype/ftsynth.h>
+
+#define GRUB_FONT_DEFAULT_SIZE         16
+
+#define GRUB_FONT_RANGE_BLOCK          1024
+
+struct grub_glyph_info
+{
+  struct grub_glyph_info *next;
+  grub_uint32_t char_code;
+  int width;
+  int height;
+  int x_ofs;
+  int y_ofs;
+  int device_width;
+  int bitmap_size;
+  grub_uint8_t bitmap[0];
+};
+
+#define GRUB_FONT_FLAG_BOLD            1
+#define GRUB_FONT_FLAG_NOBITMAP                2
+#define GRUB_FONT_FLAG_NOHINTING       4
+#define GRUB_FONT_FLAG_FORCEHINT       8
+
+struct grub_font_info
+{
+  char* name;
+  int style;
+  int desc;
+  int size;
+  int max_width;
+  int max_height;
+  int min_y;
+  int flags;
+  int num_range;
+  grub_uint32_t *ranges;
+  struct grub_glyph_info *glyph;
+};
+
+static struct option options[] =
+{
+  {"output", required_argument, 0, 'o'},
+  {"name", required_argument, 0, 'n'},
+  {"index", required_argument, 0, 'i'},
+  {"range", required_argument, 0, 'r'},
+  {"size", required_argument, 0, 's'},
+  {"desc", required_argument, 0, 'd'},
+  {"bold", no_argument, 0, 'b'},
+  {"no-bitmap", no_argument, 0, 0x100},
+  {"no-hinting", no_argument, 0, 0x101},
+  {"force-autohint", no_argument, 0, 'a'},
+  {"help", no_argument, 0, 'h'},
+  {"version", no_argument, 0, 'V'},
+  {"verbose", no_argument, 0, 'v'},
+  {0, 0, 0, 0}
+};
+
+int font_verbosity;
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr, "Try ``grub-mkfont --help'' for more information.\n");
+  else
+    printf ("\
+Usage: grub-mkfont [OPTIONS] FONT_FILES\n\
+\nOptions:\n\
+  -o, --output=FILE_NAME    set output file name\n\
+  -i, --index=N             set face index\n\
+  -r, --range=A-B[,C-D]     set font range\n\
+  -n, --name=S              set font family name\n\
+  -s, --size=N              set font size\n\
+  -d, --desc=N              set font descent\n\
+  -b, --bold                convert to bold font\n\
+  -a, --force-autohint      force autohint\n\
+  --no-hinting              disable hinting\n\
+  --no-bitmap               ignore bitmap strikes when loading\n\
+  -h, --help                display this message and exit\n\
+  -V, --version             print version information and exit\n\
+  -v, --verbose             print verbose messages\n\
+\n\
+Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
+
+  exit (status);
+}
+
+void
+add_pixel (grub_uint8_t **data, int *mask, int not_blank)
+{
+  if (*mask == 0)
+    {
+      (*data)++;
+      **data = 0;
+      *mask = 128;
+    }
+
+  if (not_blank)
+    **data |= *mask;
+
+  *mask >>= 1;
+}
+
+void
+add_char (struct grub_font_info *font_info, FT_Face face,
+         grub_uint32_t char_code)
+{
+  struct grub_glyph_info *glyph_info, **p_glyph;
+  int width, height;
+  grub_uint8_t *data;
+  int mask, i, j, bitmap_size;
+  FT_GlyphSlot glyph;
+  int flag = FT_LOAD_RENDER | FT_LOAD_MONOCHROME;
+
+  if (font_info->flags & GRUB_FONT_FLAG_NOBITMAP)
+    flag |= FT_LOAD_NO_BITMAP;
+
+  if (font_info->flags & GRUB_FONT_FLAG_NOHINTING)
+    flag |= FT_LOAD_NO_HINTING;
+  else if (font_info->flags & GRUB_FONT_FLAG_FORCEHINT)
+    flag |= FT_LOAD_FORCE_AUTOHINT;
+
+  if (FT_Load_Char (face, char_code, flag))
+    return;
+
+  glyph = face->glyph;
+
+  if (font_info->flags & GRUB_FONT_FLAG_BOLD)
+    FT_GlyphSlot_Embolden (glyph);
+
+  p_glyph = &font_info->glyph;
+  while ((*p_glyph) && ((*p_glyph)->char_code > char_code))
+    {
+      p_glyph = &(*p_glyph)->next;
+    }
+
+  /* Ignore duplicated glyph.  */
+  if ((*p_glyph) && ((*p_glyph)->char_code == char_code))
+    return;
+
+  width = glyph->bitmap.width;
+  height = glyph->bitmap.rows;
+
+  bitmap_size = ((width * height + 7) / 8);
+  glyph_info = xmalloc (sizeof (struct grub_glyph_info) + bitmap_size);
+  glyph_info->bitmap_size = bitmap_size;
+
+  glyph_info->next = *p_glyph;
+  *p_glyph = glyph_info;
+
+  glyph_info->char_code = char_code;
+  glyph_info->width = width;
+  glyph_info->height = height;
+  glyph_info->x_ofs = glyph->bitmap_left;
+  glyph_info->y_ofs = glyph->bitmap_top - height;
+  glyph_info->device_width = glyph->metrics.horiAdvance / 64;
+
+  if (width > font_info->max_width)
+    font_info->max_width = width;
+
+  if (height > font_info->max_height)
+    font_info->max_height = height;
+
+  if (glyph_info->y_ofs < font_info->min_y)
+    font_info->min_y = glyph_info->y_ofs;
+
+  mask = 0;
+  data = &glyph_info->bitmap[0] - 1;
+  for (j = 0; j < height; j++)
+    for (i = 0; i < width; i++)
+      add_pixel (&data, &mask,
+                glyph->bitmap.buffer[i / 8 + j * glyph->bitmap.pitch] &
+                (1 << (7 - (i & 7))));
+}
+
+void
+add_font (struct grub_font_info *font_info, FT_Face face)
+{
+  if (font_info->num_range)
+    {
+      int i;
+      grub_uint32_t j;
+
+      for (i = 0; i < font_info->num_range; i++)
+       for (j = font_info->ranges[i * 2]; j <= font_info->ranges[i * 2 + 1];
+            j++)
+         add_char (font_info, face, j);
+    }
+  else
+    {
+      grub_uint32_t char_code, glyph_index;
+
+      for (char_code = FT_Get_First_Char (face, &glyph_index);
+          glyph_index;
+          char_code = FT_Get_Next_Char (face, char_code, &glyph_index))
+       add_char (font_info, face, char_code);
+    }
+}
+
+void
+write_string_section (char *name, char *str, int* offset, FILE* file)
+{
+  grub_uint32_t leng, leng_be32;
+
+  leng = strlen (str) + 1;
+  leng_be32 = grub_cpu_to_be32 (leng);
+
+  grub_util_write_image (name, 4, file);
+  grub_util_write_image ((char *) &leng_be32, 4, file);
+  grub_util_write_image (str, leng, file);
+
+  *offset += 8 + leng;
+}
+
+void
+write_be16_section (char *name, grub_uint16_t data, int* offset, FILE* file)
+{
+  grub_uint32_t leng;
+
+  leng = grub_cpu_to_be32 (2);
+  data = grub_cpu_to_be16 (data);
+  grub_util_write_image (name, 4, file);
+  grub_util_write_image ((char *) &leng, 4, file);
+  grub_util_write_image ((char *) &data, 2, file);
+
+  *offset += 10;
+}
+
+void
+print_glyphs (struct grub_font_info *font_info)
+{
+  int num;
+  struct grub_glyph_info *glyph;
+  char line[512];
+
+  for (glyph = font_info->glyph, num = 0; glyph; glyph = glyph->next, num++)
+    {
+      int x, y, xmax, xmin, ymax, ymin;
+      grub_uint8_t *bitmap, mask;
+
+      printf ("\nGlyph #%d, U+%04x\n", num, glyph->char_code);
+      printf ("Width %d, Height %d, X offset %d, Y offset %d, Device width %d\n",
+             glyph->width, glyph->height, glyph->x_ofs, glyph->y_ofs,
+             glyph->device_width);
+
+      xmax = glyph->x_ofs + glyph->width;
+      if (xmax < glyph->device_width)
+       xmax = glyph->device_width;
+
+      xmin = glyph->x_ofs;
+      if (xmin > 0)
+       xmin = 0;
+
+      ymax = glyph->y_ofs + glyph->height;
+      if (ymax < font_info->size - font_info->desc)
+       ymax = font_info->size - font_info->desc;
+
+      ymin = glyph->y_ofs;
+      if (ymin > - font_info->desc)
+       ymin = - font_info->desc;
+
+      bitmap = glyph->bitmap;
+      mask = 0x80;
+      for (y = ymax - 1; y >= ymin; y--)
+       {
+         int line_pos;
+
+         line_pos = 0;
+         for (x = xmin; x < xmax; x++)
+           {
+             if ((x >= glyph->x_ofs) &&
+                 (x < glyph->x_ofs + glyph->width) &&
+                 (y >= glyph->y_ofs) &&
+                 (y < glyph->y_ofs + glyph->height))
+               {
+                 line[line_pos++] = (*bitmap & mask) ? '#' : '_';
+                 mask >>= 1;
+                 if (mask == 0)
+                   {
+                     mask = 0x80;
+                     bitmap++;
+                   }
+               }
+             else if ((x >= 0) &&
+                      (x < glyph->device_width) &&
+                      (y >= - font_info->desc) &&
+                      (y < font_info->size - font_info->desc))
+               {
+                 line[line_pos++] = ((x == 0) || (y == 0)) ? '+' : '.';
+               }
+             else
+               line[line_pos++] = '*';
+           }
+         line[line_pos] = 0;
+         printf ("%s\n", line);
+       }
+    }
+}
+
+void
+write_font (struct grub_font_info *font_info, char *output_file)
+{
+  FILE *file;
+  grub_uint32_t leng, data;
+  char style_name[20], *font_name;
+  struct grub_glyph_info *cur, *pre;
+  int num, offset;
+
+  file = fopen (output_file, "wb");
+  if (! file)
+    grub_util_error ("Can\'t write to file %s.", output_file);
+
+  offset = 0;
+
+  leng = grub_cpu_to_be32 (4);
+  grub_util_write_image ("FILE", 4, file);
+  grub_util_write_image ((char *) &leng, 4, file);
+  grub_util_write_image ("PFF2", 4, file);
+  offset += 12;
+
+  if (! font_info->name)
+    font_info->name = "Unknown";
+
+  if (font_info->flags & GRUB_FONT_FLAG_BOLD)
+    font_info->style |= FT_STYLE_FLAG_BOLD;
+
+  style_name[0] = 0;
+  if (font_info->style & FT_STYLE_FLAG_BOLD)
+    strcpy (style_name, " Bold");
+
+  if (font_info->style & FT_STYLE_FLAG_ITALIC)
+    strcat (style_name, " Italic");
+
+  if (! style_name[0])
+    strcpy (style_name, " Regular");
+
+  asprintf (&font_name, "%s %s %d", font_info->name, &style_name[1],
+           font_info->size);
+
+  write_string_section ("NAME", font_name, &offset, file);
+  write_string_section ("FAMI", font_info->name, &offset, file);
+  write_string_section ("WEIG",
+                       (font_info->style & FT_STYLE_FLAG_BOLD) ?
+                       "bold" : "normal",
+                       &offset, file);
+  write_string_section ("SLAN",
+                       (font_info->style & FT_STYLE_FLAG_ITALIC) ?
+                       "italic" : "normal",
+                       &offset, file);
+
+  write_be16_section ("PTSZ", font_info->size, &offset, file);
+  write_be16_section ("MAXW", font_info->max_width, &offset, file);
+  write_be16_section ("MAXH", font_info->max_height, &offset, file);
+
+  if (! font_info->desc)
+    {
+      if (font_info->min_y >= 0)
+       font_info->desc = 1;
+      else
+       font_info->desc = - font_info->min_y;
+    }
+
+  write_be16_section ("ASCE", font_info->size - font_info->desc, &offset, file);
+  write_be16_section ("DESC", font_info->desc, &offset, file);
+
+  if (font_verbosity > 0)
+    {
+      printf ("Font name: %s\n", font_name);
+      printf ("Max width: %d\n", font_info->max_width);
+      printf ("Max height: %d\n", font_info->max_height);
+      printf ("Font ascent: %d\n", font_info->size - font_info->desc);
+      printf ("Font descent: %d\n", font_info->desc);
+    }
+
+  num = 0;
+  pre = 0;
+  cur = font_info->glyph;
+  while (cur)
+    {
+      struct grub_glyph_info *nxt;
+
+      nxt = cur->next;
+      cur->next = pre;
+      pre = cur;
+      cur = nxt;
+      num++;
+    }
+
+  font_info->glyph = pre;
+
+  if (font_verbosity > 0)
+    printf ("Number of glyph: %d\n", num);
+
+  leng = grub_cpu_to_be32 (num * 9);
+  grub_util_write_image ("CHIX", 4, file);
+  grub_util_write_image ((char *) &leng, 4, file);
+  offset += 8 + num * 9 + 8;
+
+  for (cur = font_info->glyph; cur; cur = cur->next)
+    {
+      data = grub_cpu_to_be32 (cur->char_code);
+      grub_util_write_image ((char *) &data, 4, file);
+      data = 0;
+      grub_util_write_image ((char *) &data, 1, file);
+      data = grub_cpu_to_be32 (offset);
+      grub_util_write_image ((char *) &data, 4, file);
+      offset += 10 + cur->bitmap_size;
+    }
+
+  leng = 0xffffffff;
+  grub_util_write_image ("DATA", 4, file);
+  grub_util_write_image ((char *) &leng, 4, file);
+
+  for (cur = font_info->glyph; cur; cur = cur->next)
+    {
+      data = grub_cpu_to_be16 (cur->width);
+      grub_util_write_image ((char *) &data, 2, file);
+      data = grub_cpu_to_be16 (cur->height);
+      grub_util_write_image ((char *) &data, 2, file);
+      data = grub_cpu_to_be16 (cur->x_ofs);
+      grub_util_write_image ((char *) &data, 2, file);
+      data = grub_cpu_to_be16 (cur->y_ofs);
+      grub_util_write_image ((char *) &data, 2, file);
+      data = grub_cpu_to_be16 (cur->device_width);
+      grub_util_write_image ((char *) &data, 2, file);
+      grub_util_write_image ((char *) &cur->bitmap[0], cur->bitmap_size, file);
+    }
+
+  if (font_verbosity > 1)
+    print_glyphs (font_info);
+
+  fclose (file);
+}
+
+int
+main (int argc, char *argv[])
+{
+  struct grub_font_info font_info;
+  FT_Library ft_lib;
+  int font_index = 0;
+  int font_size = 0;
+  char *output_file = NULL;
+
+  memset (&font_info, 0, sizeof (font_info));
+
+  progname = "grub-mkfont";
+
+  /* Check for options.  */
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "bao:n:i:s:d:r:hVv", options, 0);
+
+      if (c == -1)
+       break;
+      else
+       switch (c)
+         {
+         case 'b':
+           font_info.flags |= GRUB_FONT_FLAG_BOLD;
+           break;
+
+         case 0x100:
+           font_info.flags |= GRUB_FONT_FLAG_NOBITMAP;
+           break;
+
+         case 0x101:
+           font_info.flags |= GRUB_FONT_FLAG_NOHINTING;
+           break;
+
+         case 'a':
+           font_info.flags |= GRUB_FONT_FLAG_FORCEHINT;
+           break;
+
+         case 'o':
+           output_file = optarg;
+           break;
+
+         case 'n':
+           font_info.name = optarg;
+           break;
+
+         case 'i':
+           font_index = strtoul (optarg, NULL, 0);
+           break;
+
+         case 's':
+           font_size = strtoul (optarg, NULL, 0);
+           break;
+
+         case 'r':
+           {
+             char *p = optarg;
+
+             while (1)
+               {
+                 grub_uint32_t a, b;
+
+                 a = strtoul (p, &p, 0);
+                 if (*p != '-')
+                   grub_util_error ("Invalid font range");
+                 b = strtoul (p + 1, &p, 0);
+                 if ((font_info.num_range & (GRUB_FONT_RANGE_BLOCK - 1)) == 0)
+                   font_info.ranges = xrealloc (font_info.ranges,
+                                                (font_info.num_range +
+                                                 GRUB_FONT_RANGE_BLOCK) *
+                                                sizeof (int) * 2);
+
+                 font_info.ranges[font_info.num_range * 2] = a;
+                 font_info.ranges[font_info.num_range * 2 + 1] = b;
+                 font_info.num_range++;
+
+                 if (*p)
+                   {
+                     if (*p != ',')
+                       grub_util_error ("Invalid font range");
+                     else
+                       p++;
+                   }
+                 else
+                   break;
+               }
+             break;
+           }
+
+         case 'd':
+           font_info.desc = strtoul (optarg, NULL, 0);
+           break;
+
+         case 'h':
+           usage (0);
+           break;
+
+         case 'V':
+           printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
+           return 0;
+
+         case 'v':
+           font_verbosity++;
+           break;
+
+         default:
+           usage (1);
+           break;
+         }
+    }
+
+  if (! output_file)
+    grub_util_error ("No output file is specified.");
+
+  if (FT_Init_FreeType (&ft_lib))
+    grub_util_error ("FT_Init_FreeType fails");
+
+  for (; optind < argc; optind++)
+    {
+      FT_Face ft_face;
+      int size;
+
+      if (FT_New_Face (ft_lib, argv[optind], font_index, &ft_face))
+       {
+         grub_util_info ("Can't open file %s, index %d\n", argv[optind],
+                         font_index);
+         continue;
+       }
+
+      if ((! font_info.name) && (ft_face->family_name))
+       font_info.name = xstrdup (ft_face->family_name);
+
+      size = font_size;
+      if (! size)
+       {
+         if ((ft_face->face_flags & FT_FACE_FLAG_SCALABLE) ||
+             (! ft_face->num_fixed_sizes))
+           size = GRUB_FONT_DEFAULT_SIZE;
+         else
+           size = ft_face->available_sizes[0].height;
+       }
+
+      font_info.style = ft_face->style_flags;
+      font_info.size = size;
+
+      FT_Set_Pixel_Sizes (ft_face, size, size);
+      add_font (&font_info, ft_face);
+      FT_Done_Face (ft_face);
+    }
+
+  FT_Done_FreeType (ft_lib);
+
+  write_font (&font_info, output_file);
+
+  return 0;
+}
diff --git a/util/grub-pe2elf.c b/util/grub-pe2elf.c
new file mode 100644 (file)
index 0000000..d703d33
--- /dev/null
@@ -0,0 +1,514 @@
+/* grub-pe2elf.c - tool to convert pe image to elf.  */
+/*
+ *  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/types.h>
+#include <grub/util/misc.h>
+#include <grub/elf.h>
+#include <grub/efi/pe32.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+static struct option options[] = {
+  {"help", no_argument, 0, 'h'},
+  {"version", no_argument, 0, 'V'},
+  {"verbose", no_argument, 0, 'v'},
+  {0, 0, 0, 0}
+};
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr, "Try ``grub-editenv --help'' for more information.\n");
+  else
+    printf ("\
+Usage: grub-editenv [OPTIONS] input [output]\n\
+\n\
+Tool to convert pe image to elf.\n\
+\nOptions:\n\
+  -h, --help                display this message and exit\n\
+  -V, --version             print version information and exit\n\
+  -v, --verbose             print verbose messages\n\
+\n\
+Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
+
+  exit (status);
+}
+
+/*
+ *  Section layout
+ *
+ *    null
+ *    .text
+ *    .rdata
+ *    .data
+ *    .bss
+ *    .modname
+ *    .moddeps
+ *    .symtab
+ *    .strtab
+ *    relocation sections
+ */
+
+#define TEXT_SECTION   1
+#define RDATA_SECTION  2
+#define DATA_SECTION   3
+#define BSS_SECTION    4
+#define MODNAME_SECTION        5
+#define MODDEPS_SECTION        6
+#define SYMTAB_SECTION 7
+#define STRTAB_SECTION 8
+
+#define REL_SECTION    9
+#define MAX_SECTIONS   12
+
+#define STRTAB_BLOCK   256
+
+static char *strtab;
+static int strtab_max, strtab_len;
+
+Elf32_Ehdr ehdr;
+Elf32_Shdr shdr[MAX_SECTIONS];
+int num_sections;
+grub_uint32_t offset;
+
+static int
+insert_string (char *name)
+{
+  int len, result;
+
+  if (*name == '_')
+    name++;
+
+  len = strlen (name);
+  if (strtab_len + len >= strtab_max)
+    {
+      strtab_max += STRTAB_BLOCK;
+      strtab = xrealloc (strtab, strtab_max);
+    }
+
+  strcpy (strtab + strtab_len, name);
+  result = strtab_len;
+  strtab_len += len + 1;
+
+  return result;
+}
+
+static int *
+write_section_data (FILE* fp, char *image,
+                    struct grub_pe32_coff_header *pe_chdr,
+                    struct grub_pe32_section_table *pe_shdr)
+{
+  int *section_map;
+  int i;
+
+  section_map = xmalloc ((pe_chdr->num_sections + 1) * sizeof (int));
+  section_map[0] = 0;
+
+  for (i = 0; i < pe_chdr->num_sections; i++, pe_shdr++)
+    {
+      grub_uint32_t idx;
+
+      if (! strcmp (pe_shdr->name, ".text"))
+        {
+          idx = TEXT_SECTION;
+          shdr[idx].sh_flags = SHF_ALLOC | SHF_EXECINSTR;
+        }
+      else if (! strcmp (pe_shdr->name, ".rdata"))
+        {
+          idx = RDATA_SECTION;
+          shdr[idx].sh_flags = SHF_ALLOC;
+        }
+      else if (! strcmp (pe_shdr->name, ".data"))
+        {
+          idx = DATA_SECTION;
+          shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE;
+        }
+      else if (! strcmp (pe_shdr->name, ".bss"))
+        {
+          idx = BSS_SECTION;
+          shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE;
+        }
+      else if (! strcmp (pe_shdr->name, ".modname"))
+        idx = MODNAME_SECTION;
+      else if (! strcmp (pe_shdr->name, ".moddeps"))
+        idx = MODDEPS_SECTION;
+      else
+        {
+          section_map[i + 1] = -1;
+          continue;
+        }
+
+      section_map[i + 1] = idx;
+
+      shdr[idx].sh_type = (idx == BSS_SECTION) ? SHT_NOBITS : SHT_PROGBITS;
+      shdr[idx].sh_size = pe_shdr->raw_data_size;
+      shdr[idx].sh_addralign = 1 << (((pe_shdr->characteristics >>
+                                       GRUB_PE32_SCN_ALIGN_SHIFT) &
+                                      GRUB_PE32_SCN_ALIGN_MASK) - 1);
+
+      if (idx != BSS_SECTION)
+        {
+          shdr[idx].sh_offset = offset;
+          grub_util_write_image_at (image + pe_shdr->raw_data_offset,
+                                    pe_shdr->raw_data_size, offset, fp);
+
+          offset += pe_shdr->raw_data_size;
+        }
+
+      if (pe_shdr->relocations_offset)
+        {
+          char name[5 + strlen (pe_shdr->name)];
+
+          if (num_sections >= MAX_SECTIONS)
+            grub_util_error ("Too many sections");
+
+          sprintf (name, ".rel%s", pe_shdr->name);
+
+          shdr[num_sections].sh_name = insert_string (name);
+          shdr[num_sections].sh_link = i;
+          shdr[num_sections].sh_info = idx;
+
+          shdr[idx].sh_name = shdr[num_sections].sh_name + 4;
+
+          num_sections++;
+        }
+      else
+        shdr[idx].sh_name = insert_string (pe_shdr->name);
+    }
+
+  return section_map;
+}
+
+static void
+write_reloc_section (FILE* fp, char *image,
+                     struct grub_pe32_coff_header *pe_chdr,
+                     struct grub_pe32_section_table *pe_shdr,
+                     Elf32_Sym *symtab,
+                     int *symtab_map)
+{
+  int i;
+
+  for (i = REL_SECTION; i < num_sections; i++)
+    {
+      struct grub_pe32_section_table *pe_sec;
+      struct grub_pe32_reloc *pe_rel;
+      Elf32_Rel *rel;
+      int num_rels, j, modified;
+
+      pe_sec = pe_shdr + shdr[i].sh_link;
+      pe_rel = (struct grub_pe32_reloc *) (image + pe_sec->relocations_offset);
+      rel = (Elf32_Rel *) xmalloc (pe_sec->num_relocations * sizeof (Elf32_Rel));
+      num_rels = 0;
+      modified = 0;
+
+      for (j = 0; j < pe_sec->num_relocations; j++, pe_rel++)
+        {
+          int type;
+          grub_uint32_t ofs, *addr;
+
+          if ((pe_rel->symtab_index >= pe_chdr->num_symbols) ||
+              (symtab_map[pe_rel->symtab_index] == -1))
+            grub_util_error ("Invalid symbol");
+
+          if (pe_rel->type == GRUB_PE32_REL_I386_DIR32)
+            type = R_386_32;
+          else if (pe_rel->type == GRUB_PE32_REL_I386_REL32)
+            type = R_386_PC32;
+          else
+            grub_util_error ("Unknown pe relocation type %d\n", pe_rel->type);
+
+          ofs = pe_rel->offset - pe_sec->virtual_address;
+          addr = (grub_uint32_t *)(image + pe_sec->raw_data_offset + ofs);
+          if (type == R_386_PC32)
+            {
+              unsigned char code;
+
+              code = image[pe_sec->raw_data_offset + ofs - 1];
+
+              if (((code != 0xe8) && (code != 0xe9)) || (*addr))
+                grub_util_error ("Invalid relocation (%x %x)", code, *addr);
+
+              modified = 1;
+              if (symtab[symtab_map[pe_rel->symtab_index]].st_shndx)
+                {
+                  if (symtab[symtab_map[pe_rel->symtab_index]].st_shndx
+                      != shdr[i].sh_info)
+                    grub_util_error ("Cross section call is not allowed");
+
+                  *addr = (symtab[symtab_map[pe_rel->symtab_index]].st_value
+                           - ofs - 4);
+
+                  continue;
+                }
+              else
+                *addr = -4;
+            }
+
+          rel[num_rels].r_offset = ofs;
+          rel[num_rels].r_info = ELF32_R_INFO (symtab_map[pe_rel->symtab_index],
+                                               type);
+          num_rels++;
+        }
+
+      if (modified)
+        grub_util_write_image_at (image + pe_sec->raw_data_offset,
+                                  shdr[shdr[i].sh_info].sh_size,
+                                  shdr[shdr[i].sh_info].sh_offset,
+                                  fp);
+
+      shdr[i].sh_type = SHT_REL;
+      shdr[i].sh_offset = offset;
+      shdr[i].sh_link = SYMTAB_SECTION;
+      shdr[i].sh_addralign = 4;
+      shdr[i].sh_entsize = sizeof (Elf32_Rel);
+      shdr[i].sh_size = num_rels * sizeof (Elf32_Rel);
+
+      grub_util_write_image_at (rel, shdr[i].sh_size, offset, fp);
+      offset += shdr[i].sh_size;
+      free (rel);
+    }
+}
+
+static void
+write_symbol_table (FILE* fp, char *image,
+                    struct grub_pe32_coff_header *pe_chdr,
+                    struct grub_pe32_section_table *pe_shdr,
+                    int *section_map)
+{
+  struct grub_pe32_symbol *pe_symtab;
+  char *pe_strtab;
+  Elf32_Sym *symtab;
+  int *symtab_map, num_syms;
+  int i;
+
+  pe_symtab = (struct grub_pe32_symbol *) (image + pe_chdr->symtab_offset);
+  pe_strtab = (char *) (pe_symtab + pe_chdr->num_symbols);
+
+  symtab = (Elf32_Sym *) xmalloc ((pe_chdr->num_symbols + 1) *
+                                  sizeof (Elf32_Sym));
+  memset (symtab, 0, (pe_chdr->num_symbols + 1) * sizeof (Elf32_Sym));
+  num_syms = 1;
+
+  symtab_map = (int *) xmalloc (pe_chdr->num_symbols * sizeof (int));
+
+  for (i = 0; i < (int) pe_chdr->num_symbols;
+       i += pe_symtab->num_aux + 1, pe_symtab += pe_symtab->num_aux + 1)
+    {
+      int bind, type;
+
+      symtab_map[i] = -1;
+      if ((pe_symtab->section > pe_chdr->num_sections) ||
+          (section_map[pe_symtab->section] == -1))
+        continue;
+
+      if (! pe_symtab->section)
+        type = STT_NOTYPE;
+      else if (pe_symtab->type == GRUB_PE32_DT_FUNCTION)
+        type = STT_FUNC;
+      else
+        type = STT_OBJECT;
+
+      if (pe_symtab->storage_class == GRUB_PE32_SYM_CLASS_EXTERNAL)
+        bind = STB_GLOBAL;
+      else
+        bind = STB_LOCAL;
+
+      if ((type != STT_FUNC) && (pe_symtab->num_aux))
+        {
+          if (! pe_symtab->value)
+            type = STT_SECTION;
+
+          symtab[num_syms].st_name = shdr[section_map[pe_symtab->section]].sh_name;
+        }
+      else
+        {
+          char *name;
+
+          name = ((pe_symtab->long_name[0]) ? pe_symtab->short_name :
+                  pe_strtab + pe_symtab->long_name[1]);
+
+          if ((strcmp (name, "_grub_mod_init")) &&
+              (strcmp (name, "_grub_mod_fini")) &&
+              (bind == STB_LOCAL))
+              continue;
+
+          symtab[num_syms].st_name = insert_string (name);
+        }
+
+      symtab[num_syms].st_shndx = section_map[pe_symtab->section];
+      symtab[num_syms].st_value = pe_symtab->value;
+      symtab[num_syms].st_info = ELF32_ST_INFO (bind, type);
+
+      symtab_map[i] = num_syms;
+      num_syms++;
+    }
+
+  write_reloc_section (fp, image, pe_chdr, pe_shdr, symtab, symtab_map);
+
+  shdr[SYMTAB_SECTION].sh_name = insert_string (".symtab");
+  shdr[SYMTAB_SECTION].sh_type = SHT_SYMTAB;
+  shdr[SYMTAB_SECTION].sh_offset = offset;
+  shdr[SYMTAB_SECTION].sh_size = num_syms * sizeof (Elf32_Sym);
+  shdr[SYMTAB_SECTION].sh_entsize = sizeof (Elf32_Sym);
+  shdr[SYMTAB_SECTION].sh_link = STRTAB_SECTION;
+  shdr[SYMTAB_SECTION].sh_addralign = 4;
+
+  grub_util_write_image_at (symtab, shdr[SYMTAB_SECTION].sh_size,
+                            offset, fp);
+  offset += shdr[SYMTAB_SECTION].sh_size;
+
+  free (symtab);
+  free (symtab_map);
+}
+
+static void
+write_string_table (FILE* fp)
+{
+  shdr[STRTAB_SECTION].sh_name = insert_string (".strtab");
+  shdr[STRTAB_SECTION].sh_type = SHT_STRTAB;
+  shdr[STRTAB_SECTION].sh_offset = offset;
+  shdr[STRTAB_SECTION].sh_size = strtab_len;
+  shdr[STRTAB_SECTION].sh_addralign = 1;
+  grub_util_write_image_at (strtab, strtab_len, offset, fp);
+  offset += strtab_len;
+
+  free (strtab);
+}
+
+static void
+write_section_header (FILE* fp)
+{
+  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_ident[EI_VERSION] = EV_CURRENT;
+  ehdr.e_version = EV_CURRENT;
+  ehdr.e_type = ET_REL;
+
+  ehdr.e_ident[EI_CLASS] = ELFCLASS32;
+  ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
+  ehdr.e_machine = EM_386;
+
+  ehdr.e_ehsize = sizeof (ehdr);
+  ehdr.e_shentsize = sizeof (Elf32_Shdr);
+  ehdr.e_shstrndx = STRTAB_SECTION;
+
+  ehdr.e_shoff = offset;
+  ehdr.e_shnum = num_sections;
+  grub_util_write_image_at (&shdr, sizeof (Elf32_Shdr) * num_sections,
+                            offset, fp);
+
+  grub_util_write_image_at (&ehdr, sizeof (Elf32_Ehdr), 0, fp);
+}
+
+static void
+convert_pe (FILE* fp, char *image)
+{
+  struct grub_pe32_coff_header *pe_chdr;
+  struct grub_pe32_section_table *pe_shdr;
+  int *section_map;
+
+  pe_chdr = (struct grub_pe32_coff_header *) image;
+  if (grub_le_to_cpu16 (pe_chdr->machine) != GRUB_PE32_MACHINE_I386)
+    grub_util_error ("Invalid coff image");
+
+  strtab = xmalloc (STRTAB_BLOCK);
+  strtab_max = STRTAB_BLOCK;
+  strtab[0] = 0;
+  strtab_len = 1;
+
+  offset = sizeof (ehdr);
+  pe_shdr = (struct grub_pe32_section_table *) (pe_chdr + 1);
+  num_sections = REL_SECTION;
+
+  section_map = write_section_data (fp, image, pe_chdr, pe_shdr);
+
+  write_symbol_table (fp, image, pe_chdr, pe_shdr, section_map);
+  free (section_map);
+
+  write_string_table (fp);
+
+  write_section_header (fp);
+}
+
+int
+main (int argc, char *argv[])
+{
+  char *image;
+  FILE* fp;
+
+  progname = "grub-pe2elf";
+
+    /* Check for options.  */
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "hVv", options, 0);
+
+      if (c == -1)
+       break;
+      else
+       switch (c)
+         {
+         case 'h':
+           usage (0);
+           break;
+
+         case 'V':
+           printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
+           return 0;
+
+         case 'v':
+           verbosity++;
+           break;
+
+         default:
+           usage (1);
+           break;
+         }
+    }
+
+  /* Obtain PATH.  */
+  if (optind >= argc)
+    {
+      fprintf (stderr, "Filename not specified.\n");
+      usage (1);
+    }
+
+  image = grub_util_read_image (argv[optind]);
+
+  if (optind + 1 < argc)
+    optind++;
+
+  fp = fopen (argv[optind], "wb");
+  if (! fp)
+    grub_util_error ("cannot open %s", argv[optind]);
+
+  convert_pe (fp, image);
+
+  fclose (fp);
+
+  return 0;
+}
diff --git a/util/grub-probe.c b/util/grub-probe.c
new file mode 100644 (file)
index 0000000..402b758
--- /dev/null
@@ -0,0 +1,387 @@
+/* grub-probe.c - probe device information for a given path */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2005,2006,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/>.
+ */
+
+#include <config.h>
+#include <grub/types.h>
+#include <grub/util/misc.h>
+#include <grub/device.h>
+#include <grub/disk.h>
+#include <grub/file.h>
+#include <grub/fs.h>
+#include <grub/partition.h>
+#include <grub/pc_partition.h>
+#include <grub/util/hostdisk.h>
+#include <grub/util/getroot.h>
+#include <grub/term.h>
+#include <grub/env.h>
+
+#include <grub_probe_init.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#define _GNU_SOURCE    1
+#include <getopt.h>
+
+enum {
+  PRINT_FS,
+  PRINT_FS_UUID,
+  PRINT_DRIVE,
+  PRINT_DEVICE,
+  PRINT_PARTMAP,
+  PRINT_ABSTRACTION,
+};
+
+int print = PRINT_FS;
+static unsigned int argument_is_device = 0;
+
+void
+grub_putchar (int c)
+{
+  putchar (c);
+}
+
+int
+grub_getkey (void)
+{
+  return -1;
+}
+
+grub_term_input_t
+grub_term_get_current_input (void)
+{
+  return 0;
+}
+
+grub_term_output_t
+grub_term_get_current_output (void)
+{
+  return 0;
+}
+
+void
+grub_refresh (void)
+{
+  fflush (stdout);
+}
+
+static void
+probe_partmap (grub_disk_t disk)
+{
+  char *name;
+  char *underscore;
+  
+  if (disk->partition == NULL)
+    {
+      grub_util_info ("No partition map found for %s", disk->name);
+      return;
+    }
+  
+  name = strdup (disk->partition->partmap->name);
+  if (! name)
+    grub_util_error ("Not enough memory");
+  
+  underscore = strchr (name, '_');
+  if (! underscore)
+    grub_util_error ("Invalid partition map %s", name);
+  
+  *underscore = '\0';
+  printf ("%s\n", name);
+  free (name);
+}
+
+static void
+probe (const char *path, char *device_name)
+{
+  char *drive_name = NULL;
+  char *grub_path = NULL;
+  char *filebuf_via_grub = NULL, *filebuf_via_sys = NULL;
+  int abstraction_type;
+  grub_device_t dev = NULL;
+  grub_fs_t fs;
+  
+  if (path == NULL)
+    {
+      if (! grub_util_check_block_device (device_name))
+        grub_util_error ("%s is not a block device.\n", device_name);
+    }
+  else
+    device_name = grub_guess_root_device (path);
+
+  if (! device_name)
+    grub_util_error ("cannot find a device for %s.\n", path);
+
+  if (print == PRINT_DEVICE)
+    {
+      printf ("%s\n", device_name);
+      goto end;
+    }
+
+  abstraction_type = grub_util_get_dev_abstraction (device_name);
+  /* No need to check for errors; lack of abstraction is permissible.  */
+  
+  if (print == PRINT_ABSTRACTION)
+    {
+      char *abstraction_name;
+      switch (abstraction_type)
+       {
+       case GRUB_DEV_ABSTRACTION_LVM:
+         abstraction_name = "lvm";
+         break;
+       case GRUB_DEV_ABSTRACTION_RAID:
+         abstraction_name = "raid mdraid";
+         break;
+       default:
+         grub_util_info ("did not find LVM/RAID in %s, assuming raw device", device_name);
+         goto end;
+       }
+      printf ("%s\n", abstraction_name);
+      goto end;
+    }
+
+  drive_name = grub_util_get_grub_dev (device_name);
+  if (! drive_name)
+    grub_util_error ("Cannot find a GRUB drive for %s.  Check your device.map.\n", device_name);
+  
+  if (print == PRINT_DRIVE)
+    {
+      printf ("(%s)\n", drive_name);
+      goto end;
+    }
+
+  grub_util_info ("opening %s", drive_name);
+  dev = grub_device_open (drive_name);
+  if (! dev)
+    grub_util_error ("%s", grub_errmsg);
+
+  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);
+         tmp = list->next;
+         free (list);
+         list = tmp;
+       }
+      goto end;
+    }
+
+  fs = grub_fs_probe (dev);
+  if (! fs)
+    grub_util_error ("%s", grub_errmsg);
+
+  if (print == PRINT_FS)
+    {
+      struct stat st;
+
+      stat (path, &st);
+
+      if (st.st_mode == S_IFREG)
+       {
+         /* Regular file.  Verify that we can read it properly.  */
+
+         grub_file_t file;
+         grub_util_info ("reading %s via OS facilities", path);
+         filebuf_via_sys = grub_util_read_image (path);
+         
+         grub_util_info ("reading %s via GRUB facilities", path);
+         asprintf (&grub_path, "(%s)%s", drive_name, path);
+         file = grub_file_open (grub_path);
+         filebuf_via_grub = xmalloc (file->size);
+         grub_file_read (file, filebuf_via_grub, file->size);
+         
+         grub_util_info ("comparing");
+         
+         if (memcmp (filebuf_via_grub, filebuf_via_sys, file->size))
+           grub_util_error ("files differ");
+       }
+      printf ("%s\n", fs->name);
+    }
+
+  if (print == PRINT_FS_UUID)
+    {
+      char *uuid;
+      if (! fs->uuid)
+       grub_util_error ("%s does not support UUIDs", fs->name);
+
+      fs->uuid (dev, &uuid);
+
+      printf ("%s\n", uuid);
+    }
+
+ end:
+  if (dev)
+    grub_device_close (dev);
+  free (grub_path);
+  free (filebuf_via_grub);
+  free (filebuf_via_sys);
+  free (drive_name);
+}
+
+static struct option options[] =
+  {
+    {"device", no_argument, 0, 'd'},
+    {"device-map", required_argument, 0, 'm'},
+    {"target", required_argument, 0, 't'},
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+    {"verbose", no_argument, 0, 'v'},
+    {0, 0, 0, 0}
+  };
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr,
+            "Try ``grub-probe --help'' for more information.\n");
+  else
+    printf ("\
+Usage: grub-probe [OPTION]... [PATH|DEVICE]\n\
+\n\
+Probe device information for a given path (or device, if the -d option is given).\n\
+\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|drive|device|partmap|abstraction)\n\
+                            print filesystem module, GRUB drive, system device, partition map module or abstraction module [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\
+\n\
+Report bugs to <%s>.\n\
+",
+           DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
+  
+  exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+  char *dev_map = 0;
+  char *argument;
+  
+  progname = "grub-probe";
+  
+  /* Check for options.  */
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "dm:t:hVv", options, 0);
+      
+      if (c == -1)
+       break;
+      else
+       switch (c)
+         {
+         case 'd':
+           argument_is_device = 1;
+           break;
+
+         case 'm':
+           if (dev_map)
+             free (dev_map);
+
+           dev_map = xstrdup (optarg);
+           break;
+
+         case 't':
+           if (!strcmp (optarg, "fs"))
+             print = PRINT_FS;
+           else if (!strcmp (optarg, "fs_uuid"))
+             print = PRINT_FS_UUID;
+           else if (!strcmp (optarg, "drive"))
+             print = PRINT_DRIVE;
+           else if (!strcmp (optarg, "device"))
+             print = PRINT_DEVICE;
+           else if (!strcmp (optarg, "partmap"))
+             print = PRINT_PARTMAP;
+           else if (!strcmp (optarg, "abstraction"))
+             print = PRINT_ABSTRACTION;
+           else
+             usage (1);
+           break;
+
+         case 'h':
+           usage (0);
+           break;
+
+         case 'V':
+           printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
+           return 0;
+
+         case 'v':
+           verbosity++;
+           break;
+
+         default:
+           usage (1);
+           break;
+         }
+    }
+
+  if (verbosity > 1)
+    grub_env_set ("debug", "all");
+
+  /* Obtain ARGUMENT.  */
+  if (optind >= argc)
+    {
+      fprintf (stderr, "No path or device is specified.\n");
+      usage (1);
+    }
+
+  if (optind + 1 != argc)
+    {
+      fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
+      usage (1);
+    }
+
+  argument = argv[optind];
+  
+  /* Initialize the emulated biosdisk driver.  */
+  grub_util_biosdisk_init (dev_map ? : DEFAULT_DEVICE_MAP);
+  
+  /* Initialize all modules. */
+  grub_init_all ();
+
+  /* Do it.  */
+  if (argument_is_device)
+    probe (NULL, argument);
+  else
+    probe (argument, NULL);
+  
+  /* Free resources.  */
+  grub_fini_all ();
+  grub_util_biosdisk_fini ();
+  
+  free (dev_map);
+  
+  return 0;
+}
diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
new file mode 100644 (file)
index 0000000..d8fa416
--- /dev/null
@@ -0,0 +1,114 @@
+#! /bin/sh -e
+
+# update-grub helper script.
+# Copyright (C) 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/>.
+
+transform="@program_transform_name@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+grub_prefix=`echo /boot/grub | sed ${transform}`
+
+. ${libdir}/grub/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)
+for i in ${GRUB_PRELOAD_MODULES} ; do
+  echo "insmod $i"
+done
+
+if [ "x${GRUB_DEFAULT}" = "x" ] ; then GRUB_DEFAULT=0 ; fi
+if [ "x${GRUB_TIMEOUT}" = "x" ] ; then GRUB_TIMEOUT=5 ; fi
+if [ "x${GRUB_GFXMODE}" = "x" ] ; then GRUB_GFXMODE=640x480 ; fi
+
+cat << EOF
+set default=${GRUB_DEFAULT}
+set timeout=${GRUB_TIMEOUT}
+EOF
+
+case ${GRUB_TERMINAL_INPUT}:${GRUB_TERMINAL_OUTPUT} in
+  serial:* | *:serial)
+    if ! test -e ${grub_prefix}/serial.mod ; then
+      echo "Serial terminal not available on this platform." >&2 ; exit 1
+    fi
+
+    if [ "x${GRUB_SERIAL_COMMAND}" = "x" ] ; then
+      grub_warn "Requested serial terminal but GRUB_SERIAL_COMMAND is unspecified. Default parameters will be used."
+      GRUB_SERIAL_COMMAND=serial
+    fi
+    echo "${GRUB_SERIAL_COMMAND}"
+  ;;
+esac
+
+case x${GRUB_TERMINAL_INPUT} in
+  x)
+    # Just use the native terminal
+  ;;
+  x*)
+    cat << EOF
+if terminal_input ${GRUB_TERMINAL_INPUT} ; then true ; else
+  # For backward compatibility with versions of terminal.mod that don't
+  # understand terminal_input
+  terminal ${GRUB_TERMINAL_INPUT}
+fi
+EOF
+  ;;
+esac
+
+case x${GRUB_TERMINAL_OUTPUT} in
+ xgfxterm)
+    # Make the font accessible
+    prepare_grub_to_access_device `${grub_probe} --target=device ${GRUB_FONT_PATH}`
+
+    # Pick a video backend
+    video_backend=
+    for i in vbe ; do
+      if test -e ${grub_prefix}/$i.mod ; then
+        video_backend=$i
+        break
+      fi
+    done
+    if ! [ "${video_backend}" ] ; then
+      echo "No suitable backend could be found for gfxterm." >&2 ; exit 1
+    fi
+
+    cat << EOF
+if loadfont `make_system_path_relative_to_its_root ${GRUB_FONT_PATH}` ; then
+  set gfxmode=${GRUB_GFXMODE}
+  insmod gfxterm
+  insmod ${video_backend}
+  if terminal_output gfxterm ; then true ; else
+    # For backward compatibility with versions of terminal.mod that don't
+    # understand terminal_output
+    terminal gfxterm
+  fi
+fi
+EOF
+  ;;
+  x)
+    # Just use the native terminal
+  ;;
+  x*)
+    cat << EOF
+if terminal_output ${GRUB_TERMINAL_OUTPUT} ; then true ; else
+  # For backward compatibility with versions of terminal.mod that don't
+  # understand terminal_output
+  terminal ${GRUB_TERMINAL_OUTPUT}
+fi
+EOF
+  ;;
+esac
diff --git a/util/grub.d/10_freebsd.in b/util/grub.d/10_freebsd.in
new file mode 100644 (file)
index 0000000..61d5450
--- /dev/null
@@ -0,0 +1,60 @@
+#! /bin/sh -e
+
+# grub-mkconfig helper script.
+# 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/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+. ${libdir}/grub/grub-mkconfig_lib
+
+devices=/boot/devices.hints
+if ! test -e ${devices} ; then
+  # not FreeBSD
+  exit 0
+fi
+
+if test -e /boot/kernel/kernel ; then
+  kfreebsd=/boot/kernel/kernel
+fi
+
+if [ "x$kfreebsd" != "x" ] ; then
+  echo "Found kernel of FreeBSD: $kfreebsd" >&2
+
+  kfreebsd_basename=`basename $kfreebsd`
+  kfreebsd_dirname=`dirname $kfreebsd`
+  kfreebsd_rel_dirname=`make_system_path_relative_to_its_root $kfreebsd_dirname`
+
+  devices_basename=`basename $devices`
+  devices_dirname=`dirname $devices`
+  devices_rel_dirname=`make_system_path_relative_to_its_root $devices_dirname`
+
+  root_device=`basename ${GRUB_DEVICE}`
+
+  # For "ufs" it's the same.  Do we care about the others?
+  kfreebsd_fs=${GRUB_FS}
+
+  cat << EOF
+menuentry "FreeBSD" {
+EOF
+  prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/"
+  cat << EOF
+       freebsd                 ${kfreebsd_rel_dirname}/${kfreebsd_basename}
+       freebsd_loadenv         ${devices_rel_dirname}/${devices_basename}
+       set FreeBSD.vfs.root.mountfrom=${kfreebsd_fs}:${root_device}
+}
+EOF
+fi
diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in
new file mode 100644 (file)
index 0000000..12d61b0
--- /dev/null
@@ -0,0 +1,85 @@
+#! /bin/sh -e
+
+# update-grub helper script.
+# Copyright (C) 2006,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/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+. ${libdir}/grub/grub-mkconfig_lib
+
+if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
+  OS=GNU
+else
+  OS="${GRUB_DISTRIBUTOR} GNU/Hurd"
+fi
+
+at_least_one=false
+all_of_them=true
+
+# FIXME: add l4 here?
+kernel=
+for i in /boot/gnumach.gz /boot/gnumach ; do
+  if test -e $i ; then
+    basename=`basename $i`
+    dirname=`dirname $i`
+    rel_dirname=`make_system_path_relative_to_its_root $dirname`
+    echo "Found GNU Mach: $i" >&2
+    kernel=${rel_dirname}/${basename}
+    at_least_one=true
+  fi
+done
+
+# FIXME: This works for ext2.  For other filesystems we might need special-casing
+case "${GRUB_FS}" in
+  *fs) hurd_fs="${GRUB_FS}" ;;
+  *)   hurd_fs="${GRUB_FS}fs" ;;
+esac
+
+for i in /hurd/${hurd_fs}.static /hurd/exec ; do
+  if test -e "$i" ; then 
+    echo "Found Hurd module: $i" >&2
+    at_least_one=true
+  else
+    all_of_them=false
+  fi
+done
+
+if ${at_least_one} ; then : ; else
+  # no hurd here, aborting silently
+  exit 0
+fi
+
+if ${all_of_them} && test -e /lib/ld.so.1 ; then : ; else
+  echo "Some Hurd stuff found, but not enough to boot." >&2
+  exit 1
+fi
+
+cat << EOF
+menuentry "${OS}" {
+EOF
+prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/"
+cat << EOF
+       multiboot ${kernel} root=device:${GRUB_DEVICE}
+       module /hurd/${hurd_fs}.static --readonly \\
+                       --multiboot-command-line='\${kernel-command-line}' \\
+                       --host-priv-port='\${host-port}' \\
+                       --device-master-port='\${device-port}' \\
+                       --exec-server-task='\${exec-task}' -T typed '\${root}' \\
+                       '\$(task-create)' '\$(task-resume)'
+       module /lib/ld.so.1 /hurd/exec '\$(exec-task=task-create)'
+}
+EOF
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
new file mode 100644 (file)
index 0000000..7cd5a9e
--- /dev/null
@@ -0,0 +1,158 @@
+#! /bin/sh -e
+
+# update-grub helper script.
+# Copyright (C) 2006,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/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+. ${libdir}/grub/grub-mkconfig_lib
+
+if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
+  OS=GNU/Linux
+else
+  OS="${GRUB_DISTRIBUTOR} GNU/Linux"
+fi
+
+# loop-AES arranges things so that /dev/loop/X can be our root device, but
+# the initrds that Linux uses don't like that.
+case ${GRUB_DEVICE} in
+  /dev/loop/*|/dev/loop[0-9])
+    GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"`
+  ;;
+esac
+
+if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
+    || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" ; then
+  LINUX_ROOT_DEVICE=${GRUB_DEVICE}
+else
+  LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
+fi
+
+test_numeric ()
+{
+  local a=$1
+  local cmp=$2
+  local b=$3
+  if [ "$a" = "$b" ] ; then
+    case $cmp in
+      ge|eq|le) return 0 ;;
+      gt|lt) return 1 ;;
+    esac
+  fi
+  if [ "$cmp" = "lt" ] ; then
+    c=$a
+    a=$b
+    b=$c
+  fi
+  if (echo $a ; echo $b) | sort -n | head -n 1 | grep -qx $b ; then
+    return 0
+  else
+    return 1
+  fi
+}
+
+test_gt ()
+{
+  local a=`echo $1 | sed -e "s/vmlinu[zx]-//g"`
+  local b=`echo $2 | sed -e "s/vmlinu[zx]-//g"`
+  local cmp=gt
+  if [ "x$b" = "x" ] ; then
+    return 0
+  fi
+  case $a:$b in
+    *.old:*.old) ;;
+    *.old:*) a=`echo -n $a | sed -e s/\.old$//g` ; cmp=gt ;;
+    *:*.old) b=`echo -n $b | sed -e s/\.old$//g` ; cmp=ge ;;
+  esac
+  test_numeric $a $cmp $b
+  return $?
+}
+
+find_latest ()
+{
+  local a=""
+  for i in $@ ; do
+    if test_gt "$i" "$a" ; then
+      a="$i"
+    fi
+  done
+  echo "$a"
+}
+
+list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do
+        if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
+      done`
+
+while [ "x$list" != "x" ] ; do
+  linux=`find_latest $list`
+  echo "Found linux image: $linux" >&2
+  basename=`basename $linux`
+  dirname=`dirname $linux`
+  rel_dirname=`make_system_path_relative_to_its_root $dirname`
+  version=`echo $basename | sed -e "s,^[^0-9]*-,,g"`
+  alt_version=`echo $version | sed -e "s,\.old$,,g"`
+  linux_root_device_thisversion="${LINUX_ROOT_DEVICE}"
+
+  initrd=
+  for i in "initrd.img-${version}" "initrd-${version}.img" \
+          "initrd.img-${alt_version}" "initrd-${alt_version}.img"; do
+    if test -e "${dirname}/${i}" ; then
+      initrd="$i"
+      break
+    fi
+  done
+  if test -n "${initrd}" ; then
+    echo "Found initrd image: ${dirname}/${initrd}" >&2
+  else
+    # "UUID=" magic is parsed by initrds.  Since there's no initrd, it can't work here.
+    linux_root_device_thisversion=${GRUB_DEVICE}
+  fi
+
+  cat << EOF
+menuentry "${OS}, linux ${version}" {
+EOF
+  prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/"
+  cat << EOF
+       linux   ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}
+EOF
+  if test -n "${initrd}" ; then
+    cat << EOF
+       initrd  ${rel_dirname}/${initrd}
+EOF
+  fi
+  cat << EOF
+}
+EOF
+
+  cat << EOF
+menuentry "${OS}, linux ${version} (single-user mode)" {
+EOF
+  prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/"
+  cat << EOF
+       linux   ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro single ${GRUB_CMDLINE_LINUX}
+EOF
+  if test -n "${initrd}" ; then
+    cat << EOF
+       initrd  ${rel_dirname}/${initrd}
+EOF
+  fi
+  cat << EOF
+}
+EOF
+
+  list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '`
+done
diff --git a/util/grub.d/10_windows.in b/util/grub.d/10_windows.in
new file mode 100644 (file)
index 0000000..8877b15
--- /dev/null
@@ -0,0 +1,83 @@
+#! /bin/sh -e
+
+# update-grub helper script.
+# 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/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+. ${libdir}/grub/grub-mkconfig_lib
+
+case "`uname 2>/dev/null`" in
+  CYGWIN*)  ;;
+  *) exit 0 ;;
+esac
+
+# Try C: even if current system is on other partition.
+case "$SYSTEMDRIVE" in
+  [Cc]:)     dirlist="C:"              ;;
+  [D-Zd-z]:) dirlist="C: $SYSTEMDRIVE" ;;
+  *) exit 0 ;;
+esac
+
+get_os_name_from_boot_ini ()
+{
+  # Fail if no or more than one partition.
+  test "`sed -n 's,^\(\(multi\|scsi\)[^=]*\)=.*$,\1,p' "$1" 2>/dev/null | \
+    sort | uniq | wc -l`" = 1 || return 1
+
+  # Search 'default=PARTITION'
+  local part=`sed -n 's,^default=,,p' "$1" | sed 's,\\\\,/,g;s,[ \t\r]*$,,;1q'`
+  test -n "$part" || return 1
+
+  # Search 'PARTITION="NAME" ...'
+  local name=`sed -n 's,\\\\,/,g;s,^'"$part"'="\([^"]*\)".*$,\1,p' "$1" | sed 1q`
+  test -n "$name" || return 1
+
+  echo "$name"
+}
+
+
+for dir in $dirlist ; do
+
+  # Check for Vista bootmgr.
+  if [ -f "$dir"/bootmgr -a -f "$dir"/boot/bcd ] ; then
+    OS="Windows Vista bootmgr"
+
+  # Check for NTLDR.
+  elif [ -f "$dir"/ntldr -a -f "$dir"/ntdetect.com -a -f "$dir"/boot.ini ] ; then
+    OS=`get_os_name_from_boot_ini "$dir"/boot.ini` || OS="Windows NT/2000/XP loader"
+
+  else
+    continue
+  fi
+
+  # Get boot /dev/ice.
+  dev=`${grub_probe} -t device "$dir" 2>/dev/null` || continue
+
+  echo "Found $OS on $dir ($dev)" >&2
+  cat << EOF
+menuentry "$OS" {
+EOF
+
+  prepare_grub_to_access_device "$dev" | sed 's,^,\t,'
+
+  cat << EOF
+       chainloader +1
+}
+EOF
+done
+
diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
new file mode 100644 (file)
index 0000000..429cc95
--- /dev/null
@@ -0,0 +1,89 @@
+#! /bin/sh -e
+
+# update-grub helper script.
+# Copyright (C) 2006,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/>.
+
+if [ -z "`which os-prober 2> /dev/null`" -o -z "`which linux-boot-prober 2> /dev/null`" ] ; then
+  # missing os-prober and/or linux-boot-prober
+  exit 0
+fi
+
+OSPROBED="`os-prober 2> /dev/null | tr ' ' '^' | paste -s -d ' '`"
+if [ -z "${OSPROBED}" ] ; then
+  # empty os-prober output, nothing doing
+  exit 0
+fi
+
+for OS in ${OSPROBED} ; do
+  DEVICE="`echo ${OS} | cut -d ':' -f 1`"
+  LONGNAME="`echo ${OS} | cut -d ':' -f 2 | tr '^' ' '`"
+  LABEL="`echo ${OS} | cut -d ':' -f 3 | tr '^' ' '`"
+  BOOT="`echo ${OS} | cut -d ':' -f 4`"
+
+  if [ -z "${LONGNAME}" ] ; then
+    LONGNAME="${LABEL}"
+  fi
+
+  echo "Found ${LONGNAME} on ${DEVICE}" >&2
+
+  case ${BOOT} in
+    chain)
+      CHAINROOT="`grub-probe --target=drive --device ${DEVICE} 2> /dev/null`"
+
+      cat << EOF
+menuentry "${LONGNAME} (on ${DEVICE})" {
+       set root=${CHAINROOT}
+       chainloader +1
+}
+EOF
+    ;;
+    linux)
+      LINUXPROBED="`linux-boot-prober ${DEVICE} 2> /dev/null | tr ' ' '^' | paste -s -d ' '`"
+      for LINUX in ${LINUXPROBED} ; do
+        LROOT="`echo ${LINUX} | cut -d ':' -f 1`"
+        LBOOT="`echo ${LINUX} | cut -d ':' -f 2`"
+        LLABEL="`echo ${LINUX} | cut -d ':' -f 3 | tr '^' ' '`"
+        LKERNEL="`echo ${LINUX} | cut -d ':' -f 4`"
+        LINITRD="`echo ${LINUX} | cut -d ':' -f 5`"
+        LPARAMS="`echo ${LINUX} | cut -d ':' -f 6- | tr '^' ' '`"
+
+        LINUXROOT="`grub-probe --target=drive --device ${LBOOT} 2> /dev/null`"
+
+        if [ -z "${LLABEL}" ] ; then
+          LLABEL="${LONGNAME}"
+        fi
+
+        cat << EOF
+menuentry "${LLABEL} (on ${DEVICE})" {
+       set root=${LINUXROOT}
+       linux ${LKERNEL} ${LPARAMS}
+EOF
+        if [ -n "${LINITRD}" ] ; then
+          cat << EOF
+       initrd ${LINITRD}
+EOF
+        fi
+        cat << EOF
+}
+EOF
+      done
+    ;;
+    hurd|*)
+      echo "  ${LONGNAME} is not yet supported by grub-mkconfig." >&2
+    ;;
+  esac
+done
diff --git a/util/grub.d/40_custom.in b/util/grub.d/40_custom.in
new file mode 100644 (file)
index 0000000..e16d6e3
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec tail -n +3 $0
+# This file is an example on how to add custom entries
diff --git a/util/grub.d/README b/util/grub.d/README
new file mode 100644 (file)
index 0000000..3ea109d
--- /dev/null
@@ -0,0 +1,11 @@
+
+All executable files in this directory are processed in shell expansion order.
+
+  00_*: Reserved for 00_header.
+  10_*: Native boot entries.
+  20_*: Third party apps (e.g. memtest86+).
+
+The number namespace in-between is configurable by system installer and/or
+administrator.  For example, you can add an entry to boot another OS as
+01_otheros, 11_otheros, etc, depending on the position you want it to occupy in
+the menu; and then adjust the default setting via /etc/default/grub.
diff --git a/util/hostdisk.c b/util/hostdisk.c
new file mode 100644 (file)
index 0000000..67a1233
--- /dev/null
@@ -0,0 +1,940 @@
+/* biosdisk.c - emulate biosdisk */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2006,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/>.
+ */
+
+#include <grub/disk.h>
+#include <grub/partition.h>
+#include <grub/pc_partition.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/util/misc.h>
+#include <grub/util/hostdisk.h>
+#include <grub/misc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+
+#ifdef __linux__
+# include <sys/ioctl.h>         /* ioctl */
+# if !defined(__GLIBC__) || \
+        ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
+/* Maybe libc doesn't have large file support.  */
+#  include <linux/unistd.h>     /* _llseek */
+# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
+# ifndef BLKFLSBUF
+#  define BLKFLSBUF     _IO (0x12,97)   /* flush buffer cache */
+# endif /* ! BLKFLSBUF */
+# include <sys/ioctl.h>                /* ioctl */
+# ifndef HDIO_GETGEO
+#  define HDIO_GETGEO  0x0301  /* get device geometry */
+/* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is
+   defined.  */
+struct hd_geometry
+{
+  unsigned char heads;
+  unsigned char sectors;
+  unsigned short cylinders;
+  unsigned long start;
+};
+# endif /* ! HDIO_GETGEO */
+# ifndef BLKGETSIZE64
+#  define BLKGETSIZE64  _IOR(0x12,114,size_t)    /* return device size */
+# endif /* ! BLKGETSIZE64 */
+# ifndef MAJOR
+#  ifndef MINORBITS
+#   define MINORBITS   8
+#  endif /* ! MINORBITS */
+#  define MAJOR(dev)   ((unsigned) ((dev) >> MINORBITS))
+# endif /* ! MAJOR */
+# ifndef FLOPPY_MAJOR
+#  define FLOPPY_MAJOR 2
+# endif /* ! FLOPPY_MAJOR */
+# ifndef LOOP_MAJOR
+#  define LOOP_MAJOR   7
+# endif /* ! LOOP_MAJOR */
+#endif /* __linux__ */
+
+#ifdef __CYGWIN__
+# include <sys/ioctl.h>
+# include <cygwin/fs.h> /* BLKGETSIZE64 */
+# include <cygwin/hdreg.h> /* HDIO_GETGEO */
+# define MAJOR(dev)    ((unsigned) ((dev) >> 16))
+# define FLOPPY_MAJOR  2
+#endif
+
+struct
+{
+  char *drive;
+  char *device;
+} map[256];
+
+#ifdef __linux__
+/* Check if we have devfs support.  */
+static int
+have_devfs (void)
+{
+  static int dev_devfsd_exists = -1;
+
+  if (dev_devfsd_exists < 0)
+    {
+      struct stat st;
+
+      dev_devfsd_exists = stat ("/dev/.devfsd", &st) == 0;
+    }
+
+  return dev_devfsd_exists;
+}
+#endif /* __linux__ */
+
+static int
+find_grub_drive (const char *name)
+{
+  unsigned int i;
+
+  if (name)
+    {
+      for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
+       if (map[i].drive && ! strcmp (map[i].drive, name))
+         return i;
+    }
+
+  return -1;
+}
+
+static int
+find_free_slot ()
+{
+  unsigned int i;
+
+  for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
+    if (! map[i].drive)
+      return i;
+
+  return -1;
+}
+
+static int
+grub_util_biosdisk_iterate (int (*hook) (const char *name))
+{
+  unsigned i;
+
+  for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
+    if (map[i].drive && hook (map[i].drive))
+      return 1;
+
+  return 0;
+}
+
+static grub_err_t
+grub_util_biosdisk_open (const char *name, grub_disk_t disk)
+{
+  int drive;
+  struct stat st;
+  
+  drive = find_grub_drive (name);
+  if (drive < 0)
+    return grub_error (GRUB_ERR_BAD_DEVICE,
+                      "no mapping exists for `%s'", name);
+  
+  disk->has_partitions = 1;
+  disk->id = drive;
+
+  /* Get the size.  */
+#if defined(__MINGW32__)
+  {
+    grub_uint64_t size;
+
+    size = grub_util_get_disk_size (map[drive].device);
+
+    if (size % 512)
+      grub_util_error ("unaligned device size");
+
+    disk->total_sectors = size >> 9;
+
+    grub_util_info ("the size of %s is %llu", name, disk->total_sectors);
+
+    return GRUB_ERR_NONE;
+  }
+#elif defined(__linux__) || defined(__CYGWIN__)
+  {
+    unsigned long long nr;
+    int fd;
+
+    fd = open (map[drive].device, O_RDONLY);
+    if (fd == -1)
+      return grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to get disk size", map[drive].device);
+
+    if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode))
+      {
+       close (fd);
+       goto fail;
+      }
+    
+    if (ioctl (fd, BLKGETSIZE64, &nr))
+      {
+       close (fd);
+       goto fail;
+      }
+
+    close (fd);
+    disk->total_sectors = nr / 512;
+
+    if (nr % 512)
+      grub_util_error ("unaligned device size");
+    
+    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_BAD_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 __linux__
+static int
+linux_find_partition (char *dev, unsigned long sector)
+{
+  size_t len = strlen (dev);
+  const char *format;
+  char *p;
+  int i;
+  char real_dev[PATH_MAX];
+
+  strcpy(real_dev, dev);
+
+  if (have_devfs () && strcmp (real_dev + len - 5, "/disc") == 0)
+    {
+      p = real_dev + len - 4;
+      format = "part%d";
+    }
+  else if (real_dev[len - 1] >= '0' && real_dev[len - 1] <= '9')
+    {
+      p = real_dev + len;
+      format = "p%d";
+    }
+  else
+    {
+      p = real_dev + len;
+      format = "%d";
+    }
+
+  for (i = 1; i < 10000; i++)
+    {
+      int fd;
+      struct hd_geometry hdg;
+
+      sprintf (p, format, i);
+      fd = open (real_dev, O_RDONLY);
+      if (fd == -1)
+       return 0;
+
+      if (ioctl (fd, HDIO_GETGEO, &hdg))
+       {
+         close (fd);
+         return 0;
+       }
+
+      close (fd);
+
+      if (hdg.start == sector)
+       {
+         strcpy (dev, real_dev);
+         return 1;
+       }
+    }
+
+  return 0;
+}
+#endif /* __linux__ */
+
+static int
+open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
+{
+  int fd;
+
+#ifdef O_LARGEFILE
+  flags |= O_LARGEFILE;
+#endif
+#ifdef O_SYNC
+  flags |= O_SYNC;
+#endif
+#ifdef O_FSYNC
+  flags |= O_FSYNC;
+#endif
+#ifdef O_BINARY
+  flags |= O_BINARY;
+#endif
+  
+#ifdef __linux__
+  /* Linux has a bug that the disk cache for a whole disk is not consistent
+     with the one for a partition of the disk.  */
+  {
+    int is_partition = 0;
+    char dev[PATH_MAX];
+    
+    strcpy (dev, map[disk->id].device);
+    if (disk->partition && strncmp (map[disk->id].device, "/dev/", 5) == 0)
+      is_partition = linux_find_partition (dev, disk->partition->start);
+    
+    /* Open the partition.  */
+    grub_dprintf ("hostdisk", "opening the device `%s' in open_device()", dev);
+    fd = open (dev, flags);
+    if (fd < 0)
+      {
+       grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", dev);
+       return -1;
+      }
+
+    /* Make the buffer cache consistent with the physical disk.  */
+    ioctl (fd, BLKFLSBUF, 0);
+
+    if (is_partition)
+      sector -= disk->partition->start;
+  }
+#else /* ! __linux__ */
+  fd = open (map[disk->id].device, flags);
+  if (fd < 0)
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' in open_device()", map[disk->id].device);
+      return -1;
+    }
+#endif /* ! __linux__ */
+
+#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
+
+  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 size = len;
+  
+  while (len)
+    {
+      ssize_t ret = read (fd, buf, len);
+      
+      if (ret <= 0)
+        {
+          if (errno == EINTR)
+            continue;
+          else
+            return ret;
+        }
+      
+      len -= ret;
+      buf += ret;
+    }
+  
+  return size;
+}
+
+/* Write LEN bytes from BUF to FD. Return less than or equal to zero if an
+   error occurs, otherwise return LEN.  */
+static ssize_t
+nwrite (int fd, const char *buf, size_t len)
+{
+  ssize_t size = len;
+  
+  while (len)
+    {
+      ssize_t ret = write (fd, buf, len);
+      
+      if (ret <= 0)
+        {
+          if (errno == EINTR)
+            continue;
+          else
+            return ret;
+        }
+      
+      len -= ret;
+      buf += ret;
+    }
+  
+  return size;
+}
+
+static grub_err_t
+grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
+                        grub_size_t size, char *buf)
+{
+  int fd;
+
+  fd = open_device (disk, sector, O_RDONLY);
+  if (fd < 0)
+    return grub_errno;
+  
+#ifdef __linux__
+  if (sector == 0 && size > 1)
+    {
+      /* Work around a bug in Linux ez remapping.  Linux remaps all
+        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)
+       {
+         grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
+         close (fd);
+         return grub_errno;
+       }
+      
+      buf += GRUB_DISK_SECTOR_SIZE;
+      size--;
+    }
+#endif /* __linux__ */
+  
+  if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS)
+      != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+    grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
+
+  close (fd);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
+                         grub_size_t size, const char *buf)
+{
+  int fd;
+
+  fd = open_device (disk, sector, O_WRONLY);
+  if (fd < 0)
+    return grub_errno;
+  
+  if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS)
+      != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+    grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device);
+
+  close (fd);
+  return grub_errno;
+}
+
+static struct grub_disk_dev grub_util_biosdisk_dev =
+  {
+    .name = "biosdisk",
+    .id = GRUB_DISK_DEVICE_BIOSDISK_ID,
+    .iterate = grub_util_biosdisk_iterate,
+    .open = grub_util_biosdisk_open,
+    .close = 0,
+    .read = grub_util_biosdisk_read,
+    .write = grub_util_biosdisk_write,
+    .next = 0
+  };
+
+static void
+read_device_map (const char *dev_map)
+{
+  FILE *fp;
+  char buf[1024];      /* XXX */
+  int lineno = 0;
+  struct stat st;
+
+  auto void show_error (const char *msg);
+  void show_error (const char *msg)
+    {
+      grub_util_error ("%s:%d: %s", dev_map, lineno, msg);
+    }
+  
+  fp = fopen (dev_map, "r");
+  if (! fp)
+    grub_util_error ("Cannot open `%s'", dev_map);
+
+  while (fgets (buf, sizeof (buf), fp))
+    {
+      char *p = buf;
+      char *e;
+      int drive;
+      
+      lineno++;
+      
+      /* Skip leading spaces.  */
+      while (*p && isspace (*p))
+       p++;
+
+      /* If the first character is `#' or NUL, skip this line.  */
+      if (*p == '\0' || *p == '#')
+       continue;
+
+      if (*p != '(')
+       show_error ("No open parenthesis found");
+
+      p++;
+      /* Find a free slot.  */
+      drive = find_free_slot ();
+      if (drive < 0)
+       show_error ("Map table size exceeded");
+
+      e = p;
+      p = strchr (p, ')');
+      if (! p)
+       show_error ("No close parenthesis found");
+
+      map[drive].drive = xmalloc (p - e + sizeof ('\0'));
+      strncpy (map[drive].drive, e, p - e + sizeof ('\0'));
+      map[drive].drive[p - e] = '\0';
+
+      p++;
+      /* Skip leading spaces.  */
+      while (*p && isspace (*p))
+       p++;
+
+      if (*p == '\0')
+       show_error ("No filename found");
+
+      /* NUL-terminate the filename.  */
+      e = p;
+      while (*e && ! isspace (*e))
+       e++;
+      *e = '\0';
+
+      if (stat (p, &st) == -1)
+       {
+         free (map[drive].drive);
+         map[drive].drive = NULL;
+         grub_util_info ("Cannot stat `%s', skipping", p);
+         continue;
+       }
+
+#ifdef __linux__
+      /* On Linux, the devfs uses symbolic links horribly, and that
+        confuses the interface very much, so use realpath to expand
+        symbolic links.  */
+      map[drive].device = xmalloc (PATH_MAX);
+      if (! realpath (p, map[drive].device))
+       grub_util_error ("Cannot get the real path of `%s'", p);
+#else
+      map[drive].device = xstrdup (p);
+#endif
+    }
+
+  fclose (fp);
+}
+
+void
+grub_util_biosdisk_init (const char *dev_map)
+{
+  read_device_map (dev_map);
+  grub_disk_dev_register (&grub_util_biosdisk_dev);
+}
+
+void
+grub_util_biosdisk_fini (void)
+{
+  unsigned i;
+  
+  for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
+    {
+      if (map[i].drive)
+       free (map[i].drive);
+      if (map[i].device)
+       free (map[i].device);
+      map[i].drive = map[i].device = NULL;
+    }
+  
+  grub_disk_dev_unregister (&grub_util_biosdisk_dev);
+}
+
+static char *
+make_device_name (int drive, int dos_part, int bsd_part)
+{
+  char *p;
+
+  p = xmalloc (30);
+  sprintf (p, "%s", map[drive].drive);
+  
+  if (dos_part >= 0)
+    sprintf (p + strlen (p), ",%d", dos_part + 1);
+  
+  if (bsd_part >= 0)
+    sprintf (p + strlen (p), ",%c", bsd_part + 'a');
+  
+  return p;
+}
+
+static char *
+convert_system_partition_to_system_disk (const char *os_dev)
+{
+#if defined(__linux__)
+  char *path = xmalloc (PATH_MAX);
+  if (! realpath (os_dev, path))
+    return 0;
+  
+  if (strncmp ("/dev/", path, 5) == 0)
+    {
+      char *p = path + 5;
+
+      /* If this is an IDE disk.  */
+      if (strncmp ("ide/", p, 4) == 0)
+       {
+         p = strstr (p, "part");
+         if (p)
+           strcpy (p, "disc");
+         
+         return path;
+       }
+      
+      /* If this is a SCSI disk.  */
+      if (strncmp ("scsi/", p, 5) == 0)
+       {
+         p = strstr (p, "part");
+         if (p)
+           strcpy (p, "disc");
+         
+         return path;
+       }
+      
+      /* If this is a DAC960 disk.  */
+      if (strncmp ("rd/c", p, 4) == 0)
+       {
+         /* /dev/rd/c[0-9]+d[0-9]+(p[0-9]+)? */
+         p = strchr (p, 'p');
+         if (p)
+           *p = '\0';
+
+         return path;
+       }
+      
+      /* If this is a CCISS disk.  */
+      if (strncmp ("cciss/c", p, sizeof ("cciss/c") - 1) == 0)
+       {
+         /* /dev/cciss/c[0-9]+d[0-9]+(p[0-9]+)? */
+         p = strchr (p, 'p');
+         if (p)
+           *p = '\0';
+
+         return path;
+       }
+      
+      /* If this is a Compaq Intelligent Drive Array.  */
+      if (strncmp ("ida/c", p, sizeof ("ida/c") - 1) == 0)
+       {
+         /* /dev/ida/c[0-9]+d[0-9]+(p[0-9]+)? */
+         p = strchr (p, 'p');
+         if (p)
+           *p = '\0';
+
+         return path;
+       }
+      
+      /* If this is an I2O disk.  */
+      if (strncmp ("i2o/hd", p, sizeof ("i2o/hd") - 1) == 0)
+       {
+         /* /dev/i2o/hd[a-z]([0-9]+)? */
+         p[sizeof ("i2o/hda") - 1] = '\0';
+         return path;
+       }
+      
+      /* If this is a MultiMediaCard (MMC).  */
+      if (strncmp ("mmcblk", p, sizeof ("mmcblk") - 1) == 0)
+       {
+         /* /dev/mmcblk[0-9]+(p[0-9]+)? */
+         p = strchr (p, 'p');
+         if (p)
+           *p = '\0';
+
+         return path;
+       }
+      
+      /* If this is an IDE, SCSI or Virtio disk.  */
+      if ((strncmp ("hd", p, 2) == 0
+          || strncmp ("vd", p, 2) == 0
+          || strncmp ("sd", p, 2) == 0)
+         && p[2] >= 'a' && p[2] <= 'z')
+       {
+         /* /dev/[hsv]d[a-z][0-9]* */
+         p[3] = '\0';
+         return path;
+       }
+
+      /* If this is a Xen virtual block device.  */
+      if ((strncmp ("xvd", p, 3) == 0) && p[3] >= 'a' && p[3] <= 'z')
+       {
+         /* /dev/xvd[a-z][0-9]* */
+         p[4] = '\0';
+         return path;
+       }
+    }
+
+  return path;
+  
+#elif defined(__GNU__)
+  char *path = xstrdup (os_dev);
+  if (strncmp ("/dev/sd", path, 7) == 0 || strncmp ("/dev/hd", path, 7) == 0)
+    {
+      char *p = strchr (path + 7, 's');
+      if (p)
+       *p = '\0';
+    }
+  return path;
+
+#elif defined(__CYGWIN__)
+  char *path = xstrdup (os_dev);
+  if (strncmp ("/dev/sd", path, 7) == 0 && 'a' <= path[7] && path[7] <= 'z')
+    path[8] = 0;
+  return path;
+
+#else
+# warning "The function `convert_system_partition_to_system_disk' might not work on your OS correctly."
+  return xstrdup (os_dev);
+#endif
+}
+
+static int
+find_system_device (const char *os_dev)
+{
+  int i;
+  char *os_disk;
+
+  os_disk = convert_system_partition_to_system_disk (os_dev);
+  if (! os_disk)
+    return -1;
+  
+  for (i = 0; i < (int) (sizeof (map) / sizeof (map[0])); i++)
+    if (map[i].device && strcmp (map[i].device, os_disk) == 0)
+      {
+       free (os_disk);
+       return i;
+      }
+
+  free (os_disk);
+  return -1;
+}
+
+char *
+grub_util_biosdisk_get_grub_dev (const char *os_dev)
+{
+  struct stat st;
+  int drive;
+
+  if (stat (os_dev, &st) < 0)
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev);
+      return 0;
+    }
+
+  drive = find_system_device (os_dev);
+  if (drive < 0)
+    {
+      grub_error (GRUB_ERR_BAD_DEVICE,
+                 "no mapping exists for `%s'", os_dev);
+      return 0;
+    }
+  
+  if (! S_ISBLK (st.st_mode))
+    return make_device_name (drive, -1, -1);
+  
+#if defined(__linux__) || defined(__CYGWIN__)
+  /* Linux counts partitions uniformly, whether a BSD partition or a DOS
+     partition, so mapping them to GRUB devices is not trivial.
+     Here, get the start sector of a partition by HDIO_GETGEO, and
+     compare it with each partition GRUB recognizes.
+
+     Cygwin /dev/sdXN emulation uses Windows partition mapping. It
+     does not count the extended partition and missing primary
+     partitions.  Use same method as on Linux here.  */
+  {
+    char *name;
+    grub_disk_t disk;
+    int fd;
+    struct hd_geometry hdg;
+    int dos_part = -1;
+    int bsd_part = -1;
+    auto int find_partition (grub_disk_t disk,
+                            const grub_partition_t partition);
+    
+    int find_partition (grub_disk_t disk __attribute__ ((unused)),
+                       const grub_partition_t partition)
+      {
+       struct grub_pc_partition *pcdata = NULL;
+
+       if (strcmp (partition->partmap->name, "pc_partition_map") == 0)
+         pcdata = partition->data;
+         
+       if (pcdata)
+         {
+           if (pcdata->bsd_part < 0)
+             grub_util_info ("DOS partition %d starts from %lu",
+                             pcdata->dos_part, partition->start);
+           else
+             grub_util_info ("BSD partition %d,%c starts from %lu",
+                             pcdata->dos_part, pcdata->bsd_part + 'a',
+                             partition->start);
+         }
+       else
+         {
+             grub_util_info ("Partition %d starts from %lu",
+                             partition->index, partition->start);
+         }
+       
+       if (hdg.start == partition->start)
+         {
+           if (pcdata)
+             {
+               dos_part = pcdata->dos_part;
+               bsd_part = pcdata->bsd_part;
+             }
+           else
+             {
+               dos_part = partition->index;
+               bsd_part = -1;
+             }
+           return 1;
+         }
+       
+       return 0;
+      }
+    
+    name = make_device_name (drive, -1, -1);
+    
+    if (MAJOR (st.st_rdev) == FLOPPY_MAJOR)
+      return name;
+    
+    fd = open (os_dev, O_RDONLY);
+    if (fd == -1)
+      {
+       grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to get disk geometry", os_dev);
+       free (name);
+       return 0;
+      }
+    
+    if (ioctl (fd, HDIO_GETGEO, &hdg))
+      {
+       grub_error (GRUB_ERR_BAD_DEVICE,
+                   "cannot get geometry of `%s'", os_dev);
+       close (fd);
+       free (name);
+       return 0;
+      }
+    
+    close (fd);
+
+    grub_util_info ("%s starts from %lu", os_dev, hdg.start);
+    
+    if (hdg.start == 0)
+      return name;
+
+    grub_util_info ("opening the device %s", name);
+    disk = grub_disk_open (name);
+    free (name);
+    
+    if (! disk)
+      return 0;
+    
+    grub_partition_iterate (disk, find_partition);
+    if (grub_errno != GRUB_ERR_NONE)
+      {
+       grub_disk_close (disk);
+       return 0;
+      }
+    
+    if (dos_part < 0)
+      {
+       grub_disk_close (disk);
+       grub_error (GRUB_ERR_BAD_DEVICE,
+                   "cannot find the partition of `%s'", os_dev);
+       return 0;
+      }
+    
+    return make_device_name (drive, dos_part, bsd_part);
+  }
+  
+#elif defined(__GNU__)
+  /* GNU uses "/dev/[hs]d[0-9]+(s[0-9]+[a-z]?)?".  */
+  {
+    char *p;
+    int dos_part = -1;
+    int bsd_part = -1;
+    
+    p = strrchr (os_dev, 's');
+    if (p)
+      {
+       long int n;
+       char *q;
+       
+       p++;
+       n = strtol (p, &q, 10);
+       if (p != q && n != LONG_MIN && n != LONG_MAX)
+         {
+           dos_part = (int) n;
+           
+           if (*q >= 'a' && *q <= 'g')
+             bsd_part = *q - 'a';
+         }
+      }
+    
+    return make_device_name (drive, dos_part, bsd_part);
+  }
+  
+#else
+# warning "The function `grub_util_biosdisk_get_grub_dev' might not work on your OS correctly."
+  return make_device_name (drive, -1, -1);
+#endif
+}
diff --git a/util/hostfs.c b/util/hostfs.c
new file mode 100644 (file)
index 0000000..d68c36f
--- /dev/null
@@ -0,0 +1,168 @@
+/* hostfs.c - Dummy filesystem to provide access to the hosts filesystem  */
+/*
+ *  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/>.
+ */
+
+#include <grub/fs.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/misc.h>
+#include <grub/dl.h>
+#include <grub/util/misc.h>
+
+#include <dirent.h>
+#include <stdio.h>
+
+
+#ifndef DT_DIR
+/* dirent.d_type is a BSD extension, not part of POSIX */
+#include <sys/stat.h>
+#include <string.h>
+
+static int
+is_dir (const char *path, const char *name)
+{
+  int len1 = strlen(path);
+  int len2 = strlen(name);
+
+  char pathname[len1 + 1 + len2 + 1 + 13];
+  strcpy (pathname, path);
+
+  /* Avoid UNC-path "//name" on Cygwin.  */
+  if (len1 > 0 && pathname[len1 - 1] != '/')
+    strcat (pathname, "/");
+
+  strcat (pathname, name);
+
+  struct stat st;
+  if (stat (pathname, &st))
+    return 0;
+  return S_ISDIR (st.st_mode);
+}
+#endif
+
+static grub_err_t
+grub_hostfs_dir (grub_device_t device, const char *path, 
+                int (*hook) (const char *filename, int dir))
+{
+  DIR *dir;
+
+  /* Check if the disk is our dummy disk.  */
+  if (grub_strcmp (device->disk->name, "host"))
+    return grub_error (GRUB_ERR_BAD_FS, "not a hostfs");
+
+  dir = opendir (path);
+  if (! dir)
+    return grub_error (GRUB_ERR_BAD_FILENAME,
+                      "can't open the hostfs directory `%s'", path);
+
+  while (1)
+    {
+      struct dirent *de;
+
+      de = readdir (dir);
+      if (! de)
+       break;
+
+#ifdef DT_DIR
+      hook (de->d_name, de->d_type == DT_DIR);
+#else
+      hook (de->d_name, is_dir (path, de->d_name));
+#endif
+    }
+
+  closedir (dir);
+
+  return GRUB_ERR_NONE;
+}
+
+/* Open a file named NAME and initialize FILE.  */
+static grub_err_t
+grub_hostfs_open (struct grub_file *file, const char *name)
+{
+  FILE *f;
+
+  f = fopen (name, "rb");
+  if (! f)
+    return grub_error (GRUB_ERR_BAD_FILENAME,
+                      "can't open `%s'", name);
+  file->data = f;
+
+#ifdef __MINGW32__
+  file->size = grub_util_get_disk_size (name);
+#else
+  fseeko (f, 0, SEEK_END);
+  file->size = ftello (f);
+  fseeko (f, 0, SEEK_SET);
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_ssize_t
+grub_hostfs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  FILE *f;
+
+  f = (FILE *) file->data;
+  fseeko (f, file->offset, SEEK_SET);
+  int s = fread (buf, 1, len, f);
+
+  return s;
+}
+
+static grub_err_t
+grub_hostfs_close (grub_file_t file)
+{
+  FILE *f;
+
+  f = (FILE *) file->data;
+  fclose (f);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_hostfs_label (grub_device_t device __attribute ((unused)),
+                  char **label __attribute ((unused)))
+{
+  *label = 0;
+  return GRUB_ERR_NONE;
+}
+
+static struct grub_fs grub_hostfs_fs =
+  {
+    .name = "hostfs",
+    .dir = grub_hostfs_dir,
+    .open = grub_hostfs_open,
+    .read = grub_hostfs_read,
+    .close = grub_hostfs_close,
+    .label = grub_hostfs_label,
+    .next = 0
+  };
+
+\f
+
+GRUB_MOD_INIT(hostfs)
+{
+  grub_fs_register (&grub_hostfs_fs);
+}
+
+GRUB_MOD_FINI(hostfs)
+{
+  grub_fs_unregister (&grub_hostfs_fs);
+}
diff --git a/util/i386/efi/grub-install.in b/util/i386/efi/grub-install.in
new file mode 100644 (file)
index 0000000..a5f97e3
--- /dev/null
@@ -0,0 +1,211 @@
+#! /bin/sh
+
+# Install GRUB on your EFI partition.
+# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,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/>.
+
+# Initialize some variables.
+transform="@program_transform_name@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+sbindir=@sbindir@
+bindir=@bindir@
+libdir=@libdir@
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_TARNAME=@PACKAGE_TARNAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+target_cpu=@target_cpu@
+platform=@platform@
+pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`
+
+grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}`
+grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}`
+grub_probe=${sbindir}/`echo grub-probe | sed ${transform}`
+rootdir=
+grub_prefix=`echo /boot/grub | sed ${transform}`
+modules=
+
+no_floppy=
+force_lba=
+recheck=no
+debug=no
+
+# Usage: usage
+# Print the usage.
+usage () {
+    cat <<EOF
+Usage: grub-install [OPTION]
+Install GRUB on your EFI partition.
+
+  -h, --help              print this message and exit
+  -v, --version           print the version information and exit
+  --modules=MODULES       pre-load specified modules MODULES
+  --root-directory=DIR    install GRUB images under the directory DIR
+                          instead of the root directory
+  --grub-mkimage=FILE     use FILE as grub-mkimage
+  --grub-mkdevicemap=FILE use FILE as grub-mkdevicemap
+  --grub-probe=FILE       use FILE as grub-probe
+  --no-floppy             do not probe any floppy drive
+  --recheck               probe a device map even if it already exists
+
+grub-install copies GRUB images into the DIR/boot directory specified by
+--root-directory.
+
+Report bugs to <bug-grub@gnu.org>.
+EOF
+}
+
+# Check the arguments.
+for option in "$@"; do
+    case "$option" in
+    -h | --help)
+       usage
+       exit 0 ;;
+    -v | --version)
+       echo "grub-install (GNU GRUB ${PACKAGE_VERSION})"
+       exit 0 ;;
+    --modules=*)
+       modules=`echo "$option" | sed 's/--modules=//'` ;;
+    --root-directory=*)
+       rootdir=`echo "$option" | sed 's/--root-directory=//'` ;;
+    --grub-mkimage=*)
+       grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;;
+    --grub-mkdevicemap=*)
+       grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;;
+    --grub-probe=*)
+       grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;;
+    --no-floppy)
+       no_floppy="--no-floppy" ;;
+    --recheck)
+       recheck=yes ;;
+    # This is an undocumented feature...
+    --debug)
+       debug=yes ;;
+    *)
+       echo "Unrecognized option \`$option'" 1>&2
+       usage
+       exit 1
+       ;;
+    esac
+done
+
+# If the debugging feature is enabled, print commands.
+if test $debug = yes; then
+    set -x
+fi
+
+# Initialize these directories here, since ROOTDIR was initialized.
+case "$host_os" in
+netbsd* | openbsd*)
+    # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub
+    # instead of /boot/grub.
+    grub_prefix=`echo /grub | sed ${transform}`
+    bootdir=${rootdir}
+    ;;
+*)
+    # Use /boot/grub by default.
+    bootdir=${rootdir}/boot
+    ;;
+esac
+
+grubdir=${bootdir}/`echo grub | sed ${transform}`
+device_map=${grubdir}/device.map
+
+# Check if GRUB is installed.
+set $grub_mkimage dummy
+if test -f "$1"; then
+    :
+else
+    echo "$1: Not found." 1>&2
+    exit 1
+fi
+
+set $grub_mkdevicemap dummy
+if test -f "$1"; then
+    :
+else
+    echo "$1: Not found." 1>&2
+    exit 1
+fi
+
+# Create the GRUB directory if it is not present.
+test -d "$bootdir" || mkdir "$bootdir" || exit 1
+test -d "$grubdir" || mkdir "$grubdir" || exit 1
+
+# If --recheck is specified, remove the device map, if present.
+if test $recheck = yes; then
+    rm -f $device_map
+fi
+
+# Create the device map file if it is not present.
+if test -f "$device_map"; then
+    :
+else
+    # Create a safe temporary file.
+    test -n "$mklog" && log_file=`$mklog`
+
+    $grub_mkdevicemap --device-map=$device_map $no_floppy || exit 1
+fi
+
+# Make sure that there is no duplicated entry.
+tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' $device_map \
+    | sort | uniq -d | sed -n 1p`
+if test -n "$tmp"; then
+    echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2
+    exit 1
+fi
+
+# Copy the GRUB images to the GRUB directory.
+for file in ${grubdir}/*.mod ${grubdir}/*.lst; do
+    if test -f $file && [ "`basename $file`" != menu.lst ]; then
+       rm -f $file || exit 1
+    fi
+done
+for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst; do
+    cp -f $file ${grubdir} || exit 1
+done
+
+# Create the core image. First, auto-detect the filesystem module.
+fs_module=`$grub_probe --target=fs --device-map=${device_map} ${grubdir}`
+if test "x$fs_module" = xfat; then :; else
+    echo "${grubdir} doesn't look like an EFI partition." 1>&2
+    exit 1
+fi
+
+# Then the partition map module.  In order to support partition-less media,
+# this command is allowed to fail (--target=fs already grants us that the
+# filesystem will be accessible).
+partmap_module=`$grub_probe --target=partmap --device-map=${device_map} ${grubdir} 2> /dev/null`
+
+# Device abstraction module, if any (lvm, raid).
+devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_map} ${grubdir}`
+
+# The order in this list is critical.  Be careful when modifying it.
+modules="$modules $fs_module $partmap_module $devabstraction_module"
+
+$grub_mkimage --output=${grubdir}/grub.efi $modules || exit 1
+
+# Prompt the user to check if the device map is correct.
+echo "Installation finished. No error reported."
+echo "This is the contents of the device map $device_map."
+echo "Check if this is correct or not. If any of the lines is incorrect,"
+echo "fix it and re-run the script \`grub-install'."
+echo
+
+cat $device_map
+
+# Bye.
+exit 0
diff --git a/util/i386/efi/grub-mkimage.c b/util/i386/efi/grub-mkimage.c
new file mode 100644 (file)
index 0000000..36ea31f
--- /dev/null
@@ -0,0 +1,1124 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,2005,2006,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/>.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <grub/elf.h>
+#include <grub/util/misc.h>
+#include <grub/util/resolve.h>
+#include <grub/kernel.h>
+#include <grub/efi/pe32.h>
+#include <grub/machine/kernel.h>
+
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+
+typedef Elf32_Word Elf_Word;
+typedef Elf32_Addr Elf_Addr;
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Shdr Elf_Shdr;
+typedef Elf32_Sym Elf_Sym;
+typedef Elf32_Half Elf_Half;
+typedef Elf32_Off Elf_Off;
+typedef Elf32_Section Elf_Section;
+typedef Elf32_Rel Elf_Rel;
+typedef Elf32_Rela Elf_Rela;
+
+#define ELF_R_SYM      ELF32_R_SYM
+#define ELF_R_TYPE     ELF32_R_TYPE
+#define ELF_R_INFO     ELF32_R_INFO
+
+#define grub_le_to_cpu grub_le_to_cpu32
+
+#elif GRUB_TARGET_SIZEOF_VOID_P == 8
+
+typedef Elf64_Word Elf_Word;
+typedef Elf64_Addr Elf_Addr;
+typedef Elf64_Ehdr Elf_Ehdr;
+typedef Elf64_Shdr Elf_Shdr;
+typedef Elf64_Sym Elf_Sym;
+typedef Elf64_Half Elf_Half;
+typedef Elf64_Off Elf_Off;
+typedef Elf64_Section Elf_Section;
+typedef Elf64_Rel Elf_Rel;
+typedef Elf64_Rela Elf_Rela;
+
+#define ELF_R_SYM      ELF64_R_SYM
+#define ELF_R_TYPE     ELF64_R_TYPE
+#define ELF_R_INFO     ELF64_R_INFO
+
+#define grub_le_to_cpu grub_le_to_cpu64
+
+#endif
+
+static const grub_uint8_t stub[] = GRUB_PE32_MSDOS_STUB;
+
+static inline Elf_Addr
+align_address (Elf_Addr addr, unsigned alignment)
+{
+  return (addr + alignment - 1) & ~(alignment - 1);
+}
+
+static inline Elf_Addr
+align_pe32_section (Elf_Addr addr)
+{
+  return align_address (addr, GRUB_PE32_SECTION_ALIGNMENT);
+}
+
+/* Read the whole kernel image. Return the pointer to a read image,
+   and store the size in bytes in *SIZE.  */
+static char *
+read_kernel_module (const char *dir, char *prefix, size_t *size)
+{
+  char *kernel_image;
+  char *kernel_path;
+  
+  kernel_path = grub_util_get_path (dir, "kernel.mod");
+  *size = grub_util_get_image_size (kernel_path);
+  kernel_image = grub_util_read_image (kernel_path);
+  free (kernel_path);
+
+  if (GRUB_KERNEL_MACHINE_PREFIX + strlen (prefix) + 1 > GRUB_KERNEL_MACHINE_DATA_END)
+    grub_util_error ("prefix too long");
+
+  strcpy (kernel_image + sizeof (Elf_Ehdr) + GRUB_KERNEL_MACHINE_PREFIX, prefix);
+
+  return kernel_image;
+}
+
+/* Return if the ELF header is valid.  */
+static int
+check_elf_header (Elf_Ehdr *e, size_t size)
+{
+  if (size < sizeof (*e)
+      || e->e_ident[EI_MAG0] != ELFMAG0
+      || e->e_ident[EI_MAG1] != ELFMAG1
+      || e->e_ident[EI_MAG2] != ELFMAG2
+      || e->e_ident[EI_MAG3] != ELFMAG3
+      || e->e_ident[EI_VERSION] != EV_CURRENT
+      || e->e_version != grub_cpu_to_le32 (EV_CURRENT)
+      || ((e->e_ident[EI_CLASS] != ELFCLASS32) &&
+          (e->e_ident[EI_CLASS] != ELFCLASS64))
+      || e->e_ident[EI_DATA] != ELFDATA2LSB
+      || ((e->e_machine != grub_cpu_to_le16 (EM_386)) &&
+          (e->e_machine != grub_cpu_to_le16 (EM_X86_64))))
+    return 0;
+
+  return 1;
+}
+
+/* Return the starting address right after the header,
+   aligned by the section alignment. Allocate 4 section tables for
+   .text, .data, .reloc, and mods.  */
+static Elf_Addr
+get_starting_section_address (void)
+{
+  return align_pe32_section (sizeof (struct grub_pe32_header)
+                            + 4 * sizeof (struct grub_pe32_section_table));
+}
+
+/* Determine if this section is a text section. Return false if this
+   section is not allocated.  */
+static int
+is_text_section (Elf_Shdr *s)
+{
+  return ((s->sh_flags & grub_cpu_to_le32 (SHF_EXECINSTR | SHF_ALLOC))
+         == grub_cpu_to_le32 (SHF_EXECINSTR | SHF_ALLOC));
+}
+
+/* Determine if this section is a data section. This assumes that
+   BSS is also a data section, since the converter initializes BSS
+   when producing PE32 to avoid a bug in EFI implementations.  */
+static int
+is_data_section (Elf_Shdr *s)
+{
+  return (s->sh_flags & grub_cpu_to_le32 (SHF_ALLOC)
+         && ! (s->sh_flags & grub_cpu_to_le32 (SHF_EXECINSTR)));
+}
+
+/* Locate section addresses by merging code sections and data sections
+   into .text and .data, respectively. Return the array of section
+   addresses.  */
+static Elf_Addr *
+locate_sections (Elf_Shdr *sections, Elf_Half section_entsize,
+                Elf_Half num_sections, const char *strtab)
+{
+  int i;
+  Elf_Addr current_address;
+  Elf_Addr *section_addresses;
+  Elf_Shdr *s;
+  
+  section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
+  memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
+
+  current_address = get_starting_section_address ();
+
+  /* .text */
+  for (i = 0, s = sections;
+       i < num_sections;
+       i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+    if (is_text_section (s))
+      {
+       Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
+       const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
+       
+       if (align)
+         current_address = align_address (current_address, align);
+       
+       grub_util_info ("locating the section %s at 0x%x",
+                       name, current_address);
+       section_addresses[i] = current_address;
+       current_address += grub_le_to_cpu32 (s->sh_size);
+      }
+
+  current_address = align_pe32_section (current_address);
+
+  /* .data */
+  for (i = 0, s = sections;
+       i < num_sections;
+       i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+    if (is_data_section (s))
+      {
+       Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
+       const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
+       
+       if (align)
+         current_address = align_address (current_address, align);
+       
+       grub_util_info ("locating the section %s at 0x%x",
+                       name, current_address);
+       section_addresses[i] = current_address;
+       current_address += grub_le_to_cpu32 (s->sh_size);
+      }
+
+  return section_addresses;
+}
+
+/* Return the symbol table section, if any.  */
+static Elf_Shdr *
+find_symtab_section (Elf_Shdr *sections,
+                    Elf_Half section_entsize, Elf_Half num_sections)
+{
+  int i;
+  Elf_Shdr *s;
+  
+  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_SYMTAB))
+      return s;
+
+  return 0;
+}
+
+/* Return the address of the string table.  */
+static const char *
+find_strtab (Elf_Ehdr *e, Elf_Shdr *sections, Elf_Half section_entsize)
+{
+  Elf_Shdr *s;
+  char *strtab;
+  
+  s = (Elf_Shdr *) ((char *) sections
+                     + grub_le_to_cpu16 (e->e_shstrndx) * section_entsize);
+  strtab = (char *) e + grub_le_to_cpu32 (s->sh_offset);
+  return strtab;
+}
+
+/* Relocate symbols; note that this function overwrites the symbol table.
+   Return the address of a start symbol.  */
+static Elf_Addr
+relocate_symbols (Elf_Ehdr *e, Elf_Shdr *sections,
+                 Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
+                 Elf_Half section_entsize, Elf_Half num_sections)
+{
+  Elf_Word symtab_size, sym_size, num_syms;
+  Elf_Off symtab_offset;
+  Elf_Addr start_address = 0;
+  Elf_Sym *sym;
+  Elf_Word i;
+  Elf_Shdr *strtab_section;
+  const char *strtab;
+  
+  strtab_section
+    = (Elf_Shdr *) ((char *) sections
+                     + (grub_le_to_cpu32 (symtab_section->sh_link)
+                        * section_entsize));
+  strtab = (char *) e + grub_le_to_cpu32 (strtab_section->sh_offset);
+  
+  symtab_size = grub_le_to_cpu32 (symtab_section->sh_size);
+  sym_size = grub_le_to_cpu32 (symtab_section->sh_entsize);
+  symtab_offset = grub_le_to_cpu32 (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))
+    {
+      Elf_Section index;
+      const char *name;
+      
+      name = strtab + grub_le_to_cpu32 (sym->st_name);
+      
+      index = grub_le_to_cpu16 (sym->st_shndx);
+      if (index == STN_ABS)
+        {
+          continue;
+        }
+      else if ((index == STN_UNDEF))
+       {
+         if (sym->st_name)
+           grub_util_error ("undefined symbol %s", name);
+         else
+           continue;
+       }
+      else if (index >= num_sections)
+       grub_util_error ("section %d does not exist", index);
+      
+      sym->st_value = (grub_le_to_cpu32 (sym->st_value)
+                      + section_addresses[index]);
+      grub_util_info ("locating %s at 0x%x", name, sym->st_value);
+
+      if (! start_address)
+       if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
+         start_address = sym->st_value;
+    }
+
+  return start_address;
+}
+
+/* Return the address of a symbol at the index I in the section S.  */
+static Elf_Addr
+get_symbol_address (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i)
+{
+  Elf_Sym *sym;
+  
+  sym = (Elf_Sym *) ((char *) e
+                      + grub_le_to_cpu32 (s->sh_offset)
+                      + i * grub_le_to_cpu32 (s->sh_entsize));
+  return sym->st_value;
+}
+
+/* Return the address of a modified value.  */
+static Elf_Addr *
+get_target_address (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset)
+{
+  return (Elf_Addr *) ((char *) e + grub_le_to_cpu32 (s->sh_offset) + offset);
+}
+
+/* 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
+   again by a PE32 relocator when loaded.  */
+static void
+relocate_addresses (Elf_Ehdr *e, Elf_Shdr *sections,
+                   Elf_Addr *section_addresses,
+                   Elf_Half section_entsize, Elf_Half num_sections,
+                   const char *strtab)
+{
+  Elf_Half i;
+  Elf_Shdr *s;
+  
+  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)))
+      {
+       Elf_Rela *r;
+       Elf_Word rtab_size, r_size, num_rs;
+       Elf_Off rtab_offset;
+       Elf_Shdr *symtab_section;
+       Elf_Word target_section_index;
+       Elf_Addr target_section_addr;
+       Elf_Shdr *target_section;
+       Elf_Word j;
+
+       symtab_section = (Elf_Shdr *) ((char *) sections
+                                        + (grub_le_to_cpu32 (s->sh_link)
+                                           * section_entsize));
+       target_section_index = grub_le_to_cpu32 (s->sh_info);
+       target_section_addr = section_addresses[target_section_index];
+       target_section = (Elf_Shdr *) ((char *) sections
+                                        + (target_section_index
+                                           * section_entsize));
+
+       grub_util_info ("dealing with the relocation section %s for %s",
+                       strtab + grub_le_to_cpu32 (s->sh_name),
+                       strtab + grub_le_to_cpu32 (target_section->sh_name));
+
+       rtab_size = grub_le_to_cpu32 (s->sh_size);
+       r_size = grub_le_to_cpu32 (s->sh_entsize);
+       rtab_offset = grub_le_to_cpu32 (s->sh_offset);
+       num_rs = rtab_size / r_size;
+
+       for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
+            j < num_rs;
+            j++, r = (Elf_Rela *) ((char *) r + r_size))
+         {
+            Elf_Addr info;
+           Elf_Addr offset;
+           Elf_Addr sym_addr;
+           Elf_Addr *target, *value;
+           
+           offset = grub_le_to_cpu (r->r_offset);
+           target = get_target_address (e, target_section, offset);
+           info = grub_le_to_cpu (r->r_info);
+           sym_addr = get_symbol_address (e, symtab_section,
+                                          ELF_R_SYM (info));
+
+            value = (s->sh_type == grub_cpu_to_le32 (SHT_RELA)) ?
+               (Elf_Addr *) &r->r_addend : target;
+
+            switch (ELF_R_TYPE (info))
+             {
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+             case R_386_NONE:
+               break;
+
+             case R_386_32:
+               /* This is absolute.  */
+               *target = grub_cpu_to_le32 (grub_le_to_cpu32 (*value)
+                                            + sym_addr);
+               grub_util_info ("relocating an R_386_32 entry to 0x%x at the offset 0x%x",
+                               *target, offset);
+               break;
+
+             case R_386_PC32:
+               /* This is relative.  */
+               *target = grub_cpu_to_le32 (grub_le_to_cpu32 (*value)
+                                           + sym_addr
+                                           - target_section_addr - offset);
+               grub_util_info ("relocating an R_386_PC32 entry to 0x%x at the offset 0x%x",
+                               *target, offset);
+               break;
+
+#else
+
+              case R_X86_64_NONE:
+                break;
+
+              case R_X86_64_64:
+               *target = grub_cpu_to_le64 (grub_le_to_cpu64 (*value) + sym_addr);
+               grub_util_info ("relocating an R_X86_64_64 entry to 0x%llx at the offset 0x%llx",
+                               *target, offset);
+               break;
+
+              case R_X86_64_PC32:
+                {
+                  grub_uint32_t *t32 = (grub_uint32_t *) target;
+                  *t32 = grub_cpu_to_le64 (grub_le_to_cpu64 (*value)
+                                           + sym_addr
+                                           - target_section_addr - offset);
+                  grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%llx",
+                                  *t32, offset);
+                  break;
+                }
+
+              case R_X86_64_32:
+              case R_X86_64_32S:
+                {
+                  grub_uint32_t *t32 = (grub_uint32_t *) target;
+                  *t32 = grub_cpu_to_le64 (grub_le_to_cpu64 (*value)
+                                           + sym_addr);
+                  grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%llx",
+                                  *t32, offset);
+                  break;
+                }
+
+#endif
+             default:
+               grub_util_error ("unknown relocation type %d",
+                                ELF_R_TYPE (info));
+               break;
+             }
+         }
+      }
+}
+
+void
+write_padding (FILE *out, size_t size)
+{
+  size_t i;
+
+  for (i = 0; i < size; i++)
+    if (fputc (0, out) == EOF)
+      grub_util_error ("padding failed");
+}
+
+/* Add a PE32's fixup entry for a relocation. Return the resulting address
+   after having written to the file OUT.  */
+Elf_Addr
+add_fixup_entry (struct grub_pe32_fixup_block **block, grub_uint16_t type,
+                Elf_Addr addr, int flush, Elf_Addr current_address,
+                FILE *out)
+{
+  struct grub_pe32_fixup_block *b = *block;
+  
+  /* First, check if it is necessary to write out the current block.  */
+  if (b)
+    {
+      if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr)
+       {
+         grub_uint32_t size;
+
+         if (flush)
+           {
+             /* Add as much padding as necessary to align the address
+                with a section boundary.  */
+             Elf_Addr next_address;
+             unsigned padding_size;
+              size_t index;
+             
+             next_address = current_address + b->block_size;
+             padding_size = ((align_pe32_section (next_address)
+                              - next_address)
+                             >> 1);
+              index = ((b->block_size - sizeof (*b)) >> 1);
+              grub_util_info ("adding %d padding fixup entries", padding_size);
+             while (padding_size--)
+               {
+                 b->entries[index++] = 0;
+                 b->block_size += 2;
+               }
+           }
+          else if (b->block_size & (8 - 1))
+            {
+             /* If not aligned with a 32-bit boundary, add
+                a padding entry.  */
+              size_t index;
+
+              grub_util_info ("adding a padding fixup entry");
+              index = ((b->block_size - sizeof (*b)) >> 1);
+              b->entries[index] = 0;
+              b->block_size += 2;
+            }
+
+          /* Flush it.  */
+          grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
+                          b->block_size, b->page_rva);
+          size = b->block_size;
+         current_address += size;
+         b->page_rva = grub_cpu_to_le32 (b->page_rva);
+         b->block_size = grub_cpu_to_le32 (b->block_size);
+         if (fwrite (b, size, 1, out) != 1)
+           grub_util_error ("write failed");
+         free (b);
+         *block = b = 0;
+       }
+    }
+
+  if (! flush)
+    {
+      grub_uint16_t entry;
+      size_t index;
+      
+      /* If not allocated yet, allocate a block with enough entries.  */
+      if (! b)
+       {
+         *block = b = xmalloc (sizeof (*b) + 2 * 0x1000);
+
+         /* The spec does not mention the requirement of a Page RVA.
+            Here, align the address with a 4K boundary for safety.  */
+         b->page_rva = (addr & ~(0x1000 - 1));
+         b->block_size = sizeof (*b);
+       }
+
+      /* Sanity check.  */
+      if (b->block_size >= sizeof (*b) + 2 * 0x1000)
+       grub_util_error ("too many fixup entries");
+
+      /* Add a new entry.  */
+      index = ((b->block_size - sizeof (*b)) >> 1);
+      entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
+      b->entries[index] = grub_cpu_to_le16 (entry);
+      b->block_size += 2;
+    }
+
+  return current_address;
+}
+
+/* Write out zeros to make space for the header.  */
+static Elf_Addr
+make_header_space (FILE *out)
+{
+  Elf_Addr addr;
+  
+  addr = get_starting_section_address ();
+  write_padding (out, addr);
+
+  return addr;
+}
+
+/* Write text sections.  */
+static Elf_Addr
+write_text_sections (FILE *out, Elf_Addr current_address,
+                    Elf_Ehdr *e, Elf_Shdr *sections,
+                    Elf_Half section_entsize, Elf_Half num_sections,
+                    const char *strtab)
+{
+  Elf_Half i;
+  Elf_Shdr *s;
+  Elf_Addr addr;
+  
+  for (i = 0, s = sections;
+       i < num_sections;
+       i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+    if (is_text_section (s))
+      {
+       Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
+       Elf_Off offset = grub_le_to_cpu32 (s->sh_offset);
+       Elf_Word size = grub_le_to_cpu32 (s->sh_size);
+       const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
+       
+       if (align)
+         {
+           addr = align_address (current_address, align);
+           if (current_address != addr)
+             {
+               grub_util_info ("padding %d bytes for the ELF section alignment",
+                               addr - current_address);
+               write_padding (out, addr - current_address);
+               current_address = addr;
+             }
+         }
+       
+       grub_util_info ("writing the text section %s at 0x%x",
+                       name, current_address);
+       
+       if (fwrite ((char *) e + offset, size, 1, out) != 1)
+         grub_util_error ("write failed");
+       
+       current_address += size;
+      }
+
+  addr = align_pe32_section (current_address);
+  if (addr != current_address)
+    {
+      grub_util_info ("padding %d bytes for the PE32 section alignment",
+                     addr - current_address);
+      write_padding (out, addr - current_address);
+    }
+  
+  return addr;
+}
+
+/* Write data sections.  */
+static Elf_Addr
+write_data_sections (FILE *out, Elf_Addr current_address,
+                    Elf_Ehdr *e, Elf_Shdr *sections,
+                    Elf_Half section_entsize, Elf_Half num_sections,
+                    const char *strtab)
+{
+  Elf_Half i;
+  Elf_Shdr *s;
+  Elf_Addr addr;
+  
+  for (i = 0, s = sections;
+       i < num_sections;
+       i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+    if (is_data_section (s))
+      {
+       Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
+       Elf_Off offset = grub_le_to_cpu32 (s->sh_offset);
+       Elf_Word size = grub_le_to_cpu32 (s->sh_size);
+       const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
+       
+       if (align)
+         {
+           addr = align_address (current_address, align);
+           if (current_address != addr)
+             {
+               grub_util_info ("padding %d bytes for the ELF section alignment",
+                               addr - current_address);
+               write_padding (out, addr - current_address);
+               current_address = addr;
+             }
+         }
+       
+       grub_util_info ("writing the data section %s at 0x%x",
+                       name, current_address);
+       
+       if (s->sh_type == grub_cpu_to_le32 (SHT_NOBITS))
+         write_padding (out, size);
+       else
+         if (fwrite ((char *) e + offset, size, 1, out) != 1)
+           grub_util_error ("write failed");
+       
+       current_address += size;
+      }
+  
+  addr = align_pe32_section (current_address);
+  if (addr != current_address)
+    {
+      grub_util_info ("padding %d bytes for the PE32 section alignment",
+                     addr - current_address);
+      write_padding (out, addr - current_address);
+    }
+  
+  return addr;
+}
+
+/* Write modules.  */
+static Elf_Addr
+make_mods_section (FILE *out, Elf_Addr current_address,
+                  const char *dir, char *mods[])
+{
+  struct grub_util_path_list *path_list;
+  grub_size_t total_module_size;
+  struct grub_util_path_list *p;
+  struct grub_module_info modinfo;
+  Elf_Addr addr;
+
+  path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
+  
+  total_module_size = sizeof (struct grub_module_info);
+  for (p = path_list; p; p = p->next)
+    {
+      total_module_size += (grub_util_get_image_size (p->name)
+                           + sizeof (struct grub_module_header));
+    }
+
+  grub_util_info ("the total module size is 0x%x", total_module_size);
+
+  modinfo.magic = grub_cpu_to_le32 (GRUB_MODULE_MAGIC);
+  modinfo.offset = grub_cpu_to_le32 (sizeof (modinfo));
+  modinfo.size = grub_cpu_to_le32 (total_module_size);
+
+  if (fwrite (&modinfo, sizeof (modinfo), 1, out) != 1)
+    grub_util_error ("write failed");
+
+  for (p = path_list; p; p = p->next)
+    {
+      struct grub_module_header header;
+      size_t mod_size;
+      char *mod_image;
+      
+      grub_util_info ("adding module %s", p->name);
+      
+      mod_size = grub_util_get_image_size (p->name);
+      header.type = grub_cpu_to_le32 (OBJ_TYPE_ELF);
+      header.size = grub_cpu_to_le32 (mod_size + sizeof (header));
+      
+      mod_image = grub_util_read_image (p->name);
+
+      if (fwrite (&header, sizeof (header), 1, out) != 1
+         || fwrite (mod_image, mod_size, 1, out) != 1)
+       grub_util_error ("write failed");
+
+      free (mod_image);
+    }
+  
+  for (p = path_list; p; )
+    {
+      struct grub_util_path_list *q;
+
+      q = p->next;
+      free (p);
+      p = q;
+    }
+      
+  current_address += total_module_size;
+  
+  addr = align_pe32_section (current_address);
+  if (addr != current_address)
+    {
+      grub_util_info ("padding %d bytes for the PE32 section alignment",
+                     addr - current_address);
+      write_padding (out, addr - current_address);
+    }
+
+  return addr;
+}
+
+/* Make a .reloc section.  */
+static Elf_Addr
+make_reloc_section (FILE *out, Elf_Addr current_address, Elf_Ehdr *e,
+                   Elf_Addr *section_addresses, Elf_Shdr *sections,
+                   Elf_Half section_entsize, Elf_Half num_sections,
+                   const char *strtab)
+{
+  Elf_Half i;
+  Elf_Shdr *s;
+  struct grub_pe32_fixup_block *fixup_block = 0;
+  
+  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)))
+      {
+       Elf_Rel *r;
+       Elf_Word rtab_size, r_size, num_rs;
+       Elf_Off rtab_offset;
+       Elf_Addr section_address;
+       Elf_Word j;
+       
+       grub_util_info ("translating the relocation section %s",
+                       strtab + grub_le_to_cpu32 (s->sh_name));
+                       
+       rtab_size = grub_le_to_cpu32 (s->sh_size);
+       r_size = grub_le_to_cpu32 (s->sh_entsize);
+       rtab_offset = grub_le_to_cpu32 (s->sh_offset);
+       num_rs = rtab_size / r_size;
+       
+       section_address = section_addresses[grub_le_to_cpu32 (s->sh_info)];
+
+       for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
+            j < num_rs;
+            j++, r = (Elf_Rel *) ((char *) r + r_size))
+         {
+           Elf_Addr info;
+           Elf_Addr offset;
+
+           offset = grub_le_to_cpu32 (r->r_offset);
+           info = grub_le_to_cpu32 (r->r_info);
+
+           /* Necessary to relocate only absolute addresses.  */
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+           if (ELF_R_TYPE (info) == R_386_32)
+             {
+               Elf_Addr addr;
+
+               addr = section_address + offset;
+               grub_util_info ("adding a relocation entry for 0x%x", addr);
+               current_address = add_fixup_entry (&fixup_block,
+                                                  GRUB_PE32_REL_BASED_HIGHLOW,
+                                                  addr, 0, current_address,
+                                                  out);
+             }
+#else
+           if ((ELF_R_TYPE (info) == R_X86_64_64) ||
+                (ELF_R_TYPE (info) == R_X86_64_32) ||
+                (ELF_R_TYPE (info) == R_X86_64_32S))
+             {
+               Elf_Addr addr;
+
+               addr = section_address + offset;
+               grub_util_info ("adding a relocation entry for 0x%llx", addr);
+               current_address = add_fixup_entry (&fixup_block,
+                                                  GRUB_PE32_REL_BASED_HIGHLOW,
+                                                  addr, 0, current_address,
+                                                  out);
+             }
+#endif
+         }
+      }
+
+  current_address = add_fixup_entry (&fixup_block, 0, 0, 1,
+                                    current_address, out);
+
+  return current_address;
+}
+
+/* Create the header.  */
+static void
+make_header (FILE *out, Elf_Addr text_address, Elf_Addr data_address,
+            Elf_Addr mods_address, Elf_Addr reloc_address,
+            Elf_Addr end_address, Elf_Addr start_address)
+{
+  struct grub_pe32_header header;
+  struct grub_pe32_coff_header *c;
+  struct grub_pe32_optional_header *o;
+  struct grub_pe32_section_table text_section, data_section;
+  struct grub_pe32_section_table mods_section, reloc_section;
+
+  /* The magic.  */
+  memset (&header, 0, sizeof (header));
+  memcpy (header.msdos_stub, stub, sizeof (header.msdos_stub));
+  memcpy (header.signature, "PE\0\0", sizeof (header.signature));
+
+  /* The COFF file header.  */
+  c = &header.coff_header;
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+  c->machine = grub_cpu_to_le16 (GRUB_PE32_MACHINE_I386);
+#else
+  c->machine = grub_cpu_to_le16 (GRUB_PE32_MACHINE_X86_64);
+#endif
+
+  c->num_sections = grub_cpu_to_le16 (4);
+  c->time = grub_cpu_to_le32 (time (0));
+  c->optional_header_size = grub_cpu_to_le16 (sizeof (header.optional_header));
+  c->characteristics = grub_cpu_to_le16 (GRUB_PE32_EXECUTABLE_IMAGE
+                                        | GRUB_PE32_LINE_NUMS_STRIPPED
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+                                         | GRUB_PE32_32BIT_MACHINE
+#endif
+                                        | GRUB_PE32_LOCAL_SYMS_STRIPPED
+                                         | GRUB_PE32_DEBUG_STRIPPED);
+
+  /* The PE Optional header.  */
+  o = &header.optional_header;
+  o->magic = grub_cpu_to_le16 (GRUB_PE32_PE32_MAGIC);
+  o->code_size = grub_cpu_to_le32 (data_address - text_address);
+  o->data_size = grub_cpu_to_le32 (reloc_address - data_address);
+  o->bss_size = 0;
+  o->entry_addr = grub_cpu_to_le32 (start_address);
+  o->code_base = grub_cpu_to_le32 (text_address);
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+  o->data_base = grub_cpu_to_le32 (data_address);
+#endif
+  o->image_base = 0;
+  o->section_alignment = grub_cpu_to_le32 (GRUB_PE32_SECTION_ALIGNMENT);
+  o->file_alignment = grub_cpu_to_le32 (GRUB_PE32_FILE_ALIGNMENT);
+  o->image_size = grub_cpu_to_le32 (end_address);
+  o->header_size = grub_cpu_to_le32 (text_address);
+  o->subsystem = grub_cpu_to_le16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
+  
+  /* Do these really matter? */
+  o->stack_reserve_size = grub_cpu_to_le32 (0x10000);
+  o->stack_commit_size = grub_cpu_to_le32 (0x10000);
+  o->heap_reserve_size = grub_cpu_to_le32 (0x10000);
+  o->heap_commit_size = grub_cpu_to_le32 (0x10000);
+
+  o->num_data_directories = grub_cpu_to_le32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
+  
+  o->base_relocation_table.rva = grub_cpu_to_le32 (reloc_address);
+  o->base_relocation_table.size = grub_cpu_to_le32 (end_address
+                                                   - reloc_address);
+
+  /* The sections.  */
+  memset (&text_section, 0, sizeof (text_section));
+  strcpy (text_section.name, ".text");
+  text_section.virtual_size = grub_cpu_to_le32 (data_address - text_address);
+  text_section.virtual_address = grub_cpu_to_le32 (text_address);
+  text_section.raw_data_size = grub_cpu_to_le32 (data_address - text_address);
+  text_section.raw_data_offset = grub_cpu_to_le32 (text_address);
+  text_section.characteristics = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_CODE
+                                                  | GRUB_PE32_SCN_MEM_EXECUTE
+                                                  | GRUB_PE32_SCN_MEM_READ);
+
+  memset (&data_section, 0, sizeof (data_section));
+  strcpy (data_section.name, ".data");
+  data_section.virtual_size = grub_cpu_to_le32 (mods_address - data_address);
+  data_section.virtual_address = grub_cpu_to_le32 (data_address);
+  data_section.raw_data_size = grub_cpu_to_le32 (mods_address - data_address);
+  data_section.raw_data_offset = grub_cpu_to_le32 (data_address);
+  data_section.characteristics
+    = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
+                       | GRUB_PE32_SCN_MEM_READ
+                       | GRUB_PE32_SCN_MEM_WRITE);
+
+  memset (&mods_section, 0, sizeof (mods_section));
+  strcpy (mods_section.name, "mods");
+  mods_section.virtual_size = grub_cpu_to_le32 (reloc_address - mods_address);
+  mods_section.virtual_address = grub_cpu_to_le32 (mods_address);
+  mods_section.raw_data_size = grub_cpu_to_le32 (reloc_address - mods_address);
+  mods_section.raw_data_offset = grub_cpu_to_le32 (mods_address);
+  mods_section.characteristics
+    = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
+                       | GRUB_PE32_SCN_MEM_READ
+                       | GRUB_PE32_SCN_MEM_WRITE);
+
+  memset (&reloc_section, 0, sizeof (reloc_section));
+  strcpy (reloc_section.name, ".reloc");
+  reloc_section.virtual_size = grub_cpu_to_le32 (end_address - reloc_address);
+  reloc_section.virtual_address = grub_cpu_to_le32 (reloc_address);
+  reloc_section.raw_data_size = grub_cpu_to_le32 (end_address - reloc_address);
+  reloc_section.raw_data_offset = grub_cpu_to_le32 (reloc_address);
+  reloc_section.characteristics
+    = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
+                       | GRUB_PE32_SCN_MEM_DISCARDABLE
+                       | GRUB_PE32_SCN_MEM_READ);
+
+  /* Write them out.  */
+  if (fseeko (out, 0, SEEK_SET) < 0)
+    grub_util_error ("seek failed");
+
+  if (fwrite (&header, sizeof (header), 1, out) != 1
+      || fwrite (&text_section, sizeof (text_section), 1, out) != 1
+      || fwrite (&data_section, sizeof (data_section), 1, out) != 1
+      || fwrite (&mods_section, sizeof (mods_section), 1, out) != 1
+      || fwrite (&reloc_section, sizeof (reloc_section), 1, out) != 1)
+    grub_util_error ("write failed");
+}
+
+/* Convert an ELF relocatable object into an EFI Application (PE32).  */
+void
+convert_elf (const char *dir, char *prefix, FILE *out, char *mods[])
+{
+  char *kernel_image;
+  size_t kernel_size;
+  const char *strtab;
+  Elf_Ehdr *e;
+  Elf_Shdr *sections;
+  Elf_Off section_offset;
+  Elf_Half section_entsize;
+  Elf_Half num_sections;
+  Elf_Addr *section_addresses;
+  Elf_Shdr *symtab_section;
+  Elf_Addr start_address;
+  Elf_Addr text_address, data_address, reloc_address, mods_address;
+  Elf_Addr end_address;
+
+  /* Get the kernel image and check the format.  */
+  kernel_image = read_kernel_module (dir, prefix, &kernel_size);
+  e = (Elf_Ehdr *) kernel_image;
+  if (! check_elf_header (e, kernel_size))
+    grub_util_error ("invalid ELF header");
+  
+  section_offset = grub_cpu_to_le32 (e->e_shoff);
+  section_entsize = grub_cpu_to_le16 (e->e_shentsize);
+  num_sections = grub_cpu_to_le16 (e->e_shnum);
+
+  if (kernel_size < section_offset + section_entsize * num_sections)
+    grub_util_error ("invalid ELF format");
+
+  sections = (Elf_Shdr *) (kernel_image + section_offset);
+  strtab = find_strtab (e, sections, section_entsize);
+
+  /* Relocate sections then symbols in the virtual address space.  */
+  section_addresses = locate_sections (sections, section_entsize,
+                                      num_sections, strtab);
+  
+  symtab_section = find_symtab_section (sections,
+                                       section_entsize, num_sections);
+  if (! symtab_section)
+    grub_util_error ("no symbol table");
+  
+  start_address = relocate_symbols (e, sections, symtab_section,
+                                   section_addresses, section_entsize,
+                                   num_sections);
+  if (start_address == 0)
+    grub_util_error ("start symbol is not defined");
+
+  /* Resolve addresses in the virtual address space.  */
+  relocate_addresses (e, sections, section_addresses, section_entsize,
+                     num_sections, strtab);
+
+  /* Generate a PE32 image file. The strategy is to dump binary data first,
+     then fill up the header.  */
+  text_address = make_header_space (out);
+  data_address = write_text_sections (out, text_address, e, sections,
+                                     section_entsize, num_sections,
+                                     strtab);
+  mods_address = write_data_sections (out, data_address, e, sections,
+                                     section_entsize, num_sections,
+                                     strtab);
+  reloc_address = make_mods_section (out, mods_address, dir, mods);
+  end_address = make_reloc_section (out, reloc_address, e, section_addresses,
+                                   sections, section_entsize, num_sections,
+                                   strtab);
+  make_header (out, text_address, data_address, mods_address,
+              reloc_address, end_address, start_address);
+
+  /* Clean up.  */
+  free (section_addresses);
+  free (kernel_image);
+}
+
+static struct option options[] =
+  {
+    {"directory", required_argument, 0, 'd'},
+    {"prefix", required_argument, 0, 'p'},
+    {"output", required_argument, 0, 'o'},
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+    {"verbose", no_argument, 0, 'v'},
+    { 0, 0, 0, 0 }
+  };
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr, "Try ``grub-mkimage --help'' for more information.\n");
+  else
+    printf ("\
+Usage: grub-mkimage -o FILE [OPTION]... [MODULES]\n\
+\n\
+Make a bootable image of GRUB.\n\
+\n\
+-d, --directory=DIR     use images and modules under DIR [default=%s]\n\
+-p, --prefix=DIR        set grub_prefix directory [default=%s]\n\
+-o, --output=FILE       output a generated image to FILE\n\
+-h, --help              display this message and exit\n\
+-V, --version           print version information and exit\n\
+-v, --verbose           print verbose messages\n\
+\n\
+Report bugs to <%s>.\n\
+", GRUB_LIBDIR, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT);
+
+  exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+  FILE *fp;
+  char *output = NULL;
+  char *dir = NULL;
+  char *prefix = NULL;
+
+  progname = "grub-mkimage";
+
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "d:p:o:hVv", options, 0);
+      if (c == -1)
+       break;
+
+      switch (c)
+       {
+         case 'd':
+           if (dir)
+             free (dir);
+           dir = xstrdup (optarg);
+           break;
+         case 'h':
+           usage (0);
+           break;
+         case 'o':
+           if (output)
+             free (output);
+           output = xstrdup (optarg);
+           break;
+         case 'p':
+           if (prefix)
+             free (prefix);
+           prefix = xstrdup (optarg);
+           break;
+         case 'V':
+           printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+           return 0;
+         case 'v':
+           verbosity++;
+           break;
+         default:
+           usage (1);
+           break;
+       }
+  }
+
+  if (! output)
+    usage (1);
+
+  fp = fopen (output, "wb");
+  if (! fp)
+    grub_util_error ("cannot open %s", output);
+
+  convert_elf (dir ? : GRUB_LIBDIR, prefix ? : DEFAULT_DIRECTORY, fp, argv + optind);
+
+  fclose (fp);
+
+  return 0;
+}
diff --git a/util/i386/pc/grub-install.in b/util/i386/pc/grub-install.in
new file mode 100644 (file)
index 0000000..ff1ed1e
--- /dev/null
@@ -0,0 +1,314 @@
+#! /bin/sh
+
+# Install GRUB on your drive.
+# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,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/>.
+
+# Initialize some variables.
+transform="@program_transform_name@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+sbindir=@sbindir@
+bindir=@bindir@
+libdir=@libdir@
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_TARNAME=@PACKAGE_TARNAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+target_cpu=@target_cpu@
+platform=@platform@
+pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`
+
+grub_setup=${sbindir}/`echo grub-setup | sed ${transform}`
+if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
+    grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}`
+else
+    grub_mkimage=${bindir}/`echo grub-mkelfimage | sed ${transform}`
+fi
+grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}`
+grub_probe=${sbindir}/`echo grub-probe | sed ${transform}`
+rootdir=
+grub_prefix=`echo /boot/grub | sed ${transform}`
+modules=
+
+install_device=
+no_floppy=
+force_lba=
+recheck=no
+debug=no
+
+# Usage: usage
+# Print the usage.
+usage () {
+    cat <<EOF
+Usage: grub-install [OPTION] install_device
+Install GRUB on your drive.
+
+  -h, --help              print this message and exit
+  -v, --version           print the version information and exit
+  --modules=MODULES       pre-load specified modules MODULES
+  --root-directory=DIR    install GRUB images under the directory DIR
+                          instead of the root directory
+  --grub-setup=FILE       use FILE as grub-setup
+  --grub-mkimage=FILE     use FILE as grub-mkimage
+  --grub-mkdevicemap=FILE use FILE as grub-mkdevicemap
+  --grub-probe=FILE       use FILE as grub-probe
+  --no-floppy             do not probe any floppy drive
+  --recheck               probe a device map even if it already exists
+
+INSTALL_DEVICE can be a GRUB device name or a system device filename.
+
+grub-install copies GRUB images into the DIR/boot directory specified by
+--root-directory, and uses grub-setup to install grub into the boot
+sector.
+
+Report bugs to <bug-grub@gnu.org>.
+EOF
+}
+
+# Check the arguments.
+for option in "$@"; do
+    case "$option" in
+    -h | --help)
+       usage
+       exit 0 ;;
+    -v | --version)
+       echo "grub-install (GNU GRUB ${PACKAGE_VERSION})"
+       exit 0 ;;
+    --modules=*)
+       modules=`echo "$option" | sed 's/--modules=//'` ;;
+    --root-directory=*)
+       rootdir=`echo "$option" | sed 's/--root-directory=//'` ;;
+    --grub-setup=*)
+       grub_setup=`echo "$option" | sed 's/--grub-setup=//'` ;;
+    --grub-mkimage=*)
+       grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;;
+    --grub-mkdevicemap=*)
+       grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;;
+    --grub-probe=*)
+       grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;;
+    --no-floppy)
+       no_floppy="--no-floppy" ;;
+    --recheck)
+       recheck=yes ;;
+    # This is an undocumented feature...
+    --debug)
+       debug=yes ;;
+    -*)
+       echo "Unrecognized option \`$option'" 1>&2
+       usage
+       exit 1
+       ;;
+    *)
+       if test "x$install_device" != x; then
+           echo "More than one install_devices?" 1>&2
+           usage
+           exit 1
+       fi
+       install_device="${option}" ;;
+    esac
+done
+
+# for make_system_path_relative_to_its_root()
+. ${libdir}/grub/grub-mkconfig_lib
+
+if test "x$install_device" = x; then
+    echo "install_device not specified." 1>&2
+    usage
+    exit 1
+fi
+
+# If the debugging feature is enabled, print commands.
+setup_verbose=
+if test $debug = yes; then
+    set -x
+    setup_verbose="--verbose"
+fi
+
+# Initialize these directories here, since ROOTDIR was initialized.
+case "$host_os" in
+netbsd* | openbsd*)
+    # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub
+    # instead of /boot/grub.
+    grub_prefix=`echo /grub | sed ${transform}`
+    bootdir=${rootdir}
+    ;;
+*)
+    # Use /boot/grub by default.
+    bootdir=${rootdir}/boot
+    ;;
+esac
+
+grubdir=${bootdir}/`echo grub | sed ${transform}`
+device_map=${grubdir}/device.map
+
+grub_probe="${grub_probe} --device-map=${device_map}"
+
+# Check if GRUB is installed.
+if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
+    set $grub_setup dummy
+    if test -f "$1"; then
+        :
+    else
+        echo "$1: Not found." 1>&2
+        exit 1
+    fi
+fi
+
+set $grub_mkimage dummy
+if test -f "$1"; then
+    :
+else
+    echo "$1: Not found." 1>&2
+    exit 1
+fi
+
+set $grub_mkdevicemap dummy
+if test -f "$1"; then
+    :
+else
+    echo "$1: Not found." 1>&2
+    exit 1
+fi
+
+# Create the GRUB directory if it is not present.
+test -d "$bootdir" || mkdir "$bootdir" || exit 1
+test -d "$grubdir" || mkdir "$grubdir" || exit 1
+
+# If --recheck is specified, remove the device map, if present.
+if test $recheck = yes; then
+    rm -f $device_map
+fi
+
+# Create the device map file if it is not present.
+if test -f "$device_map"; then
+    :
+else
+    # Create a safe temporary file.
+    test -n "$mklog" && log_file=`$mklog`
+
+    $grub_mkdevicemap --device-map=$device_map $no_floppy || exit 1
+fi
+
+# Make sure that there is no duplicated entry.
+tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' $device_map \
+    | sort | uniq -d | sed -n 1p`
+if test -n "$tmp"; then
+    echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2
+    exit 1
+fi
+
+# Copy the GRUB images to the GRUB directory.
+for file in ${grubdir}/*.mod ${grubdir}/*.lst ${grubdir}/*.img; do
+    if test -f $file && [ "`basename $file`" != menu.lst ]; then
+       rm -f $file || exit 1
+    fi
+done
+for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst; do
+    cp -f $file ${grubdir} || exit 1
+done
+if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
+    for file in ${pkglibdir}/*.img; do
+        cp -f $file ${grubdir} || exit 1
+    done
+fi
+
+# Write device to a variable so we don't have to traverse /dev every time.
+grub_device=`$grub_probe --target=device ${grubdir}`
+
+# Create the core image. First, auto-detect the filesystem module.
+fs_module=`$grub_probe --target=fs --device ${grub_device}`
+if test "x$fs_module" = x -a "x$modules" = x; then
+    echo "Auto-detection of a filesystem module failed." 1>&2
+    echo "Please specify the module with the option \`--modules' explicitly." 1>&2
+    exit 1
+fi
+
+# Then the partition map module.  In order to support partition-less media,
+# this command is allowed to fail (--target=fs already grants us that the
+# filesystem will be accessible).
+partmap_module=`$grub_probe --target=partmap --device ${grub_device} 2> /dev/null`
+
+# Device abstraction module, if any (lvm, raid).
+devabstraction_module=`$grub_probe --target=abstraction --device ${grub_device}`
+
+# The order in this list is critical.  Be careful when modifying it.
+if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
+    modules="$modules biosdisk"
+else
+    modules="$modules ata"
+fi
+modules="$modules $fs_module $partmap_module $devabstraction_module"
+
+prefix_drive=
+if [ "x${devabstraction_module}" = "x" ] ; then
+    if echo "${install_device}" | grep -qx "(.*)" ; then
+      install_drive="${install_device}"
+    else
+      install_drive="`$grub_probe --target=drive --device ${install_device}`"
+    fi
+    grub_drive="`$grub_probe --target=drive --device ${grub_device}`"
+
+    # Strip partition number
+    install_drive="`echo ${install_drive} | sed -e s/,[0-9]*//g`"
+    grub_drive="`echo ${grub_drive} | sed -e s/,[0-9]*//g`"
+    if [ "${target_cpu}-${platform}" != "i386-pc" ] ; then
+        # generic method (used on coreboot)
+        uuid="`$grub_probe --target=fs_uuid --device ${grub_device}`"
+        if [ "x${uuid}" = "x" ] ; then
+          echo "UUID needed on this platform, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2
+          exit 1
+        fi
+        prefix_drive="(UUID=${uuid})"
+        modules="$modules fs_uuid"
+    elif [ "x${grub_drive}" != "x${install_drive}" ] ; then
+        uuid="`$grub_probe --target=fs_uuid --device ${grub_device}`"
+        if [ "x${uuid}" = "x" ] ; then
+          echo "You attempted a cross-disk install, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2
+          exit 1
+        fi
+        prefix_drive="(UUID=${uuid})"
+        modules="$modules fs_uuid"
+    fi
+else
+    prefix_drive=`$grub_probe --target=drive --device ${grub_device}`
+fi
+
+relative_grubdir=`make_system_path_relative_to_its_root ${grubdir}` || exit 1
+if [ "x${relative_grubdir}" = "x" ] ; then
+    relative_grubdir=/
+fi
+
+if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
+    $grub_mkimage --output=${grubdir}/core.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1
+
+    # Now perform the installation.
+    $grub_setup ${setup_verbose} --directory=${grubdir} --device-map=${device_map} \
+        ${install_device} || exit 1
+else
+    $grub_mkimage -d ${pkglibdir} --output=/boot/multiboot.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1
+fi
+
+# Prompt the user to check if the device map is correct.
+echo "Installation finished. No error reported."
+echo "This is the contents of the device map $device_map."
+echo "Check if this is correct or not. If any of the lines is incorrect,"
+echo "fix it and re-run the script \`grub-install'."
+echo
+
+cat $device_map
+
+# Bye.
+exit 0
diff --git a/util/i386/pc/grub-mkimage.c b/util/i386/pc/grub-mkimage.c
new file mode 100644 (file)
index 0000000..4625b6d
--- /dev/null
@@ -0,0 +1,397 @@
+/* grub-mkimage.c - make a bootable image */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,2005,2006,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/>.
+ */
+
+#include <config.h>
+#include <grub/types.h>
+#include <grub/machine/boot.h>
+#include <grub/machine/kernel.h>
+#include <grub/machine/memory.h>
+#include <grub/kernel.h>
+#include <grub/disk.h>
+#include <grub/util/misc.h>
+#include <grub/util/resolve.h>
+#include <grub/misc.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define _GNU_SOURCE    1
+#include <getopt.h>
+
+#if defined(ENABLE_LZO)
+
+#if defined(HAVE_LZO_LZO1X_H)
+# include <lzo/lzo1x.h>
+#elif defined(HAVE_LZO1X_H)
+# include <lzo1x.h>
+#endif
+
+#elif defined(ENABLE_LZMA)
+
+#include <grub/lib/LzmaEnc.h>
+
+#endif
+
+#if defined(ENABLE_LZO)
+
+static void
+compress_kernel (char *kernel_img, size_t kernel_size,
+                char **core_img, size_t *core_size)
+{
+  lzo_uint size;
+  char *wrkmem;
+  
+  grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size);
+  if (kernel_size < GRUB_KERNEL_MACHINE_RAW_SIZE)
+    grub_util_error ("the core image is too small");
+  
+  if (lzo_init () != LZO_E_OK)
+    grub_util_error ("cannot initialize LZO");
+
+  *core_img = xmalloc (kernel_size + kernel_size / 64 + 16 + 3);
+  wrkmem = xmalloc (LZO1X_999_MEM_COMPRESS);
+
+  memcpy (*core_img, kernel_img, GRUB_KERNEL_MACHINE_RAW_SIZE);
+  
+  grub_util_info ("compressing the core image");
+  if (lzo1x_999_compress ((const lzo_byte *) (kernel_img
+                                             + GRUB_KERNEL_MACHINE_RAW_SIZE),
+                         kernel_size - GRUB_KERNEL_MACHINE_RAW_SIZE,
+                         (lzo_byte *) (*core_img
+                                       + GRUB_KERNEL_MACHINE_RAW_SIZE),
+                         &size, wrkmem)
+      != LZO_E_OK)
+    grub_util_error ("cannot compress the kernel image");
+
+  free (wrkmem);
+
+  *core_size = (size_t) size + GRUB_KERNEL_MACHINE_RAW_SIZE;
+}
+
+#elif defined(ENABLE_LZMA)
+
+static void *SzAlloc(void *p, size_t size) { p = p; return xmalloc(size); }
+static void SzFree(void *p, void *address) { p = p; free(address); }
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };
+
+static void
+compress_kernel (char *kernel_img, size_t kernel_size,
+                char **core_img, size_t *core_size)
+{
+  CLzmaEncProps props;
+  unsigned char out_props[5];
+  size_t out_props_size = 5;
+
+  LzmaEncProps_Init(&props);
+  props.dictSize = 1 << 16;
+  props.lc = 3;
+  props.lp = 0;
+  props.pb = 2;
+  props.numThreads = 1;
+
+  grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size);
+  if (kernel_size < GRUB_KERNEL_MACHINE_RAW_SIZE)
+    grub_util_error ("the core image is too small");
+
+  *core_img = xmalloc (kernel_size);
+  memcpy (*core_img, kernel_img, GRUB_KERNEL_MACHINE_RAW_SIZE);
+
+  *core_size = kernel_size - GRUB_KERNEL_MACHINE_RAW_SIZE;
+  if (LzmaEncode((unsigned char *) *core_img + GRUB_KERNEL_MACHINE_RAW_SIZE,
+                 core_size,
+                 (unsigned char *) kernel_img + GRUB_KERNEL_MACHINE_RAW_SIZE,
+                 kernel_size - GRUB_KERNEL_MACHINE_RAW_SIZE,
+                 &props, out_props, &out_props_size,
+                 0, NULL, &g_Alloc, &g_Alloc) != SZ_OK)
+    grub_util_error ("cannot compress the kernel image");
+
+  *core_size += GRUB_KERNEL_MACHINE_RAW_SIZE;
+}
+
+#endif
+
+static void
+generate_image (const char *dir, char *prefix, FILE *out, char *mods[], char *memdisk_path)
+{
+  grub_addr_t module_addr = 0;
+  char *kernel_img, *boot_img, *core_img;
+  size_t kernel_size, boot_size, total_module_size, core_size, memdisk_size = 0;
+  char *kernel_path, *boot_path;
+  unsigned num;
+  size_t offset;
+  struct grub_util_path_list *path_list, *p, *next;
+  struct grub_module_info *modinfo;
+
+  path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
+
+  kernel_path = grub_util_get_path (dir, "kernel.img");
+  kernel_size = grub_util_get_image_size (kernel_path);
+
+  total_module_size = sizeof (struct grub_module_info);
+
+  if (memdisk_path)
+    {
+      memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512);
+      grub_util_info ("the size of memory disk is 0x%x", memdisk_size);
+      total_module_size += memdisk_size + sizeof (struct grub_module_header);
+    }
+
+  for (p = path_list; p; p = p->next)
+    total_module_size += (grub_util_get_image_size (p->name)
+                         + sizeof (struct grub_module_header));
+
+  grub_util_info ("the total module size is 0x%x", total_module_size);
+
+  kernel_img = xmalloc (kernel_size + total_module_size);
+  grub_util_load_image (kernel_path, kernel_img);
+
+  if (GRUB_KERNEL_MACHINE_PREFIX + strlen (prefix) + 1 > GRUB_KERNEL_MACHINE_DATA_END)
+    grub_util_error ("prefix too long");
+  strcpy (kernel_img + GRUB_KERNEL_MACHINE_PREFIX, prefix);
+
+  /* Fill in the grub_module_info structure.  */
+  modinfo = (struct grub_module_info *) (kernel_img + kernel_size);
+  modinfo->magic = GRUB_MODULE_MAGIC;
+  modinfo->offset = sizeof (struct grub_module_info);
+  modinfo->size = total_module_size;
+
+  offset = kernel_size + sizeof (struct grub_module_info);
+  for (p = path_list; p; p = p->next)
+    {
+      struct grub_module_header *header;
+      size_t mod_size;
+
+      mod_size = grub_util_get_image_size (p->name);
+      
+      header = (struct grub_module_header *) (kernel_img + offset);
+      header->type = grub_cpu_to_le32 (OBJ_TYPE_ELF);
+      header->size = grub_cpu_to_le32 (mod_size + sizeof (*header));
+      offset += sizeof (*header);
+
+      grub_util_load_image (p->name, kernel_img + offset);
+      offset += mod_size;
+    }
+
+  if (memdisk_path)
+    {
+      struct grub_module_header *header;
+      
+      header = (struct grub_module_header *) (kernel_img + offset);
+      header->type = grub_cpu_to_le32 (OBJ_TYPE_MEMDISK);
+      header->size = grub_cpu_to_le32 (memdisk_size + sizeof (*header));
+      offset += sizeof (*header);
+
+      grub_util_load_image (memdisk_path, kernel_img + offset);
+      offset += memdisk_size;
+    }
+
+  compress_kernel (kernel_img, kernel_size + total_module_size,
+                  &core_img, &core_size);
+
+  grub_util_info ("the core size is 0x%x", core_size);
+  
+  num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
+  if (num > 0xffff)
+    grub_util_error ("the core image is too big");
+
+  boot_path = grub_util_get_path (dir, "diskboot.img");
+  boot_size = grub_util_get_image_size (boot_path);
+  if (boot_size != GRUB_DISK_SECTOR_SIZE)
+    grub_util_error ("diskboot.img is not one sector size");
+  
+  boot_img = grub_util_read_image (boot_path);
+  
+  /* i386 is a little endian architecture.  */
+  *((grub_uint16_t *) (boot_img + GRUB_DISK_SECTOR_SIZE
+                      - GRUB_BOOT_MACHINE_LIST_SIZE + 8))
+    = grub_cpu_to_le16 (num);
+
+  grub_util_write_image (boot_img, boot_size, out);
+  free (boot_img);
+  free (boot_path);
+  
+  module_addr = (path_list
+                ? (GRUB_BOOT_MACHINE_KERNEL_ADDR + GRUB_DISK_SECTOR_SIZE
+                   + kernel_size)
+                : 0);
+
+  grub_util_info ("the first module address is 0x%x", module_addr);
+  *((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE))
+    = grub_cpu_to_le32 (total_module_size);
+  *((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE))
+    = grub_cpu_to_le32 (kernel_size);
+  *((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE))
+    = grub_cpu_to_le32 (core_size - GRUB_KERNEL_MACHINE_RAW_SIZE);
+
+  /* If we included a drive in our prefix, let GRUB know it doesn't have to
+     prepend the drive told by BIOS.  */
+  if (prefix[0] == '(')
+    {
+      *((grub_int32_t *) (core_img + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART))
+       = grub_cpu_to_le32 (-2);
+      *((grub_int32_t *) (core_img + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART))
+       = grub_cpu_to_le32 (-2);
+    }
+
+  if (core_size > GRUB_MEMORY_MACHINE_UPPER - GRUB_MEMORY_MACHINE_LINK_ADDR)
+    grub_util_error ("Core image is too big (%p > %p)\n", core_size,
+                    GRUB_MEMORY_MACHINE_UPPER - GRUB_MEMORY_MACHINE_LINK_ADDR);
+  
+  grub_util_write_image (core_img, core_size, out);
+  free (kernel_img);
+  free (core_img);
+  free (kernel_path);
+
+  while (path_list)
+    {
+      next = path_list->next;
+      free ((void *) path_list->name);
+      free (path_list);
+      path_list = next;
+    }
+}
+
+\f
+
+static struct option options[] =
+  {
+    {"directory", required_argument, 0, 'd'},
+    {"prefix", required_argument, 0, 'p'},
+    {"memdisk", required_argument, 0, 'm'},
+    {"output", required_argument, 0, 'o'},
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+    {"verbose", no_argument, 0, 'v'},
+    {0, 0, 0, 0}
+  };
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr, "Try ``grub-mkimage --help'' for more information.\n");
+  else
+    printf ("\
+Usage: grub-mkimage [OPTION]... [MODULES]\n\
+\n\
+Make a bootable image of GRUB.\n\
+\n\
+  -d, --directory=DIR     use images and modules under DIR [default=%s]\n\
+  -p, --prefix=DIR        set grub_prefix directory [default=%s]\n\
+  -m, --memdisk=FILE      embed FILE as a memdisk image\n\
+  -o, --output=FILE       output a generated image to FILE [default=stdout]\n\
+  -h, --help              display this message and exit\n\
+  -V, --version           print version information and exit\n\
+  -v, --verbose           print verbose messages\n\
+\n\
+Report bugs to <%s>.\n\
+", GRUB_LIBDIR, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT);
+
+  exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+  char *output = NULL;
+  char *dir = NULL;
+  char *prefix = NULL;
+  char *memdisk = NULL;
+  FILE *fp = stdout;
+
+  progname = "grub-mkimage";
+  
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "d:p:m:o:hVv", options, 0);
+
+      if (c == -1)
+       break;
+      else
+       switch (c)
+         {
+         case 'o':
+           if (output)
+             free (output);
+           
+           output = xstrdup (optarg);
+           break;
+
+         case 'd':
+           if (dir)
+             free (dir);
+
+           dir = xstrdup (optarg);
+           break;
+
+         case 'm':
+           if (memdisk)
+             free (memdisk);
+
+           memdisk = xstrdup (optarg);
+       
+           if (prefix)
+             free (prefix);
+
+           prefix = xstrdup ("(memdisk)/boot/grub");
+           break;
+
+         case 'h':
+           usage (0);
+           break;
+
+         case 'p':
+           if (prefix)
+             free (prefix);
+
+           prefix = xstrdup (optarg);
+           break;
+
+         case 'V':
+           printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+           return 0;
+
+         case 'v':
+           verbosity++;
+           break;
+
+         default:
+           usage (1);
+           break;
+         }
+    }
+
+  if (output)
+    {
+      fp = fopen (output, "wb");
+      if (! fp)
+       grub_util_error ("cannot open %s", output);
+    }
+
+  generate_image (dir ? : GRUB_LIBDIR, prefix ? : DEFAULT_DIRECTORY, fp, argv + optind, memdisk);
+
+  fclose (fp);
+
+  if (dir)
+    free (dir);
+
+  return 0;
+}
diff --git a/util/i386/pc/grub-mkrescue.in b/util/i386/pc/grub-mkrescue.in
new file mode 100644 (file)
index 0000000..358b37b
--- /dev/null
@@ -0,0 +1,176 @@
+#! /bin/sh -e
+
+# Make GRUB rescue image
+# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,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/>.
+
+# 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@
+target_cpu=@target_cpu@
+platform=@platform@
+pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`
+
+grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}`
+
+# Usage: usage
+# Print the usage.
+usage () {
+    cat <<EOF
+Usage: grub-mkrescue [OPTION] output_image
+Make GRUB rescue image.
+
+  -h, --help              print this message and exit
+  -v, --version           print the version information and exit
+  --modules=MODULES       pre-load specified modules MODULES
+  --overlay=DIR           overlay directory DIR in the memdisk image
+                          (may be specified multiple times)
+  --pkglibdir=DIR         use images from directory DIR instead of ${pkglibdir}
+  --grub-mkimage=FILE     use FILE as grub-mkimage
+  --image-type=TYPE       select floppy or cdrom (default)
+  --emulation=TYPE        select El Torito boot emulation type floppy
+                          or none (default) (cdrom only)
+
+grub-mkimage generates a bootable rescue image of the specified type.
+
+Report bugs to <bug-grub@gnu.org>.
+EOF
+}
+
+image_type=cdrom
+input_dir=${pkglibdir}
+emulation=none
+
+# Check the arguments.
+for option in "$@"; do
+    case "$option" in
+    -h | --help)
+       usage
+       exit 0 ;;
+    -v | --version)
+       echo "grub-mkrescue (GNU GRUB ${PACKAGE_VERSION})"
+       exit 0 ;;
+    --modules=*)
+       modules=`echo "$option" | sed 's/--modules=//'` ;;
+    --overlay=*)
+       overlay=${overlay}${overlay:+ }`echo "$option" | sed 's/--overlay=//'` ;;
+    --pkglibdir=*)
+       input_dir=`echo "$option" | sed 's/--pkglibdir=//'` ;;
+    --grub-mkimage=*)
+       grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;;
+    --image-type=*)
+       image_type=`echo "$option" | sed 's/--image-type=//'`
+        case "$image_type" in
+          floppy|cdrom) ;;
+          *)
+            echo "Unknown image type \`$image_type'" 1>&2
+            exit 1 ;;
+        esac ;;
+    --emulation=*)
+       emulation=`echo "$option" | sed 's/--emulation=//'`
+        case "$emulation" in
+          floppy|none) ;;
+          *)
+            echo "Unknown emulation type \`$emulation'" 1>&2
+            exit 1 ;;
+        esac ;;
+    -*)
+       echo "Unrecognized option \`$option'" 1>&2
+       usage
+       exit 1
+       ;;
+    *)
+       if test "x$output_image" != x; then
+           echo "Unrecognized option \`$option'" 1>&2
+           usage
+           exit 1
+       fi
+       output_image="${option}" ;;
+    esac
+done
+
+if test "x$output_image" = x; then
+  usage
+  exit 1
+fi
+
+aux_dir=`mktemp -d`
+mkdir -p ${aux_dir}/boot/grub
+
+cp ${input_dir}/*.mod \
+  ${input_dir}/command.lst ${input_dir}/moddep.lst ${input_dir}/fs.lst \
+  ${aux_dir}/boot/grub/
+
+modules="biosdisk `cat ${input_dir}/partmap.lst` ${modules}"
+for i in ${modules} ; do
+  echo "insmod $i"
+done > ${aux_dir}/boot/grub/grub.cfg
+
+for d in ${overlay}; do
+  echo "Overlaying $d"
+  cp -dpR "${d}"/* "${aux_dir}"/
+done
+
+if [ "x${image_type}" = xfloppy -o "x${emulation}" = xfloppy ] ; then
+  # build memdisk
+  memdisk_img=`mktemp`
+  tar -C ${aux_dir} -cf ${memdisk_img} boot
+  rm -rf ${aux_dir}
+
+  # build core.img
+  core_img=`mktemp`
+  ${grub_mkimage} -d ${input_dir}/ -m ${memdisk_img} -o ${core_img} memdisk tar
+  rm -f ${memdisk_img}
+
+  # build floppy image
+  if [ "x${image_type}" = xcdrom ] ; then
+    floppy_dir=`mktemp -d`
+    floppy_img=${floppy_dir}/grub_floppy.img
+  else
+    floppy_img=${output_image}
+  fi
+  cat ${input_dir}/boot.img ${core_img} /dev/zero | dd bs=1024 count=1440 > ${floppy_img}
+  rm -f ${core_img}
+
+  if [ "x${image_type}" = xcdrom ] ; then
+    # build iso image
+    genisoimage -b grub_floppy.img \
+      -o ${output_image} -r -J ${floppy_dir}
+    rm -rf ${floppy_dir}
+  fi
+else
+  # build core.img
+  core_img=`mktemp`
+  ${grub_mkimage} -d ${input_dir}/ -o ${core_img} biosdisk iso9660
+
+  # build grub_eltorito image
+  cat ${input_dir}/cdboot.img ${core_img} > ${aux_dir}/boot/grub/grub_eltorito
+  rm -f ${core_img}
+
+  # build iso image
+  genisoimage -b boot/grub/grub_eltorito \
+    -no-emul-boot -boot-load-size 4 -boot-info-table \
+    -o ${output_image} -r -J ${aux_dir}
+  rm -rf ${aux_dir}
+fi
+
+exit 0
diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c
new file mode 100644 (file)
index 0000000..ccbb465
--- /dev/null
@@ -0,0 +1,751 @@
+/* grub-setup.c - make GRUB usable */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,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/>.
+ */
+
+#include <config.h>
+#include <grub/types.h>
+#include <grub/util/misc.h>
+#include <grub/device.h>
+#include <grub/disk.h>
+#include <grub/file.h>
+#include <grub/fs.h>
+#include <grub/partition.h>
+#include <grub/pc_partition.h>
+#include <grub/gpt_partition.h>
+#include <grub/env.h>
+#include <grub/util/hostdisk.h>
+#include <grub/machine/boot.h>
+#include <grub/machine/kernel.h>
+#include <grub/term.h>
+#include <grub/util/raid.h>
+#include <grub/util/lvm.h>
+
+static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT;
+
+#include <grub_setup_init.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <grub/util/getroot.h>
+
+#define _GNU_SOURCE    1
+#include <getopt.h>
+
+#define DEFAULT_BOOT_FILE      "boot.img"
+#define DEFAULT_CORE_FILE      "core.img"
+
+/* This is the blocklist used in the diskboot image.  */
+struct boot_blocklist
+{
+  grub_uint64_t start;
+  grub_uint16_t len;
+  grub_uint16_t segment;
+} __attribute__ ((packed));
+
+void
+grub_putchar (int c)
+{
+  putchar (c);
+}
+
+int
+grub_getkey (void)
+{
+  return -1;
+}
+
+grub_term_input_t
+grub_term_get_current_input (void)
+{
+  return 0;
+}
+
+grub_term_output_t
+grub_term_get_current_output (void)
+{
+  return 0;
+}
+
+void
+grub_refresh (void)
+{
+  fflush (stdout);
+}
+
+static void
+setup (const char *dir,
+       const char *boot_file, const char *core_file,
+       const char *root, const char *dest, int must_embed)
+{
+  char *boot_path, *core_path, *core_path_dev;
+  char *boot_img, *core_img;
+  size_t boot_size, core_size;
+  grub_uint16_t core_sectors;
+  grub_device_t root_dev, dest_dev;
+  grub_uint8_t *boot_drive, *root_drive;
+  grub_disk_addr_t *kernel_sector;
+  grub_uint16_t *boot_drive_check;
+  struct boot_blocklist *first_block, *block;
+  grub_int32_t *install_dos_part, *install_bsd_part;
+  grub_int32_t dos_part, bsd_part;
+  char *tmp_img;
+  int i;
+  grub_disk_addr_t first_sector;
+  grub_uint16_t current_segment
+    = GRUB_BOOT_MACHINE_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4);
+  grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE;
+  grub_file_t file;
+  FILE *fp;
+  struct { grub_uint64_t start; grub_uint64_t end; } embed_region;
+  embed_region.start = embed_region.end = ~0UL;
+  int able_to_embed = 1;
+  
+  auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, unsigned offset,
+                              unsigned length);
+  auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, unsigned offset,
+                            unsigned length);
+
+  auto int find_usable_region (grub_disk_t disk,
+                              const grub_partition_t p);
+  int find_usable_region (grub_disk_t disk __attribute__ ((unused)),
+                         const grub_partition_t p)
+    {
+      if (! strcmp (p->partmap->name, "pc_partition_map"))
+       {
+         struct grub_pc_partition *pcdata = p->data;
+         
+         /* There's always an embed region, and it starts right after the MBR.  */
+         embed_region.start = 1;
+         
+         /* For its end offset, include as many dummy partitions as we can.  */
+         if (! grub_pc_partition_is_empty (pcdata->dos_type)
+             && ! grub_pc_partition_is_bsd (pcdata->dos_type)
+             && embed_region.end > p->start)
+           embed_region.end = p->start;
+       }
+      else
+       {
+         struct grub_gpt_partentry *gptdata = p->data;
+         
+         /* If there's an embed region, it is in a dedicated partition.  */
+         if (! memcmp (&gptdata->type, &grub_gpt_partition_type_bios_boot, 16))
+           {
+             embed_region.start = p->start;
+             embed_region.end = p->start + p->len;
+             
+             return 1;
+           }
+       }
+
+      return 0;
+    }
+  
+  void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, unsigned offset,
+                         unsigned length)
+    {
+      grub_util_info ("the first sector is <%llu,%u,%u>",
+                     sector, offset, length);
+      
+      if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE)
+       grub_util_error ("The first sector of the core file is not sector-aligned");
+
+      first_sector = sector;
+    }
+
+  void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, unsigned offset,
+                       unsigned length)
+    {
+      struct boot_blocklist *prev = block + 1;
+
+      grub_util_info ("saving <%llu,%u,%u> with the segment 0x%x",
+                     sector, offset, length, (unsigned) current_segment);
+      
+      if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE)
+       grub_util_error ("Non-sector-aligned data is found in the core file");
+
+      if (block != first_block
+         && (grub_le_to_cpu64 (prev->start)
+             + grub_le_to_cpu16 (prev->len)) == sector)
+       prev->len = grub_cpu_to_le16 (grub_le_to_cpu16 (prev->len) + 1);
+      else
+       {
+         block->start = grub_cpu_to_le64 (sector);
+         block->len = grub_cpu_to_le16 (1);
+         block->segment = grub_cpu_to_le16 (current_segment);
+
+         block--;
+         if (block->len)
+           grub_util_error ("The sectors of the core file are too fragmented");
+       }
+      
+      last_length = length;
+      current_segment += GRUB_DISK_SECTOR_SIZE >> 4;
+    }
+  
+  /* Read the boot image by the OS service.  */
+  boot_path = grub_util_get_path (dir, boot_file);
+  boot_size = grub_util_get_image_size (boot_path);
+  if (boot_size != GRUB_DISK_SECTOR_SIZE)
+    grub_util_error ("The size of `%s' is not %d",
+                    boot_path, GRUB_DISK_SECTOR_SIZE);
+  boot_img = grub_util_read_image (boot_path);
+  free (boot_path);
+
+  /* Set the addresses of variables in the boot image.  */
+  boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE);
+  root_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_ROOT_DRIVE);
+  kernel_sector = (grub_disk_addr_t *) (boot_img
+                                    + GRUB_BOOT_MACHINE_KERNEL_SECTOR);
+  boot_drive_check = (grub_uint16_t *) (boot_img
+                                       + GRUB_BOOT_MACHINE_DRIVE_CHECK);
+  
+  core_path = grub_util_get_path (dir, core_file);
+  core_size = grub_util_get_image_size (core_path);
+  core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1)
+                 >> GRUB_DISK_SECTOR_BITS);
+  if (core_size < GRUB_DISK_SECTOR_SIZE)
+    grub_util_error ("The size of `%s' is too small", core_path);
+  else if (core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE)
+    grub_util_error ("The size of `%s' is too large", core_path);
+  
+  core_img = grub_util_read_image (core_path);
+
+  /* Have FIRST_BLOCK to point to the first blocklist.  */
+  first_block = (struct boot_blocklist *) (core_img
+                                          + GRUB_DISK_SECTOR_SIZE
+                                          - sizeof (*block));
+
+  install_dos_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE
+                                      + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART);
+  install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE
+                                      + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART);
+
+  /* Open the root device and the destination device.  */
+  root_dev = grub_device_open (root);
+  if (! root_dev)
+    grub_util_error ("%s", grub_errmsg);
+
+  dest_dev = grub_device_open (dest);
+  if (! dest_dev)
+    grub_util_error ("%s", grub_errmsg);
+
+  grub_util_info ("setting the root device to `%s'", root);
+  if (grub_env_set ("root", root) != GRUB_ERR_NONE)
+    grub_util_error ("%s", grub_errmsg);
+
+  /* Read the original sector from the disk.  */
+  tmp_img = xmalloc (GRUB_DISK_SECTOR_SIZE);
+  if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img))
+    grub_util_error ("%s", grub_errmsg);
+
+  /* Copy the possible DOS BPB.  */
+  memcpy (boot_img + GRUB_BOOT_MACHINE_BPB_START,
+         tmp_img + GRUB_BOOT_MACHINE_BPB_START,
+         GRUB_BOOT_MACHINE_BPB_END - GRUB_BOOT_MACHINE_BPB_START);
+
+  /* Copy the possible partition table.  */
+  if (dest_dev->disk->has_partitions)
+    memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC,
+           tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC,
+           GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC);
+
+  free (tmp_img);
+  
+  /* If DEST_DRIVE is a hard disk, enable the workaround, which is
+     for buggy BIOSes which don't pass boot drive correctly. Instead,
+     they pass 0x00 or 0x01 even when booted from 0x80.  */
+  if (dest_dev->disk->id & 0x80)
+    /* Replace the jmp (2 bytes) with double nop's.  */
+    *boot_drive_check = 0x9090;
+
+  /* If we hardcoded drive as part of prefix, we don't want to
+     override the current setting.  */
+  if (*install_dos_part != -2)
+    {
+      /* Embed information about the installed location.  */
+      if (root_dev->disk->partition)
+       {
+         if (strcmp (root_dev->disk->partition->partmap->name,
+                     "pc_partition_map") == 0)
+           {
+             struct grub_pc_partition *pcdata =
+               root_dev->disk->partition->data;
+             dos_part = pcdata->dos_part;
+             bsd_part = pcdata->bsd_part;
+           }
+         else if (strcmp (root_dev->disk->partition->partmap->name,
+                          "gpt_partition_map") == 0)
+           {
+             dos_part = root_dev->disk->partition->index;
+             bsd_part = -1;
+           }
+         else
+           grub_util_error ("No PC style partitions found");
+       }
+      else
+       dos_part = bsd_part = -1;
+    }
+  else
+    {
+      dos_part = grub_le_to_cpu32 (*install_dos_part);
+      bsd_part = grub_le_to_cpu32 (*install_bsd_part);
+    }
+  
+  grub_util_info ("dos partition is %d, bsd partition is %d",
+                 dos_part, bsd_part);
+  
+  /* If the destination device can have partitions and it is the MBR,
+     try to embed the core image into after the MBR.  */
+  if (dest_dev->disk->has_partitions && ! dest_dev->disk->partition)
+    {
+      grub_partition_iterate (dest_dev->disk, find_usable_region);
+
+      /* If there is enough space...  */
+      if ((unsigned long) core_sectors <= embed_region.end - embed_region.start)
+       {
+         grub_util_info ("will embed the core image at sector 0x%llx", embed_region.start);
+
+         *install_dos_part = grub_cpu_to_le32 (dos_part);
+         *install_bsd_part = grub_cpu_to_le32 (bsd_part);
+
+         /* The first blocklist contains the whole sectors.  */
+         first_block->start = grub_cpu_to_le64 (embed_region.start + 1);
+         first_block->len = grub_cpu_to_le16 (core_sectors - 1);
+         first_block->segment
+           = grub_cpu_to_le16 (GRUB_BOOT_MACHINE_KERNEL_SEG
+                               + (GRUB_DISK_SECTOR_SIZE >> 4));
+
+         /* Make sure that the second blocklist is a terminator.  */
+         block = first_block - 1;
+         block->start = 0;
+         block->len = 0;
+         block->segment = 0;
+
+         /* Write the core image onto the disk.  */
+         if (grub_disk_write (dest_dev->disk, embed_region.start, 0, core_size, core_img))
+           grub_util_error ("%s", grub_errmsg);
+
+         /* FIXME: can this be skipped?  */
+         *boot_drive = 0xFF;
+         *root_drive = 0xFF;
+
+         *kernel_sector = grub_cpu_to_le64 (embed_region.start);
+
+         /* Write the boot image onto the disk.  */
+         if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE,
+                              boot_img))
+           grub_util_error ("%s", grub_errmsg);
+
+         goto finish;
+       }
+      else
+        able_to_embed = 0;
+    }
+  else
+    able_to_embed = 0;
+
+  if (must_embed && ! able_to_embed)
+    grub_util_error ("Core image is too big for embedding, but this is required when\n"
+                    "the root device is on a RAID array or LVM volume.");
+  
+  /* The core image must be put on a filesystem unfortunately.  */
+  grub_util_info ("will leave the core image on the filesystem");
+  
+  /* Make sure that GRUB reads the identical image as the OS.  */
+  tmp_img = xmalloc (core_size);
+  core_path_dev = grub_util_get_path (DEFAULT_DIRECTORY, core_file);
+  
+  /* It is a Good Thing to sync two times.  */
+  sync ();
+  sync ();
+
+#define MAX_TRIES      5
+  
+  for (i = 0; i < MAX_TRIES; i++)
+    {
+      grub_util_info ("attempting to read the core image `%s' from GRUB%s",
+                     core_path_dev, (i == 0) ? "" : " again");
+      
+      grub_disk_cache_invalidate_all ();
+      
+      file = grub_file_open (core_path_dev);
+      if (file)
+       {
+         if (grub_file_size (file) != core_size)
+           grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)",
+                           (int) grub_file_size (file), (int) core_size);
+         else if (grub_file_read (file, tmp_img, core_size)
+                  != (grub_ssize_t) core_size)
+           grub_util_info ("succeeded in opening the core image but cannot read %d bytes",
+                           (int) core_size);
+         else if (memcmp (core_img, tmp_img, core_size) != 0)
+           {
+#if 0
+             FILE *dump;
+             FILE *dump2;
+             
+             dump = fopen ("dump.img", "wb");
+             if (dump)
+               {
+                 fwrite (tmp_img, 1, core_size, dump);
+                 fclose (dump);
+               }
+
+             dump2 = fopen ("dump2.img", "wb");
+             if (dump2)
+               {
+                 fwrite (core_img, 1, core_size, dump2);
+                 fclose (dump2);
+               }
+             
+#endif      
+             grub_util_info ("succeeded in opening the core image but the data is different");
+           }
+         else
+           {
+             grub_file_close (file);
+             break;
+           }
+
+         grub_file_close (file);
+       }
+      else
+       grub_util_info ("couldn't open the core image");
+
+      if (grub_errno)
+       grub_util_info ("error message = %s", grub_errmsg);
+      
+      grub_errno = GRUB_ERR_NONE;
+      sync ();
+      sleep (1);
+    }
+
+  if (i == MAX_TRIES)
+    grub_util_error ("Cannot read `%s' correctly", core_path_dev);
+
+  /* Clean out the blocklists.  */
+  block = first_block;
+  while (block->len)
+    {
+      block->start = 0;
+      block->len = 0;
+      block->segment = 0;
+
+      block--;
+      
+      if ((char *) block <= core_img)
+       grub_util_error ("No terminator in the core image");
+    }
+  
+  /* Now read the core image to determine where the sectors are.  */
+  file = grub_file_open (core_path_dev);
+  if (! file)
+    grub_util_error ("%s", grub_errmsg);
+  
+  file->read_hook = save_first_sector;
+  if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE)
+      != GRUB_DISK_SECTOR_SIZE)
+    grub_util_error ("Failed to read the first sector of the core image");
+
+  block = first_block;
+  file->read_hook = save_blocklists;
+  if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE)
+      != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE)
+    grub_util_error ("Failed to read the rest sectors of the core image");
+
+  grub_file_close (file);
+  
+  free (core_path_dev);
+  free (tmp_img);
+  
+  *kernel_sector = grub_cpu_to_le64 (first_sector);
+
+  /* FIXME: can this be skipped?  */
+  *boot_drive = 0xFF;
+  *root_drive = 0xFF;
+
+  *install_dos_part = grub_cpu_to_le32 (dos_part);
+  *install_bsd_part = grub_cpu_to_le32 (bsd_part);
+
+  /* Write the first two sectors of the core image onto the disk.  */
+  grub_util_info ("opening the core image `%s'", core_path);
+  fp = fopen (core_path, "r+b");
+  if (! fp)
+    grub_util_error ("Cannot open `%s'", core_path);
+
+  grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp);
+  fclose (fp);
+
+  /* Write the boot image onto the disk.  */
+  if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, boot_img))
+    grub_util_error ("%s", grub_errmsg);
+
+ finish:
+
+  /* Sync is a Good Thing.  */
+  sync ();
+  
+  free (core_path);
+  free (core_img);
+  free (boot_img);
+  grub_device_close (dest_dev);
+  grub_device_close (root_dev);
+}
+
+static struct option options[] =
+  {
+    {"boot-image", required_argument, 0, 'b'},
+    {"core-image", required_argument, 0, 'c'},
+    {"directory", required_argument, 0, 'd'},
+    {"device-map", required_argument, 0, 'm'},
+    {"root-device", required_argument, 0, 'r'},
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+    {"verbose", no_argument, 0, 'v'},
+    {0, 0, 0, 0}
+  };
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr, "Try ``grub-setup --help'' for more information.\n");
+  else
+    printf ("\
+Usage: grub-setup [OPTION]... DEVICE\n\
+\n\
+Set up images to boot from DEVICE.\n\
+DEVICE must be a GRUB device (e.g. ``(hd0,1)'').\n\
+\n\
+  -b, --boot-image=FILE   use FILE as the boot image [default=%s]\n\
+  -c, --core-image=FILE   use FILE as the core image [default=%s]\n\
+  -d, --directory=DIR     use GRUB files in the directory DIR [default=%s]\n\
+  -m, --device-map=FILE   use FILE as the device map [default=%s]\n\
+  -r, --root-device=DEV   use DEV as the root device [default=guessed]\n\
+  -h, --help              display this message and exit\n\
+  -V, --version           print version information and exit\n\
+  -v, --verbose           print verbose messages\n\
+\n\
+Report bugs to <%s>.\n\
+",
+           DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY,
+           DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
+
+  exit (status);
+}
+
+static char *
+get_device_name (char *dev)
+{
+  size_t len = strlen (dev);
+  
+  if (dev[0] != '(' || dev[len - 1] != ')')
+    return 0;
+
+  dev[len - 1] = '\0';
+  return dev + 1;
+}
+
+int
+main (int argc, char *argv[])
+{
+  char *boot_file = 0;
+  char *core_file = 0;
+  char *dir = 0;
+  char *dev_map = 0;
+  char *root_dev = 0;
+  char *dest_dev;
+  int must_embed = 0;
+  
+  progname = "grub-setup";
+
+  /* Check for options.  */
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "b:c:d:m:r:hVv", options, 0);
+
+      if (c == -1)
+       break;
+      else
+       switch (c)
+         {
+         case 'b':
+           if (boot_file)
+             free (boot_file);
+
+           boot_file = xstrdup (optarg);
+           break;
+
+         case 'c':
+           if (core_file)
+             free (core_file);
+
+           core_file = xstrdup (optarg);
+           break;
+
+         case 'd':
+           if (dir)
+             free (dir);
+
+           dir = xstrdup (optarg);
+           break;
+           
+         case 'm':
+           if (dev_map)
+             free (dev_map);
+
+           dev_map = xstrdup (optarg);
+           break;
+
+         case 'r':
+           if (root_dev)
+             free (root_dev);
+
+           root_dev = xstrdup (optarg);
+           break;
+           
+         case 'h':
+           usage (0);
+           break;
+
+         case 'V':
+           printf ("grub-setup (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+           return 0;
+
+         case 'v':
+           verbosity++;
+           break;
+
+         default:
+           usage (1);
+           break;
+         }
+    }
+
+  if (verbosity > 1)
+    grub_env_set ("debug", "all");
+
+  /* Obtain DEST_DEV.  */
+  if (optind >= argc)
+    {
+      fprintf (stderr, "No device is specified.\n");
+      usage (1);
+    }
+
+  if (optind + 1 != argc)
+    {
+      fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
+      usage (1);
+    }
+
+  /* Initialize the emulated biosdisk driver.  */
+  grub_util_biosdisk_init (dev_map ? : DEFAULT_DEVICE_MAP);
+
+  /* Initialize all modules. */
+  grub_init_all ();
+  
+  dest_dev = get_device_name (argv[optind]);
+  if (! dest_dev)
+    {
+      /* Possibly, the user specified an OS device file.  */
+      dest_dev = grub_util_get_grub_dev (argv[optind]);
+      if (! dest_dev)
+       {
+         fprintf (stderr, "Invalid device `%s'.\n", argv[optind]);
+         usage (1);
+       }
+    }
+  else
+    /* For simplicity.  */
+    dest_dev = xstrdup (dest_dev);
+
+  if (root_dev)
+    {
+      char *tmp = get_device_name (root_dev);
+
+      if (! tmp)
+       grub_util_error ("Invalid root device `%s'", root_dev);
+      
+      tmp = xstrdup (tmp);
+      free (root_dev);
+      root_dev = tmp;
+    }
+  else
+    {
+      root_dev = grub_util_get_grub_dev (grub_guess_root_device (dir ? : DEFAULT_DIRECTORY));
+      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''.");
+       }
+    }
+
+#ifdef __linux__
+  if (grub_util_lvm_isvolume (root_dev))
+    must_embed = 1;
+  
+  if (root_dev[0] == 'm' && root_dev[1] == 'd'
+      && root_dev[2] >= '0' && root_dev[2] <= '9')
+    {
+      /* FIXME: we can avoid this on RAID1.  */
+      must_embed = 1;
+    }
+
+  if (dest_dev[0] == 'm' && dest_dev[1] == 'd'
+      && dest_dev[2] >= '0' && dest_dev[2] <= '9')
+    {
+      char **devicelist;
+      int i;
+
+      devicelist = grub_util_raid_getmembers (dest_dev);
+
+      for (i = 0; devicelist[i]; i++)
+       {
+         setup (dir ? : DEFAULT_DIRECTORY,
+                boot_file ? : DEFAULT_BOOT_FILE,
+                core_file ? : DEFAULT_CORE_FILE,
+                root_dev, grub_util_get_grub_dev (devicelist[i]), 1);
+       }
+    }
+  else
+#endif
+  /* Do the real work.  */
+    setup (dir ? : DEFAULT_DIRECTORY,
+          boot_file ? : DEFAULT_BOOT_FILE,
+          core_file ? : DEFAULT_CORE_FILE,
+          root_dev, dest_dev, must_embed);
+
+  /* Free resources.  */
+  grub_fini_all ();
+  grub_util_biosdisk_fini ();
+  
+  free (boot_file);
+  free (core_file);
+  free (dir);
+  free (dev_map);
+  free (root_dev);
+  free (dest_dev);
+  
+  return 0;
+}
diff --git a/util/i386/pc/misc.c b/util/i386/pc/misc.c
new file mode 100644 (file)
index 0000000..8490fbf
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <setjmp.h>
+
+#include <grub/util/misc.h>
+
+void
+grub_reboot (void)
+{
+  longjmp (main_env, 1);
+}
+
+void
+grub_halt (int no_apm __attribute__ ((unused)))
+{
+  grub_reboot ();
+}
diff --git a/util/ieee1275/grub-install.in b/util/ieee1275/grub-install.in
new file mode 100644 (file)
index 0000000..710ed12
--- /dev/null
@@ -0,0 +1,233 @@
+#! /bin/sh
+
+# Install GRUB on your drive.
+# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,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/>.
+
+# This script uses `ofpathname', which is downloadable from
+# http://ppc64-utils.ozlabs.org .
+
+# Initialize some variables.
+transform="@program_transform_name@"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+sbindir=@sbindir@
+bindir=@bindir@
+libdir=@libdir@
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_TARNAME=@PACKAGE_TARNAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+target_cpu=@target_cpu@
+platform=@platform@
+pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`
+
+grub_mkimage=${bindir}/`echo grub-mkelfimage | sed ${transform}`
+grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}`
+grub_probe=${sbindir}/`echo grub-probe | sed ${transform}`
+rootdir=
+grub_prefix=`echo /boot/grub | sed ${transform}`
+modules=
+
+install_device=
+debug=no
+update_nvram=yes
+
+ofpathname=/usr/sbin/ofpathname
+nvsetenv=/sbin/nvsetenv
+
+# Usage: usage
+# Print the usage.
+usage () {
+    cat <<EOF
+Usage: grub-install [OPTION] [install_device]
+Install GRUB on your drive.
+
+  -h, --help              print this message and exit
+  -v, --version           print the version information and exit
+  --modules=MODULES       pre-load specified modules MODULES
+  --root-directory=DIR    install GRUB images under the directory DIR
+                          instead of the root directory
+  --grub-mkdevicemap=FILE use FILE as grub-mkdevicemap
+  --grub-mkimage=FILE     use FILE as grub-mkimage
+  --grub-probe=FILE       use FILE as grub-probe
+  --no-nvram              don't update the boot-device NVRAM variable
+
+grub-install copies GRUB images into the DIR/boot directory specified by
+--root-directory, and uses nvsetenv to set the Open Firmware boot-device
+variable.
+
+Report bugs to <bug-grub@gnu.org>.
+EOF
+}
+
+# Check the arguments.
+for option in "$@"; do
+    case "$option" in
+    -h | --help)
+       usage
+       exit 0 ;;
+    -v | --version)
+       echo "grub-install (GNU GRUB ${PACKAGE_VERSION})"
+       exit 0 ;;
+    --modules=*)
+       modules=`echo "$option" | sed 's/--modules=//'` ;;
+    --root-directory=*)
+       rootdir=`echo "$option" | sed 's/--root-directory=//'` ;;
+    --grub-mkdevicemap=*)
+       grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;;
+    --grub-mkimage=*)
+       grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;;
+    --grub-probe=*)
+       grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;;
+    --no-nvram)
+       update_nvram=no ;;
+    # This is an undocumented feature...
+    --debug)
+       debug=yes ;;
+    -*)
+       echo "Unrecognized option \`$option'" 1>&2
+       usage
+       exit 1
+       ;;
+    *)
+       if test "x$install_device" != x; then
+           echo "More than one install_devices?" 1>&2
+           usage
+           exit 1
+       fi
+       install_device="${option}" ;;
+    esac
+done
+
+# If the debugging feature is enabled, print commands.
+if test $debug = yes; then
+    set -x
+fi
+
+# Initialize these directories here, since ROOTDIR was initialized.
+bootdir=${rootdir}/boot
+grubdir=${bootdir}/`echo grub | sed ${transform}`
+device_map=${grubdir}/device.map
+
+set $grub_mkimage dummy
+if test -f "$1"; then
+    :
+else
+    echo "$1: Not found." 1>&2
+    exit 1
+fi
+
+# Find the partition at the right mount point.
+install_device=`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${grubdir}`
+
+if test "x$install_device" = "x`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${bootdir}`"; then
+    echo "$grubdir must be a mount point."
+    exit 1
+fi
+# XXX warn on firmware-unreadable filesystems?
+
+# Create the GRUB directory if it is not present.
+test -d "$bootdir" || mkdir "$bootdir" || exit 1
+test -d "$grubdir" || mkdir "$grubdir" || exit 1
+
+# Create the device map file if it is not present.
+if test -f "$device_map"; then
+    :
+else
+    # Create a safe temporary file.
+    test -n "$mklog" && log_file=`$mklog`
+
+    $grub_mkdevicemap --device-map=$device_map $no_floppy || exit 1
+fi
+
+# Copy the GRUB images to the GRUB directory.
+for file in ${grubdir}/*.mod ${grubdir}/*.lst ; do
+    if test -f $file; then
+       rm -f $file || exit 1
+    fi
+done
+for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst ; do
+    cp -f $file ${grubdir} || exit 1
+done
+
+# Create the core image. First, auto-detect the filesystem module.
+fs_module=`$grub_probe --target=fs --device-map=${device_map} ${grubdir}`
+if test "x$fs_module" = x -a "x$modules" = x; then
+    echo "Auto-detection of a filesystem module failed." 1>&2
+    echo "Please specify the module with the option \`--modules' explicitly." 1>&2
+    exit 1
+fi
+
+# Then the partition map module.  In order to support partition-less media,
+# this command is allowed to fail (--target=fs already grants us that the
+# filesystem will be accessible).
+partmap_module=`$grub_probe --target=partmap --device-map=${device_map} ${grubdir} 2> /dev/null`
+
+# Device abstraction module, if any (lvm, raid).
+devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_map} ${grubdir}`
+
+modules="$modules $fs_module $partmap_module $devabstraction_module"
+
+# Now perform the installation.
+"$grub_mkimage" --directory=${pkglibdir} --output=${grubdir}/grub $modules || exit 1
+
+if test $update_nvram = yes; then
+    set $ofpathname dummy
+    if test -f "$1"; then
+       :
+    else
+       echo "$1: Not found." 1>&2
+       exit 1
+    fi
+
+    set $nvsetenv dummy
+    if test -f "$1"; then
+       :
+    else
+       echo "$1: Not found." 1>&2
+       exit 1
+    fi
+
+    # Get the Open Firmware device tree path translation.
+    dev=`echo $install_device | sed -e 's/\/dev\///' -e 's/[0-9]\+//'`
+    partno=`echo $install_device | sed -e 's/.*[^0-9]\([0-9]\+\)$/\1/'`
+    ofpath=`$ofpathname $dev` || {
+       echo "Couldn't find Open Firmware device tree path for $dev."
+       echo "You will have to set boot-device manually."
+       exit 1
+    }
+
+    # Point boot-device at the new grub install
+    boot_device="boot-device $ofpath:$partno,\\grub"
+    "$nvsetenv" "$boot_device" || {
+       echo "$nvsetenv failed."
+       echo "You will have to set boot-device manually.  At the Open Firmware prompt, type:"
+       echo "  setenv $boot_device"
+       exit 1
+    }
+fi
+
+# Prompt the user to check if the device map is correct.
+echo "Installation finished. No error reported."
+echo "This is the contents of the device map $device_map."
+echo "Check if this is correct or not. If any of the lines is incorrect,"
+echo "fix it and re-run the script \`grub-install'."
+echo
+
+cat $device_map
+
+# Bye.
+exit 0
diff --git a/util/lvm.c b/util/lvm.c
new file mode 100644 (file)
index 0000000..edd31b0
--- /dev/null
@@ -0,0 +1,50 @@
+/* lvm.c - LVM support for GRUB utils.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+/* We only support LVM on Linux.  */
+#ifdef __linux__
+
+#include <grub/util/misc.h>
+#include <grub/util/lvm.h>
+
+#include <string.h>
+#include <sys/stat.h>
+
+int
+grub_util_lvm_isvolume (char *name)
+{
+  char *devname;
+  struct stat st;
+  int err;
+  
+  devname = xmalloc (strlen (name) + 13);
+
+  strcpy (devname, "/dev/mapper/");
+  strcpy (devname+12, name);
+
+  err = stat (devname, &st);
+  free (devname);
+
+  if (err)
+    return 0;
+  else
+    return 1;
+}
+
+#endif /* ! __linux__ */
diff --git a/util/misc.c b/util/misc.c
new file mode 100644 (file)
index 0000000..559022f
--- /dev/null
@@ -0,0 +1,396 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2005,2006,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/>.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <grub/kernel.h>
+#include <grub/misc.h>
+#include <grub/cache.h>
+#include <grub/util/misc.h>
+#include <grub/mm.h>
+#include <grub/term.h>
+#include <grub/time.h>
+#include <grub/machine/time.h>
+
+/* Include malloc.h, only if memalign is available. It is known that
+   memalign is declared in malloc.h in all systems, if present.  */
+#ifdef HAVE_MEMALIGN
+# include <malloc.h>
+#endif
+
+char *progname = 0;
+int verbosity = 0;
+
+void
+grub_util_info (const char *fmt, ...)
+{
+  if (verbosity > 0)
+    {
+      va_list ap;
+      
+      fprintf (stderr, "%s: info: ", progname);
+      va_start (ap, fmt);
+      vfprintf (stderr, fmt, ap);
+      va_end (ap);
+      fputc ('\n', stderr);
+      fflush (stderr);
+    }
+}
+
+void
+grub_util_error (const char *fmt, ...)
+{
+  va_list ap;
+  
+  fprintf (stderr, "%s: error: ", progname);
+  va_start (ap, fmt);
+  vfprintf (stderr, fmt, ap);
+  va_end (ap);
+  fputc ('\n', stderr);
+  exit (1);
+}
+
+int
+grub_err_printf (const char *fmt, ...)
+{
+  va_list ap;
+  int ret;
+  
+  va_start (ap, fmt);
+  ret = vfprintf (stderr, fmt, ap);
+  va_end (ap);
+
+  return ret;
+}
+
+void *
+xmalloc (size_t size)
+{
+  void *p;
+  
+  p = malloc (size);
+  if (! p)
+    grub_util_error ("out of memory");
+
+  return p;
+}
+
+void *
+xrealloc (void *ptr, size_t size)
+{
+  ptr = realloc (ptr, size);
+  if (! ptr)
+    grub_util_error ("out of memory");
+
+  return ptr;
+}
+
+char *
+xstrdup (const char *str)
+{
+  size_t len;
+  char *dup;
+  
+  len = strlen (str);
+  dup = (char *) xmalloc (len + 1);
+  memcpy (dup, str, len + 1);
+
+  return dup;
+}
+
+char *
+grub_util_get_path (const char *dir, const char *file)
+{
+  char *path;
+  
+  path = (char *) xmalloc (strlen (dir) + 1 + strlen (file) + 1);
+  sprintf (path, "%s/%s", dir, file);
+  return path;
+}
+
+size_t
+grub_util_get_fp_size (FILE *fp)
+{
+  struct stat st;
+  
+  if (fflush (fp) == EOF)
+    grub_util_error ("fflush failed");
+
+  if (fstat (fileno (fp), &st) == -1)
+    grub_util_error ("fstat failed");
+  
+  return st.st_size;
+}
+
+size_t
+grub_util_get_image_size (const char *path)
+{
+  struct stat st;
+  
+  grub_util_info ("getting the size of %s", path);
+  
+  if (stat (path, &st) == -1)
+    grub_util_error ("cannot stat %s", path);
+  
+  return st.st_size;
+}
+
+void
+grub_util_read_at (void *img, size_t size, off_t offset, FILE *fp)
+{
+  if (fseeko (fp, offset, SEEK_SET) == -1)
+    grub_util_error ("seek failed");
+
+  if (fread (img, 1, size, fp) != size)
+    grub_util_error ("read failed");
+}
+
+char *
+grub_util_read_image (const char *path)
+{
+  char *img;
+  FILE *fp;
+  size_t size;
+  
+  grub_util_info ("reading %s", path);
+
+  size = grub_util_get_image_size (path);
+  img = (char *) xmalloc (size);
+
+  fp = fopen (path, "rb");
+  if (! fp)
+    grub_util_error ("cannot open %s", path);
+
+  grub_util_read_at (img, size, 0, fp);
+
+  fclose (fp);
+  
+  return img;
+}
+
+void
+grub_util_load_image (const char *path, char *buf)
+{
+  FILE *fp;
+  size_t size;
+  
+  grub_util_info ("reading %s", path);
+
+  size = grub_util_get_image_size (path);
+  
+  fp = fopen (path, "rb");
+  if (! fp)
+    grub_util_error ("cannot open %s", path);
+
+  if (fread (buf, 1, size, fp) != size)
+    grub_util_error ("cannot read %s", path);
+
+  fclose (fp);
+}
+
+void
+grub_util_write_image_at (const void *img, size_t size, off_t offset, FILE *out)
+{
+  grub_util_info ("writing 0x%x bytes at offset 0x%x", size, offset);
+  if (fseeko (out, offset, SEEK_SET) == -1)
+    grub_util_error ("seek failed");
+  if (fwrite (img, 1, size, out) != size)
+    grub_util_error ("write failed");
+}
+
+void
+grub_util_write_image (const char *img, size_t size, FILE *out)
+{
+  grub_util_info ("writing 0x%x bytes", size);
+  if (fwrite (img, 1, size, out) != size)
+    grub_util_error ("write failed");
+}
+
+void *
+grub_malloc (grub_size_t size)
+{
+  return xmalloc (size);
+}
+
+void
+grub_free (void *ptr)
+{
+  free (ptr);
+}
+
+void *
+grub_realloc (void *ptr, grub_size_t size)
+{
+  return xrealloc (ptr, size);
+}
+
+void *
+grub_memalign (grub_size_t align, grub_size_t size)
+{
+  void *p;
+
+#if defined(HAVE_POSIX_MEMALIGN)
+  if (posix_memalign (&p, align, size) != 0)
+    p = 0;
+#elif defined(HAVE_MEMALIGN)
+  p = memalign (align, size);
+#else
+  (void) align;
+  (void) size;
+  grub_util_error ("grub_memalign is not supported");
+#endif
+  
+  if (! p)
+    grub_util_error ("out of memory");
+  
+  return p;
+}
+
+/* Some functions that we don't use.  */
+void
+grub_mm_init_region (void *addr __attribute__ ((unused)),
+                    grub_size_t size __attribute__ ((unused)))
+{
+}
+
+void
+grub_register_exported_symbols (void)
+{
+}
+
+void
+grub_exit (void)
+{
+  exit (1);
+}
+
+grub_uint32_t
+grub_get_rtc (void)
+{
+  struct timeval tv;
+
+  gettimeofday (&tv, 0);
+  
+  return (tv.tv_sec * GRUB_TICKS_PER_SECOND
+         + (((tv.tv_sec % GRUB_TICKS_PER_SECOND) * 1000000 + tv.tv_usec)
+            * GRUB_TICKS_PER_SECOND / 1000000));
+}
+
+grub_uint64_t
+grub_get_time_ms (void)
+{
+  struct timeval tv;
+
+  gettimeofday (&tv, 0);
+  
+  return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
+}
+
+void 
+grub_arch_sync_caches (void *address __attribute__ ((unused)),
+                      grub_size_t len __attribute__ ((unused)))
+{
+}
+
+#ifndef  HAVE_ASPRINTF
+
+int
+asprintf (char **buf, const char *fmt, ...)
+{
+  int status;
+  va_list ap;
+
+  /* Should be large enough.  */
+  *buf = xmalloc (512);
+
+  va_start (ap, fmt);
+  status = vsprintf (*buf, fmt, ap);
+  va_end (ap);
+
+  return status;
+}
+
+#endif
+
+#ifdef __MINGW32__
+
+#include <windows.h>
+#include <winioctl.h>
+
+void sync (void)
+{
+}
+
+void sleep (int s)
+{
+  Sleep (s * 1000);
+}
+
+grub_int64_t
+grub_util_get_disk_size (char *name)
+{
+  HANDLE hd;
+  grub_int64_t size = -1LL;
+
+  hd = CreateFile (name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+                   0, OPEN_EXISTING, 0, 0);
+
+  if (hd == INVALID_HANDLE_VALUE)
+    return size;
+
+  if (((name[0] == '/') || (name[0] == '\\')) &&
+      ((name[1] == '/') || (name[1] == '\\')) &&
+      (name[2] == '.') &&
+      ((name[3] == '/') || (name[3] == '\\')) &&
+      (! strncasecmp (name + 4, "PHYSICALDRIVE", 13)))
+    {
+      DWORD nr;
+      DISK_GEOMETRY g;
+
+      if (! DeviceIoControl (hd, IOCTL_DISK_GET_DRIVE_GEOMETRY,
+                             0, 0, &g, sizeof (g), &nr, 0))
+        goto fail;
+
+      size = g.Cylinders.QuadPart;
+      size *= g.TracksPerCylinder * g.SectorsPerTrack * g.BytesPerSector;
+    }
+  else
+    {
+      LARGE_INTEGER s;
+
+      s.LowPart = GetFileSize (hd, &s.HighPart);
+      size = s.QuadPart;
+    }
+
+fail:
+
+  CloseHandle (hd);
+
+  return size;
+}
+
+#endif
diff --git a/util/powerpc/ieee1275/grub-mkrescue.in b/util/powerpc/ieee1275/grub-mkrescue.in
new file mode 100644 (file)
index 0000000..30bdabe
--- /dev/null
@@ -0,0 +1,115 @@
+#! /bin/sh -e
+
+# Make GRUB rescue image
+# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,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/>.
+
+# 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@
+target_cpu=@target_cpu@
+platform=@platform@
+pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`
+
+grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}`
+
+# Usage: usage
+# Print the usage.
+usage () {
+    cat <<EOF
+Usage: grub-mkrescue [OPTION] output_image
+Make GRUB rescue image.
+
+  -h, --help              print this message and exit
+  -v, --version           print the version information and exit
+  --modules=MODULES       pre-load specified modules MODULES
+  --pkglibdir=DIR         use images from directory DIR
+                          default: ${pkglibdir}
+  --grub-mkimage=FILE     use FILE as grub-mkimage
+
+grub-mkimage generates a bootable rescue CD image for PowerMac and CHRP.
+
+Report bugs to <bug-grub@gnu.org>.
+EOF
+}
+
+input_dir=${pkglibdir}
+
+# Check the arguments.
+for option in "$@"; do
+    case "$option" in
+    -h | --help)
+       usage
+       exit 0 ;;
+    -v | --version)
+       echo "grub-install (GNU GRUB ${PACKAGE_VERSION})"
+       exit 0 ;;
+    --modules=*)
+       modules=`echo "$option" | sed 's/--modules=//'` ;;
+    --pkglibdir=*)
+       input_dir=`echo "$option" | sed 's/--pkglibdir=//'` ;;
+    --grub-mkimage=*)
+       grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;;
+    -*)
+       echo "Unrecognized option \`$option'" 1>&2
+       usage
+       exit 1
+       ;;
+    *)
+       if test "x$output_image" != x; then
+           echo "Unrecognized option \`$option'" 1>&2
+           usage
+           exit 1
+       fi
+       output_image="${option}" ;;
+    esac
+done
+
+if test "x$output_image" = x; then
+  usage
+  exit 1
+fi
+
+if [ "x${modules}" = "x" ] ; then
+  modules=`cd ${input_dir}/ && ls *.mod`
+fi
+
+map_file=`mktemp`
+cat >${map_file} <<EOF
+# EXTN          XLate   CREATOR   TYPE     Comment
+grub.img        Raw     'UNIX'    'tbxi'   "bootstrap"
+EOF
+
+iso_dir=`mktemp -d`
+boot_dir=${iso_dir}/boot/grub
+mkdir ${iso_dir}/boot
+mkdir ${boot_dir}
+core_img=${boot_dir}/grub.img
+${grub_mkimage} -n -d ${input_dir}/ -o ${core_img} ${modules}
+genisoimage -hfs -part -no-desktop -r -J -o ${output_image} \
+ -map ${map_file} -hfs-bless ${boot_dir} -chrp-boot -sysid PPC \
+ ${iso_dir}
+
+rm -rf ${iso_dir}
+rm -f ${map_file}
+
+exit 0
diff --git a/util/powerpc/ieee1275/misc.c b/util/powerpc/ieee1275/misc.c
new file mode 100644 (file)
index 0000000..b0ce83b
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <setjmp.h>
+
+#include <grub/util/misc.h>
+
+void
+grub_reboot (void)
+{
+  longjmp (main_env, 1);
+}
+
+void
+grub_halt (void)
+{
+  grub_reboot ();
+}
diff --git a/util/raid.c b/util/raid.c
new file mode 100644 (file)
index 0000000..ad6e407
--- /dev/null
@@ -0,0 +1,112 @@
+/* raid.c - RAID support for GRUB utils.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+/* We only support RAID on Linux.  */
+#ifdef __linux__
+#include <grub/util/misc.h>
+#include <grub/util/raid.h>
+
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/raid/md_p.h>
+#include <linux/raid/md_u.h>
+
+static char *
+grub_util_getdiskname (int major, int minor)
+{
+  char *name = xmalloc (15);
+
+  if (major == LOOP_MAJOR)
+    sprintf (name, "/dev/loop%d", minor);
+  else if (major == IDE0_MAJOR)
+    sprintf (name, "/dev/hd%c", 'a' + minor / 64);
+  else if (major == IDE1_MAJOR)
+    sprintf (name, "/dev/hd%c", 'c' + minor / 64);
+  else if (major == IDE2_MAJOR)
+    sprintf (name, "/dev/hd%c", 'e' + minor / 64);
+  else if (major == IDE3_MAJOR)
+    sprintf (name, "/dev/hd%c", 'g' + minor / 64);
+  else if (major == SCSI_DISK0_MAJOR)
+    sprintf (name, "/dev/sd%c", 'a' + minor / 16);
+  else
+    grub_util_error ("Unknown device number: %d, %d", major, minor);
+    
+  return name;
+}
+
+char **
+grub_util_raid_getmembers (char *name)
+{
+  int fd, ret, i, j;
+  char *devname;
+  char **devicelist;
+  mdu_version_t version;
+  mdu_array_info_t info;
+  mdu_disk_info_t disk;
+
+  devname = xmalloc (strlen (name) + 6);
+  strcpy (devname, "/dev/");
+  strcpy (devname+5, name);
+
+  fd = open (devname, O_RDONLY);
+
+  if (fd == -1)
+    grub_util_error ("Can't open %s: %s", devname, strerror (errno));
+
+  free (devname);
+
+  ret = ioctl (fd, RAID_VERSION, &version);
+  if (ret != 0)
+    grub_util_error ("ioctl RAID_VERSION error: %s", strerror (errno));
+
+  if (version.major != 0 || version.minor != 90)
+    grub_util_error ("Unsupported RAID version: %d.%d",
+                    version.major, version.minor);
+  
+  ret = ioctl (fd, GET_ARRAY_INFO, &info);
+  if (ret != 0)
+    grub_util_error ("ioctl GET_ARRAY_INFO error: %s", strerror (errno));
+
+  devicelist = xmalloc ((info.nr_disks + 1) * sizeof (char *));
+
+  for (i = 0, j = 0; i <info.nr_disks; i++)
+    {
+      disk.number = i;
+      ret = ioctl (fd, GET_DISK_INFO, &disk);
+      if (ret != 0)
+       grub_util_error ("ioctl GET_DISK_INFO error: %s", strerror (errno));
+
+      if (disk.state & (1 << MD_DISK_ACTIVE))
+       {
+         devicelist[j] = grub_util_getdiskname (disk.major, disk.minor);
+         j++;
+       }
+    }
+
+  devicelist[j] = NULL;
+  
+  return devicelist;
+}
+
+#endif /* ! __linux__ */
diff --git a/util/resolve.c b/util/resolve.c
new file mode 100644 (file)
index 0000000..85aec72
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,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/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <grub/util/resolve.h>
+#include <grub/util/misc.h>
+
+/* Module.  */
+struct mod_list
+{
+  const char *name;
+  struct mod_list *next;
+};
+
+/* Dependency.  */
+struct dep_list
+{
+  const char *name;
+  struct mod_list *list;
+  struct dep_list *next;
+};
+
+static char buf[1024];
+
+static void
+free_mod_list (struct mod_list *head)
+{
+  while (head)
+    {
+      struct mod_list *next;
+
+      next = head->next;
+      free ((void *) head->name);
+      free (head);
+      head = next;
+    }
+}
+
+static void
+free_dep_list (struct dep_list *head)
+{
+  while (head)
+    {
+      struct dep_list *next;
+
+      next = head->next;
+      free ((void *) head->name);
+      free_mod_list (head->list);
+      free (head);
+      head = next;
+    }
+}
+
+/* Read the list of dependencies.  */
+static struct dep_list *
+read_dep_list (FILE *fp)
+{
+  struct dep_list *dep_list = 0;
+  
+  while (fgets (buf, sizeof (buf), fp))
+    {
+      char *p;
+      struct dep_list *dep;
+
+      /* Get the target name.  */
+      p = strchr (buf, ':');
+      if (! p)
+       grub_util_error ("invalid line format: %s", buf);
+
+      *p++ = '\0';
+
+      dep = xmalloc (sizeof (*dep));
+      dep->name = xstrdup (buf);
+      dep->list = 0;
+      
+      dep->next = dep_list;
+      dep_list = dep;
+
+      /* Add dependencies.  */
+      while (*p)
+       {
+         struct mod_list *mod;
+         char *name;
+
+         /* Skip white spaces.  */
+         while (*p && isspace (*p))
+           p++;
+
+         if (! *p)
+           break;
+
+         name = p;
+
+         /* Skip non-WSPs.  */
+         while (*p && ! isspace (*p))
+           p++;
+
+         *p++ = '\0';
+         
+         mod = (struct mod_list *) xmalloc (sizeof (*mod));
+         mod->name = xstrdup (name);
+         mod->next = dep->list;
+         dep->list = mod;
+       }
+    }
+
+  return dep_list;
+}
+
+static char *
+get_module_name (const char *str)
+{
+  char *base;
+  char *ext;
+  
+  base = strrchr (str, '/');
+  if (! base)
+    base = (char *) str;
+  else
+    base++;
+
+  ext = strrchr (base, '.');
+  if (ext && strcmp (ext, ".mod") == 0)
+    {
+      char *name;
+      
+      name = xmalloc (ext - base + 1);
+      memcpy (name, base, ext - base);
+      name[ext - base] = '\0';
+      return name;
+    }
+  
+  return xstrdup (base);
+}
+
+static char *
+get_module_path (const char *prefix, const char *str)
+{
+  char *dir;
+  char *base;
+  char *ext;
+  char *ret;
+  
+  ext = strrchr (str, '.');
+  if (ext && strcmp (ext, ".mod") == 0)
+    base = xstrdup (str);
+  else
+    {
+      base = xmalloc (strlen (str) + 4 + 1);
+      sprintf (base, "%s.mod", str);
+    }
+  
+  dir = strchr (str, '/');
+  if (dir)
+    return base;
+
+  ret = grub_util_get_path (prefix, base);
+  free (base);
+  return ret;
+}
+
+static void
+add_module (const char *dir,
+           struct dep_list *dep_list,
+           struct mod_list **mod_head,
+           struct grub_util_path_list **path_head,
+           const char *name)
+{
+  char *mod_name;
+  struct grub_util_path_list *path;
+  struct mod_list *mod;
+  struct dep_list *dep;
+  
+  mod_name = get_module_name (name);
+
+  /* Check if the module has already been added.  */
+  for (mod = *mod_head; mod; mod = mod->next)
+    if (strcmp (mod->name, mod_name) == 0)
+      {
+       free (mod_name);
+       return;
+      }
+
+  /* Resolve dependencies.  */
+  for (dep = dep_list; dep; dep = dep->next)
+    if (strcmp (dep->name, mod_name) == 0)
+      {
+       for (mod = dep->list; mod; mod = mod->next)
+         add_module (dir, dep_list, mod_head, path_head, mod->name);
+
+       break;
+      }
+
+  /* Add this module.  */
+  mod = (struct mod_list *) xmalloc (sizeof (*mod));
+  mod->name = mod_name;
+  mod->next = *mod_head;
+  *mod_head = mod;
+
+  /* Add this path.  */
+  path = (struct grub_util_path_list *) xmalloc (sizeof (*path));
+  path->name = get_module_path (dir, name);
+  path->next = *path_head;
+  *path_head = path;
+}
+
+struct grub_util_path_list *
+grub_util_resolve_dependencies (const char *prefix,
+                               const char *dep_list_file,
+                               char *modules[])
+{
+  char *path;
+  FILE *fp;
+  struct dep_list *dep_list;
+  struct mod_list *mod_list = 0;
+  struct grub_util_path_list *path_list = 0;
+
+  path = grub_util_get_path (prefix, dep_list_file);
+  fp = fopen (path, "r");
+  if (! fp)
+    grub_util_error ("cannot open %s", path);
+
+  free (path);
+  dep_list = read_dep_list (fp);
+  fclose (fp);
+
+  while (*modules)
+    {
+      add_module (prefix, dep_list, &mod_list, &path_list, *modules);
+      modules++;
+    }
+
+  free_dep_list (dep_list);
+  free_mod_list (mod_list);
+
+  { /* Reverse the path_list */
+    struct grub_util_path_list *p, *prev, *next;
+
+    for (p = path_list, prev = NULL; p; p = next)
+      {
+       next = p->next;
+       p->next = prev;
+       prev = p;
+      }
+
+    return prev;
+  }
+}
diff --git a/util/update-grub_lib.in b/util/update-grub_lib.in
new file mode 100644 (file)
index 0000000..998452e
--- /dev/null
@@ -0,0 +1,23 @@
+# stub for new grub-mkconfig_lib
+# 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/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+
+. ${libdir}/grub/grub-mkconfig_lib
+
+grub_warn "update-grub_lib is deprecated, use grub-mkconfig_lib instead"
diff --git a/util/usb.c b/util/usb.c
new file mode 100644 (file)
index 0000000..744ad86
--- /dev/null
@@ -0,0 +1,191 @@
+/*  usb.c -- libusb USB support for GRUB.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <usb.h>
+#include <grub/usb.h>
+#include <grub/dl.h>
+
+\f
+static struct grub_usb_controller_dev usb_controller =
+{
+  .name = "libusb"
+};
+
+static struct grub_usb_device *grub_usb_devs[128];
+
+struct usb_bus *busses;
+
+static grub_err_t
+grub_libusb_devices (void)
+
+{
+  struct usb_bus *bus;
+  int last = 0;
+
+  busses = usb_get_busses();
+
+  for (bus = busses; bus; bus = bus->next)
+    {
+      struct usb_device *usbdev;
+      struct grub_usb_device *dev;
+
+      for (usbdev = bus->devices; usbdev; usbdev = usbdev->next)
+       {
+         struct usb_device_descriptor *desc = &usbdev->descriptor;
+
+         if (! desc->bcdUSB)
+           continue;
+
+         dev = grub_malloc (sizeof (*dev));
+         if (! dev)
+           return grub_errno;
+
+         dev->data = usbdev;
+
+         /* Fill in all descriptors.  */
+         grub_usb_device_initialize (dev);
+
+         /* Register the device.  */
+         grub_usb_devs[last++] = dev;
+       }
+    }
+
+  return GRUB_USB_ERR_NONE;
+}
+
+grub_err_t
+grub_libusb_init (void)
+{
+  usb_init();
+  usb_find_busses();
+  usb_find_devices();
+
+  if (grub_libusb_devices ())
+    return grub_errno;
+
+  grub_usb_controller_dev_register (&usb_controller);  
+
+  return 0;
+}
+
+grub_err_t
+grub_libusb_fini (void)
+{
+  return 0;
+}
+
+\f
+int
+grub_usb_iterate (int (*hook) (grub_usb_device_t dev))
+{
+  int i;
+
+  for (i = 0; i < 128; i++)
+    {
+      if (grub_usb_devs[i])
+       {
+         if (hook (grub_usb_devs[i]))
+             return 1;
+       }
+    }
+
+  return 0;
+}
+
+grub_usb_err_t
+grub_usb_root_hub (grub_usb_controller_t controller __attribute__((unused)))
+{
+  return GRUB_USB_ERR_NONE;
+}
+
+grub_usb_err_t
+grub_usb_control_msg (grub_usb_device_t dev, grub_uint8_t reqtype,
+                     grub_uint8_t request, grub_uint16_t value,
+                     grub_uint16_t index, grub_size_t size, char *data)
+{
+  usb_dev_handle *devh;
+  struct usb_device *d = dev->data;
+
+  devh = usb_open (d);
+  if (usb_control_msg (devh, reqtype, request,
+                      value, index, data, size, 20) < 0)
+    {
+      usb_close (devh);
+      return GRUB_USB_ERR_STALL;
+    }
+
+  usb_close (devh);
+
+  return GRUB_USB_ERR_NONE;
+}
+
+grub_usb_err_t
+grub_usb_bulk_read (grub_usb_device_t dev,
+                   int endpoint, grub_size_t size, char *data)
+{
+  usb_dev_handle *devh;
+  struct usb_device *d = dev->data;
+
+  devh = usb_open (d);
+  if (usb_claim_interface (devh, 0) < 1)
+    {
+      usb_close (devh);
+      return GRUB_USB_ERR_STALL;
+    }
+
+  if (usb_bulk_read (devh, endpoint, data, size, 20) < 1)
+    {
+      usb_close (devh);
+      return GRUB_USB_ERR_STALL;
+    }
+
+  usb_release_interface (devh, 0);
+  usb_close (devh);
+
+  return GRUB_USB_ERR_NONE;
+}
+
+grub_usb_err_t
+grub_usb_bulk_write (grub_usb_device_t dev,
+                    int endpoint, grub_size_t size, char *data)
+{
+  usb_dev_handle *devh;
+  struct usb_device *d = dev->data;
+
+  devh = usb_open (d);
+  if (usb_claim_interface (devh, 0) < 0)
+    goto fail;
+
+  if (usb_bulk_write (devh, endpoint, data, size, 20) < 0)
+    goto fail;
+
+  if (usb_release_interface (devh, 0) < 0)
+    goto fail;
+
+  usb_close (devh);
+
+  return GRUB_USB_ERR_NONE;
+
+ fail:
+  usb_close (devh);
+  return GRUB_USB_ERR_STALL;
+}
diff --git a/video/bitmap.c b/video/bitmap.c
new file mode 100644 (file)
index 0000000..8fda511
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ *  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/>.
+ */
+
+#include <grub/video.h>
+#include <grub/bitmap.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+
+/* List of bitmap readers registered to system.  */
+static grub_video_bitmap_reader_t bitmap_readers_list;
+
+/* Register bitmap reader.  */
+void
+grub_video_bitmap_reader_register (grub_video_bitmap_reader_t reader)
+{
+  reader->next = bitmap_readers_list;
+  bitmap_readers_list = reader;
+}
+
+/* Unregister bitmap reader.  */
+void
+grub_video_bitmap_reader_unregister (grub_video_bitmap_reader_t reader)
+{
+  grub_video_bitmap_reader_t *p, q;
+
+  for (p = &bitmap_readers_list, q = *p; q; p = &(q->next), q = q->next)
+    if (q == reader)
+      {
+        *p = q->next;
+        break;
+      }
+}
+
+/* Creates new bitmap, saves created bitmap on success to *bitmap.  */
+grub_err_t
+grub_video_bitmap_create (struct grub_video_bitmap **bitmap, 
+                          unsigned int width, unsigned int height,
+                          enum grub_video_blit_format blit_format)
+{
+  struct grub_video_mode_info *mode_info;
+  unsigned int size;
+
+  if (!bitmap)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument.");
+
+  *bitmap = 0;
+
+  if (width == 0 || height == 0)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument.");
+
+  *bitmap = (struct grub_video_bitmap *)grub_malloc (sizeof (struct grub_video_bitmap));
+  if (! *bitmap)
+    return grub_errno;
+
+  mode_info = &((*bitmap)->mode_info);
+
+  /* Populate mode_info.  */
+  mode_info->width = width;
+  mode_info->height = height;
+  mode_info->blit_format = blit_format;
+
+  switch (blit_format)
+    {
+      case GRUB_VIDEO_BLIT_FORMAT_RGBA_8888:
+        mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_RGB 
+                               | GRUB_VIDEO_MODE_TYPE_ALPHA;
+        mode_info->bpp = 32;
+        mode_info->bytes_per_pixel = 4;
+        mode_info->number_of_colors = 256;
+        mode_info->red_mask_size = 8;
+        mode_info->red_field_pos = 0;
+        mode_info->green_mask_size = 8;
+        mode_info->green_field_pos = 8;
+        mode_info->blue_mask_size = 8;
+        mode_info->blue_field_pos = 16;
+        mode_info->reserved_mask_size = 8;
+        mode_info->reserved_field_pos = 24;
+        break;
+
+      case GRUB_VIDEO_BLIT_FORMAT_RGB_888:
+        mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
+        mode_info->bpp = 24;
+        mode_info->bytes_per_pixel = 3;
+        mode_info->number_of_colors = 256;
+        mode_info->red_mask_size = 8;
+        mode_info->red_field_pos = 0;
+        mode_info->green_mask_size = 8;
+        mode_info->green_field_pos = 8;
+        mode_info->blue_mask_size = 8;
+        mode_info->blue_field_pos = 16;
+        mode_info->reserved_mask_size = 0;
+        mode_info->reserved_field_pos = 0;
+        break;
+
+      case GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR:
+        mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+        mode_info->bpp = 8;
+        mode_info->bytes_per_pixel = 1;
+        mode_info->number_of_colors = 256;
+        mode_info->red_mask_size = 0;
+        mode_info->red_field_pos = 0;
+        mode_info->green_mask_size = 0;
+        mode_info->green_field_pos = 0;
+        mode_info->blue_mask_size = 0;
+        mode_info->blue_field_pos = 0;
+        mode_info->reserved_mask_size = 0;
+        mode_info->reserved_field_pos = 0;
+        break;
+
+      default:
+        grub_free (*bitmap);
+        *bitmap = 0;
+
+        return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                           "Unsupported bitmap format");
+    }
+
+  mode_info->pitch = width * mode_info->bytes_per_pixel;
+
+  /* Calculate size needed for the data.  */
+  size = (width * mode_info->bytes_per_pixel) * height;
+
+  (*bitmap)->data = grub_malloc (size);  
+  if (! (*bitmap)->data)
+    {
+      grub_free (*bitmap);
+      *bitmap = 0;
+
+      return grub_errno;
+    }
+
+  /* Clear bitmap.  */
+  grub_memset ((*bitmap)->data, 0, size);
+
+  return GRUB_ERR_NONE;
+}
+
+/* Frees all resources allocated by bitmap.  */
+grub_err_t
+grub_video_bitmap_destroy (struct grub_video_bitmap *bitmap)
+{
+  if (! bitmap)
+    return GRUB_ERR_NONE;
+
+  grub_free (bitmap->data);
+  grub_free (bitmap);
+
+  return GRUB_ERR_NONE;
+}
+
+/* Match extension to filename.  */
+static int
+match_extension (const char *filename, const char *ext)
+{
+  int pos;
+  int ext_len;
+
+  pos = grub_strlen (filename);
+  ext_len = grub_strlen (ext);
+
+  if (! pos || ! ext_len || ext_len > pos)
+    return 0;
+
+  pos -= ext_len;
+
+  return grub_strcmp (filename + pos, ext) == 0;
+}
+
+/* Loads bitmap using registered bitmap readers.  */
+grub_err_t
+grub_video_bitmap_load (struct grub_video_bitmap **bitmap, 
+                        const char *filename)
+{
+  grub_video_bitmap_reader_t reader = bitmap_readers_list;
+
+  if (!bitmap)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument.");
+
+  *bitmap = 0;
+
+  while (reader)
+    {
+      if (match_extension (filename, reader->extension))
+        return reader->reader (bitmap, filename);
+
+      reader = reader->next;
+    }
+
+  return grub_error(GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format");
+}
+
+/* Return bitmap width.  */
+unsigned int
+grub_video_bitmap_get_width (struct grub_video_bitmap *bitmap)
+{
+  if (!bitmap)
+    return 0;
+
+  return bitmap->mode_info.width;
+}
+
+/* Return bitmap height.  */
+unsigned int
+grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap)
+{
+  if (!bitmap)
+    return 0;
+
+  return bitmap->mode_info.height;
+}
+
+/* Return mode info for bitmap.  */
+void grub_video_bitmap_get_mode_info (struct grub_video_bitmap *bitmap,
+                                      struct grub_video_mode_info *mode_info)
+{
+  if (!bitmap)
+    return;
+
+  *mode_info = bitmap->mode_info;
+}
+
+/* Return pointer to bitmap's raw data.  */
+void *grub_video_bitmap_get_data (struct grub_video_bitmap *bitmap)
+{
+  if (!bitmap)
+    return 0;
+
+  return bitmap->data;
+}
+
+/* Initialize bitmap module.  */
+GRUB_MOD_INIT(video_bitmap)
+{
+}
+
+/* Finalize bitmap module.  */
+GRUB_MOD_FINI(video_bitmap)
+{
+}
diff --git a/video/i386/pc/vbe.c b/video/i386/pc/vbe.c
new file mode 100644 (file)
index 0000000..23f7d46
--- /dev/null
@@ -0,0 +1,1635 @@
+/*
+ *  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/>.
+ */
+
+#include <grub/err.h>
+#include <grub/machine/memory.h>
+#include <grub/machine/vga.h>
+#include <grub/machine/vbe.h>
+#include <grub/machine/vbeblit.h>
+#include <grub/machine/vbefill.h>
+#include <grub/machine/vbeutil.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/video.h>
+#include <grub/bitmap.h>
+
+/* Specify "standard" VGA palette, some video cards may
+   need this and this will also be used when using RGB modes.  */
+static struct grub_vbe_palette_data vga_colors[16] =
+  {
+    // {B, G, R, A}
+    {0x00, 0x00, 0x00, 0x00}, // 0 = black
+    {0xA8, 0x00, 0x00, 0x00}, // 1 = blue
+    {0x00, 0xA8, 0x00, 0x00}, // 2 = green
+    {0xA8, 0xA8, 0x00, 0x00}, // 3 = cyan
+    {0x00, 0x00, 0xA8, 0x00}, // 4 = red
+    {0xA8, 0x00, 0xA8, 0x00}, // 5 = magenta
+    {0x00, 0x54, 0xA8, 0x00}, // 6 = brown
+    {0xA8, 0xA8, 0xA8, 0x00}, // 7 = ligth gray
+
+    {0x54, 0x54, 0x54, 0x00}, // 8 = dark gray
+    {0xFE, 0x54, 0x54, 0x00}, // 9 = bright blue
+    {0x54, 0xFE, 0x54, 0x00}, // 10 = bright green
+    {0xFE, 0xFE, 0x54, 0x00}, // 11 = bright cyan
+    {0x54, 0x54, 0xFE, 0x00}, // 12 = bright red
+    {0xFE, 0x54, 0xFE, 0x00}, // 13 = bright magenta
+    {0x54, 0xFE, 0xFE, 0x00}, // 14 = yellow
+    {0xFE, 0xFE, 0xFE, 0x00}  // 15 = white
+  };
+
+static int vbe_detected = -1;
+
+static struct grub_vbe_info_block controller_info;
+static struct grub_vbe_mode_info_block active_mode_info;
+
+static struct
+{
+  struct grub_video_render_target render_target;
+
+  unsigned int bytes_per_scan_line;
+  unsigned int bytes_per_pixel;
+  grub_uint32_t active_mode;
+  grub_uint8_t *ptr;
+  int index_color_mode;
+  struct grub_video_palette_data palette[256];
+} framebuffer;
+
+static struct grub_video_render_target *render_target;
+static grub_uint32_t initial_mode;
+static grub_uint32_t mode_in_use = 0x55aa;
+static grub_uint16_t *mode_list;
+
+static void *
+real2pm (grub_vbe_farptr_t ptr)
+{
+  return (void *) ((((unsigned long) ptr & 0xFFFF0000) >> 12UL)
+                   + ((unsigned long) ptr & 0x0000FFFF));
+}
+
+grub_err_t
+grub_vbe_probe (struct grub_vbe_info_block *info_block)
+{
+  struct grub_vbe_info_block *vbe_ib;
+  grub_vbe_status_t status;
+
+  /* Clear caller's controller info block.  */
+  if (info_block)
+    grub_memset (info_block, 0, sizeof (*info_block));
+
+  /* Do not probe more than one time, if not necessary.  */
+  if (vbe_detected == -1 || info_block)
+    {
+      /* Clear old copy of controller info block.  */
+      grub_memset (&controller_info, 0, sizeof (controller_info));
+
+      /* Mark VESA BIOS extension as undetected.  */
+      vbe_detected = 0;
+
+      /* Use low memory scratch area as temporary storage
+         for VESA BIOS call.  */
+      vbe_ib = (struct grub_vbe_info_block *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+
+      /* Prepare info block.  */
+      grub_memset (vbe_ib, 0, sizeof (*vbe_ib));
+
+      vbe_ib->signature[0] = 'V';
+      vbe_ib->signature[1] = 'B';
+      vbe_ib->signature[2] = 'E';
+      vbe_ib->signature[3] = '2';
+
+      /* Try to get controller info block.  */
+      status = grub_vbe_bios_get_controller_info (vbe_ib);
+      if (status == 0x004F)
+        {
+          /* Copy it for later usage.  */
+          grub_memcpy (&controller_info, vbe_ib, sizeof (controller_info));
+
+          /* Mark VESA BIOS extension as detected.  */
+          vbe_detected = 1;
+        }
+    }
+
+  if (! vbe_detected)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "VESA BIOS Extension not found");
+
+  /* Make copy of controller info block to caller.  */
+  if (info_block)
+    grub_memcpy (info_block, &controller_info, sizeof (*info_block));
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_vbe_set_video_mode (grub_uint32_t mode,
+                         struct grub_vbe_mode_info_block *mode_info)
+{
+  grub_vbe_status_t status;
+  grub_uint32_t old_mode;
+
+  /* Make sure that VBE is supported.  */
+  grub_vbe_probe (0);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* Try to get mode info.  */
+  grub_vbe_get_video_mode_info (mode, &active_mode_info);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* For all VESA BIOS modes, force linear frame buffer.  */
+  if (mode >= 0x100)
+    {
+      /* We only want linear frame buffer modes.  */
+      mode |= 1 << 14;
+
+      /* Determine frame buffer pixel format.  */
+      switch (active_mode_info.memory_model)
+        {
+        case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL:
+          framebuffer.index_color_mode = 1;
+          break;
+
+        case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR:
+          framebuffer.index_color_mode = 0;
+          break;
+
+        default:
+          return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                             "unsupported pixel format 0x%x",
+                             active_mode_info.memory_model);
+        }
+    }
+
+  /* Get current mode.  */
+  grub_vbe_get_video_mode (&old_mode);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* Try to set video mode.  */
+  status = grub_vbe_bios_set_mode (mode, 0);
+  if (status != GRUB_VBE_STATUS_OK)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "cannot set VBE mode %x", mode);
+
+  /* Save information for later usage.  */
+  framebuffer.active_mode = mode;
+
+  if (mode < 0x100)
+    {
+      /* If this is not a VESA mode, guess address.  */
+      framebuffer.ptr = (grub_uint8_t *) GRUB_MEMORY_MACHINE_VGA_ADDR;
+      framebuffer.index_color_mode = 1;
+    }
+  else
+    {
+      framebuffer.ptr = (grub_uint8_t *) active_mode_info.phys_base_addr;
+
+      if (controller_info.version >= 0x300)
+        framebuffer.bytes_per_scan_line = active_mode_info.lin_bytes_per_scan_line;
+      else
+        framebuffer.bytes_per_scan_line = active_mode_info.bytes_per_scan_line;
+    }
+
+  /* Check whether mode is text mode or graphics mode.  */
+  if (active_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_TEXT)
+    {
+      /* Text mode.  */
+
+      /* No special action needed for text mode as it is not supported for
+         graphical support.  */
+    }
+  else
+    {
+      /* Graphics mode.  */
+
+      /* Calculate bytes_per_pixel value.  */
+      switch(active_mode_info.bits_per_pixel)
+       {
+       case 32: framebuffer.bytes_per_pixel = 4; break;
+       case 24: framebuffer.bytes_per_pixel = 3; break;
+       case 16: framebuffer.bytes_per_pixel = 2; break;
+       case 15: framebuffer.bytes_per_pixel = 2; break;
+       case 8: framebuffer.bytes_per_pixel = 1; break;
+       default:
+         grub_vbe_bios_set_mode (old_mode, 0);
+         return grub_error (GRUB_ERR_BAD_DEVICE,
+                            "cannot set VBE mode %x",
+                            mode);
+         break;
+       }
+
+      /* If video mode is in indexed color, setup default VGA palette.  */
+      if (framebuffer.index_color_mode)
+       {
+         struct grub_vbe_palette_data *palette
+           = (struct grub_vbe_palette_data *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+
+         /* Make sure that the BIOS can reach the palette.  */
+         grub_memcpy (palette, vga_colors, sizeof (vga_colors));
+         status = grub_vbe_bios_set_palette_data (sizeof (vga_colors)
+                                                  / sizeof (struct grub_vbe_palette_data),
+                                                  0,
+                                                  palette);
+
+         /* Just ignore the status.  */
+       }
+    }
+
+  /* Copy mode info for caller.  */
+  if (mode_info)
+    grub_memcpy (mode_info, &active_mode_info, sizeof (*mode_info));
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_vbe_get_video_mode (grub_uint32_t *mode)
+{
+  grub_vbe_status_t status;
+
+  /* Make sure that VBE is supported.  */
+  grub_vbe_probe (0);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* Try to query current mode from VESA BIOS.  */
+  status = grub_vbe_bios_get_mode (mode);
+  if (status != GRUB_VBE_STATUS_OK)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "cannot get current VBE mode");
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_vbe_get_video_mode_info (grub_uint32_t mode,
+                              struct grub_vbe_mode_info_block *mode_info)
+{
+  struct grub_vbe_mode_info_block *mi_tmp
+    = (struct grub_vbe_mode_info_block *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+  grub_vbe_status_t status;
+
+  /* Make sure that VBE is supported.  */
+  grub_vbe_probe (0);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* If mode is not VESA mode, skip mode info query.  */
+  if (mode >= 0x100)
+    {
+      /* Try to get mode info from VESA BIOS.  */
+      status = grub_vbe_bios_get_mode_info (mode, mi_tmp);
+      if (status != GRUB_VBE_STATUS_OK)
+        return grub_error (GRUB_ERR_BAD_DEVICE,
+                           "cannot get information on the mode %x", mode);
+
+      /* Make copy of mode info block.  */
+      grub_memcpy (mode_info, mi_tmp, sizeof (*mode_info));
+    }
+  else
+    /* Just clear mode info block if it isn't a VESA mode.  */
+    grub_memset (mode_info, 0, sizeof (*mode_info));
+
+  return GRUB_ERR_NONE;
+}
+
+grub_uint8_t *
+grub_video_vbe_get_video_ptr (struct grub_video_i386_vbeblit_info *source,
+                              grub_uint32_t x, grub_uint32_t y)
+{
+  grub_uint8_t *ptr = 0;
+
+  switch (source->mode_info->bpp)
+    {
+    case 32:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info->pitch
+            + x * 4;
+      break;
+
+    case 24:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info->pitch
+            + x * 3;
+      break;
+
+    case 16:
+    case 15:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info->pitch
+            + x * 2;
+      break;
+
+    case 8:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info->pitch
+            + x;
+      break;
+    }
+
+  return ptr;
+}
+
+static grub_err_t
+grub_video_vbe_init (void)
+{
+  grub_uint16_t *rm_mode_list;
+  grub_uint16_t *p;
+  grub_size_t mode_list_size;
+  struct grub_vbe_info_block info_block;
+
+  /* Check if there is adapter present.
+
+     Firmware note: There has been a report that some cards store video mode
+     list in temporary memory.  So we must first use vbe probe to get
+     refreshed information to receive valid pointers and data, and then
+     copy this information to somewhere safe.  */
+  grub_vbe_probe (&info_block);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
+  /* Copy modelist to local memory.  */
+  p = rm_mode_list = real2pm (info_block.video_mode_ptr);
+  while(*p++ != 0xFFFF)
+    ;
+
+  mode_list_size = (grub_addr_t) p - (grub_addr_t) rm_mode_list;
+  mode_list = grub_malloc (mode_list_size);
+  if (! mode_list)
+    return grub_errno;
+  grub_memcpy (mode_list, rm_mode_list, mode_list_size);
+
+  /* Adapter could be found, figure out initial video mode.  */
+  grub_vbe_get_video_mode (&initial_mode);
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      /* Free allocated resources.  */
+      grub_free (mode_list);
+      mode_list = 0;
+
+      return grub_errno;
+    }
+
+  /* Reset frame buffer and render target variables.  */
+  grub_memset (&framebuffer, 0, sizeof(framebuffer));
+  render_target = &framebuffer.render_target;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_fini (void)
+{
+  grub_vbe_status_t status;
+
+  /* Restore old video mode.  */
+  status = grub_vbe_bios_set_mode (initial_mode, 0);
+  if (status != GRUB_VBE_STATUS_OK)
+    /* TODO: Decide, is this something we want to do.  */
+    return grub_errno;
+
+  /* TODO: Free any resources allocated by driver.  */
+  grub_free (mode_list);
+  mode_list = 0;
+
+  /* TODO: destroy render targets.  */
+
+  /* Return success to caller.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_setup (unsigned int width, unsigned int height,
+                      unsigned int mode_type)
+{
+  grub_uint16_t *p;
+  struct grub_vbe_mode_info_block mode_info;
+  struct grub_vbe_mode_info_block best_mode_info;
+  grub_uint32_t best_mode = 0;
+  int depth;
+  unsigned int i;
+
+  /* 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;
+
+  /* Walk thru mode list and try to find matching mode.  */
+  for (p = mode_list; *p != 0xFFFF; p++)
+    {
+      grub_uint32_t mode = *p;
+
+      grub_vbe_get_video_mode_info (mode, &mode_info);
+      if (grub_errno != GRUB_ERR_NONE)
+        {
+          /* Could not retrieve mode info, retreat.  */
+          grub_errno = GRUB_ERR_NONE;
+          break;
+        }
+
+      if ((mode_info.mode_attributes & 0x001) == 0)
+        /* If not available, skip it.  */
+        continue;
+
+      if ((mode_info.mode_attributes & 0x002) == 0)
+        /* Not enough information.  */
+        continue;
+
+      if ((mode_info.mode_attributes & 0x008) == 0)
+        /* Monochrome is unusable.  */
+        continue;
+
+      if ((mode_info.mode_attributes & 0x080) == 0)
+        /* We support only linear frame buffer modes.  */
+        continue;
+
+      if ((mode_info.mode_attributes & 0x010) == 0)
+        /* We allow only graphical modes.  */
+        continue;
+
+      if ((mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL)
+          && (mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
+        /* Not compatible memory model.  */
+        continue;
+
+      if ((mode_info.x_resolution != width)
+          || (mode_info.y_resolution != height))
+        /* Non matching resolution.  */
+        continue;
+
+      /* Check if user requested RGB or index color mode.  */
+      if ((mode_type & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0)
+        {
+          if (((mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+              && (mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL))
+            /* Requested only index color modes.  */
+            continue;
+
+          if (((mode_type & GRUB_VIDEO_MODE_TYPE_RGB) != 0)
+              && (mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
+            /* Requested only RGB modes.  */
+            continue;
+        }
+
+      /* If there is a request for specific depth, ignore others.  */
+      if ((depth != 0) && (mode_info.bits_per_pixel != depth))
+        continue;
+
+      /* Select mode with most number of bits per pixel.  */
+      if (best_mode != 0)
+        if (mode_info.bits_per_pixel < best_mode_info.bits_per_pixel)
+          continue;
+
+      /* Save so far best mode information for later use.  */
+      best_mode = mode;
+      grub_memcpy (&best_mode_info, &mode_info, sizeof (mode_info));
+    }
+
+  /* Try to initialize best mode found.  */
+  if (best_mode != 0)
+    {
+      /* If this fails, then we have mode selection heuristics problem,
+         or adapter failure.  */
+      grub_vbe_set_video_mode (best_mode, &active_mode_info);
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;
+
+      /* Now we are happily in requested video mode.  Cache some info
+         in order to fasten later operations.  */
+      mode_in_use = best_mode;
+
+      /* Reset render target to framebuffer one.  */
+      render_target = &framebuffer.render_target;
+
+      /* Fill mode info details in framebuffer's render target.  */
+      render_target->mode_info.width = active_mode_info.x_resolution;
+      render_target->mode_info.height = active_mode_info.y_resolution;
+
+      if (framebuffer.index_color_mode)
+        render_target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+      else
+        render_target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
+
+      render_target->mode_info.bpp = active_mode_info.bits_per_pixel;
+      render_target->mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel;
+      render_target->mode_info.pitch = framebuffer.bytes_per_scan_line;
+      render_target->mode_info.number_of_colors = 256; /* TODO: fix me.  */
+      render_target->mode_info.red_mask_size = active_mode_info.red_mask_size;
+      render_target->mode_info.red_field_pos = active_mode_info.red_field_position;
+      render_target->mode_info.green_mask_size = active_mode_info.green_mask_size;
+      render_target->mode_info.green_field_pos = active_mode_info.green_field_position;
+      render_target->mode_info.blue_mask_size = active_mode_info.blue_mask_size;
+      render_target->mode_info.blue_field_pos = active_mode_info.blue_field_position;
+      render_target->mode_info.reserved_mask_size = active_mode_info.rsvd_mask_size;
+      render_target->mode_info.reserved_field_pos = active_mode_info.rsvd_field_position;
+
+      render_target->mode_info.blit_format = grub_video_get_blit_format (&render_target->mode_info);
+
+      /* Reset viewport to match new mode.  */
+      render_target->viewport.x = 0;
+      render_target->viewport.y = 0;
+      render_target->viewport.width = active_mode_info.x_resolution;
+      render_target->viewport.height = active_mode_info.y_resolution;
+
+      /* Set framebuffer pointer and mark it as non allocated.  */
+      render_target->is_allocated = 0;
+      render_target->data = framebuffer.ptr;
+
+      /* Copy default palette to initialize emulated palette.  */
+      for (i = 0;
+           i < (sizeof (vga_colors)
+                / sizeof (struct grub_vbe_palette_data));
+           i++)
+        {
+          framebuffer.palette[i].r = vga_colors[i].red;
+          framebuffer.palette[i].g = vga_colors[i].green;
+          framebuffer.palette[i].b = vga_colors[i].blue;
+          framebuffer.palette[i].a = 0xFF;
+        }
+
+      return GRUB_ERR_NONE;
+    }
+
+  /* Couldn't found matching mode.  */
+  return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found.");
+}
+
+static grub_err_t
+grub_video_vbe_get_info (struct grub_video_mode_info *mode_info)
+{
+  /* Copy mode info from active render target.  */
+  grub_memcpy (mode_info, &render_target->mode_info,
+               sizeof (struct grub_video_mode_info));
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_palette (unsigned int start, unsigned int count,
+                            struct grub_video_palette_data *palette_data)
+{
+  unsigned int i;
+
+  if (framebuffer.index_color_mode)
+    {
+      /* TODO: Implement setting indexed color mode palette to hardware.  */
+      //status = grub_vbe_bios_set_palette_data (sizeof (vga_colors)
+      //                                         / sizeof (struct grub_vbe_palette_data),
+      //                                         0,
+      //                                         palette);
+
+    }
+
+  /* Then set color to emulated palette.  */
+  for (i = 0; (i < count) && ((i + start) < 256); i++)
+    framebuffer.palette[start + i] = palette_data[i];
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_get_palette (unsigned int start, unsigned int count,
+                            struct grub_video_palette_data *palette_data)
+{
+  unsigned int i;
+
+  /* Assume that we know everything from index color palette.  */
+  for (i = 0; (i < count) && ((i + start) < 256); i++)
+    palette_data[i] = framebuffer.palette[start + i];
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_viewport (unsigned int x, unsigned int y,
+                             unsigned int width, unsigned int height)
+{
+  /* Make sure viewport is withing screen dimensions.  If viewport was set
+     to be out of the region, mark its size as zero.  */
+  if (x > active_mode_info.x_resolution)
+    {
+      x = 0;
+      width = 0;
+    }
+
+  if (y > active_mode_info.y_resolution)
+    {
+      y = 0;
+      height = 0;
+    }
+
+  if (x + width > active_mode_info.x_resolution)
+    width = active_mode_info.x_resolution - x;
+
+  if (y + height > active_mode_info.y_resolution)
+    height = active_mode_info.y_resolution - y;
+
+  render_target->viewport.x = x;
+  render_target->viewport.y = y;
+  render_target->viewport.width = width;
+  render_target->viewport.height = height;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_get_viewport (unsigned int *x, unsigned int *y,
+                             unsigned int *width, unsigned int *height)
+{
+  if (x) *x = render_target->viewport.x;
+  if (y) *y = render_target->viewport.y;
+  if (width) *width = render_target->viewport.width;
+  if (height) *height = render_target->viewport.height;
+
+  return GRUB_ERR_NONE;
+}
+
+/* Maps color name to target optimized color format.  */
+static grub_video_color_t
+grub_video_vbe_map_color (grub_uint32_t color_name)
+{
+  /* TODO: implement color theme mapping code.  */
+
+  if (color_name < 256)
+    {
+      if ((render_target->mode_info.mode_type
+           & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+        return color_name;
+      else
+        {
+          grub_video_color_t color;
+
+          color = grub_video_vbe_map_rgb (framebuffer.palette[color_name].r,
+                                          framebuffer.palette[color_name].g,
+                                          framebuffer.palette[color_name].b);
+
+          return color;
+        }
+    }
+
+  return 0;
+}
+
+/* Maps RGB to target optimized color format.  */
+grub_video_color_t
+grub_video_vbe_map_rgb (grub_uint8_t red, grub_uint8_t green,
+                        grub_uint8_t blue)
+{
+  if ((render_target->mode_info.mode_type
+       & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+    {
+      int minindex = 0;
+      int delta = 0;
+      int tmp;
+      int val;
+      int i;
+
+      /* Find best matching color.  */
+      for (i = 0; i < 256; i++)
+        {
+          val = framebuffer.palette[i].r - red;
+          tmp = val * val;
+          val = framebuffer.palette[i].g - green;
+          tmp += val * val;
+          val = framebuffer.palette[i].b - blue;
+          tmp += val * val;
+
+          if (i == 0)
+            delta = tmp;
+
+          if (tmp < delta)
+            {
+              delta = tmp;
+              minindex = i;
+              if (tmp == 0)
+                break;
+            }
+        }
+
+      return minindex;
+    }
+  else if ((render_target->mode_info.mode_type
+            & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
+    {
+       if (red == render_target->mode_info.fg_red
+           && green == render_target->mode_info.fg_green
+           && blue == render_target->mode_info.fg_blue)
+         return 1;
+       else
+         return 0;
+    }
+  else
+    {
+      grub_uint32_t value;
+      grub_uint8_t alpha = 255; /* Opaque color.  */
+
+      red >>= 8 - render_target->mode_info.red_mask_size;
+      green >>= 8 - render_target->mode_info.green_mask_size;
+      blue >>= 8 - render_target->mode_info.blue_mask_size;
+      alpha >>= 8 - render_target->mode_info.reserved_mask_size;
+
+      value = red << render_target->mode_info.red_field_pos;
+      value |= green << render_target->mode_info.green_field_pos;
+      value |= blue << render_target->mode_info.blue_field_pos;
+      value |= alpha << render_target->mode_info.reserved_field_pos;
+
+      return value;
+    }
+
+}
+
+/* Maps RGBA to target optimized color format.  */
+grub_video_color_t
+grub_video_vbe_map_rgba (grub_uint8_t red, grub_uint8_t green,
+                         grub_uint8_t blue, grub_uint8_t alpha)
+{
+  if ((render_target->mode_info.mode_type
+       & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+    /* No alpha available in index color modes, just use
+       same value as in only RGB modes.  */
+    return grub_video_vbe_map_rgb (red, green, blue);
+  else if ((render_target->mode_info.mode_type
+            & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
+    {
+      if (red == render_target->mode_info.fg_red
+          && green == render_target->mode_info.fg_green
+          && blue == render_target->mode_info.fg_blue
+          && alpha == render_target->mode_info.fg_alpha)
+        return 1;
+      else
+        return 0;
+    }
+  else
+    {
+      grub_uint32_t value;
+
+      red >>= 8 - render_target->mode_info.red_mask_size;
+      green >>= 8 - render_target->mode_info.green_mask_size;
+      blue >>= 8 - render_target->mode_info.blue_mask_size;
+      alpha >>= 8 - render_target->mode_info.reserved_mask_size;
+
+      value = red << render_target->mode_info.red_field_pos;
+      value |= green << render_target->mode_info.green_field_pos;
+      value |= blue << render_target->mode_info.blue_field_pos;
+      value |= alpha << render_target->mode_info.reserved_field_pos;
+
+      return value;
+    }
+}
+
+/* Splits target optimized format to components.  */
+grub_err_t grub_video_vbe_unmap_color (grub_video_color_t color,
+                                       grub_uint8_t *red, grub_uint8_t *green,
+                                       grub_uint8_t *blue, grub_uint8_t *alpha)
+{
+  struct grub_video_i386_vbeblit_info target_info;
+
+  target_info.mode_info = &render_target->mode_info;
+  target_info.data = render_target->data;
+
+  grub_video_vbe_unmap_color_int (&target_info, color, red, green, blue, alpha);
+
+  return GRUB_ERR_NONE;
+}
+
+/* Splits color in source format to components.  */
+void
+grub_video_vbe_unmap_color_int (struct grub_video_i386_vbeblit_info * source,
+                                grub_video_color_t color,
+                                grub_uint8_t *red, grub_uint8_t *green,
+                                grub_uint8_t *blue, grub_uint8_t *alpha)
+{
+  struct grub_video_mode_info *mode_info;
+  mode_info = source->mode_info;
+
+  if ((mode_info->mode_type
+       & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
+    {
+      /* If we have an out-of-bounds color, return transparent black.  */
+      if (color > 255)
+        {
+          *red = 0;
+          *green = 0;
+          *blue = 0;
+          *alpha = 0;
+          return;
+        }
+
+      *red = framebuffer.palette[color].r;
+      *green = framebuffer.palette[color].g;
+      *blue = framebuffer.palette[color].b;
+      *alpha = framebuffer.palette[color].a;
+      return;
+    }
+  else if ((mode_info->mode_type
+            & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
+    {
+      if (color & 1)
+        {
+          *red = mode_info->fg_red;
+          *green = mode_info->fg_green;
+          *blue = mode_info->fg_blue;
+          *alpha = mode_info->fg_alpha;
+        }
+      else
+        {
+          *red = mode_info->bg_red;
+          *green = mode_info->bg_green;
+          *blue = mode_info->bg_blue;
+          *alpha = mode_info->bg_alpha;
+        }
+    }
+  else
+    {
+      grub_uint32_t tmp;
+
+      /* Get red component.  */
+      tmp = color >> mode_info->red_field_pos;
+      tmp &= (1 << mode_info->red_mask_size) - 1;
+      tmp <<= 8 - mode_info->red_mask_size;
+      tmp |= (1 << (8 - mode_info->red_mask_size)) - 1;
+      *red = tmp & 0xFF;
+
+      /* Get green component.  */
+      tmp = color >> mode_info->green_field_pos;
+      tmp &= (1 << mode_info->green_mask_size) - 1;
+      tmp <<= 8 - mode_info->green_mask_size;
+      tmp |= (1 << (8 - mode_info->green_mask_size)) - 1;
+      *green = tmp & 0xFF;
+
+      /* Get blue component.  */
+      tmp = color >> mode_info->blue_field_pos;
+      tmp &= (1 << mode_info->blue_mask_size) - 1;
+      tmp <<= 8 - mode_info->blue_mask_size;
+      tmp |= (1 << (8 - mode_info->blue_mask_size)) - 1;
+      *blue = tmp & 0xFF;
+
+      /* Get alpha component.  */
+      if (source->mode_info->reserved_mask_size > 0)
+        {
+          tmp = color >> mode_info->reserved_field_pos;
+          tmp &= (1 << mode_info->reserved_mask_size) - 1;
+          tmp <<= 8 - mode_info->reserved_mask_size;
+          tmp |= (1 << (8 - mode_info->reserved_mask_size)) - 1;
+        }
+      else
+        /* If there is no alpha component, assume it opaque.  */
+        tmp = 255;
+
+      *alpha = tmp & 0xFF;
+    }
+}
+
+static grub_err_t
+grub_video_vbe_fill_rect (grub_video_color_t color, int x, int y,
+                          unsigned int width, unsigned int height)
+{
+  struct grub_video_i386_vbeblit_info target;
+
+  /* Make sure there is something to do.  */
+  if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0))
+    return GRUB_ERR_NONE;
+  if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
+    return GRUB_ERR_NONE;
+
+  /* Do not allow drawing out of viewport.  */
+  if (x < 0)
+    {
+      width += x;
+      x = 0;
+    }
+  if (y < 0)
+    {
+      height += y;
+      y = 0;
+    }
+
+  if ((x + width) > render_target->viewport.width)
+    width = render_target->viewport.width - x;
+  if ((y + height) > render_target->viewport.height)
+    height = render_target->viewport.height - y;
+
+  /* Add viewport offset.  */
+  x += render_target->viewport.x;
+  y += render_target->viewport.y;
+
+  /* Use vbeblit_info to encapsulate rendering.  */
+  target.mode_info = &render_target->mode_info;
+  target.data = render_target->data;
+
+  /* Try to figure out more optimized version.  Note that color is already
+     mapped to target format so we can make assumptions based on that.  */
+  if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
+    {
+      grub_video_i386_vbefill_direct32 (&target, color, x, y,
+                                        width, height);
+      return GRUB_ERR_NONE;
+    }
+  else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
+    {
+      grub_video_i386_vbefill_direct32 (&target, color, x, y,
+                                        width, height);
+      return GRUB_ERR_NONE;
+    }
+  else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+    {
+      grub_video_i386_vbefill_direct24 (&target, color, x, y,
+                                        width, height);
+      return GRUB_ERR_NONE;
+    }
+  else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_565)
+    {
+      grub_video_i386_vbefill_direct16 (&target, color, x, y,
+                                        width, height);
+      return GRUB_ERR_NONE;
+    }
+  else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_565)
+    {
+      grub_video_i386_vbefill_direct16 (&target, color, x, y,
+                                        width, height);
+      return GRUB_ERR_NONE;
+    }
+  else if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+    {
+      grub_video_i386_vbefill_direct8 (&target, color, x, y,
+                                      width, height);
+      return GRUB_ERR_NONE;
+    }
+
+  /* No optimized version found, use default (slow) filler.  */
+  grub_video_i386_vbefill (&target, color, x, y, width, height);
+
+  return GRUB_ERR_NONE;
+}
+
+/* NOTE: This function assumes that given coordinates are within bounds of
+   handled data.  */
+static void
+common_blitter (struct grub_video_i386_vbeblit_info *target,
+                struct grub_video_i386_vbeblit_info *source,
+                enum grub_video_blit_operators oper, int x, int y,
+                unsigned int width, unsigned int height,
+                int offset_x, int offset_y)
+{
+  if (oper == GRUB_VIDEO_BLIT_REPLACE)
+    {
+      /* Try to figure out more optimized version for replace operator.  */
+      if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
+       {
+         if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
+           {
+             grub_video_i386_vbeblit_replace_directN (target, source,
+                                                      x, y, width, height,
+                                                      offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
+           {
+             grub_video_i386_vbeblit_replace_BGRX8888_RGBX8888 (target, source,
+                                                                x, y, width, height,
+                                                                offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888)
+           {
+             grub_video_i386_vbeblit_replace_BGR888_RGBX8888 (target, source,
+                                                              x, y, width, height,
+                                                              offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+           {
+             grub_video_i386_vbeblit_replace_RGB888_RGBX8888 (target, source,
+                                                              x, y, width, height,
+                                                              offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+           {
+             grub_video_i386_vbeblit_replace_index_RGBX8888 (target, source,
+                                                             x, y, width, height,
+                                                             offset_x, offset_y);
+             return;
+           }
+       }
+      else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+       {
+         if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
+           {
+             grub_video_i386_vbeblit_replace_BGRX8888_RGB888 (target, source,
+                                                              x, y, width, height,
+                                                              offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
+           {
+             grub_video_i386_vbeblit_replace_RGBX8888_RGB888 (target, source,
+                                                              x, y, width, height,
+                                                              offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888)
+           {
+             grub_video_i386_vbeblit_replace_BGR888_RGB888 (target, source,
+                                                            x, y, width, height,
+                                                            offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+           {
+             grub_video_i386_vbeblit_replace_directN (target, source,
+                                                      x, y, width, height,
+                                                      offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+           {
+             grub_video_i386_vbeblit_replace_index_RGB888 (target, source,
+                                                           x, y, width, height,
+                                                           offset_x, offset_y);
+             return;
+           }
+       }
+      else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
+       {
+         if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
+           {
+             grub_video_i386_vbeblit_replace_directN (target, source,
+                                                      x, y, width, height,
+                                                      offset_x, offset_y);
+             return;
+           }
+       }
+      else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+       {
+         if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+           {
+             grub_video_i386_vbeblit_replace_directN (target, source,
+                                                      x, y, width, height,
+                                                      offset_x, offset_y);
+             return;
+           }
+       }
+
+      /* No optimized replace operator found, use default (slow) blitter.  */
+      grub_video_i386_vbeblit_replace (target, source, x, y, width, height,
+                                      offset_x, offset_y);
+    }
+  else
+    {
+      /* Try to figure out more optimized blend operator.  */
+      if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
+       {
+         if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
+           {
+             grub_video_i386_vbeblit_blend_BGRA8888_RGBA8888 (target, source,
+                                                              x, y, width, height,
+                                                              offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
+           {
+             grub_video_i386_vbeblit_blend_RGBA8888_RGBA8888 (target, source,
+                                                              x, y, width, height,
+                                                              offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888)
+           {
+             grub_video_i386_vbeblit_blend_BGR888_RGBA8888 (target, source,
+                                                            x, y, width, height,
+                                                            offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+           {
+             grub_video_i386_vbeblit_blend_RGB888_RGBA8888 (target, source,
+                                                            x, y, width, height,
+                                                            offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+           {
+             grub_video_i386_vbeblit_blend_index_RGBA8888 (target, source,
+                                                           x, y, width, height,
+                                                           offset_x, offset_y);
+             return;
+           }
+       }
+      else if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+       {
+         /* Note: There is really no alpha information here, so blend is
+            changed to replace.  */
+
+         if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
+           {
+             grub_video_i386_vbeblit_replace_BGRX8888_RGB888 (target, source,
+                                                              x, y, width, height,
+                                                              offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
+           {
+             grub_video_i386_vbeblit_replace_RGBX8888_RGB888 (target, source,
+                                                              x, y, width, height,
+                                                              offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888)
+           {
+             grub_video_i386_vbeblit_replace_BGR888_RGB888 (target, source,
+                                                            x, y, width, height,
+                                                            offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGB_888)
+           {
+             grub_video_i386_vbeblit_replace_directN (target, source,
+                                                      x, y, width, height,
+                                                      offset_x, offset_y);
+             return;
+           }
+         else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR)
+           {
+             grub_video_i386_vbeblit_replace_index_RGB888 (target, source,
+                                                           x, y, width, height,
+                                                           offset_x, offset_y);
+             return;
+           }
+       }
+
+      /* No optimized blend operation found, use default (slow) blitter.  */
+      grub_video_i386_vbeblit_blend (target, source, x, y, width, height,
+                                    offset_x, offset_y);
+    }
+}
+
+static grub_err_t
+grub_video_vbe_blit_bitmap (struct grub_video_bitmap *bitmap,
+                            enum grub_video_blit_operators oper, int x, int y,
+                            int offset_x, int offset_y,
+                            unsigned int width, unsigned int height)
+{
+  struct grub_video_i386_vbeblit_info source;
+  struct grub_video_i386_vbeblit_info target;
+
+  /* Make sure there is something to do.  */
+  if ((width == 0) || (height == 0))
+    return GRUB_ERR_NONE;
+  if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0))
+    return GRUB_ERR_NONE;
+  if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
+    return GRUB_ERR_NONE;
+  if ((x + (int)bitmap->mode_info.width) < 0)
+    return GRUB_ERR_NONE;
+  if ((y + (int)bitmap->mode_info.height) < 0)
+    return GRUB_ERR_NONE;
+  if ((offset_x >= (int)bitmap->mode_info.width)
+      || (offset_x + (int)width < 0))
+    return GRUB_ERR_NONE;
+  if ((offset_y >= (int)bitmap->mode_info.height)
+      || (offset_y + (int)height < 0))
+    return GRUB_ERR_NONE;
+
+  /* If we have negative coordinates, optimize drawing to minimum.  */
+  if (offset_x < 0)
+    {
+      width += offset_x;
+      x -= offset_x;
+      offset_x = 0;
+    }
+
+  if (offset_y < 0)
+    {
+      height += offset_y;
+      y -= offset_y;
+      offset_y = 0;
+    }
+
+  if (x < 0)
+    {
+      width += x;
+      offset_x -= x;
+      x = 0;
+    }
+
+  if (y < 0)
+    {
+      height += y;
+      offset_y -= y;
+      y = 0;
+    }
+
+  /* Do not allow drawing out of viewport.  */
+  if ((x + width) > render_target->viewport.width)
+    width = render_target->viewport.width - x;
+  if ((y + height) > render_target->viewport.height)
+    height = render_target->viewport.height - y;
+
+  if ((offset_x + width) > bitmap->mode_info.width)
+    width = bitmap->mode_info.width - offset_x;
+  if ((offset_y + height) > bitmap->mode_info.height)
+    height = bitmap->mode_info.height - offset_y;
+
+  /* Limit drawing to source render target dimensions.  */
+  if (width > bitmap->mode_info.width)
+    width = bitmap->mode_info.width;
+
+  if (height > bitmap->mode_info.height)
+    height = bitmap->mode_info.height;
+
+  /* Add viewport offset.  */
+  x += render_target->viewport.x;
+  y += render_target->viewport.y;
+
+  /* Use vbeblit_info to encapsulate rendering.  */
+  source.mode_info = &bitmap->mode_info;
+  source.data = bitmap->data;
+  target.mode_info = &render_target->mode_info;
+  target.data = render_target->data;
+
+  /* Do actual blitting.  */
+  common_blitter (&target, &source, oper, x, y, width, height,
+                  offset_x, offset_y);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_blit_render_target (struct grub_video_render_target *source,
+                                   enum grub_video_blit_operators oper,
+                                   int x, int y, int offset_x, int offset_y,
+                                   unsigned int width, unsigned int height)
+{
+  struct grub_video_i386_vbeblit_info source_info;
+  struct grub_video_i386_vbeblit_info target_info;
+
+  /* Make sure there is something to do.  */
+  if ((width == 0) || (height == 0))
+    return GRUB_ERR_NONE;
+  if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0))
+    return GRUB_ERR_NONE;
+  if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
+    return GRUB_ERR_NONE;
+  if ((x + (int)source->mode_info.width) < 0)
+    return GRUB_ERR_NONE;
+  if ((y + (int)source->mode_info.height) < 0)
+    return GRUB_ERR_NONE;
+  if ((offset_x >= (int)source->mode_info.width)
+      || (offset_x + (int)width < 0))
+    return GRUB_ERR_NONE;
+  if ((offset_y >= (int)source->mode_info.height)
+      || (offset_y + (int)height < 0))
+    return GRUB_ERR_NONE;
+
+  /* If we have negative coordinates, optimize drawing to minimum.  */
+  if (offset_x < 0)
+    {
+      width += offset_x;
+      x -= offset_x;
+      offset_x = 0;
+    }
+
+  if (offset_y < 0)
+    {
+      height += offset_y;
+      y -= offset_y;
+      offset_y = 0;
+    }
+
+  if (x < 0)
+    {
+      width += x;
+      offset_x -= x;
+      x = 0;
+    }
+
+  if (y < 0)
+    {
+      height += y;
+      offset_y -= y;
+      y = 0;
+    }
+
+  /* Do not allow drawing out of viewport.  */
+  if ((x + width) > render_target->viewport.width)
+    width = render_target->viewport.width - x;
+  if ((y + height) > render_target->viewport.height)
+    height = render_target->viewport.height - y;
+
+  if ((offset_x + width) > source->mode_info.width)
+    width = source->mode_info.width - offset_x;
+  if ((offset_y + height) > source->mode_info.height)
+    height = source->mode_info.height - offset_y;
+
+  /* Limit drawing to source render target dimensions.  */
+  if (width > source->mode_info.width)
+    width = source->mode_info.width;
+
+  if (height > source->mode_info.height)
+    height = source->mode_info.height;
+
+  /* Add viewport offset.  */
+  x += render_target->viewport.x;
+  y += render_target->viewport.y;
+
+  /* Use vbeblit_info to encapsulate rendering.  */
+  source_info.mode_info = &source->mode_info;
+  source_info.data = source->data;
+  target_info.mode_info = &render_target->mode_info;
+  target_info.data = render_target->data;
+
+  /* Do actual blitting.  */
+  common_blitter (&target_info, &source_info, oper, x, y, width, height,
+                  offset_x, offset_y);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_scroll (grub_video_color_t color, int dx, int dy)
+{
+  int width;
+  int height;
+  int src_x;
+  int src_y;
+  int dst_x;
+  int dst_y;
+
+  /* 1. Check if we have something to do.  */
+  if ((dx == 0) && (dy == 0))
+    return GRUB_ERR_NONE;
+
+  width = render_target->viewport.width - grub_abs (dx);
+  height = render_target->viewport.height - grub_abs (dy);
+
+  if (dx < 0)
+    {
+      src_x = render_target->viewport.x - dx;
+      dst_x = render_target->viewport.x;
+    }
+  else
+    {
+      src_x = render_target->viewport.x;
+      dst_x = render_target->viewport.x + dx;
+    }
+
+  if (dy < 0)
+    {
+      src_y = render_target->viewport.y - dy;
+      dst_y = render_target->viewport.y;
+    }
+  else
+    {
+      src_y = render_target->viewport.y;
+      dst_y = render_target->viewport.y + dy;
+    }
+
+  /* 2. Check if there is need to copy data.  */
+  if ((grub_abs (dx) < render_target->viewport.width)
+       && (grub_abs (dy) < render_target->viewport.height))
+    {
+      /* 3. Move data in render target.  */
+      struct grub_video_i386_vbeblit_info target;
+      grub_uint8_t *src;
+      grub_uint8_t *dst;
+      int j;
+
+      target.mode_info = &render_target->mode_info;
+      target.data = render_target->data;
+
+      /* Check vertical direction of the move.  */
+      if (dy <= 0)
+       /* 3a. Move data upwards.  */
+       for (j = 0; j < height; j++)
+         {
+           dst = grub_video_vbe_get_video_ptr (&target, dst_x, dst_y + j);
+           src = grub_video_vbe_get_video_ptr (&target, src_x, src_y + j);
+           grub_memmove (dst, src,
+                         width * target.mode_info->bytes_per_pixel);
+         }
+      else
+       /* 3b. Move data downwards.  */
+       for (j = (height - 1); j >= 0; j--)
+         {
+           dst = grub_video_vbe_get_video_ptr (&target, dst_x, dst_y + j);
+           src = grub_video_vbe_get_video_ptr (&target, src_x, src_y + j);
+           grub_memmove (dst, src,
+                         width * target.mode_info->bytes_per_pixel);
+         }
+    }
+
+  /* 4. Fill empty space with specified color.  In this implementation
+     there might be colliding areas but at the moment there is no need
+     to optimize this.  */
+
+  /* 4a. Fill top & bottom parts.  */
+  if (dy > 0)
+    grub_video_vbe_fill_rect (color, 0, 0, render_target->viewport.width, dy);
+  else if (dy < 0)
+    {
+      if (render_target->viewport.height < grub_abs (dy))
+        dy = -render_target->viewport.height;
+
+      grub_video_vbe_fill_rect (color, 0, render_target->viewport.height + dy,
+                                render_target->viewport.width, -dy);
+    }
+
+  /* 4b. Fill left & right parts.  */
+  if (dx > 0)
+    grub_video_vbe_fill_rect (color, 0, 0,
+                              dx, render_target->viewport.height);
+  else if (dx < 0)
+    {
+      if (render_target->viewport.width < grub_abs (dx))
+        dx = -render_target->viewport.width;
+
+      grub_video_vbe_fill_rect (color, render_target->viewport.width + dx, 0,
+                                -dx, render_target->viewport.height);
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_swap_buffers (void)
+{
+  /* TODO: Implement buffer swapping.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_create_render_target (struct grub_video_render_target **result,
+                                     unsigned int width, unsigned int height,
+                                     unsigned int mode_type __attribute__ ((unused)))
+{
+  struct grub_video_render_target *target;
+  unsigned int size;
+
+  /* Validate arguments.  */
+  if ((! result)
+      || (width == 0)
+      || (height == 0))
+    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                       "invalid argument given.");
+
+  /* Allocate memory for render target.  */
+  target = grub_malloc (sizeof (struct grub_video_render_target));
+  if (! target)
+    return grub_errno;
+
+  /* TODO: Implement other types too.
+     Currently only 32bit render targets are supported.  */
+
+  /* Mark render target as allocated.  */
+  target->is_allocated = 1;
+
+  /* Maximize viewport.  */
+  target->viewport.x = 0;
+  target->viewport.y = 0;
+  target->viewport.width = width;
+  target->viewport.height = height;
+
+  /* Setup render target format.  */
+  target->mode_info.width = width;
+  target->mode_info.height = height;
+  target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB
+                                | GRUB_VIDEO_MODE_TYPE_ALPHA;
+  target->mode_info.bpp = 32;
+  target->mode_info.bytes_per_pixel = 4;
+  target->mode_info.pitch = target->mode_info.bytes_per_pixel * width;
+  target->mode_info.number_of_colors = 256; /* Emulated palette.  */
+  target->mode_info.red_mask_size = 8;
+  target->mode_info.red_field_pos = 0;
+  target->mode_info.green_mask_size = 8;
+  target->mode_info.green_field_pos = 8;
+  target->mode_info.blue_mask_size = 8;
+  target->mode_info.blue_field_pos = 16;
+  target->mode_info.reserved_mask_size = 8;
+  target->mode_info.reserved_field_pos = 24;
+
+  target->mode_info.blit_format = grub_video_get_blit_format (&target->mode_info);
+
+  /* Calculate size needed for the data.  */
+  size = (width * target->mode_info.bytes_per_pixel) * height;
+
+  target->data = grub_malloc (size);
+  if (! target->data)
+    {
+      grub_free (target);
+      return grub_errno;
+    }
+
+  /* Clear render target with black and maximum transparency.  */
+  grub_memset (target->data, 0, size);
+
+  /* TODO: Add render target to render target list.  */
+
+  /* Save result to caller.  */
+  *result = target;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_delete_render_target (struct grub_video_render_target *target)
+{
+  /* If there is no target, then just return without error.  */
+  if (! target)
+    return GRUB_ERR_NONE;
+
+  /* TODO: Delist render target fron render target list.  */
+
+  /* If this is software render target, free it's memory.  */
+  if (target->is_allocated)
+    grub_free (target->data);
+
+  /* Free render target.  */
+  grub_free (target);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_set_active_render_target (struct grub_video_render_target *target)
+{
+  if (target == GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER)
+    {
+      render_target = &framebuffer.render_target;
+
+      return GRUB_ERR_NONE;
+    }
+
+  if (target == GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER)
+    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                       "double buffering not implemented yet.");
+
+  if (! target->data)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                       "invalid render target given.");
+
+  render_target = target;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_vbe_get_active_render_target (struct grub_video_render_target **target)
+{
+  *target = render_target;
+
+  return GRUB_ERR_NONE;
+}
+
+static struct grub_video_adapter grub_video_vbe_adapter =
+  {
+    .name = "VESA BIOS Extension Video Driver",
+
+    .init = grub_video_vbe_init,
+    .fini = grub_video_vbe_fini,
+    .setup = grub_video_vbe_setup,
+    .get_info = grub_video_vbe_get_info,
+    .set_palette = grub_video_vbe_set_palette,
+    .get_palette = grub_video_vbe_get_palette,
+    .set_viewport = grub_video_vbe_set_viewport,
+    .get_viewport = grub_video_vbe_get_viewport,
+    .map_color = grub_video_vbe_map_color,
+    .map_rgb = grub_video_vbe_map_rgb,
+    .map_rgba = grub_video_vbe_map_rgba,
+    .unmap_color = grub_video_vbe_unmap_color,
+    .fill_rect = grub_video_vbe_fill_rect,
+    .blit_bitmap = grub_video_vbe_blit_bitmap,
+    .blit_render_target = grub_video_vbe_blit_render_target,
+    .scroll = grub_video_vbe_scroll,
+    .swap_buffers = grub_video_vbe_swap_buffers,
+    .create_render_target = grub_video_vbe_create_render_target,
+    .delete_render_target = grub_video_vbe_delete_render_target,
+    .set_active_render_target = grub_video_vbe_set_active_render_target,
+    .get_active_render_target = grub_video_vbe_get_active_render_target,
+
+    .next = 0
+  };
+
+GRUB_MOD_INIT(video_i386_pc_vbe)
+{
+  grub_video_register (&grub_video_vbe_adapter);
+}
+
+GRUB_MOD_FINI(video_i386_pc_vbe)
+{
+  grub_video_unregister (&grub_video_vbe_adapter);
+}
diff --git a/video/i386/pc/vbeblit.c b/video/i386/pc/vbeblit.c
new file mode 100644 (file)
index 0000000..4121bfe
--- /dev/null
@@ -0,0 +1,828 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+/* SPECIAL NOTES!
+
+   Please note following when reading the code below:
+
+   - In this driver we assume that every memory can be accessed by same memory
+   bus.  If there are different address spaces do not use this code as a base
+   code for other archs.
+
+   - Every function in this code assumes that bounds checking has been done in
+   previous phase and they are opted out in here.  */
+
+#include <grub/machine/vbe.h>
+#include <grub/machine/vbeblit.h>
+#include <grub/machine/vbeutil.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/video.h>
+
+/* Generic replacing blitter (slow).  Works for every supported format.  */
+void
+grub_video_i386_vbeblit_replace (struct grub_video_i386_vbeblit_info *dst,
+                                struct grub_video_i386_vbeblit_info *src,
+                                int x, int y, int width, int height,
+                                int offset_x, int offset_y)
+{
+  int i;
+  int j;
+  grub_uint8_t src_red;
+  grub_uint8_t src_green;
+  grub_uint8_t src_blue;
+  grub_uint8_t src_alpha;
+  grub_video_color_t src_color;
+  grub_video_color_t dst_color;
+
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+       {
+         src_color = get_pixel (src, i + offset_x, j + offset_y);
+
+         grub_video_vbe_unmap_color_int (src, src_color, &src_red, &src_green,
+                                         &src_blue, &src_alpha);
+
+         dst_color = grub_video_vbe_map_rgba (src_red, src_green,
+                                              src_blue, src_alpha);
+
+         set_pixel (dst, x + i, y + j, dst_color);
+       }
+    }
+}
+
+/* Block copy replacing blitter.  Works with modes multiple of 8 bits.  */
+void
+grub_video_i386_vbeblit_replace_directN (struct grub_video_i386_vbeblit_info *dst,
+                                        struct grub_video_i386_vbeblit_info *src,
+                                        int x, int y, int width, int height,
+                                        int offset_x, int offset_y)
+{
+  int j;
+  grub_uint32_t *srcptr;
+  grub_uint32_t *dstptr;
+  int bpp;
+
+  bpp = src->mode_info->bytes_per_pixel;
+
+  for (j = 0; j < height; j++)
+    {
+      srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint32_t *)get_data_ptr (dst, x, y + j);
+
+      grub_memmove (dstptr, srcptr, width * bpp);
+    }
+}
+
+/* Optimized replacing blitter for RGBX8888 to BGRX8888.  */
+void
+grub_video_i386_vbeblit_replace_BGRX8888_RGBX8888 (struct grub_video_i386_vbeblit_info *dst,
+                                                  struct grub_video_i386_vbeblit_info *src,
+                                                  int x, int y,
+                                                  int width, int height,
+                                                  int offset_x, int offset_y)
+{
+  int i;
+  int j;
+  grub_uint8_t *srcptr;
+  grub_uint8_t *dstptr;
+  unsigned int srcrowskip;
+  unsigned int dstrowskip;
+
+  /* Calculate the number of bytes to advance from the end of one line
+     to the beginning of the next line.  */
+  srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width;
+  dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+
+  srcptr = (grub_uint8_t *) get_data_ptr (src, offset_x, offset_y);
+  dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y);
+
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        {
+          grub_uint8_t r = *srcptr++;
+          grub_uint8_t g = *srcptr++;
+          grub_uint8_t b = *srcptr++;
+          grub_uint8_t a = *srcptr++;
+
+          *dstptr++ = b;
+          *dstptr++ = g;
+          *dstptr++ = r;
+          *dstptr++ = a;
+        }
+
+      srcptr += srcrowskip;
+      dstptr += dstrowskip;
+    }
+}
+
+/* Optimized replacing blitter for RGB888 to BGRX8888.  */
+void
+grub_video_i386_vbeblit_replace_BGRX8888_RGB888 (struct grub_video_i386_vbeblit_info *dst,
+                                                struct grub_video_i386_vbeblit_info *src,
+                                                int x, int y,
+                                                int width, int height,
+                                                int offset_x, int offset_y)
+{
+  int i;
+  int j;
+  grub_uint8_t *srcptr;
+  grub_uint8_t *dstptr;
+  unsigned int srcrowskip;
+  unsigned int dstrowskip;
+
+  /* Calculate the number of bytes to advance from the end of one line
+     to the beginning of the next line.  */
+  srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width;
+  dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+
+  srcptr = (grub_uint8_t *) get_data_ptr (src, offset_x, offset_y);
+  dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y);
+
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        {
+          grub_uint8_t r = *srcptr++;
+          grub_uint8_t g = *srcptr++;
+          grub_uint8_t b = *srcptr++;
+
+          *dstptr++ = b;
+          *dstptr++ = g;
+          *dstptr++ = r;
+
+          /* Set alpha component as opaque.  */
+          *dstptr++ = 255;
+        }
+
+      srcptr += srcrowskip;
+      dstptr += dstrowskip;
+    }
+}
+
+/* Optimized replacing blitter for RGBX8888 to BGR888.  */
+void
+grub_video_i386_vbeblit_replace_BGR888_RGBX8888 (struct grub_video_i386_vbeblit_info *dst,
+                                                struct grub_video_i386_vbeblit_info *src,
+                                                int x, int y,
+                                                int width, int height,
+                                                int offset_x, int offset_y)
+{
+  grub_uint32_t *srcptr;
+  grub_uint8_t *dstptr;
+  unsigned int srcrowskip;
+  unsigned int dstrowskip;
+  int i;
+  int j;
+
+  /* Calculate the number of bytes to advance from the end of one line
+     to the beginning of the next line.  */
+  srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width;
+  dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+
+  srcptr = (grub_uint32_t *) get_data_ptr (src, offset_x, offset_y);
+  dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y);
+
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        {
+          grub_uint32_t color;
+          grub_uint8_t sr;
+          grub_uint8_t sg;
+          grub_uint8_t sb;
+
+          color = *srcptr++;
+
+          sr = (color >> 0) & 0xFF;
+          sg = (color >> 8) & 0xFF;
+          sb = (color >> 16) & 0xFF;
+
+          *dstptr++ = sb;
+          *dstptr++ = sg;
+          *dstptr++ = sr;
+        }
+
+      srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip);
+      dstptr += dstrowskip;
+    }
+}
+
+/* Optimized replacing blitter for RGB888 to BGR888.  */
+void
+grub_video_i386_vbeblit_replace_BGR888_RGB888 (struct grub_video_i386_vbeblit_info *dst,
+                                              struct grub_video_i386_vbeblit_info *src,
+                                              int x, int y,
+                                              int width, int height,
+                                              int offset_x, int offset_y)
+{
+  int i;
+  int j;
+  grub_uint8_t *srcptr;
+  grub_uint8_t *dstptr;
+  unsigned int srcrowskip;
+  unsigned int dstrowskip;
+
+  /* Calculate the number of bytes to advance from the end of one line
+     to the beginning of the next line.  */
+  srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width;
+  dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+
+  srcptr = (grub_uint8_t *) get_data_ptr (src, offset_x, offset_y);
+  dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y);
+
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        {
+          grub_uint8_t r = *srcptr++;
+          grub_uint8_t g = *srcptr++;
+          grub_uint8_t b = *srcptr++;
+
+          *dstptr++ = b;
+          *dstptr++ = g;
+          *dstptr++ = r;
+        }
+
+      srcptr += srcrowskip;
+      dstptr += dstrowskip;
+    }
+}
+
+/* Optimized replacing blitter for RGB888 to RGBX8888.  */
+void
+grub_video_i386_vbeblit_replace_RGBX8888_RGB888 (struct grub_video_i386_vbeblit_info *dst,
+                                                struct grub_video_i386_vbeblit_info *src,
+                                                int x, int y,
+                                                int width, int height,
+                                                int offset_x, int offset_y)
+{
+  grub_uint32_t color;
+  int i;
+  int j;
+  grub_uint8_t *srcptr;
+  grub_uint32_t *dstptr;
+  unsigned int sr;
+  unsigned int sg;
+  unsigned int sb;
+
+  for (j = 0; j < height; j++)
+    {
+      srcptr = (grub_uint8_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint32_t *)get_data_ptr (dst, x, y + j);
+
+      for (i = 0; i < width; i++)
+        {
+          sr = *srcptr++;
+          sg = *srcptr++;
+          sb = *srcptr++;
+
+          /* Set alpha as opaque.  */
+          color = 0xFF000000 | (sb << 16) | (sg << 8) | sr;
+
+          *dstptr++ = color;
+        }
+    }
+}
+
+/* Optimized replacing blitter for RGBX8888 to RGB888.  */
+void
+grub_video_i386_vbeblit_replace_RGB888_RGBX8888 (struct grub_video_i386_vbeblit_info *dst,
+                                                struct grub_video_i386_vbeblit_info *src,
+                                                int x, int y,
+                                                int width, int height,
+                                                int offset_x, int offset_y)
+{
+  grub_uint32_t color;
+  int i;
+  int j;
+  grub_uint32_t *srcptr;
+  grub_uint8_t *dstptr;
+  unsigned int sr;
+  unsigned int sg;
+  unsigned int sb;
+
+  for (j = 0; j < height; j++)
+    {
+      srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j);
+
+      for (i = 0; i < width; i++)
+       {
+         color = *srcptr++;
+
+         sr = (color >> 0) & 0xFF;
+         sg = (color >> 8) & 0xFF;
+         sb = (color >> 16) & 0xFF;
+
+         *dstptr++ = sr;
+         *dstptr++ = sg;
+         *dstptr++ = sb;
+       }
+    }
+}
+
+/* Optimized replacing blitter for RGBX8888 to indexed color.  */
+void
+grub_video_i386_vbeblit_replace_index_RGBX8888 (struct grub_video_i386_vbeblit_info *dst,
+                                               struct grub_video_i386_vbeblit_info *src,
+                                               int x, int y,
+                                               int width, int height,
+                                               int offset_x, int offset_y)
+{
+  grub_uint32_t color;
+  int i;
+  int j;
+  grub_uint32_t *srcptr;
+  grub_uint8_t *dstptr;
+  unsigned int sr;
+  unsigned int sg;
+  unsigned int sb;
+
+  for (j = 0; j < height; j++)
+    {
+      srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j);
+
+      for (i = 0; i < width; i++)
+       {
+         color = *srcptr++;
+
+         sr = (color >> 0) & 0xFF;
+         sg = (color >> 8) & 0xFF;
+         sb = (color >> 16) & 0xFF;
+
+         color = grub_video_vbe_map_rgb(sr, sg, sb);
+         *dstptr++ = color & 0xFF;
+       }
+    }
+}
+
+/* Optimized replacing blitter for RGB888 to indexed color.  */
+void
+grub_video_i386_vbeblit_replace_index_RGB888 (struct grub_video_i386_vbeblit_info *dst,
+                                             struct grub_video_i386_vbeblit_info *src,
+                                             int x, int y,
+                                             int width, int height,
+                                             int offset_x, int offset_y)
+{
+  grub_uint32_t color;
+  int i;
+  int j;
+  grub_uint8_t *srcptr;
+  grub_uint8_t *dstptr;
+  unsigned int sr;
+  unsigned int sg;
+  unsigned int sb;
+
+  for (j = 0; j < height; j++)
+    {
+      srcptr = (grub_uint8_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j);
+
+      for (i = 0; i < width; i++)
+        {
+          sr = *srcptr++;
+          sg = *srcptr++;
+          sb = *srcptr++;
+
+          color = grub_video_vbe_map_rgb(sr, sg, sb);
+
+          *dstptr++ = color & 0xFF;
+        }
+    }
+}
+
+/* Generic blending blitter.  Works for every supported format.  */
+void
+grub_video_i386_vbeblit_blend (struct grub_video_i386_vbeblit_info *dst,
+                               struct grub_video_i386_vbeblit_info *src,
+                               int x, int y, int width, int height,
+                               int offset_x, int offset_y)
+{
+  int i;
+  int j;
+
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        {
+          grub_uint8_t src_red;
+          grub_uint8_t src_green;
+          grub_uint8_t src_blue;
+          grub_uint8_t src_alpha;
+          grub_uint8_t dst_red;
+          grub_uint8_t dst_green;
+          grub_uint8_t dst_blue;
+          grub_uint8_t dst_alpha;
+          grub_video_color_t src_color;
+          grub_video_color_t dst_color;
+
+          src_color = get_pixel (src, i + offset_x, j + offset_y);
+          grub_video_vbe_unmap_color_int (src, src_color, &src_red, &src_green,
+                                      &src_blue, &src_alpha);
+
+          if (src_alpha == 0)
+            continue;
+
+          if (src_alpha == 255)
+            {
+              dst_color = grub_video_vbe_map_rgba (src_red, src_green,
+                                                   src_blue, src_alpha);
+              set_pixel (dst, x + i, y + j, dst_color);
+              continue;
+            }
+
+          dst_color = get_pixel (dst, x + i, y + j);
+
+          grub_video_vbe_unmap_color_int (dst, dst_color, &dst_red,
+                                      &dst_green, &dst_blue, &dst_alpha);
+
+          dst_red = (((src_red * src_alpha)
+                      + (dst_red * (255 - src_alpha))) / 255);
+          dst_green = (((src_green * src_alpha)
+                        + (dst_green * (255 - src_alpha))) / 255);
+          dst_blue = (((src_blue * src_alpha)
+                       + (dst_blue * (255 - src_alpha))) / 255);
+
+          dst_alpha = src_alpha;
+          dst_color = grub_video_vbe_map_rgba (dst_red, dst_green, dst_blue,
+                                               dst_alpha);
+
+          set_pixel (dst, x + i, y + j, dst_color);
+        }
+    }
+}
+
+/* Optimized blending blitter for RGBA8888 to BGRA8888.  */
+void
+grub_video_i386_vbeblit_blend_BGRA8888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst,
+                                                struct grub_video_i386_vbeblit_info *src,
+                                                int x, int y,
+                                                int width, int height,
+                                                int offset_x, int offset_y)
+{
+  grub_uint32_t *srcptr;
+  grub_uint32_t *dstptr;
+  unsigned int srcrowskip;
+  unsigned int dstrowskip;
+  int i;
+  int j;
+
+  /* Calculate the number of bytes to advance from the end of one line
+     to the beginning of the next line.  */
+  srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width;
+  dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+
+  srcptr = (grub_uint32_t *) get_data_ptr (src, offset_x, offset_y);
+  dstptr = (grub_uint32_t *) get_data_ptr (dst, x, y);
+
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        {
+          grub_uint32_t color;
+          unsigned int sr;
+          unsigned int sg;
+          unsigned int sb;
+          unsigned int a;
+          unsigned int dr;
+          unsigned int dg;
+          unsigned int db;
+
+          color = *srcptr++;
+
+          a = color >> 24;
+
+          if (a == 0)
+            {
+              /* Skip transparent source pixels.  */
+              dstptr++;
+              continue;
+            }
+
+          sr = (color >> 0) & 0xFF;
+          sg = (color >> 8) & 0xFF;
+          sb = (color >> 16) & 0xFF;
+
+          if (a == 255)
+            {
+              /* Opaque pixel shortcut.  */
+              dr = sr;
+              dg = sg;
+              db = sb;
+            }
+          else
+            {
+              /* General pixel color blending.  */
+              color = *dstptr;
+
+              dr = (color >> 16) & 0xFF;
+              dr = (dr * (255 - a) + sr * a) / 255;
+              dg = (color >> 8) & 0xFF;
+              dg = (dg * (255 - a) + sg * a) / 255;
+              db = (color >> 0) & 0xFF;
+              db = (db * (255 - a) + sb * a) / 255;
+            }
+
+          color = (a << 24) | (dr << 16) | (dg << 8) | db;
+
+          *dstptr++ = color;
+        }
+
+      srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip);
+      dstptr = (grub_uint32_t *) (((grub_uint8_t *) dstptr) + dstrowskip);
+    }
+}
+
+/* Optimized blending blitter for RGBA8888 to BGR888.  */
+void
+grub_video_i386_vbeblit_blend_BGR888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst,
+                                              struct grub_video_i386_vbeblit_info *src,
+                                              int x, int y,
+                                              int width, int height,
+                                              int offset_x, int offset_y)
+{
+  grub_uint32_t *srcptr;
+  grub_uint8_t *dstptr;
+  unsigned int srcrowskip;
+  unsigned int dstrowskip;
+  int i;
+  int j;
+
+  /* Calculate the number of bytes to advance from the end of one line
+     to the beginning of the next line.  */
+  srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width;
+  dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+
+  srcptr = (grub_uint32_t *) get_data_ptr (src, offset_x, offset_y);
+  dstptr = (grub_uint8_t *) get_data_ptr (dst, x, y);
+
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        {
+          grub_uint32_t color;
+          unsigned int sr;
+          unsigned int sg;
+          unsigned int sb;
+          unsigned int a;
+          unsigned int dr;
+          unsigned int dg;
+          unsigned int db;
+
+          color = *srcptr++;
+
+          a = color >> 24;
+
+          if (a == 0)
+            {
+              /* Skip transparent source pixels.  */
+              dstptr += 3;
+              continue;
+            }
+
+          sr = (color >> 0) & 0xFF;
+          sg = (color >> 8) & 0xFF;
+          sb = (color >> 16) & 0xFF;
+
+          if (a == 255)
+            {
+              /* Opaque pixel shortcut.  */
+              dr = sr;
+              dg = sg;
+              db = sb;
+            }
+          else
+            {
+              /* General pixel color blending.  */
+              color = *dstptr;
+
+              db = dstptr[0];
+              db = (db * (255 - a) + sb * a) / 255;
+              dg = dstptr[1];
+              dg = (dg * (255 - a) + sg * a) / 255;
+              dr = dstptr[2];
+              dr = (dr * (255 - a) + sr * a) / 255;
+            }
+
+          *dstptr++ = db;
+          *dstptr++ = dg;
+          *dstptr++ = dr;
+        }
+
+      srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip);
+      dstptr += dstrowskip;
+    }
+}
+
+/* Optimized blending blitter for RGBA888 to RGBA8888.  */
+void
+grub_video_i386_vbeblit_blend_RGBA8888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst,
+                                                struct grub_video_i386_vbeblit_info *src,
+                                                int x, int y,
+                                                int width, int height,
+                                                int offset_x, int offset_y)
+{
+  grub_uint32_t color;
+  int i;
+  int j;
+  grub_uint32_t *srcptr;
+  grub_uint32_t *dstptr;
+  unsigned int sr;
+  unsigned int sg;
+  unsigned int sb;
+  unsigned int a;
+  unsigned int dr;
+  unsigned int dg;
+  unsigned int db;
+
+  for (j = 0; j < height; j++)
+    {
+      srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint32_t *)get_data_ptr (dst, x, y + j);
+
+      for (i = 0; i < width; i++)
+        {
+          color = *srcptr++;
+
+          a = color >> 24;
+
+          if (a == 0)
+            {
+              dstptr++;
+              continue;
+            }
+
+          if (a == 255)
+            {
+              *dstptr++ = color;
+              continue;
+            }
+
+          sr = (color >> 0) & 0xFF;
+          sg = (color >> 8) & 0xFF;
+          sb = (color >> 16) & 0xFF;
+
+          color = *dstptr;
+
+          dr = (color >> 0) & 0xFF;
+          dg = (color >> 8) & 0xFF;
+          db = (color >> 16) & 0xFF;
+
+          dr = (dr * (255 - a) + sr * a) / 255;
+          dg = (dg * (255 - a) + sg * a) / 255;
+          db = (db * (255 - a) + sb * a) / 255;
+
+          color = (a << 24) | (db << 16) | (dg << 8) | dr;
+
+          *dstptr++ = color;
+        }
+    }
+}
+
+/* Optimized blending blitter for RGBA8888 to RGB888.  */
+void
+grub_video_i386_vbeblit_blend_RGB888_RGBA8888 (struct grub_video_i386_vbeblit_info *dst,
+                                              struct grub_video_i386_vbeblit_info *src,
+                                              int x, int y,
+                                              int width, int height,
+                                              int offset_x, int offset_y)
+{
+  grub_uint32_t color;
+  int i;
+  int j;
+  grub_uint32_t *srcptr;
+  grub_uint8_t *dstptr;
+  unsigned int sr;
+  unsigned int sg;
+  unsigned int sb;
+  unsigned int a;
+  unsigned int dr;
+  unsigned int dg;
+  unsigned int db;
+
+  for (j = 0; j < height; j++)
+    {
+      srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j);
+
+      for (i = 0; i < width; i++)
+        {
+          color = *srcptr++;
+
+          a = color >> 24;
+
+          if (a == 0)
+            {
+              dstptr += 3;
+              continue;
+            }
+
+          sr = (color >> 0) & 0xFF;
+          sg = (color >> 8) & 0xFF;
+          sb = (color >> 16) & 0xFF;
+
+          if (a == 255)
+            {
+              *dstptr++ = sr;
+              *dstptr++ = sg;
+              *dstptr++ = sb;
+
+              continue;
+            }
+
+          dr = dstptr[0];
+          dg = dstptr[1];
+          db = dstptr[2];
+
+          dr = (dr * (255 - a) + sr * a) / 255;
+          dg = (dg * (255 - a) + sg * a) / 255;
+          db = (db * (255 - a) + sb * a) / 255;
+
+          *dstptr++ = dr;
+          *dstptr++ = dg;
+          *dstptr++ = db;
+        }
+    }
+}
+
+/* Optimized blending blitter for RGBA8888 to indexed color.  */
+void
+grub_video_i386_vbeblit_blend_index_RGBA8888 (struct grub_video_i386_vbeblit_info *dst,
+                                             struct grub_video_i386_vbeblit_info *src,
+                                             int x, int y,
+                                             int width, int height,
+                                             int offset_x, int offset_y)
+{
+  grub_uint32_t color;
+  int i;
+  int j;
+  grub_uint32_t *srcptr;
+  grub_uint8_t *dstptr;
+  unsigned int sr;
+  unsigned int sg;
+  unsigned int sb;
+  unsigned int a;
+  unsigned char dr;
+  unsigned char dg;
+  unsigned char db;
+  unsigned char da;
+
+  for (j = 0; j < height; j++)
+    {
+      srcptr = (grub_uint32_t *)get_data_ptr (src, offset_x, j + offset_y);
+      dstptr = (grub_uint8_t *)get_data_ptr (dst, x, y + j);
+
+      for (i = 0; i < width; i++)
+        {
+          color = *srcptr++;
+
+          a = color >> 24;
+
+          if (a == 0)
+            {
+              dstptr++;
+              continue;
+            }
+
+          sr = (color >> 0) & 0xFF;
+          sg = (color >> 8) & 0xFF;
+          sb = (color >> 16) & 0xFF;
+
+          if (a == 255)
+            {
+              color = grub_video_vbe_map_rgb(sr, sg, sb);
+              *dstptr++ = color & 0xFF;
+              continue;
+            }
+
+          grub_video_vbe_unmap_color_int (dst, *dstptr, &dr, &dg, &db, &da);
+
+          dr = (dr * (255 - a) + sr * a) / 255;
+          dg = (dg * (255 - a) + sg * a) / 255;
+          db = (db * (255 - a) + sb * a) / 255;
+
+          color = grub_video_vbe_map_rgb(dr, dg, db);
+
+          *dstptr++ = color & 0xFF;
+        }
+    }
+}
diff --git a/video/i386/pc/vbefill.c b/video/i386/pc/vbefill.c
new file mode 100644 (file)
index 0000000..3a98a71
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/>.
+ */
+
+/* SPECIAL NOTES!
+
+   Please note following when reading the code below:
+
+   - In this driver we assume that every memory can be accessed by same memory
+     bus.  If there are different address spaces do not use this code as a base
+     code for other archs.
+
+   - Every function in this code assumes that bounds checking has been done in
+     previous phase and they are opted out in here.  */
+
+#include <grub/machine/vbe.h>
+#include <grub/machine/vbefill.h>
+#include <grub/machine/vbeutil.h>
+#include <grub/types.h>
+#include <grub/video.h>
+
+/* Generic filler that works for every supported mode.  */
+void
+grub_video_i386_vbefill (struct grub_video_i386_vbeblit_info *dst,
+                         grub_video_color_t color, int x, int y,
+                         int width, int height)
+{
+  int i;
+  int j;
+
+  for (j = 0; j < height; j++)
+    for (i = 0; i < width; i++)
+      set_pixel (dst, x+i, y+j, color);
+}
+
+/* Optimized filler for direct color 32 bit modes.  It is assumed that color
+   is already mapped to destination format.  */
+void
+grub_video_i386_vbefill_direct32 (struct grub_video_i386_vbeblit_info *dst,
+                                  grub_video_color_t color, int x, int y,
+                                  int width, int height)
+{
+  int i;
+  int j;
+  grub_uint32_t *dstptr;
+  grub_size_t rowskip;
+
+  /* Calculate the number of bytes to advance from the end of one line
+     to the beginning of the next line.  */
+  rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+
+  /* Get the start address.  */
+  dstptr = (grub_uint32_t *) grub_video_vbe_get_video_ptr (dst, x, y);
+
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        *dstptr++ = color;
+
+      /* Advance the dest pointer to the right location on the next line.  */
+      dstptr = (grub_uint32_t *) (((char *) dstptr) + rowskip);
+    }
+}
+
+/* Optimized filler for direct color 24 bit modes.  It is assumed that color
+   is already mapped to destination format.  */
+void
+grub_video_i386_vbefill_direct24 (struct grub_video_i386_vbeblit_info *dst,
+                                  grub_video_color_t color, int x, int y,
+                                  int width, int height)
+{
+  int i;
+  int j;
+  grub_size_t rowskip;
+  grub_uint8_t *dstptr;
+  grub_uint8_t fill0 = (grub_uint8_t)((color >> 0) & 0xFF);
+  grub_uint8_t fill1 = (grub_uint8_t)((color >> 8) & 0xFF);
+  grub_uint8_t fill2 = (grub_uint8_t)((color >> 16) & 0xFF);
+
+  /* Calculate the number of bytes to advance from the end of one line
+     to the beginning of the next line.  */
+  rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+
+  /* Get the start address.  */
+  dstptr = (grub_uint8_t *) grub_video_vbe_get_video_ptr (dst, x, y);
+
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        {
+          *dstptr++ = fill0;
+          *dstptr++ = fill1;
+          *dstptr++ = fill2;
+        }
+
+      /* Advance the dest pointer to the right location on the next line.  */
+      dstptr += rowskip;
+    }
+}
+
+/* Optimized filler for direct color 16 bit modes.  It is assumed that color
+   is already mapped to destination format.  */
+void
+grub_video_i386_vbefill_direct16 (struct grub_video_i386_vbeblit_info *dst,
+                                  grub_video_color_t color, int x, int y,
+                                  int width, int height)
+{
+  int i;
+  int j;
+  grub_size_t rowskip;
+  grub_uint8_t *dstptr;
+  grub_uint8_t fill0 = (grub_uint8_t)((color >> 0) & 0xFF);
+  grub_uint8_t fill1 = (grub_uint8_t)((color >> 8) & 0xFF);
+
+  /* Calculate the number of bytes to advance from the end of one line
+     to the beginning of the next line.  */
+  rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+
+  /* Get the start address.  */
+  dstptr = (grub_uint8_t *) grub_video_vbe_get_video_ptr (dst, x, y);
+
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        {
+          *dstptr++ = fill0;
+          *dstptr++ = fill1;
+        }
+
+      /* Advance the dest pointer to the right location on the next line.  */
+      dstptr += rowskip;
+    }
+}
+
+/* Optimized filler for index color.  It is assumed that color
+   is already mapped to destination format.  */
+void
+grub_video_i386_vbefill_direct8 (struct grub_video_i386_vbeblit_info *dst,
+                                grub_video_color_t color, int x, int y,
+                                int width, int height)
+{
+  int i;
+  int j;
+  grub_size_t rowskip;
+  grub_uint8_t *dstptr;
+  grub_uint8_t fill = (grub_uint8_t)color & 0xFF;
+
+  /* Calculate the number of bytes to advance from the end of one line
+     to the beginning of the next line.  */
+  rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+
+  /* Get the start address.  */
+  dstptr = (grub_uint8_t *) grub_video_vbe_get_video_ptr (dst, x, y);
+
+  for (j = 0; j < height; j++)
+    {
+      for (i = 0; i < width; i++)
+        *dstptr++ = fill;
+
+      /* Advance the dest pointer to the right location on the next line.  */
+      dstptr += rowskip;
+    }
+}
diff --git a/video/i386/pc/vbeutil.c b/video/i386/pc/vbeutil.c
new file mode 100644 (file)
index 0000000..1040dc9
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,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/machine/vbeutil.h>
+#include <grub/types.h>
+#include <grub/video.h>
+
+grub_uint8_t *
+get_data_ptr (struct grub_video_i386_vbeblit_info *source,
+              unsigned int x, unsigned int y)
+{
+  grub_uint8_t *ptr = 0;
+
+  switch (source->mode_info->bpp)
+    {
+    case 32:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info->pitch
+            + x * 4;
+      break;
+
+    case 24:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info->pitch
+            + x * 3;
+      break;
+
+    case 16:
+    case 15:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info->pitch
+            + x * 2;
+      break;
+
+    case 8:
+      ptr = (grub_uint8_t *)source->data
+            + y * source->mode_info->pitch
+            + x;
+      break;
+
+    case 1:
+      /* For 1-bit bitmaps, addressing needs to be done at the bit level
+         and it doesn't make sense, in general, to ask for a pointer
+         to a particular pixel's data.  */
+      break;
+    }
+
+  return ptr;
+}
+
+grub_video_color_t
+get_pixel (struct grub_video_i386_vbeblit_info *source,
+           unsigned int x, unsigned int y)
+{
+  grub_video_color_t color = 0;
+
+  switch (source->mode_info->bpp)
+    {
+    case 32:
+      color = *(grub_uint32_t *)get_data_ptr (source, x, y);
+      break;
+
+    case 24:
+      {
+        grub_uint8_t *ptr;
+        ptr = get_data_ptr (source, x, y);
+        color = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
+      }
+      break;
+
+    case 16:
+    case 15:
+      color = *(grub_uint16_t *)get_data_ptr (source, x, y);
+      break;
+
+    case 8:
+      color = *(grub_uint8_t *)get_data_ptr (source, x, y);
+      break;
+
+    case 1:
+      if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED)
+        {
+          int bit_index = y * source->mode_info->width + x;
+          grub_uint8_t *ptr = (grub_uint8_t *)source->data
+                              + bit_index / 8;
+          int bit_pos = 7 - bit_index % 8;
+          color = (*ptr >> bit_pos) & 0x01;
+        }
+      break;
+
+    default:
+      break;
+    }
+
+  return color;
+}
+
+void
+set_pixel (struct grub_video_i386_vbeblit_info *source,
+           unsigned int x, unsigned int y, grub_video_color_t color)
+{
+  switch (source->mode_info->bpp)
+    {
+    case 32:
+      {
+        grub_uint32_t *ptr;
+
+        ptr = (grub_uint32_t *)get_data_ptr (source, x, y);
+
+        *ptr = color;
+      }
+      break;
+
+    case 24:
+      {
+        grub_uint8_t *ptr;
+        grub_uint8_t *colorptr = (grub_uint8_t *)&color;
+
+        ptr = get_data_ptr (source, x, y);
+
+        ptr[0] = colorptr[0];
+        ptr[1] = colorptr[1];
+        ptr[2] = colorptr[2];
+      }
+      break;
+
+    case 16:
+    case 15:
+      {
+        grub_uint16_t *ptr;
+
+        ptr = (grub_uint16_t *)get_data_ptr (source, x, y);
+
+        *ptr = (grub_uint16_t) (color & 0xFFFF);
+      }
+      break;
+
+    case 8:
+      {
+        grub_uint8_t *ptr;
+
+        ptr = (grub_uint8_t *)get_data_ptr (source, x, y);
+
+        *ptr = (grub_uint8_t) (color & 0xFF);
+      }
+      break;
+
+    case 1:
+      if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED)
+        {
+          int bit_index = y * source->mode_info->width + x;
+          grub_uint8_t *ptr = (grub_uint8_t *)source->data
+                              + bit_index / 8;
+          int bit_pos = 7 - bit_index % 8;
+          *ptr = (*ptr & ~(1 << bit_pos)) | ((color & 0x01) << bit_pos);
+        }
+      break;
+
+    default:
+      break;
+    }
+}
diff --git a/video/readers/jpeg.c b/video/readers/jpeg.c
new file mode 100644 (file)
index 0000000..327c9f9
--- /dev/null
@@ -0,0 +1,748 @@
+/*
+ *  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/bitmap.h>
+#include <grub/types.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/arg.h>
+#include <grub/bufio.h>
+
+/* Uncomment following define to enable JPEG debug.  */
+//#define JPEG_DEBUG
+
+#define JPEG_ESC_CHAR          0xFF
+
+#define JPEG_SAMPLING_1x1      0x11
+
+#define JPEG_MARKER_SOI                0xd8
+#define JPEG_MARKER_EOI                0xd9
+#define JPEG_MARKER_DHT                0xc4
+#define JPEG_MARKER_DQT                0xdb
+#define JPEG_MARKER_SOF0       0xc0
+#define JPEG_MARKER_SOS                0xda
+
+#define SHIFT_BITS             8
+#define CONST(x)               ((int) ((x) * (1L << SHIFT_BITS) + 0.5))
+
+#define JPEG_UNIT_SIZE         8
+
+static const grub_uint8_t jpeg_zigzag_order[64] = {
+  0, 1, 8, 16, 9, 2, 3, 10,
+  17, 24, 32, 25, 18, 11, 4, 5,
+  12, 19, 26, 33, 40, 48, 41, 34,
+  27, 20, 13, 6, 7, 14, 21, 28,
+  35, 42, 49, 56, 57, 50, 43, 36,
+  29, 22, 15, 23, 30, 37, 44, 51,
+  58, 59, 52, 45, 38, 31, 39, 46,
+  53, 60, 61, 54, 47, 55, 62, 63
+};
+
+typedef int jpeg_data_unit_t[64];
+
+struct grub_jpeg_data
+{
+  grub_file_t file;
+  struct grub_video_bitmap **bitmap;
+
+  int image_width;
+  int image_height;
+
+  grub_uint8_t *huff_value[4];
+  int huff_offset[4][16];
+  int huff_maxval[4][16];
+
+  grub_uint8_t quan_table[2][64];
+  int comp_index[3][3];
+
+  jpeg_data_unit_t ydu[4];
+  jpeg_data_unit_t crdu;
+  jpeg_data_unit_t cbdu;
+
+  int vs, hs;
+
+  int dc_value[3];
+
+  int bit_mask, bit_save;
+};
+
+static grub_uint8_t
+grub_jpeg_get_byte (struct grub_jpeg_data *data)
+{
+  grub_uint8_t r;
+
+  r = 0;
+  grub_file_read (data->file, (char *) &r, 1);
+
+  return r;
+}
+
+static grub_uint16_t
+grub_jpeg_get_word (struct grub_jpeg_data *data)
+{
+  grub_uint16_t r;
+
+  r = 0;
+  grub_file_read (data->file, (char *) &r, sizeof (grub_uint16_t));
+
+  return grub_be_to_cpu16 (r);
+}
+
+static int
+grub_jpeg_get_bit (struct grub_jpeg_data *data)
+{
+  int ret;
+
+  if (data->bit_mask == 0)
+    {
+      data->bit_save = grub_jpeg_get_byte (data);
+      if (data->bit_save == JPEG_ESC_CHAR)
+       {
+         if (grub_jpeg_get_byte (data) != 0)
+           {
+             grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                         "jpeg: invalid 0xFF in data stream");
+             return 0;
+           }
+       }
+      data->bit_mask = 0x80;
+    }
+
+  ret = ((data->bit_save & data->bit_mask) != 0);
+  data->bit_mask >>= 1;
+  return ret;
+}
+
+static int
+grub_jpeg_get_number (struct grub_jpeg_data *data, int num)
+{
+  int value, i, msb;
+
+  if (num == 0)
+    return 0;
+
+  msb = value = grub_jpeg_get_bit (data);
+  for (i = 1; i < num; i++)
+    value = (value << 1) + (grub_jpeg_get_bit (data) != 0);
+  if (!msb)
+    value += 1 - (1 << num);
+
+  return value;
+}
+
+static int
+grub_jpeg_get_huff_code (struct grub_jpeg_data *data, int id)
+{
+  int code, i;
+
+  code = 0;
+  for (i = 0; i < 16; i++)
+    {
+      code <<= 1;
+      if (grub_jpeg_get_bit (data))
+       code++;
+      if (code < data->huff_maxval[id][i])
+       return data->huff_value[id][code + data->huff_offset[id][i]];
+    }
+  grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: huffman decode fails");
+  return 0;
+}
+
+static grub_err_t
+grub_jpeg_decode_huff_table (struct grub_jpeg_data *data)
+{
+  int id, ac, i, n, base, ofs;
+  grub_uint32_t next_marker;
+  grub_uint8_t count[16];
+
+  next_marker = data->file->offset;
+  next_marker += grub_jpeg_get_word (data);
+
+  id = grub_jpeg_get_byte (data);
+  ac = (id >> 4);
+  id &= 0xF;
+  if (id > 1)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                      "jpeg: too many huffman tables");
+
+  if (grub_file_read (data->file, (char *) &count, sizeof (count)) !=
+      sizeof (count))
+    return grub_errno;
+
+  n = 0;
+  for (i = 0; i < 16; i++)
+    n += count[i];
+
+  id += ac * 2;
+  data->huff_value[id] = grub_malloc (n);
+  if (grub_errno)
+    return grub_errno;
+
+  if (grub_file_read (data->file, (char *) data->huff_value[id], n) != n)
+    return grub_errno;
+
+  base = 0;
+  ofs = 0;
+  for (i = 0; i < 16; i++)
+    {
+      base += count[i];
+      ofs += count[i];
+
+      data->huff_maxval[id][i] = base;
+      data->huff_offset[id][i] = ofs - base;
+
+      base <<= 1;
+    }
+
+  if (data->file->offset != next_marker)
+    grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in huffman table");
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_jpeg_decode_quan_table (struct grub_jpeg_data *data)
+{
+  int id;
+  grub_uint32_t next_marker;
+
+  next_marker = data->file->offset;
+  next_marker += grub_jpeg_get_word (data);
+
+  id = grub_jpeg_get_byte (data);
+  if (id >= 0x10)              /* Upper 4-bit is precision.  */
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                      "jpeg: only 8-bit precision is supported");
+
+  if (id > 1)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                      "jpeg: too many quantization tables");
+
+  if (grub_file_read (data->file, (char *) &data->quan_table[id], 64) != 64)
+    return grub_errno;
+
+  if (data->file->offset != next_marker)
+    grub_error (GRUB_ERR_BAD_FILE_TYPE,
+               "jpeg: extra byte in quantization table");
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_jpeg_decode_sof (struct grub_jpeg_data *data)
+{
+  int i, cc;
+  grub_uint32_t next_marker;
+
+  next_marker = data->file->offset;
+  next_marker += grub_jpeg_get_word (data);
+
+  if (grub_jpeg_get_byte (data) != 8)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                      "jpeg: only 8-bit precision is supported");
+
+  data->image_height = grub_jpeg_get_word (data);
+  data->image_width = grub_jpeg_get_word (data);
+
+  if ((!data->image_height) || (!data->image_width))
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid image size");
+
+  cc = grub_jpeg_get_byte (data);
+  if (cc != 3)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                      "jpeg: component count must be 3");
+
+  for (i = 0; i < cc; i++)
+    {
+      int id, ss;
+
+      id = grub_jpeg_get_byte (data) - 1;
+      if ((id < 0) || (id >= 3))
+       return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
+
+      ss = grub_jpeg_get_byte (data);  /* Sampling factor.  */
+      if (!id)
+       {
+         data->vs = ss & 0xF;  /* Vertical sampling.  */
+         data->hs = ss >> 4;   /* Horizontal sampling.  */
+         if ((data->vs > 2) || (data->hs > 2))
+           return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                              "jpeg: sampling method not supported");
+       }
+      else if (ss != JPEG_SAMPLING_1x1)
+       return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                          "jpeg: sampling method not supported");
+      data->comp_index[id][0] = grub_jpeg_get_byte (data);
+    }
+
+  if (data->file->offset != next_marker)
+    grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sof");
+
+  return grub_errno;
+}
+
+static void
+grub_jpeg_idct_transform (jpeg_data_unit_t du)
+{
+  int *pd;
+  int i;
+  int t0, t1, t2, t3, t4, t5, t6, t7;
+  int v0, v1, v2, v3, v4;
+
+  pd = du;
+  for (i = 0; i < JPEG_UNIT_SIZE; i++, pd++)
+    {
+      if ((pd[JPEG_UNIT_SIZE * 1] | pd[JPEG_UNIT_SIZE * 2] |
+          pd[JPEG_UNIT_SIZE * 3] | pd[JPEG_UNIT_SIZE * 4] |
+          pd[JPEG_UNIT_SIZE * 5] | pd[JPEG_UNIT_SIZE * 6] |
+          pd[JPEG_UNIT_SIZE * 7]) == 0)
+       {
+         pd[JPEG_UNIT_SIZE * 0] <<= SHIFT_BITS;
+
+         pd[JPEG_UNIT_SIZE * 1] = pd[JPEG_UNIT_SIZE * 2]
+           = pd[JPEG_UNIT_SIZE * 3] = pd[JPEG_UNIT_SIZE * 4]
+           = pd[JPEG_UNIT_SIZE * 5] = pd[JPEG_UNIT_SIZE * 6]
+           = pd[JPEG_UNIT_SIZE * 7] = pd[JPEG_UNIT_SIZE * 0];
+
+         continue;
+       }
+
+      t0 = pd[JPEG_UNIT_SIZE * 0];
+      t1 = pd[JPEG_UNIT_SIZE * 2];
+      t2 = pd[JPEG_UNIT_SIZE * 4];
+      t3 = pd[JPEG_UNIT_SIZE * 6];
+
+      v4 = (t1 + t3) * CONST (0.541196100);
+
+      v0 = ((t0 + t2) << SHIFT_BITS);
+      v1 = ((t0 - t2) << SHIFT_BITS);
+      v2 = v4 - t3 * CONST (1.847759065);
+      v3 = v4 + t1 * CONST (0.765366865);
+
+      t0 = v0 + v3;
+      t3 = v0 - v3;
+      t1 = v1 + v2;
+      t2 = v1 - v2;
+
+      t4 = pd[JPEG_UNIT_SIZE * 7];
+      t5 = pd[JPEG_UNIT_SIZE * 5];
+      t6 = pd[JPEG_UNIT_SIZE * 3];
+      t7 = pd[JPEG_UNIT_SIZE * 1];
+
+      v0 = t4 + t7;
+      v1 = t5 + t6;
+      v2 = t4 + t6;
+      v3 = t5 + t7;
+
+      v4 = (v2 + v3) * CONST (1.175875602);
+
+      v0 *= CONST (0.899976223);
+      v1 *= CONST (2.562915447);
+      v2 = v2 * CONST (1.961570560) - v4;
+      v3 = v3 * CONST (0.390180644) - v4;
+
+      t4 = t4 * CONST (0.298631336) - v0 - v2;
+      t5 = t5 * CONST (2.053119869) - v1 - v3;
+      t6 = t6 * CONST (3.072711026) - v1 - v2;
+      t7 = t7 * CONST (1.501321110) - v0 - v3;
+
+      pd[JPEG_UNIT_SIZE * 0] = t0 + t7;
+      pd[JPEG_UNIT_SIZE * 7] = t0 - t7;
+      pd[JPEG_UNIT_SIZE * 1] = t1 + t6;
+      pd[JPEG_UNIT_SIZE * 6] = t1 - t6;
+      pd[JPEG_UNIT_SIZE * 2] = t2 + t5;
+      pd[JPEG_UNIT_SIZE * 5] = t2 - t5;
+      pd[JPEG_UNIT_SIZE * 3] = t3 + t4;
+      pd[JPEG_UNIT_SIZE * 4] = t3 - t4;
+    }
+
+  pd = du;
+  for (i = 0; i < JPEG_UNIT_SIZE; i++, pd += JPEG_UNIT_SIZE)
+    {
+      if ((pd[1] | pd[2] | pd[3] | pd[4] | pd[5] | pd[6] | pd[7]) == 0)
+       {
+         pd[0] >>= (SHIFT_BITS + 3);
+         pd[1] = pd[2] = pd[3] = pd[4] = pd[5] = pd[6] = pd[7] = pd[0];
+         continue;
+       }
+
+      v4 = (pd[2] + pd[6]) * CONST (0.541196100);
+
+      v0 = (pd[0] + pd[4]) << SHIFT_BITS;
+      v1 = (pd[0] - pd[4]) << SHIFT_BITS;
+      v2 = v4 - pd[6] * CONST (1.847759065);
+      v3 = v4 + pd[2] * CONST (0.765366865);
+
+      t0 = v0 + v3;
+      t3 = v0 - v3;
+      t1 = v1 + v2;
+      t2 = v1 - v2;
+
+      t4 = pd[7];
+      t5 = pd[5];
+      t6 = pd[3];
+      t7 = pd[1];
+
+      v0 = t4 + t7;
+      v1 = t5 + t6;
+      v2 = t4 + t6;
+      v3 = t5 + t7;
+
+      v4 = (v2 + v3) * CONST (1.175875602);
+
+      v0 *= CONST (0.899976223);
+      v1 *= CONST (2.562915447);
+      v2 = v2 * CONST (1.961570560) - v4;
+      v3 = v3 * CONST (0.390180644) - v4;
+
+      t4 = t4 * CONST (0.298631336) - v0 - v2;
+      t5 = t5 * CONST (2.053119869) - v1 - v3;
+      t6 = t6 * CONST (3.072711026) - v1 - v2;
+      t7 = t7 * CONST (1.501321110) - v0 - v3;
+
+      pd[0] = (t0 + t7) >> (SHIFT_BITS * 2 + 3);
+      pd[7] = (t0 - t7) >> (SHIFT_BITS * 2 + 3);
+      pd[1] = (t1 + t6) >> (SHIFT_BITS * 2 + 3);
+      pd[6] = (t1 - t6) >> (SHIFT_BITS * 2 + 3);
+      pd[2] = (t2 + t5) >> (SHIFT_BITS * 2 + 3);
+      pd[5] = (t2 - t5) >> (SHIFT_BITS * 2 + 3);
+      pd[3] = (t3 + t4) >> (SHIFT_BITS * 2 + 3);
+      pd[4] = (t3 - t4) >> (SHIFT_BITS * 2 + 3);
+    }
+
+  for (i = 0; i < JPEG_UNIT_SIZE * JPEG_UNIT_SIZE; i++)
+    {
+      du[i] += 128;
+
+      if (du[i] < 0)
+       du[i] = 0;
+      if (du[i] > 255)
+       du[i] = 255;
+    }
+}
+
+static void
+grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
+{
+  int pos, h1, h2, qt;
+
+  grub_memset (du, 0, sizeof (jpeg_data_unit_t));
+
+  qt = data->comp_index[id][0];
+  h1 = data->comp_index[id][1];
+  h2 = data->comp_index[id][2];
+
+  data->dc_value[id] +=
+    grub_jpeg_get_number (data, grub_jpeg_get_huff_code (data, h1));
+
+  du[0] = data->dc_value[id] * (int) data->quan_table[qt][0];
+  pos = 1;
+  while (pos < 64)
+    {
+      int num, val;
+
+      num = grub_jpeg_get_huff_code (data, h2);
+      if (!num)
+       break;
+
+      val = grub_jpeg_get_number (data, num & 0xF);
+      num >>= 4;
+      pos += num;
+      du[jpeg_zigzag_order[pos]] = val * (int) data->quan_table[qt][pos];
+      pos++;
+    }
+
+  grub_jpeg_idct_transform (du);
+}
+
+static void
+grub_jpeg_ycrcb_to_rgb (int yy, int cr, int cb, grub_uint8_t * rgb)
+{
+  int dd;
+
+  cr -= 128;
+  cb -= 128;
+
+  /* Red  */
+  dd = yy + ((cr * CONST (1.402)) >> SHIFT_BITS);
+  if (dd < 0)
+    dd = 0;
+  if (dd > 255)
+    dd = 255;
+  *(rgb++) = dd;
+
+  /* Green  */
+  dd = yy - ((cb * CONST (0.34414) + cr * CONST (0.71414)) >> SHIFT_BITS);
+  if (dd < 0)
+    dd = 0;
+  if (dd > 255)
+    dd = 255;
+  *(rgb++) = dd;
+
+  /* Blue  */
+  dd = yy + ((cb * CONST (1.772)) >> SHIFT_BITS);
+  if (dd < 0)
+    dd = 0;
+  if (dd > 255)
+    dd = 255;
+  *(rgb++) = dd;
+}
+
+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;
+  grub_uint32_t data_offset;
+
+  data_offset = data->file->offset;
+  data_offset += grub_jpeg_get_word (data);
+
+  cc = grub_jpeg_get_byte (data);
+
+  if (cc != 3)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                      "jpeg: component count must be 3");
+
+  for (i = 0; i < cc; i++)
+    {
+      int id, ht;
+
+      id = grub_jpeg_get_byte (data) - 1;
+      if ((id < 0) || (id >= 3))
+       return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
+
+      ht = grub_jpeg_get_byte (data);
+      data->comp_index[id][1] = (ht >> 4);
+      data->comp_index[id][2] = (ht & 0xF) + 2;
+    }
+
+  grub_jpeg_get_byte (data);   /* Skip 3 unused bytes.  */
+  grub_jpeg_get_word (data);
+
+  if (data->file->offset != data_offset)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos");
+
+  if (grub_video_bitmap_create (data->bitmap, data->image_width,
+                               data->image_height,
+                               GRUB_VIDEO_BLIT_FORMAT_RGB_888))
+    return grub_errno;
+
+  data->bit_mask = 0x0;
+
+  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)
+      {
+       int r2, c2, nr2, nc2;
+       grub_uint8_t *ptr2;
+
+       for (r2 = 0; r2 < data->vs; r2++)
+         for (c2 = 0; c2 < data->hs; c2++)
+           grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]);
+
+       grub_jpeg_decode_du (data, 1, data->cbdu);
+       grub_jpeg_decode_du (data, 2, data->crdu);
+
+       if (grub_errno)
+         return grub_errno;
+
+       nr2 = (r1 == nr1 - 1) ? (data->image_height - r1 * vb) : vb;
+       nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb;
+
+       ptr2 = ptr1;
+       for (r2 = 0; r2 < nr2; r2++, ptr2 += (data->image_width - nc2) * 3)
+         for (c2 = 0; c2 < nc2; c2++, ptr2 += 3)
+           {
+             int i0, yy, cr, cb;
+
+             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)];
+
+             grub_jpeg_ycrcb_to_rgb (yy, cr, cb, ptr2);
+           }
+      }
+
+  return grub_errno;
+}
+
+static grub_uint8_t
+grub_jpeg_get_marker (struct grub_jpeg_data *data)
+{
+  grub_uint8_t r;
+
+  r = grub_jpeg_get_byte (data);
+
+  if (r != JPEG_ESC_CHAR)
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid maker");
+      return 0;
+    }
+
+  return grub_jpeg_get_byte (data);
+}
+
+static grub_err_t
+grub_jpeg_decode_jpeg (struct grub_jpeg_data *data)
+{
+  if (grub_jpeg_get_marker (data) != JPEG_MARKER_SOI)  /* Start Of Image.  */
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid jpeg file");
+
+  while (grub_errno == 0)
+    {
+      grub_uint8_t marker;
+
+      marker = grub_jpeg_get_marker (data);
+      if (grub_errno)
+       break;
+
+#ifdef JPEG_DEBUG
+      grub_printf ("jpeg marker: %x\n", marker);
+#endif
+
+      switch (marker)
+       {
+       case JPEG_MARKER_DHT:   /* Define Huffman Table.  */
+         grub_jpeg_decode_huff_table (data);
+         break;
+       case JPEG_MARKER_DQT:   /* Define Quantization Table.  */
+         grub_jpeg_decode_quan_table (data);
+         break;
+       case JPEG_MARKER_SOF0:  /* Start Of Frame 0.  */
+         grub_jpeg_decode_sof (data);
+         break;
+       case JPEG_MARKER_SOS:   /* Start Of Scan.  */
+         grub_jpeg_decode_sos (data);
+         break;
+       case JPEG_MARKER_EOI:   /* End Of Image.  */
+         return grub_errno;
+       default:                /* Skip unrecognized marker.  */
+         {
+           grub_uint16_t sz;
+
+           sz = grub_jpeg_get_word (data);
+           if (grub_errno)
+             return (grub_errno);
+           grub_file_seek (data->file, data->file->offset + sz - 2);
+         }
+       }
+    }
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_video_reader_jpeg (struct grub_video_bitmap **bitmap,
+                       const char *filename)
+{
+  grub_file_t file;
+  struct grub_jpeg_data *data;
+
+  file = grub_buffile_open (filename, 0);
+  if (!file)
+    return grub_errno;
+
+  data = grub_malloc (sizeof (*data));
+  if (data != NULL)
+    {
+      int i;
+
+      grub_memset (data, 0, sizeof (*data));
+      data->file = file;
+      data->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);
+    }
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_video_bitmap_destroy (*bitmap);
+      *bitmap = 0;
+    }
+
+  grub_file_close (file);
+  return grub_errno;
+}
+
+#if defined(JPEG_DEBUG)
+static grub_err_t
+grub_cmd_jpegtest (struct grub_arg_list *state __attribute__ ((unused)),
+                  int argc, char **args)
+{
+  struct grub_video_bitmap *bitmap = 0;
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
+
+  grub_video_reader_jpeg (&bitmap, args[0]);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
+  grub_video_bitmap_destroy (bitmap);
+
+  return GRUB_ERR_NONE;
+}
+#endif
+
+static struct grub_video_bitmap_reader jpg_reader = {
+  .extension = ".jpg",
+  .reader = grub_video_reader_jpeg,
+  .next = 0
+};
+
+static struct grub_video_bitmap_reader jpeg_reader = {
+  .extension = ".jpeg",
+  .reader = grub_video_reader_jpeg,
+  .next = 0
+};
+
+GRUB_MOD_INIT (video_reader_jpeg)
+{
+  grub_video_bitmap_reader_register (&jpg_reader);
+  grub_video_bitmap_reader_register (&jpeg_reader);
+#if defined(JPEG_DEBUG)
+  grub_register_command ("jpegtest", grub_cmd_jpegtest,
+                        GRUB_COMMAND_FLAG_BOTH, "jpegtest FILE",
+                        "Tests loading of JPEG bitmap.", 0);
+#endif
+}
+
+GRUB_MOD_FINI (video_reader_jpeg)
+{
+#if defined(JPEG_DEBUG)
+  grub_unregister_command ("jpegtest");
+#endif
+  grub_video_bitmap_reader_unregister (&jpeg_reader);
+  grub_video_bitmap_reader_unregister (&jpg_reader);
+}
diff --git a/video/readers/png.c b/video/readers/png.c
new file mode 100644 (file)
index 0000000..3364d56
--- /dev/null
@@ -0,0 +1,912 @@
+/*
+ *  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/bitmap.h>
+#include <grub/types.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/arg.h>
+#include <grub/bufio.h>
+
+/* Uncomment following define to enable PNG debug.  */
+//#define PNG_DEBUG
+
+#define PNG_COLOR_MASK_PALETTE 1
+#define PNG_COLOR_MASK_COLOR   2
+#define PNG_COLOR_MASK_ALPHA   4
+
+#define PNG_COLOR_TYPE_GRAY    0
+#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
+#define PNG_COLOR_TYPE_RGB     (PNG_COLOR_MASK_COLOR)
+#define PNG_COLOR_TYPE_RGBA    (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
+#define PNG_COLOR_TYPE_GRAYA   (PNG_COLOR_MASK_ALPHA)
+
+#define PNG_COMPRESSION_BASE   0
+
+#define PNG_INTERLACE_NONE     0
+#define PNG_INTERLACE_ADAM7    1
+
+#define PNG_FILTER_TYPE_BASE   0
+
+#define PNG_FILTER_VALUE_NONE  0
+#define PNG_FILTER_VALUE_SUB   1
+#define PNG_FILTER_VALUE_UP    2
+#define PNG_FILTER_VALUE_AVG   3
+#define PNG_FILTER_VALUE_PAETH 4
+#define PNG_FILTER_VALUE_LAST  5
+
+#define PNG_CHUNK_IHDR         0x49484452
+#define PNG_CHUNK_IDAT         0x49444154
+#define PNG_CHUNK_IEND         0x49454e44
+
+#define Z_DEFLATED             8
+#define Z_FLAG_DICT            32
+
+#define INFLATE_STORED         0
+#define INFLATE_FIXED          1
+#define INFLATE_DYNAMIC                2
+
+#define WSIZE                  0x8000
+
+#define DEFLATE_HCLEN_BASE     4
+#define DEFLATE_HCLEN_MAX      19
+#define DEFLATE_HLIT_BASE      257
+#define DEFLATE_HLIT_MAX       288
+#define DEFLATE_HDIST_BASE     1
+#define DEFLATE_HDIST_MAX      30
+
+#define DEFLATE_HUFF_LEN       16
+
+struct huff_table
+{
+  int *values, *maxval, *offset;
+  int num_values, max_length;
+};
+
+struct grub_png_data
+{
+  grub_file_t file;
+  struct grub_video_bitmap **bitmap;
+
+  int bit_count, bit_save;
+
+  grub_uint32_t next_offset;
+
+  int image_width, image_height, bpp, is_16bit, raw_bytes;
+  grub_uint8_t *image_data;
+
+  int inside_idat, idat_remain;
+
+  int code_values[DEFLATE_HLIT_MAX];
+  int code_maxval[DEFLATE_HUFF_LEN];
+  int code_offset[DEFLATE_HUFF_LEN];
+
+  int dist_values[DEFLATE_HDIST_MAX];
+  int dist_maxval[DEFLATE_HUFF_LEN];
+  int dist_offset[DEFLATE_HUFF_LEN];
+
+  struct huff_table code_table;
+  struct huff_table dist_table;
+
+  grub_uint8_t slide[WSIZE];
+  int wp;
+
+  grub_uint8_t *cur_rgb;
+
+  int cur_colume, cur_filter, first_line;
+};
+
+static grub_uint32_t
+grub_png_get_dword (struct grub_png_data *data)
+{
+  grub_uint32_t r;
+
+  r = 0;
+  grub_file_read (data->file, (char *) &r, sizeof (grub_uint32_t));
+
+  return grub_be_to_cpu32 (r);
+}
+
+static grub_uint8_t
+grub_png_get_byte (struct grub_png_data *data)
+{
+  grub_uint8_t r;
+
+  if ((data->inside_idat) && (data->idat_remain == 0))
+    {
+      grub_uint32_t len, type;
+
+      do
+       {
+          /* Skip crc checksum.  */
+         grub_png_get_dword (data);
+
+          if (data->file->offset != data->next_offset)
+            {
+              grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                          "png: chunk size error");
+              return 0;
+            }
+
+         len = grub_png_get_dword (data);
+         type = grub_png_get_dword (data);
+         if (type != PNG_CHUNK_IDAT)
+           {
+             grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                         "png: unexpected end of data");
+             return 0;
+           }
+
+          data->next_offset = data->file->offset + len + 4;
+       }
+      while (len == 0);
+      data->idat_remain = len;
+    }
+
+  r = 0;
+  grub_file_read (data->file, (char *) &r, 1);
+
+  if (data->inside_idat)
+    data->idat_remain--;
+
+  return r;
+}
+
+static int
+grub_png_get_bits (struct grub_png_data *data, int num)
+{
+  int code, shift;
+
+  if (data->bit_count == 0)
+    {
+      data->bit_save = grub_png_get_byte (data);
+      data->bit_count = 8;
+    }
+
+  code = 0;
+  shift = 0;
+  while (grub_errno == 0)
+    {
+      int n;
+
+      n = data->bit_count;
+      if (n > num)
+       n = num;
+
+      code += (int) (data->bit_save & ((1 << n) - 1)) << shift;
+      num -= n;
+      if (!num)
+       {
+         data->bit_count -= n;
+         data->bit_save >>= n;
+         break;
+       }
+
+      shift += n;
+
+      data->bit_save = grub_png_get_byte (data);
+      data->bit_count = 8;
+    }
+
+  return code;
+}
+
+static grub_err_t
+grub_png_decode_image_header (struct grub_png_data *data)
+{
+  int color_type;
+  int color_bits;
+
+  data->image_width = grub_png_get_dword (data);
+  data->image_height = grub_png_get_dword (data);
+
+  if ((!data->image_height) || (!data->image_width))
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid image size");
+
+  color_bits = grub_png_get_byte (data);
+  if ((color_bits != 8) && (color_bits != 16))
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                       "png: bit depth must be 8 or 16");
+  data->is_16bit = (color_bits == 16);
+
+  color_type = grub_png_get_byte (data);
+  if (color_type == PNG_COLOR_TYPE_RGB)
+    {
+      if (grub_video_bitmap_create (data->bitmap, data->image_width,
+                                   data->image_height,
+                                   GRUB_VIDEO_BLIT_FORMAT_RGB_888))
+       return grub_errno;
+      data->bpp = 3;
+    }
+  else if (color_type == PNG_COLOR_TYPE_RGBA)
+    {
+      if (grub_video_bitmap_create (data->bitmap, data->image_width,
+                                   data->image_height,
+                                   GRUB_VIDEO_BLIT_FORMAT_RGBA_8888))
+       return grub_errno;
+      data->bpp = 4;
+    }
+  else
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                      "png: color type not supported");
+
+  if (data->is_16bit)
+    {
+      data->bpp <<= 1;
+
+      data->image_data = grub_malloc (data->image_height *
+                                      data->image_width *  data->bpp);
+      if (grub_errno)
+        return grub_errno;
+
+      data->cur_rgb = data->image_data;
+    }
+  else
+    {
+      data->image_data = 0;
+      data->cur_rgb = (*data->bitmap)->data;
+    }
+
+  data->raw_bytes = data->image_height * (data->image_width + 1) * data->bpp;
+
+  data->cur_colume = 0;
+  data->first_line = 1;
+
+  if (grub_png_get_byte (data) != PNG_COMPRESSION_BASE)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                      "png: compression method not supported");
+
+  if (grub_png_get_byte (data) != PNG_FILTER_TYPE_BASE)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                      "png: filter method not supported");
+
+  if (grub_png_get_byte (data) != PNG_INTERLACE_NONE)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                      "png: interlace method not supported");
+
+  /* Skip crc checksum.  */
+  grub_png_get_dword (data);
+
+  return grub_errno;
+}
+
+/* Order of the bit length code lengths.  */
+static const grub_uint8_t bitorder[] = {
+  16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+};
+
+/* Copy lengths for literal codes 257..285.  */
+static const int cplens[] = {
+  3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+  35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+};
+
+/* Extra bits for literal codes 257..285.  */
+static const grub_uint8_t cplext[] = {
+  0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+  3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99
+};                             /* 99==invalid  */
+
+/* Copy offsets for distance codes 0..29.  */
+static const int cpdist[] = {
+  1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+  257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+  8193, 12289, 16385, 24577
+};
+
+/* Extra bits for distance codes.  */
+static const grub_uint8_t cpdext[] = {
+  0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+  7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+  12, 12, 13, 13
+};
+
+static void
+grub_png_init_huff_table (struct huff_table *ht, int cur_maxlen,
+                         int *cur_values, int *cur_maxval, int *cur_offset)
+{
+  ht->values = cur_values;
+  ht->maxval = cur_maxval;
+  ht->offset = cur_offset;
+  ht->num_values = 0;
+  ht->max_length = cur_maxlen;
+  grub_memset (cur_maxval, 0, sizeof (int) * cur_maxlen);
+}
+
+static void
+grub_png_insert_huff_item (struct huff_table *ht, int code, int len)
+{
+  int i, n;
+
+  if (len == 0)
+    return;
+
+  if (len > ht->max_length)
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid code length");
+      return;
+    }
+
+  n = 0;
+  for (i = len; i < ht->max_length; i++)
+    n += ht->maxval[i];
+
+  for (i = 0; i < n; i++)
+    ht->values[ht->num_values - i] = ht->values[ht->num_values - i - 1];
+
+  ht->values[ht->num_values - n] = code;
+  ht->num_values++;
+  ht->maxval[len - 1]++;
+}
+
+static void
+grub_png_build_huff_table (struct huff_table *ht)
+{
+  int base, ofs, i;
+
+  base = 0;
+  ofs = 0;
+  for (i = 0; i < ht->max_length; i++)
+    {
+      base += ht->maxval[i];
+      ofs += ht->maxval[i];
+
+      ht->maxval[i] = base;
+      ht->offset[i] = ofs - base;
+
+      base <<= 1;
+    }
+}
+
+static int
+grub_png_get_huff_code (struct grub_png_data *data, struct huff_table *ht)
+{
+  int code, i;
+
+  code = 0;
+  for (i = 0; i < ht->max_length; i++)
+    {
+      code = (code << 1) + grub_png_get_bits (data, 1);
+      if (code < ht->maxval[i])
+       return ht->values[code + ht->offset[i]];
+    }
+  return 0;
+}
+
+static grub_err_t
+grub_png_init_fixed_block (struct grub_png_data *data)
+{
+  int i;
+
+  grub_png_init_huff_table (&data->code_table, DEFLATE_HUFF_LEN,
+                           data->code_values, data->code_maxval,
+                           data->code_offset);
+
+  for (i = 0; i < 144; i++)
+    grub_png_insert_huff_item (&data->code_table, i, 8);
+
+  for (; i < 256; i++)
+    grub_png_insert_huff_item (&data->code_table, i, 9);
+
+  for (; i < 280; i++)
+    grub_png_insert_huff_item (&data->code_table, i, 7);
+
+  for (; i < DEFLATE_HLIT_MAX; i++)
+    grub_png_insert_huff_item (&data->code_table, i, 8);
+
+  grub_png_build_huff_table (&data->code_table);
+
+  grub_png_init_huff_table (&data->dist_table, DEFLATE_HUFF_LEN,
+                           data->dist_values, data->dist_maxval,
+                           data->dist_offset);
+
+  for (i = 0; i < DEFLATE_HDIST_MAX; i++)
+    grub_png_insert_huff_item (&data->dist_table, i, 5);
+
+  grub_png_build_huff_table (&data->dist_table);
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_png_init_dynamic_block (struct grub_png_data *data)
+{
+  int nl, nd, nb, i, prev;
+  struct huff_table cl;
+  int cl_values[sizeof (bitorder)];
+  int cl_maxval[8];
+  int cl_offset[8];
+  grub_uint8_t lens[DEFLATE_HCLEN_MAX];
+
+  nl = DEFLATE_HLIT_BASE + grub_png_get_bits (data, 5);
+  nd = DEFLATE_HDIST_BASE + grub_png_get_bits (data, 5);
+  nb = DEFLATE_HCLEN_BASE + grub_png_get_bits (data, 4);
+
+  if ((nl > DEFLATE_HLIT_MAX) || (nd > DEFLATE_HDIST_MAX) ||
+      (nb > DEFLATE_HCLEN_MAX))
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: too much data");
+
+  grub_png_init_huff_table (&cl, 8, cl_values, cl_maxval, cl_offset);
+
+  for (i = 0; i < nb; i++)
+    lens[bitorder[i]] = grub_png_get_bits (data, 3);
+
+  for (; i < DEFLATE_HCLEN_MAX; i++)
+    lens[bitorder[i]] = 0;
+
+  for (i = 0; i < DEFLATE_HCLEN_MAX; i++)
+    grub_png_insert_huff_item (&cl, i, lens[i]);
+
+  grub_png_build_huff_table (&cl);
+
+  grub_png_init_huff_table (&data->code_table, DEFLATE_HUFF_LEN,
+                           data->code_values, data->code_maxval,
+                           data->code_offset);
+
+  grub_png_init_huff_table (&data->dist_table, DEFLATE_HUFF_LEN,
+                           data->dist_values, data->dist_maxval,
+                           data->dist_offset);
+
+  prev = 0;
+  for (i = 0; i < nl + nd; i++)
+    {
+      int n, code;
+      struct huff_table *ht;
+
+      if (grub_errno)
+       return grub_errno;
+
+      if (i < nl)
+       {
+         ht = &data->code_table;
+         code = i;
+       }
+      else
+       {
+         ht = &data->dist_table;
+         code = i - nl;
+       }
+
+      n = grub_png_get_huff_code (data, &cl);
+      if (n < 16)
+       {
+         grub_png_insert_huff_item (ht, code, n);
+         prev = n;
+       }
+      else if (n == 16)
+       {
+         int c;
+
+         c = 3 + grub_png_get_bits (data, 2);
+         while (c > 0)
+           {
+             grub_png_insert_huff_item (ht, code++, prev);
+             i++;
+             c--;
+           }
+         i--;
+       }
+      else if (n == 17)
+       i += 3 + grub_png_get_bits (data, 3) - 1;
+      else
+       i += 11 + grub_png_get_bits (data, 7) - 1;
+    }
+
+  grub_png_build_huff_table (&data->code_table);
+  grub_png_build_huff_table (&data->dist_table);
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_png_output_byte (struct grub_png_data *data, grub_uint8_t n)
+{
+  int row_bytes;
+
+  if (--data->raw_bytes < 0)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "image size overflown");
+
+  if (data->cur_colume == 0)
+    {
+      if (n >= PNG_FILTER_VALUE_LAST)
+       return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid filter value");
+
+      data->cur_filter = n;
+    }
+  else
+    *(data->cur_rgb++) = n;
+
+  data->cur_colume++;
+  row_bytes = data->image_width * data->bpp;
+  if (data->cur_colume == row_bytes + 1)
+    {
+      grub_uint8_t *blank_line = NULL;
+      grub_uint8_t *cur = data->cur_rgb - row_bytes;
+      grub_uint8_t *left = cur;
+      grub_uint8_t *up;
+
+      if (data->first_line)
+       {
+         blank_line = grub_malloc (row_bytes);
+         if (blank_line == NULL)
+           return grub_errno;
+
+         grub_memset (blank_line, 0, row_bytes);
+         up = blank_line;
+       }
+      else
+       up = cur - row_bytes;
+
+      switch (data->cur_filter)
+       {
+       case PNG_FILTER_VALUE_SUB:
+         {
+           int i;
+
+           cur += data->bpp;
+           for (i = data->bpp; i < row_bytes; i++, cur++, left++)
+             *cur += *left;
+
+           break;
+         }
+       case PNG_FILTER_VALUE_UP:
+         {
+           int i;
+
+           for (i = 0; i < row_bytes; i++, cur++, up++)
+             *cur += *up;
+
+           break;
+         }
+       case PNG_FILTER_VALUE_AVG:
+         {
+           int i;
+
+           for (i = 0; i < data->bpp; i++, cur++, up++)
+             *cur += *up >> 1;
+
+           for (; i < row_bytes; i++, cur++, up++, left++)
+             *cur += ((int) *up + (int) *left) >> 1;
+
+           break;
+         }
+       case PNG_FILTER_VALUE_PAETH:
+         {
+           int i;
+           grub_uint8_t *upper_left = up;
+
+           for (i = 0; i < data->bpp; i++, cur++, up++)
+             *cur += *up;
+
+           for (; i < row_bytes; i++, cur++, up++, left++, upper_left++)
+             {
+               int a, b, c, pa, pb, pc;
+
+                a = *left;
+                b = *up;
+                c = *upper_left;
+
+                pa = b - c;
+                pb = a - c;
+                pc = pa + pb;
+
+                if (pa < 0)
+                  pa = -pa;
+
+                if (pb < 0)
+                  pb = -pb;
+
+                if (pc < 0)
+                  pc = -pc;
+
+                *cur += ((pa <= pb) && (pa <= pc)) ? a : (pb <= pc) ? b : c;
+             }
+         }
+       }
+
+      if (blank_line)
+       grub_free (blank_line);
+
+      data->cur_colume = 0;
+      data->first_line = 0;
+    }
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_png_read_dynamic_block (struct grub_png_data *data)
+{
+  while (grub_errno == 0)
+    {
+      int n;
+
+      n = grub_png_get_huff_code (data, &data->code_table);
+      if (n < 256)
+       {
+         data->slide[data->wp] = n;
+         grub_png_output_byte (data, n);
+
+         data->wp++;
+         if (data->wp >= WSIZE)
+           data->wp = 0;
+       }
+      else if (n == 256)
+       break;
+      else
+       {
+         int len, dist, pos;
+
+         n -= 257;
+         len = cplens[n];
+         if (cplext[n])
+           len += grub_png_get_bits (data, cplext[n]);
+
+         n = grub_png_get_huff_code (data, &data->dist_table);
+         dist = cpdist[n];
+         if (cpdext[n])
+           dist += grub_png_get_bits (data, cpdext[n]);
+
+         pos = data->wp - dist;
+         if (pos < 0)
+           pos += WSIZE;
+
+         while (len > 0)
+           {
+             data->slide[data->wp] = data->slide[pos];
+             grub_png_output_byte (data, data->slide[data->wp]);
+
+             data->wp++;
+             if (data->wp >= WSIZE)
+               data->wp = 0;
+
+             pos++;
+             if (pos >= WSIZE)
+               pos = 0;
+
+             len--;
+           }
+       }
+    }
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_png_decode_image_data (struct grub_png_data *data)
+{
+  grub_uint8_t cmf, flg;
+  int final;
+
+  cmf = grub_png_get_byte (data);
+  flg = grub_png_get_byte (data);
+
+  if ((cmf & 0xF) != Z_DEFLATED)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                      "png: only support deflate compression method");
+
+  if (flg & Z_FLAG_DICT)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                      "png: dictionary not supported");
+
+  do
+    {
+      int block_type;
+
+      final = grub_png_get_bits (data, 1);
+      block_type = grub_png_get_bits (data, 2);
+
+      switch (block_type)
+       {
+       case INFLATE_STORED:
+         {
+           grub_uint16_t i, len;
+
+           data->bit_count = 0;
+           len = grub_png_get_byte (data);
+           len += ((grub_uint16_t) grub_png_get_byte (data)) << 8;
+
+            /* Skip NLEN field.  */
+           grub_png_get_byte (data);
+           grub_png_get_byte (data);
+
+           for (i = 0; i < len; i++)
+             grub_png_output_byte (data, grub_png_get_byte (data));
+
+           break;
+         }
+
+       case INFLATE_FIXED:
+          grub_png_init_fixed_block (data);
+         grub_png_read_dynamic_block (data);
+         break;
+
+       case INFLATE_DYNAMIC:
+         grub_png_init_dynamic_block (data);
+         grub_png_read_dynamic_block (data);
+         break;
+
+       default:
+         return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                            "png: unknown block type");
+       }
+    }
+  while ((!final) && (grub_errno == 0));
+
+  /* Skip adler checksum.  */
+  grub_png_get_dword (data);
+
+  /* Skip crc checksum.  */
+  grub_png_get_dword (data);
+
+  return grub_errno;
+}
+
+static const grub_uint8_t png_magic[8] =
+  { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0x0a };
+
+static void
+grub_png_convert_image (struct grub_png_data *data)
+{
+  int i;
+  grub_uint8_t *d1, *d2;
+
+  d1 = (*data->bitmap)->data;
+  d2 = data->image_data + 1;
+
+  /* Only copy the upper 8 bit.  */
+  for (i = 0; i < (data->image_width * data->image_height * data->bpp >> 1);
+       i++, d1++, d2+=2)
+    *d1 = *d2;
+}
+
+static grub_err_t
+grub_png_decode_png (struct grub_png_data *data)
+{
+  grub_uint8_t magic[8];
+
+  if (grub_file_read (data->file, (char *) &magic[0], 8) != 8)
+    return grub_errno;
+
+  if (grub_memcmp (magic, png_magic, sizeof (png_magic)))
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: not a png file");
+
+  while (1)
+    {
+      grub_uint32_t len, type;
+
+      len = grub_png_get_dword (data);
+      type = grub_png_get_dword (data);
+      data->next_offset = data->file->offset + len + 4;
+
+      switch (type)
+       {
+       case PNG_CHUNK_IHDR:
+         grub_png_decode_image_header (data);
+         break;
+
+       case PNG_CHUNK_IDAT:
+         data->inside_idat = 1;
+         data->idat_remain = len;
+         data->bit_count = 0;
+
+         grub_png_decode_image_data (data);
+
+         data->inside_idat = 0;
+         break;
+
+       case PNG_CHUNK_IEND:
+          if (data->is_16bit)
+            grub_png_convert_image (data);
+
+         return grub_errno;
+
+       default:
+         grub_file_seek (data->file, data->file->offset + len + 4);
+       }
+
+      if (grub_errno)
+        break;
+
+      if (data->file->offset != data->next_offset)
+        return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                           "png: chunk size error");
+    }
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_video_reader_png (struct grub_video_bitmap **bitmap,
+                      const char *filename)
+{
+  grub_file_t file;
+  struct grub_png_data *data;
+
+  file = grub_buffile_open (filename, 0);
+  if (!file)
+    return grub_errno;
+
+  data = grub_malloc (sizeof (*data));
+  if (data != NULL)
+    {
+      grub_memset (data, 0, sizeof (*data));
+      data->file = file;
+      data->bitmap = bitmap;
+
+      grub_png_decode_png (data);
+
+      grub_free (data->image_data);
+      grub_free (data);
+    }
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_video_bitmap_destroy (*bitmap);
+      *bitmap = 0;
+    }
+
+  grub_file_close (file);
+  return grub_errno;
+}
+
+#if defined(PNG_DEBUG)
+static grub_err_t
+grub_cmd_pngtest (struct grub_arg_list *state __attribute__ ((unused)),
+                 int argc, char **args)
+{
+  struct grub_video_bitmap *bitmap = 0;
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
+
+  grub_video_reader_png (&bitmap, args[0]);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
+  grub_video_bitmap_destroy (bitmap);
+
+  return GRUB_ERR_NONE;
+}
+#endif
+
+static struct grub_video_bitmap_reader png_reader = {
+  .extension = ".png",
+  .reader = grub_video_reader_png,
+  .next = 0
+};
+
+GRUB_MOD_INIT (video_reader_png)
+{
+  grub_video_bitmap_reader_register (&png_reader);
+#if defined(PNG_DEBUG)
+  grub_register_command ("pngtest", grub_cmd_pngtest,
+                        GRUB_COMMAND_FLAG_BOTH, "pngtest FILE",
+                        "Tests loading of PNG bitmap.", 0);
+#endif
+}
+
+GRUB_MOD_FINI (video_reader_png)
+{
+#if defined(PNG_DEBUG)
+  grub_unregister_command ("pngtest");
+#endif
+  grub_video_bitmap_reader_unregister (&png_reader);
+}
diff --git a/video/readers/tga.c b/video/readers/tga.c
new file mode 100644 (file)
index 0000000..de56008
--- /dev/null
@@ -0,0 +1,495 @@
+/*
+ *  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/>.
+ */
+
+#include <grub/bitmap.h>
+#include <grub/types.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/arg.h>
+#include <grub/bufio.h>
+
+/* Uncomment following define to enable TGA debug.  */
+//#define TGA_DEBUG
+
+#if defined(TGA_DEBUG)
+#define dump_int_field(x) grub_printf( #x " = %d (0x%04x)\n", x, x);
+#endif
+
+enum
+{
+  GRUB_TGA_IMAGE_TYPE_NONE = 0,
+  GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_INDEXCOLOR = 1,
+  GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR = 2,
+  GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_BLACK_AND_WHITE = 3,
+  GRUB_TGA_IMAGE_TYPE_RLE_INDEXCOLOR = 9,
+  GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR = 10,
+  GRUB_TGA_IMAGE_TYPE_RLE_BLACK_AND_WHITE = 11,
+};
+
+enum
+{
+  GRUB_TGA_COLOR_MAP_TYPE_NONE = 0,
+  GRUB_TGA_COLOR_MAP_TYPE_INCLUDED = 1
+};
+
+enum
+{
+  GRUB_TGA_IMAGE_ORIGIN_RIGHT = 0x10,
+  GRUB_TGA_IMAGE_ORIGIN_TOP   = 0x20
+};
+
+struct grub_tga_header
+{
+  grub_uint8_t id_length;
+  grub_uint8_t color_map_type;
+  grub_uint8_t image_type;
+
+  /* Color Map Specification.  */
+  grub_uint16_t color_map_first_index;
+  grub_uint16_t color_map_length;
+  grub_uint8_t color_map_bpp;
+
+  /* Image Specification.  */
+  grub_uint16_t image_x_origin;
+  grub_uint16_t image_y_origin;
+  grub_uint16_t image_width;
+  grub_uint16_t image_height;
+  grub_uint8_t image_bpp;
+  grub_uint8_t image_descriptor;
+} __attribute__ ((packed));
+
+static grub_err_t
+tga_load_truecolor_rle_R8G8B8 (struct grub_video_bitmap *bitmap,
+                               struct grub_tga_header *header,
+                               grub_file_t file)
+{
+  unsigned int x;
+  unsigned int y;
+  grub_uint8_t type;
+  grub_uint8_t *ptr;
+  grub_uint8_t tmp[4]; /* Size should be max_bpp / 8.  */
+  grub_uint8_t bytes_per_pixel;
+
+  bytes_per_pixel = header->image_bpp / 8;
+
+  for (y = 0; y < header->image_height; y++)
+    {
+      ptr = bitmap->data;
+      if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
+        ptr += y * bitmap->mode_info.pitch;
+      else
+        ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
+
+      for (x = 0; x < header->image_width;)
+        {
+          if (grub_file_read (file, (char *)&type, sizeof (type)) != sizeof(type))
+            return grub_errno;
+
+          if (type & 0x80)
+            {
+              /* RLE-encoded packet.  */
+              type &= 0x7f;
+              type++;
+
+              if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel)
+                  != bytes_per_pixel)
+                return grub_errno;
+
+              while (type)
+                {
+                  if (x < header->image_width)
+                    {
+                      ptr[0] = tmp[2];
+                      ptr[1] = tmp[1];
+                      ptr[2] = tmp[0];
+                      ptr += 3;
+                    }
+
+                  type--;
+                  x++;
+                }
+            }
+          else
+            {
+              /* RAW-encoded packet.  */
+              type++;
+
+              while (type)
+                {
+                  if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel)
+                      != bytes_per_pixel)
+                    return grub_errno;
+
+                  if (x < header->image_width)
+                    {
+                      ptr[0] = tmp[2];
+                      ptr[1] = tmp[1];
+                      ptr[2] = tmp[0];
+                      ptr += 3;
+                    }
+
+                  type--;
+                  x++;
+                }
+            }
+        }
+    }
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+tga_load_truecolor_rle_R8G8B8A8 (struct grub_video_bitmap *bitmap,
+                                 struct grub_tga_header *header,
+                                 grub_file_t file)
+{
+  unsigned int x;
+  unsigned int y;
+  grub_uint8_t type;
+  grub_uint8_t *ptr;
+  grub_uint8_t tmp[4]; /* Size should be max_bpp / 8.  */
+  grub_uint8_t bytes_per_pixel;
+
+  bytes_per_pixel = header->image_bpp / 8;
+
+  for (y = 0; y < header->image_height; y++)
+    {
+      ptr = bitmap->data;
+      if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
+        ptr += y * bitmap->mode_info.pitch;
+      else
+        ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
+
+      for (x = 0; x < header->image_width;)
+        {
+          if (grub_file_read (file, (char *)&type, sizeof (type)) != sizeof(type))
+            return grub_errno;
+
+          if (type & 0x80)
+            {
+              /* RLE-encoded packet.  */
+              type &= 0x7f;
+              type++;
+
+              if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel)
+                  != bytes_per_pixel)
+                return grub_errno;
+
+              while (type)
+                {
+                  if (x < header->image_width)
+                    {
+                      ptr[0] = tmp[2];
+                      ptr[1] = tmp[1];
+                      ptr[2] = tmp[0];
+                      ptr[3] = tmp[3];
+                      ptr += 4;
+                    }
+
+                  type--;
+                  x++;
+                }
+            }
+          else
+            {
+              /* RAW-encoded packet.  */
+              type++;
+
+              while (type)
+                {
+                  if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel)
+                      != bytes_per_pixel)
+                    return grub_errno;
+
+                  if (x < header->image_width)
+                    {
+                      ptr[0] = tmp[2];
+                      ptr[1] = tmp[1];
+                      ptr[2] = tmp[0];
+                      ptr[3] = tmp[3];
+                      ptr += 4;
+                    }
+
+                  type--;
+                  x++;
+                }
+            }
+        }
+    }
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+tga_load_truecolor_R8G8B8 (struct grub_video_bitmap *bitmap,
+                           struct grub_tga_header *header,
+                           grub_file_t file)
+{
+  unsigned int x;
+  unsigned int y;
+  grub_uint8_t *ptr;
+  grub_uint8_t tmp[4]; /* Size should be max_bpp / 8.  */
+  grub_uint8_t bytes_per_pixel;
+
+  bytes_per_pixel = header->image_bpp / 8;
+
+  for (y = 0; y < header->image_height; y++)
+    {
+      ptr = bitmap->data;
+      if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
+        ptr += y * bitmap->mode_info.pitch;
+      else
+        ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
+
+      for (x = 0; x < header->image_width; x++)
+        {
+          if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel)
+              != bytes_per_pixel)
+            return grub_errno;
+
+          ptr[0] = tmp[2];
+          ptr[1] = tmp[1];
+          ptr[2] = tmp[0];
+
+          ptr += 3;
+        }
+    }
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+tga_load_truecolor_R8G8B8A8 (struct grub_video_bitmap *bitmap,
+                             struct grub_tga_header *header,
+                             grub_file_t file)
+{
+  unsigned int x;
+  unsigned int y;
+  grub_uint8_t *ptr;
+  grub_uint8_t tmp[4]; /* Size should be max_bpp / 8.  */
+  grub_uint8_t bytes_per_pixel;
+
+  bytes_per_pixel = header->image_bpp / 8;
+
+  for (y = 0; y < header->image_height; y++)
+    {
+      ptr = bitmap->data;
+      if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
+        ptr += y * bitmap->mode_info.pitch;
+      else
+        ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
+
+      for (x = 0; x < header->image_width; x++)
+        {
+          if (grub_file_read (file, (char *)&tmp[0], bytes_per_pixel)
+              != bytes_per_pixel)
+            return grub_errno;
+
+          ptr[0] = tmp[2];
+          ptr[1] = tmp[1];
+          ptr[2] = tmp[0];
+          ptr[3] = tmp[3];
+
+          ptr += 4;
+        }
+    }
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_video_reader_tga (struct grub_video_bitmap **bitmap,
+                       const char *filename)
+{
+  grub_file_t file;
+  grub_ssize_t pos;
+  struct grub_tga_header header;
+  int has_alpha;
+
+  file = grub_buffile_open (filename, 0);
+  if (! file)
+    return grub_errno;
+
+  /* TGA Specification states that we SHOULD start by reading
+     ID from end of file, but we really don't care about that as we are
+     not going to support developer area & extensions at this point.  */
+
+  /* Read TGA header from beginning of file.  */
+  if (grub_file_read (file, (char*)&header, sizeof (header)) 
+      != sizeof (header))
+    {
+      grub_file_close (file);
+      return grub_errno;
+    }
+
+  /* Skip ID field.  */
+  pos = grub_file_tell (file);
+  pos += header.id_length;
+  grub_file_seek (file, pos);
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_file_close (file);
+      return grub_errno;
+    }
+
+#if defined(TGA_DEBUG)
+  grub_printf("tga: header\n");
+  dump_int_field(header.id_length);
+  dump_int_field(header.color_map_type);
+  dump_int_field(header.image_type);
+  dump_int_field(header.color_map_first_index);
+  dump_int_field(header.color_map_length);
+  dump_int_field(header.color_map_bpp);
+  dump_int_field(header.image_x_origin);
+  dump_int_field(header.image_y_origin);
+  dump_int_field(header.image_width);
+  dump_int_field(header.image_height);
+  dump_int_field(header.image_bpp);
+  dump_int_field(header.image_descriptor);
+#endif
+
+  /* Check that bitmap encoding is supported.  */
+  switch (header.image_type)
+    {
+      case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR:
+      case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR:
+        break;
+
+      default:
+        grub_file_close (file);
+        return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                           "Unsupported bitmap format (unknown encoding).");
+    }
+
+  /* Check that bitmap depth is supported.  */
+  switch (header.image_bpp)
+    {
+      case 24:
+        has_alpha = 0;
+        break;
+
+      case 32:
+        has_alpha = 1;
+        break;
+
+      default:
+        grub_file_close (file);
+        return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                           "Unsupported bitmap format (bpp=%d).",
+                           header.image_bpp);
+    }
+
+  /* Allocate bitmap.  If there is alpha information store it too.  */
+  if (has_alpha)
+    {
+      grub_video_bitmap_create (bitmap, header.image_width,
+                                header.image_height,
+                                GRUB_VIDEO_BLIT_FORMAT_RGBA_8888);
+      if (grub_errno != GRUB_ERR_NONE)
+        {
+          grub_file_close (file);
+          return grub_errno;
+        }
+
+      /* Load bitmap data.  */
+      switch (header.image_type)
+        {
+          case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR:
+            tga_load_truecolor_R8G8B8A8 (*bitmap, &header, file);
+            break;
+
+          case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR:
+            tga_load_truecolor_rle_R8G8B8A8 (*bitmap, &header, file);
+            break;
+        }
+    }
+  else
+    {
+      grub_video_bitmap_create (bitmap, header.image_width,
+                                header.image_height,
+                                GRUB_VIDEO_BLIT_FORMAT_RGB_888);
+      if (grub_errno != GRUB_ERR_NONE)
+        {
+          grub_file_close (file);
+          return grub_errno;
+        }
+
+      /* Load bitmap data.  */
+      switch (header.image_type)
+        {
+          case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR:
+            tga_load_truecolor_R8G8B8 (*bitmap, &header, file);
+            break;
+
+          case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR:
+            tga_load_truecolor_rle_R8G8B8 (*bitmap, &header, file);
+            break;
+        }
+    }
+
+  /* If there was a loading problem, destroy bitmap.  */
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_video_bitmap_destroy (*bitmap);
+      *bitmap = 0;
+    }
+
+  grub_file_close (file);
+  return grub_errno;
+}
+
+#if defined(TGA_DEBUG)
+static grub_err_t
+grub_cmd_tgatest (struct grub_arg_list *state __attribute__ ((unused)),
+                  int argc, char **args)
+{
+  struct grub_video_bitmap *bitmap = 0;
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
+
+  grub_video_reader_tga (&bitmap, args[0]);  
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
+  grub_video_bitmap_destroy (bitmap);
+
+  return GRUB_ERR_NONE;
+}
+#endif
+
+static struct grub_video_bitmap_reader tga_reader = {
+  .extension = ".tga",
+  .reader = grub_video_reader_tga,
+  .next = 0
+};
+
+GRUB_MOD_INIT(video_reader_tga)
+{
+  grub_video_bitmap_reader_register (&tga_reader);
+#if defined(TGA_DEBUG)
+  grub_register_command ("tgatest", grub_cmd_tgatest, GRUB_COMMAND_FLAG_BOTH,
+                         "tgatest FILE", "Tests loading of TGA bitmap.", 0);
+#endif
+}
+
+GRUB_MOD_FINI(video_reader_tga)
+{
+#if defined(TGA_DEBUG)
+  grub_unregister_command ("tgatest");
+#endif
+  grub_video_bitmap_reader_unregister (&tga_reader);
+}
diff --git a/video/video.c b/video/video.c
new file mode 100644 (file)
index 0000000..49e6cb9
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/video.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+
+/* The list of video adapters registered to system.  */
+static grub_video_adapter_t grub_video_adapter_list;
+
+/* Active video adapter.  */
+static grub_video_adapter_t grub_video_adapter_active;
+
+/* Register video driver.  */
+void
+grub_video_register (grub_video_adapter_t adapter)
+{
+  adapter->next = grub_video_adapter_list;
+  grub_video_adapter_list = adapter;
+}
+
+/* Unregister video driver.  */
+void
+grub_video_unregister (grub_video_adapter_t adapter)
+{
+  grub_video_adapter_t *p, q;
+
+  for (p = &grub_video_adapter_list, q = *p; q; p = &(q->next), q = q->next)
+    if (q == adapter)
+      {
+        *p = q->next;
+        break;
+      }
+}
+
+/* Iterate thru all registered video drivers.  */
+void
+grub_video_iterate (int (*hook) (grub_video_adapter_t adapter))
+{
+  grub_video_adapter_t p;
+
+  for (p = grub_video_adapter_list; p; p = p->next)
+    if (hook (p))
+      break;
+}
+
+/* Setup specified video mode.  */
+grub_err_t
+grub_video_setup (unsigned int width, unsigned int height,
+                  unsigned int mode_type)
+{
+  grub_video_adapter_t p;
+
+  /* De-activate last set video adapter.  */
+  if (grub_video_adapter_active)
+    {
+      /* Finalize adapter.  */
+      grub_video_adapter_active->fini ();
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;
+
+      /* Mark active adapter as not set.  */
+      grub_video_adapter_active = 0;
+    }
+
+  /* Loop thru all possible video adapter trying to find requested mode.  */
+  for (p = grub_video_adapter_list; p; p = p->next)
+    {
+      /* Try to initialize adapter, if it fails, skip to next adapter.  */
+      p->init ();
+      if (grub_errno != GRUB_ERR_NONE)
+        {
+          grub_errno = GRUB_ERR_NONE;
+          continue;
+        }
+
+      /* Try to initialize video mode.  */
+      p->setup (width, height, mode_type);
+      if (grub_errno == GRUB_ERR_NONE)
+        {
+          /* Valid mode found from adapter, and it has been activated.
+             Specify it as active adapter.  */
+          grub_video_adapter_active = p;
+          return GRUB_ERR_NONE;
+        }
+      else
+        grub_errno = GRUB_ERR_NONE;
+
+      /* No valid mode found in this adapter, finalize adapter.  */
+      p->fini ();
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;
+    }
+
+  /* We couldn't find suitable adapter for specified mode.  */
+  return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                     "Can't locate valid adapter for mode");
+}
+
+/* Restore back to initial mode (where applicable).  */
+grub_err_t
+grub_video_restore (void)
+{
+  if (grub_video_adapter_active)
+    {
+      grub_video_adapter_active->fini ();
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;
+
+      grub_video_adapter_active = 0;
+    }
+  return GRUB_ERR_NONE;
+}
+
+/* Get information about active video mode.  */
+grub_err_t
+grub_video_get_info (struct grub_video_mode_info *mode_info)
+{
+  if (! grub_video_adapter_active)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+  /* If mode_info is NULL just report that video adapter is active.  */
+  if (! mode_info)
+    {
+      grub_errno = GRUB_ERR_NONE;
+      return grub_errno;
+    }
+
+  return grub_video_adapter_active->get_info (mode_info);
+}
+
+/* Determine optimized blitting formation for specified video mode info.  */
+enum grub_video_blit_format
+grub_video_get_blit_format (struct grub_video_mode_info *mode_info)
+{
+  /* Check if we have any known 32 bit modes.  */
+  if (mode_info->bpp == 32)
+    {
+      if ((mode_info->red_mask_size == 8)
+         && (mode_info->red_field_pos == 16)
+         && (mode_info->green_mask_size == 8)
+         && (mode_info->green_field_pos == 8)
+         && (mode_info->blue_mask_size == 8)
+         && (mode_info->blue_field_pos == 0))
+       {
+         return GRUB_VIDEO_BLIT_FORMAT_BGRA_8888;
+       }
+      else if ((mode_info->red_mask_size == 8)
+              && (mode_info->red_field_pos == 0)
+              && (mode_info->green_mask_size == 8)
+              && (mode_info->green_field_pos == 8)
+              && (mode_info->blue_mask_size == 8)
+              && (mode_info->blue_field_pos == 16))
+       {
+         return GRUB_VIDEO_BLIT_FORMAT_RGBA_8888;
+       }
+    }
+  /* Check if we have any known 24 bit modes.  */
+  else if (mode_info->bpp == 24)
+    {
+      if ((mode_info->red_mask_size == 8)
+         && (mode_info->red_field_pos == 16)
+         && (mode_info->green_mask_size == 8)
+         && (mode_info->green_field_pos == 8)
+         && (mode_info->blue_mask_size == 8)
+         && (mode_info->blue_field_pos == 0))
+       {
+         return GRUB_VIDEO_BLIT_FORMAT_BGR_888;
+       }
+      else if ((mode_info->red_mask_size == 8)
+              && (mode_info->red_field_pos == 0)
+              && (mode_info->green_mask_size == 8)
+              && (mode_info->green_field_pos == 8)
+              && (mode_info->blue_mask_size == 8)
+              && (mode_info->blue_field_pos == 16))
+       {
+         return GRUB_VIDEO_BLIT_FORMAT_RGB_888;
+       }
+    }
+  /* Check if we have any known 16 bit modes.  */
+  else if (mode_info->bpp == 16)
+    {
+      if ((mode_info->red_mask_size == 5)
+         && (mode_info->red_field_pos == 11)
+         && (mode_info->green_mask_size == 6)
+         && (mode_info->green_field_pos == 5)
+         && (mode_info->blue_mask_size == 5)
+         && (mode_info->blue_field_pos == 0))
+       {
+         return GRUB_VIDEO_BLIT_FORMAT_BGR_565;
+       }
+      else if ((mode_info->red_mask_size == 5)
+              && (mode_info->red_field_pos == 0)
+              && (mode_info->green_mask_size == 6)
+              && (mode_info->green_field_pos == 5)
+              && (mode_info->blue_mask_size == 5)
+              && (mode_info->blue_field_pos == 11))
+       {
+         return GRUB_VIDEO_BLIT_FORMAT_RGB_565;
+       }
+    }
+
+  /* Backup route.  Unknown format.  */
+
+  /* If there are more than 8 bits per color, assume RGB(A) mode.  */
+  if (mode_info->bpp > 8)
+    {
+      if (mode_info->reserved_mask_size > 0)
+       {
+         return GRUB_VIDEO_BLIT_FORMAT_RGBA;
+       }
+      else
+       {
+         return GRUB_VIDEO_BLIT_FORMAT_RGB;
+       }
+    }
+
+  /* Assume as indexcolor mode.  */
+  return GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR;
+}
+
+/* Set new indexed color palette entries.  */
+grub_err_t
+grub_video_set_palette (unsigned int start, unsigned int count,
+                        struct grub_video_palette_data *palette_data)
+{
+  if (! grub_video_adapter_active)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+  return grub_video_adapter_active->set_palette (start, count, palette_data);
+}
+
+/* Get indexed color palette entries.  */
+grub_err_t
+grub_video_get_palette (unsigned int start, unsigned int count,
+                        struct grub_video_palette_data *palette_data)
+{
+  if (! grub_video_adapter_active)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+  return grub_video_adapter_active->get_palette (start, count, palette_data);
+}
+
+/* Set viewport dimensions.  */
+grub_err_t
+grub_video_set_viewport (unsigned int x, unsigned int y,
+                         unsigned int width, unsigned int height)
+{
+  if (! grub_video_adapter_active)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+  return grub_video_adapter_active->set_viewport (x, y, width, height);
+}
+
+/* Get viewport dimensions.  */
+grub_err_t
+grub_video_get_viewport (unsigned int *x, unsigned int *y,
+                         unsigned int *width, unsigned int *height)
+{
+  if (! grub_video_adapter_active)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+  return grub_video_adapter_active->get_viewport (x, y, width, height);
+}
+
+/* Map color name to adapter specific color.  */
+grub_video_color_t
+grub_video_map_color (grub_uint32_t color_name)
+{
+  if (! grub_video_adapter_active)
+    return 0;
+
+  return grub_video_adapter_active->map_color (color_name);
+}
+
+/* Map RGB value to adapter specific color.  */
+grub_video_color_t
+grub_video_map_rgb (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue)
+{
+  if (! grub_video_adapter_active)
+    return 0;
+
+  return grub_video_adapter_active->map_rgb (red, green, blue);
+}
+
+/* Map RGBA value to adapter specific color.  */
+grub_video_color_t
+grub_video_map_rgba (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue,
+                     grub_uint8_t alpha)
+{
+  if (! grub_video_adapter_active)
+    return 0;
+
+  return grub_video_adapter_active->map_rgba (red, green, blue, alpha);
+}
+
+/* Unmap video color back to RGBA components.  */
+grub_err_t
+grub_video_unmap_color (grub_video_color_t color, grub_uint8_t *red,
+                        grub_uint8_t *green, grub_uint8_t *blue,
+                        grub_uint8_t *alpha)
+{
+  if (! grub_video_adapter_active)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+  return grub_video_adapter_active->unmap_color (color,
+                                                 red,
+                                                 green,
+                                                 blue,
+                                                 alpha);
+}
+
+/* Fill rectangle using specified color.  */
+grub_err_t
+grub_video_fill_rect (grub_video_color_t color, int x, int y,
+                      unsigned int width, unsigned int height)
+{
+  if (! grub_video_adapter_active)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+  return grub_video_adapter_active->fill_rect (color, x, y, width, height);
+}
+
+/* Blit bitmap to screen.  */
+grub_err_t
+grub_video_blit_bitmap (struct grub_video_bitmap *bitmap,
+                        enum grub_video_blit_operators oper,
+                        int x, int y, int offset_x, int offset_y,
+                        unsigned int width, unsigned int height)
+{
+  if (! grub_video_adapter_active)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+  return grub_video_adapter_active->blit_bitmap (bitmap, oper, x, y,
+                                                 offset_x, offset_y,
+                                                 width, height);
+}
+
+/* Blit render target to active render target.  */
+grub_err_t
+grub_video_blit_render_target (struct grub_video_render_target *target,
+                               enum grub_video_blit_operators oper,
+                               int x, int y, int offset_x, int offset_y,
+                               unsigned int width, unsigned int height)
+{
+  if (! grub_video_adapter_active)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+  return grub_video_adapter_active->blit_render_target (target, oper, x, y,
+                                                        offset_x, offset_y,
+                                                        width, height);
+}
+
+/* Scroll viewport and fill new areas with specified color.  */
+grub_err_t
+grub_video_scroll (grub_video_color_t color, int dx, int dy)
+{
+  if (! grub_video_adapter_active)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+  return grub_video_adapter_active->scroll (color, dx, dy);
+}
+
+/* Swap buffers (swap active render target).  */
+grub_err_t
+grub_video_swap_buffers (void)
+{
+  if (! grub_video_adapter_active)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+  return grub_video_adapter_active->swap_buffers ();
+}
+
+/* Create new render target.  */
+grub_err_t
+grub_video_create_render_target (struct grub_video_render_target **result,
+                                 unsigned int width, unsigned int height,
+                                 unsigned int mode_type)
+{
+  if (! grub_video_adapter_active)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+  return grub_video_adapter_active->create_render_target (result,
+                                                          width, height,
+                                                          mode_type);
+}
+
+/* Delete render target.  */
+grub_err_t
+grub_video_delete_render_target (struct grub_video_render_target *target)
+{
+  if (! grub_video_adapter_active)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+  return grub_video_adapter_active->delete_render_target (target);
+}
+
+/* Set active render target.  */
+grub_err_t
+grub_video_set_active_render_target (struct grub_video_render_target *target)
+{
+  if (! grub_video_adapter_active)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+  return grub_video_adapter_active->set_active_render_target (target);
+}
+
+/* Get active render target.  */
+grub_err_t
+grub_video_get_active_render_target (struct grub_video_render_target **target)
+{
+  if (! grub_video_adapter_active)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
+
+  return grub_video_adapter_active->get_active_render_target (target);
+}
+
+/* Initialize Video API module.  */
+GRUB_MOD_INIT(video_video)
+{
+  grub_video_adapter_active = 0;
+  grub_video_adapter_list = 0;
+}
+
+/* Finalize Video API module.  */
+GRUB_MOD_FINI(video_video)
+{
+}