commit-grub
[Top][All Lists]
Advanced

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

[2162] 2009-05-02 Vladimir Serbinenko <address@hidden>


From: Vladimir Serbinenko
Subject: [2162] 2009-05-02 Vladimir Serbinenko <address@hidden>
Date: Sat, 02 May 2009 22:40:22 +0000

Revision: 2162
          http://svn.sv.gnu.org/viewvc/?view=rev&root=grub&revision=2162
Author:   phcoder
Date:     2009-05-02 22:40:21 +0000 (Sat, 02 May 2009)
Log Message:
-----------
2009-05-02  Vladimir Serbinenko  <address@hidden>

        Efiemu
 
        * conf/i386-pc.rmk: new modules efiemu, efiemu_acpi, efiemu_pnvram,
        _linux_efi, linux_efi. 
        new files in grub-emu 
        new targets efiemu32.o and efiemu64.o
        * loader/linux_normal_efiemu.c: likewise
        * loader/i386/efi/linux.c: added preliminary efiemu support
        * util/i386/pc/grub-install.in: add efiemu??.o to the list of 
        files to copy
        * include/grub/autoefi.h: new file
        * nclude/grub/i386/efiemu.h: likewise
        * include/grub/i386/pc/efiemu.h: likewise
        * include/grub/efi/api.h: add LL suffix when necessary
        new definitions relating to tables
        * include/grub/efiemu/efiemu.h: new file
        * include/grub/efiemu/runtime.h: likewise
        * efiemu/prepare.c: likewise
        * efiemu/loadcore_common.c: likewise
        * efiemu/loadcore64.c: likewise
        * efiemu/runtime/efiemu.sh: likewise
        * efiemu/runtime/efiemu.S: likewise
        * efiemu/runtime/efiemu.c: likewise
        * efiemu/runtime/config.h: likewise
        * efiemu/prepare32.c: likewise
        * efiemu/main.c: likewise
        * efiemu/modules/pnvram.c: likewise
        * efiemu/modules/i386: likewise
        * efiemu/modules/i386/pc: likewise
        * efiemu/modules/acpi.c: likewise
        * efiemu/i386/pc/cfgtables.c: likewise
        * efiemu/i386/loadcore64.c: likewise
        * efiemu/i386/loadcore32.c: likewise
        * efiemu/prepare64.c: likewise
        * efiemu/loadcore.c: likewise
        * efiemu/symbols.c: likewise
        * efiemu/mm.c: likewise
        * efiemu/loadcore32.c: likewise
        

Modified Paths:
--------------
    trunk/grub2/ChangeLog
    trunk/grub2/conf/i386-pc.rmk
    trunk/grub2/include/grub/efi/api.h
    trunk/grub2/util/i386/pc/grub-install.in
    trunk/grub2/util/i386/pc/grub-mkrescue.in

Added Paths:
-----------
    trunk/grub2/efiemu/
    trunk/grub2/efiemu/i386/
    trunk/grub2/efiemu/i386/coredetect.c
    trunk/grub2/efiemu/i386/loadcore32.c
    trunk/grub2/efiemu/i386/loadcore64.c
    trunk/grub2/efiemu/i386/pc/
    trunk/grub2/efiemu/i386/pc/cfgtables.c
    trunk/grub2/efiemu/loadcore.c
    trunk/grub2/efiemu/loadcore32.c
    trunk/grub2/efiemu/loadcore64.c
    trunk/grub2/efiemu/loadcore_common.c
    trunk/grub2/efiemu/main.c
    trunk/grub2/efiemu/mm.c
    trunk/grub2/efiemu/pnvram.c
    trunk/grub2/efiemu/prepare.c
    trunk/grub2/efiemu/prepare32.c
    trunk/grub2/efiemu/prepare64.c
    trunk/grub2/efiemu/runtime/
    trunk/grub2/efiemu/runtime/config.h
    trunk/grub2/efiemu/runtime/efiemu.S
    trunk/grub2/efiemu/runtime/efiemu.c
    trunk/grub2/efiemu/runtime/efiemu.sh
    trunk/grub2/efiemu/symbols.c
    trunk/grub2/include/grub/autoefi.h
    trunk/grub2/include/grub/efiemu/
    trunk/grub2/include/grub/efiemu/efiemu.h
    trunk/grub2/include/grub/efiemu/runtime.h
    trunk/grub2/include/grub/i386/efiemu.h
    trunk/grub2/include/grub/i386/pc/efiemu.h

Modified: trunk/grub2/ChangeLog
===================================================================
--- trunk/grub2/ChangeLog       2009-05-02 22:31:29 UTC (rev 2161)
+++ trunk/grub2/ChangeLog       2009-05-02 22:40:21 UTC (rev 2162)
@@ -1,3 +1,44 @@
+2009-05-02  Vladimir Serbinenko  <address@hidden>
+
+       Efiemu
+ 
+       * conf/i386-pc.rmk: new modules efiemu, efiemu_acpi, efiemu_pnvram,
+       _linux_efi, linux_efi. 
+       new files in grub-emu 
+       new targets efiemu32.o and efiemu64.o
+       * loader/linux_normal_efiemu.c: likewise
+       * loader/i386/efi/linux.c: added preliminary efiemu support
+       * util/i386/pc/grub-install.in: add efiemu??.o to the list of 
+       files to copy
+       * include/grub/autoefi.h: new file
+       * nclude/grub/i386/efiemu.h: likewise
+       * include/grub/i386/pc/efiemu.h: likewise
+       * include/grub/efi/api.h: add LL suffix when necessary
+       new definitions relating to tables
+       * include/grub/efiemu/efiemu.h: new file
+       * include/grub/efiemu/runtime.h: likewise
+       * efiemu/prepare.c: likewise
+       * efiemu/loadcore_common.c: likewise
+       * efiemu/loadcore64.c: likewise
+       * efiemu/runtime/efiemu.sh: likewise
+       * efiemu/runtime/efiemu.S: likewise
+       * efiemu/runtime/efiemu.c: likewise
+       * efiemu/runtime/config.h: likewise
+       * efiemu/prepare32.c: likewise
+       * efiemu/main.c: likewise
+       * efiemu/modules/pnvram.c: likewise
+       * efiemu/modules/i386: likewise
+       * efiemu/modules/i386/pc: likewise
+       * efiemu/modules/acpi.c: likewise
+       * efiemu/i386/pc/cfgtables.c: likewise
+       * efiemu/i386/loadcore64.c: likewise
+       * efiemu/i386/loadcore32.c: likewise
+       * efiemu/prepare64.c: likewise
+       * efiemu/loadcore.c: likewise
+       * efiemu/symbols.c: likewise
+       * efiemu/mm.c: likewise
+       * efiemu/loadcore32.c: likewise
+       
 2009-05-02  Vladimir Serbinenko <address@hidden>
 
        ACPI spoofing

Modified: trunk/grub2/conf/i386-pc.rmk
===================================================================
--- trunk/grub2/conf/i386-pc.rmk        2009-05-02 22:31:29 UTC (rev 2161)
+++ trunk/grub2/conf/i386-pc.rmk        2009-05-02 22:40:21 UTC (rev 2162)
@@ -185,8 +185,18 @@
        aout.mod bsd.mod pxe.mod pxecmd.mod datetime.mod date.mod \
        datehook.mod lsmmap.mod ata_pthru.mod hdparm.mod \
        usb.mod uhci.mod ohci.mod usbtest.mod usbms.mod usb_keyboard.mod \
-       mmap.mod acpi.mod
+       efiemu.mod mmap.mod acpi.mod
 
+# For efiemu.mod.
+efiemu_mod_SOURCES = efiemu/main.c efiemu/i386/loadcore32.c \
+                    efiemu/i386/loadcore64.c efiemu/i386/pc/cfgtables.c \
+                    efiemu/mm.c efiemu/loadcore_common.c efiemu/symbols.c \
+                    efiemu/loadcore32.c efiemu/loadcore64.c \
+                    efiemu/prepare32.c efiemu/prepare64.c efiemu/pnvram.c \
+                    efiemu/i386/coredetect.c
+efiemu_mod_CFLAGS = $(COMMON_CFLAGS) -Werror -Wall
+efiemu_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 # For acpi.mod.
 acpi_mod_SOURCES = commands/acpi.c commands/i386/pc/acpi.c
 acpi_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -370,5 +380,19 @@
 hdparm_mod_CFLAGS = $(COMMON_CFLAGS)
 hdparm_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+efiemu32.o: efiemu/runtime/efiemu.c
+       $(CC) -c -m32 -DELF32 -o $@ -Wall -Werror efiemu/runtime/efiemu.c 
-nostdlib -O2 -Iefiemu/runtime -Iinclude 
+efiemu64_c.o: efiemu/runtime/efiemu.c
+       $(CC) -c -m64 -DELF64 -o $@ -Wall -Werror efiemu/runtime/efiemu.c 
-nostdlib  -mcmodel=large -O2 -Iefiemu/runtime -Iinclude 
+
+efiemu64_s.o: efiemu/runtime/efiemu.S
+       $(CC) -c -m64 -DELF64 -o $@ -Wall -Werror efiemu/runtime/efiemu.S 
-nostdlib  -mcmodel=large -O2 -Iefiemu/runtime -Iinclude 
+
+efiemu64.o: efiemu64_c.o efiemu64_s.o
+       ld -melf_x86_64 -o $@ -r efiemu64_c.o efiemu64_s.o -nostdlib 
+
+CLEANFILES += efiemu32.o efiemu64.o efiemu64_c.o efiemu64_s.o
+lib_DATA += efiemu32.o efiemu64.o
+
 include $(srcdir)/conf/i386.mk
 include $(srcdir)/conf/common.mk

Added: trunk/grub2/efiemu/i386/coredetect.c
===================================================================
--- trunk/grub2/efiemu/i386/coredetect.c                                (rev 0)
+++ trunk/grub2/efiemu/i386/coredetect.c        2009-05-02 22:40:21 UTC (rev 
2162)
@@ -0,0 +1,60 @@
+/*
+ *  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/efiemu/efiemu.h>
+#include <grub/machine/efiemu.h>
+#include <grub/command.h>
+
+#define cpuid(num,a,b,c,d) \
+  asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
+               : "=a" (a), "=r" (b), "=c" (c), "=d" (d)  \
+               : "0" (num))
+
+#define bit_LM (1 << 29)
+
+char *
+grub_efiemu_get_default_core_name (void)
+{
+
+  unsigned int eax, ebx, ecx, edx;
+  unsigned int max_level;
+  unsigned int ext_level;
+
+  /* See if we can use cpuid.  */
+  asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
+               "pushl %0; popfl; pushfl; popl %0; popfl"
+               : "=&r" (eax), "=&r" (ebx)
+               : "i" (0x00200000));
+  if (((eax ^ ebx) & 0x00200000) == 0)
+    return "efiemu32.o";
+
+  /* Check the highest input value for eax.  */
+  cpuid (0, eax, ebx, ecx, edx);
+  /* We only look at the first four characters.  */
+  max_level = eax;
+  if (max_level == 0)
+    return "efiemu32.o";
+
+  cpuid (0x80000000, eax, ebx, ecx, edx);
+  ext_level = eax;
+  if (ext_level < 0x80000000)
+    return "efiemu32.o";
+
+  cpuid (0x80000001, eax, ebx, ecx, edx);
+  return (edx & bit_LM) ? "efiemu64.o" : "efiemu32.o";
+}

Added: trunk/grub2/efiemu/i386/loadcore32.c
===================================================================
--- trunk/grub2/efiemu/i386/loadcore32.c                                (rev 0)
+++ trunk/grub2/efiemu/i386/loadcore32.c        2009-05-02 22:40:21 UTC (rev 
2162)
@@ -0,0 +1,114 @@
+/* i386 CPU-specific part of loadcore.c for 32-bit mode */
+/*
+ *  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/err.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/efiemu/efiemu.h>
+#include <grub/cpu/efiemu.h>
+#include <grub/elf.h>
+
+/* Check if EHDR is a valid ELF header.  */
+int
+grub_arch_efiemu_check_header32 (void *ehdr)
+{
+  Elf32_Ehdr *e = ehdr;
+
+  /* Check the magic numbers.  */
+  return (e->e_ident[EI_CLASS] == ELFCLASS32
+         && e->e_ident[EI_DATA] == ELFDATA2LSB
+         && e->e_machine == EM_386);
+}
+
+/* Relocate symbols.  */
+grub_err_t
+grub_arch_efiemu_relocate_symbols32 (grub_efiemu_segment_t segs, 
+                                    struct grub_efiemu_elf_sym *elfsyms,
+                                    void *ehdr)
+{
+  unsigned i;
+  Elf32_Ehdr *e = ehdr;
+  Elf32_Shdr *s;
+  grub_err_t err;
+
+  grub_dprintf ("efiemu", "relocating symbols %d %d\n",
+               e->e_shoff, e->e_shnum);
+
+  for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_REL)
+      {
+       grub_efiemu_segment_t seg;
+       grub_dprintf ("efiemu", "shtrel\n");
+
+       /* Find the target segment.  */
+       for (seg = segs; seg; seg = seg->next)
+         if (seg->section == s->sh_info)
+           break;
+
+       if (seg)
+         {
+           Elf32_Rel *rel, *max;
+           
+           for (rel = (Elf32_Rel *) ((char *) e + s->sh_offset),
+                  max = rel + s->sh_size / s->sh_entsize;
+                rel < max;
+                rel++)
+             {
+               Elf32_Word *addr;
+               struct grub_efiemu_elf_sym sym;
+               if (seg->size < rel->r_offset)
+                 return grub_error (GRUB_ERR_BAD_MODULE,
+                                    "reloc offset is out of the segment");
+               
+               addr = (Elf32_Word *) 
+                 ((char *) grub_efiemu_mm_obtain_request (seg->handle) 
+                  + seg->off + rel->r_offset);
+               sym = elfsyms[ELF32_R_SYM (rel->r_info)];
+               
+               switch (ELF32_R_TYPE (rel->r_info))
+                 {
+                 case R_386_32:
+                   if ((err = grub_efiemu_write_value 
+                        (addr, sym.off + *addr, sym.handle, 0, 
+                         seg->ptv_rel_needed, sizeof (grub_uint32_t))))
+                     return err;
+                   
+                   break;
+
+                 case R_386_PC32:
+                   if ((err = grub_efiemu_write_value
+                        (addr, sym.off + *addr - rel->r_offset 
+                         - seg->off, sym.handle, seg->handle, 
+                         seg->ptv_rel_needed, sizeof (grub_uint32_t))))
+                     return err;
+                   break;
+                 default:
+                   return grub_error (GRUB_ERR_BAD_OS, 
+                                      "unrecognised relocation");
+                 }
+             }
+         }
+      }
+
+  return GRUB_ERR_NONE;
+}
+
+

Added: trunk/grub2/efiemu/i386/loadcore64.c
===================================================================
--- trunk/grub2/efiemu/i386/loadcore64.c                                (rev 0)
+++ trunk/grub2/efiemu/i386/loadcore64.c        2009-05-02 22:40:21 UTC (rev 
2162)
@@ -0,0 +1,120 @@
+/* i386 CPU-specific part of loadcore.c for 32-bit mode */
+/*
+ *  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/err.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/efiemu/efiemu.h>
+#include <grub/cpu/efiemu.h>
+#include <grub/elf.h>
+
+/* Check if EHDR is a valid ELF header.  */
+int
+grub_arch_efiemu_check_header64 (void *ehdr)
+{
+  Elf64_Ehdr *e = ehdr;
+
+  return (e->e_ident[EI_CLASS] == ELFCLASS64
+         && e->e_ident[EI_DATA] == ELFDATA2LSB
+         && e->e_machine == EM_X86_64);
+}
+
+/* Relocate symbols.  */
+grub_err_t
+grub_arch_efiemu_relocate_symbols64 (grub_efiemu_segment_t segs, 
+                                    struct grub_efiemu_elf_sym *elfsyms,
+                                    void *ehdr)
+{
+  unsigned i;
+  Elf64_Ehdr *e = ehdr;
+  Elf64_Shdr *s;
+  grub_err_t err;
+
+  for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf64_Shdr *) ((char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_RELA)
+      {
+       grub_efiemu_segment_t seg;
+       grub_dprintf ("efiemu", "shtrel\n");
+
+       /* Find the target segment.  */
+       for (seg = segs; seg; seg = seg->next)
+         if (seg->section == s->sh_info)
+           break;
+
+       if (seg)
+         {
+           Elf64_Rela *rel, *max;
+           
+           for (rel = (Elf64_Rela *) ((char *) e + s->sh_offset),
+                  max = rel + (unsigned long) s->sh_size 
+                  / (unsigned long)s->sh_entsize;
+                rel < max;
+                rel++)
+             {
+               void *addr;
+               grub_uint32_t *addr32;
+               grub_uint64_t *addr64;
+               struct grub_efiemu_elf_sym sym;
+               if (seg->size < rel->r_offset)
+                 return grub_error (GRUB_ERR_BAD_MODULE,
+                                    "reloc offset is out of the segment");
+               
+               addr =
+                 ((char *) grub_efiemu_mm_obtain_request (seg->handle) 
+                  + seg->off + rel->r_offset);
+               addr32 = (grub_uint32_t *) addr;
+               addr64 = (grub_uint64_t *) addr;
+               sym = elfsyms[ELF64_R_SYM (rel->r_info)];
+               
+               switch (ELF64_R_TYPE (rel->r_info))
+                 {
+                 case R_X86_64_64:
+                   if ((err = grub_efiemu_write_value 
+                        (addr, *addr64 + rel->r_addend + sym.off, sym.handle, 
+                         0, seg->ptv_rel_needed, sizeof (grub_uint64_t))))
+                     return err;
+                   break;
+
+                 case R_X86_64_PC32:
+                   if ((err = grub_efiemu_write_value
+                        (addr, *addr32 + rel->r_addend + sym.off 
+                         - rel->r_offset - seg->off, sym.handle, seg->handle, 
+                         seg->ptv_rel_needed, sizeof (grub_uint32_t))))
+                     return err;
+                   break;
+
+                  case R_X86_64_32:
+                  case R_X86_64_32S:
+                   if ((err = grub_efiemu_write_value 
+                        (addr, *addr32 + rel->r_addend + sym.off, sym.handle, 
+                         0, seg->ptv_rel_needed, sizeof (grub_uint32_t))))
+                     return err;
+                    break;
+                 default:
+                   return grub_error (GRUB_ERR_BAD_OS, 
+                                      "unrecognised relocation");
+                 }
+             }
+         }
+      }
+
+  return GRUB_ERR_NONE;
+}

Added: trunk/grub2/efiemu/i386/pc/cfgtables.c
===================================================================
--- trunk/grub2/efiemu/i386/pc/cfgtables.c                              (rev 0)
+++ trunk/grub2/efiemu/i386/pc/cfgtables.c      2009-05-02 22:40:21 UTC (rev 
2162)
@@ -0,0 +1,76 @@
+/* Register SMBIOS and ACPI tables. */
+/*
+ *  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/err.h>
+#include <grub/efiemu/efiemu.h>
+#include <grub/machine/efiemu.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/acpi.h>
+
+grub_err_t
+grub_machine_efiemu_init_tables ()
+{
+  grub_uint8_t *ptr;
+  void *table;
+  grub_err_t err;
+  grub_efi_guid_t smbios = GRUB_EFI_SMBIOS_TABLE_GUID;
+  grub_efi_guid_t acpi20 = GRUB_EFI_ACPI_20_TABLE_GUID;
+  grub_efi_guid_t acpi = GRUB_EFI_ACPI_TABLE_GUID;
+
+  err = grub_efiemu_unregister_configuration_table (smbios);
+  if (err)
+    return err;
+  err = grub_efiemu_unregister_configuration_table (acpi);
+  if (err)
+    return err;
+  err = grub_efiemu_unregister_configuration_table (acpi20);
+  if (err)
+    return err;
+
+  table = grub_acpi_get_rsdpv1 ();
+  if (table)
+    {
+      err = grub_efiemu_register_configuration_table (acpi, 0, 0, table);
+      if (err)
+       return err;
+    }
+  table = grub_acpi_get_rsdpv2 ();
+  if (table)
+    {
+      err = grub_efiemu_register_configuration_table (acpi20, 0, 0, table);
+      if (err)
+       return err;
+    }
+
+  for (ptr = (grub_uint8_t *) 0xf0000; ptr < (grub_uint8_t *) 0x100000; 
+       ptr += 16)
+    if (grub_memcmp (ptr, "_SM_", 4) == 0
+       && grub_byte_checksum (ptr, *(ptr + 5)) == 0)
+      break;
+
+  if (ptr < (grub_uint8_t *) 0x100000)
+    {
+      grub_dprintf ("efiemu", "Registering SMBIOS\n");
+      if ((err = grub_efiemu_register_configuration_table (smbios, 0, 0, ptr)))
+       return err;
+    }
+
+  return GRUB_ERR_NONE;
+}

Added: trunk/grub2/efiemu/loadcore.c
===================================================================
--- trunk/grub2/efiemu/loadcore.c                               (rev 0)
+++ trunk/grub2/efiemu/loadcore.c       2009-05-02 22:40:21 UTC (rev 2162)
@@ -0,0 +1,365 @@
+/* Load runtime image of EFIemu. Functions specific to 32/64-bit mode */
+/*
+ *  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/err.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/efiemu/efiemu.h>
+#include <grub/cpu/efiemu.h>
+#include <grub/machine/efiemu.h>
+#include <grub/elf.h>
+
+/* ELF symbols and their values */
+static struct grub_efiemu_elf_sym *grub_efiemu_elfsyms = 0;
+static int grub_efiemu_nelfsyms = 0;
+
+/* Return the address of a section whose index is N.  */
+static grub_err_t
+grub_efiemu_get_section_addr (grub_efiemu_segment_t segs, unsigned n,
+                             int *handle, grub_off_t *off)
+{
+  grub_efiemu_segment_t seg;
+
+  for (seg = segs; seg; seg = seg->next)
+    if (seg->section == n)
+      {
+       *handle = seg->handle;
+       *off = seg->off;        
+       return GRUB_ERR_NONE;
+      }
+
+  return grub_error (GRUB_ERR_BAD_OS, "section %d not found", n);
+}
+
+grub_err_t
+SUFFIX (grub_efiemu_loadcore_unload) (void)
+{
+  grub_free (grub_efiemu_elfsyms);
+  grub_efiemu_elfsyms = 0;
+  return GRUB_ERR_NONE;
+}
+
+/* Check if EHDR is a valid ELF header.  */
+int
+SUFFIX (grub_efiemu_check_header) (void *ehdr, grub_size_t size)
+{
+  Elf_Ehdr *e = ehdr;
+
+  /* Check the header size.  */
+  if (size < sizeof (Elf_Ehdr))
+    return 0;
+
+  /* Check the magic numbers.  */
+  if (!SUFFIX (grub_arch_efiemu_check_header) (ehdr)
+      || e->e_ident[EI_MAG0] != ELFMAG0
+      || e->e_ident[EI_MAG1] != ELFMAG1
+      || e->e_ident[EI_MAG2] != ELFMAG2
+      || e->e_ident[EI_MAG3] != ELFMAG3
+      || e->e_ident[EI_VERSION] != EV_CURRENT
+      || e->e_version != EV_CURRENT)
+    return 0;
+
+  return 1;
+}
+
+/* Load all segments from memory specified by E.  */
+static grub_err_t
+grub_efiemu_load_segments (grub_efiemu_segment_t segs, const Elf_Ehdr *e)
+{
+  Elf_Shdr *s;
+  grub_efiemu_segment_t cur;
+
+  grub_dprintf ("efiemu", "loading segments\n");
+  
+  for (cur=segs; cur; cur = cur->next)
+    {
+      s = (Elf_Shdr *)cur->srcptr;
+
+      if ((s->sh_flags & SHF_ALLOC) && s->sh_size)
+       {
+         void *addr;
+         
+         addr = (grub_uint8_t *) grub_efiemu_mm_obtain_request (cur->handle) 
+           + cur->off;
+         
+         switch (s->sh_type)
+           {
+           case SHT_PROGBITS:
+             grub_memcpy (addr, (char *) e + s->sh_offset, s->sh_size);
+             break;
+           case SHT_NOBITS:
+             grub_memset (addr, 0, s->sh_size);
+             break;
+           }
+       }
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+/* Get a string at offset OFFSET from strtab */
+static char *
+grub_efiemu_get_string (unsigned offset, const Elf_Ehdr *e)
+{
+  unsigned i;
+  Elf_Shdr *s;
+
+  for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_STRTAB && offset < s->sh_size)
+      return (char *) e + s->sh_offset + offset;
+  return 0;
+}
+
+/* Request memory for segments and fill segments info */
+static grub_err_t
+grub_efiemu_init_segments (grub_efiemu_segment_t *segs, const Elf_Ehdr *e)
+{
+  unsigned i;
+  Elf_Shdr *s;
+
+  for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize))
+    {
+      if (s->sh_flags & SHF_ALLOC)
+       {
+         grub_efiemu_segment_t seg;
+         seg = (grub_efiemu_segment_t) grub_malloc (sizeof (*seg));
+         if (! seg)
+           return grub_errno;
+         
+         if (s->sh_size)
+           {
+             seg->handle 
+               = grub_efiemu_request_memalign 
+               (s->sh_addralign, s->sh_size,
+                s->sh_flags & SHF_EXECINSTR ? GRUB_EFI_RUNTIME_SERVICES_CODE
+                : GRUB_EFI_RUNTIME_SERVICES_DATA);
+             if (seg->handle < 0)
+               return grub_errno;
+             seg->off = 0;
+           }
+         
+         /* 
+            .text-physical doesn't need to be relocated when switching to
+            virtual mode
+          */
+         if (!grub_strcmp (grub_efiemu_get_string (s->sh_name, e), 
+                           ".text-physical"))
+           seg->ptv_rel_needed = 0;
+         else
+           seg->ptv_rel_needed = 1;
+         seg->size = s->sh_size;
+         seg->section = i;
+         seg->next = *segs;
+         seg->srcptr = s;
+         *segs = seg;
+       }
+    }
+  
+  return GRUB_ERR_NONE;
+}
+
+/* Count symbols and relocators and allocate/request memory for them */
+static grub_err_t
+grub_efiemu_count_symbols (const Elf_Ehdr *e)
+{
+  unsigned i;
+  Elf_Shdr *s;
+  int num = 0;
+  
+  /* Symbols */
+  for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_SYMTAB)
+      break;
+
+  if (i == e->e_shnum)
+    return grub_error (GRUB_ERR_BAD_OS, "no symbol table");
+
+  grub_efiemu_nelfsyms = (unsigned) s->sh_size / (unsigned) s->sh_entsize;
+  grub_efiemu_elfsyms = (struct grub_efiemu_elf_sym *) 
+    grub_malloc (sizeof (struct grub_efiemu_elf_sym) * grub_efiemu_nelfsyms);
+
+  /* Relocators */
+  for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_REL || s->sh_type == SHT_RELA)
+      num += ((unsigned) s->sh_size) / ((unsigned) s->sh_entsize);
+
+  grub_efiemu_request_symbols (num);
+
+  return GRUB_ERR_NONE;
+}
+
+/* Fill grub_efiemu_elfsyms with symbol values */
+static grub_err_t
+grub_efiemu_resolve_symbols (grub_efiemu_segment_t segs, Elf_Ehdr *e)
+{
+  unsigned i;
+  Elf_Shdr *s;
+  Elf_Sym *sym;
+  const char *str;
+  Elf_Word size, entsize;
+  
+  grub_dprintf ("efiemu", "resolving symbols\n");
+
+  for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_SYMTAB)
+      break;
+
+  if (i == e->e_shnum)
+    return grub_error (GRUB_ERR_BAD_OS, "no symbol table");
+
+  sym = (Elf_Sym *) ((char *) e + s->sh_offset);
+  size = s->sh_size;
+  entsize = s->sh_entsize;
+
+  s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shentsize * s->sh_link);
+  str = (char *) e + s->sh_offset;
+
+  for (i = 0;
+       i < size / entsize;
+       i++, sym = (Elf_Sym *) ((char *) sym + entsize))
+    {
+      unsigned char type = ELF_ST_TYPE (sym->st_info);
+      unsigned char bind = ELF_ST_BIND (sym->st_info);
+      int handle;
+      grub_off_t off;
+      grub_err_t err;
+      const char *name = str + sym->st_name;
+      grub_efiemu_elfsyms[i].section = sym->st_shndx;
+      switch (type)
+       {
+       case STT_NOTYPE:
+         /* Resolve a global symbol.  */
+         if (sym->st_name != 0 && sym->st_shndx == 0)
+           {
+             if ((err = grub_efiemu_resolve_symbol (name, &handle, &off)))
+               return err;
+             grub_efiemu_elfsyms[i].handle = handle;
+             grub_efiemu_elfsyms[i].off = off;
+           }
+         else
+           sym->st_value = 0;
+         break;
+
+       case STT_OBJECT:
+         if ((err = grub_efiemu_get_section_addr 
+              (segs, sym->st_shndx, &handle, &off)))
+           return err;
+
+         off += sym->st_value;
+         if (bind != STB_LOCAL)
+           if ((err = grub_efiemu_register_symbol (name, handle, off)))
+             return err;
+         grub_efiemu_elfsyms[i].handle = handle;
+         grub_efiemu_elfsyms[i].off = off;
+         break;
+
+       case STT_FUNC:
+         if ((err = grub_efiemu_get_section_addr 
+              (segs, sym->st_shndx, &handle, &off)))
+           return err;
+
+         off += sym->st_value;
+         if (bind != STB_LOCAL)
+           if ((err = grub_efiemu_register_symbol (name, handle, off)))
+             return err;
+         grub_efiemu_elfsyms[i].handle = handle;
+         grub_efiemu_elfsyms[i].off = off;
+         break;
+
+       case STT_SECTION:
+         if ((err = grub_efiemu_get_section_addr 
+              (segs, sym->st_shndx, &handle, &off)))
+           {
+             grub_efiemu_elfsyms[i].handle = 0;
+             grub_efiemu_elfsyms[i].off = 0;
+             grub_errno = GRUB_ERR_NONE; 
+             break;
+           }
+
+         grub_efiemu_elfsyms[i].handle = handle;
+         grub_efiemu_elfsyms[i].off = off;
+         break;
+
+       case STT_FILE:
+         grub_efiemu_elfsyms[i].handle = 0;
+         grub_efiemu_elfsyms[i].off = 0;
+         break;
+
+       default:
+         return grub_error (GRUB_ERR_BAD_MODULE,
+                            "unknown symbol type `%d'", (int) type);
+       }
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+/* Load runtime to the memory and request memory for definitive location*/
+grub_err_t
+SUFFIX (grub_efiemu_loadcore_init) (void *core, grub_size_t core_size,
+                                   grub_efiemu_segment_t *segments)
+{
+  Elf_Ehdr *e = (Elf_Ehdr *) core;
+  grub_err_t err;
+
+  if (e->e_type != ET_REL)
+    return grub_error (GRUB_ERR_BAD_MODULE, "invalid ELF file type");
+
+  /* Make sure that every section is within the core.  */
+  if ((grub_size_t) core_size < e->e_shoff + e->e_shentsize * e->e_shnum)
+    return grub_error (GRUB_ERR_BAD_OS, "ELF sections outside core");
+
+  if ((err = grub_efiemu_init_segments (segments, core)))
+    return err;
+  if ((err = grub_efiemu_count_symbols (core)))
+    return err;
+
+  grub_efiemu_request_symbols (1);
+  return GRUB_ERR_NONE;
+}
+
+/* Load runtime definitively */
+grub_err_t
+SUFFIX (grub_efiemu_loadcore_load) (void *core, 
+                                   grub_size_t core_size 
+                                   __attribute__ ((unused)),
+                                   grub_efiemu_segment_t segments)
+{
+  grub_err_t err;
+  if ((err = grub_efiemu_load_segments (segments, core)))
+    return err;
+  if ((err = grub_efiemu_resolve_symbols (segments, core)))
+    return err;
+  if ((err = SUFFIX (grub_arch_efiemu_relocate_symbols) (segments, 
+                                                        grub_efiemu_elfsyms,
+                                                        core)))
+    return err;
+    
+  return GRUB_ERR_NONE;
+}

Added: trunk/grub2/efiemu/loadcore32.c
===================================================================
--- trunk/grub2/efiemu/loadcore32.c                             (rev 0)
+++ trunk/grub2/efiemu/loadcore32.c     2009-05-02 22:40:21 UTC (rev 2162)
@@ -0,0 +1,27 @@
+/* This file contains definitions so that loadcore.c compiles for 32-bit */
+/*
+ *  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/>.
+ */
+
+#define SUFFIX(x) x ## 32
+#define Elf_Ehdr Elf32_Ehdr
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Word Elf32_Word
+#define ELF_ST_TYPE ELF32_ST_TYPE
+#define ELF_ST_BIND ELF32_ST_BIND
+#include "loadcore.c"

Added: trunk/grub2/efiemu/loadcore64.c
===================================================================
--- trunk/grub2/efiemu/loadcore64.c                             (rev 0)
+++ trunk/grub2/efiemu/loadcore64.c     2009-05-02 22:40:21 UTC (rev 2162)
@@ -0,0 +1,27 @@
+/* This file contains definitions so that loadcore.c compiles for 64-bit */
+/*
+ *  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/>.
+ */
+
+#define SUFFIX(x) x ## 64
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+#define Elf_Word Elf64_Word
+#define ELF_ST_TYPE ELF64_ST_TYPE
+#define ELF_ST_BIND ELF64_ST_BIND
+#include "loadcore.c"

Added: trunk/grub2/efiemu/loadcore_common.c
===================================================================
--- trunk/grub2/efiemu/loadcore_common.c                                (rev 0)
+++ trunk/grub2/efiemu/loadcore_common.c        2009-05-02 22:40:21 UTC (rev 
2162)
@@ -0,0 +1,189 @@
+/* Load runtime image of EFIemu. Functions common to 32/64-bit mode */
+/*
+ *  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/file.h>
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/efiemu/efiemu.h>
+#include <grub/cpu/efiemu.h>
+
+/* Are we in 32 or 64-bit mode?*/
+static grub_efiemu_mode_t grub_efiemu_mode = GRUB_EFIEMU_NOTLOADED;
+/* Runtime ELF file */
+static grub_ssize_t efiemu_core_size;
+static void *efiemu_core = 0;
+/* Linked list of segments */
+static grub_efiemu_segment_t efiemu_segments = 0;
+
+/* equivalent to sizeof (grub_efi_uintn_t) but taking the mode into account*/
+int
+grub_efiemu_sizeof_uintn_t (void)
+{
+  if (grub_efiemu_mode == GRUB_EFIEMU32)
+    return 4;
+  if (grub_efiemu_mode == GRUB_EFIEMU64)
+    return 8;
+  return 0;
+}
+
+/* Check the header and set mode */
+static grub_err_t
+grub_efiemu_check_header (void *ehdr, grub_size_t size, 
+                         grub_efiemu_mode_t *mode)
+{
+  /* Check the magic numbers.  */
+  if ((*mode == GRUB_EFIEMU_NOTLOADED || *mode == GRUB_EFIEMU32)
+      && grub_efiemu_check_header32 (ehdr,size))
+    {
+      *mode = GRUB_EFIEMU32;
+      return GRUB_ERR_NONE;
+    }
+  if ((*mode == GRUB_EFIEMU_NOTLOADED || *mode == GRUB_EFIEMU64)
+      && grub_efiemu_check_header64 (ehdr,size))
+    {
+      *mode = GRUB_EFIEMU64;
+      return GRUB_ERR_NONE;
+    }
+  return grub_error (GRUB_ERR_BAD_OS, "invalid ELF magic");
+}
+
+/* Unload segments */
+static int
+grub_efiemu_unload_segs (grub_efiemu_segment_t seg)
+{
+  grub_efiemu_segment_t segn;
+  for (; seg; seg = segn)
+    {
+      segn = seg->next;
+      grub_efiemu_mm_return_request (seg->handle);
+      grub_free (seg);
+    }
+  return 1;
+}
+
+
+grub_err_t
+grub_efiemu_loadcore_unload(void)
+{
+  switch (grub_efiemu_mode)
+    {
+    case GRUB_EFIEMU32:
+      grub_efiemu_loadcore_unload32 ();
+      break;
+
+    case GRUB_EFIEMU64:
+      grub_efiemu_loadcore_unload64 ();
+      break;
+      
+    default:
+      break;
+    }
+
+  grub_efiemu_mode = GRUB_EFIEMU_NOTLOADED;
+
+  grub_free (efiemu_core);
+  efiemu_core = 0;
+
+  grub_efiemu_unload_segs (efiemu_segments);
+  efiemu_segments = 0;
+
+  grub_efiemu_free_syms ();
+
+  return GRUB_ERR_NONE;
+}
+
+/* Load runtime file and do some initial preparations */ 
+grub_err_t
+grub_efiemu_loadcore_init (grub_file_t file)
+{
+  grub_err_t err;
+
+  efiemu_core_size = grub_file_size (file);
+  efiemu_core = 0;
+  efiemu_core = grub_malloc (efiemu_core_size);
+  if (! efiemu_core)
+    return grub_errno;
+
+  if (grub_file_read (file, efiemu_core, efiemu_core_size) 
+      != (int) efiemu_core_size)
+    {
+      grub_free (efiemu_core);
+      efiemu_core = 0;
+      return grub_errno;
+    }
+
+  if (grub_efiemu_check_header (efiemu_core, efiemu_core_size, 
+                               &grub_efiemu_mode))
+    {
+      grub_free (efiemu_core);
+      efiemu_core = 0;
+      return GRUB_ERR_BAD_MODULE;
+    }
+
+  switch (grub_efiemu_mode)
+    {
+    case GRUB_EFIEMU32:
+      if ((err = grub_efiemu_loadcore_init32 (efiemu_core, efiemu_core_size,
+                                             &efiemu_segments)))
+       {
+         grub_free (efiemu_core);
+         efiemu_core = 0;
+         grub_efiemu_mode = GRUB_EFIEMU_NOTLOADED;
+         return err;
+       }
+      break;
+
+    case GRUB_EFIEMU64:
+      if ((err = grub_efiemu_loadcore_init64 (efiemu_core, efiemu_core_size,
+                                             &efiemu_segments)))
+       {
+         grub_free (efiemu_core);
+         efiemu_core = 0;
+         grub_efiemu_mode = GRUB_EFIEMU_NOTLOADED;
+         return err;
+       }
+      break;
+      
+    default:
+      return grub_error (GRUB_ERR_BAD_OS, "unknown EFI runtime");
+    }
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_efiemu_loadcore_load (void)
+{
+  grub_err_t err;
+  switch (grub_efiemu_mode)
+    {
+    case GRUB_EFIEMU32:
+      if ((err = grub_efiemu_loadcore_load32 (efiemu_core, efiemu_core_size,
+                                             efiemu_segments)))
+         grub_efiemu_loadcore_unload ();
+      return err;
+    case GRUB_EFIEMU64:
+      if ((err = grub_efiemu_loadcore_load64 (efiemu_core, efiemu_core_size,
+                                             efiemu_segments)))
+         grub_efiemu_loadcore_unload ();
+      return err;
+    default:
+      return grub_error (GRUB_ERR_BAD_OS, "unknown EFI runtime");
+    }
+}

Added: trunk/grub2/efiemu/main.c
===================================================================
--- trunk/grub2/efiemu/main.c                           (rev 0)
+++ trunk/grub2/efiemu/main.c   2009-05-02 22:40:21 UTC (rev 2162)
@@ -0,0 +1,345 @@
+/*
+ *  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/>.
+ */
+
+/* This is an emulation of EFI runtime services.
+   This allows a more uniform boot on i386 machines. 
+   As it emulates only runtime service it isn't able 
+   to chainload EFI bootloader on non-EFI system. */
+
+
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/mm.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/efiemu/efiemu.h>
+#include <grub/machine/efiemu.h>
+#include <grub/command.h>
+
+/* System table. Two version depending on mode */
+grub_efi_system_table32_t *grub_efiemu_system_table32 = 0;
+grub_efi_system_table64_t *grub_efiemu_system_table64 = 0;
+/* Modules may need to execute some actions after memory allocation happens */
+static struct grub_efiemu_prepare_hook *efiemu_prepare_hooks = 0;
+/* Linked list of configuration tables */
+static struct grub_efiemu_configuration_table *efiemu_config_tables = 0;
+
+/* Free all allocated space */
+grub_err_t
+grub_efiemu_unload (void)
+{
+  struct grub_efiemu_configuration_table *cur, *d;
+  struct grub_efiemu_prepare_hook *curhook, *d2;
+  grub_efiemu_loadcore_unload ();
+
+  grub_efiemu_mm_unload ();
+
+  for (cur = efiemu_config_tables; cur;)
+    {
+      d = cur->next;
+      if (cur->unload)
+       cur->unload (cur->data);
+      grub_free (cur);
+      cur = d;
+    }
+  efiemu_config_tables = 0;
+
+  for (curhook = efiemu_prepare_hooks; curhook;)
+    {
+      d2 = curhook->next;
+      if (curhook->unload)
+       curhook->unload (curhook->data);
+      grub_free (curhook);
+      curhook = d2;
+    }
+  efiemu_prepare_hooks = 0;
+
+  return GRUB_ERR_NONE;
+}
+
+/* Remove previously registered table from the list */
+grub_err_t
+grub_efiemu_unregister_configuration_table (grub_efi_guid_t guid)
+{
+  struct grub_efiemu_configuration_table *cur, *prev;
+
+  /* Special treating if head is to remove */
+  while (efiemu_config_tables
+        && !grub_memcmp (&(efiemu_config_tables->guid), &guid, sizeof (guid)))
+    {
+      if (efiemu_config_tables->unload)
+         efiemu_config_tables->unload (efiemu_config_tables->data);
+       cur = efiemu_config_tables->next;
+       grub_free (efiemu_config_tables);
+       efiemu_config_tables = cur;
+    }
+  if (!efiemu_config_tables)
+    return GRUB_ERR_NONE;
+
+  /* Remove from chain */
+  for (prev = efiemu_config_tables, cur = prev->next; cur;)
+    if (grub_memcmp (&(cur->guid), &guid, sizeof (guid)) == 0)
+      {
+       if (cur->unload)
+         cur->unload (cur->data);
+       prev->next = cur->next;
+       grub_free (cur);
+       cur = prev->next;
+      }
+    else
+      {
+       prev = cur;
+       cur = cur->next;
+      }
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_efiemu_register_prepare_hook (grub_err_t (*hook) (void *data),
+                                  void (*unload) (void *data), 
+                                  void *data)
+{
+  struct grub_efiemu_prepare_hook *nhook;
+  if (! hook)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "you must supply the hook");
+  nhook = (struct grub_efiemu_prepare_hook *) grub_malloc (sizeof (*nhook));
+  if (! nhook)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't prepare hook");
+  nhook->hook = hook;
+  nhook->unload = unload;
+  nhook->data = data;
+  nhook->next = efiemu_prepare_hooks;
+  efiemu_prepare_hooks = nhook;
+  return GRUB_ERR_NONE;
+}
+
+/* Register a configuration table either supplying the address directly 
+   or with a hook
+*/
+grub_err_t
+grub_efiemu_register_configuration_table (grub_efi_guid_t guid, 
+                                         void * (*get_table) (void *data),
+                                         void (*unload) (void *data), 
+                                         void *data)
+{
+  struct grub_efiemu_configuration_table *tbl;
+  grub_err_t err;
+ 
+ if (! get_table && ! data)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                      "you must set at least get_table or data");
+  if ((err = grub_efiemu_unregister_configuration_table (guid)))
+    return err;
+
+  tbl = (struct grub_efiemu_configuration_table *) grub_malloc (sizeof (*tbl));
+  if (! tbl)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't register table");
+
+  tbl->guid = guid;
+  tbl->get_table = get_table;
+  tbl->unload = unload;
+  tbl->data = data;
+  tbl->next = efiemu_config_tables;
+  efiemu_config_tables = tbl;
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_efiemu_unload (grub_command_t cmd __attribute__ ((unused)),
+                       int argc __attribute__ ((unused)), 
+                       char *args[] __attribute__ ((unused)))
+{
+  return grub_efiemu_unload ();
+}
+
+static grub_err_t
+grub_cmd_efiemu_prepare (grub_command_t cmd __attribute__ ((unused)),
+                        int argc __attribute__ ((unused)), 
+                        char *args[] __attribute__ ((unused)))
+{
+  return grub_efiemu_prepare ();
+}
+
+
+
+
+int 
+grub_efiemu_exit_boot_services (grub_efi_uintn_t map_key 
+                               __attribute__ ((unused)))
+{
+  /* Nothing to do here yet */
+  return 1;
+}
+
+int 
+grub_efiemu_finish_boot_services (void)
+{
+  /* Nothing to do here yet */
+  return 1;
+}
+
+/* Load the runtime from the file FILENAME.  */
+static grub_err_t
+grub_efiemu_load_file (const char *filename)
+{
+  grub_file_t file;
+  grub_err_t err;
+  
+  file = grub_file_open (filename);
+  if (! file)
+    return 0;
+  
+  err = grub_efiemu_mm_init ();
+  if (err)
+    {
+      grub_file_close (file);
+      grub_efiemu_unload ();
+      return grub_error (grub_errno, "Couldn't init memory management");
+    }
+
+  grub_dprintf ("efiemu", "mm inited\n");
+
+  err = grub_efiemu_loadcore_init (file);
+  if (err)
+    {
+      grub_file_close (file);
+      grub_efiemu_unload ();
+      return err;
+    }
+
+  grub_file_close (file);
+
+  /* For configuration tables entry in system table. */
+  grub_efiemu_request_symbols (1);
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_efiemu_autocore (void)
+{
+  const char *prefix;
+  char *filename;
+  char *suffix;
+  grub_err_t err;
+
+  if (grub_efiemu_sizeof_uintn_t () != 0)
+    return GRUB_ERR_NONE;
+
+  prefix = grub_env_get ("prefix");
+  
+  if (! prefix)
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, 
+                      "couldn't find efiemu core because prefix "
+                      "isn't set");
+  
+  suffix = grub_efiemu_get_default_core_name ();
+  
+  filename = grub_malloc (grub_strlen (prefix) + grub_strlen (suffix) + 2);
+  if (! filename)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                      "couldn't allocate temporary space");
+  
+  grub_sprintf (filename, "%s/%s", prefix, suffix);
+
+  err = grub_efiemu_load_file (filename);
+  grub_free (filename);
+  if (err)
+    return err;
+#ifndef GRUB_UTIL
+  err = grub_machine_efiemu_init_tables ();
+  if (err)
+    return err;
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_efiemu_prepare (void)
+{
+  grub_err_t err;
+
+  grub_dprintf ("efiemu", "Preparing %d-bit efiemu\n", 
+               8 * grub_efiemu_sizeof_uintn_t ());
+
+  err = grub_efiemu_autocore ();
+
+  /* Create NVRAM if not yet done. */
+  grub_efiemu_pnvram ();
+
+  if (grub_efiemu_sizeof_uintn_t () == 4)
+    return grub_efiemu_prepare32 (efiemu_prepare_hooks, efiemu_config_tables);
+  else
+    return grub_efiemu_prepare64 (efiemu_prepare_hooks, efiemu_config_tables);
+}
+
+
+static grub_err_t
+grub_cmd_efiemu_load (grub_command_t cmd __attribute__ ((unused)),
+                     int argc, char *args[])
+{
+  grub_err_t err;
+
+  grub_efiemu_unload ();
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "filename required");
+
+  err = grub_efiemu_load_file (args[0]);
+  if (err)
+    return err;
+#ifndef GRUB_UTIL
+  err = grub_machine_efiemu_init_tables ();
+  if (err)
+    return err;
+#endif
+  return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd_loadcore, cmd_prepare, cmd_unload;
+
+void
+grub_efiemu_pnvram_cmd_register (void);
+
+GRUB_MOD_INIT(efiemu)
+{
+  (void) mod;                  /* To stop warning. */
+  cmd_loadcore = grub_register_command ("efiemu_loadcore", 
+                                       grub_cmd_efiemu_load, 
+                                      "efiemu_loadcore FILE", 
+                                      "Load and initialize EFI emulator");
+  cmd_prepare = grub_register_command ("efiemu_prepare", 
+                                      grub_cmd_efiemu_prepare, 
+                                      "efiemu_prepare", 
+                                      "Finalize loading of EFI emulator");
+  cmd_unload = grub_register_command ("efiemu_unload", grub_cmd_efiemu_unload, 
+                                     "efiemu_unload", 
+                                     "Unload  EFI emulator");
+  grub_efiemu_pnvram_cmd_register ();
+}
+
+GRUB_MOD_FINI(efiemu)
+{
+  grub_unregister_command (cmd_loadcore);
+  grub_unregister_command (cmd_prepare);
+  grub_unregister_command (cmd_unload);
+  grub_efiemu_pnvram_cmd_unregister ();
+}

Added: trunk/grub2/efiemu/mm.c
===================================================================
--- trunk/grub2/efiemu/mm.c                             (rev 0)
+++ trunk/grub2/efiemu/mm.c     2009-05-02 22:40:21 UTC (rev 2162)
@@ -0,0 +1,635 @@
+/* Memory management for efiemu */
+/*
+ *  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/>.
+ */
+/*
+  To keep efiemu runtime contiguous this mm is special. 
+  It uses deffered allocation.
+  In the first stage you may request memory with grub_efiemu_request_memalign
+  It will give you a handle with which in the second phase you can access your 
+  memory with grub_efiemu_mm_obtain_request (handle). It's guaranteed that
+  subsequent calls with the same handle return the same result. You can't 
request any additional memory once you're in the second phase
+*/
+
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/machine/memory.h>
+#include <grub/efiemu/efiemu.h>
+
+struct grub_efiemu_memrequest 
+{
+  struct grub_efiemu_memrequest *next;
+  grub_efi_memory_type_t type;
+  grub_size_t size;
+  grub_size_t align_overhead;
+  int handle;
+  void *val;
+};
+/* Linked list of requested memory. */
+static struct grub_efiemu_memrequest *memrequests = 0;
+/* Memory map. */
+static grub_efi_memory_descriptor_t *efiemu_mmap = 0;
+/* Pointer to allocated memory */
+static void *resident_memory = 0;
+/* Size of requested memory per type */
+static grub_size_t requested_memory[GRUB_EFI_MAX_MEMORY_TYPE];
+/* How many slots is allocated for memory_map and how many are already used */
+static int mmap_reserved_size = 0, mmap_num = 0;
+
+/* Add a memory region to map*/
+static grub_err_t
+grub_efiemu_add_to_mmap (grub_uint64_t start, grub_uint64_t size, 
+                        grub_efi_memory_type_t type)
+{
+  grub_uint64_t page_start, npages;
+
+  /* Extend map if necessary*/
+  if (mmap_num >= mmap_reserved_size)
+    {
+      efiemu_mmap = (grub_efi_memory_descriptor_t *)
+       grub_realloc (efiemu_mmap, (++mmap_reserved_size) 
+                     * sizeof (grub_efi_memory_descriptor_t));
+      if (!efiemu_mmap)
+       return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                          "Not enough space for memory map");
+    }
+
+  /* Fill slot*/
+  page_start = start - (start % GRUB_EFIEMU_PAGESIZE);
+  npages = (size + (start % GRUB_EFIEMU_PAGESIZE) + GRUB_EFIEMU_PAGESIZE - 1)
+    / GRUB_EFIEMU_PAGESIZE;
+  efiemu_mmap[mmap_num].physical_start = page_start; 
+  efiemu_mmap[mmap_num].virtual_start = page_start; 
+  efiemu_mmap[mmap_num].num_pages = npages; 
+  efiemu_mmap[mmap_num].type = type;
+  mmap_num++;
+
+  return GRUB_ERR_NONE;
+}
+
+/* Request a resident memory of type TYPE of size SIZE aligned at ALIGN
+   ALIGN must be a divisor of page size (if it's a divisor of 4096 
+   it should be ok on all platforms)
+ */
+int
+grub_efiemu_request_memalign (grub_size_t align, grub_size_t size, 
+                             grub_efi_memory_type_t type)
+{
+  grub_size_t align_overhead;
+  struct grub_efiemu_memrequest *ret, *cur, *prev;
+  /* Check that the request is correct */
+  if (type >= GRUB_EFI_MAX_MEMORY_TYPE || type <= GRUB_EFI_LOADER_CODE)
+    return -2;
+
+  /* Add new size to requested size */
+  align_overhead = align - (requested_memory[type]%align);
+  if (align_overhead == align)
+    align_overhead = 0;
+  requested_memory[type] += align_overhead + size;
+
+  /* Remember the request */
+  ret = grub_malloc (sizeof (*ret));
+  if (!ret)
+    return -1;
+  ret->type = type;
+  ret->size = size;
+  ret->align_overhead = align_overhead;
+  ret->val = 0;
+  ret->next = 0;
+  prev = 0;
+  
+  /* Add request to the end of the chain. 
+     It should be at the end because otherwise alignment isn't guaranteed */
+  for (cur = memrequests; cur; prev = cur, cur = cur->next);
+  if (prev)
+    {
+      ret->handle = prev->handle + 1;
+      prev->next = ret;
+    }
+  else
+    {
+      ret->handle = 1; /* Avoid 0 handle*/
+      memrequests = ret;
+    }
+  return ret->handle;
+}
+
+/* Really allocate the memory */
+static grub_err_t
+efiemu_alloc_requests (void)
+{
+  grub_size_t align_overhead = 0;
+  grub_uint8_t *curptr, *typestart;
+  struct grub_efiemu_memrequest *cur;
+  grub_size_t total_alloc = 0;
+  unsigned i;
+  /* Order of memory regions */
+  grub_efi_memory_type_t reqorder[] =
+    {
+      /* First come regions usable by OS*/
+      GRUB_EFI_LOADER_CODE,
+      GRUB_EFI_LOADER_DATA,
+      GRUB_EFI_BOOT_SERVICES_CODE,
+      GRUB_EFI_BOOT_SERVICES_DATA,
+      GRUB_EFI_CONVENTIONAL_MEMORY,
+      GRUB_EFI_ACPI_RECLAIM_MEMORY,
+
+      /* Then memory used by runtime */
+      /* This way all our regions are in a single block */
+      GRUB_EFI_RUNTIME_SERVICES_CODE,
+      GRUB_EFI_RUNTIME_SERVICES_DATA,
+      GRUB_EFI_ACPI_MEMORY_NVS,
+      
+      /* And then unavailable memory types. This is more for a completeness. 
+        You should double think before allocating memory of any of these types
+       */
+      GRUB_EFI_UNUSABLE_MEMORY,
+      GRUB_EFI_MEMORY_MAPPED_IO,
+      GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE,
+      GRUB_EFI_PAL_CODE 
+    };
+
+  /* Compute total memory needed */
+  for (i = 0; i < sizeof (reqorder) / sizeof (reqorder[0]); i++)
+    {
+      align_overhead = GRUB_EFIEMU_PAGESIZE 
+       - (requested_memory[reqorder[i]] % GRUB_EFIEMU_PAGESIZE);
+      if (align_overhead == GRUB_EFIEMU_PAGESIZE)
+       align_overhead = 0;
+      total_alloc += requested_memory[reqorder[i]] + align_overhead;
+    }
+
+  /* Allocate the whole memory in one block */
+  resident_memory = grub_memalign (GRUB_EFIEMU_PAGESIZE, total_alloc);
+  if (!resident_memory)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                      "couldn't allocate resident memory");
+
+  /* Split the memory into blocks by type */
+  curptr = resident_memory;
+  for (i = 0; i < sizeof (reqorder) / sizeof (reqorder[0]); i++)
+    {
+      if (!requested_memory[reqorder[i]])
+       continue;
+      typestart = curptr;
+
+      /* Write pointers to requests */
+      for (cur = memrequests; cur; cur = cur->next)
+       if (cur->type == reqorder[i])
+         {
+           curptr = ((grub_uint8_t *)curptr) + cur->align_overhead;
+           cur->val = curptr;
+           curptr = ((grub_uint8_t *)curptr) + cur->size;
+         }
+
+      /* Ensure that the regions are page-aligned */
+      align_overhead = GRUB_EFIEMU_PAGESIZE 
+       - (requested_memory[reqorder[i]] % GRUB_EFIEMU_PAGESIZE);
+      if (align_overhead == GRUB_EFIEMU_PAGESIZE)
+       align_overhead = 0;
+      curptr = ((grub_uint8_t *)curptr) + align_overhead;
+      
+      /* Add the region to memory map */
+      grub_efiemu_add_to_mmap (PTR_TO_UINT64 (typestart), 
+                              curptr - typestart, reqorder[i]);
+    }
+
+  return GRUB_ERR_NONE;
+}
+
+/* Get a pointer to requested memory from handle */
+void *
+grub_efiemu_mm_obtain_request (int handle)
+{
+  struct grub_efiemu_memrequest *cur;
+  for (cur = memrequests; cur; cur = cur->next)
+    if (cur->handle == handle)
+      return cur->val;
+  return 0;
+}
+
+/* Get type of requested memory by handle */
+grub_efi_memory_type_t
+grub_efiemu_mm_get_type (int handle)
+{
+  struct grub_efiemu_memrequest *cur;
+  for (cur = memrequests; cur; cur = cur->next)
+    if (cur->handle == handle)
+      return cur->type;
+  return 0;
+}
+
+/* Free a request */
+void
+grub_efiemu_mm_return_request (int handle)
+{
+  struct grub_efiemu_memrequest *cur, *prev;
+
+  /* Remove head if necessary */
+  while (memrequests && memrequests->handle == handle)
+    {
+      cur = memrequests->next;
+      grub_free (memrequests);
+      memrequests = cur;
+    }
+  if (!memrequests)
+    return;
+
+  /* Remove request from a middle of chain*/
+  for (prev = memrequests, cur = prev->next; cur;)
+    if (cur->handle == handle)
+      {
+       prev->next = cur->next;
+       grub_free (cur);
+       cur = prev->next;
+      }
+    else
+      {
+       prev = cur;
+       cur = prev->next;
+      }
+}
+
+/* Reserve space for memory map */
+static grub_err_t
+grub_efiemu_mmap_init (void)
+{
+  auto int NESTED_FUNC_ATTR bounds_hook (grub_uint64_t, grub_uint64_t, 
+                                        grub_uint32_t);
+  int NESTED_FUNC_ATTR bounds_hook (grub_uint64_t addr __attribute__ 
((unused)),
+                                   grub_uint64_t size __attribute__ ((unused)),
+                                   grub_uint32_t type __attribute__ ((unused)))
+    {
+      mmap_reserved_size++;
+      return 0;
+    }
+
+  // the place for memory used by efiemu itself
+  mmap_reserved_size = GRUB_EFI_MAX_MEMORY_TYPE + 1;
+
+#ifndef GRUB_UTIL
+  grub_machine_mmap_iterate (bounds_hook);
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
+/* This is a drop-in replacement of grub_efi_get_memory_map */
+/* Get the memory map as defined in the EFI spec. Return 1 if successful,
+   return 0 if partial, or return -1 if an error occurs.  */
+int
+grub_efiemu_get_memory_map (grub_efi_uintn_t *memory_map_size,
+                           grub_efi_memory_descriptor_t *memory_map,
+                           grub_efi_uintn_t *map_key,
+                           grub_efi_uintn_t *descriptor_size,
+                           grub_efi_uint32_t *descriptor_version)
+{
+  if (!efiemu_mmap)
+    {
+      grub_error (GRUB_ERR_INVALID_COMMAND, 
+                 "you need to first launch efiemu_prepare");
+      return -1;
+    }
+
+  if (*memory_map_size < mmap_num * sizeof (grub_efi_memory_descriptor_t))
+    {
+      *memory_map_size = mmap_num * sizeof (grub_efi_memory_descriptor_t);
+      return 0;
+    }
+
+  *memory_map_size = mmap_num * sizeof (grub_efi_memory_descriptor_t);
+  grub_memcpy (memory_map, efiemu_mmap, *memory_map_size);
+  if (descriptor_size)
+    *descriptor_size = sizeof (grub_efi_memory_descriptor_t);
+  if (descriptor_version)
+    *descriptor_version = 1;
+  if (map_key)
+    *map_key = 0;
+
+  return 1;
+}
+
+/* Free everything */
+grub_err_t
+grub_efiemu_mm_unload (void)
+{
+  struct grub_efiemu_memrequest *cur, *d;
+  for (cur = memrequests; cur;)
+    {
+      d = cur->next;
+      grub_free (cur);
+      cur = d;
+    }
+  memrequests = 0;
+  grub_memset (&requested_memory, 0, sizeof (requested_memory));
+  grub_free (resident_memory);
+  resident_memory = 0;
+  grub_free (efiemu_mmap);
+  efiemu_mmap = 0;
+  mmap_reserved_size = mmap_num = 0;
+  return GRUB_ERR_NONE;
+}
+
+/* This function should be called before doing any requests */
+grub_err_t
+grub_efiemu_mm_init (void)
+{
+  grub_err_t err;
+
+  err = grub_efiemu_mm_unload ();
+  if (err)
+    return err;
+
+  grub_efiemu_mmap_init ();
+
+  return GRUB_ERR_NONE;
+}
+
+/* Copy host memory map */
+static grub_err_t
+grub_efiemu_mmap_fill (void)
+{
+  auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, 
grub_uint32_t);
+  int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr,
+                                 grub_uint64_t size,
+                                 grub_uint32_t type)
+    {
+      switch (type)
+       {
+       case GRUB_MACHINE_MEMORY_AVAILABLE:
+         return grub_efiemu_add_to_mmap (addr, size, 
+                                         GRUB_EFI_CONVENTIONAL_MEMORY);
+
+#ifdef GRUB_MACHINE_MEMORY_ACPI
+       case GRUB_MACHINE_MEMORY_ACPI:
+         return grub_efiemu_add_to_mmap (addr, size, 
+                                         GRUB_EFI_ACPI_RECLAIM_MEMORY);
+#endif
+
+#ifdef GRUB_MACHINE_MEMORY_NVS
+       case GRUB_MACHINE_MEMORY_NVS:
+         return grub_efiemu_add_to_mmap (addr, size, 
+                                         GRUB_EFI_ACPI_MEMORY_NVS);
+#endif
+
+       default:
+         grub_printf ("Unknown memory type %d. Marking as unusable\n", type);
+       case GRUB_MACHINE_MEMORY_RESERVED:
+         return grub_efiemu_add_to_mmap (addr, size, 
+                                         GRUB_EFI_UNUSABLE_MEMORY);      
+       }
+    }
+
+#ifndef GRUB_UTIL
+  grub_machine_mmap_iterate (fill_hook);
+#endif
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, 
+                                                       grub_uint64_t, 
+                                                       grub_uint32_t))
+{
+  unsigned i;
+
+  for (i = 0; i < (unsigned) mmap_num; i++)
+    switch (efiemu_mmap[i].type)
+      {
+      case GRUB_EFI_RUNTIME_SERVICES_CODE:
+       hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, 
+             GRUB_EFIEMU_MEMORY_CODE);
+       break;
+       
+      case GRUB_EFI_RESERVED_MEMORY_TYPE:
+      case GRUB_EFI_RUNTIME_SERVICES_DATA:
+      case GRUB_EFI_UNUSABLE_MEMORY:
+      case GRUB_EFI_MEMORY_MAPPED_IO:
+      case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE:
+      case GRUB_EFI_PAL_CODE:
+      case GRUB_EFI_MAX_MEMORY_TYPE:
+       hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, 
+             GRUB_EFIEMU_MEMORY_RESERVED);
+       break;
+       
+      case GRUB_EFI_LOADER_CODE:
+      case GRUB_EFI_LOADER_DATA:
+      case GRUB_EFI_BOOT_SERVICES_CODE:
+      case GRUB_EFI_BOOT_SERVICES_DATA:
+      case GRUB_EFI_CONVENTIONAL_MEMORY:
+       hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, 
+             GRUB_EFIEMU_MEMORY_AVAILABLE);
+       break;
+       
+      case GRUB_EFI_ACPI_RECLAIM_MEMORY:
+       hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, 
+             GRUB_EFIEMU_MEMORY_ACPI);
+       break;
+       
+      case GRUB_EFI_ACPI_MEMORY_NVS:
+       hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, 
+             GRUB_EFIEMU_MEMORY_NVS);
+       break;
+      }
+  
+  return 0;
+}
+
+
+/* This function resolves overlapping regions and sorts the memory map
+   It uses scanline (sweeping) algorithm
+ */
+static grub_err_t
+grub_efiemu_mmap_sort_and_uniq (void)
+{
+  /* If same page is used by multiple types it's resolved 
+     according to priority 
+     0 - free memory
+     1 - memory immediately usable after ExitBootServices
+     2 - memory usable after loading ACPI tables
+     3 - efiemu memory
+     4 - unusable memory
+  */
+  int priority[GRUB_EFI_MAX_MEMORY_TYPE] =
+    {
+      [GRUB_EFI_RESERVED_MEMORY_TYPE] = 4,
+      [GRUB_EFI_LOADER_CODE] = 1,
+      [GRUB_EFI_LOADER_DATA] = 1,
+      [GRUB_EFI_BOOT_SERVICES_CODE] = 1,
+      [GRUB_EFI_BOOT_SERVICES_DATA] = 1,
+      [GRUB_EFI_RUNTIME_SERVICES_CODE] = 3,
+      [GRUB_EFI_RUNTIME_SERVICES_DATA] = 3,
+      [GRUB_EFI_CONVENTIONAL_MEMORY] = 0,
+      [GRUB_EFI_UNUSABLE_MEMORY] = 4,
+      [GRUB_EFI_ACPI_RECLAIM_MEMORY] = 2,
+      [GRUB_EFI_ACPI_MEMORY_NVS] = 3,
+      [GRUB_EFI_MEMORY_MAPPED_IO] = 4,
+      [GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE] = 4,
+      [GRUB_EFI_PAL_CODE] = 4
+    };
+
+  int i, j, k, done;
+
+  /* Scanline events */
+  struct grub_efiemu_mmap_scan
+  {
+    /* At which memory address*/
+    grub_uint64_t pos;
+    /* 0 = region starts, 1 = region ends */
+    int type;
+    /* Which type of memory region */
+    grub_efi_memory_type_t memtype;
+  };
+  struct grub_efiemu_mmap_scan *scanline_events;
+  struct grub_efiemu_mmap_scan t;
+
+  /* Previous scanline event */
+  grub_uint64_t lastaddr;
+  int lasttype;
+  /* Current scanline event */
+  int curtype;
+  /* how many regions of given type overlap at current location */
+  int present[GRUB_EFI_MAX_MEMORY_TYPE];
+  /* Here is stored the resulting memory map*/
+  grub_efi_memory_descriptor_t *result;
+
+  /* Initialize variables*/
+  grub_memset (present, 0, sizeof (int) * GRUB_EFI_MAX_MEMORY_TYPE);
+  scanline_events = (struct grub_efiemu_mmap_scan *) 
+    grub_malloc (sizeof (struct grub_efiemu_mmap_scan) * 2 * mmap_num);
+
+  /* Number of chunks can't increase more than by factor of 2 */
+  result = (grub_efi_memory_descriptor_t *) 
+    grub_malloc (sizeof (grub_efi_memory_descriptor_t) * 2 * mmap_num);
+  if (!result || !scanline_events)
+    {
+      grub_free (result);
+      grub_free (scanline_events);
+      return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                        "couldn't allocate space for new memory map");
+    }
+   
+  /* Register scanline events */
+  for (i = 0; i < mmap_num; i++)
+    {
+      scanline_events[2 * i].pos = efiemu_mmap[i].physical_start;
+      scanline_events[2 * i].type = 0;
+      scanline_events[2 * i].memtype = efiemu_mmap[i].type;
+      scanline_events[2 * i + 1].pos = efiemu_mmap[i].physical_start
+       + efiemu_mmap[i].num_pages * GRUB_EFIEMU_PAGESIZE;
+      scanline_events[2 * i + 1].type = 1;
+      scanline_events[2 * i + 1].memtype = efiemu_mmap[i].type;
+    }
+
+  /* Primitive bubble sort. It has complexity O(n^2) but since we're 
+     unlikely to have more than 100 chunks it's probably one of the 
+     fastest for one purpose */
+  done = 1;
+  while (done)
+    {
+      done = 0;
+      for (i = 0; i < 2 * mmap_num - 1; i++)
+       if (scanline_events[i + 1].pos < scanline_events[i].pos)
+         {
+           t = scanline_events[i + 1];
+           scanline_events[i + 1] = scanline_events[i];
+           scanline_events[i] = t;
+           done = 1;
+         }
+    }
+
+  /* Pointer in resulting memory map */
+  j = 0;
+  lastaddr = scanline_events[0].pos;
+  lasttype = scanline_events[0].memtype;
+  for (i = 0; i < 2 * mmap_num; i++)
+    {
+      /* Process event */
+      if (scanline_events[i].type)
+       present[scanline_events[i].memtype]--;
+      else
+       present[scanline_events[i].memtype]++;
+
+      /* Determine current region type */
+      curtype = -1;
+      for (k = 0; k < GRUB_EFI_MAX_MEMORY_TYPE; k++)
+       if (present[k] && (curtype == -1 || priority[k] > priority[curtype]))
+         curtype = k;
+
+      /* Add memory region to resulting map if necessary */
+      if ((curtype == -1 || curtype != lasttype) 
+         && lastaddr != scanline_events[i].pos
+         && lasttype != -1)
+       {
+         result[j].virtual_start = result[j].physical_start = lastaddr;
+         result[j].num_pages = (scanline_events[i].pos - lastaddr) 
+           / GRUB_EFIEMU_PAGESIZE;
+         result[j].type = lasttype;
+
+         /* We set runtime attribute on pages we need to be mapped */
+         result[j].attribute 
+           = (lasttype == GRUB_EFI_RUNTIME_SERVICES_CODE
+                  || lasttype == GRUB_EFI_RUNTIME_SERVICES_DATA)
+           ? GRUB_EFI_MEMORY_RUNTIME : 0;
+         grub_dprintf ("efiemu", 
+                       "mmap entry: type %d start 0x%llx 0x%llx pages\n", 
+                       result[j].type,
+                       result[j].physical_start, result[j].num_pages);
+         j++;
+       }
+
+      /* Update last values if necessary */
+      if (curtype == -1 || curtype != lasttype) 
+       {
+         lasttype = curtype;
+         lastaddr = scanline_events[i].pos;
+       }
+    }
+
+  grub_free (scanline_events);
+
+  /* Shrink resulting memory map to really used size and replace efiemu_mmap 
+     by new value */
+  grub_free (efiemu_mmap);
+  efiemu_mmap = grub_realloc (result, j * sizeof (*result));
+  return GRUB_ERR_NONE;
+}
+
+/* This function is called to switch from first to second phase */
+grub_err_t
+grub_efiemu_mm_do_alloc (void)
+{
+  grub_err_t err;
+
+  /* Preallocate mmap */
+  efiemu_mmap = (grub_efi_memory_descriptor_t *) 
+    grub_malloc (mmap_reserved_size * sizeof (grub_efi_memory_descriptor_t));
+  if (!efiemu_mmap)
+    {
+      grub_efiemu_unload ();
+      return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Couldn't initilaize mmap");
+    }
+
+  if ((err = efiemu_alloc_requests ()))
+    return err;
+  if ((err = grub_efiemu_mmap_fill ()))
+    return err;
+  return grub_efiemu_mmap_sort_and_uniq ();
+} 

Added: trunk/grub2/efiemu/pnvram.c
===================================================================
--- trunk/grub2/efiemu/pnvram.c                         (rev 0)
+++ trunk/grub2/efiemu/pnvram.c 2009-05-02 22:40:21 UTC (rev 2162)
@@ -0,0 +1,402 @@
+/* Export pnvram and some variables for runtime */
+/*
+ *  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/file.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/efiemu/efiemu.h>
+#include <grub/efiemu/runtime.h>
+#include <grub/extcmd.h>
+
+/* Place for final location of variables */
+static int nvram_handle = 0;
+static int nvramsize_handle = 0;
+static int high_monotonic_count_handle = 0;
+static int timezone_handle = 0;
+static int accuracy_handle = 0;
+static int daylight_handle = 0;
+
+/* Temporary place */
+static grub_uint8_t *nvram;
+static grub_size_t nvramsize;
+static grub_uint32_t high_monotonic_count;
+static grub_int16_t timezone;
+static grub_uint8_t daylight;
+static grub_uint32_t accuracy;
+
+static const struct grub_arg_option options[] = {
+  {"size", 's', 0, "number of bytes to reserve for pseudo NVRAM", 0,
+   ARG_TYPE_INT},
+  {"high-monotonic-count", 'm', 0, 
+   "Initial value of high monotonic count", 0, ARG_TYPE_INT},
+  {"timezone", 't', 0, 
+   "Timezone, offset in minutes from GMT", 0, ARG_TYPE_INT},
+  {"accuracy", 'a', 0, 
+   "Accuracy of clock, in 1e-12 units", 0, ARG_TYPE_INT},
+  {"daylight", 'd', 0, 
+   "Daylight value, as per EFI specifications", 0, ARG_TYPE_INT},
+  {0, 0, 0, 0, 0, 0}
+};
+
+/* Parse signed value */
+static int
+grub_strtosl (char *arg, char **end, int base)
+{
+  if (arg[0] == '-')
+    return -grub_strtoul (arg + 1, end, base);
+  return grub_strtoul (arg, end, base);
+}
+
+/* Export stuff for efiemu */
+static grub_err_t
+nvram_set (void * data __attribute__ ((unused)))
+{      
+  /* Take definitive pointers */
+  grub_uint8_t *nvram_def = grub_efiemu_mm_obtain_request (nvram_handle);
+  grub_uint32_t *nvramsize_def 
+    = grub_efiemu_mm_obtain_request (nvramsize_handle);
+  grub_uint32_t *high_monotonic_count_def
+    = grub_efiemu_mm_obtain_request (high_monotonic_count_handle);
+  grub_int16_t *timezone_def 
+    = grub_efiemu_mm_obtain_request (timezone_handle);
+  grub_uint8_t *daylight_def
+    = grub_efiemu_mm_obtain_request (daylight_handle);
+  grub_uint32_t *accuracy_def
+    = grub_efiemu_mm_obtain_request (accuracy_handle);
+
+  /* Copy to definitive loaction */
+  grub_dprintf ("efiemu", "preparing pnvram\n");
+  grub_memcpy (nvram_def, nvram, nvramsize);
+  *nvramsize_def = nvramsize;
+  *high_monotonic_count_def = high_monotonic_count;
+  *timezone_def = timezone;
+  *daylight_def = daylight;
+  *accuracy_def = accuracy;
+
+  /* Register symbols */
+  grub_efiemu_register_symbol ("efiemu_variables", nvram_handle, 0);
+  grub_efiemu_register_symbol ("efiemu_varsize", nvramsize_handle, 0);
+  grub_efiemu_register_symbol ("efiemu_high_monotonic_count", 
+                              high_monotonic_count_handle, 0);
+  grub_efiemu_register_symbol ("efiemu_time_zone", timezone_handle, 0);
+  grub_efiemu_register_symbol ("efiemu_time_daylight", daylight_handle, 0);
+  grub_efiemu_register_symbol ("efiemu_time_accuracy", 
+                              accuracy_handle, 0);
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+nvram_unload (void * data __attribute__ ((unused)))
+{
+  grub_efiemu_mm_return_request (nvram_handle);
+  grub_efiemu_mm_return_request (nvramsize_handle);
+  grub_efiemu_mm_return_request (high_monotonic_count_handle);
+  grub_efiemu_mm_return_request (timezone_handle);
+  grub_efiemu_mm_return_request (accuracy_handle);
+  grub_efiemu_mm_return_request (daylight_handle);
+
+  grub_free (nvram);
+  nvram = 0;
+}
+
+/* Load the variables file It's in format
+   guid1:attr1:name1:data1;
+   guid2:attr2:name2:data2;
+   ...
+   Where all fields are in hex
+*/
+static grub_err_t
+read_pnvram (char *filename)
+{
+  char *buf, *ptr, *ptr2;
+  grub_file_t file;
+  grub_size_t size;
+  grub_uint8_t *nvramptr = nvram;
+  struct efi_variable *efivar;
+  grub_size_t guidlen, datalen;
+  unsigned i, j;
+  
+  file = grub_file_open (filename);
+  if (!file)
+    return grub_error (GRUB_ERR_BAD_OS, "couldn't read pnvram");
+  size = grub_file_size (file);
+  buf = grub_malloc (size + 1);
+  if (!buf)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't read pnvram");
+  if (grub_file_read (file, buf, size) != (grub_ssize_t) size)
+    return grub_error (GRUB_ERR_BAD_OS, "couldn't read pnvram");
+  buf[size] = 0;
+  grub_file_close (file);
+
+  for (ptr = buf; *ptr; )
+    {
+      if (grub_isspace (*ptr))
+       {
+         ptr++;
+         continue;
+       }
+
+      efivar = (struct efi_variable *) nvramptr;
+      if (nvramptr - nvram + sizeof (struct efi_variable) > nvramsize)
+       return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                          "file is too large for reserved variable space");
+
+      nvramptr += sizeof (struct efi_variable);
+
+      /* look ahow long guid field is*/
+      guidlen = 0;      
+      for (ptr2 = ptr; (grub_isspace (*ptr2) 
+                       || (*ptr2 >= '0' && *ptr2 <= '9')
+                       || (*ptr2 >= 'a' && *ptr2 <= 'f')
+                       || (*ptr2 >= 'A' && *ptr2 <= 'F')); 
+          ptr2++)
+       if (!grub_isspace (*ptr2))
+         guidlen++;
+      guidlen /= 2;
+
+      /* Read guid */
+      if (guidlen != sizeof (efivar->guid))
+       {   
+         grub_free (buf);
+         return grub_error (GRUB_ERR_BAD_OS, "can't parse %s", filename);
+       }
+      for (i = 0; i < 2 * sizeof (efivar->guid); i++)
+       {
+         int hex = 0;
+         while (grub_isspace (*ptr))
+           ptr++;
+         if (*ptr >= '0' && *ptr <= '9')
+           hex = *ptr - '0';
+         if (*ptr >= 'a' && *ptr <= 'f')
+           hex = *ptr - 'a' + 10;
+         if (*ptr >= 'A' && *ptr <= 'F')
+           hex = *ptr - 'A' + 10;
+         
+         if (i%2 == 0)
+           ((grub_uint8_t *)&(efivar->guid))[i/2] = hex << 4;
+         else
+           ((grub_uint8_t *)&(efivar->guid))[i/2] |= hex;
+         ptr++;
+       }
+      
+      while (grub_isspace (*ptr))
+       ptr++;
+      if (*ptr != ':')
+       {
+         grub_dprintf ("efiemu", "Not colon\n");
+         grub_free (buf);
+         return grub_error (GRUB_ERR_BAD_OS, "can't parse %s", filename);
+       }
+      ptr++;
+      while (grub_isspace (*ptr))
+       ptr++;
+
+      /* Attributes can be just parsed by existing functions */
+      efivar->attributes = grub_strtoul (ptr, &ptr, 16);
+
+      while (grub_isspace (*ptr))
+       ptr++;
+      if (*ptr != ':')
+       {
+         grub_dprintf ("efiemu", "Not colon\n");
+         grub_free (buf);
+         return grub_error (GRUB_ERR_BAD_OS, "can't parse %s", filename);
+       }
+      ptr++;
+      while (grub_isspace (*ptr))
+       ptr++;
+
+      /* Read name and value */
+      for (j = 0; j < 2; j++)
+       {
+         /* Look the length */
+         datalen = 0;
+         for (ptr2 = ptr; *ptr2 && (grub_isspace (*ptr2) 
+                                    || (*ptr2 >= '0' && *ptr2 <= '9')
+                                    || (*ptr2 >= 'a' && *ptr2 <= 'f')
+                                    || (*ptr2 >= 'A' && *ptr2 <= 'F')); 
+              ptr2++)
+           if (!grub_isspace (*ptr2))
+             datalen++;
+         datalen /= 2;
+        
+         if (nvramptr - nvram + datalen > nvramsize)
+           {
+             grub_free (buf);
+             return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                                "file is too large for reserved "
+                                " variable space");
+           }
+         
+         for (i = 0; i < 2 * datalen; i++)
+           {
+             int hex = 0;
+             while (grub_isspace (*ptr))
+               ptr++;
+             if (*ptr >= '0' && *ptr <= '9')
+               hex = *ptr - '0';
+             if (*ptr >= 'a' && *ptr <= 'f')
+               hex = *ptr - 'a' + 10;
+             if (*ptr >= 'A' && *ptr <= 'F')
+               hex = *ptr - 'A' + 10;
+             
+             if (i%2 == 0)
+               nvramptr[i/2] = hex << 4;
+             else
+               nvramptr[i/2] |= hex;
+             ptr++;
+           }
+         nvramptr += datalen;
+         while (grub_isspace (*ptr))
+           ptr++;
+         if (*ptr != (j ? ';' : ':'))
+           {
+             grub_free (buf);
+             grub_dprintf ("efiemu", j?"Not semicolon\n":"Not colon\n");
+             return grub_error (GRUB_ERR_BAD_OS, "can't parse %s", filename);
+           }
+         if (j)
+           efivar->size = datalen;
+         else
+           efivar->namelen = datalen;
+         
+         ptr++;
+       }
+    }
+  grub_free (buf);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_efiemu_make_nvram (void)
+{
+  grub_err_t err;
+
+  err = grub_efiemu_autocore ();
+  if (err)
+    {
+      grub_free (nvram);
+      return err;
+    }
+
+  err = grub_efiemu_register_prepare_hook (nvram_set, nvram_unload, 0);
+  if (err)
+    {
+      grub_free (nvram);
+      return err;
+    }
+  nvram_handle 
+    = grub_efiemu_request_memalign (1, nvramsize, 
+                                   GRUB_EFI_RUNTIME_SERVICES_DATA);
+  nvramsize_handle 
+    = grub_efiemu_request_memalign (1, sizeof (grub_uint32_t), 
+                                   GRUB_EFI_RUNTIME_SERVICES_DATA);
+  high_monotonic_count_handle
+    = grub_efiemu_request_memalign (1, sizeof (grub_uint32_t), 
+                                   GRUB_EFI_RUNTIME_SERVICES_DATA);
+  timezone_handle
+    = grub_efiemu_request_memalign (1, sizeof (grub_uint16_t), 
+                                   GRUB_EFI_RUNTIME_SERVICES_DATA);
+  daylight_handle
+    = grub_efiemu_request_memalign (1, sizeof (grub_uint8_t), 
+                                   GRUB_EFI_RUNTIME_SERVICES_DATA);
+  accuracy_handle
+    = grub_efiemu_request_memalign (1, sizeof (grub_uint32_t), 
+                                   GRUB_EFI_RUNTIME_SERVICES_DATA);
+
+  grub_efiemu_request_symbols (6);
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_efiemu_pnvram (void)
+{
+  if (nvram)
+    return GRUB_ERR_NONE;
+
+  nvramsize = 2048;
+  high_monotonic_count = 1;
+  timezone = GRUB_EFI_UNSPECIFIED_TIMEZONE;
+  accuracy = 50000000;
+  daylight = 0;
+
+  nvram = grub_malloc (nvramsize);
+  if (!nvram)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                      "Couldn't allocate space for temporary pnvram storage");
+  grub_memset (nvram, 0, nvramsize);
+
+  return grub_efiemu_make_nvram ();
+}
+
+static grub_err_t
+grub_cmd_efiemu_pnvram (struct grub_extcmd *cmd,
+                       int argc, char **args)
+{
+  struct grub_arg_list *state = cmd->state;
+  grub_err_t err;
+
+  if (argc > 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "only one argument expected");
+
+  nvramsize = state[0].set ? grub_strtoul (state[0].arg, 0, 0) : 2048;
+  high_monotonic_count = state[1].set ? grub_strtoul (state[1].arg, 0, 0) : 1;
+  timezone = state[2].set ? grub_strtosl (state[2].arg, 0, 0) 
+    : GRUB_EFI_UNSPECIFIED_TIMEZONE;
+  accuracy = state[3].set ? grub_strtoul (state[3].arg, 0, 0) : 50000000;
+  daylight = state[4].set ? grub_strtoul (state[4].arg, 0, 0) : 0;
+  
+  nvram = grub_malloc (nvramsize);
+  if (!nvram)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                      "Couldn't allocate space for temporary pnvram storage");
+  grub_memset (nvram, 0, nvramsize);  
+
+  if (argc == 1 && (err = read_pnvram (args[0])))
+    {
+      grub_free (nvram);
+      return err;
+    }
+  return grub_efiemu_make_nvram ();
+}
+
+static grub_extcmd_t cmd;
+
+void grub_efiemu_pnvram_cmd_register (void);
+void grub_efiemu_pnvram_cmd_unregister (void);
+
+void
+grub_efiemu_pnvram_cmd_register (void)
+{
+  cmd = grub_register_extcmd ("efiemu_pnvram", grub_cmd_efiemu_pnvram, 
+                             GRUB_COMMAND_FLAG_BOTH,
+                             "efiemu_pnvram [FILENAME]",
+                             "Initialise pseudo-NVRAM and load variables "
+                             "from FILE", 
+                             options);
+}
+
+void
+grub_efiemu_pnvram_cmd_unregister (void)
+{
+  grub_unregister_extcmd (cmd);
+}

Added: trunk/grub2/efiemu/prepare.c
===================================================================
--- trunk/grub2/efiemu/prepare.c                                (rev 0)
+++ trunk/grub2/efiemu/prepare.c        2009-05-02 22:40:21 UTC (rev 2162)
@@ -0,0 +1,127 @@
+/* Prepare efiemu. E.g. allocate memory, load the runtime 
+   to appropriate place, etc */
+/*
+ *  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/err.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/efiemu/efiemu.h>
+#include <grub/lib/crc.h>
+
+grub_err_t
+SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks,
+                             struct grub_efiemu_configuration_table 
+                             *config_tables)
+{
+  grub_err_t err;
+  int conftable_handle;
+  struct grub_efiemu_configuration_table *cur;
+  struct grub_efiemu_prepare_hook *curhook;
+
+  int cntconftables = 0;
+  TYPE (grub_efiemu_configuration_table) *conftables = 0;
+  TYPE (grub_efiemu_runtime_services) *runtime_services;
+  int i;
+  int handle;
+  grub_off_t off;
+
+  grub_dprintf ("efiemu", "Preparing EfiEmu\n");
+
+  /* Request space for the list of configuration tables */
+  for (cur = config_tables; cur; cur = cur->next)
+    cntconftables++;
+  conftable_handle 
+    = grub_efiemu_request_memalign (GRUB_EFIEMU_PAGESIZE, 
+                                   cntconftables * sizeof (*conftables),
+                                   GRUB_EFI_RUNTIME_SERVICES_DATA);
+
+  /* Switch from phase 1 (counting) to phase 2 (real job) */
+  grub_efiemu_alloc_syms ();
+  grub_efiemu_mm_do_alloc ();
+
+  grub_efiemu_system_table32 = 0;
+  grub_efiemu_system_table64 = 0;
+
+  /* Execute hooks */
+  for (curhook = prepare_hooks; curhook; curhook = curhook->next)
+    curhook->hook (curhook->data);
+
+  /* Move runtime to its due place */
+  if ((err = grub_efiemu_loadcore_load ()))
+    {
+      grub_efiemu_unload ();
+      return err;
+    }
+
+  if ((err = grub_efiemu_resolve_symbol ("efiemu_system_table", 
+                                        &handle, &off)))
+    {
+      grub_efiemu_unload ();
+      return err;
+    }
+
+  SUFFIX (grub_efiemu_system_table)  
+    = (TYPE (grub_efi_system_table) *) 
+    ((grub_uint8_t *)grub_efiemu_mm_obtain_request (handle) + off);
+
+  /* compute CRC32 of runtime_services */
+  if ((err = grub_efiemu_resolve_symbol ("efiemu_runtime_services", 
+                                        &handle, &off)))
+    return err;
+  runtime_services = (TYPE (grub_efiemu_runtime_services) *)
+       ((grub_uint8_t *)grub_efiemu_mm_obtain_request (handle) + off);
+  runtime_services->hdr.crc32 = 0;
+  runtime_services->hdr.crc32 = grub_getcrc32 
+    (0, runtime_services, runtime_services->hdr.header_size);
+
+  /* Put pointer to the list of configuration tables in system table */
+  grub_efiemu_write_value
+    (&(SUFFIX (grub_efiemu_system_table)->configuration_table), 0, 
+     conftable_handle, 0, 1, 
+     sizeof (SUFFIX (grub_efiemu_system_table)->configuration_table));
+  SUFFIX(grub_efiemu_system_table)->num_table_entries = cntconftables;
+
+  /* Fill the list of configuration tables */
+  conftables = (TYPE (grub_efiemu_configuration_table) *)
+    grub_efiemu_mm_obtain_request (conftable_handle);
+  i = 0;
+  for (cur = config_tables; cur; cur = cur->next, i++)
+    {
+      grub_memcpy (&(conftables[i].vendor_guid), &(cur->guid), 
+                      sizeof (cur->guid));
+      if (cur->get_table)
+       conftables[i].vendor_table
+         = PTR_TO_UINT64 (cur->get_table (cur->data));
+      else
+       conftables[i].vendor_table = PTR_TO_UINT64 (cur->data);
+    }
+
+  /* compute CRC32 of system table */
+  SUFFIX (grub_efiemu_system_table)->hdr.crc32 = 0;
+  SUFFIX (grub_efiemu_system_table)->hdr.crc32 
+    = grub_getcrc32 (0, SUFFIX (grub_efiemu_system_table), 
+                    SUFFIX (grub_efiemu_system_table)->hdr.header_size);
+
+  grub_dprintf ("efiemu","system_table = %p, runtime_services = %p,"
+               " conftables = %p (%d entries)\n",
+               SUFFIX (grub_efiemu_system_table), runtime_services, 
+               conftables, cntconftables);
+
+  return GRUB_ERR_NONE;
+}

Added: trunk/grub2/efiemu/prepare32.c
===================================================================
--- trunk/grub2/efiemu/prepare32.c                              (rev 0)
+++ trunk/grub2/efiemu/prepare32.c      2009-05-02 22:40:21 UTC (rev 2162)
@@ -0,0 +1,23 @@
+/* This file contains definitions so that prepare.c compiles for 32-bit */
+/*
+ *  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/>.
+ */
+
+#define SUFFIX(x) x ## 32
+#define TYPE(x) x ## 32_t
+
+#include "prepare.c"

Added: trunk/grub2/efiemu/prepare64.c
===================================================================
--- trunk/grub2/efiemu/prepare64.c                              (rev 0)
+++ trunk/grub2/efiemu/prepare64.c      2009-05-02 22:40:21 UTC (rev 2162)
@@ -0,0 +1,23 @@
+/* This file contains definitions so that prepare.c compiles for 64-bit */
+/*
+ *  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/>.
+ */
+
+#define SUFFIX(x) x ## 64
+#define TYPE(x) x ## 64_t
+
+#include "prepare.c"

Added: trunk/grub2/efiemu/runtime/config.h
===================================================================
--- trunk/grub2/efiemu/runtime/config.h                         (rev 0)
+++ trunk/grub2/efiemu/runtime/config.h 2009-05-02 22:40:21 UTC (rev 2162)
@@ -0,0 +1,34 @@
+/* This is a pseudo config.h so that types.h compiles nicely */
+/*
+ *  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/>.
+ */
+
+#define GRUB_TYPES_CPU_HEADER  1
+
+#ifdef ELF32
+# define SIZEOF_VOID_P 4
+# define SIZEOF_LONG   4
+# define GRUB_TARGET_SIZEOF_VOID_P     4
+# define GRUB_TARGET_SIZEOF_LONG       4
+# define EFI_FUNC(x) x
+#else
+# define SIZEOF_VOID_P 8
+# define SIZEOF_LONG   8
+# define GRUB_TARGET_SIZEOF_VOID_P     8
+# define GRUB_TARGET_SIZEOF_LONG       8
+# define EFI_FUNC(x) x ## _real
+#endif

Added: trunk/grub2/efiemu/runtime/efiemu.S
===================================================================
--- trunk/grub2/efiemu/runtime/efiemu.S                         (rev 0)
+++ trunk/grub2/efiemu/runtime/efiemu.S 2009-05-02 22:40:21 UTC (rev 2162)
@@ -0,0 +1,159 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,2007,2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/symbol.h>
+
+/*
+ * x86_64 uses registry to pass parameters. Unfortunately, gcc and efi use
+ * different call conversion, so we need to do some conversion.
+ *
+ * gcc:
+ *   %rdi,  %rsi,  %rdx,  %rcx, %r8, %r9, 8(%rsp), 16(%rsp), ...
+ *
+ * efi:
+ *   %rcx,  %rdx,  %r8,  %r9,  32(%rsp), 40(%rsp), 48(%rsp), ...
+ *
+ */
+       
+        .file   "efiemu.S"
+       .text
+       
+FUNCTION (efiemu_get_time)
+       push %rdi
+       push %rsi
+       mov %rcx, %rdi
+       mov %rdx, %rsi
+       call efiemu_get_time_real
+       pop %rsi
+       pop %rdi
+       ret
+
+FUNCTION (efiemu_set_time)
+       push %rdi
+       push %rsi
+       mov %rcx, %rdi
+       call efiemu_set_time_real
+       pop %rsi
+       pop %rdi
+       ret
+
+
+FUNCTION (efiemu_get_wakeup_time)
+       push %rdi
+       push %rsi
+       mov %rcx, %rdi
+       mov %rdx, %rsi
+       mov %r8, %rdx
+       call efiemu_get_wakeup_time_real
+       pop %rsi
+       pop %rdi
+       ret
+
+FUNCTION (efiemu_set_wakeup_time)
+       push %rdi
+       push %rsi
+       mov %rcx, %rdi
+       mov %rdx, %rsi
+       call efiemu_set_wakeup_time_real
+       pop %rsi
+       pop %rdi
+       ret
+
+FUNCTION (efiemu_get_variable)
+       push %rdi
+       push %rsi
+       mov %rcx, %rdi
+       mov %rdx, %rsi
+       mov %r8, %rdx
+       mov %r9, %rcx
+       mov 56(%rsp), %r8
+       call efiemu_get_variable_real
+       pop %rsi
+       pop %rdi
+       ret
+
+FUNCTION (efiemu_get_next_variable_name)
+       push %rdi
+       push %rsi
+       mov %rcx, %rdi
+       mov %rdx, %rsi
+       mov %r8, %rdx
+       call efiemu_get_next_variable_name_real
+       pop %rsi
+       pop %rdi
+       ret
+
+FUNCTION (efiemu_set_variable)
+       push %rdi
+       push %rsi
+       mov %rcx, %rdi
+       mov %rdx, %rsi
+       mov %r8, %rdx
+       mov %r9, %rcx   
+       mov 56(%rsp), %r8
+       call efiemu_set_variable_real
+       pop %rsi
+       pop %rdi
+       ret
+
+FUNCTION (efiemu_get_next_high_monotonic_count)
+       push %rdi
+       push %rsi
+       mov %rcx, %rdi
+       call efiemu_get_next_high_monotonic_count_real
+       pop %rsi
+       pop %rdi
+       ret
+
+FUNCTION (efiemu_reset_system)
+       push %rdi
+       push %rsi
+       mov %rcx, %rdi
+       mov %rdx, %rsi
+       mov %r8, %rdx
+       mov %r9, %rcx
+       call efiemu_reset_system_real
+       pop %rsi
+       pop %rdi
+       ret
+
+       /* The following functions are always called in physical mode */
+       .section ".text-physical", "ax"         
+       
+FUNCTION (efiemu_set_virtual_address_map)
+       push %rdi
+       push %rsi
+       mov %rcx, %rdi
+       mov %rdx, %rsi
+       mov %r8, %rdx
+       mov %r9, %rcx
+       call efiemu_set_virtual_address_map_real
+       pop %rsi
+       pop %rdi
+       ret
+
+FUNCTION (efiemu_convert_pointer)
+       push %rdi
+       push %rsi
+       mov %rcx, %rdi
+       mov %rdx, %rsi
+       call efiemu_convert_pointer_real
+       pop %rsi
+       pop %rdi
+       ret
+

Added: trunk/grub2/efiemu/runtime/efiemu.c
===================================================================
--- trunk/grub2/efiemu/runtime/efiemu.c                         (rev 0)
+++ trunk/grub2/efiemu/runtime/efiemu.c 2009-05-02 22:40:21 UTC (rev 2162)
@@ -0,0 +1,623 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2006,2007,2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* This is an emulation of EFI runtime services.
+   This allows a more uniform boot on i386 machines. 
+   As it emulates only runtime serviceit isn't able 
+   to chainload EFI bootloader on non-EFI system (TODO) */
+
+#include <grub/symbol.h>
+#include <grub/types.h>
+#include <grub/efi/api.h>
+#include <grub/efiemu/runtime.h>
+
+grub_efi_status_t 
+efiemu_get_time (grub_efi_time_t *time,
+                grub_efi_time_capabilities_t *capabilities);
+grub_efi_status_t
+efiemu_set_time (grub_efi_time_t *time);
+
+grub_efi_status_t
+efiemu_get_wakeup_time (grub_efi_boolean_t *enabled,
+                       grub_efi_boolean_t *pending,
+                       grub_efi_time_t *time);
+grub_efi_status_t
+efiemu_set_wakeup_time (grub_efi_boolean_t enabled,
+                       grub_efi_time_t *time);
+
+
+grub_efi_status_t
+efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
+                               grub_efi_uintn_t descriptor_size,
+                               grub_efi_uint32_t descriptor_version,
+                               grub_efi_memory_descriptor_t *virtual_map)
+  __attribute__ ((section(".text-physical")));
+
+grub_efi_status_t
+efiemu_convert_pointer (grub_efi_uintn_t debug_disposition, 
+                       void **address)
+  __attribute__ ((section(".text-physical")));
+
+grub_efi_status_t
+efiemu_get_variable (grub_efi_char16_t *variable_name,
+                    grub_efi_guid_t *vendor_guid,
+                    grub_efi_uint32_t *attributes,
+                    grub_efi_uintn_t *data_size,
+                    void *data);
+
+grub_efi_status_t
+efiemu_get_next_variable_name (grub_efi_uintn_t *variable_name_size,
+                              grub_efi_char16_t *variable_name,
+                              grub_efi_guid_t *vendor_guid);
+
+grub_efi_status_t
+efiemu_set_variable (grub_efi_char16_t *variable_name,
+                    grub_efi_guid_t *vendor_guid,
+                    grub_efi_uint32_t attributes,
+                    grub_efi_uintn_t data_size,
+                    void *data);
+grub_efi_status_t
+efiemu_get_next_high_monotonic_count (grub_efi_uint32_t *high_count);
+void
+efiemu_reset_system (grub_efi_reset_type_t reset_type,
+                    grub_efi_status_t reset_status,
+                    grub_efi_uintn_t data_size,
+                    grub_efi_char16_t *reset_data);
+
+grub_efi_status_t 
+EFI_FUNC (efiemu_set_virtual_address_map) (grub_efi_uintn_t,
+                                             grub_efi_uintn_t,
+                                             grub_efi_uint32_t,
+                                             grub_efi_memory_descriptor_t *)
+  __attribute__ ((section(".text-physical")));
+grub_efi_status_t
+EFI_FUNC (efiemu_convert_pointer) (grub_efi_uintn_t debug_disposition, 
+                                     void **address)
+  __attribute__ ((section(".text-physical")));
+static grub_uint32_t
+efiemu_getcrc32 (grub_uint32_t crc, void *buf, int size)
+     __attribute__ ((section(".text-physical")));
+static void
+init_crc32_table (void)
+  __attribute__ ((section(".text-physical")));
+                            
+/*
+  The log. It's used when examining memory dump
+*/                                  
+static grub_uint8_t loge[1000] = "EFIEMULOG";
+static int logn = 9; 
+#define LOG(x)   { if (logn<900) loge[logn++]=x; }
+
+static int ptv_relocated = 0;
+
+/* Interface with grub */
+struct grub_efi_runtime_services efiemu_runtime_services;
+struct grub_efi_system_table efiemu_system_table;
+extern struct grub_efiemu_ptv_rel efiemu_ptv_relloc[];
+extern grub_uint8_t efiemu_variables[];
+extern grub_uint32_t efiemu_varsize;
+extern grub_uint32_t efiemu_high_monotonic_count;
+extern grub_int16_t efiemu_time_zone;
+extern grub_uint8_t efiemu_time_daylight;
+extern grub_uint32_t efiemu_time_accuracy;
+
+/* Some standard functions because we need to be stadalone */
+static void
+efiemu_memcpy (void *to, void *from, int count)
+{
+  int i;
+  for (i = 0; i < count; i++)
+    ((grub_uint8_t *) to)[i] = ((grub_uint8_t *) from)[i];
+}
+
+static int
+efiemu_str16equal (grub_uint16_t *a, grub_uint16_t *b)
+{
+  grub_uint16_t *ptr1, *ptr2;
+  for (ptr1=a,ptr2=b; *ptr1 && *ptr2 == *ptr1; ptr1++, ptr2++);
+  return *ptr2 == *ptr1;
+}
+
+static grub_size_t
+efiemu_str16len (grub_uint16_t *a)
+{
+  grub_uint16_t *ptr1;
+  for (ptr1 = a; *ptr1; ptr1++);
+  return ptr1 - a;
+}
+
+static int
+efiemu_memequal (void *a, void *b, grub_size_t n)
+{
+  grub_uint8_t *ptr1, *ptr2;
+  for (ptr1 = (grub_uint8_t *) a, ptr2 = (grub_uint8_t *)b;
+       ptr1 < (grub_uint8_t *)a + n && *ptr2 == *ptr1; ptr1++, ptr2++);
+  return ptr1 == a + n;
+}
+
+static void
+efiemu_memset (grub_uint8_t *a, grub_uint8_t b, grub_size_t n)
+{
+  grub_uint8_t *ptr1;
+  for (ptr1=a; ptr1 < a + n; ptr1++)
+    *ptr1 = b;
+}
+
+static inline void
+write_cmos (grub_uint8_t addr, grub_uint8_t val)
+{
+  __asm__ __volatile__ ("outb %%al,$0x70\n"
+                       "mov %%bl, %%al\n"
+                       "outb %%al,$0x71": :"a" (addr), "b" (val));
+}
+
+static inline grub_uint8_t
+read_cmos (grub_uint8_t addr)
+{
+  grub_uint8_t ret;
+  __asm__ __volatile__ ("outb %%al, $0x70\n"
+                       "inb $0x71, %%al": "=a"(ret) :"a" (addr));
+  return ret;
+}
+
+/* Needed by some gcc versions */
+int __stack_chk_fail ()
+{
+  return 0;
+}
+
+/* The function that implement runtime services as specified in 
+   EFI specification */
+static inline grub_uint8_t
+bcd_to_hex (grub_uint8_t in)
+{
+  return 10 * ((in & 0xf0) >> 4) + (in & 0x0f);
+}
+
+grub_efi_status_t 
+EFI_FUNC (efiemu_get_time) (grub_efi_time_t *time,
+                              grub_efi_time_capabilities_t *capabilities)
+{
+  LOG ('a');
+  grub_uint8_t state;
+  state = read_cmos (0xb);
+  if (!(state & (1 << 2)))
+    {
+      time->year = 2000 + bcd_to_hex (read_cmos (0x9));
+      time->month = bcd_to_hex (read_cmos (0x8));
+      time->day = bcd_to_hex (read_cmos (0x7));
+      time->hour = bcd_to_hex (read_cmos (0x4));
+      if (time->hour >= 81)
+       time->hour -= 80 - 12;
+      if (time->hour == 24)
+       time->hour = 0;
+      time->minute = bcd_to_hex (read_cmos (0x2));
+      time->second = bcd_to_hex (read_cmos (0x0));
+    }
+  else
+    {
+      time->year = 2000 + read_cmos (0x9);
+      time->month = read_cmos (0x8);
+      time->day = read_cmos (0x7);
+      time->hour = read_cmos (0x4);
+      if (time->hour >= 0x81)
+       time->hour -= 0x80 - 12;
+      if (time->hour == 24)
+       time->hour = 0;
+      time->minute = read_cmos (0x2);
+      time->second = read_cmos (0x0);
+    }
+  time->nanosecond = 0;
+  time->pad1 = 0;
+  time->pad2 = 0;
+  time->time_zone = efiemu_time_zone;
+  time->daylight = efiemu_time_daylight;
+  capabilities->resolution = 1;
+  capabilities->accuracy = efiemu_time_accuracy;
+  capabilities->sets_to_zero = 0;
+  return GRUB_EFI_SUCCESS;
+}
+
+grub_efi_status_t
+EFI_FUNC (efiemu_set_time) (grub_efi_time_t *time)
+{
+  LOG ('b');
+  grub_uint8_t state;
+  state = read_cmos (0xb);
+  write_cmos (0xb, state | 0x6);
+  write_cmos (0x9, time->year - 2000);
+  write_cmos (0x8, time->month);
+  write_cmos (0x7, time->day);
+  write_cmos (0x4, time->hour);
+  write_cmos (0x2, time->minute);
+  write_cmos (0x0, time->second);
+  efiemu_time_zone = time->time_zone;
+  efiemu_time_daylight = time->daylight;
+  return GRUB_EFI_SUCCESS;
+}
+
+/* Folowing 2 functions are vendor specific. So announce it as unsupported */
+grub_efi_status_t
+EFI_FUNC (efiemu_get_wakeup_time) (grub_efi_boolean_t *enabled,
+                                     grub_efi_boolean_t *pending,
+                                     grub_efi_time_t *time)
+{
+  LOG ('c');
+  return GRUB_EFI_UNSUPPORTED;
+}
+
+grub_efi_status_t
+EFI_FUNC (efiemu_set_wakeup_time) (grub_efi_boolean_t enabled,
+                                     grub_efi_time_t *time)
+{
+  LOG ('d');
+  return GRUB_EFI_UNSUPPORTED;
+}
+
+static grub_uint32_t crc32_table [256];
+
+static void
+init_crc32_table (void)
+{
+  auto grub_uint32_t reflect (grub_uint32_t ref, int len);
+  grub_uint32_t reflect (grub_uint32_t ref, int len)
+    {
+      grub_uint32_t result = 0;
+      int i;
+
+      for (i = 1; i <= len; i++)
+        {
+          if (ref & 1)
+            result |= 1 << (len - i);
+          ref >>= 1;
+        }
+
+      return result;
+    }
+
+  grub_uint32_t polynomial = 0x04c11db7;
+  int i, j;
+
+  for(i = 0; i < 256; i++)
+    {
+      crc32_table[i] = reflect(i, 8) << 24;
+      for (j = 0; j < 8; j++)
+        crc32_table[i] = (crc32_table[i] << 1) ^
+            (crc32_table[i] & (1 << 31) ? polynomial : 0);
+      crc32_table[i] = reflect(crc32_table[i], 32);
+    }
+}
+
+static grub_uint32_t
+efiemu_getcrc32 (grub_uint32_t crc, void *buf, int size)
+{
+  int i;
+  grub_uint8_t *data = buf;
+
+  if (! crc32_table[1])
+    init_crc32_table ();
+
+  crc^= 0xffffffff;
+
+  for (i = 0; i < size; i++)
+    {
+      crc = (crc >> 8) ^ crc32_table[(crc & 0xFF) ^ *data];
+      data++;
+    }
+
+  return crc ^ 0xffffffff;
+}
+
+
+grub_efi_status_t EFI_FUNC 
+(efiemu_set_virtual_address_map) (grub_efi_uintn_t memory_map_size,
+                                 grub_efi_uintn_t descriptor_size,
+                                 grub_efi_uint32_t descriptor_version,
+                                 grub_efi_memory_descriptor_t *virtual_map)
+{
+  struct grub_efiemu_ptv_rel *cur_relloc;
+
+  LOG ('e');
+  
+  /* Ensure that we are called only once */
+  if (ptv_relocated)
+    return GRUB_EFI_UNSUPPORTED;
+  ptv_relocated = 1;
+  
+  /* Correct addresses using information supplied by grub */
+  for (cur_relloc = efiemu_ptv_relloc; cur_relloc->size;cur_relloc++)
+    {
+      grub_int64_t corr = 0;
+      grub_efi_memory_descriptor_t *descptr;
+
+      /* Compute correction */
+      for (descptr = virtual_map;  
+          ((grub_uint8_t *) descptr - (grub_uint8_t *) virtual_map) 
+            < memory_map_size;
+          descptr = (grub_efi_memory_descriptor_t *)
+            ((grub_uint8_t *) descptr + descriptor_size))
+       {
+         if (descptr->type == cur_relloc->plustype)
+           corr += descptr->virtual_start - descptr->physical_start;
+         if (descptr->type == cur_relloc->minustype)
+           corr -= descptr->virtual_start - descptr->physical_start;
+       }
+
+      /* Apply correction */
+      switch (cur_relloc->size)
+       {
+       case 8:
+         *((grub_uint64_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
+         break;
+       case 4:
+         *((grub_uint32_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
+         break;
+       case 2:
+         *((grub_uint16_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
+         break;
+       case 1:
+         *((grub_uint8_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
+         break;
+       }
+    }
+
+  /* Recompute crc32 of system table and runtime services */
+  efiemu_system_table.hdr.crc32 = 0;
+  efiemu_system_table.hdr.crc32 = efiemu_getcrc32 
+    (0, &efiemu_system_table, sizeof (efiemu_system_table));
+
+  efiemu_runtime_services.hdr.crc32 = 0;
+  efiemu_runtime_services.hdr.crc32 = efiemu_getcrc32 
+    (0, &efiemu_runtime_services, sizeof (efiemu_runtime_services));
+
+  return GRUB_EFI_SUCCESS;
+}
+
+/* since efiemu_set_virtual_address_map corrects all the pointers 
+   we don't need efiemu_convert_pointer */
+grub_efi_status_t
+EFI_FUNC (efiemu_convert_pointer) (grub_efi_uintn_t debug_disposition, 
+                                     void **address)
+{
+  LOG ('f');
+  return GRUB_EFI_UNSUPPORTED;
+}
+
+/* Next comes variable services. Because we have no vendor-independent 
+   way to store these variables we have no non-volatility */
+
+/* Find variable by name and GUID. */
+static struct efi_variable *
+find_variable (grub_efi_guid_t *vendor_guid,
+              grub_efi_char16_t *variable_name)
+{
+  grub_uint8_t *ptr;
+  struct efi_variable *efivar;
+
+  for (ptr = efiemu_variables; ptr < efiemu_variables + efiemu_varsize; )
+    {
+      efivar = (struct efi_variable *) ptr;
+      if (!efivar->namelen)
+       return 0;
+      if (efiemu_str16equal((grub_efi_char16_t *)(efivar + 1), variable_name)
+         && efiemu_memequal (&(efivar->guid), vendor_guid, 
+                             sizeof (efivar->guid)))
+       return efivar;
+      ptr += efivar->namelen + efivar->size + sizeof (*efivar);
+    }
+  return 0;
+}
+
+grub_efi_status_t
+EFI_FUNC (efiemu_get_variable) (grub_efi_char16_t *variable_name,
+                                  grub_efi_guid_t *vendor_guid,
+                                  grub_efi_uint32_t *attributes,
+                                  grub_efi_uintn_t *data_size,
+                                  void *data)
+{
+  struct efi_variable *efivar;
+  LOG ('g');
+  efivar = find_variable (vendor_guid, variable_name);
+  if (!efivar)
+    return GRUB_EFI_NOT_FOUND;
+  if (*data_size < efivar->size)
+    {
+      *data_size = efivar->size;
+      return GRUB_EFI_BUFFER_TOO_SMALL;
+    }
+  *data_size = efivar->size;
+  efiemu_memcpy (data, (grub_uint8_t *)(efivar + 1) + efivar->namelen,
+                efivar->size);
+  *attributes = efivar->attributes;
+  
+  return GRUB_EFI_SUCCESS;
+}
+
+grub_efi_status_t EFI_FUNC 
+(efiemu_get_next_variable_name) (grub_efi_uintn_t *variable_name_size,
+                                grub_efi_char16_t *variable_name,
+                                grub_efi_guid_t *vendor_guid)
+{
+  struct efi_variable *efivar;
+  LOG ('l');
+
+  if (!variable_name_size || !variable_name || !vendor_guid)
+    return GRUB_EFI_INVALID_PARAMETER;
+  if (variable_name[0])
+    {
+      efivar = find_variable (vendor_guid, variable_name);
+      if (!efivar)
+       return GRUB_EFI_NOT_FOUND;
+      efivar = (struct efi_variable *)((grub_uint8_t *)efivar 
+                                      + efivar->namelen 
+                                      + efivar->size + sizeof (*efivar));
+    }
+  else
+    efivar = (struct efi_variable *) (efiemu_variables);
+
+  LOG ('m');
+  if ((grub_uint8_t *)efivar >= efiemu_variables + efiemu_varsize 
+      || !efivar->namelen)
+    return GRUB_EFI_NOT_FOUND;
+  if (*variable_name_size < efivar->namelen)
+    {
+      *variable_name_size = efivar->namelen;
+      return GRUB_EFI_BUFFER_TOO_SMALL;
+    }
+
+  efiemu_memcpy (variable_name, efivar + 1, efivar->namelen);
+  efiemu_memcpy (vendor_guid, &(efivar->guid), 
+                sizeof (efivar->guid));
+
+  LOG('h');
+  return GRUB_EFI_SUCCESS;
+}
+
+grub_efi_status_t
+EFI_FUNC (efiemu_set_variable) (grub_efi_char16_t *variable_name,
+                                  grub_efi_guid_t *vendor_guid,
+                                  grub_efi_uint32_t attributes,
+                                  grub_efi_uintn_t data_size,
+                                  void *data)
+{
+  struct efi_variable *efivar;
+  grub_uint8_t *ptr;
+  LOG('i');
+  if (!variable_name[0])
+    return GRUB_EFI_INVALID_PARAMETER;
+  efivar = find_variable (vendor_guid, variable_name);
+
+  /* Delete variable if any */
+  if (efivar)
+    {
+      efiemu_memcpy (efivar, (grub_uint8_t *)(efivar + 1) 
+                    + efivar->namelen + efivar->size, 
+                    (efiemu_variables + efiemu_varsize)
+                    - ((grub_uint8_t *)(efivar + 1) 
+                       + efivar->namelen + efivar->size));
+      efiemu_memset (efiemu_variables + efiemu_varsize 
+                    - (sizeof (*efivar) + efivar->namelen + efivar->size),
+                    0, (sizeof (*efivar) + efivar->namelen + efivar->size));
+    }
+
+  if (!data_size)
+    return GRUB_EFI_SUCCESS;
+
+  for (ptr = efiemu_variables; ptr < efiemu_variables + efiemu_varsize; )
+    {
+      efivar = (struct efi_variable *) ptr;
+      ptr += efivar->namelen + efivar->size + sizeof (*efivar);
+      if (!efivar->namelen)
+       break;
+    }
+  if ((grub_uint8_t *)(efivar + 1) + data_size 
+      + 2 * (efiemu_str16len (variable_name) + 1) 
+      >= efiemu_variables + efiemu_varsize)
+    return GRUB_EFI_OUT_OF_RESOURCES;
+
+  efiemu_memcpy (&(efivar->guid), vendor_guid, sizeof (efivar->guid));
+  efivar->namelen = 2 * (efiemu_str16len (variable_name) + 1);
+  efivar->size = data_size;
+  efivar->attributes = attributes;
+  efiemu_memcpy (efivar + 1, variable_name, 
+                2 * (efiemu_str16len (variable_name) + 1));
+  efiemu_memcpy ((grub_uint8_t *)(efivar + 1) 
+                + 2 * (efiemu_str16len (variable_name) + 1), 
+                data, data_size);
+
+  return GRUB_EFI_SUCCESS;
+}
+
+grub_efi_status_t EFI_FUNC 
+(efiemu_get_next_high_monotonic_count) (grub_efi_uint32_t *high_count)
+{
+  LOG ('j');
+  if (!high_count)
+    return GRUB_EFI_INVALID_PARAMETER;
+  *high_count = ++efiemu_high_monotonic_count;
+  return GRUB_EFI_SUCCESS;
+}
+
+/* To implement it with APM we need to go to real mode. It's too much hassle
+   Besides EFI specification says that this function shouldn't be used
+   on systems supporting ACPI
+ */
+void
+EFI_FUNC (efiemu_reset_system) (grub_efi_reset_type_t reset_type,
+                                  grub_efi_status_t reset_status,
+                                  grub_efi_uintn_t data_size,
+                                  grub_efi_char16_t *reset_data)
+{
+  LOG ('k');
+}
+
+struct grub_efi_runtime_services efiemu_runtime_services = 
+{
+  .hdr = 
+  {
+    .signature = GRUB_EFIEMU_RUNTIME_SERVICES_SIGNATURE,
+    .revision = 0x0001000a,
+    .header_size = sizeof (struct grub_efi_runtime_services),
+    .crc32 = 0, /* filled later*/
+    .reserved = 0
+  },
+  .get_time = efiemu_get_time,
+  .set_time = efiemu_set_time,
+  .get_wakeup_time = efiemu_get_wakeup_time,
+  .set_wakeup_time = efiemu_set_wakeup_time,
+
+  .set_virtual_address_map = efiemu_set_virtual_address_map,
+  .convert_pointer = efiemu_convert_pointer,
+
+  .get_variable = efiemu_get_variable,
+  .get_next_variable_name = efiemu_get_next_variable_name,
+  .set_variable = efiemu_set_variable,
+  .get_next_high_monotonic_count = efiemu_get_next_high_monotonic_count,
+  
+  .reset_system = efiemu_reset_system
+};
+
+
+static grub_uint16_t efiemu_vendor[] = 
+  {'G', 'R', 'U', 'B', ' ', 'E', 'F', 'I', ' ',
+   'R', 'U', 'N', 'T', 'I', 'M', 'E', 0};
+
+struct grub_efi_system_table efiemu_system_table =
+{
+  .hdr = 
+  {
+    .signature = GRUB_EFIEMU_SYSTEM_TABLE_SIGNATURE,
+    .revision = 0x0001000a,
+    .header_size = sizeof (struct grub_efi_system_table),
+    .crc32 = 0, /* filled later*/
+    .reserved = 0
+  },
+  .firmware_vendor = efiemu_vendor,
+  .firmware_revision = 0x0001000a,
+  .console_in_handler = 0,
+  .con_in = 0,
+  .console_out_handler = 0,
+  .con_out = 0,
+  .standard_error_handle = 0,
+  .std_err = 0,
+  .runtime_services = &efiemu_runtime_services,
+  .boot_services = 0,
+  .num_table_entries = 0,
+  .configuration_table = 0
+};
+

Added: trunk/grub2/efiemu/runtime/efiemu.sh
===================================================================
--- trunk/grub2/efiemu/runtime/efiemu.sh                                (rev 0)
+++ trunk/grub2/efiemu/runtime/efiemu.sh        2009-05-02 22:40:21 UTC (rev 
2162)
@@ -0,0 +1,4 @@
+gcc -c -m32 -DELF32 -o efiemu32.o ./efiemu.c -Wall -Werror -nostdlib -O2 -I. 
-I../../include
+gcc -c -m64 -DELF64 -o efiemu64_c.o ./efiemu.c -Wall -Werror -mcmodel=large 
-O2 -I. -I../../include
+gcc -c -m64 -DELF64 -o efiemu64_s.o ./efiemu.S -Wall -Werror -mcmodel=large 
-O2 -I. -I../../include
+ld -o efiemu64.o -r efiemu64_s.o efiemu64_c.o -nostdlib 

Added: trunk/grub2/efiemu/symbols.c
===================================================================
--- trunk/grub2/efiemu/symbols.c                                (rev 0)
+++ trunk/grub2/efiemu/symbols.c        2009-05-02 22:40:21 UTC (rev 2162)
@@ -0,0 +1,188 @@
+/* Code for managing symbols and pointers in efiemu */
+/*
+ *  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/err.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/efiemu/efiemu.h>
+#include <grub/efiemu/runtime.h>
+
+static int ptv_written = 0;
+static int ptv_alloc = 0;
+static int ptv_handle = 0;
+static int ptv_requested = 0;
+static struct grub_efiemu_sym *efiemu_syms = 0;
+
+struct grub_efiemu_sym
+{
+  struct grub_efiemu_sym *next;
+  char *name;
+  int handle;
+  grub_off_t off;
+};
+
+void
+grub_efiemu_free_syms (void)
+{
+  struct grub_efiemu_sym *cur, *d;
+  for (cur = efiemu_syms; cur;)
+    {
+      d = cur->next;
+      grub_free (cur->name);
+      grub_free (cur);
+      cur = d;
+    }
+  efiemu_syms = 0;
+  ptv_written = 0;
+  ptv_alloc = 0;
+  ptv_requested = 0;
+  grub_efiemu_mm_return_request (ptv_handle);
+  ptv_handle = 0;
+}
+
+/* Announce that the module will need NUM allocators */
+/* Because of deferred memory allocation all the relocators have to be 
+   announced during phase 1*/
+grub_err_t
+grub_efiemu_request_symbols (int num)
+{
+  if (ptv_alloc)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                      "symbols have already been allocated");
+  if (num < 0)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                      "can't request negative symbols");
+  ptv_requested += num;
+  return GRUB_ERR_NONE;
+}
+
+/* Resolve the symbol name NAME and set HANDLE and OFF accordingly  */
+grub_err_t
+grub_efiemu_resolve_symbol (const char *name, int *handle, grub_off_t *off)
+{
+  struct grub_efiemu_sym *cur;
+  for (cur = efiemu_syms; cur; cur = cur->next)
+    if (!grub_strcmp (name, cur->name))
+      {
+       *handle = cur->handle;
+       *off = cur->off;
+       return GRUB_ERR_NONE;
+      }
+  grub_dprintf ("efiemu", "%s not found\n", name);
+  return grub_error (GRUB_ERR_BAD_OS, "symbol %s isn't found", name);
+}
+
+/* Register symbol named NAME in memory handle HANDLE at offset OFF */
+grub_err_t
+grub_efiemu_register_symbol (const char *name, int handle, grub_off_t off)
+{
+  struct grub_efiemu_sym *cur;
+  cur = (struct grub_efiemu_sym *) grub_malloc (sizeof (*cur));
+  grub_dprintf ("efiemu", "registering symbol '%s'\n", name);
+  if (!cur)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't register symbol");
+  cur->name = grub_strdup (name);
+  cur->next = efiemu_syms;
+  cur->handle = handle;
+  cur->off = off;
+  efiemu_syms = cur;
+
+  return 0;
+}
+
+/* Go from phase 1 to phase 2. Must be called before similar function in mm.c 
*/
+grub_err_t
+grub_efiemu_alloc_syms (void)
+{
+  ptv_alloc = ptv_requested;
+  ptv_handle = grub_efiemu_request_memalign 
+    (1, (ptv_requested + 1) * sizeof (struct grub_efiemu_ptv_rel), 
+     GRUB_EFI_RUNTIME_SERVICES_DATA);
+  grub_efiemu_register_symbol ("efiemu_ptv_relloc", ptv_handle, 0);
+  return grub_errno;
+}
+
+/* Write value (pointer to memory PLUS_HANDLE) 
+   - (pointer to memory MINUS_HANDLE) + VALUE to ADDR assuming that the 
+   size SIZE bytes. If PTV_NEEDED is 1 then announce it to runtime that this
+   value needs to be recomputed before going to virtual mode
+*/
+grub_err_t
+grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle,
+                        int minus_handle, int ptv_needed, int size)
+{
+  /* Announce relocator to runtime */
+  if (ptv_needed)
+    {
+      struct grub_efiemu_ptv_rel *ptv_rels 
+       = grub_efiemu_mm_obtain_request (ptv_handle);
+
+      if (ptv_needed && ptv_written >= ptv_alloc)
+       return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                          "your module didn't declare efiemu "
+                          " relocators correctly");
+
+      if (minus_handle)
+       ptv_rels[ptv_written].minustype 
+         = grub_efiemu_mm_get_type (minus_handle);
+      else
+       ptv_rels[ptv_written].minustype = 0;
+
+      if (plus_handle)
+       ptv_rels[ptv_written].plustype 
+         = grub_efiemu_mm_get_type (plus_handle);
+      else
+       ptv_rels[ptv_written].plustype = 0;
+
+      ptv_rels[ptv_written].addr = PTR_TO_UINT64 (addr);
+      ptv_rels[ptv_written].size = size;
+      ptv_written++;
+      
+      /* memset next value to zero to mark the end */
+      grub_memset (&ptv_rels[ptv_written], 0, sizeof (ptv_rels[ptv_written]));
+    }
+
+  /* Compute the value */
+  if (minus_handle)
+    value -= PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (minus_handle));
+
+  if (plus_handle)
+    value += PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (plus_handle));
+
+  /* Write the value */
+  switch (size)
+    {
+    case 8:
+      *((grub_uint64_t *) addr) = value;
+      break;
+    case 4:
+      *((grub_uint32_t *) addr) = value;
+      break;
+    case 2:
+      *((grub_uint16_t *) addr) = value;
+      break;
+    case 1:
+      *((grub_uint8_t *) addr) = value;
+      break;
+    default:
+      return grub_error (GRUB_ERR_BAD_ARGUMENT, "wrong symbol size");
+    }
+
+  return GRUB_ERR_NONE;
+}

Added: trunk/grub2/include/grub/autoefi.h
===================================================================
--- trunk/grub2/include/grub/autoefi.h                          (rev 0)
+++ trunk/grub2/include/grub/autoefi.h  2009-05-02 22:40:21 UTC (rev 2162)
@@ -0,0 +1,75 @@
+/*
+ *  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/>.
+ */
+/* This file provides some abstractions so that the same code compiles with
+   both efi and efiemu
+ */
+#ifndef GRUB_AUTOEFI_HEADER
+#define GRUB_AUTOEFI_HEADER    1
+
+#include <grub/machine/machine.h>
+
+#ifdef GRUB_MACHINE_EFI
+# include <grub/efi/efi.h>
+# define grub_autoefi_get_memory_map grub_efi_get_memory_map
+# define grub_autoefi_finish_boot_services grub_efi_finish_boot_services
+# define grub_autoefi_system_table grub_efi_system_table
+# define grub_autoefi_mmap_iterate grub_machine_mmap_iterate
+static inline grub_err_t grub_autoefi_prepare (void)
+{
+  return GRUB_ERR_NONE;
+};
+# define GRUB_AUTOEFI_MEMORY_AVAILABLE GRUB_MACHINE_MEMORY_AVAILABLE
+# define GRUB_AUTOEFI_MEMORY_RESERVED GRUB_MACHINE_MEMORY_RESERVED
+# ifdef GRUB_MACHINE_MEMORY_ACPI
+#  define GRUB_AUTOEFI_MEMORY_ACPI GRUB_MACHINE_MEMORY_ACPI
+# endif
+# ifdef GRUB_MACHINE_MEMORY_NVS
+#  define GRUB_AUTOEFI_MEMORY_NVS GRUB_MACHINE_MEMORY_NVS
+# endif
+# ifdef GRUB_MACHINE_MEMORY_CODE
+#  define GRUB_AUTOEFI_MEMORY_CODE GRUB_MACHINE_MEMORY_CODE
+# endif
+# define SYSTEM_TABLE_SIZEOF(x) (sizeof(grub_efi_system_table->x))
+# define SYSTEM_TABLE_VAR(x) ((void *)&(grub_efi_system_table->x))
+# define SYSTEM_TABLE_PTR(x) ((void *)(grub_efi_system_table->x))
+# define SIZEOF_OF_UINTN sizeof (grub_efi_uintn_t)
+# define SYSTEM_TABLE(x) (grub_efi_system_table->x)
+# define EFI_PRESENT 1
+#else
+# include <grub/efiemu/efiemu.h>
+# define grub_autoefi_get_memory_map grub_efiemu_get_memory_map
+# define grub_autoefi_finish_boot_services grub_efiemu_finish_boot_services
+# define grub_autoefi_system_table grub_efiemu_system_table
+# define grub_autoefi_mmap_iterate grub_efiemu_mmap_iterate
+# define grub_autoefi_prepare grub_efiemu_prepare
+# define GRUB_AUTOEFI_MEMORY_AVAILABLE GRUB_EFIEMU_MEMORY_AVAILABLE
+# define GRUB_AUTOEFI_MEMORY_RESERVED GRUB_EFIEMU_MEMORY_RESERVED
+# define GRUB_AUTOEFI_MEMORY_ACPI GRUB_EFIEMU_MEMORY_ACPI
+# define GRUB_AUTOEFI_MEMORY_NVS GRUB_EFIEMU_MEMORY_NVS
+# define GRUB_AUTOEFI_MEMORY_CODE GRUB_EFIEMU_MEMORY_CODE
+# define SYSTEM_TABLE_SIZEOF GRUB_EFIEMU_SYSTEM_TABLE_SIZEOF
+# define SYSTEM_TABLE_VAR GRUB_EFIEMU_SYSTEM_TABLE_VAR
+# define SYSTEM_TABLE_PTR GRUB_EFIEMU_SYSTEM_TABLE_PTR
+# define SIZEOF_OF_UINTN GRUB_EFIEMU_SIZEOF_OF_UINTN 
+# define SYSTEM_TABLE GRUB_EFIEMU_SYSTEM_TABLE 
+# define grub_efi_allocate_pages(x,y) (x)
+# define grub_efi_free_pages(x,y) GRUB_EFI_SUCCESS
+# define EFI_PRESENT 1
+#endif
+
+#endif

Modified: trunk/grub2/include/grub/efi/api.h
===================================================================
--- trunk/grub2/include/grub/efi/api.h  2009-05-02 22:31:29 UTC (rev 2161)
+++ trunk/grub2/include/grub/efi/api.h  2009-05-02 22:40:21 UTC (rev 2162)
@@ -40,15 +40,15 @@
 #define GRUB_EFI_TPL_NOTIFY            16
 #define GRUB_EFI_TPL_HIGH_LEVEL                31
 
-#define GRUB_EFI_MEMORY_UC     0x0000000000000001
-#define GRUB_EFI_MEMORY_WC     0x0000000000000002
-#define GRUB_EFI_MEMORY_WT     0x0000000000000004
-#define GRUB_EFI_MEMORY_WB     0x0000000000000008
-#define GRUB_EFI_MEMORY_UCE    0x0000000000000010
-#define GRUB_EFI_MEMORY_WP     0x0000000000001000
-#define GRUB_EFI_MEMORY_RP     0x0000000000002000
-#define GRUB_EFI_MEMORY_XP     0x0000000000004000
-#define GRUB_EFI_MEMORY_RUNTIME        0x8000000000000000
+#define GRUB_EFI_MEMORY_UC     0x0000000000000001LL
+#define GRUB_EFI_MEMORY_WC     0x0000000000000002LL
+#define GRUB_EFI_MEMORY_WT     0x0000000000000004LL
+#define GRUB_EFI_MEMORY_WB     0x0000000000000008LL
+#define GRUB_EFI_MEMORY_UCE    0x0000000000000010LL
+#define GRUB_EFI_MEMORY_WP     0x0000000000001000LL
+#define GRUB_EFI_MEMORY_RP     0x0000000000002000LL
+#define GRUB_EFI_MEMORY_XP     0x0000000000004000LL
+#define GRUB_EFI_MEMORY_RUNTIME        0x8000000000000000LL
 
 #define GRUB_EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL      0x00000001
 #define GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL            0x00000002
@@ -619,7 +619,7 @@
   grub_efi_int16_t time_zone;
   grub_efi_uint8_t daylight;
   grub_efi_uint8_t pad2;
-};
+} __attribute__ ((packed));
 typedef struct grub_efi_time grub_efi_time_t;
 
 struct grub_efi_time_capabilities
@@ -936,6 +936,9 @@
 } __attribute__ ((packed));
 typedef struct grub_efi_configuration_table grub_efi_configuration_table_t;
 
+#define GRUB_EFIEMU_SYSTEM_TABLE_SIGNATURE 0x5453595320494249LL
+#define GRUB_EFIEMU_RUNTIME_SERVICES_SIGNATURE 0x56524553544e5552LL
+
 struct grub_efi_simple_input_interface
 {
   grub_efi_status_t

Added: trunk/grub2/include/grub/efiemu/efiemu.h
===================================================================
--- trunk/grub2/include/grub/efiemu/efiemu.h                            (rev 0)
+++ trunk/grub2/include/grub/efiemu/efiemu.h    2009-05-02 22:40:21 UTC (rev 
2162)
@@ -0,0 +1,276 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_EFI_EMU_HEADER
+#define GRUB_EFI_EMU_HEADER    1
+
+#include <grub/efi/api.h>
+#include <grub/file.h>
+
+#define GRUB_EFIEMU_PAGESIZE 4096
+
+/* EFI api defined in 32-bit and 64-bit version*/
+struct grub_efi_system_table32
+{
+  grub_efi_table_header_t hdr;
+  grub_efi_uint32_t firmware_vendor;
+  grub_efi_uint32_t firmware_revision;
+  grub_efi_uint32_t console_in_handler;
+  grub_efi_uint32_t con_in;
+  grub_efi_uint32_t console_out_handler;
+  grub_efi_uint32_t con_out;
+  grub_efi_uint32_t standard_error_handle;
+  grub_efi_uint32_t std_err;
+  grub_efi_uint32_t runtime_services;
+  grub_efi_uint32_t boot_services;
+  grub_efi_uint32_t num_table_entries;
+  grub_efi_uint32_t configuration_table;
+} __attribute__ ((packed));
+typedef struct grub_efi_system_table32  grub_efi_system_table32_t;
+
+struct grub_efi_system_table64
+{
+  grub_efi_table_header_t hdr;
+  grub_efi_uint64_t firmware_vendor;
+  grub_efi_uint32_t firmware_revision;
+  grub_efi_uint32_t pad;
+  grub_efi_uint64_t console_in_handler;
+  grub_efi_uint64_t con_in;
+  grub_efi_uint64_t console_out_handler;
+  grub_efi_uint64_t con_out;
+  grub_efi_uint64_t standard_error_handle;
+  grub_efi_uint64_t std_err;
+  grub_efi_uint64_t runtime_services;
+  grub_efi_uint64_t boot_services;
+  grub_efi_uint64_t num_table_entries;
+  grub_efi_uint64_t configuration_table;
+} __attribute__ ((packed));
+typedef struct grub_efi_system_table64  grub_efi_system_table64_t;
+
+struct grub_efiemu_runtime_services32
+{
+  grub_efi_table_header_t hdr;
+  grub_efi_uint32_t get_time;
+  grub_efi_uint32_t set_time;
+  grub_efi_uint32_t get_wakeup_time;
+  grub_efi_uint32_t set_wakeup_time;
+  grub_efi_uint32_t set_virtual_address_map;
+  grub_efi_uint32_t convert_pointer;
+  grub_efi_uint32_t get_variable;
+  grub_efi_uint32_t get_next_variable_name;
+  grub_efi_uint32_t set_variable;
+  grub_efi_uint32_t get_next_high_monotonic_count;
+  grub_efi_uint32_t reset_system;
+} __attribute__ ((packed));
+typedef struct grub_efiemu_runtime_services32 grub_efiemu_runtime_services32_t;
+
+struct grub_efiemu_runtime_services64
+{
+  grub_efi_table_header_t hdr;
+  grub_efi_uint64_t get_time;
+  grub_efi_uint64_t set_time;
+  grub_efi_uint64_t get_wakeup_time;
+  grub_efi_uint64_t set_wakeup_time;
+  grub_efi_uint64_t set_virtual_address_map;
+  grub_efi_uint64_t convert_pointer;
+  grub_efi_uint64_t get_variable;
+  grub_efi_uint64_t get_next_variable_name;
+  grub_efi_uint64_t set_variable;
+  grub_efi_uint64_t get_next_high_monotonic_count;
+  grub_efi_uint64_t reset_system;
+} __attribute__ ((packed));
+typedef struct grub_efiemu_runtime_services64 grub_efiemu_runtime_services64_t;
+
+extern grub_efi_system_table32_t *grub_efiemu_system_table32;
+extern grub_efi_system_table64_t *grub_efiemu_system_table64;
+
+/* Convenience macroses to access currently loaded efiemu */
+#define grub_efiemu_system_table ((grub_efiemu_sizeof_uintn_t () == 8) \
+                                 ? (void *) grub_efiemu_system_table64 \
+                                 : (void *) grub_efiemu_system_table32)
+#define GRUB_EFIEMU_SIZEOF_OF_UINTN (grub_efiemu_sizeof_uintn_t ())
+#define GRUB_EFIEMU_SYSTEM_TABLE(x) ((grub_efiemu_sizeof_uintn_t () == 8) \
+                                    ? grub_efiemu_system_table64->x \
+                                    : grub_efiemu_system_table32->x)
+#define GRUB_EFIEMU_SYSTEM_TABLE_SET(x,y) ((grub_efiemu_sizeof_uintn_t () == 
8)\
+                                          ? (grub_efiemu_system_table64->x \
+                                             = (y)) \
+                                          : (grub_efiemu_system_table32->x \
+                                             = (y)))
+#define GRUB_EFIEMU_SYSTEM_TABLE_PTR(x) ((grub_efiemu_sizeof_uintn_t () == 8)\
+                                        ? UINT_TO_PTR \
+                                        (grub_efiemu_system_table64->x) \
+                                        : UINT_TO_PTR \
+                                        (grub_efiemu_system_table32->x))
+#define GRUB_EFIEMU_SYSTEM_TABLE_VAR(x) ((grub_efiemu_sizeof_uintn_t () == 8) \
+                                        ? (void *) \
+                                        &(grub_efiemu_system_table64->x) \
+                                        : (void *) \
+                                        &(grub_efiemu_system_table32->x))
+#define GRUB_EFIEMU_SYSTEM_TABLE_SIZEOF(x) \
+  ((grub_efiemu_sizeof_uintn_t () == 8) \
+   ? sizeof(grub_efiemu_system_table64->x)\
+   : sizeof(grub_efiemu_system_table32->x))
+#define GRUB_EFIEMU_SYSTEM_TABLE_SIZEOF_TOTAL ((grub_efiemu_sizeof_uintn_t () 
== 8) ? sizeof(*grub_efiemu_system_table64):sizeof(*grub_efiemu_system_table32))
+
+/* ELF management definitions and functions */
+
+struct grub_efiemu_segment
+{
+  struct grub_efiemu_segment *next;
+  grub_size_t size;
+  unsigned section;
+  int handle;
+  int ptv_rel_needed;
+  grub_off_t off;
+  void *srcptr;
+};
+typedef struct grub_efiemu_segment *grub_efiemu_segment_t;
+
+struct grub_efiemu_elf_sym
+{
+  int handle;
+  grub_off_t off;
+  unsigned section;
+};
+
+int grub_efiemu_check_header32 (void *ehdr, grub_size_t size);
+int grub_efiemu_check_header64 (void *ehdr, grub_size_t size);
+grub_err_t grub_efiemu_loadcore_init32 (void *core, grub_size_t core_size,
+                                       grub_efiemu_segment_t *segments);
+grub_err_t grub_efiemu_loadcore_init64 (void *core, grub_size_t core_size,
+                                       grub_efiemu_segment_t *segments);
+grub_err_t grub_efiemu_loadcore_load32 (void *core, 
+                                       grub_size_t core_size,
+                                       grub_efiemu_segment_t segments);
+grub_err_t grub_efiemu_loadcore_load64 (void *core, 
+                                       grub_size_t core_size,
+                                       grub_efiemu_segment_t segments);
+grub_err_t grub_efiemu_loadcore_unload32 (void);
+grub_err_t grub_efiemu_loadcore_unload64 (void);
+grub_err_t grub_efiemu_loadcore_unload(void);
+grub_err_t grub_efiemu_loadcore_init (grub_file_t file);
+grub_err_t grub_efiemu_loadcore_load (void);
+
+/* Configuration tables manipulation. Definitions and functions */
+struct grub_efiemu_configuration_table
+{
+  struct grub_efiemu_configuration_table *next;
+  grub_efi_guid_t guid;
+  void * (*get_table) (void *data);
+  void (*unload) (void *data);
+  void *data;
+};
+struct grub_efiemu_configuration_table32
+{
+  grub_efi_guid_t vendor_guid;
+  grub_efi_uint32_t vendor_table;
+} __attribute__ ((packed));
+typedef struct grub_efiemu_configuration_table32 
grub_efiemu_configuration_table32_t;
+struct grub_efiemu_configuration_table64
+{
+  grub_efi_guid_t vendor_guid;
+  grub_efi_uint64_t vendor_table;
+} __attribute__ ((packed));
+typedef struct grub_efiemu_configuration_table32 
grub_efiemu_configuration_table64_t;
+grub_err_t grub_efiemu_unregister_configuration_table (grub_efi_guid_t guid);
+grub_err_t 
+grub_efiemu_register_configuration_table (grub_efi_guid_t guid, 
+                                         void * (*get_table) (void *data),
+                                         void (*unload) (void *data), 
+                                         void *data);
+
+/* Memory management functions */
+int grub_efiemu_request_memalign (grub_size_t align, grub_size_t size, 
+                                 grub_efi_memory_type_t type);
+void *grub_efiemu_mm_obtain_request (int handle);
+int grub_efiemu_get_memory_map (grub_efi_uintn_t *memory_map_size,
+                               grub_efi_memory_descriptor_t *memory_map,
+                               grub_efi_uintn_t *map_key,
+                               grub_efi_uintn_t *descriptor_size,
+                               grub_efi_uint32_t *descriptor_version);
+grub_err_t grub_efiemu_mm_unload (void);
+grub_err_t grub_efiemu_mm_do_alloc (void);
+grub_err_t grub_efiemu_mm_init (void);
+void *grub_efiemu_mm_obtain_request (int handle);
+void grub_efiemu_mm_return_request (int handle);
+grub_efi_memory_type_t grub_efiemu_mm_get_type (int handle);
+
+/* Drop-in replacements for grub_efi_* and grub_machine_* */
+int grub_efiemu_get_memory_map (grub_efi_uintn_t *memory_map_size,
+                               grub_efi_memory_descriptor_t *memory_map,
+                               grub_efi_uintn_t *map_key,
+                               grub_efi_uintn_t *descriptor_size,
+                               grub_efi_uint32_t *descriptor_version);
+grub_err_t
+grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, 
+                                                       grub_uint64_t, 
+                                                       grub_uint32_t));
+int grub_efiemu_sizeof_uintn_t (void);
+int grub_efiemu_exit_boot_services (grub_efi_uintn_t map_key);
+int grub_efiemu_finish_boot_services (void);
+grub_err_t
+grub_efiemu_get_lower_upper_memory (grub_uint64_t *lower, grub_uint64_t 
*upper);
+#define GRUB_EFIEMU_MEMORY_AVAILABLE   1
+#define GRUB_EFIEMU_MEMORY_RESERVED    2
+#define GRUB_EFIEMU_MEMORY_ACPI        3
+#define GRUB_EFIEMU_MEMORY_NVS         4
+#define GRUB_EFIEMU_MEMORY_CODE         5
+
+/* efiemu main control definitions and functions*/
+typedef enum {GRUB_EFIEMU_NOTLOADED,
+             GRUB_EFIEMU32, GRUB_EFIEMU64} grub_efiemu_mode_t;
+struct grub_efiemu_prepare_hook
+{
+  struct grub_efiemu_prepare_hook *next;
+  grub_err_t (*hook) (void *data);
+  void (*unload) (void *data);
+  void *data;
+};
+grub_err_t grub_efiemu_prepare32 (struct grub_efiemu_prepare_hook 
+                                 *prepare_hooks,
+                                 struct grub_efiemu_configuration_table 
+                                 *config_tables);
+grub_err_t grub_efiemu_prepare64 (struct grub_efiemu_prepare_hook 
+                                 *prepare_hooks,
+                                 struct grub_efiemu_configuration_table 
+                                 *config_tables);
+grub_err_t grub_efiemu_unload (void);
+grub_err_t grub_efiemu_prepare (void);
+grub_err_t
+grub_efiemu_register_prepare_hook (grub_err_t (*hook) (void *data),
+                                  void (*unload) (void *data), 
+                                  void *data);
+
+/* symbols and pointers */
+grub_err_t grub_efiemu_alloc_syms (void);
+grub_err_t grub_efiemu_request_symbols (int num);
+grub_err_t grub_efiemu_resolve_symbol (const char *name, 
+                                      int *handle, grub_off_t *off);
+grub_err_t grub_efiemu_register_symbol (const char *name, 
+                                       int handle, grub_off_t off);
+void grub_efiemu_free_syms (void);
+grub_err_t grub_efiemu_write_value (void * addr, grub_uint32_t value, 
+                                   int plus_handle,
+                                   int minus_handle, int ptv_needed, int size);
+grub_err_t grub_efiemu_pnvram (void);
+grub_err_t grub_efiemu_prepare (void);
+char *grub_efiemu_get_default_core_name (void);
+void grub_efiemu_pnvram_cmd_unregister (void);
+grub_err_t grub_efiemu_autocore (void);
+#endif /* ! GRUB_EFI_EMU_HEADER */

Added: trunk/grub2/include/grub/efiemu/runtime.h
===================================================================
--- trunk/grub2/include/grub/efiemu/runtime.h                           (rev 0)
+++ trunk/grub2/include/grub/efiemu/runtime.h   2009-05-02 22:40:21 UTC (rev 
2162)
@@ -0,0 +1,37 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_EFI_EMU_RUNTIME_HEADER
+#define GRUB_EFI_EMU_RUNTIME_HEADER    1
+
+struct grub_efiemu_ptv_rel
+{
+  grub_uint64_t addr;
+  grub_efi_memory_type_t plustype;
+  grub_efi_memory_type_t minustype;
+  grub_uint32_t size;
+} __attribute__ ((packed));
+
+struct efi_variable
+{
+  grub_efi_guid_t guid;
+  grub_uint32_t namelen;
+  grub_uint32_t size;
+  grub_efi_uint32_t attributes;
+} __attribute__ ((packed));
+#endif /* ! GRUB_EFI_EMU_RUNTIME_HEADER */

Added: trunk/grub2/include/grub/i386/efiemu.h
===================================================================
--- trunk/grub2/include/grub/i386/efiemu.h                              (rev 0)
+++ trunk/grub2/include/grub/i386/efiemu.h      2009-05-02 22:40:21 UTC (rev 
2162)
@@ -0,0 +1,33 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_ARCH_EFI_EMU_HEADER
+#define GRUB_ARCH_EFI_EMU_HEADER       1
+
+grub_err_t
+grub_arch_efiemu_relocate_symbols32 (grub_efiemu_segment_t segs, 
+                                    struct grub_efiemu_elf_sym *elfsyms,
+                                    void *ehdr);
+grub_err_t
+grub_arch_efiemu_relocate_symbols64 (grub_efiemu_segment_t segs, 
+                                    struct grub_efiemu_elf_sym *elfsyms,
+                                    void *ehdr);
+
+int grub_arch_efiemu_check_header32 (void *ehdr);
+int grub_arch_efiemu_check_header64 (void *ehdr);
+#endif

Added: trunk/grub2/include/grub/i386/pc/efiemu.h
===================================================================
--- trunk/grub2/include/grub/i386/pc/efiemu.h                           (rev 0)
+++ trunk/grub2/include/grub/i386/pc/efiemu.h   2009-05-02 22:40:21 UTC (rev 
2162)
@@ -0,0 +1,24 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MACHINE_EFI_EMU_HEADER
+#define GRUB_MACHINE_EFI_EMU_HEADER    1
+
+grub_err_t grub_machine_efiemu_init_tables (void);
+
+#endif

Modified: trunk/grub2/util/i386/pc/grub-install.in
===================================================================
--- trunk/grub2/util/i386/pc/grub-install.in    2009-05-02 22:31:29 UTC (rev 
2161)
+++ trunk/grub2/util/i386/pc/grub-install.in    2009-05-02 22:40:21 UTC (rev 
2162)
@@ -211,7 +211,7 @@
 fi
 
 # Copy the GRUB images to the GRUB directory.
-for file in ${grubdir}/*.mod ${grubdir}/*.lst ${grubdir}/*.img; do
+for file in ${grubdir}/*.mod ${grubdir}/*.lst ${grubdir}/*.img 
${grubdir}/efiemu??.o; do
     if test -f $file && [ "`basename $file`" != menu.lst ]; then
        rm -f $file || exit 1
     fi
@@ -220,7 +220,7 @@
     cp -f $file ${grubdir} || exit 1
 done
 if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
-    for file in ${pkglibdir}/*.img; do
+    for file in ${pkglibdir}/*.img ${pkglibdir}/efiemu??.o; do
         cp -f $file ${grubdir} || exit 1
     done
 fi

Modified: trunk/grub2/util/i386/pc/grub-mkrescue.in
===================================================================
--- trunk/grub2/util/i386/pc/grub-mkrescue.in   2009-05-02 22:31:29 UTC (rev 
2161)
+++ trunk/grub2/util/i386/pc/grub-mkrescue.in   2009-05-02 22:40:21 UTC (rev 
2162)
@@ -116,7 +116,7 @@
 aux_dir=`mktemp -d`
 mkdir -p ${aux_dir}/boot/grub
 
-cp ${input_dir}/*.mod \
+cp ${input_dir}/*.mod ${input_dir}/efiemu??.o \
   ${input_dir}/command.lst ${input_dir}/moddep.lst ${input_dir}/fs.lst \
   ${input_dir}/handler.lst ${input_dir}/parttool.lst  \
   ${aux_dir}/boot/grub/





reply via email to

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