grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH]: grub: Add sparc64 support code.


From: David Miller
Subject: [PATCH]: grub: Add sparc64 support code.
Date: Sun, 19 Apr 2009 17:42:18 -0700 (PDT)

Ok, this gets sparc64 building again and adds the necessary seperation
of the mkdevicemap implementation so we can use escaped openfirmware
path names instead of "(hdX)" and "(fdX)" as is customary on i386.

Code is added to convert OS path names into openfirmware device
paths.  With some very simple changes, this code can be adapted
to powerpc.  This is not done yet, but when it is then grub will
no longer depend upon the 'ofpathname' program on powerpc.

We're pretty close to working on sparc64 with this patch.  What
remains is:

1) Fleshing out and implementing the OF path name escaping for
   device map entries.

2) Fixing how FS UUID code can open the same device multiple times
   at once, which doesn't work on OpenBoot.

I have patches for #2 and will begin working on #1 now.

2009-04-19  David S. Miller  <address@hidden>

        * util/sparc64/ieee1275/misc.c: New file.
        * util/sparc64/ieee1275/grub-setup.c: New file.
        * util/sparc64/ieee1275/grub-ofpathname.c: New file.
        * util/sparc64/ieee1275/grub-mkimage.c: New file.
        * util/sparc64/ieee1275/grub-install.in: New file.
        * util/ieee1275/ofpath.c: New file.
        * util/ieee1275/devicemap.c: New file.
        * util/devicemap.c: New file.
        * util/deviceiter.c: New file.
        * kern/sparc64/ieee1275/init.c: New file.
        * include/grub/util/ofpath.h: New file.
        * include/grub/util/deviceiter.h: New file.
        * util/grub-mkdevicemap.c: Include deviceiter.h.
        Implement using grub_util_emit_devicemap_entry and
        grub_util_iterate_devices.
        * conf/i386-corebook.rmk: Build util/deviceiter.c and
        util/devicemap.c into grub-mkdevicemap
        * conf/i386-efi.rmk: Likewise.
        * conf/i386-ieee1275.rmk: Likewise.
        * conf/i386-pc.rmk: Likewise.
        * conf/powerpc-ieee1275.rmk: Likewise.
        * conf/sparc64-ieee1275.rmk: Add rules to build boot block
        images and installation utilities.  Build kernel as image
        instead of as elf binary.  Use common rules as much as possible.
        
Signed-off-by: David S. Miller <address@hidden>
---
 conf/i386-coreboot.rmk                  |    3 +-
 conf/i386-efi.rmk                       |    3 +-
 conf/i386-ieee1275.rmk                  |    3 +-
 conf/i386-pc.rmk                        |    3 +-
 conf/powerpc-ieee1275.rmk               |    3 +-
 conf/sparc64-ieee1275.rmk               |  368 +++++++------------
 include/grub/util/deviceiter.h          |   11 +
 include/grub/util/ofpath.h              |    6 +
 kern/sparc64/ieee1275/init.c            |  161 ++++++++
 util/deviceiter.c                       |  621 ++++++++++++++++++++++++++++++
 util/devicemap.c                        |   13 +
 util/grub-mkdevicemap.c                 |  589 +----------------------------
 util/ieee1275/devicemap.c               |   13 +
 util/ieee1275/ofpath.c                  |  415 ++++++++++++++++++++
 util/sparc64/ieee1275/grub-install.in   |  276 ++++++++++++++
 util/sparc64/ieee1275/grub-mkimage.c    |  294 +++++++++++++++
 util/sparc64/ieee1275/grub-ofpathname.c |   39 ++
 util/sparc64/ieee1275/grub-setup.c      |  625 +++++++++++++++++++++++++++++++
 util/sparc64/ieee1275/misc.c            |   33 ++
 19 files changed, 2663 insertions(+), 816 deletions(-)
 create mode 100644 include/grub/util/deviceiter.h
 create mode 100644 include/grub/util/ofpath.h
 create mode 100644 kern/sparc64/ieee1275/init.c
 create mode 100644 util/deviceiter.c
 create mode 100644 util/devicemap.c
 create mode 100644 util/ieee1275/devicemap.c
 create mode 100644 util/ieee1275/ofpath.c
 create mode 100644 util/sparc64/ieee1275/grub-install.in
 create mode 100644 util/sparc64/ieee1275/grub-mkimage.c
 create mode 100644 util/sparc64/ieee1275/grub-ofpathname.c
 create mode 100644 util/sparc64/ieee1275/grub-setup.c
 create mode 100644 util/sparc64/ieee1275/misc.c

diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index f7cb58d..1284fe4 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -51,7 +51,8 @@ sbin_UTILITIES += grub-emu
 endif
 
 # For grub-mkdevicemap.
-grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/deviceiter.c \
+       util/devicemap.c util/misc.c
 
 # For grub-emu.
 util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index fdb83b8..717683b 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -28,7 +28,8 @@ util/i386/efi/grub-mkimage.c_DEPENDENCIES = Makefile
 #      kern/fs.c kern/env.c fs/fshelp.c
 
 # For grub-mkdevicemap.
-grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/deviceiter.c \
+       util/devicemap.c util/misc.c
 
 # For grub-emu.
 util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index cb41cce..cb32c73 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -50,7 +50,8 @@ sbin_UTILITIES += grub-emu
 endif
 
 # For grub-mkdevicemap.
-grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/deviceiter.c \
+       util/devicemap.c util/misc.c
 
 # For grub-emu.
 util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 265b250..d74a5fa 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -114,7 +114,8 @@ grub_setup_SOURCES = util/i386/pc/grub-setup.c 
util/hostdisk.c      \
        grub_setup_init.c
 
 # For grub-mkdevicemap.
-grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/deviceiter.c \
+       util/devicemap.c util/misc.c
 
 # For grub-emu.
 util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk
index d8d35d5..84f91d8 100644
--- a/conf/powerpc-ieee1275.rmk
+++ b/conf/powerpc-ieee1275.rmk
@@ -35,7 +35,8 @@ sbin_UTILITIES += grub-emu
 endif
  
 # For grub-mkdevicemap.
-grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/deviceiter.c \
+       util/devicemap.c util/misc.c
 
 # For grub-emu
 util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk
index 029bca2..e1929d1 100644
--- a/conf/sparc64-ieee1275.rmk
+++ b/conf/sparc64-ieee1275.rmk
@@ -1,162 +1,156 @@
 
 # -*- makefile -*-
 
-COMMON_ASFLAGS = -nostdinc
-COMMON_CFLAGS = -ggdb -ffreestanding -m64 -mno-app-regs
-COMMON_LDFLAGS = -melf64_sparc -nostdlib
+COMMON_ASFLAGS = -nostdinc -m64
+COMMON_CFLAGS = -ffreestanding -m64 -mno-app-regs
+COMMON_LDFLAGS = -melf64_sparc -nostdlib -mno-relax
 
 # 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
+
+# For boot.img.
+boot_img_SOURCES = boot/sparc64/ieee1275/boot.S
+boot_img_ASFLAGS = $(COMMON_ASFLAGS)
+boot_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-Ttext,0x4000
+boot_img_FORMAT = a.out-sunos-big
+
+# For diskboot.img.
+diskboot_img_SOURCES = boot/sparc64/ieee1275/diskboot.S
+diskboot_img_ASFLAGS = $(COMMON_ASFLAGS)
+diskboot_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-Ttext,0x4200
+diskboot_img_FORMAT = binary
 
 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
+kernel_img_HEADERS = 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 \
+       list.h handler.h command.h \
+       sparc64/libgcc.h ieee1275/ieee1275.h machine/kernel.h \
+       sparc64/ieee1275/ieee1275.h
+kernel_img_SOURCES = kern/sparc64/ieee1275/crt0.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/rescue.c kern/term.c                 \
+       kern/list.c kern/handler.c kern/command.c kern/corecmd.c        \
+       kern/sparc64/ieee1275/ieee1275.c                                \
+       kern/sparc64/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/sparc64/dl.c     \
+       kern/generic/millisleep.c kern/time.c                           \
+       symlist.c kern/sparc64/cache.S
+kernel_img_CFLAGS = $(COMMON_CFLAGS)
+kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,0x200000,-Bstatic,-melf64_sparc 
-static-libgcc -lgcc
+kernel_img_FORMAT = binary
+
+symlist.c: $(addprefix include/grub/,$(kernel_img_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
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_img_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
+bin_UTILITIES = grub-mkimage
+sbin_UTILITIES = grub-setup grub-mkdevicemap grub-ofpathname
+ifeq ($(enable_grub_emu), yes)
+sbin_UTILITIES += grub-emu
+endif
 
 # For grub-mkimage.
 grub_mkimage_SOURCES = util/sparc64/ieee1275/grub-mkimage.c util/misc.c \
         util/resolve.c 
 
+# For grub-setup.
+util/sparc64/ieee1275/grub-setup.c_DEPENDENCIES = grub_setup_init.h
+grub_setup_SOURCES = util/sparc64/ieee1275/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/amiga.c partmap/apple.c partmap/pc.c            \
+       partmap/sun.c partmap/acorn.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/deviceiter.c \
+       util/ieee1275/ofpath.c util/ieee1275/devicemap.c util/misc.c
+
+# For grub-ofpathname.
+grub_ofpathname_SOURCES = util/sparc64/ieee1275/grub-ofpathname.c \
+       util/ieee1275/ofpath.c util/misc.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 commands/boot.c kern/main.c kern/misc.c   \
-#      kern/parser.c kern/partition.c kern/rescue.c kern/term.c        \
-#      kern/list.c kern/handler.c                                      \
-#      normal/arg.c normal/cmdline.c normal/command.c normal/datetime.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                                  \
-#      commands/parttool.c parttool/pcpart.c                           \
-#      util/sparc64/ieee1275/misc.c
+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/handler.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/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                                         \
+       kern/list.c kern/handler.c                                      \
+       lib/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/sparc64/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/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/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 -static-libgcc -lgcc
-
-# 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)
+# Scripts.
+sbin_SCRIPTS = grub-install
 
-# For affs.mod.
-affs_mod_SOURCES = fs/affs.c
-affs_mod_CFLAGS = $(COMMON_CFLAGS)
-affs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For grub-install.
+grub_install_SOURCES = util/sparc64/ieee1275/grub-install.in
 
-# For sfs.mod.
-sfs_mod_SOURCES = fs/sfs.c
-sfs_mod_CFLAGS = $(COMMON_CFLAGS)
-sfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# Modules.
+pkglib_MODULES = halt.mod \
+       linux.mod \
+       normal.mod \
+       reboot.mod \
+       memdisk.mod \
+       lsmmap.mod
 
-# 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)
+linux_mod_SOURCES = loader/sparc64/ieee1275/linux.c
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
 #
 # Only arch dependant part of normal.mod will be here. Common part for
@@ -166,7 +160,7 @@ sfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
 # 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_mod_SOURCES = lib/arg.c normal/cmdline.c normal/command.c       \
        normal/datetime.c normal/completion.c normal/execute.c          \
        normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
        normal/handler.c normal/menu_text.c                             \
@@ -179,116 +173,24 @@ 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
+# For reboot.mod.
 reboot_mod_SOURCES = commands/reboot.c
 reboot_mod_CFLAGS = $(COMMON_CFLAGS)
 reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
-# For halt.mod
+# 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 memdisk.mod.
+memdisk_mod_SOURCES = disk/memdisk.c
+memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
-# For gzio.mod.
-gzio_mod_SOURCES = io/gzio.c
-gzio_mod_CFLAGS = $(COMMON_CFLAGS)
-gzio_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For lsmmap.mod
+lsmmap_mod_SOURCES = commands/lsmmap.c
+lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
+lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
-# For test.mod.
-test_mod_SOURCES = commands/test.c
-test_mod_CFLAGS = $(COMMON_CFLAGS)
-test_mod_LDFLAGS = $(COMMON_LDFLAGS)
+include $(srcdir)/conf/common.mk
diff --git a/include/grub/util/deviceiter.h b/include/grub/util/deviceiter.h
new file mode 100644
index 0000000..a8af03c
--- /dev/null
+++ b/include/grub/util/deviceiter.h
@@ -0,0 +1,11 @@
+#ifndef GRUB_DEVICEITER_MACHINE_UTIL_HEADER
+#define GRUB_DEVICEITER_MACHINE_UTIL_HEADER    1
+
+#include <config.h>
+
+void grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, 
int),
+                               int floppy_disks);
+void grub_util_emit_devicemap_entry (FILE *fp, char *name, int is_floppy,
+                                    int *num_fd, int *num_hd);
+
+#endif /* ! GRUB_DEVICEITER_MACHINE_UTIL_HEADER */
diff --git a/include/grub/util/ofpath.h b/include/grub/util/ofpath.h
new file mode 100644
index 0000000..78f24d7
--- /dev/null
+++ b/include/grub/util/ofpath.h
@@ -0,0 +1,6 @@
+#ifndef GRUB_OFPATH_MACHINE_UTIL_HEADER
+#define GRUB_OFPATH_MACHINE_UTIL_HEADER        1
+
+char *grub_util_devname_to_ofpath (char *devname);
+
+#endif /* ! GRUB_OFPATH_MACHINE_UTIL_HEADER */
diff --git a/kern/sparc64/ieee1275/init.c b/kern/sparc64/ieee1275/init.c
new file mode 100644
index 0000000..5114f76
--- /dev/null
+++ b/kern/sparc64/ieee1275/init.c
@@ -0,0 +1,161 @@
+/*  init.c -- Initialize GRUB on SPARC64.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/kernel.h>
+#include <grub/mm.h>
+#include <grub/env.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/time.h>
+#include <grub/machine/console.h>
+#include <grub/machine/kernel.h>
+#include <grub/machine/time.h>
+#include <grub/ieee1275/ofdisk.h>
+#include <grub/ieee1275/ieee1275.h>
+
+void
+grub_exit (void)
+{
+  grub_ieee1275_exit ();
+}
+
+static grub_uint64_t
+ieee1275_get_time_ms (void)
+{
+  grub_uint32_t msecs = 0;
+
+  grub_ieee1275_milliseconds (&msecs);
+
+  return msecs;
+}
+
+grub_uint32_t
+grub_get_rtc (void)
+{
+  return ieee1275_get_time_ms ();
+}
+
+grub_addr_t
+grub_arch_modules_addr (void)
+{
+  extern char _end[];
+  return (grub_addr_t) _end;
+}
+
+void
+grub_machine_set_prefix (void)
+{
+  if (grub_prefix[0] != '(')
+    {
+      char bootpath[IEEE1275_MAX_PATH_LEN];
+      grub_ssize_t actual;
+      char *prefix, *path;
+
+      if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath",
+                                     &bootpath, sizeof (bootpath), &actual))
+       {
+         /* Should never happen.  */
+         grub_printf ("/chosen/bootpath property missing!\n");
+         grub_env_set ("prefix", "");
+         return;
+       }
+
+      /* Transform an OF device path to a GRUB path.  */
+      prefix = grub_ieee1275_encode_devname (bootpath);
+
+      path = grub_malloc (grub_strlen (grub_prefix)
+                         + grub_strlen (prefix)
+                         + 2);
+      grub_sprintf(path, "%s%s", prefix, grub_prefix);
+
+      grub_strcpy (grub_prefix, path);
+
+      grub_free (path);
+      grub_free (prefix);
+    }
+
+  grub_env_set ("prefix", grub_prefix);
+}
+
+static void
+grub_heap_init (void)
+{
+  grub_mm_init_region ((void *)(long)0x4000UL, 0x200000 - 0x4000);
+}
+
+static void
+grub_parse_cmdline (void)
+{
+  grub_ssize_t actual;
+  char args[256];
+
+  if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args,
+                                 sizeof args, &actual) == 0
+      && actual > 1)
+    {
+      int i = 0;
+
+      while (i < actual)
+       {
+         char *command = &args[i];
+         char *end;
+         char *val;
+
+         end = grub_strchr (command, ';');
+         if (end == 0)
+           i = actual; /* No more commands after this one.  */
+         else
+           {
+             *end = '\0';
+             i += end - command + 1;
+             while (grub_isspace(args[i]))
+               i++;
+           }
+
+         /* Process command.  */
+         val = grub_strchr (command, '=');
+         if (val)
+           {
+             *val = '\0';
+             grub_env_set (command, val + 1);
+           }
+       }
+    }
+}
+
+void
+grub_machine_init (void)
+{
+  grub_ieee1275_init ();
+  grub_console_init ();
+  grub_heap_init ();
+
+  grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0);
+  grub_ofdisk_init ();
+
+  grub_parse_cmdline ();
+  grub_install_get_time_ms (ieee1275_get_time_ms);
+}
+
+void
+grub_machine_fini (void)
+{
+  grub_ofdisk_fini ();
+  grub_console_fini ();
+}
diff --git a/util/deviceiter.c b/util/deviceiter.c
new file mode 100644
index 0000000..a36ad31
--- /dev/null
+++ b/util/deviceiter.c
@@ -0,0 +1,621 @@
+/* deviceiter.c - iterate over system devices */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008 Free Software 
Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  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>
+#include <grub/util/deviceiter.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)
+{
+#ifdef __sparc__
+  sprintf (name, "/dev/vdisk%c", unit + 'a');
+#else
+  sprintf (name, "/dev/vd%c", unit + 'a');
+#endif
+}
+
+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;
+}
+
+void
+grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
+                          int floppy_disks)
+{
+  int i;
+
+  /* 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 (hook (name, 1))
+       return;
+    }
+
+#ifdef __linux__
+  if (have_devfs ())
+    {
+      i = 0;
+      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", i++);
+         if (stat (discn, &st) < 0)
+           break;
+
+         if (realpath (discn, name))
+           {
+             strcat (name, "/disc");
+             if (hook (name, 0))
+               return;
+           }
+       }
+      return;
+    }
+#endif /* __linux__ */
+
+  /* IDE disks.  */
+  for (i = 0; i < 20; i++)
+    {
+      char name[16];
+
+      get_ide_disk_name (name, i);
+      if (check_device (name))
+       {
+         if (hook (name, 0))
+           return;
+       }
+    }
+
+#ifdef __linux__
+  /* Virtio disks.  */
+  for (i = 0; i < 20; i++)
+    {
+      char name[16];
+
+      get_virtio_disk_name (name, i);
+      if (check_device (name))
+       {
+         if (hook (name, 0))
+           return;
+       }
+    }
+
+  /* ATARAID disks.  */
+  for (i = 0; i < 8; i++)
+    {
+      char name[20];
+
+      get_ataraid_disk_name (name, i);
+      if (check_device (name))
+       {
+         if (hook (name, 0))
+           return;
+        }
+    }
+
+  /* Xen virtual block devices.  */
+  for (i = 0; i < 16; i++)
+    {
+      char name[16];
+
+      get_xvd_disk_name (name, i);
+      if (check_device (name))
+       {
+         if (hook (name, 0))
+           return;
+       }
+    }
+#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))
+       {
+         if (hook (name, 0))
+           return;
+       }
+    }
+
+#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))
+             {
+               if (hook (name, 0))
+                 return;
+             }
+         }
+      }
+  }
+
+  /* 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))
+             {
+               if (hook (name, 0))
+                 return;
+             }
+         }
+      }
+  }
+
+  /* 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))
+             {
+               if (hook (name, 0))
+                 return;
+             }
+         }
+      }
+  }
+
+  /* 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))
+         {
+           if (hook (name, 0))
+             return;
+         }
+      }
+  }
+
+  /* MultiMediaCard (MMC).  */
+  for (i = 0; i < 10; i++)
+    {
+      char name[16];
+
+      get_mmc_disk_name (name, i);
+      if (check_device (name))
+       {
+         if (hook (name, 0))
+           return;
+       }
+    }
+#endif /* __linux__ */
+}
+
diff --git a/util/devicemap.c b/util/devicemap.c
new file mode 100644
index 0000000..c618644
--- /dev/null
+++ b/util/devicemap.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+#include <grub/util/deviceiter.h>
+
+void
+grub_util_emit_devicemap_entry (FILE *fp, char *name, int is_floppy,
+                               int *num_fd, int *num_hd)
+{
+    if (is_floppy)
+      fprintf (fp, "(fd%d)\t%s\n", (*num_fd)++, name);
+    else
+      fprintf (fp, "(hd%d)\t%s\n", (*num_hd)++, name);
+}
diff --git a/util/grub-mkdevicemap.c b/util/grub-mkdevicemap.c
index fa8b158..4f544f8 100644
--- a/util/grub-mkdevicemap.c
+++ b/util/grub-mkdevicemap.c
@@ -30,385 +30,26 @@
 #include <limits.h>
 
 #include <grub/util/misc.h>
+#include <grub/util/deviceiter.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)
+make_device_map (const char *device_map, int floppy_disks)
 {
-  char buf[512];
+  int num_hd = 0;
+  int num_fd = 0;
   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__ */
+  auto int process_device (const char *name, int is_floppy);
 
-#if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
-# ifdef CDIOCCLRDEBUG
-  if (ioctl (fileno (fp), CDIOCCLRDEBUG, 0) >= 0)
+  int process_device (const char *name, int is_floppy)
+  {
+    grub_util_emit_devicemap_entry (fp, (char *) name,
+                                   is_floppy, &num_fd, &num_hd);
     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;
@@ -418,215 +59,7 @@ make_device_map (const char *device_map, int floppy_disks)
   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__ */
+  grub_util_iterate_devices (process_device, floppy_disks);
 
   if (fp != stdout)
     fclose (fp);
diff --git a/util/ieee1275/devicemap.c b/util/ieee1275/devicemap.c
new file mode 100644
index 0000000..8e6eb39
--- /dev/null
+++ b/util/ieee1275/devicemap.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <grub/types.h>
+#include <grub/util/deviceiter.h>
+#include <grub/util/ofpath.h>
+
+void
+grub_util_emit_devicemap_entry (FILE *fp, char *name, int is_floppy UNUSED,
+                               int *num_fd UNUSED, int *num_hd UNUSED)
+{
+  const char *ofpath = grub_util_devname_to_ofpath (name);
+
+  fprintf(fp, "(%s)\t%s\n", ofpath, name);
+}
diff --git a/util/ieee1275/ofpath.c b/util/ieee1275/ofpath.c
new file mode 100644
index 0000000..7b464bf
--- /dev/null
+++ b/util/ieee1275/ofpath.c
@@ -0,0 +1,415 @@
+/* ofpath.c - calculate OpenFirmware path names given an OS device */
+/*
+ *  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/>.
+ */
+
+#undef OFPATH_STANDALONE
+
+#ifndef OFPATH_STANDALONE
+#include <grub/types.h>
+#include <grub/util/misc.h>
+#include <grub/util/ofpath.h>
+#endif
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <malloc.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+
+#ifdef OFPATH_STANDALONE
+#define UNUSED __attribute__((unused))
+#define xmalloc malloc
+void
+grub_util_error (const char *fmt, ...)
+{
+  va_list ap;
+
+  fprintf (stderr, "ofpath: error: ");
+  va_start (ap, fmt);
+  vfprintf (stderr, fmt, ap);
+  va_end (ap);
+  fputc ('\n', stderr);
+  exit (1);
+}
+
+#endif
+
+static void
+kill_trailing_dir(char *path)
+{
+  char *end = path + strlen(path) - 1;
+
+  while (end >= path)
+    {
+      if (*end != '/')
+       {
+         end--;
+         continue;
+       }
+      *end = '\0';
+      break;
+    }
+}
+
+static void
+trim_newline (char *path)
+{
+  char *end = path + strlen(path) - 1;
+
+  while (*end == '\n')
+    *end-- = '\0';
+}
+
+#define OF_PATH_MAX    256
+
+static void
+find_obppath(char *of_path, const char *sysfs_path_orig)
+{
+  char *sysfs_path, *path;
+
+  sysfs_path = xmalloc (PATH_MAX);
+  path = xmalloc (PATH_MAX);
+
+  strcpy(sysfs_path, sysfs_path_orig);
+  while (1)
+    {
+      int fd;
+
+      snprintf(path, PATH_MAX, "%s/obppath", sysfs_path);
+#if 0
+      printf("Trying %s\n", path);
+#endif
+
+      fd = open(path, O_RDONLY);
+      if (fd < 0)
+       {
+         kill_trailing_dir(sysfs_path);
+         if (!strcmp(sysfs_path, "/sys"))
+           grub_util_error("'obppath' not found in parent dirs of %s",
+                           sysfs_path_orig);
+         continue;
+       }
+      memset(of_path, 0, OF_PATH_MAX);
+      read(fd, of_path, OF_PATH_MAX);
+      close(fd);
+
+      trim_newline(of_path);
+      break;
+    }
+
+  free (path);
+  free (sysfs_path);
+}
+
+static void
+block_device_get_sysfs_path_and_link(const char *devicenode,
+                                    char *sysfs_path, int sysfs_path_len)
+{
+  char *rpath = xmalloc (PATH_MAX);
+
+  snprintf(sysfs_path, sysfs_path_len, "/sys/block/%s", devicenode);
+
+  if (!realpath (sysfs_path, rpath))
+    grub_util_error ("Cannot get the real path of `%s'", sysfs_path);
+
+  strcat(rpath, "/device");
+
+  if (!realpath (rpath, sysfs_path))
+    grub_util_error ("Cannot get the real path of `%s'", rpath);
+
+  free (rpath);
+}
+
+static const char *
+trailing_digits (const char *p)
+{
+  const char *end;
+
+  end = p + strlen(p) - 1;
+  while (end >= p)
+    {
+      if (! isdigit(*end))
+       break;
+      end--;
+    }
+
+  return end + 1;
+}
+
+static void
+__of_path_common(char *of_path, char *sysfs_path,
+                const char *device, int devno)
+{
+  const char *digit_string;
+  char disk[64];
+
+  find_obppath(of_path, sysfs_path);
+
+  digit_string = trailing_digits (device);
+  if (*digit_string == '\0')
+    {
+      sprintf(disk, "/address@hidden", devno);
+    }
+  else
+    {
+      int part;
+
+      sscanf(digit_string, "%d", &part);
+      sprintf(disk, "/address@hidden:%c", devno, 'a' + (part - 1));
+    }
+  strcat(of_path, disk);
+}
+
+static char *
+get_basename(char *p)
+{
+  char *ret = p;
+
+  while (*p)
+    {
+      if (*p == '/')
+       ret = p + 1;
+      p++;
+    }
+
+  return ret;
+}
+
+static void
+of_path_of_vdisk(char *of_path,
+                const char *devname UNUSED, const char *device,
+                const char *devnode UNUSED, const char *devicenode)
+{
+  char *sysfs_path, *p;
+  int devno, junk;
+
+  sysfs_path = xmalloc (PATH_MAX);
+  block_device_get_sysfs_path_and_link(devicenode,
+                                      sysfs_path, PATH_MAX);
+  p = get_basename (sysfs_path);
+  sscanf(p, "vdc-port-%d-%d", &devno, &junk);
+  __of_path_common(of_path, sysfs_path, device, devno);
+
+  free (sysfs_path);
+}
+
+static void
+of_path_of_ide(char *of_path,
+              const char *devname UNUSED, const char *device,
+              const char *devnode UNUSED, const char *devicenode)
+{
+  char *sysfs_path, *p;
+  int chan, devno;
+
+  sysfs_path = xmalloc (PATH_MAX);
+  block_device_get_sysfs_path_and_link(devicenode,
+                                      sysfs_path, PATH_MAX);
+  p = get_basename (sysfs_path);
+  sscanf(p, "%d.%d", &chan, &devno);
+
+  __of_path_common(of_path, sysfs_path, device, devno);
+
+  free (sysfs_path);
+}
+
+static int
+vendor_is_ATA(const char *path)
+{
+  int fd, err;
+  char *buf;
+
+  buf = xmalloc (PATH_MAX);
+
+  snprintf(buf, PATH_MAX, "%s/vendor", path);
+  fd = open(buf, O_RDONLY);
+  if (fd < 0)
+    grub_util_error ("Cannot open 'vendor' node of `%s'", path);
+
+  memset(buf, 0, PATH_MAX);
+  err = read(fd, buf, PATH_MAX);
+  if (err < 0)
+    grub_util_error ("Cannot read 'vendor' node of `%s'", path);
+
+  close(fd);
+
+  free (buf);
+
+  if (!strncmp(buf, "ATA", 3))
+    return 1;
+  return 0;
+}
+
+static void
+check_sas (char *sysfs_path, int *tgt)
+{
+  char *ed = strstr (sysfs_path, "end_device");
+  char *p, *q, *path;
+  char phy[16];
+  int fd;
+
+  if (!ed)
+    return;
+
+  /* SAS devices are identified using address@hidden */
+  p = strdup (sysfs_path);
+  ed = strstr(p, "end_device");
+
+  q = ed;
+  while (*q && *q != '/')
+    q++;
+  *q = '\0';
+
+  path = xmalloc (PATH_MAX);
+  sprintf (path, "%s/sas_device:%s/phy_identifier", p, ed);
+
+  fd = open(path, O_RDONLY);
+  if (fd < 0)
+    grub_util_error("Cannot open SAS PHY ID '%s'\n", path);
+
+  memset (phy, 0, sizeof (phy));
+  read (fd, phy, sizeof (phy));
+
+  sscanf (phy, "%d", tgt);
+
+  free (path);
+  free (p);
+}
+
+static void
+of_path_of_scsi(char *of_path,
+               const char *devname UNUSED, const char *device,
+               const char *devnode UNUSED, const char *devicenode)
+{
+  const char *p, *digit_string, *disk_name;
+  int host, bus, tgt, lun;
+  char *sysfs_path, disk[64];
+
+  sysfs_path = xmalloc (PATH_MAX);
+
+  block_device_get_sysfs_path_and_link(devicenode,
+                                      sysfs_path, PATH_MAX);
+  p = get_basename (sysfs_path);
+  sscanf(p, "%d:%d:%d:%d", &host, &bus, &tgt, &lun);
+  check_sas (sysfs_path, &tgt);
+
+  if (vendor_is_ATA(sysfs_path))
+    {
+      __of_path_common(of_path, sysfs_path, device, tgt);
+      free (sysfs_path);
+      return;
+    }
+
+  find_obppath(of_path, sysfs_path);
+  free (sysfs_path);
+
+  if (strstr (of_path, "qlc"))
+    strcat (of_path, "/address@hidden,0");
+
+  if (strstr (of_path, "sbus"))
+    disk_name = "sd";
+  else
+    disk_name = "disk";
+
+  digit_string = trailing_digits (device);
+  if (*digit_string == '\0')
+    {
+      sprintf(disk, "/address@hidden,%d", disk_name, tgt, lun);
+    }
+  else
+    {
+      int part;
+
+      sscanf(digit_string, "%d", &part);
+      sprintf(disk, "/address@hidden,%d:%c", disk_name, tgt, lun, 'a' + (part 
- 1));
+    }
+  strcat(of_path, disk);
+}
+
+static char *
+strip_trailing_digits (const char *p)
+{
+  char *new, *end;
+
+  new = strdup (p);
+  end = new + strlen(new) - 1;
+  while (end >= new)
+    {
+      if (! isdigit(*end))
+       break;
+      *end-- = '\0';
+    }
+
+  return new;
+}
+
+char *
+grub_util_devname_to_ofpath (char *devname)
+{
+  char *name_buf, *device, *devnode, *devicenode, *ofpath;
+
+  name_buf = xmalloc (PATH_MAX);
+  name_buf = realpath (devname, name_buf);
+  if (! name_buf)
+    grub_util_error ("Cannot get the real path of `%s'", devname);
+
+  device = get_basename (devname);
+  devnode = strip_trailing_digits (devname);
+  devicenode = strip_trailing_digits (device);
+
+  ofpath = xmalloc (OF_PATH_MAX);
+
+  if (device[0] == 'h' && device[1] == 'd')
+    of_path_of_ide(ofpath, name_buf, device, devnode, devicenode);
+  else if (device[0] == 's'
+          && (device[1] == 'd' || device[1] == 'r'))
+    of_path_of_scsi(ofpath, name_buf, device, devnode, devicenode);
+  else if (device[0] == 'v' && device[1] == 'd' && device[2] == 'i'
+          && device[3] == 's' && device[4] == 'k')
+    of_path_of_vdisk(ofpath, name_buf, device, devnode, devicenode);
+
+  free (devnode);
+  free (devicenode);
+  free (name_buf);
+
+  return ofpath;
+}
+
+#ifdef OFPATH_STANDALONE
+int main(int argc, char **argv)
+{
+  char *of_path;
+
+  if (argc != 2)
+    {
+      printf("Usage: grub-ofpathname DEVICE\n");
+      return 1;
+    }
+
+  of_path = grub_util_devname_to_ofpath (argv[1]);
+  printf("%s\n", of_path);
+
+  return 0;
+}
+#endif
diff --git a/util/sparc64/ieee1275/grub-install.in 
b/util/sparc64/ieee1275/grub-install.in
new file mode 100644
index 0000000..e2af5e8
--- /dev/null
+++ b/util/sparc64/ieee1275/grub-install.in
@@ -0,0 +1,276 @@
+#! /bin/sh
+
+# Install GRUB on your drive.
+# 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/>.
+
+# Initialize some variables.
+transform="@program_transform_name@"
+
address@hidden@
address@hidden@
address@hidden@
address@hidden@
address@hidden@
address@hidden@
address@hidden@
address@hidden@
address@hidden@
address@hidden@
+pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed 
${transform}`
+
+grub_setup=${sbindir}/`echo grub-setup | 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=
+
+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 <address@hidden>.
+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.
+bootdir=${rootdir}/boot
+grubdir=${bootdir}/`echo grub | sed ${transform}`
+device_map=${grubdir}/device.map
+
+grub_probe="${grub_probe} --device-map=${device_map}"
+
+# Check if GRUB is installed.
+set $grub_setup dummy
+if test -f "$1"; then
+    :
+else
+    echo "$1: Not found." 1>&2
+    exit 1
+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
+
+for file in ${pkglibdir}/*.img; do
+    cp -f $file ${grubdir} || exit 1
+done
+
+# 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}`
+
+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 [ "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
+
+$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
+
+# 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/sparc64/ieee1275/grub-mkimage.c 
b/util/sparc64/ieee1275/grub-mkimage.c
new file mode 100644
index 0000000..247f138
--- /dev/null
+++ b/util/sparc64/ieee1275/grub-mkimage.c
@@ -0,0 +1,294 @@
+/* grub-mkimage.c - make a bootable image */
+/*
+ *  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 <config.h>
+#include <grub/types.h>
+#include <grub/machine/boot.h>
+#include <grub/machine/kernel.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>
+
+static void
+compress_kernel (char *kernel_img, size_t kernel_size,
+                char **core_img, size_t *core_size)
+{
+  /* No compression support yet.  */
+  grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size);
+  *core_img = xmalloc (kernel_size);
+  memcpy (*core_img, kernel_img, kernel_size);
+  *core_size = kernel_size;
+}
+
+static void
+generate_image (const char *dir, const char *prefix, FILE *out, char *mods[], 
char *memdisk_path)
+{
+  size_t kernel_size, total_module_size, memdisk_size, core_size, boot_size, 
offset;
+  char *kernel_path, *kernel_img, *core_img, *boot_path, *boot_img;
+  struct grub_util_path_list *path_list, *p;
+  struct grub_module_info *modinfo;
+  grub_addr_t module_addr;
+  unsigned int num;
+
+  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);
+  for (p = path_list; p; p = p->next)
+    total_module_size += (grub_util_get_image_size (p->name)
+                         + sizeof (struct grub_module_header));
+
+  memdisk_size = 0;
+  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);
+    }
+
+  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_be32 (OBJ_TYPE_ELF);
+      header->size = grub_cpu_to_be32 (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_be32 (OBJ_TYPE_MEMDISK);
+      header->size = grub_cpu_to_be32 (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);
+  num <<= GRUB_DISK_SECTOR_BITS;
+
+  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);
+
+  /* sparc is a big endian architecture.  */
+  *((grub_uint32_t *) (boot_img + GRUB_DISK_SECTOR_SIZE
+                      - GRUB_BOOT_MACHINE_LIST_SIZE + 8))
+    = grub_cpu_to_be32 (num);
+
+  grub_util_write_image (boot_img, boot_size, out);
+  free (boot_img);
+  free (boot_path);
+
+  module_addr = (path_list
+                ? (GRUB_BOOT_MACHINE_IMAGE_ADDRESS + 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_be32 (total_module_size);
+  *((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE))
+    = grub_cpu_to_be32 (kernel_size);
+
+  /* No compression support yet.  */
+  *((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE))
+    = grub_cpu_to_be32 (0);
+
+  grub_util_write_image (core_img, core_size, out);
+  free (kernel_img);
+  free (core_img);
+  free (kernel_path);
+
+  while (path_list)
+    {
+      struct grub_util_path_list *next = path_list->next;
+      free ((void *) path_list->name);
+      free (path_list);
+      path_list = next;
+    }
+}
+
+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/sparc64/ieee1275/grub-ofpathname.c 
b/util/sparc64/ieee1275/grub-ofpathname.c
new file mode 100644
index 0000000..092826c
--- /dev/null
+++ b/util/sparc64/ieee1275/grub-ofpathname.c
@@ -0,0 +1,39 @@
+/* grub-ofpathname.c - Find OpenBOOT path for a given device */
+/*
+ *  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/util/misc.h>
+#include <grub/util/ofpath.h>
+
+int main(int argc, char **argv)
+{
+  char *of_path;
+
+  if (argc != 2)
+    {
+      printf("Usage: grub-ofpathname DEVICE\n");
+      return 1;
+    }
+
+  of_path = grub_util_devname_to_ofpath (argv[1]);
+  printf("%s\n", of_path);
+
+  free (of_path);
+
+  return 0;
+}
diff --git a/util/sparc64/ieee1275/grub-setup.c 
b/util/sparc64/ieee1275/grub-setup.c
new file mode 100644
index 0000000..6ca3a7a
--- /dev/null
+++ b/util/sparc64/ieee1275/grub-setup.c
@@ -0,0 +1,625 @@
+/* grub-setup.c - make GRUB usable */
+/*
+ *  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 <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>
+
+#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>
+
+/* This program fills in various fields inside of the 'boot' and 'core'
+ * image files.
+ *
+ * The 'boot' image needs to know the OBP path name of the root
+ * device.  It also needs to know the initial block number of
+ * 'core' (which is 'diskboot' concatenated with 'kernel' and
+ * all the modules, this is created by grub-mkimage).  This resulting
+ * 'boot' image is 512 bytes in size and is placed in the first block
+ * of a partition.
+ *
+ * The initial 'diskboot' block acts as a loader for the actual GRUB
+ * kernel.  It contains the loading code and then a block list.
+ *
+ * The block list of 'core' starts at the end of the 'diskboot' image
+ * and works it's way backwards towards the end of the code of 'diskboot'.
+ *
+ * We patch up the images with the necessary values and write out the
+ * result.
+ */
+
+#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_uint32_t len;
+} __attribute__ ((packed));
+
+void
+grub_putchar (int c)
+{
+  putchar (c);
+}
+
+int
+grub_getkey (void)
+{
+  return -1;
+}
+
+struct grub_handler_class grub_term_input_class;
+struct grub_handler_class grub_term_output_class;
+
+void
+grub_refresh (void)
+{
+  fflush (stdout);
+}
+
+static void
+setup (const char *prefix, const char *dir,
+       const char *boot_file, const char *core_file,
+       const char *root, const char *dest)
+{
+  char *boot_path, *core_path;
+  char *boot_img, *core_img;
+  size_t boot_size, core_size;
+  grub_uint16_t core_sectors;
+  grub_device_t root_dev, dest_dev;
+  char *boot_devpath;
+  grub_disk_addr_t *kernel_sector;
+  struct boot_blocklist *first_block, *block;
+  char *tmp_img;
+  int i;
+  grub_disk_addr_t first_sector;
+  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;
+
+  auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector,
+                                               unsigned int offset,
+                                               unsigned int length);
+  auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector,
+                                             unsigned int offset,
+                                             unsigned int length);
+
+  void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector,
+                                          unsigned int offset,
+                                          unsigned int length)
+    {
+      grub_util_info ("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 int offset,
+                                        unsigned int length)
+    {
+      struct boot_blocklist *prev = block + 1;
+
+      grub_util_info ("saving <%llu,%u,%u>", sector, offset, length);
+
+      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_be_to_cpu64 (prev->start)
+             + grub_be_to_cpu16 (prev->len)) == sector)
+       prev->len = grub_cpu_to_be16 (grub_be_to_cpu16 (prev->len) + 1);
+      else
+       {
+         block->start = grub_cpu_to_be64 (sector);
+         block->len = grub_cpu_to_be16 (1);
+
+         block--;
+         if (block->len)
+           grub_util_error ("The sectors of the core file are too fragmented");
+       }
+
+      last_length = length;
+    }
+
+  /* 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_devpath = (char *) (boot_img
+                          + GRUB_BOOT_AOUT_HEADER_SIZE
+                          + GRUB_BOOT_MACHINE_BOOT_DEVPATH);
+  kernel_sector = (grub_disk_addr_t *) (boot_img
+                                       + GRUB_BOOT_AOUT_HEADER_SIZE
+                                       + GRUB_BOOT_MACHINE_KERNEL_SECTOR);
+
+  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);
+
+  core_img = grub_util_read_image (core_path);
+  free (core_path);
+
+  /* Have FIRST_BLOCK to point to the first blocklist.  */
+  first_block = (struct boot_blocklist *) (core_img
+                                          + GRUB_DISK_SECTOR_SIZE
+                                          - sizeof (*block));
+
+  grub_util_info ("root is '%s' and dest is '%s'", root, dest);
+
+  /* Open the root device and the destination device.  */
+  grub_util_info ("Opening root");
+  root_dev = grub_device_open (root);
+  if (! root_dev)
+    grub_util_error ("%s", grub_errmsg);
+
+  grub_util_info ("Opening dest");
+  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);
+
+  /* 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 = grub_util_get_path (prefix, 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, (i == 0) ? "" : " again");
+
+      grub_disk_cache_invalidate_all ();
+
+      file = grub_file_open (core_path);
+      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);
+
+  /* Clean out the blocklists.  */
+  block = first_block;
+  while (block->len)
+    {
+      block->start = 0;
+      block->len = 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);
+  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);
+  free (tmp_img);
+
+  *kernel_sector = grub_cpu_to_be64 (first_sector);
+
+  strcpy(boot_devpath, dest);
+
+  grub_util_info ("boot device path %s, prefix is %s, dest is %s",
+                 boot_devpath, prefix, dest);
+
+  /* Write the first two sectors of the core image onto the disk.  */
+  core_path = grub_util_get_path (dir, core_file);
+  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, fp);
+  fclose (fp);
+  free (core_path);
+
+  /* Write the boot image onto the disk.  */
+  if (grub_disk_write (dest_dev->disk, 1, 0, GRUB_DISK_SECTOR_SIZE, boot_img))
+    grub_util_error ("%s", grub_errmsg);
+
+  /* Sync is a Good Thing.  */
+  sync ();
+
+  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);
+}
+
+struct grub_setup_info
+{
+  char *boot_file;
+  char *core_file;
+  char *dir;
+  char *dev_map;
+  char *root_dev;
+  char *prefix;
+  char *dest_dev;
+};
+
+static void
+init_info (struct grub_setup_info *gp)
+{
+  gp->boot_file = NULL;
+  gp->core_file = NULL;
+  gp->dir = NULL;
+  gp->dev_map = NULL;
+  gp->root_dev = NULL;
+  gp->prefix = NULL;
+  gp->dest_dev = NULL;
+}
+
+static int
+parse_options (struct grub_setup_info *gp, int argc, char *argv[])
+{
+  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 (gp->boot_file)
+             free (gp->boot_file);
+
+           gp->boot_file = xstrdup (optarg);
+           break;
+
+         case 'c':
+           if (gp->core_file)
+             free (gp->core_file);
+
+           gp->core_file = xstrdup (optarg);
+           break;
+
+         case 'd':
+           if (gp->dir)
+             free (gp->dir);
+
+           gp->dir = xstrdup (optarg);
+           break;
+
+         case 'm':
+           if (gp->dev_map)
+             free (gp->dev_map);
+
+           gp->dev_map = xstrdup (optarg);
+           break;
+
+         case 'r':
+           if (gp->root_dev)
+             free (gp->root_dev);
+
+           gp->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");
+
+  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);
+    }
+  return 1;
+}
+
+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;
+}
+
+static void
+find_dest_dev (struct grub_setup_info *gp, char *argv[])
+{
+  gp->dest_dev = get_device_name (argv[optind]);
+  if (! gp->dest_dev)
+    {
+      /* Possibly, the user specified an OS device file.  */
+      gp->dest_dev = grub_util_get_grub_dev (argv[optind]);
+      if (! gp->dest_dev)
+       {
+         fprintf (stderr, "Invalid device `%s'.\n", argv[optind]);
+         usage (1);
+       }
+      grub_util_info ("transformed OS device '%s' into GRUB device '%s'",
+                     argv[optind], gp->dest_dev);
+    }
+  else
+    {
+      /* For simplicity.  */
+      gp->dest_dev = xstrdup (gp->dest_dev);
+      grub_util_info ("Using '%s' as GRUB device", gp->dest_dev);
+    }
+}
+
+static void
+check_root_dev (struct grub_setup_info *gp)
+{
+  if (gp->root_dev)
+    {
+      char *tmp = get_device_name (gp->root_dev);
+
+      if (! tmp)
+       grub_util_error ("Invalid root device `%s'", gp->root_dev);
+
+      tmp = xstrdup (tmp);
+      free (gp->root_dev);
+      gp->root_dev = tmp;
+    }
+  else
+    {
+      char *dir = gp->dir ? gp->dir : DEFAULT_DIRECTORY;
+      char *root_device = grub_guess_root_device (dir);
+
+      gp->root_dev = grub_util_get_grub_dev (root_device);
+      if (! gp->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''.");
+       }
+      grub_util_info ("Guessed root device '%s' and root_dev '%s' from "
+                     "dir '%s'", root_device, gp->root_dev, dir);
+    }
+}
+
+static void
+free_memory (struct grub_setup_info *gp)
+{
+  free (gp->boot_file);
+  free (gp->core_file);
+  free (gp->dir);
+  free (gp->dev_map);
+  free (gp->root_dev);
+  free (gp->prefix);
+  free (gp->dest_dev);
+}
+
+int
+main (int argc, char *argv[])
+{
+  struct grub_setup_info ginfo;
+
+  progname = "grub-setup";
+
+  init_info (&ginfo);
+  if (!parse_options (&ginfo, argc, argv))
+    return 0;
+
+  /* Initialize the emulated biosdisk driver.  */
+  grub_util_biosdisk_init (ginfo.dev_map ? ginfo.dev_map : DEFAULT_DEVICE_MAP);
+
+  /* Initialize all modules. */
+  grub_init_all ();
+
+  find_dest_dev (&ginfo, argv);
+
+  ginfo.prefix = grub_get_prefix (ginfo.dir ? : DEFAULT_DIRECTORY);
+
+  check_root_dev (&ginfo);
+
+  /* Do the real work.  */
+  setup (ginfo.prefix,
+        ginfo.dir ? ginfo.dir : DEFAULT_DIRECTORY,
+        ginfo.boot_file ? ginfo.boot_file : DEFAULT_BOOT_FILE,
+        ginfo.core_file ? ginfo.core_file : DEFAULT_CORE_FILE,
+        ginfo.root_dev, ginfo.dest_dev);
+
+  /* Free resources.  */
+  grub_fini_all ();
+
+  free_memory (&ginfo);
+
+  return 0;
+}
diff --git a/util/sparc64/ieee1275/misc.c b/util/sparc64/ieee1275/misc.c
new file mode 100644
index 0000000..99b9513
--- /dev/null
+++ b/util/sparc64/ieee1275/misc.c
@@ -0,0 +1,33 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <setjmp.h>
+
+#include <grub/util/misc.h>
+
+void
+grub_reboot (void)
+{
+  longjmp (main_env, 1);
+}
+
+void
+grub_halt (void)
+{
+  grub_reboot ();
+}
-- 
1.6.2.3





reply via email to

[Prev in Thread] Current Thread [Next in Thread]