grub-devel
[Top][All Lists]
Advanced

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

Re: Efiemu


From: phcoder
Subject: Re: Efiemu
Date: Sun, 01 Mar 2009 11:49:17 +0100
User-agent: Thunderbird 2.0.0.19 (X11/20090105)

Naming problem fixed
Usage:
First compile grub2 with this patch and efiemu runtime (in archive)
Now it's compiled by normal make

--

Regards
Vladimir 'phcoder' Serbinenko
Index: conf/i386-pc.rmk
===================================================================
--- conf/i386-pc.rmk    (revision 1998)
+++ conf/i386-pc.rmk    (working copy)
@@ -146,7 +147,8 @@
        \
        disk/raid.c disk/raid5_recover.c disk/raid6_recover.c           \
        disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c             \
-       grub_emu_init.c
+       grub_emu_init.c efiemu/main.c efiemu/loadcore.c efiemu/mm.c     \
+       efiemu/modules/pnvram.c efiemu/i386/loadcore.c  lib/crc.c       \
 
 grub_emu_LDFLAGS = $(LIBCURSES) 
 
@@ -172,3 +177,3 @@
        vbe.mod vbetest.mod vbeinfo.mod play.mod serial.mod     \
        ata.mod vga.mod memdisk.mod pci.mod lspci.mod \
        aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod datetime.mod date.mod \
        datehook.mod lsmmap.mod ata_pthru.mod hdparm.mod \
        usb.mod uhci.mod ohci.mod usbtest.mod usbms.mod usb_keyboard.mod
+       efiemu.mod efiemu_acpi.mod efiemu_pnvram.mod _linux_efi.mod 
linux_efi.mod
 
+# For efiemu.mod.
+efiemu_mod_SOURCES = efiemu/main.c efiemu/i386/loadcore.c 
efiemu/i386/pc/cfgtables.c efiemu/mm.c efiemu/loadcore.c
+efiemu_mod_CFLAGS = $(COMMON_CFLAGS) -Werror -Wall
+efiemu_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+efiemu_acpi_mod_SOURCES = efiemu/modules/acpi.c efiemu/modules/i386/pc/acpi.c
+efiemu_acpi_mod_CFLAGS = $(COMMON_CFLAGS) -Werror -Wall
+efiemu_acpi_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+efiemu_pnvram_mod_SOURCES = efiemu/modules/pnvram.c 
+efiemu_pnvram_mod_CFLAGS = $(COMMON_CFLAGS) -Werror -Wall
+efiemu_pnvram_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 # For biosdisk.mod.
 biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
 biosdisk_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -200,6 +225,16 @@
 linux_mod_CFLAGS = $(COMMON_CFLAGS)
 linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For _linux_efi.mod.
+_linux_efi_mod_SOURCES = loader/i386/efi/linux.c
+_linux_efi_mod_CFLAGS = $(COMMON_CFLAGS)
+_linux_efi_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For linux_efi.mod.
+linux_efi_mod_SOURCES = loader/linux_normal_efiemu.c
+linux_efi_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_efi_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 #
 # Only arch dependant part of normal.mod will be here. Common part for
 # all architecures of normal.mod is at start and should be kept at sync
Index: kern/i386/pc/init.c
===================================================================
--- kern/i386/pc/init.c (revision 1998)
+++ kern/i386/pc/init.c (working copy)
@@ -149,9 +149,9 @@
 #endif
 
   /* Add the lower memory into free memory.  */
-  if (grub_lower_mem >= GRUB_MEMORY_MACHINE_RESERVED_END)
+  /*  if (grub_lower_mem >= GRUB_MEMORY_MACHINE_RESERVED_END)
     add_mem_region (GRUB_MEMORY_MACHINE_RESERVED_END,
-                   grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END);
+    grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END);*/
   
   auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
   int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, 
grub_uint32_t type)
Index: efiemu/main.c
===================================================================
--- efiemu/main.c       (revision 0)
+++ efiemu/main.c       (revision 0)
@@ -0,0 +1,363 @@
+
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.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/lib/crc.h>
+
+/* These are function for loading and configuring EFI emulator*/
+
+grub_efi_system_table32_t *grub_efiemu_system_table32 = 0;
+grub_efi_system_table64_t *grub_efiemu_system_table64 = 0;
+
+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_prepare_hook
+{
+  struct grub_efiemu_prepare_hook *next;
+  grub_err_t (*hook) (void *data);
+  void (*unload) (void *data);
+  void *data;
+};
+
+static struct grub_efiemu_prepare_hook *efiemu_prepare_hooks = 0;
+static struct grub_efiemu_configuration_table *efiemu_config_tables = 0;
+
+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;
+}
+
+grub_err_t
+grub_efiemu_prepare (void)
+{
+  grub_err_t err;
+  int conftable_handle;
+  struct grub_efiemu_configuration_table *cur;
+  struct grub_efiemu_prepare_hook *curhook;
+
+  int cntconftables = 0;
+  grub_efiemu_configuration_table32_t *conftables32 = 0;
+
+  grub_dprintf ("efiemu", "Preparing EfiEmu\n");
+
+  for (cur = efiemu_config_tables; cur; cur = cur->next)
+    cntconftables++;
+
+  if (grub_arch_efiemu_sizeof_uintn_t () == 4)
+    {
+      conftable_handle 
+       = grub_efiemu_request_memalign (GRUB_EFIEMU_PAGESIZE, 
+                                       cntconftables * sizeof (*conftables32),
+                                       GRUB_EFI_RUNTIME_SERVICES_DATA);
+
+    }
+  else
+    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
+                      "loading 64-bit efiemu isn't implemented yet");
+
+  grub_efiemu_alloc_syms ();
+
+  grub_efiemu_mm_do_alloc ();
+
+  grub_efiemu_system_table32 = 0;
+  grub_efiemu_system_table64 = 0;
+  grub_dprintf ("efiemu", "Preparing %d-bit efiemu\n", 
+               8*grub_arch_efiemu_sizeof_uintn_t ());
+  if (grub_arch_efiemu_sizeof_uintn_t () == 4)
+    {
+      grub_efiemu_runtime_services32_t *runtime_services;
+      int i;
+      int handle;
+      grub_off_t off;
+
+      for (curhook = efiemu_prepare_hooks; curhook; curhook = curhook->next)
+       curhook->hook (curhook->data);
+
+      if ((err = grub_efiemu_loadcore_load ()))
+       {
+         grub_efiemu_unload ();
+         return err;
+       }
+
+      if ((err = grub_efiemu_resolve_symbol ("efiemu_system_table", 
+                                            &handle, &off)))
+       return err;
+
+      grub_efiemu_system_table32 = (grub_efi_system_table32_t *) 
+       ((grub_uint8_t *)grub_efiemu_mm_obtain_request (handle) + off);
+      grub_dprintf ("efiemu", "system_table = %p\n",
+                   grub_efiemu_system_table32);
+
+
+      if ((err = grub_efiemu_resolve_symbol ("efiemu_runtime_services", 
+                                            &handle, &off)))
+       return err;
+      runtime_services = (grub_efiemu_runtime_services32_t *)
+       ((grub_uint8_t *)grub_efiemu_mm_obtain_request (handle) + off);
+      runtime_services->hdr.crc32 = 0;
+      runtime_services->hdr.crc32 = grub_getcrc32 (0, runtime_services, 
+                                                   sizeof (*runtime_services));
+
+
+      grub_efiemu_write_uint32 
+       (&(grub_efiemu_system_table32->configuration_table), 0, 
+        conftable_handle, 0, 1);
+      grub_efiemu_system_table32->num_table_entries = cntconftables;
+
+      conftables32 = (grub_efiemu_configuration_table32_t *)
+       grub_efiemu_mm_obtain_request (conftable_handle);
+      i = 0;
+      for (cur = efiemu_config_tables; cur; cur = cur->next, i++)
+       {
+         grub_memcpy (&(conftables32[i].vendor_guid), &(cur->guid), 
+                      sizeof (cur->guid));
+         if (cur->get_table)
+           conftables32[i].vendor_table
+             = PTR_TO_UINT32 (cur->get_table (cur->data));
+         else
+           conftables32[i].vendor_table = PTR_TO_UINT32 (cur->data);
+       }
+
+      grub_efiemu_system_table32->hdr.crc32 = 0;
+      grub_efiemu_system_table32->hdr.crc32 
+       = grub_getcrc32 (0, grub_efiemu_system_table32, 
+                        sizeof (*grub_efiemu_system_table32));
+      grub_dprintf ("efiemu","system_table = %p, runtime_services = %p,"
+                   " conftables = %p (%d entries)\n",
+                   grub_efiemu_system_table32, runtime_services, 
+                   conftables32, cntconftables);
+    }
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_efiemu_unregister_configuration_table (grub_efi_guid_t guid)
+{
+  struct grub_efiemu_configuration_table *cur, *prev;  
+  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;
+  for (prev = efiemu_config_tables, cur=prev->next;cur;)
+    if (!grub_memcmp (&(cur->guid),&guid, sizeof (guid)))
+      {
+       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 set at least get_table or data");
+  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;
+}
+
+
+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;
+  grub_dprintf ("efiemu", "registering table %x\n",guid.data1);
+  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 (struct grub_arg_list *state __attribute__ ((unused)),
+                       int argc __attribute__ ((unused)), 
+                       char **args __attribute__ ((unused)))
+{
+  return grub_efiemu_unload ();
+}
+
+static grub_err_t
+grub_cmd_efiemu_prepare (struct grub_arg_list *state __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;
+}
+
+
+/* Load a module 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;
+  
+  grub_dprintf ("efiemu", "file opened\n");
+
+  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");
+
+  if ((err = grub_efiemu_loadcore_init (file)))
+    {
+      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;
+}
+
+
+static grub_err_t
+grub_cmd_efiemu_load (struct grub_arg_list *state __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");
+
+  if ((err = grub_efiemu_load_file (args[0])))
+    return err;
+#ifndef GRUB_UTIL
+  if ((err = grub_machine_efiemu_init_tables ()))
+    return err;
+#endif
+  return GRUB_ERR_NONE;
+}
+
+
+GRUB_MOD_INIT(efiemu)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("efiemu_loadcore", grub_cmd_efiemu_load, 
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "efiemu_loadcore FILE", 
+                        "Load and initialize EFI emulator", 0);
+  grub_register_command ("efiemu_prepare", grub_cmd_efiemu_prepare, 
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "efiemu_prepare", 
+                        "Finalize loading of EFI emulator", 0);
+  grub_register_command ("efiemu_unload", grub_cmd_efiemu_unload, 
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "efiemu_unload", 
+                        "Unload  EFI emulator", 0);
+}
+
+GRUB_MOD_FINI(efiemu)
+{
+  grub_unregister_command ("efiemu_loadcore");
+  grub_unregister_command ("efiemu_prepare");
+  grub_unregister_command ("efiemu_unload");
+}

Property changes on: efiemu/main.c
___________________________________________________________________
Added: svn:mergeinfo

Index: efiemu/modules/pnvram.c
===================================================================
--- efiemu/modules/pnvram.c     (revision 0)
+++ efiemu/modules/pnvram.c     (revision 0)
@@ -0,0 +1,282 @@
+
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.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/lib/crc.h>
+
+struct efi_variable
+{
+  grub_efi_guid_t guid;
+  grub_uint32_t namelen;
+  grub_uint32_t size;
+  grub_efi_uint32_t attributes;
+} __attribute__ ((packed));
+
+static int nvram_handle = 0;
+static int nvramsize_handle = 0;
+static int high_monotonic_count_handle = 0;
+static grub_uint8_t *nvram;
+static grub_size_t nvramsize;
+static grub_dl_t my_mod;
+static grub_uint32_t high_monotonic_count;
+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},
+  {0, 0, 0, 0, 0, 0}
+};
+
+static grub_err_t
+nvram_set (void * data __attribute__ ((unused)))
+{
+      
+  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_dprintf ("efiemu", "preparing pnvram\n");
+  grub_memcpy (nvram_def, nvram, nvramsize);
+  *nvramsize_def = nvramsize;
+  *high_monotonic_count_def = high_monotonic_count;
+  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);
+  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_free (nvram);
+  nvram = 0;
+}
+
+/* guid:attr:name:data;*/
+static grub_err_t
+read_pnvram (char *filename)
+{
+  char *buf, *end, *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);
+  end = buf + size;
+  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);
+
+      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;
+      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++;
+      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++;
+
+      for (j = 0; j < 2; j++)
+       {
+         datalen = 0;
+         for (ptr2 = ptr; ptr2 < end && (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_cmd_efiemu_pnvram (struct grub_arg_list *state,
+                      int argc, char **args)
+{
+  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;
+  
+  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;
+    }
+
+  if ((err = grub_efiemu_register_prepare_hook (nvram_set, nvram_unload, 0)))
+    {
+      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);
+  grub_efiemu_request_symbols (3);
+#ifndef GRUB_UTIL
+  grub_dl_ref (my_mod);
+#endif
+  return GRUB_ERR_NONE;
+}
+
+
+
+GRUB_MOD_INIT(efiemu_pnvram)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("efiemu_pnvram", grub_cmd_efiemu_pnvram, 
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "efiemu_pnvram [FILENAME]",
+                        "Initialise pseudo-NVRAM and load variables from 
FILE", 
+                        options);
+  my_mod=mod;
+}
+
+GRUB_MOD_FINI(efiemu_pnvram)
+{
+  grub_unregister_command ("efiemu_pnvram");
+}

Property changes on: efiemu/modules/pnvram.c
___________________________________________________________________
Added: svn:mergeinfo

Index: efiemu/modules/i386/pc/acpi.c
===================================================================
--- efiemu/modules/i386/pc/acpi.c       (revision 0)
+++ efiemu/modules/i386/pc/acpi.c       (revision 0)
@@ -0,0 +1,35 @@
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+#include <grub/efiemu/efiemu.h>
+#include <grub/efiemu/acpi.h>
+
+struct grub_acpi_rsdp_v10 *
+grub_machine_efiemu_get_rsdp (void)
+{
+  int ebda_len;
+  grub_uint8_t *ptr;
+
+  grub_dprintf ("efiemu", "Looking for RSDP. Scanning EBDA\n");  
+
+  ebda_len = 1024 * (*((grub_uint8_t *)0x40e));
+  for (ptr = (grub_uint8_t *)0x410; ptr < (grub_uint8_t *)(0x410 + ebda_len);
+       ptr += 16)
+    if (!grub_memcmp (ptr, "RSD PTR ", 8) 
+       && grub_efiemu_acpi_checksum (ptr, 
+                                     sizeof (struct grub_acpi_rsdp_v10)) == 0)
+      return (struct grub_acpi_rsdp_v10 *) ptr;
+
+  grub_dprintf ("efiemu", "Looking for RSDP. Scanning BIOS\n");  
+  for (ptr=(grub_uint8_t *)0xe0000;ptr<(grub_uint8_t *)0x100000;ptr+=16)
+    if (!grub_memcmp (ptr, "RSD PTR ", 8)
+       && grub_efiemu_acpi_checksum (ptr, 
+                                     sizeof (struct grub_acpi_rsdp_v10)) == 0)
+      return (struct grub_acpi_rsdp_v10 *) ptr;
+  return 0;
+}
Index: efiemu/modules/acpi.c
===================================================================
--- efiemu/modules/acpi.c       (revision 0)
+++ efiemu/modules/acpi.c       (revision 0)
@@ -0,0 +1,514 @@
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/arg.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/gzio.h>
+#include <grub/efiemu/efiemu.h>
+#include <grub/efiemu/acpi.h>
+#include <grub/mm.h>
+
+
+static const struct grub_arg_option options[] = {
+  {"exclude", 'x', 0, 
+   "Don't load host tables specified by comma-separated list", 
+   0, ARG_TYPE_STRING},
+  {"load-only", 'n', 0, 
+   "Load only tables specified by comma-separated list", 0, ARG_TYPE_STRING},
+  {"v1", '1', 0, "Expose v1 tables", 0, ARG_TYPE_NONE},
+  {"v2", '2', 0, "Expose v2 and v3 tables", 0, ARG_TYPE_NONE},
+  {"oemid", 'o', 0, "Set OEMID of RSDP, XSDT and RSDT", 0, ARG_TYPE_STRING},
+  {"oemtable", 't', 0, 
+   "Set OEMTABLE ID of RSDP, XSDT and RSDT", 0, ARG_TYPE_STRING},  
+  {"oemtablerev", 'r', 0, 
+   "Set OEMTABLE revision of RSDP, XSDT and RSDT", 0, ARG_TYPE_INT},  
+  {"oemtablecreator", 'c', 0, 
+   "Set creator field of RSDP, XSDT and RSDT", 0, ARG_TYPE_STRING},  
+  {"oemtablecreatorrev", 'd', 0, 
+   "Set creator revision of RSDP, XSDT and RSDT", 0, ARG_TYPE_INT},  
+  {0, 0, 0, 0, 0, 0}
+};
+
+static int rev1, rev2;
+static grub_dl_t my_mod;
+static char root_oemid[6];
+static char root_oemtable[8];
+static grub_uint32_t root_oemrev;
+static char root_creator_id[4];
+static grub_uint32_t root_creator_rev;
+
+struct efiemu_acpi_table
+{
+  void *data;
+  void *addr;
+  grub_size_t size;
+  int alloc_handle;
+  struct efiemu_acpi_table *next;
+};
+
+static struct efiemu_acpi_table *acpi_tables = 0;
+/* DSDT isn't in RSDT. So treat it specially */
+static void *table_dsdt = 0;
+static void *rsdt_addr = 0;
+static int dsdt_alloc_handle = 0;
+static grub_size_t dsdt_size = 0;
+static grub_uint32_t facs_addr = 0;
+static int rsdpv1_alloc_handle = 0;
+static int rsdpv2_alloc_handle = 0;
+static int rsdt_alloc_handle = 0;
+static int xsdt_alloc_handle = 0;
+static int tables_set = 0;
+static int locked = 0;
+
+grub_uint8_t 
+grub_efiemu_acpi_checksum (void *base, grub_size_t size)
+{
+  grub_uint8_t *ptr;
+  grub_uint8_t ret = 0;
+  for (ptr = (grub_uint8_t *) base; ptr < ((grub_uint8_t *) base) + size;
+       ptr++)
+    ret += *ptr;
+  return ret;
+}
+
+static void
+grub_efiemu_acpi_clear (void)
+{
+  static struct efiemu_acpi_table *cur, *d;
+  for (cur = acpi_tables; cur; )
+    {
+      grub_free (cur->data);
+      d = cur->next;
+      grub_free (cur);
+      cur = d;
+    }
+
+  acpi_tables = 0;
+  grub_free (table_dsdt);
+  table_dsdt = 0;
+  dsdt_size = 0;
+  dsdt_alloc_handle = 0;
+  rev1 = rev2 = 0;
+
+  grub_efiemu_mm_return_request (dsdt_alloc_handle);
+  grub_efiemu_mm_return_request (rsdpv1_alloc_handle);
+  grub_efiemu_mm_return_request (rsdpv2_alloc_handle);
+  grub_efiemu_mm_return_request (rsdt_alloc_handle);
+  grub_efiemu_mm_return_request (xsdt_alloc_handle);
+
+  dsdt_alloc_handle = 0;
+  rsdpv1_alloc_handle = 0;
+  rsdpv2_alloc_handle = 0;
+  rsdt_alloc_handle = 0;
+  xsdt_alloc_handle = 0;
+
+  tables_set = 0;
+  rsdt_addr = 0;
+
+  if (locked)
+    grub_dl_unref (my_mod);
+
+}
+
+static void
+unloadv1table (void *data __attribute__ ((unused)))
+{
+  rev1 = 0;
+  grub_efiemu_mm_return_request (rsdpv1_alloc_handle);
+  rsdpv1_alloc_handle = 0;
+  if (!rev2)
+    grub_efiemu_acpi_clear ();
+}
+
+static void
+unloadv2table (void *data __attribute__ ((unused)))
+{
+  rev2 = 0;
+  grub_efiemu_mm_return_request (rsdpv2_alloc_handle);
+  grub_efiemu_mm_return_request (xsdt_alloc_handle);
+  rsdpv2_alloc_handle = 0;
+  xsdt_alloc_handle = 0;
+
+  if (!rev1)
+    grub_efiemu_acpi_clear ();
+}
+
+static void
+setup_common_tables (void)
+{
+  struct efiemu_acpi_table *cur;
+  void *dest;
+  void *dsdt_addr = 0;
+  struct grub_acpi_table_header *rsdt;
+  grub_uint32_t *rsdt_entry;
+  int numoftables;
+
+  if (tables_set)
+    return;
+  if (table_dsdt)
+    {
+      dsdt_addr = grub_efiemu_mm_obtain_request (dsdt_alloc_handle);
+      grub_memcpy (dsdt_addr, table_dsdt, dsdt_size);
+    }
+  for (cur = acpi_tables; cur; cur = cur->next)
+    {
+      struct grub_acpi_fadt *fadt;
+      cur->addr = dest = grub_efiemu_mm_obtain_request (cur->alloc_handle);
+      grub_memcpy (dest, cur->data, cur->size);      
+      fadt = (struct grub_acpi_fadt *) dest;
+      if (!grub_memcmp (fadt->hdr.signature, "FACP", 4))
+       {
+         fadt->dsdt_addr = PTR_TO_UINT32 (dsdt_addr);
+         /* Does a revision 2 exist at all? */
+         if (fadt->hdr.revision >= 3)
+           fadt->dsdt_xaddr = PTR_TO_UINT64 (dsdt_addr);
+         fadt->hdr.checksum = 0;
+         fadt->hdr.checksum = 1 + ~grub_efiemu_acpi_checksum 
+           (fadt, fadt->hdr.length);
+       }
+    }
+  rsdt_addr = rsdt = (struct grub_acpi_table_header *) 
+    grub_efiemu_mm_obtain_request (rsdt_alloc_handle);
+  rsdt_entry = (grub_uint32_t *)(rsdt + 1);
+  numoftables = 0;
+  for (cur = acpi_tables; cur; cur = cur->next)
+    {
+      *(rsdt_entry++) = PTR_TO_UINT32 (cur->addr);
+      numoftables++;
+    }
+  grub_memcpy (&(rsdt->signature), "RSDT", 4);
+  rsdt->length = sizeof (struct grub_acpi_table_header) + 4 * numoftables;
+  rsdt->revision = 1;
+  grub_memcpy (&(rsdt->oemid), root_oemid, 6);
+  grub_memcpy (&(rsdt->oemtable), root_oemtable, 4);
+  rsdt->oemrev = root_oemrev;
+  grub_memcpy (&(rsdt->creator_id), root_creator_id, 6);
+  rsdt->creator_rev = root_creator_rev;
+  
+  rsdt->checksum = 0;
+  rsdt->checksum = 1 + ~grub_efiemu_acpi_checksum (rsdt, rsdt->length);
+}
+
+static void *
+getv1table (void *data __attribute__ ((unused)))
+{
+  struct grub_acpi_rsdp_v10 *rsdp;
+  grub_dprintf ("efiemu", "Generating common tables\n");
+  setup_common_tables ();
+  grub_dprintf ("efiemu", "Generating ACPIv1 tables\n");
+  rsdp = (struct grub_acpi_rsdp_v10 *) 
+    grub_efiemu_mm_obtain_request (rsdpv1_alloc_handle);
+  grub_memcpy (&(rsdp->signature), "RSD PTR ", 8);
+  grub_memcpy (&(rsdp->oemid), root_oemid, sizeof  (rsdp->oemid));
+  rsdp->revision = 0;
+  rsdp->rsdt_addr = PTR_TO_UINT32 (rsdt_addr);
+  rsdp->checksum = 0;
+  rsdp->checksum = 1 + ~grub_efiemu_acpi_checksum (rsdp, 
+                                              sizeof (*rsdp));  
+  grub_dprintf ("efiemu", "Generated ACPIv1 tables\n");
+
+  return rsdp;
+}
+
+static void *
+getv2table (void *data __attribute__ ((unused)))
+{
+  struct grub_acpi_rsdp_v20 *rsdp;
+  struct grub_acpi_table_header *xsdt;
+  struct efiemu_acpi_table *cur;
+  grub_uint64_t *xsdt_entry;
+  int numoftables;
+  grub_dprintf ("efiemu", "Generating common tables\n");
+  setup_common_tables ();
+  grub_dprintf ("efiemu", "Generating ACPIv2 tables\n");
+  xsdt = (struct grub_acpi_table_header *) 
+    grub_efiemu_mm_obtain_request (xsdt_alloc_handle);
+  xsdt_entry = (grub_uint64_t *)(xsdt + 1);
+  numoftables = 0;
+  for (cur = acpi_tables; cur; cur = cur->next)
+    {
+      *(xsdt_entry++) = PTR_TO_UINT64 (cur->addr);
+      numoftables++;
+    }
+  grub_memcpy (&(xsdt->signature), "XSDT", 4);
+  xsdt->length = sizeof (struct grub_acpi_table_header) + 8 * numoftables;
+  xsdt->revision = 1;
+  grub_memcpy (&(xsdt->oemid), root_oemid, sizeof (xsdt->oemid));
+  grub_memcpy (&(xsdt->oemtable), root_oemtable, sizeof (xsdt->oemtable));
+  xsdt->oemrev = root_oemrev;
+  grub_memcpy (&(xsdt->creator_id), root_creator_id, sizeof 
(xsdt->creator_id));
+  xsdt->creator_rev = root_creator_rev;
+  xsdt->checksum = 0;
+  xsdt->checksum = 1 + ~grub_efiemu_acpi_checksum (xsdt, xsdt->length);
+
+  rsdp = (struct grub_acpi_rsdp_v20 *) 
+    grub_efiemu_mm_obtain_request (rsdpv2_alloc_handle);
+  grub_memcpy (&(rsdp->rsdpv1.signature), "RSD PTR ", 
+              sizeof (rsdp->rsdpv1.signature));
+  grub_memcpy (&(rsdp->rsdpv1.oemid), root_oemid, sizeof (rsdp->rsdpv1.oemid));
+  rsdp->rsdpv1.revision = rev2;
+  rsdp->rsdpv1.rsdt_addr = PTR_TO_UINT32 (rsdt_addr);
+  rsdp->rsdpv1.checksum = 0;
+  rsdp->rsdpv1.checksum = 1 + ~grub_efiemu_acpi_checksum 
+    (&(rsdp->rsdpv1), sizeof (rsdp->rsdpv1));
+  rsdp->length = sizeof (*rsdp);
+  rsdp->xsdt_addr = PTR_TO_UINT64 (xsdt);
+  rsdp->checksum = 0;
+  rsdp->checksum = 1 + ~grub_efiemu_acpi_checksum (rsdp, rsdp->length);
+  grub_dprintf ("efiemu", "Generated ACPIv2 tables\n");
+  
+  return rsdp;
+}
+
+static grub_err_t
+grub_cmd_efiemu_acpi (struct grub_arg_list *state,
+                     int argc, char **args)
+{
+  grub_efi_guid_t acpi20 = GRUB_EFI_ACPI_20_TABLE_GUID;
+  grub_efi_guid_t acpi =  GRUB_EFI_ACPI_TABLE_GUID;
+  struct grub_acpi_rsdp_v10 *rsdp;
+  int i;
+  int numtables;
+  
+  grub_efiemu_unregister_configuration_table (acpi);  
+    
+  grub_efiemu_acpi_clear ();
+
+  rev1 = 1;
+  rev2 = 3;
+  
+  rsdp = grub_machine_efiemu_get_rsdp ();
+
+  if (rsdp)
+    {
+      grub_uint32_t *entry_ptr;
+      char *exclude = 0;
+      char *load_only = 0;
+      char *ptr;
+      /* RSDT consists of header and an array of 32-bit pointers */
+      struct grub_acpi_table_header *rsdt;
+
+      exclude = state[0].set ? grub_strdup (state[0].arg) : 0;
+
+      if (exclude)
+       {
+         for (ptr = exclude; ptr; ptr++)
+           *ptr = grub_tolower (*ptr);
+       }
+
+      load_only = state[1].set ? grub_strdup (state[1].arg) : 0;
+      if (load_only)
+       {
+         for (ptr = load_only; ptr; ptr++)
+           *ptr = grub_tolower (*ptr);
+       }
+
+      rev1 = !rsdp->revision;
+      rev2 = rsdp->revision;
+      rsdt = (struct grub_acpi_table_header *)(rsdp->rsdt_addr);
+      for (entry_ptr = (grub_uint32_t *)(rsdt + 1);
+          entry_ptr < (grub_uint32_t *)(((grub_uint8_t *) rsdt)+rsdt->length);
+          entry_ptr++)
+       {
+         char signature[5];
+         struct efiemu_acpi_table *table;
+         struct grub_acpi_table_header *curtable 
+           = (struct grub_acpi_table_header *)*entry_ptr;
+         signature[4] = 0;
+         for (i = 0; i < 4;i++)
+           signature[i] = grub_tolower (curtable->signature[i]);
+         
+         if (!grub_strcmp (signature, "facp"))
+           {
+             struct grub_acpi_table_header *dsdt;
+             struct grub_acpi_fadt *fadt = (struct grub_acpi_fadt *) curtable;
+
+             dsdt = (struct grub_acpi_table_header *) fadt->dsdt_addr;
+             grub_memcpy (&root_oemid, &(fadt->hdr.oemid), 
+                          sizeof (root_oemid));
+             grub_memcpy (&root_oemtable, &(fadt->hdr.oemtable), 
+                          sizeof (root_oemtable));
+             root_oemrev = fadt->hdr.oemrev;
+             grub_memcpy (&root_creator_id, &(fadt->hdr.creator_id), 
+                          sizeof (root_creator_id));
+             root_creator_rev = fadt->hdr.creator_rev;
+
+             if (dsdt && (!exclude || !grub_strword (exclude, "dsdt"))
+                 && (!load_only || grub_strword (load_only, "dsdt"))
+                 && dsdt->length >= sizeof (*dsdt))
+               {
+                 dsdt_size = dsdt->length;
+                 table_dsdt = grub_malloc (dsdt->length);
+                 if (!table_dsdt)
+                   {
+                     grub_efiemu_acpi_clear ();
+                     return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                                        "Could allocate table");
+                   }
+                 grub_memcpy (table_dsdt, dsdt, dsdt->length);
+               }
+             facs_addr = ((struct grub_acpi_fadt *) entry_ptr)->facs_addr;
+           }
+  
+         if (exclude && grub_strword (exclude, signature))
+           continue;
+         if (load_only && !grub_strword (load_only, signature))
+           continue;
+
+         if (curtable->length < sizeof (*curtable))
+           continue;
+         
+         table = (struct efiemu_acpi_table *) grub_malloc 
+           (sizeof (struct efiemu_acpi_table));
+         if (!table)
+           {
+             grub_efiemu_acpi_clear ();
+             return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                                "Could allocate table structure");
+           }
+         table->size = curtable->length;
+         table->data = grub_malloc (table->size);
+         if (!table->data)
+           {
+             grub_efiemu_acpi_clear ();
+             return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                                "Could allocate table");
+           }
+         table->alloc_handle = 0;
+         table->next = acpi_tables;
+         acpi_tables = table;
+         grub_memcpy (table->data, curtable, table->size);
+       }
+      grub_free (exclude);
+      grub_free (load_only);      
+    }
+  if (state[2].set || state[3].set)
+    {
+      rev1 = state[2].set;
+      if (state[3].set)
+       rev2 = rev2 ? : 2;
+      else
+       rev2 = 0;
+    }
+
+  if (state[4].set)
+    grub_strncpy (root_oemid, state[4].arg, sizeof (root_oemid));
+  if (state[5].set)
+    grub_strncpy (root_oemtable, state[5].arg, sizeof (root_oemtable));
+  if (state[6].set)
+    root_oemrev = grub_strtoul (state[6].arg, 0, 0);
+  if (state[7].set)
+    grub_strncpy (root_creator_id, state[7].arg, sizeof (root_creator_id));
+  if (state[8].set)
+    root_creator_rev = grub_strtoul (state[8].arg, 0, 0);
+
+  for (i = 0; i < argc; i++)
+    {
+      grub_file_t file;
+      grub_size_t size;
+      char *buf;
+      file = grub_gzfile_open (args[i], 1);
+      if (!file)
+       {
+         grub_efiemu_acpi_clear ();
+         return grub_error (GRUB_ERR_BAD_OS, "couldn't open file %s", args[i]);
+       }
+      size = grub_file_size (file);
+      if (size < sizeof (struct grub_acpi_table_header))
+       {
+         grub_file_close (file);
+         grub_efiemu_acpi_clear ();
+         return grub_error (GRUB_ERR_BAD_OS, "file %s is too small", args[i]);
+       }
+      buf = (char *) grub_malloc (size);
+      if (grub_file_read (file, buf, size) != (int) size)
+       {
+         grub_file_close (file);
+         grub_efiemu_acpi_clear ();
+         return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[i]);
+       }
+      grub_file_close (file);      
+      if (!grub_memcmp (((struct grub_acpi_table_header *) buf)->signature, 
+                       "DSDT", 4))
+       {
+         grub_free (table_dsdt);
+         table_dsdt = buf;
+         dsdt_size = size;
+       }
+      else
+       {
+         struct efiemu_acpi_table *table;
+         table = (struct efiemu_acpi_table *) grub_malloc 
+           (sizeof (struct efiemu_acpi_table));
+         if (!table)
+           {
+             grub_efiemu_acpi_clear ();
+             return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                                "Could allocate table structure");
+           }
+         table->alloc_handle = 0;
+         table->size = size;
+         table->data = buf;
+       }
+    }
+
+  numtables = 0;
+  {
+    struct efiemu_acpi_table *cur;
+    for (cur = acpi_tables; cur; cur = cur->next)
+      {
+       cur->alloc_handle = grub_efiemu_request_memalign 
+         (1, cur->size, GRUB_EFI_ACPI_RECLAIM_MEMORY);
+       numtables++;
+      }
+  }
+
+
+  rsdt_alloc_handle = grub_efiemu_request_memalign 
+    (1, sizeof (struct grub_acpi_table_header)+4*numtables, 
+     GRUB_EFI_ACPI_RECLAIM_MEMORY);
+
+  if (rev1)
+    {
+      rsdpv1_alloc_handle = grub_efiemu_request_memalign 
+       (1, sizeof (struct grub_acpi_rsdp_v10), 
+        GRUB_EFI_ACPI_RECLAIM_MEMORY);
+      grub_efiemu_register_configuration_table (acpi, getv1table,
+                                               unloadv1table, 0);
+    }
+
+  if (rev2)
+    {
+      rsdpv2_alloc_handle = grub_efiemu_request_memalign 
+       (1, sizeof (struct grub_acpi_rsdp_v20), 
+        GRUB_EFI_ACPI_RECLAIM_MEMORY);
+      xsdt_alloc_handle = grub_efiemu_request_memalign 
+       (1, sizeof (struct grub_acpi_table_header)+8*numtables, 
+        GRUB_EFI_ACPI_RECLAIM_MEMORY);
+      grub_efiemu_register_configuration_table (acpi20, getv2table,
+                                               unloadv2table, 0);
+    }
+  if (dsdt_size)
+    dsdt_alloc_handle = grub_efiemu_request_memalign 
+      (1, dsdt_size, GRUB_EFI_ACPI_RECLAIM_MEMORY);
+  grub_dl_ref (my_mod);
+  return GRUB_ERR_NONE;
+}
+
+GRUB_MOD_INIT(efiemu_acpi)
+{
+  (void) mod;                  /* To stop warning. */
+  grub_register_command ("efiemu_acpi", grub_cmd_efiemu_acpi, 
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "efiemu_acpi [-1|-2] 
[--exclude=table1,table2|--load-only=table1,table2] filename1 [filename2] 
[...]",
+                        "Load host acpi tables and tables specified by 
arguments", 
+                        options);
+  my_mod=mod;
+}
+
+GRUB_MOD_FINI(efiemu_acpi)
+{
+  grub_unregister_command ("efiemu_acpi");
+}
Index: efiemu/loadcore.c
===================================================================
--- efiemu/loadcore.c   (revision 0)
+++ efiemu/loadcore.c   (revision 0)
@@ -0,0 +1,544 @@
+
+#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>
+#include <grub/machine/efiemu.h>
+#include <grub/elf.h>
+
+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 grub_efiemu_sym
+{
+  struct grub_efiemu_sym *next;
+  char *name;
+  int handle;
+  grub_off_t off;
+};
+struct grub_efiemu_elf_sym *grub_efiemu_elfsyms = 0;
+int grub_efiemu_nelfsyms = 0;
+static struct grub_efiemu_sym *efiemu_syms = 0;
+static grub_efiemu_segment_t efiemu_segments = 0;
+static grub_ssize_t efiemu_core_size;
+static void *efiemu_core = 0;
+grub_efiemu_mode_t grub_efiemu_mode = GRUB_EFIEMU_NOTLOADED;
+static int ptv_written = 0;
+static int ptv_alloc = 0;
+static int ptv_handle = 0;
+static int ptv_requested = 0;
+static int grub_efiemu_unload_segs (grub_efiemu_segment_t seg);
+static void grub_efiemu_free_syms (void);
+
+static 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;
+}
+
+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 return the address.
+   Return NULL, if not found.  */
+grub_err_t
+grub_efiemu_resolve_symbol (const char *name, int *handle, grub_off_t *off)
+{
+  struct grub_efiemu_sym *cur;
+  grub_dprintf ("efiemu", "looking for %s\n", name);
+  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);
+}
+
+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 %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;
+}
+
+grub_err_t
+grub_efiemu_write_uint32 (void * addr, grub_uint32_t value, int plus_handle,
+                         int minus_handle, int 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 symbols correctly");
+  if (ptv_needed)
+    {
+      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 = sizeof (grub_uint32_t);
+      ptv_written++;
+      grub_memset (&ptv_rels[ptv_written], 0, sizeof (ptv_rels[ptv_written]));
+    }
+
+  if (minus_handle)
+    value -= PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (minus_handle));
+  else
+    ptv_rels[ptv_written].minustype = 0;
+
+  if (plus_handle)
+    value += PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (plus_handle));
+  else
+    ptv_rels[ptv_written].plustype = 0;
+
+  *((grub_uint32_t *) addr) = value;
+  
+  return GRUB_ERR_NONE;
+}
+
+/* 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);
+}
+
+/* Check if EHDR is a valid ELF header.  */
+static grub_err_t
+grub_efiemu_check_header (void *ehdr, grub_size_t size)
+{
+  Elf32_Ehdr *e = ehdr;
+
+  /* Check the header size.  */
+  if (size < sizeof (Elf32_Ehdr))
+    return grub_error (GRUB_ERR_BAD_OS, "ELF header smaller than expected");
+
+  /* Check the magic numbers.  */
+  if (grub_arch_efiemu_check_header (ehdr, &grub_efiemu_mode)
+      || e->e_ident[EI_MAG0] != ELFMAG0
+      || e->e_ident[EI_MAG1] != ELFMAG1
+      || e->e_ident[EI_MAG2] != ELFMAG2
+      || e->e_ident[EI_MAG3] != ELFMAG3
+      || e->e_ident[EI_VERSION] != EV_CURRENT
+      || e->e_version != EV_CURRENT)
+    return grub_error (GRUB_ERR_BAD_OS, "invalid arch independent ELF magic");
+
+  return GRUB_ERR_NONE;
+}
+
+/* Load all segments from memory specified by E.  */
+static grub_err_t
+grub_efiemu_load_segments32 (grub_efiemu_segment_t segs, const Elf32_Ehdr *e)
+{
+  Elf32_Shdr *s;
+  grub_efiemu_segment_t cur;
+
+  grub_dprintf ("efiemu", "loading segments\n");
+  
+  for (cur=segs; cur; cur = cur->next)
+    {
+      s = (Elf32_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;
+}
+
+static char *
+grub_efiemu_get_string32 (unsigned offset, const Elf32_Ehdr *e)
+{
+  unsigned i;
+  Elf32_Shdr *s;
+
+  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_STRTAB && offset < s->sh_size)
+      {
+       grub_dprintf ("efiemu", "string:%s\n", (char *) e + s->sh_offset + 
offset);
+       return (char *) e + s->sh_offset + offset;
+      }
+  return 0;
+}
+
+static grub_err_t
+grub_efiemu_init_segments32 (grub_efiemu_segment_t *segs, const Elf32_Ehdr *e)
+{
+  unsigned i;
+  Elf32_Shdr *s;
+
+  grub_dprintf ("efiemu", "allocating segments\n");
+  
+  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_flags & SHF_ALLOC)
+       {
+         grub_efiemu_segment_t seg;
+         grub_dprintf ("efiemu", "section %d, %d\n", i, s->sh_size);
+         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;
+           }
+         
+         if (!grub_strcmp (grub_efiemu_get_string32 (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;
+}
+
+static grub_err_t
+grub_efiemu_count_symbols32 (const Elf32_Ehdr *e)
+{
+  unsigned i;
+  Elf32_Shdr *s;
+  int num = 0;
+  
+  grub_dprintf ("efiemu", "counting symbols\n");
+
+  for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_SYMTAB)
+      break;
+
+  if (i == e->e_shnum)
+    return grub_error (GRUB_ERR_BAD_OS, "no symbol table");
+
+  grub_efiemu_nelfsyms = s->sh_size / s->sh_entsize;
+  grub_efiemu_elfsyms = (struct grub_efiemu_elf_sym *) 
+    grub_malloc (sizeof (struct grub_efiemu_elf_sym) * grub_efiemu_nelfsyms);
+
+  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)
+      num += s->sh_size / s->sh_entsize;
+  grub_efiemu_request_symbols (num);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_efiemu_resolve_symbols32 (grub_efiemu_segment_t segs, Elf32_Ehdr *e)
+{
+  unsigned i;
+  Elf32_Shdr *s;
+  Elf32_Sym *sym;
+  const char *str;
+  Elf32_Word size, entsize;
+  
+  grub_dprintf ("efiemu", "resolving symbols\n");
+
+  for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_SYMTAB)
+      break;
+
+  if (i == e->e_shnum)
+    return grub_error (GRUB_ERR_BAD_OS, "no symbol table");
+
+  sym = (Elf32_Sym *) ((char *) e + s->sh_offset);
+  size = s->sh_size;
+  entsize = s->sh_entsize;
+
+  grub_efiemu_nelfsyms = size / entsize;
+  grub_efiemu_elfsyms = (struct grub_efiemu_elf_sym *) 
+    grub_malloc (sizeof (struct grub_efiemu_elf_sym) * grub_efiemu_nelfsyms);
+
+
+  s = (Elf32_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 = (Elf32_Sym *) ((char *) sym + entsize))
+    {
+      unsigned char type = ELF32_ST_TYPE (sym->st_info);
+      unsigned char bind = ELF32_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;
+}
+
+/* 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)
+{
+  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 ();
+  
+  grub_free (grub_efiemu_elfsyms);
+  grub_efiemu_elfsyms = 0;
+
+  ptv_written = 0;
+  ptv_alloc = 0;
+  ptv_requested = 0;
+  grub_efiemu_mm_return_request (ptv_handle);
+  ptv_handle = 0;
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_efiemu_loadcore_init (grub_file_t file)
+{
+  Elf32_Ehdr *e;
+  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);
+      return grub_errno;
+    }
+
+  e = efiemu_core;
+  if (grub_efiemu_check_header (e, efiemu_core_size))
+    {
+      grub_free (efiemu_core);
+      return GRUB_ERR_BAD_MODULE;
+    }
+
+  if (e->e_type != ET_REL)
+    {
+      grub_free (efiemu_core);
+      return grub_error (GRUB_ERR_BAD_MODULE, "invalid ELF file type");
+    }
+
+  /* Make sure that every section is within the core.  */
+  if ((grub_size_t)efiemu_core_size < e->e_shoff + e->e_shentsize * e->e_shnum)
+    {
+      grub_free (efiemu_core);
+      return grub_error (GRUB_ERR_BAD_OS, "ELF sections outside core");
+    }
+
+  if ((err = grub_efiemu_init_segments32 (&efiemu_segments, efiemu_core)))
+    {
+      grub_free (efiemu_core);
+      return err;
+    }
+  if ((err = grub_efiemu_count_symbols32 (efiemu_core)))
+    {
+      grub_free (efiemu_core);
+      return err;
+    }    
+  grub_efiemu_request_symbols (1);
+  return GRUB_ERR_NONE;
+}
+
+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;
+}
+
+grub_err_t
+grub_efiemu_loadcore_load (void)
+{
+  if (grub_efiemu_load_segments32 (efiemu_segments, efiemu_core)
+      || grub_efiemu_resolve_symbols32 (efiemu_segments, efiemu_core)
+      || grub_arch_efiemu_relocate_symbols (efiemu_segments, efiemu_core, 
+                                           grub_efiemu_mode))
+    grub_efiemu_loadcore_unload ();
+    
+  return grub_errno;
+}
Index: efiemu/i386/pc/cfgtables.c
===================================================================
--- efiemu/i386/pc/cfgtables.c  (revision 0)
+++ efiemu/i386/pc/cfgtables.c  (revision 0)
@@ -0,0 +1,22 @@
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/efiemu/efiemu.h>
+#include <grub/machine/efiemu.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+
+grub_err_t
+grub_machine_efiemu_init_tables ()
+{
+  grub_uint8_t *ptr;
+  grub_efi_guid_t smbios = GRUB_EFI_SMBIOS_TABLE_GUID;
+  grub_dprintf ("efiemu", "Registering SMBIOS\n");
+  for (ptr=(grub_uint8_t *)0xf0000;ptr<(grub_uint8_t *)0x100000;ptr+=16)
+    if (!grub_memcmp (ptr, "_SM_", 4))
+      break;
+  /* FIXME: checksum ! */
+  if (ptr < (grub_uint8_t *)0x100000)
+    grub_efiemu_register_configuration_table (smbios, 0, 0, ptr);
+
+  return GRUB_ERR_NONE;
+}

Property changes on: efiemu/i386/pc/cfgtables.c
___________________________________________________________________
Added: svn:mergeinfo

Index: efiemu/i386/loadcore.c
===================================================================
--- efiemu/i386/loadcore.c      (revision 0)
+++ efiemu/i386/loadcore.c      (revision 0)
@@ -0,0 +1,129 @@
+
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/machine/memory.h>
+#include <grub/efiemu/efiemu.h>
+#include <grub/cpu/efiemu.h>
+#include <grub/elf.h>
+
+int
+grub_arch_efiemu_sizeof_uintn_t (void)
+{
+  if (grub_efiemu_mode == GRUB_EFIEMU32)
+    return 4;
+  if (grub_efiemu_mode == GRUB_EFIEMU64)
+    return 8;
+  return 0;
+}
+
+/* Check if EHDR is a valid ELF header.  */
+grub_err_t
+grub_arch_efiemu_check_header (void *ehdr, grub_efiemu_mode_t *mode)
+{
+  Elf32_Ehdr *e32 = ehdr;
+  Elf64_Ehdr *e64 = ehdr;
+
+  /* Check the magic numbers.  */
+  if (e32->e_ident[EI_CLASS] == ELFCLASS32
+      && e32->e_ident[EI_DATA] == ELFDATA2LSB
+      && e32->e_machine == EM_386
+      && (*mode == GRUB_EFIEMU_NOTLOADED || *mode == GRUB_EFIEMU32))
+    {
+      *mode = GRUB_EFIEMU32;
+      return GRUB_ERR_NONE;
+    }
+  if (e64->e_ident[EI_CLASS] == ELFCLASS64
+      && e64->e_ident[EI_DATA] == ELFDATA2LSB
+      && e64->e_machine == EM_X86_64
+      && (*mode == GRUB_EFIEMU_NOTLOADED || *mode == GRUB_EFIEMU64))
+    {
+      *mode = GRUB_EFIEMU64;
+      return GRUB_ERR_NONE;
+    }
+  return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic");
+}
+
+/* Relocate symbols.  */
+static grub_err_t
+grub_arch_efiemu32_relocate_symbols (grub_efiemu_segment_t segs, 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 = grub_efiemu_elfsyms[ELF32_R_SYM (rel->r_info)];
+               
+               switch (ELF32_R_TYPE (rel->r_info))
+                 {
+                 case R_386_32:
+                   if ((err = grub_efiemu_write_uint32 (addr, 
+                                                        sym.off + *addr, 
+                                                        sym.handle,
+                                                        0, 
+                                                        seg->ptv_rel_needed)))
+                     return err;
+                   
+                   break;
+
+                 case R_386_PC32:
+                   if ((err = grub_efiemu_write_uint32 
+                        (addr, sym.off + *addr - rel->r_offset 
+                         - seg->off, sym.handle, 
+                         seg->handle, 
+                         seg->ptv_rel_needed)))
+                     return err;
+                   break;
+                 }
+             }
+         }
+      }
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_arch_efiemu_relocate_symbols (grub_efiemu_segment_t segs, void *ehdr,
+                                  grub_efiemu_mode_t mode)
+{
+  if (mode == GRUB_EFIEMU32)
+    return grub_arch_efiemu32_relocate_symbols (segs, ehdr);
+  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
+                    "64-bit EFI emulation isn't implemented yet");
+}

Property changes on: efiemu/i386/loadcore.c
___________________________________________________________________
Added: svn:mergeinfo

Index: efiemu/mm.c
===================================================================
--- efiemu/mm.c (revision 0)
+++ efiemu/mm.c (revision 0)
@@ -0,0 +1,463 @@
+#include <grub/file.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/machine/memory.h>
+#include <grub/efiemu/efiemu.h>
+#include <grub/cpu/efiemu.h>
+#include <grub/machine/efiemu.h>
+#include <grub/elf.h>
+#include <grub/lib/crc.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;
+};
+static struct grub_efiemu_memrequest *memrequests = 0;
+//static int mmap_handle;
+//static grub_uint8_t *efiemu_mmap = 0;
+static grub_efi_memory_descriptor_t *efiemu_mmap = 0;
+static void *resident_memory = 0;
+static grub_size_t total_alloc = 0;
+static grub_size_t requested_memory[GRUB_EFI_MAX_MEMORY_TYPE];
+static grub_uint64_t type_start[GRUB_EFI_MAX_MEMORY_TYPE];
+static grub_uint64_t type_end[GRUB_EFI_MAX_MEMORY_TYPE];
+
+//static grub_uint64_t mmap_startaddr, mmap_endaddr, mmap_size;
+static int mmap_reserved_size = 0, mmap_num = 0;
+
+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;
+  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");
+    }
+  grub_dprintf ("efiemu", "grub_efiemu_add_to_mmap: %d, 0x%llx, 0x%llx\n",
+               type, start, size);
+  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 = start; 
+  efiemu_mmap[mmap_num].virtual_start = start; 
+  efiemu_mmap[mmap_num].num_pages = npages; 
+  efiemu_mmap[mmap_num].type = type;
+  mmap_num++;
+  return GRUB_ERR_NONE;
+}
+
+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;
+  align_overhead = align - (requested_memory[type]%align);
+  if (align_overhead == align)
+    align_overhead = 0;
+  requested_memory[type] += align_overhead + size;
+  if (type >= GRUB_EFI_MAX_MEMORY_TYPE || type <= GRUB_EFI_LOADER_CODE)
+    return -2;
+  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;
+  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;
+}
+
+static grub_err_t
+efiemu_alloc_requests (void)
+{
+  grub_size_t align_overhead = 0;
+  grub_uint8_t *curptr, *typestart;
+  struct grub_efiemu_memrequest *cur;
+  unsigned i;
+  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,
+
+      GRUB_EFI_RUNTIME_SERVICES_CODE,
+      GRUB_EFI_RUNTIME_SERVICES_DATA,
+      GRUB_EFI_ACPI_MEMORY_NVS,
+      GRUB_EFI_UNUSABLE_MEMORY,
+      GRUB_EFI_MEMORY_MAPPED_IO,
+      GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE,
+      GRUB_EFI_PAL_CODE 
+    };
+  total_alloc = 0;
+  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;
+    }
+  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");
+  curptr = resident_memory;
+  for (i = 0; i < sizeof (reqorder) / sizeof (reqorder[0]); i++)
+    {
+      if (!requested_memory[reqorder[i]])
+       {
+         type_start[reqorder[i]] = type_end[reqorder[i]] = 0;
+         continue;
+       }
+      typestart = curptr;
+      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;
+         }
+      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;      
+      grub_efiemu_add_to_mmap (PTR_TO_UINT64 (typestart), 
+                              curptr - typestart, reqorder[i]);
+    }
+  return GRUB_ERR_NONE;
+}
+
+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;
+}
+
+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;
+}
+
+void
+grub_efiemu_mm_return_request (int handle)
+{
+  struct grub_efiemu_memrequest *cur, *prev;
+  while (memrequests && memrequests->handle == handle)
+    {
+      cur = memrequests->next;
+      grub_free (memrequests);
+      memrequests = cur;
+    }
+  if (!memrequests)
+    return;
+
+  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;
+      }
+
+}
+
+
+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;
+}
+/* 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)
+    return grub_error (GRUB_ERR_INVALID_COMMAND, 
+                      "you need to first launch efiemu_prepare");
+  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;
+}
+
+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;
+}
+
+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;
+}
+
+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);
+       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;
+}
+
+static grub_err_t
+grub_efiemu_mmap_sort_and_uniq (void)
+{
+  int priority[GRUB_EFI_MAX_MEMORY_TYPE] =
+    {
+      [GRUB_EFI_RESERVED_MEMORY_TYPE] = 4,
+      [GRUB_EFI_LOADER_CODE] = 2,
+      [GRUB_EFI_LOADER_DATA] = 2,
+      [GRUB_EFI_BOOT_SERVICES_CODE] = 2,
+      [GRUB_EFI_BOOT_SERVICES_DATA] = 2,
+      [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] = 1,
+      [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;
+  struct grub_efiemu_mmap_scan
+  {
+    grub_uint64_t pos;
+    int type;
+    grub_efi_memory_type_t memtype;
+  };
+
+  struct grub_efiemu_mmap_scan *scanline_events;
+  struct grub_efiemu_mmap_scan t;
+  grub_uint64_t lastaddr;
+  int lasttype;
+  int curtype;
+  int present[GRUB_EFI_MAX_MEMORY_TYPE];
+  grub_efi_memory_descriptor_t *result;
+
+  grub_dprintf ("efiemu", "mmap %d entries originally\n", mmap_num);
+  for (j = 0; j < mmap_num; j++)
+    {
+      grub_dprintf ("efiemu", 
+                   "mmap entry: type %d start 0x%llx 0x%llx pages\n", 
+                   efiemu_mmap[j].type,
+                   efiemu_mmap[j].physical_start, efiemu_mmap[j].num_pages)
+
+    }
+
+  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)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't allocate space for");
+   
+  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;
+    }
+
+  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;
+         }
+    }
+  j = 0;
+  lastaddr = scanline_events[0].pos;
+  lasttype = scanline_events[0].memtype;
+  for (i = 0; i < 2 * mmap_num; i++)
+    {
+      if (scanline_events[i].type)
+       present[scanline_events[i].memtype]--;
+      else
+       present[scanline_events[i].memtype]++;
+      curtype = -1;
+      for (k = 0; k < GRUB_EFI_MAX_MEMORY_TYPE; k++)
+       if (present[k] && (curtype == -1 || priority[k] > priority[curtype]))
+         curtype = k;
+      if ((curtype == -1 || curtype != lasttype) 
+         && lastaddr != scanline_events[i].pos
+         && lasttype != -1 && (scanline_events[i].pos - lastaddr) 
+         / GRUB_EFIEMU_PAGESIZE != 0)
+       {
+         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;
+         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++;
+       }
+      if (curtype == -1 || curtype != lasttype) 
+       {
+         lasttype = curtype;
+         lastaddr = scanline_events[i].pos;
+       }
+    }
+  grub_free (efiemu_mmap);
+  grub_free (scanline_events);
+  efiemu_mmap = grub_realloc (result, j * sizeof (*result));
+  return GRUB_ERR_NONE;
+}
+
+
+grub_err_t
+grub_efiemu_mm_do_alloc (void)
+{
+  /* 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");
+    }
+  efiemu_alloc_requests ();
+  grub_efiemu_mmap_fill ();
+  grub_efiemu_mmap_sort_and_uniq ();
+  return GRUB_ERR_NONE;
+} 
Index: include/grub/autoefi.h
===================================================================
--- include/grub/autoefi.h      (revision 0)
+++ include/grub/autoefi.h      (revision 0)
@@ -0,0 +1,22 @@
+#include <grub/machine/machine.h>
+
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/efi.h>
+#define GRUB_EFI(x) grub_efi_ ## x 
+#define SYSTEM_TABLE_SIZEOF GRUB_EFI_SYSTEM_TABLE_SIZEOF
+#define SYSTEM_TABLE_VAR GRUB_EFI_SYSTEM_TABLE_VAR
+#define SYSTEM_TABLE_PTR GRUB_EFI_SYSTEM_TABLE_PTR
+#define SIZEOF_OF_UINTN GRUB_EFI_SIZEOF_OF_UINTN 
+#define SYSTEM_TABLE GRUB_EFI_SYSTEM_TABLE 
+#else
+#include <grub/efiemu/efiemu.h>
+#include <grub/cpu/efiemu.h>
+#define GRUB_EFI(x) grub_efiemu_ ## x 
+#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
+#endif
Index: include/grub/i386/efiemu.h
===================================================================
--- include/grub/i386/efiemu.h  (revision 0)
+++ include/grub/i386/efiemu.h  (revision 0)
@@ -0,0 +1,15 @@
+#ifndef GRUB_ARCH_EFI_EMU_HEADER
+#define GRUB_ARCH_EFI_EMU_HEADER       1
+
+typedef enum {GRUB_EFIEMU_NOTLOADED,
+             GRUB_EFIEMU32, GRUB_EFIEMU64} grub_efiemu_mode_t;
+
+grub_err_t
+grub_arch_efiemu_relocate_symbols (grub_efiemu_segment_t segs, void *ehdr,
+                                  grub_efiemu_mode_t mode);
+grub_err_t
+grub_arch_efiemu_check_header (void *ehdr, grub_efiemu_mode_t *mode);
+
+extern grub_efiemu_mode_t grub_efiemu_mode;
+
+#endif
Index: include/grub/i386/pc/efiemu.h
===================================================================
--- include/grub/i386/pc/efiemu.h       (revision 0)
+++ include/grub/i386/pc/efiemu.h       (revision 0)
@@ -0,0 +1,6 @@
+#ifndef GRUB_MACHINE_EFI_EMU_HEADER
+#define GRUB_MACHINE_EFI_EMU_HEADER    1
+
+grub_err_t grub_machine_efiemu_init_tables (void);
+
+#endif
Index: include/grub/efi/api.h
===================================================================
--- include/grub/efi/api.h      (revision 1998)
+++ include/grub/efi/api.h      (working copy)
@@ -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
@@ -916,6 +916,20 @@
 };
 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
+
+#define GRUB_EFI_ACPI_20_TABLE_GUID \
+  {0x8868e871,0xe4f1,0x11d3,{0xbc,0x22,0x0,0x80,0xc7,0x3c,0x88,0x81}}
+#define GRUB_EFI_ACPI_TABLE_GUID \
+  {0xeb9d2d30,0x2d88,0x11d3,{0x9a,0x16,0x0,0x90,0x27,0x3f,0xc1,0x4d}}
+#define GRUB_EFI_SAL_SYSTEM_TABLE_GUID \
+  {0xeb9d2d32,0x2d88,0x11d3,{0x9a,0x16,0x0,0x90,0x27,0x3f,0xc1,0x4d}}
+#define GRUB_EFI_SMBIOS_TABLE_GUID \
+  {0xeb9d2d31,0x2d88,0x11d3,{0x9a,0x16,0x0,0x90,0x27,0x3f,0xc1,0x4d}}
+#define GRUB_EFI_MPS_TABLE_GUID \
+  {0xeb9d2d2f,0x2d88,0x11d3,{0x9a,0x16,0x0,0x90,0x27,0x3f,0xc1,0x4d}}
+
 struct grub_efi_simple_input_interface
 {
   grub_efi_status_t
Index: include/grub/efi/efi.h
===================================================================
--- include/grub/efi/efi.h      (revision 1998)
+++ include/grub/efi/efi.h      (working copy)
@@ -24,6 +24,12 @@
 #include <grub/dl.h>
 #include <grub/efi/api.h>
 
+#define GRUB_EFI_SYSTEM_TABLE_SIZEOF(x) (sizeof(grub_efi_system_table->x))
+#define GRUB_EFI_SYSTEM_TABLE_VAR(x) ((void *)&(grub_efi_system_table->x))
+#define GRUB_EFI_SYSTEM_TABLE_PTR(x) ((void *)(grub_efi_system_table->x))
+#define GRUB_EFI_SIZEOF_OF_UINTN sizeof (grub_efi_uintn_t)
+#define GRUB_EFI_SYSTEM_TABLE(x) (grub_efi_system_table->x)
+
 /* Functions.  */
 void *EXPORT_FUNC(grub_efi_locate_protocol) (grub_efi_guid_t *protocol,
                                             void *registration);
Index: include/grub/types.h
===================================================================
--- include/grub/types.h        (revision 1998)
+++ include/grub/types.h        (working copy)
@@ -100,6 +100,16 @@
 # define LONG_MAX 2147483647UL
 #endif
 
+#if GRUB_CPU_SIZEOF_VOID_P == 4
+#define UINT_TO_PTR(x) ((void*)(grub_uint32_t)(x))
+#define PTR_TO_UINT64(x) ((grub_uint64_t)(grub_uint32_t)(x))
+#define PTR_TO_UINT32(x) ((grub_uint32_t)(x))
+#else
+#define UINT_TO_PTR(x) ((void*)(grub_uint64_t)(x))
+#define PTR_TO_UINT64(x) ((grub_uint64_t)(x))
+#define PTR_TO_UINT32(x) ((grub_uint32_t)(grub_uint64_t)(x))
+#endif
+
 /* The type for representing a file offset.  */
 typedef grub_uint64_t  grub_off_t;
 
Index: include/grub/efiemu/efiemu.h
===================================================================
--- include/grub/efiemu/efiemu.h        (revision 0)
+++ include/grub/efiemu/efiemu.h        (revision 0)
@@ -0,0 +1,180 @@
+#ifndef GRUB_EFI_EMU_HEADER
+#define GRUB_EFI_EMU_HEADER    1
+
+#include <grub/efi/api.h>
+
+#define GRUB_EFIEMU_PAGESIZE 4096
+
+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_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;
+};
+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_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;
+};
+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_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;
+
+extern grub_efi_system_table32_t *grub_efiemu_system_table32;
+extern grub_efi_system_table64_t *grub_efiemu_system_table64;
+
+#define grub_efiemu_system_table ((grub_arch_efiemu_sizeof_uintn_t () == 8) ? 
(void *)grub_efiemu_system_table64:(void *)grub_efiemu_system_table32)
+#define GRUB_EFIEMU_SIZEOF_OF_UINTN (grub_arch_efiemu_sizeof_uintn_t ())
+#define GRUB_EFIEMU_SYSTEM_TABLE(x) ((grub_arch_efiemu_sizeof_uintn_t () == 8) 
? grub_efiemu_system_table64->x:grub_efiemu_system_table32->x)
+#define GRUB_EFIEMU_SYSTEM_TABLE_SET(x,y) ((grub_arch_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_arch_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_arch_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_arch_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_arch_efiemu_sizeof_uintn_t () == 8) ? 
sizeof(*grub_efiemu_system_table64):sizeof(*grub_efiemu_system_table32))
+
+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);
+
+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_unload (void);
+
+grub_err_t grub_efiemu_prepare (void);
+
+int grub_arch_efiemu_sizeof_uintn_t (void);
+
+int grub_efiemu_exit_boot_services (grub_efi_uintn_t map_key);
+
+/* loadcore.c */
+struct grub_efiemu_elf_sym
+{
+  int handle;
+  grub_off_t off;
+  unsigned section;
+};
+extern struct grub_efiemu_elf_sym *grub_efiemu_elfsyms;
+extern int grub_efiemu_nelfsyms;
+
+grub_err_t grub_efiemu_alloc_syms (void);
+grub_err_t grub_efiemu_request_symbols (int num);
+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);
+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);
+
+/* mm.c */
+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_err_t
+grub_efiemu_register_prepare_hook (grub_err_t (*hook) (void *data),
+                                  void (*unload) (void *data), 
+                                  void *data);
+
+grub_err_t
+grub_efiemu_write_uint32 (void * addr, grub_uint32_t value, int plus_handle,
+                         int minus_handle, int ptv_needed);
+grub_efi_memory_type_t grub_efiemu_mm_get_type (int handle);
+#endif /* GRUB_EFI_EMU_HEADER */

Property changes on: include/grub/efiemu/efiemu.h
___________________________________________________________________
Added: svn:mergeinfo

Index: include/grub/efiemu/acpi.h
===================================================================
--- include/grub/efiemu/acpi.h  (revision 0)
+++ include/grub/efiemu/acpi.h  (revision 0)
@@ -0,0 +1,42 @@
+
+struct grub_acpi_rsdp_v10
+{
+  grub_uint8_t signature[8];
+  grub_uint8_t checksum;
+  grub_uint8_t oemid[6];
+  grub_uint8_t revision;
+  grub_uint32_t rsdt_addr;
+} __attribute__ ((packed));
+struct grub_acpi_rsdp_v20
+{
+  struct grub_acpi_rsdp_v10 rsdpv1;
+  grub_uint32_t length;
+  grub_uint64_t xsdt_addr;
+  grub_uint8_t checksum;
+  grub_uint8_t reserved[3];
+} __attribute__ ((packed));
+struct grub_acpi_table_header
+{
+  grub_uint8_t signature[4];
+  grub_uint32_t length;
+  grub_uint8_t revision;
+  grub_uint8_t checksum;
+  grub_uint8_t oemid[6];
+  grub_uint8_t oemtable[8];
+  grub_uint32_t oemrev;
+  grub_uint8_t creator_id[4];
+  grub_uint32_t creator_rev;  
+} __attribute__ ((packed));
+struct grub_acpi_fadt
+{
+  struct grub_acpi_table_header hdr;
+  grub_uint32_t facs_addr;
+  grub_uint32_t dsdt_addr;
+  grub_uint8_t somefields1[88];
+  grub_uint64_t facs_xaddr;
+  grub_uint64_t dsdt_xaddr;
+  grub_uint8_t somefields2[96];
+} __attribute__ ((packed));
+
+grub_uint8_t grub_efiemu_acpi_checksum (void *ptr, grub_size_t size);
+struct grub_acpi_rsdp_v10 *grub_machine_efiemu_get_rsdp (void);
Index: loader/linux_normal_efiemu.c
===================================================================
--- loader/linux_normal_efiemu.c        (revision 0)
+++ loader/linux_normal_efiemu.c        (revision 0)
@@ -0,0 +1,64 @@
+/* linux_normal.c - boot linux */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004,2005,2006,2007  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/machine/loader.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+
+void grub_rescue_cmd_linuxefi (int argc, char *argv[]);
+void grub_rescue_cmd_initrdefi (int argc, char *argv[]);
+
+
+static grub_err_t
+grub_normal_linuxefi_command (struct grub_arg_list *state __attribute__ 
((unused)),
+                          int argc, char **args)
+{
+  grub_rescue_cmd_linuxefi (argc, args);
+  return grub_errno;
+}
+
+
+static grub_err_t
+grub_normal_initrd_command (struct grub_arg_list *state __attribute__ 
((unused)),
+                           int argc, char **args)
+{
+  grub_rescue_cmd_initrdefi (argc, args);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(linux_normal)
+{
+  (void) mod; /* To stop warning.  */
+  grub_register_command ("linux_efiemu", grub_normal_linuxefi_command,
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "linux_efiemu FILE [ARGS...]",
+                        "Load a linux kernel.", 0);
+  
+  grub_register_command ("initrd_efiemu", grub_normal_initrd_command,
+                        GRUB_COMMAND_FLAG_BOTH,
+                        "initrd_efiemu FILE",
+                        "Load an initrd.", 0);
+}
+
+GRUB_MOD_FINI(linux_normal)
+{
+  grub_unregister_command ("linux");
+  grub_unregister_command ("initrd");
+}
Index: loader/i386/efi/linux.c
===================================================================
--- loader/i386/efi/linux.c     (revision 1998)
+++ loader/i386/efi/linux.c     (working copy)
@@ -32,6 +32,7 @@
 #include <grub/efi/efi.h>
 #include <grub/efi/uga_draw.h>
 #include <grub/pci.h>
+#include <grub/autoefi.h>
 
 #define GRUB_LINUX_CL_OFFSET           0x1000
 #define GRUB_LINUX_CL_END_OFFSET       0x2000
@@ -114,7 +115,7 @@
       if (! mmap)
        return 0;
 
-      ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0);
+      ret = GRUB_EFI (get_memory_map) (&mmap_size, mmap, 0, &desc_size, 0);
       grub_free (mmap);
       
       if (ret < 0)
@@ -188,7 +189,7 @@
     return 0;
 
   tmp_mmap_size = mmap_size;
-  if (grub_efi_get_memory_map (&tmp_mmap_size, mmap, 0, &desc_size, 0) <= 0)
+  if (GRUB_EFI (get_memory_map) (&tmp_mmap_size, mmap, 0, &desc_size, 0) <= 0)
     grub_fatal ("cannot get memory map");
 
   mmap_end = NEXT_MEMORY_DESCRIPTOR (mmap, tmp_mmap_size);
@@ -293,7 +294,7 @@
 #endif
 
 static grub_err_t
-grub_linux_boot (void)
+grub_linux_efi_boot (void)
 {
   struct linux_kernel_params *params;
   grub_efi_uintn_t mmap_size;
@@ -314,8 +315,8 @@
                (unsigned) gdt_desc.limit, (unsigned long) gdt_desc.base);
 
   mmap_size = find_mmap_size ();
-  if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
-                              &desc_size, &desc_version) <= 0)
+  if (GRUB_EFI (get_memory_map) (&mmap_size, mmap_buf, &map_key,
+                                &desc_size, &desc_version) <= 0)
     grub_fatal ("cannot get memory map");
 
   e820_num = 0;
@@ -391,7 +392,7 @@
 
   params->mmap_size = e820_num;
 
-  if (! grub_efi_exit_boot_services (map_key))
+  if (! GRUB_EFI (exit_boot_services) (map_key))
      grub_fatal ("cannot exit boot services");
 
   /* Note that no boot services are available from here.  */
@@ -513,6 +514,7 @@
   return 0;
 }
 
+#ifdef GRUB_MACHINE_EFI
 static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID;
 
 static int
@@ -562,9 +564,15 @@
 
   return 0;
 }
+#endif
 
+#ifndef GRUB_MACHINE_EFI
 void
+grub_rescue_cmd_linuxefi (int argc, char *argv[])
+#else
+void
 grub_rescue_cmd_linux (int argc, char *argv[])
+#endif
 {
   grub_file_t file = 0;
   struct linux_kernel_header lh;
@@ -667,7 +675,11 @@
   params->video_cursor_x = grub_getxy () >> 8;
   params->video_cursor_y = grub_getxy () & 0xff;
   params->video_page = 0; /* ??? */
+#ifdef GRUB_MACHINE_EFI
   params->video_mode = grub_efi_system_table->con_out->mode->mode;
+#else
+  params->video_mode = 0;
+#endif
   params->video_width = (grub_getwh () >> 8);
   params->video_ega_bx = 0;
   params->video_height = (grub_getwh () & 0xff);
@@ -677,15 +689,15 @@
   if (grub_le_to_cpu16 (params->version) >= 0x0206)
     {
       params->v0206.efi_signature = GRUB_LINUX_EFI_SIGNATURE;
-      params->v0206.efi_system_table = (grub_uint32_t) (unsigned long) 
grub_efi_system_table;
+      params->v0206.efi_system_table = PTR_TO_UINT32 (GRUB_EFI (system_table));
 #ifdef __x86_64__
-      params->v0206.efi_system_table_hi = (grub_uint32_t) ((grub_uint64_t) 
grub_efi_system_table >> 32);
+      params->v0206.efi_system_table_hi = (grub_uint32_t) (PTR_TO_UINT64 
(GRUB_EFI (system_table)) >> 32);
 #endif
     }
   else if (grub_le_to_cpu16 (params->version) >= 0x0204)
     {
       params->v0204.efi_signature = GRUB_LINUX_EFI_SIGNATURE_0204;
-      params->v0204.efi_system_table = (grub_uint32_t) (unsigned long) 
grub_efi_system_table;
+      params->v0204.efi_system_table = PTR_TO_UINT32 (GRUB_EFI (system_table));
     }
 
 #if 0
@@ -807,11 +819,13 @@
           video_type = GRUB_VIDEO_TYPE_EFI;
       }
 
+#ifdef GRUB_EFI_MACHINE_EFI
   if (video_type)
     {
       if (!  grub_linux_setup_video (params))
-        params->have_vga = video_type;
+       params->have_vga = video_type;
     }
+#endif
 
   /* Specify the boot file.  */
   dest = grub_stpcpy ((char *) real_mode_mem + GRUB_LINUX_CL_OFFSET,
@@ -835,7 +849,7 @@
 
   if (grub_errno == GRUB_ERR_NONE)
     {
-      grub_loader_set (grub_linux_boot, grub_linux_unload, 1);
+      grub_loader_set (grub_linux_efi_boot, grub_linux_unload, 1);
       loaded = 1;
     }
 
@@ -851,8 +865,13 @@
     }
 }
 
+#ifndef GRUB_MACHINE_EFI
 void
+grub_rescue_cmd_initrdefi (int argc, char *argv[])
+#else
+void
 grub_rescue_cmd_initrd (int argc, char *argv[])
+#endif
 {
   grub_file_t file = 0;
   grub_ssize_t size;
@@ -900,7 +919,7 @@
   
   /* Find the highest address to put the initrd.  */
   mmap_size = find_mmap_size ();
-  if (grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0) <= 0)
+  if (GRUB_EFI (get_memory_map) (&mmap_size, mmap_buf, 0, &desc_size, 0) <= 0)
     grub_fatal ("cannot get memory map");
 
   addr = 0;
@@ -956,4 +975,12 @@
 
 GRUB_MOD_INIT(linux)
 {
+#ifndef GRUB_MACHINE_EFI
+  grub_rescue_register_command ("linuxefi",
+                               grub_rescue_cmd_linuxefi,
+                               "load linux");
+  grub_rescue_register_command ("initrdefi",
+                               grub_rescue_cmd_initrdefi,
+                               "load initrd");
+#else
   grub_rescue_register_command ("linux",
                                grub_rescue_cmd_linux,
                                "load linux");
   grub_rescue_register_command ("initrd",
                                grub_rescue_cmd_initrd,
                                "load initrd");
+#endif
   my_mod = mod;
 }
 
 GRUB_MOD_FINI(linux)
 {
+#ifndef GRUB_MACHINE_EFI
+  grub_rescue_unregister_command ("linuxefi");
+  grub_rescue_unregister_command ("initrdefi");
+#else
   grub_rescue_unregister_command ("linux");
   grub_rescue_unregister_command ("initrd");
+#endif
 }

reply via email to

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