]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Import Tristan Gingold's ia64 port
authorRobert Millan <rmh@aybabtu.com>
Mon, 18 Jan 2010 14:17:47 +0000 (14:17 +0000)
committerRobert Millan <rmh@aybabtu.com>
Mon, 18 Jan 2010 14:17:47 +0000 (14:17 +0000)
(based on patch sent to grub-devel by Tristan in 2008-01-28)

32 files changed:
ChangeLog.ia64 [new file with mode: 0644]
Makefile.in
commands/efi/acpi.c [new file with mode: 0644]
commands/efi/memmap.c [new file with mode: 0644]
commands/efi/systab.c [new file with mode: 0644]
conf/ia64-efi.rmk [new file with mode: 0644]
configure.ac
geninit.sh
genmk.rb
include/grub/dl.h
include/grub/efi/efi.h
include/grub/ia64/efi/kernel.h [new file with mode: 0644]
include/grub/ia64/efi/loader.h [new file with mode: 0644]
include/grub/ia64/efi/misc.h [new file with mode: 0644]
include/grub/ia64/efi/time.h [new file with mode: 0644]
include/grub/ia64/setjmp.h [new file with mode: 0644]
include/grub/ia64/time.h [new file with mode: 0644]
include/grub/ia64/types.h [new file with mode: 0644]
include/grub/kernel.h
kern/dl.c
kern/efi/mm.c
kern/ia64/efi/elf_ia64_efi.lds [new file with mode: 0644]
kern/ia64/efi/init.c [new file with mode: 0644]
kern/ia64/efi/startup.S [new file with mode: 0644]
kern/ia64/trampoline.S [new file with mode: 0644]
loader/ia64/efi/linux.c [new file with mode: 0644]
loader/ia64/efi/linux_normal.c [new file with mode: 0644]
normal/ia64/longjmp.S [new file with mode: 0644]
normal/ia64/setjmp.S [new file with mode: 0644]
util/ia64/efi/elf2pe.c [new file with mode: 0644]
util/ia64/efi/grub-install.in [new file with mode: 0644]
util/ia64/efi/pe32.h [new file with mode: 0644]

diff --git a/ChangeLog.ia64 b/ChangeLog.ia64
new file mode 100644 (file)
index 0000000..35417be
--- /dev/null
@@ -0,0 +1,45 @@
+2008-01-28  Tristan Gingold  <gingold@free.fr>
+
+       * geninit.sh: Call _init with a null argument.
+       * configure.ac: Add ia64-efi target.
+       * Makefile.in (STRIP_FLAGS): Declare (overriden on ia64).
+       (RMKFILES): Add ia64-efi.rmk
+       * genmk.rb: Use STRIP_FLAGS for strip.
+       * util/ia64/efi/grub-install.in: New file.
+       * util/ia64/efi/pe32.h: New file.
+       * util/ia64/efi/elf2pe.c: New file.
+       * normal/ia64/setjmp.S: New file (from glibc).
+       * normal/ia64/longjmp.S: New file (from glibc).
+       * loader/ia64/efi/linux_normal.c: New file.
+       * loader/ia64/efi/linux.c: New file.
+       * conf/ia64-efi.rmk: New file.
+       * commands/efi/systab.c: New file.
+       * commands/efi/memmap.c: New file.
+       * commands/efi/acpi.c: New file.
+       * include/grub/efi/efi.h: Declare grub_efi_allocate_boot_pages and
+       grub_efi_free_boot_pages.
+       * include/grub/kernel.h: Export grub_machine_fini.
+       * include/grub/dl.h: Use attribute instead of raw asm statement.
+       Use grub_module as prefix to make identification easier.
+       * include/grub/ia64/efi/time.h: New file.
+       * include/grub/ia64/efi/misc.h: New file.
+       * include/grub/ia64/efi/loader.h: New file.
+       * include/grub/ia64/efi/kernel.h: New file.
+       * include/grub/ia64/time.h: New file.
+       * include/grub/ia64/setjmp.h: New file.
+       * include/grub/ia64/types.h: New file.
+       * kern/efi/mm.c (BYTES_TO_PAGES): Round instead of truncating.
+       (grub_efi_allocate_boot_pages): Low level interface to allocate_pages.
+       (grub_efi_free_boot_pages): Low level interface to free_pages.
+       (grub_efi_allocate_pages): Call grub_efi_allocate_boot_pages.
+       (grub_efi_free_pages): Call grubèefi_free_boot_pages.
+       (add_memory_regions): Add debug message in ifdef.
+       (add_memory_regions): Add debug message in ifdef.
+       (grub_efi_mm_init): Do not constraint memory map length, add space for
+       a few more entries.
+       * kern/dl.c (grub_init_module): New function.  Register an already
+       linked module.
+       * kern/ia64/efi/elf_ia64_efi.lds: New file.
+       * kern/ia64/efi/startup.S: New file.
+       * kern/ia64/efi/init.c: New file.
+       * kern/ia64/trampoline.S: New file.
index 84b4e9c7c0a61c2d816d491739cd9f847804848f..134505d3c611ff3db2ee997f6d75d5cb2f15a323 100644 (file)
@@ -67,6 +67,7 @@ TARGET_CFLAGS = @TARGET_CFLAGS@
 TARGET_CPPFLAGS = @TARGET_CPPFLAGS@ -I. -Iinclude -I$(srcdir)/include \
        -Wall -W
 TARGET_LDFLAGS = @TARGET_LDFLAGS@
+STRIP_FLAGS=--strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment 
 OBJCOPY = @OBJCOPY@
 STRIP = @STRIP@
 NM = @NM@
@@ -83,7 +84,7 @@ enable_grub_emu = @enable_grub_emu@
 ### General variables.
 
 RMKFILES = $(addprefix conf/,common.rmk i386-pc.rmk powerpc-ieee1275.rmk \
-       sparc64-ieee1275.rmk i386-efi.rmk)
+       sparc64-ieee1275.rmk i386-efi.rmk ia64-efi.rmk)
 MKFILES = $(patsubst %.rmk,%.mk,$(RMKFILES))
 
 PKGLIB = $(pkglib_IMAGES) $(pkglib_MODULES) $(pkglib_PROGRAMS) \
diff --git a/commands/efi/acpi.c b/commands/efi/acpi.c
new file mode 100644 (file)
index 0000000..ea9783f
--- /dev/null
@@ -0,0 +1,193 @@
+/* acpi.c  - Display acpi.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <grub/types.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+
+static grub_uint32_t read16 (grub_uint8_t *p)
+{
+  return p[0] | (p[1] << 8);
+}
+
+static grub_uint32_t read32 (grub_uint8_t *p)
+{
+  return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+}
+
+static grub_uint64_t read64 (grub_uint8_t *p)
+{
+  grub_uint32_t l, h;
+  l = read32(p);
+  h = read32(p + 4);
+  return l | (((grub_uint64_t)h) << 32);
+}
+
+static void
+disp_acpi_table (grub_uint8_t *t)
+{
+  int i;
+  grub_printf ("%c%c%c%c %4dB rev=%d OEM=", t[0], t[1], t[2], t[3],
+              read32 (t + 4), t[8]);
+  for (i = 0; i < 6; i++)
+    grub_printf ("%c", t[10 + i]);
+  grub_printf (" ");
+  for (i = 0; i < 8; i++)
+    grub_printf ("%c", t[16 + i]);
+  grub_printf (" V=%08lx ", read32 (t + 24));
+  for (i = 0; i < 4; i++)
+    grub_printf ("%c", t[28 + i]);
+  grub_printf (" %08lx\n", read32 (t + 32));
+
+}
+
+static void
+disp_acpi_apic_table (grub_uint8_t *t)
+{
+  grub_uint8_t *d;
+  grub_uint32_t len;
+  grub_uint32_t flags;
+
+  disp_acpi_table (t);
+  grub_printf ("Local APIC=%08lx  Flags=%08lx\n",
+              read32 (t + 36), read32 (t + 40));
+  len = read32 (t + 4);
+  len -= 44;
+  d = t + 44;
+  while (len > 0)
+    {
+      grub_uint32_t l = d[1];
+      grub_printf ("  type=%x l=%d ", d[0], l);
+
+      switch (d[0])
+       {
+       case 2:
+         grub_printf ("Int Override bus=%x src=%x GSI=%08x Flags=%04x",
+                      d[2], d[3], read32 (d + 4), read16 (d + 8));
+         break;
+       case 6:
+         grub_printf ("IOSAPIC Id=%02x GSI=%08x Addr=%016llx",
+                      d[2], read32 (d + 4), read64 (d + 8));
+         break;
+       case 7:
+         flags = read32 (d + 8);
+         grub_printf ("LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x",
+                      d[2], d[3], d[4], flags);
+         if (flags & 1)
+           grub_printf (" Enabled");
+         else
+           grub_printf (" Disabled");
+         if (l >= 17)
+           grub_printf ("\n"
+                        "    UID val=%08x, Str=%s", read32 (d + 12), d + 16);
+         break;
+       case 8:
+         grub_printf ("Platform INT flags=%04x type=%02x (",
+                      read16 (d + 2), d[4]);
+         if (d[4] <= 3)
+           {
+             static const char * const platint_type[4] =
+               {"Nul", "PMI", "INIT", "CPEI"};
+             grub_printf ("%s", platint_type[d[4]]);
+           }
+         else
+           grub_printf ("??");
+         grub_printf (") ID=%02x EID=%02x\n", d[5], d[6]);
+         grub_printf ("      IOSAPIC Vec=%02x GSI=%08x source flags=%08x",
+                      d[7], read32 (d + 8), read32 (d + 12));
+         break;
+       default:
+         grub_printf (" ??");
+       }
+      grub_printf ("\n");
+      d += l;
+      len -= l;
+    }
+}
+
+static void
+disp_acpi_xsdt_table (grub_uint8_t *t)
+{
+  grub_uint32_t len;
+  grub_uint8_t *desc;
+
+  disp_acpi_table (t);
+  len = read32 (t + 4) - 36;
+  desc = t + 36;
+  while (len > 0)
+    {
+      t = read64 (desc);
+         
+      if (t[0] == 'A' && t[1] == 'P' && t[2] == 'I' && t[3] == 'C')
+       disp_acpi_apic_table (t);
+      else
+       disp_acpi_table (t);
+      desc += 8;
+      len -= 8;
+    }
+}
+
+static void
+disp_acpi_rsdt_table (grub_uint8_t *t)
+{
+  grub_uint32_t len;
+  grub_uint8_t *desc;
+
+  disp_acpi_table (t);
+  len = read32 (t + 4) - 36;
+  desc = t + 36;
+  while (len > 0)
+    {
+      t = read32 (desc);
+         
+      if (t != NULL)
+       disp_acpi_table (t);
+      desc += 4;
+      len -= 4;
+    }
+}
+
+void
+disp_acpi_rsdp_table (grub_uint8_t *rsdp)
+{
+  grub_uint8_t *t = rsdp;
+  int i;
+  grub_uint8_t *xsdt;
+
+  grub_printf ("RSDP signature:");
+  for (i = 0; i < 8; i++)
+    grub_printf ("%c", t[i]);
+  grub_printf (" chksum:%02x, OEM-ID: ", t[8]);
+  for (i = 0; i < 6; i++)
+    grub_printf ("%c", t[9 + i]);
+  grub_printf (" rev=%d\n", t[15]);
+  grub_printf ("RSDT=%08lx", read32 (t + 16));
+  if (t[15] == 2)
+    {
+      xsdt = read64 (t + 24);
+      grub_printf (" len=%d XSDT=%016llx\n", read32 (t + 20), xsdt);
+      grub_printf ("\n");
+      disp_acpi_xsdt_table (xsdt);
+    }
+  else
+    {
+      grub_printf ("\n");
+      disp_acpi_rsdt_table (read32 (t + 16));
+    }
+}
diff --git a/commands/efi/memmap.c b/commands/efi/memmap.c
new file mode 100644 (file)
index 0000000..a3ce828
--- /dev/null
@@ -0,0 +1,143 @@
+/* memmap.c  - Display memory map.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <grub/types.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+
+#define ADD_MEMORY_DESCRIPTOR(desc, size)      \
+  ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
+
+static grub_err_t
+grub_cmd_memmap (struct grub_arg_list *state, int argc, char **args)
+{
+  grub_efi_uintn_t map_size;
+  grub_efi_memory_descriptor_t *memory_map;
+  grub_efi_memory_descriptor_t *memory_map_end;
+  grub_efi_memory_descriptor_t *desc;
+  grub_efi_uintn_t desc_size;
+
+  map_size = 0;
+  if (grub_efi_get_memory_map (&map_size, NULL, NULL, &desc_size, 0) < 0)
+    return 0;
+
+  memory_map = grub_malloc (map_size);
+  if (memory_map == NULL)
+    return 0;
+  if (grub_efi_get_memory_map (&map_size, memory_map, NULL, &desc_size, 0) < 0)
+    goto fail;
+
+  grub_set_more (1);
+
+  grub_printf
+    ("Type      Physical start  - end             #Pages   "
+     "  Size Attributes\n");
+  memory_map_end = ADD_MEMORY_DESCRIPTOR(memory_map, map_size);
+  for (desc = memory_map;
+       desc < memory_map_end;
+       desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size))
+    {
+      grub_efi_uintn_t size;
+      grub_efi_uint64_t attr;
+      static const char types_str[][9] = 
+       {
+         "reserved", 
+         "ldr-code",
+         "ldr-data",
+         "BS-code ",
+         "BS-data ",
+         "RT-code ",
+         "RT-data ",
+         "conv-mem",
+         "unusable",
+         "ACPI-rec",
+         "ACPI-nvs",
+         "MMIO    ",
+         "IO-ports",
+         "PAL-code"
+       };
+      if (desc->type < sizeof (types_str) / sizeof (types_str[0]))
+       grub_printf ("%s ", types_str[desc->type]);
+      else
+       grub_printf ("Unk %02x   ", desc->type);
+      
+      grub_printf (" %016llx-%016llx %08lx",
+                  desc->physical_start,
+                  desc->physical_start + (desc->num_pages << 12) - 1,
+                  desc->num_pages);
+
+      size = desc->num_pages << (12 - 10);
+      if (size < 1024)
+       grub_printf (" %4uKB", size);
+      else
+       {
+         size /= 1024;
+         if (size < 1024)
+           grub_printf (" %4uMB", size);
+         else
+           {
+             size /= 1024;
+             grub_printf (" %4uGB", size);
+           }
+       }
+
+      attr = desc->attribute;
+      if (attr & GRUB_EFI_MEMORY_RUNTIME)
+       grub_printf (" RT");
+      if (attr & GRUB_EFI_MEMORY_UC)
+       grub_printf (" UC");
+      if (attr & GRUB_EFI_MEMORY_WC)
+       grub_printf (" WC");
+      if (attr & GRUB_EFI_MEMORY_WT)
+       grub_printf (" WT");
+      if (attr & GRUB_EFI_MEMORY_WB)
+       grub_printf (" WB");
+      if (attr & GRUB_EFI_MEMORY_UCE)
+       grub_printf (" UCE");
+      if (attr & GRUB_EFI_MEMORY_WP)
+       grub_printf (" WP");
+      if (attr & GRUB_EFI_MEMORY_RP)
+       grub_printf (" RP");
+      if (attr & GRUB_EFI_MEMORY_XP)
+       grub_printf (" XP");
+
+      grub_printf ("\n");
+    }
+
+  grub_set_more (0);
+
+ fail:
+  grub_free (memory_map);
+  return 0;
+}
+
+GRUB_MOD_INIT(memmap)
+{
+  (void)mod;                   /* To stop warning. */
+  grub_register_command ("memmap", grub_cmd_memmap, GRUB_COMMAND_FLAG_BOTH,
+                        "memmap",
+                        "Display memory map.", NULL);
+}
+
+GRUB_MOD_FINI(memmap)
+{
+  grub_unregister_command ("memmap");
+}
diff --git a/commands/efi/systab.c b/commands/efi/systab.c
new file mode 100644 (file)
index 0000000..1d90ca9
--- /dev/null
@@ -0,0 +1,258 @@
+/* systab.c  - Display EFI systab.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <grub/types.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+
+#define ACPI_20_TABLE_GUID \
+{0x8868e871,0xe4f1,0x11d3,{0xbc,0x22,0x0,0x80,0xc7,0x3c,0x88,0x81}}
+#define ACPI_TABLE_GUID \
+{0xeb9d2d30,0x2d88,0x11d3,{0x9a,0x16,0x0,0x90,0x27,0x3f,0xc1,0x4d}}
+#define SAL_SYSTEM_TABLE_GUID \
+{0xeb9d2d32,0x2d88,0x11d3,{0x9a,0x16,0x0,0x90,0x27,0x3f,0xc1,0x4d}}
+#define SMBIOS_TABLE_GUID \
+{0xeb9d2d31,0x2d88,0x11d3,{0x9a,0x16,0x0,0x90,0x27,0x3f,0xc1,0x4d}}
+#define MPS_TABLE_GUID \
+{0xeb9d2d2f,0x2d88,0x11d3,{0x9a,0x16,0x0,0x90,0x27,0x3f,0xc1,0x4d}}
+#define HCDP_TABLE_GUID \
+{0xf951938d,0x620b,0x42ef,{0x82,0x79,0xa8,0x4b,0x79,0x61,0x78,0x98}}
+
+struct guid_mapping
+{
+  grub_efi_guid_t guid;
+  const char *name;
+  void (*disp)(struct guid_mapping *map, void *table);
+};
+
+static void disp_sal (struct guid_mapping *map, void *table);
+static void disp_acpi (struct guid_mapping *map, void *table);
+
+static const struct guid_mapping guid_mappings[] =
+  {
+    { ACPI_20_TABLE_GUID, "ACPI-2.0", disp_acpi},
+    { ACPI_TABLE_GUID, "ACPI-1.0", disp_acpi},
+    { SAL_SYSTEM_TABLE_GUID, "SAL", disp_sal},
+    { SMBIOS_TABLE_GUID, "SMBIOS",NULL},
+    { MPS_TABLE_GUID, "MPS", NULL},
+    { HCDP_TABLE_GUID, "HCDP", NULL}
+  };
+
+struct sal_system_table
+{
+  grub_uint32_t signature;
+  grub_uint32_t total_table_len;
+  grub_uint16_t sal_rev;
+  grub_uint16_t entry_count;
+  grub_uint8_t checksum;
+  grub_uint8_t reserved1[7];
+  grub_uint16_t sal_a_version;
+  grub_uint16_t sal_b_version;
+  grub_uint8_t oem_id[32];
+  grub_uint8_t product_id[32];
+  grub_uint8_t reserved2[8];
+};
+
+static void
+disp_sal (struct guid_mapping *map, void *table)
+{
+  struct sal_system_table *t = table;
+  grub_uint8_t *desc = table;
+  grub_uint32_t len, l;
+
+  grub_printf ("SAL rev: %02x, signature: %x, len:%x\n",
+              t->sal_rev, t->signature, t->total_table_len);
+  grub_printf ("nbr entry: %d, chksum: %02x, SAL version A: %02x B: %02x\n",
+              t->entry_count, t->checksum,
+              t->sal_a_version, t->sal_b_version);
+  grub_printf ("OEM-ID: %-32s\n", t->oem_id);
+  grub_printf ("Product-ID: %-32s\n", t->product_id);
+
+  desc += sizeof (struct sal_system_table);
+  len = t->total_table_len - sizeof (struct sal_system_table);
+  while (len > 0)
+    {
+      switch (*desc)
+       {
+       case 0:
+         l = 48;
+         grub_printf (" Entry point: PAL=%016lx SAL=%016lx GP=%016lx\n",
+                      *(grub_uint64_t*)(desc + 8),
+                      *(grub_uint64_t*)(desc + 16),
+                      *(grub_uint64_t*)(desc + 24));
+         break;
+       case 1:
+         l = 32;
+         grub_printf (" Memory descriptor entry addr=%016llx len=%uKB\n",
+                      *(grub_uint64_t*)(desc + 8),
+                      *(grub_uint32_t*)(desc + 16) * 4);
+         grub_printf ("     sal_used=%d attr=%x AR=%x attr_mask=%x "
+                      "type=%x usage=%x\n",
+                      desc[1], desc[2], desc[3], desc[4], desc[5], desc[6]);
+         break;
+       case 2:
+         l = 16;
+         grub_printf (" Platform features: %02x", desc[1]);
+         if (desc[1] & 0x01)
+           grub_printf (" BusLock");
+         if (desc[1] & 0x02)
+           grub_printf (" IrqRedirect");
+         if (desc[1] & 0x04)
+           grub_printf (" IPIRedirect");
+         grub_printf ("\n");
+         break;
+       case 3:
+         l = 32;
+         grub_printf (" TR type=%d num=%d va=%016llx pte=%016llx\n",
+                      desc[1], desc[2],
+                      *(grub_uint64_t *)(desc + 8),
+                      *(grub_uint64_t *)(desc + 16));
+         break;
+       case 4:
+         l = 16;
+         grub_printf (" PTC coherence nbr=%d addr=%016llx\n",
+                      desc[1], *(grub_uint64_t *)(desc + 8));
+         break;
+       case 5:
+         l = 16;
+         grub_printf (" AP wake-up: mec=%d vect=%x\n",
+                      desc[1], *(grub_uint64_t *)(desc + 8));
+         break;
+       default:
+         grub_printf (" unknown entry %d\n", *desc);
+         return;
+       }
+      desc += l;
+      len -= l;
+    }
+}
+
+static void
+disp_acpi (struct guid_mapping *map, void *table)
+{
+  disp_acpi_rsdp_table (table);
+}
+
+static void
+disp_systab (void)
+{
+  grub_efi_char16_t *vendor;
+  const grub_efi_system_table_t *st = grub_efi_system_table;
+  grub_efi_configuration_table_t *t;
+  unsigned int i;
+
+  grub_printf ("Signature: %016llx revision: %08x\n",
+              st->hdr.signature, st->hdr.revision);
+  grub_printf ("Vendor: ");
+  for (vendor = st->firmware_vendor; *vendor; vendor++)
+    grub_printf ("%c", *vendor);
+  grub_printf (", Version=%x\n", st->firmware_revision);
+
+  grub_printf ("%ld tables:\n", st->num_table_entries);
+  t = st->configuration_table;
+  for (i = 0; i < st->num_table_entries; i++)
+    {
+      unsigned int j;
+
+      grub_printf ("%016llx  ", (grub_uint64_t)t->vendor_table);
+
+      grub_printf ("%08x-%04x-%04x-",
+                  t->vendor_guid.data1, t->vendor_guid.data2,
+                  t->vendor_guid.data3);
+      for (j = 0; j < 8; j++)
+       grub_printf ("%02x", t->vendor_guid.data4[j]);
+      
+      for (j = 0; j < sizeof (guid_mappings)/sizeof(guid_mappings[0]); j++)
+       if (grub_memcmp (&guid_mappings[j].guid, &t->vendor_guid,
+                        sizeof (grub_efi_guid_t)) == 0)
+         grub_printf ("   %s", guid_mappings[j].name);
+
+      grub_printf ("\n");
+      t++;
+    }
+}
+
+static void
+disp_systab_entry (const char *name)
+{
+  const grub_efi_system_table_t *st = grub_efi_system_table;
+  grub_efi_configuration_table_t *t;
+  unsigned int i;
+  struct guid_mapping *map;
+
+  map = NULL;
+  for (i = 0; i < sizeof (guid_mappings)/sizeof(guid_mappings[0]); i++)
+    if (grub_strcmp (guid_mappings[i].name, name) == 0)
+      {
+       map = &guid_mappings[i];
+       break;
+      }
+  if (map == NULL)
+    {
+      grub_printf ("System table '%s' unknown\n", name);
+      return;
+    }
+  if (map->disp == NULL)
+    {
+      grub_printf ("Don't know how to display table '%s'\n", name);
+      return;
+    }
+  t = st->configuration_table;
+  for (i = 0; i < st->num_table_entries; i++)
+    {
+      if (grub_memcmp (&map->guid, &t->vendor_guid,
+                      sizeof (grub_efi_guid_t)) == 0)
+       {
+         grub_set_more (1);
+         (*map->disp)(map, t->vendor_table);
+         grub_set_more (0);
+         return;
+       }
+      t++;
+    }
+  grub_printf ("Systab '%s' not found\n", map->name);
+}
+
+static grub_err_t
+grub_cmd_systab (struct grub_arg_list *state, int argc, char **args)
+{
+  int i;
+
+  if (argc == 0)
+    disp_systab ();
+  else
+    for (i = 0; i < argc; i++)
+      disp_systab_entry (args[i]);
+  return 0;
+}
+
+GRUB_MOD_INIT(systab)
+{
+  (void)mod;                   /* To stop warning. */
+  grub_register_command ("systab", grub_cmd_systab, GRUB_COMMAND_FLAG_BOTH,
+                        "systab [NAME]",
+                        "Display EFI system table.", NULL);
+}
+
+GRUB_MOD_FINI(systab)
+{
+  grub_unregister_command ("systab");
+}
diff --git a/conf/ia64-efi.rmk b/conf/ia64-efi.rmk
new file mode 100644 (file)
index 0000000..ce72d14
--- /dev/null
@@ -0,0 +1,122 @@
+# -*- makefile -*-
+
+COMMON_ASFLAGS = -nostdinc -fno-builtin
+COMMON_CFLAGS = -fno-builtin -fpic -minline-int-divide-max-throughput
+COMMON_LDFLAGS = -melf_64 -nostdlib 
+
+STRIP_FLAGS=-R .note -R .comment -X
+
+# Utilities.
+bin_UTILITIES = grub-elf2pe
+#sbin_UTILITIES = grub-emu
+
+# Scripts.
+sbin_SCRIPTS = grub-install
+
+# For grub-install.
+grub_install_SOURCES = util/ia64/efi/grub-install.in
+
+pkgdata_DATA += kern/ia64/efi/elf_ia64_efi.lds
+
+# For grub-elf2pe
+grub_elf2pe_SOURCES = util/ia64/efi/elf2pe.c
+
+# For grub-emu.
+grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c       \
+       commands/configfile.c commands/help.c                           \
+       commands/terminal.c commands/ls.c commands/test.c               \
+       commands/search.c commands/blocklist.c                          \
+       disk/loopback.c                                                 \
+       fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c  \
+       fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c     \
+       io/gzio.c                                                       \
+       kern/device.c kern/disk.c kern/dl.c kern/env.c kern/err.c       \
+       normal/execute.c kern/file.c kern/fs.c normal/lexer.c           \
+       kern/loader.c kern/main.c kern/misc.c kern/parser.c             \
+       grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c    \
+       normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
+       normal/completion.c normal/main.c                               \
+       normal/menu.c normal/menu_entry.c normal/misc.c normal/script.c \
+       partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c      \
+       partmap/acorn.c partmap/gpt.c                                   \
+       util/console.c util/grub-emu.c util/misc.c                      \
+       util/i386/pc/misc.c grub_emu_init.c
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+# Modules.
+pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod \
+       _linux.mod linux.mod memmap.mod systab.mod
+
+# For kernel.mod.
+kernel_mod_EXPORTS = no
+kernel_mod_SOURCES = kern/ia64/efi/startup.S \
+       kern/ia64/trampoline.S \
+       kern/main.c kern/device.c \
+       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
+       kern/i386/dl.c kern/ia64/efi/init.c kern/parser.c kern/partition.c \
+       kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \
+       term/efi/console.c disk/efi/efidisk.c
+kernel_mod_HEADERS = arg.h boot.h device.h disk.h dl.h elf.h env.h err.h \
+       file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h partition.h \
+       pc_partition.h rescue.h symbol.h term.h types.h cache.h \
+       i386/efi/time.h efi/efi.h efi/time.h efi/disk.h ia64/efi/misc.h
+kernel_mod_CFLAGS = $(COMMON_CFLAGS)
+kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+MOSTLYCLEANFILES += symlist.c
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+symlist.c: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h gensymlist.sh
+       /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h genkernsyms.sh
+       /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+# For normal.mod.
+normal_mod_DEPENDENCIES = grub_script.tab.c grub_script.tab.h
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c    \
+       normal/completion.c normal/execute.c            \
+       normal/function.c normal/lexer.c normal/main.c normal/menu.c    \
+       normal/menu_entry.c normal/misc.c grub_script.tab.c             \
+       normal/script.c \
+       normal/ia64/setjmp.S normal/ia64/longjmp.S normal/color.c
+
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _chain.mod.
+_chain_mod_SOURCES = loader/efi/chainloader.c
+_chain_mod_CFLAGS = $(COMMON_CFLAGS)
+_chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For chain.mod.
+chain_mod_SOURCES = loader/efi/chainloader_normal.c
+chain_mod_CFLAGS = $(COMMON_CFLAGS)
+chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _linux.mod.
+_linux_mod_SOURCES = loader/ia64/efi/linux.c
+_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/ia64/efi/linux_normal.c
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For memmap.mod.
+memmap_mod_SOURCES = commands/efi/memmap.c
+memmap_mod_CFLAGS = $(COMMON_CFLAGS)
+memmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For systab.mod.
+systab_mod_SOURCES = commands/efi/systab.c commands/efi/acpi.c
+systab_mod_CFLAGS = $(COMMON_CFLAGS)
+systab_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+include $(srcdir)/conf/common.mk
index b3f73e0bd756a20e37f3f5dd8f7b56dc14d107b3..895b5ffc37d4b36a50b23af48eaa17bd348f8650 100644 (file)
@@ -53,7 +53,8 @@ case "$target_cpu" in
   powerpc) ;;
   powerpc64) target_cpu=powerpc target_m32=1;;
   sparc64) ;;
-  *) AC_MSG_ERROR([unsupported CPU type]) ;;
+  ia64) ;;
+  *) AC_MSG_ERROR([unsupported CPU type $target_cpu]) ;;
 esac
 
 # Specify the platform (such as firmware).
@@ -68,6 +69,7 @@ if test "x$with_platform" = x; then
     i386-*) platform=pc ;;
     powerpc-*) platform=ieee1275 ;;
     sparc64-*) platform=ieee1275 ;;
+    ia64*) platform=efi ;;
     *) AC_MSG_ERROR([unsupported machine type]) ;;
   esac
 else
@@ -82,6 +84,7 @@ case "$target_cpu"-"$platform" in
   i386-ieee1275) ;;
   powerpc-ieee1275) ;;
   sparc64-ieee1275) ;;
+  ia64-efi) ;;
   *) AC_MSG_ERROR([unsupported machine type]) ;;
 esac
 
index 43d2d1640f937b94f457f64c254043819f61166a..31a6d660bc868bc17adc361ef3302c1fca7ce00e 100644 (file)
@@ -49,7 +49,7 @@ EOF
 while read line; do
   file=`echo $line | cut -f1 -d:`
   if echo $@ | grep $file >/dev/null; then
-    echo $line | sed -e 's/.*GRUB_MOD_INIT *(\([a-zA-Z0-9_]*\)).*/  grub_\1_init ();/'
+    echo $line | sed -e 's/.*GRUB_MOD_INIT *(\([a-zA-Z0-9_]*\)).*/  grub_\1_init (0);/'
   fi
 done < ${lst}
 
index 43dbeacf5c922884d4e6cc0fabab18ee3c6bf7fa..e4abd56d50303efb975eb604ba5b8b3079858053 100644 (file)
--- a/genmk.rb
+++ b/genmk.rb
@@ -115,7 +115,7 @@ UNDSYMFILES += #{undsym}
 #{@name}: #{pre_obj} #{mod_obj}
        -rm -f $@
        $(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^
-       $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
+       $(STRIP) $(STRIP_FLAGS) $@
 
 #{pre_obj}: $(#{prefix}_DEPENDENCIES) #{objs_str}
        -rm -f $@
index b630c6fcd83e4c90ece5a048e521261f72dcddfd..017846d797d065ce9dd1220ab9044e65349304a9 100644 (file)
 
 #define GRUB_MOD_INIT(name)    \
 static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \
-void grub_##name##_init (void); \
+void grub_module_##name##_init (grub_dl_t); \
 void \
-grub_##name##_init (void) { grub_mod_init (0); } \
+grub_module_##name##_init (grub_dl_t mod) { grub_mod_init (mod); } \
 static void \
 grub_mod_init (grub_dl_t mod __attribute__ ((unused)))
 
 #define GRUB_MOD_FINI(name)    \
 static void grub_mod_fini (void) __attribute__ ((used)); \
-void grub_##name##_fini (void); \
+void grub_module_##name##_fini (void); \
 void \
-grub_##name##_fini (void) { grub_mod_fini (); } \
+grub_module_##name##_fini (void) { grub_mod_fini (); } \
 static void \
 grub_mod_fini (void)
 
 #define GRUB_MOD_NAME(name)    \
-__asm__ (".section .modname,\"S\"\n.string \"" #name "\"\n.previous")
+static const char grub_module_name_##name[] \
+  __attribute__((section(".modname"), __used__)) = #name
 
 #define GRUB_MOD_DEP(name)     \
-__asm__ (".section .moddeps,\"S\"\n.string \"" #name "\"\n.previous")
+static const char grub_module_depend_##name[] \
+  __attribute__((section(".moddeps"), __used__)) = #name
 
 struct grub_dl_segment
 {
index fbc6be9852997d39ecf7a00bc8de21b0be622e5e..c45cbed02edb7818d1cba3465de4a86dfb38a15c 100644 (file)
@@ -42,6 +42,13 @@ EXPORT_FUNC(grub_efi_allocate_pages) (grub_efi_physical_address_t address,
                                      grub_efi_uintn_t pages);
 void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address,
                                       grub_efi_uintn_t pages);
+void *
+EXPORT_FUNC(grub_efi_allocate_boot_pages) (grub_efi_physical_address_t address,
+                                          grub_efi_uintn_t pages);
+void
+EXPORT_FUNC(grub_efi_free_boot_pages) (grub_efi_physical_address_t address,
+                                      grub_efi_uintn_t pages);
+
 int
 EXPORT_FUNC(grub_efi_get_memory_map) (grub_efi_uintn_t *memory_map_size,
                                      grub_efi_memory_descriptor_t *memory_map,
diff --git a/include/grub/ia64/efi/kernel.h b/include/grub/ia64/efi/kernel.h
new file mode 100644 (file)
index 0000000..c0549f4
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2007  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MACHINE_KERNEL_HEADER
+#define GRUB_MACHINE_KERNEL_HEADER   1
+
+/* The prefix which points to the directory where GRUB modules and its
+   configuration file are located.  */
+extern char grub_prefix[];
+
+/* The offset of GRUB_PREFIX.  */
+#define GRUB_KERNEL_MACHINE_PREFIX             0x8
+
+/* End of the data section. */
+#define GRUB_KERNEL_MACHINE_DATA_END           0x50
+
+#endif /* ! GRUB_MACHINE_KERNEL_HEADER */
+
diff --git a/include/grub/ia64/efi/loader.h b/include/grub/ia64/efi/loader.h
new file mode 100644 (file)
index 0000000..623ae5c
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_LOADER_MACHINE_HEADER
+#define GRUB_LOADER_MACHINE_HEADER     1
+
+/* It is necessary to export these functions, because normal mode commands
+   reuse rescue mode commands.  */
+void grub_rescue_cmd_linux (int argc, char *argv[]);
+void grub_rescue_cmd_initrd (int argc, char *argv[]);
+void grub_rescue_cmd_module (int argc, char *argv[]);
+void grub_rescue_cmd_relocate (int argc, char *argv[]);
+void grub_rescue_cmd_fpswa (int argc, char *argv[]);
+
+#endif /* ! GRUB_LOADER_MACHINE_HEADER */
diff --git a/include/grub/ia64/efi/misc.h b/include/grub/ia64/efi/misc.h
new file mode 100644 (file)
index 0000000..2037f7c
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+void EXPORT_FUNC (memset) (void);
+void EXPORT_FUNC (__ia64_trampoline) (void);
+void EXPORT_FUNC (grub_init_modules) (void);
+
+extern unsigned long EXPORT_VAR (__gp);
+
diff --git a/include/grub/ia64/efi/time.h b/include/grub/ia64/efi/time.h
new file mode 100644 (file)
index 0000000..897ce9c
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GRUB_MACHINE_TIME_HEADER
+#define GRUB_MACHINE_TIME_HEADER       1
+
+#include <grub/efi/time.h>
+
+#endif /* ! GRUB_MACHINE_TIME_HEADER */
diff --git a/include/grub/ia64/setjmp.h b/include/grub/ia64/setjmp.h
new file mode 100644 (file)
index 0000000..c3b2d3b
--- /dev/null
@@ -0,0 +1,31 @@
+/* Define the machine-dependent type `jmp_buf'.  Linux/IA-64 version.
+   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+   Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* User code must not depend on the internal representation of jmp_buf. */
+
+#define _JBLEN 70
+
+/* the __jmp_buf element type should be __float80 per ABI... */
+typedef long grub_jmp_buf[_JBLEN] __attribute__ ((aligned (16))); /* guarantees 128-bit alignment! */
+
+#define grub_setjmp setjmp
+#define grub_longjmp longjmp
+
+int grub_setjmp (grub_jmp_buf env);
+void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn));
diff --git a/include/grub/ia64/time.h b/include/grub/ia64/time.h
new file mode 100644 (file)
index 0000000..5db7ff4
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERNEL_CPU_TIME_HEADER
+#define KERNEL_CPU_TIME_HEADER 1
+
+static __inline void
+grub_cpu_idle (void)
+{
+  /* FIXME: not implemented */
+}
+
+#endif /* ! KERNEL_CPU_TIME_HEADER */
diff --git a/include/grub/ia64/types.h b/include/grub/ia64/types.h
new file mode 100644 (file)
index 0000000..91a546d
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_TYPES_CPU_HEADER
+#define GRUB_TYPES_CPU_HEADER  1
+
+/* The size of void *.  */
+#define GRUB_TARGET_SIZEOF_VOID_P      8
+
+/* The size of long.  */
+#define GRUB_TARGET_SIZEOF_LONG                8
+
+/* ia64 is little-endian (usually).  */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
index 4a4e2cc41c79b582a45a38e765c4a84f4f4e8578..b1b8f593026380afa2688e0cc60edc7be5bd6afa 100644 (file)
@@ -53,7 +53,7 @@ void grub_main (void);
 void grub_machine_init (void);
 
 /* The machine-specific finalization.  */
-void grub_machine_fini (void);
+void EXPORT_FUNC (grub_machine_fini) (void);
 
 /* The machine-specific prefix initialization.  */
 void grub_machine_set_prefix (void);
index 9e8c24abae0272221d6cd89b8d977271e3f29683..c6c6f00ec2a25f7601e0b37158a1b3e6b8097ff2 100644 (file)
--- a/kern/dl.c
+++ b/kern/dl.c
@@ -579,6 +579,29 @@ grub_dl_load_core (void *addr, grub_size_t size)
   return mod;
 }
 
+void
+grub_init_module (const char *name,
+                 void (*init)(grub_dl_t), void (*fini)(void))
+{
+  grub_dl_t mod;
+
+  mod = (grub_dl_t) grub_malloc (sizeof (*mod));
+  if (! mod)
+    return;
+
+  mod->name = name;
+  mod->ref_count = 1;
+  mod->dep = 0;
+  mod->segment = 0;
+  mod->init = init;
+  mod->fini = fini;
+
+  grub_dl_call_init (mod);
+
+  /* Can't fail.  */
+  grub_dl_add (mod);
+}
+
 /* Load a module from the file FILENAME.  */
 grub_dl_t
 grub_dl_load_file (const char *filename)
index 9cd096d7d0222319c94b39818e04a4bac8895df3..6e55e36550a4e0f2c2f161a69511b5302934c60f 100644 (file)
 #include <grub/efi/api.h>
 #include <grub/efi/efi.h>
 
+//#define DEBUG_MM
+
 #define NEXT_MEMORY_DESCRIPTOR(desc, size)     \
   ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
 
-#define BYTES_TO_PAGES(bytes)  ((bytes) >> 12)
+#define BYTES_TO_PAGES(bytes)  ((bytes + 0xfff) >> 12)
 #define PAGES_TO_BYTES(pages)  ((pages) << 12)
 
-/* The size of a memory map obtained from the firmware. This must be
-   a multiplier of 4KB.  */
-#define MEMORY_MAP_SIZE        0x1000
-
 /* Maintain the list of allocated pages.  */
 struct allocated_page
 {
@@ -49,11 +47,10 @@ static struct allocated_page *allocated_pages = 0;
 #define MIN_HEAP_SIZE  0x100000
 #define MAX_HEAP_SIZE  (16 * 0x100000)
 
-
 /* Allocate pages. Return the pointer to the first of allocated pages.  */
 void *
-grub_efi_allocate_pages (grub_efi_physical_address_t address,
-                        grub_efi_uintn_t pages)
+grub_efi_allocate_boot_pages (grub_efi_physical_address_t address,
+                             grub_efi_uintn_t pages)
 {
   grub_efi_allocate_type_t type;
   grub_efi_status_t status;
@@ -87,14 +84,34 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address,
     {
       /* Uggh, the address 0 was allocated... This is too annoying,
         so reallocate another one.  */
-      address = 0xffffffff;
       status = b->allocate_pages (type, GRUB_EFI_LOADER_DATA, pages, &address);
-      grub_efi_free_pages (0, pages);
+      grub_efi_free_boot_pages (0, pages);
       if (status != GRUB_EFI_SUCCESS)
        return 0;
     }
       
-  if (allocated_pages)
+  return (void *)address;
+}
+
+/* Free pages starting from ADDRESS.  */
+void
+grub_efi_free_boot_pages (grub_efi_physical_address_t address,
+                         grub_efi_uintn_t pages)
+{
+  grub_efi_boot_services_t *b;
+
+  b = grub_efi_system_table->boot_services;
+  b->free_pages (address, pages);
+}
+
+/* Allocate pages. Return the pointer to the first of allocated pages.  */
+void *
+grub_efi_allocate_pages (grub_efi_physical_address_t address,
+                        grub_efi_uintn_t pages)
+{
+  address = grub_efi_allocate_boot_pages (address, pages);
+
+  if (address != 0 && allocated_pages)
     {
       unsigned i;
 
@@ -118,8 +135,6 @@ void
 grub_efi_free_pages (grub_efi_physical_address_t address,
                     grub_efi_uintn_t pages)
 {
-  grub_efi_boot_services_t *b;
-
   if (allocated_pages
       && ((grub_efi_physical_address_t) ((grub_addr_t) allocated_pages)
          != address))
@@ -133,9 +148,8 @@ grub_efi_free_pages (grub_efi_physical_address_t address,
            break;
          }
     }
-  
-  b = grub_efi_system_table->boot_services;
-  b->free_pages (address, pages);
+
+  grub_efi_free_boot_pages (address, pages);
 }
 
 /* Get the memory map as defined in the EFI spec. Return 1 if successful,
@@ -278,7 +292,11 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
                    grub_efi_uint64_t required_pages)
 {
   grub_efi_memory_descriptor_t *desc;
-  
+
+#ifdef DEBUG_MM
+  grub_printf ("mm: required_pages=%lu\n", required_pages);
+#endif
+
   for (desc = memory_map;
        desc < memory_map_end;
        desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
@@ -303,6 +321,10 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
 
       grub_mm_init_region (addr, PAGES_TO_BYTES (pages));
 
+#ifdef DEBUG_MM
+      grub_printf ("mm: add %lu pages from %p\n", pages, addr);
+#endif
+
       required_pages -= pages;
       if (required_pages == 0)
        break;
@@ -344,6 +366,8 @@ grub_efi_mm_init (void)
   grub_efi_uintn_t desc_size;
   grub_efi_uint64_t total_pages;
   grub_efi_uint64_t required_pages;
+  grub_efi_uintn_t memory_map_size;
+  int res;
 
   /* First of all, allocate pages to maintain allocations.  */
   allocated_pages
@@ -352,26 +376,35 @@ grub_efi_mm_init (void)
     grub_fatal ("cannot allocate memory");
 
   grub_memset (allocated_pages, 0, ALLOCATED_PAGES_SIZE);
-  
+
   /* Prepare a memory region to store two memory maps.  */
-  memory_map = grub_efi_allocate_pages (0,
-                                       2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
+  memory_map_size = 0;
+  res = grub_efi_get_memory_map (&memory_map_size, NULL, 0, &desc_size, 0);
+  if (res != 0)
+    grub_fatal ("cannot get memory map size");
+
+  /* Add space for a few more entries as allocating pages can increase
+     memory map size.  */
+  memory_map_size += 4 * desc_size;
+
+  memory_map = grub_efi_allocate_pages
+    (0, 2 * BYTES_TO_PAGES (memory_map_size));
   if (! memory_map)
     grub_fatal ("cannot allocate memory");
 
-  filtered_memory_map = NEXT_MEMORY_DESCRIPTOR (memory_map, MEMORY_MAP_SIZE);
+  filtered_memory_map = NEXT_MEMORY_DESCRIPTOR (memory_map, memory_map_size);
 
   /* Obtain descriptors for available memory.  */
-  map_size = MEMORY_MAP_SIZE;
+  map_size = memory_map_size;
 
-  if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) < 0)
+  if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) <= 0)
     grub_fatal ("cannot get memory map");
 
   memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size);
   
   filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map,
                                               desc_size, memory_map_end);
-  
+
   /* By default, request a quarter of the available memory.  */
   total_pages = get_total_pages (filtered_memory_map, desc_size,
                                 filtered_memory_map_end);
@@ -391,7 +424,7 @@ grub_efi_mm_init (void)
 
 #if 0
   /* For debug.  */
-  map_size = MEMORY_MAP_SIZE;
+  map_size = memory_map_size;
 
   if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) < 0)
     grub_fatal ("cannot get memory map");
@@ -404,7 +437,7 @@ grub_efi_mm_init (void)
   
   /* Release the memory maps.  */
   grub_efi_free_pages ((grub_addr_t) memory_map,
-                      2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
+                      2 * BYTES_TO_PAGES (memory_map_size));
 }
 
 void
@@ -420,10 +453,13 @@ grub_efi_mm_fini (void)
 
          p = allocated_pages + i;
          if (p->addr != 0)
-           grub_efi_free_pages ((grub_addr_t) p->addr, p->num_pages);
+           {
+             grub_efi_free_pages ((grub_addr_t) p->addr, p->num_pages);
+           }
        }
 
       grub_efi_free_pages ((grub_addr_t) allocated_pages,
                           BYTES_TO_PAGES (ALLOCATED_PAGES_SIZE));
+      allocated_pages = 0;
     }
 }
diff --git a/kern/ia64/efi/elf_ia64_efi.lds b/kern/ia64/efi/elf_ia64_efi.lds
new file mode 100644 (file)
index 0000000..b6889d4
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+OUTPUT_FORMAT("elf64-ia64-little")
+OUTPUT_ARCH(ia64)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x240;
+ .text :
+ {
+  *(.text)
+  *(.text.*)
+  *(.rodata)
+  *(.rodata.*)
+ /* Reserve space for the entry point descriptor.  */
+  . = ALIGN(16);
+  QUAD(0)
+  QUAD(0)
+ }
+ . = ALIGN(0x20);
+ .got :
+ {
+  *(.got.plt)
+  *(.got)
+  . = ALIGN(0x10);
+ }
+ .opd :
+ {
+   *(.opd)
+ }
+ .sdata :
+ {
+  *(.srodata)
+  *(.sdata)
+  *(.sbss)
+  *(.scommon)
+  . = ALIGN(0x10);
+ }
+ .data :
+ {
+  *(.data*)
+  *(.dynbss)
+  *(.bss)
+  *(COMMON)
+  . = ALIGN(0x10);
+ }
+ .dynamic : { *(.dynamic) }
+
+ . = ALIGN(4096);
+ .interp : { *(.interp) }
+ .plt : { *(.plt) }
+ .rela :
+ {
+  *(.rela.text*)
+  *(.rela.data*)
+  *(.rela.sdata)
+  *(.rela.got)
+ }
+ .hash : { *(.hash) } 
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ /DISCARD/ :
+ {
+  *(.IA_64.unwind*)
+  *(.IA64.unwind*)
+  *(.moddeps)
+  *(.modname)
+ }
+}
diff --git a/kern/ia64/efi/init.c b/kern/ia64/efi/init.c
new file mode 100644 (file)
index 0000000..c85ef6c
--- /dev/null
@@ -0,0 +1,59 @@
+/* init.c - initialize an ia64-based EFI system */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/cache.h>
+#include <grub/kernel.h>
+#include <grub/efi/efi.h>
+
+void
+grub_machine_init (void)
+{
+  grub_efi_init ();
+  grub_init_modules ();
+}
+
+void
+grub_machine_fini (void)
+{
+  grub_efi_fini ();
+}
+
+void
+grub_machine_set_prefix (void)
+{
+  grub_efi_set_prefix ();
+}
+
+void
+grub_arch_sync_caches (void *address, grub_size_t len)
+{
+  /* Cache line length is at least 32.  */
+  grub_uint64_t a = (grub_uint64_t)address & ~0x1f;
+
+  /* Flush data.  */
+  for (len = (len + 31) & ~0x1f; len > 0; len -= 0x20, a += 0x20)
+    asm volatile ("fc.i %0" : : "r" (a));
+  /* Sync and serialize.  Maybe extra.  */
+  asm volatile (";; sync.i;; srlz.i;;");
+}
diff --git a/kern/ia64/efi/startup.S b/kern/ia64/efi/startup.S
new file mode 100644 (file)
index 0000000..9ba6858
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+       .text
+       .psr abi64
+       .psr lsb
+       .lsb
+
+       .global _start
+       .proc _start
+_start:
+       alloc loc0=ar.pfs,2,4,0,0
+       mov loc1=rp
+       addl loc2=@gprel(grub_efi_image_handle),gp
+       addl loc3=@gprel(grub_efi_system_table),gp
+       ;;
+       st8 [loc2]=in0
+       st8 [loc3]=in1
+       br.call.sptk.few rp=grub_main
+       ;;
+       mov ar.pfs=loc0
+       mov rp=loc1
+       ;;
+       br.ret.sptk.few rp
+
+       .endp _start
diff --git a/kern/ia64/trampoline.S b/kern/ia64/trampoline.S
new file mode 100644 (file)
index 0000000..376b7ba
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+       .text
+       .psr abi64
+       .psr lsb
+       .lsb
+       
+       .proc __ia64_trampoline
+       .global __ia64_trampoline
+__ia64_trampoline:
+       // Read address of the real descriptor
+       ld8 r2=[r1],8
+       ;;
+       // Read chain
+       ld8 r15=[r1]
+       // Read pc
+       ld8 r3=[r2],8
+       ;;
+       // Read gp
+       ld8 r1=[r2]
+       mov b6=r3
+       br.many b6
+       .endp __ia64_trampoline
diff --git a/loader/ia64/efi/linux.c b/loader/ia64/efi/linux.c
new file mode 100644 (file)
index 0000000..04c4638
--- /dev/null
@@ -0,0 +1,776 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/machine/loader.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/rescue.h>
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/cache.h>
+/* #include <grub/cpu/linux.h> */
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/elf.h>
+#include <grub/gzio.h>
+
+#define ALIGN_MIN (256*1024*1024)
+
+#define GRUB_ELF_SEARCH 1024
+
+#define BOOT_PARAM_SIZE        16384
+
+struct ia64_boot_param {
+  grub_uint64_t command_line;  /* physical address of command line. */
+  grub_uint64_t efi_systab;    /* physical address of EFI system table */
+  grub_uint64_t efi_memmap;    /* physical address of EFI memory map */
+  grub_uint64_t efi_memmap_size;       /* size of EFI memory map */
+  grub_uint64_t efi_memdesc_size; /* size of an EFI memory map descriptor */
+  grub_uint32_t efi_memdesc_version;   /* memory descriptor version */
+  struct {
+    grub_uint16_t num_cols;    /* number of columns on console output dev */
+    grub_uint16_t num_rows;    /* number of rows on console output device */
+    grub_uint16_t orig_x;      /* cursor's x position */
+    grub_uint16_t orig_y;      /* cursor's y position */
+  } console_info;
+  grub_uint64_t fpswa;         /* physical address of the fpswa interface */
+  grub_uint64_t initrd_start;
+  grub_uint64_t initrd_size;
+  grub_uint64_t domain_start;   /* boot domain address.  */
+  grub_uint64_t domain_size;    /* how big is the boot domain */
+  grub_uint64_t modules_chain;
+  grub_uint64_t modules_nbr;
+};
+
+struct ia64_boot_module {
+  grub_uint64_t mod_start;
+  grub_uint64_t mod_end;
+  
+  /* Module command line */
+  grub_uint64_t cmdline;
+  
+  grub_uint64_t next;
+};
+
+typedef struct {
+  grub_uint32_t        revision;
+  grub_uint32_t        reserved;
+  void *fpswa;
+} fpswa_interface_t;
+static fpswa_interface_t *fpswa;
+
+#define NEXT_MEMORY_DESCRIPTOR(desc, size)      \
+  ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
+
+static grub_dl_t my_mod;
+
+static int loaded;
+
+/* Kernel base and size.  */
+static void *kernel_mem;
+static grub_efi_uintn_t kernel_pages;
+static grub_uint64_t entry;
+
+/* Initrd base and size.  */
+static void *initrd_mem;
+static grub_efi_uintn_t initrd_pages;
+static grub_efi_uintn_t initrd_size;
+
+static struct ia64_boot_param *boot_param;
+static grub_efi_uintn_t boot_param_pages;
+static struct ia64_boot_module *last_module = NULL;
+
+/* Can linux kernel be relocated ?  */
+#define RELOCATE_OFF   0       /* No.  */
+#define RELOCATE_ON    1       /* Yes.  */
+#define RELOCATE_FORCE 2       /* Always - used to debug.  */
+static int relocate = RELOCATE_OFF;
+
+static inline grub_size_t
+page_align (grub_size_t size)
+{
+  return (size + (1 << 12) - 1) & (~((1 << 12) - 1));
+}
+
+static void
+query_fpswa (void)
+{
+  grub_efi_handle_t fpswa_image;
+  grub_efi_boot_services_t *bs;
+  grub_efi_status_t status;
+  grub_efi_uintn_t size;
+  static const grub_efi_guid_t fpswa_protocol = 
+    { 0xc41b6531, 0x97b9, 0x11d3,
+      {0x9a, 0x29, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} };
+
+  if (fpswa != NULL)
+    return;
+
+  size = sizeof(grub_efi_handle_t);
+  
+  bs = grub_efi_system_table->boot_services;
+  status = bs->locate_handle (GRUB_EFI_BY_PROTOCOL,
+                             &fpswa_protocol,
+                             NULL, &size, &fpswa_image);
+  if (status != GRUB_EFI_SUCCESS)
+    {
+      grub_printf("Could not locate FPSWA driver\n");
+      return;
+    }
+  status = bs->handle_protocol (fpswa_image, &fpswa_protocol, &fpswa);
+  if (status != GRUB_EFI_SUCCESS)
+    {
+      grub_printf ("Fpswa protocol not able find the interface\n");
+      return;
+    } 
+}
+
+/* Find the optimal number of pages for the memory map. Is it better to
+   move this code to efi/mm.c?  */
+static grub_efi_uintn_t
+find_mmap_size (void)
+{
+  static grub_efi_uintn_t mmap_size = 0;
+
+  if (mmap_size != 0)
+    return mmap_size;
+  
+  mmap_size = (1 << 12);
+  while (1)
+    {
+      int ret;
+      grub_efi_memory_descriptor_t *mmap;
+      grub_efi_uintn_t desc_size;
+      
+      mmap = grub_malloc (mmap_size);
+      if (! mmap)
+       return 0;
+
+      ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0);
+      grub_free (mmap);
+      
+      if (ret < 0)
+       grub_fatal ("cannot get memory map");
+      else if (ret > 0)
+       break;
+
+      mmap_size += (1 << 12);
+    }
+
+  /* Increase the size a bit for safety, because GRUB allocates more on
+     later, and EFI itself may allocate more.  */
+  mmap_size += (1 << 12);
+
+  return page_align (mmap_size);
+}
+
+static void
+free_pages (void)
+{
+  if (kernel_mem)
+    {
+      grub_efi_free_boot_pages ((grub_addr_t) kernel_mem, kernel_pages);
+      kernel_mem = 0;
+    }
+
+  if (initrd_mem)
+    {
+      grub_efi_free_boot_pages ((grub_addr_t) initrd_mem, initrd_pages);
+      initrd_mem = 0;
+    }
+
+  if (boot_param)
+    {
+      struct ia64_boot_module *mod;
+      struct ia64_boot_module *next_mod;
+
+      /* Free modules.  */
+      mod = (struct ia64_boot_module *)boot_param->modules_chain;
+      while (mod != 0)
+       {
+         next_mod = (struct ia64_boot_module *)mod->next;
+
+         grub_efi_free_boot_pages
+           (mod->mod_start, page_align (mod->mod_end - mod->mod_start) >> 12);
+         grub_efi_free_boot_pages ((grub_efi_physical_address_t)mod, 1);
+
+         mod = next_mod;
+       }
+
+      /* Free bootparam.  */
+      grub_efi_free_boot_pages ((grub_efi_physical_address_t)boot_param,
+                               boot_param_pages);
+      boot_param = 0;
+    }
+}
+
+static void *
+allocate_pages (grub_uint64_t align, grub_uint64_t size_pages,
+               grub_uint64_t nobase)
+{
+  grub_uint64_t size;
+  grub_efi_uintn_t desc_size;
+  grub_efi_memory_descriptor_t *mmap, *mmap_end;
+  grub_efi_uintn_t mmap_size, tmp_mmap_size;
+  grub_efi_memory_descriptor_t *desc;
+  void *mem = NULL;
+
+  size = size_pages << 12;
+
+  mmap_size = find_mmap_size ();
+
+    /* Read the memory map temporarily, to find free space.  */
+  mmap = grub_malloc (mmap_size);
+  if (! mmap)
+    return 0;
+
+  tmp_mmap_size = mmap_size;
+  if (grub_efi_get_memory_map (&tmp_mmap_size, mmap, 0, &desc_size, 0) <= 0)
+    grub_fatal ("cannot get memory map");
+
+  mmap_end = NEXT_MEMORY_DESCRIPTOR (mmap, tmp_mmap_size);
+  
+  /* First, find free pages for the real mode code
+     and the memory map buffer.  */
+  for (desc = mmap;
+       desc < mmap_end;
+       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+    {
+      grub_uint64_t start, end;
+      grub_uint64_t aligned_start;
+
+      if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY)
+       continue;
+
+      start = desc->physical_start;
+      end = start + (desc->num_pages << 12);
+      /* Align is a power of 2.  */
+      aligned_start = (start + align - 1) & ~(align - 1);
+      if (aligned_start + size > end)
+       continue;
+      if (aligned_start == nobase)
+       aligned_start += align;
+      if (aligned_start + size > end)
+       continue;
+      mem = grub_efi_allocate_pages (aligned_start, size_pages);
+      if (! mem)
+       grub_fatal ("cannot allocate pages");
+      break;
+    }
+
+  if (! mem)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory");
+      goto fail;
+    }
+
+  grub_free (mmap);
+  return mem;
+
+ fail:
+  grub_free (mmap);
+  free_pages ();
+  return 0;
+}
+
+static void
+set_boot_param_console (void)
+{
+  grub_efi_simple_text_output_interface_t *conout;
+  grub_efi_uintn_t cols, rows;
+  
+  conout = grub_efi_system_table->con_out;
+  if (conout->query_mode (conout, conout->mode->mode, &cols, &rows)
+      != GRUB_EFI_SUCCESS)
+    return;
+
+  grub_dprintf("linux",
+              "Console info: cols=%lu rows=%lu x=%u y=%u\n",
+              cols, rows,
+              conout->mode->cursor_column, conout->mode->cursor_row);
+  
+  boot_param->console_info.num_cols = cols;
+  boot_param->console_info.num_rows = rows;
+  boot_param->console_info.orig_x = conout->mode->cursor_column;
+  boot_param->console_info.orig_y = conout->mode->cursor_row;
+}
+
+static grub_err_t
+grub_linux_boot (void)
+{
+  grub_efi_uintn_t mmap_size;
+  grub_efi_uintn_t map_key;
+  grub_efi_uintn_t desc_size;
+  grub_efi_uint32_t desc_version;
+  grub_efi_memory_descriptor_t *mmap_buf;
+
+  /* FPSWA.  */
+  query_fpswa ();
+  boot_param->fpswa = (grub_uint64_t)fpswa;
+
+  /* Initrd.  */
+  boot_param->initrd_start = (grub_uint64_t)initrd_mem;
+  boot_param->initrd_size = (grub_uint64_t)initrd_size;
+
+  set_boot_param_console ();
+
+  grub_printf ("Jump to %016lx\n", entry);
+
+  grub_machine_fini ();
+
+  /* MDT.
+     Must be done after grub_machine_fini because map_key is used by
+     exit_boot_services.  */
+  mmap_size = find_mmap_size ();
+  mmap_buf = grub_efi_allocate_boot_pages (0, page_align (mmap_size) >> 12);
+  if (! mmap_buf)
+    grub_fatal ("cannot allocate memory map");
+  if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
+                              &desc_size, &desc_version) <= 0)
+    grub_fatal ("cannot get memory map");
+
+  boot_param->efi_memmap = (grub_uint64_t)mmap_buf;
+  boot_param->efi_memmap_size = mmap_size;
+  boot_param->efi_memdesc_size = desc_size;
+  boot_param->efi_memdesc_version = desc_version;
+
+  if (! grub_efi_exit_boot_services (map_key))
+    grub_fatal ("cannot exit boot services");
+
+  /* See you next boot.  */
+  asm volatile ("mov r28=%1; br.sptk.few %0" :: "b"(entry),"r"(boot_param));
+  
+  /* Never reach here.  */
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_linux_unload (void)
+{
+  free_pages ();
+  grub_dl_unref (my_mod);
+  loaded = 0;
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_load_elf64 (grub_file_t file, void *buffer)
+{
+  Elf64_Ehdr *ehdr = (Elf64_Ehdr *) buffer;
+  Elf64_Phdr *phdr;
+  int i;
+  grub_uint64_t low_addr;
+  grub_uint64_t high_addr;
+  grub_uint64_t align;
+  grub_uint64_t reloc_offset;
+
+  if (ehdr->e_ident[EI_CLASS] != ELFCLASS64)
+    return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class");
+
+  if (ehdr->e_ident[EI_MAG0] != ELFMAG0
+      || ehdr->e_ident[EI_MAG1] != ELFMAG1
+      || ehdr->e_ident[EI_MAG2] != ELFMAG2
+      || ehdr->e_ident[EI_MAG3] != ELFMAG3
+      || ehdr->e_version != EV_CURRENT
+      || ehdr->e_ident[EI_DATA] != ELFDATA2LSB
+      || ehdr->e_machine != EM_IA_64)
+    return grub_error(GRUB_ERR_UNKNOWN_OS, "no valid ELF header found");
+
+  if (ehdr->e_type != ET_EXEC)
+    return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type");
+
+  /* FIXME: Should we support program headers at strange locations?  */
+  if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > GRUB_ELF_SEARCH)
+    return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
+
+  entry = ehdr->e_entry;
+
+  /* Compute low, high and align addresses.  */
+  low_addr = ~0UL;
+  high_addr = 0;
+  align = 0;
+  for (i = 0; i < ehdr->e_phnum; i++)
+    {
+      phdr = (Elf64_Phdr *) ((char *) buffer + ehdr->e_phoff
+                            + i * ehdr->e_phentsize);
+      if (phdr->p_type == PT_LOAD)
+       {
+         if (phdr->p_paddr < low_addr)
+           low_addr = phdr->p_paddr;
+         if (phdr->p_paddr + phdr->p_memsz > high_addr)
+           high_addr = phdr->p_paddr + phdr->p_memsz;
+         if (phdr->p_align > align)
+           align = phdr->p_align;
+       }
+    }
+
+  if (align < ALIGN_MIN)
+    align = ALIGN_MIN;
+
+  if (high_addr == 0)
+    return grub_error (GRUB_ERR_BAD_OS, "no program entries");
+
+  kernel_pages = page_align (high_addr - low_addr) >> 12;
+
+  if (relocate != RELOCATE_FORCE)
+    {
+      kernel_mem = grub_efi_allocate_boot_pages (low_addr, kernel_pages);
+      reloc_offset = 0;
+    }
+  /* Try to relocate.  */
+  if (! kernel_mem && relocate != RELOCATE_OFF)
+    {
+      kernel_mem = allocate_pages (align, kernel_pages, low_addr);
+      if (kernel_mem)
+       {
+         reloc_offset = kernel_mem - low_addr;
+         grub_printf ("  Relocated at %p (offset=%016llx)\n",
+                      kernel_mem, reloc_offset);
+         entry += reloc_offset;
+       }
+    }
+  if (! kernel_mem)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+                      "cannot allocate memory for OS");
+
+  /* Load every loadable segment in memory.  */
+  for (i = 0; i < ehdr->e_phnum; i++)
+    {
+      phdr = (Elf64_Phdr *) ((char *) buffer + ehdr->e_phoff
+                            + i * ehdr->e_phentsize);
+      if (phdr->p_type == PT_LOAD)
+        {
+         grub_printf ("  [paddr=%llx load=%llx memsz=%08llx "
+                      "off=%lx flags=%x]\n",
+                      phdr->p_paddr, phdr->p_paddr + reloc_offset,
+                      phdr->p_memsz, phdr->p_offset, phdr->p_flags);
+
+         if (grub_file_seek (file, phdr->p_offset) == -1)
+           return grub_error (GRUB_ERR_BAD_OS,
+                              "invalid offset in program header");
+
+         if (grub_file_read (file, (void *)(phdr->p_paddr + reloc_offset),
+                             phdr->p_filesz)
+              != (grub_ssize_t) phdr->p_filesz)
+           return grub_error (GRUB_ERR_BAD_OS,
+                              "couldn't read segment from file");
+         
+          if (phdr->p_filesz < phdr->p_memsz)
+           grub_memset
+             ((char *)(phdr->p_paddr + reloc_offset + phdr->p_filesz),
+              0, phdr->p_memsz - phdr->p_filesz);
+
+         /* Sync caches if necessary.  */
+         if (phdr->p_flags & PF_X)
+           grub_arch_sync_caches
+             ((void *)(phdr->p_paddr + reloc_offset), phdr->p_memsz);
+        }
+    }
+  loaded = 1;
+  return 0;
+}
+
+void
+grub_rescue_cmd_linux (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  char buffer[GRUB_ELF_SEARCH];
+  char *cmdline, *p;
+  grub_ssize_t len;
+  int i;
+
+  grub_dl_ref (my_mod);
+
+  grub_loader_unset ();
+    
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "No kernel specified");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if (! file)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "Couldn't open file");
+      goto fail;
+    }
+
+  len = grub_file_read (file, buffer, sizeof (buffer));
+  if (len < (grub_ssize_t)sizeof (Elf64_Ehdr))
+    {
+      grub_error (GRUB_ERR_BAD_OS, "File too small");
+      goto fail;
+    }
+
+  grub_printf ("Loading linux: %s\n", argv[0]);
+
+  if (grub_load_elf64 (file, buffer))
+    goto fail;
+
+  len = sizeof("BOOT_IMAGE=") + 8;
+  for (i = 0; i < argc; i++)
+    len += grub_strlen (argv[i]) + 1;
+  len += sizeof (struct ia64_boot_param) + 256; /* Room for extensions.  */
+  boot_param_pages = page_align (len) >> 12;
+  boot_param = grub_efi_allocate_boot_pages (0, boot_param_pages);
+  if (boot_param == 0)
+    {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY,
+                 "cannot allocate memory for bootparams");
+      goto fail;
+    }
+
+  grub_memset (boot_param, 0, len);
+  cmdline = ((char *)(boot_param + 1)) + 256;
+
+  /* Build cmdline.  */
+  p = grub_stpcpy (cmdline, "BOOT_IMAGE");
+  for (i = 0; i < argc; i++)
+    {
+      *p++ = ' ';
+      p = grub_stpcpy (p, argv[i]);
+    }
+  cmdline[10] = '=';
+  
+  boot_param->command_line = (grub_uint64_t)cmdline;
+  boot_param->efi_systab = (grub_uint64_t)grub_efi_system_table;
+
+  grub_errno = GRUB_ERR_NONE;
+
+  grub_loader_set (grub_linux_boot, grub_linux_unload, 0);
+
+ fail:
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_efi_free_boot_pages ((grub_efi_physical_address_t)boot_param,
+                               boot_param_pages);
+      grub_dl_unref (my_mod);
+    }
+}
+
+void
+grub_rescue_cmd_initrd (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified");
+      goto fail;
+    }
+  
+  if (! loaded)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "You need to load the kernel first.");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if (! file)
+    goto fail;
+
+  grub_printf ("Loading initrd: %s\n",argv[0]);
+
+  initrd_size = grub_file_size (file);
+  initrd_pages = (page_align (initrd_size) >> 12);
+  initrd_mem = grub_efi_allocate_boot_pages (0, initrd_pages);
+  if (! initrd_mem)
+    grub_fatal ("cannot allocate pages");
+  
+  grub_printf ("  [addr=0x%lx, size=0x%lx]\n",
+              (grub_uint64_t)initrd_mem, initrd_size);
+
+  if (grub_file_read (file, initrd_mem, initrd_size) 
+      != (grub_ssize_t)initrd_size)
+    {
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+ fail:
+  if (file)
+    grub_file_close (file);
+}
+
+void
+grub_rescue_cmd_module  (int argc, char *argv[])
+{
+  grub_file_t file = 0;
+  grub_ssize_t size, len = 0;
+  char *module = 0, *cmdline = 0, *p;
+  struct ia64_boot_module *mod = NULL;
+  int i;
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified");
+      goto fail;
+    }
+
+  if (!boot_param)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, 
+                 "You need to load the multiboot kernel first");
+      goto fail;
+    }
+
+  file = grub_gzfile_open (argv[0], 1);
+  if (! file)
+    goto fail;
+
+  size = grub_file_size (file);
+  module = grub_efi_allocate_boot_pages (0, page_align (size) >> 12);
+  if (! module)
+    goto fail;
+
+  grub_printf ("Module %s [addr=%llx + %lx]\n",
+              argv[0], (grub_uint64_t)module, size);
+
+  if (grub_file_read (file, module, size) != size)
+    {
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+
+  len = sizeof (struct ia64_boot_module);  
+  for (i = 0; i < argc; i++)
+    len += grub_strlen (argv[i]) + 1;
+
+  if (len > 4096)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "module command line too long");
+      goto fail;
+    }
+  mod = grub_efi_allocate_boot_pages (0, 1);
+  if (! mod)
+    goto fail;
+
+  p = (char *)(mod + 1);
+
+  mod->mod_start = (grub_uint64_t)module;
+  mod->mod_end = (grub_uint64_t)module + size;
+  mod->cmdline = (grub_uint64_t)p;
+  mod->next = 0;
+
+  if (last_module)
+    last_module->next = (grub_uint64_t)mod;
+  else
+    {
+      last_module = mod;
+      boot_param->modules_chain = (grub_uint64_t)mod;
+    }
+  boot_param->modules_nbr++;
+
+  /* Copy command line.  */
+  for (i = 0; i < argc; i++)
+    {
+      p = grub_stpcpy (p, argv[i]);
+      *(p++) = ' ';
+    }
+  
+  /* Remove the space after the last word.  */
+  *(--p) = '\0';
+
+
+ fail:
+  if (file)
+    grub_file_close (file);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      grub_free (module);
+      grub_free (cmdline);
+    }
+}
+
+void
+grub_rescue_cmd_relocate  (int argc, char *argv[])
+{
+  static const char * const vals[] = { "off", "on", "force"};
+  unsigned int i;
+
+  if (argc == 0)
+    {
+      grub_printf ("relocate is %s\n", vals[relocate]);
+    }
+  else if (argc == 1)
+    {
+      if (kernel_mem != NULL)
+       grub_printf ("Warning: kernel already loaded!\n");
+      for (i = 0; i < sizeof (vals)/sizeof(vals[0]); i++)
+       if (grub_strcmp (argv[0], vals[i]) == 0)
+         {
+           relocate = i;
+           return;
+         }
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown relocate value");
+    }
+  else
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "accept 0 or 1 argument");
+    }
+}
+
+
+void
+grub_rescue_cmd_fpswa  (int argc, char *argv[] __attribute__((unused)))
+{
+  if (argc != 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "Arguments not expected");
+      return;
+    }
+  query_fpswa ();
+  if (fpswa == NULL)
+    grub_printf ("No FPSWA loaded\n");
+  else
+    grub_printf ("FPSWA revision: %x\n", fpswa->revision);
+}
+
+GRUB_MOD_INIT(linux)
+{
+  grub_rescue_register_command ("linux",
+                               grub_rescue_cmd_linux,
+                               "load linux");
+  grub_rescue_register_command ("initrd",
+                               grub_rescue_cmd_initrd,
+                               "load initrd");
+  grub_rescue_register_command ("module", grub_rescue_cmd_module,
+                               "load a multiboot module");
+  grub_rescue_register_command ("relocate", grub_rescue_cmd_relocate,
+                               "set relocate feature");
+  grub_rescue_register_command ("fpswa", grub_rescue_cmd_fpswa,
+                               "load fpswa");
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI(linux)
+{
+  grub_rescue_unregister_command ("linux");
+  grub_rescue_unregister_command ("initrd");
+  grub_rescue_unregister_command ("module");
+  grub_rescue_unregister_command ("relocate");
+  grub_rescue_unregister_command ("fpswa");
+}
diff --git a/loader/ia64/efi/linux_normal.c b/loader/ia64/efi/linux_normal.c
new file mode 100644 (file)
index 0000000..3a567b0
--- /dev/null
@@ -0,0 +1,107 @@
+/* linux_normal.c - boot linux */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/machine/loader.h>
+#include <grub/err.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+
+static grub_err_t
+grub_normal_linux_command (struct grub_arg_list *state __attribute__ ((unused)),
+                          int argc, char **args)
+{
+  grub_rescue_cmd_linux (argc, args);
+  return grub_errno;
+}
+
+
+static grub_err_t
+grub_normal_initrd_command (struct grub_arg_list *state __attribute__ ((unused)),
+                           int argc, char **args)
+{
+  grub_rescue_cmd_initrd (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_cmd_module (struct grub_arg_list *state __attribute__ ((unused)),
+                       int argc, char **args)
+{
+  grub_rescue_cmd_module (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_cmd_relocate (struct grub_arg_list *state __attribute__ ((unused)),
+                       int argc, char **args)
+{
+  grub_rescue_cmd_relocate (argc, args);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_normal_cmd_fpswa (struct grub_arg_list *state __attribute__ ((unused)),
+                       int argc, char **args)
+{
+  grub_rescue_cmd_fpswa (argc, args);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(linux_normal)
+{
+  (void) mod; /* To stop warning.  */
+  grub_register_command
+    ("linux", grub_normal_linux_command,
+     GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE,
+     "linux FILE [ARGS...]",
+     "Load a linux kernel.", 0);
+  
+  grub_register_command
+    ("initrd", grub_normal_initrd_command,
+     GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE,
+     "initrd FILE",
+     "Load an initrd.", 0);
+
+  grub_register_command
+    ("module", grub_normal_cmd_module,
+     GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE,
+     "module FILE [ARGS...]",
+     "Load a Multiboot module.", 0);
+
+  grub_register_command
+    ("relocate", grub_normal_cmd_relocate,
+     GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE,
+     "relocate [on|off|force]",
+     "Set relocate feature.", 0);
+
+  grub_register_command
+    ("fpswa", grub_normal_cmd_fpswa,
+     GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE,
+     "fpswa",
+     "Display FPSWA version.", 0);
+}
+
+GRUB_MOD_FINI(linux_normal)
+{
+  grub_unregister_command ("linux");
+  grub_unregister_command ("initrd");
+  grub_unregister_command ("normal");
+  grub_unregister_command ("relocate");
+  grub_unregister_command ("fpswa");
+}
diff --git a/normal/ia64/longjmp.S b/normal/ia64/longjmp.S
new file mode 100644 (file)
index 0000000..23dec86
--- /dev/null
@@ -0,0 +1,162 @@
+/* Copyright (C) 1999, 2000, 2001, 2002  Free Software Foundation, Inc.
+   Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Note that __sigsetjmp() did NOT flush the register stack.  Instead,
+   we do it here since __longjmp() is usually much less frequently
+   invoked than __sigsetjmp(). The only difficulty is that __sigsetjmp()
+   didn't (and wouldn't be able to) save ar.rnat either.  This is a problem
+   because if we're not careful, we could end up loading random NaT bits.
+   There are two cases:
+
+       (i)  ar.bsp < ia64_rse_rnat_addr(jmpbuf.ar_bsp)
+               ar.rnat contains the desired bits---preserve ar.rnat
+               across loadrs and write to ar.bspstore
+
+       (ii) ar.bsp >= ia64_rse_rnat_addr(jmpbuf.ar_bsp)
+               The desired ar.rnat is stored in
+               ia64_rse_rnat_addr(jmpbuf.ar_bsp).  Load those
+               bits into ar.rnat after setting ar.bspstore. */
+
+
+
+#      define  pPos    p6      /* is rotate count positive? */
+#      define  pNeg    p7      /* is rotate count negative? */
+
+
+       /* __longjmp(__jmp_buf buf, int val) */
+
+       .text 
+       .global longjmp
+       .proc longjmp
+longjmp:
+       alloc r8=ar.pfs,2,1,0,0
+       mov r27=ar.rsc
+       add r2=0x98,in0         // r2 <- &jmpbuf.orig_jmp_buf_addr
+       ;;
+       ld8 r8=[r2],-16         // r8 <- orig_jmp_buf_addr
+       mov r10=ar.bsp
+       and r11=~0x3,r27        // clear ar.rsc.mode
+       ;;
+       flushrs                 // flush dirty regs to backing store (must be first in insn grp)
+       ld8 r23=[r2],8          // r23 <- jmpbuf.ar_bsp
+       sub r8=r8,in0           // r8 <- &orig_jmpbuf - &jmpbuf
+       ;;
+       ld8 r25=[r2]            // r25 <- jmpbuf.ar_unat
+       extr.u r8=r8,3,6        // r8 <- (&orig_jmpbuf - &jmpbuf)/8 & 0x3f
+       ;;
+       cmp.lt pNeg,pPos=r8,r0
+       mov r2=in0
+       ;;
+(pPos) mov r16=r8
+(pNeg) add r16=64,r8
+(pPos) sub r17=64,r8
+(pNeg) sub r17=r0,r8
+       ;;
+       mov ar.rsc=r11          // put RSE in enforced lazy mode
+       shr.u r8=r25,r16
+       add r3=8,in0            // r3 <- &jmpbuf.r1
+       shl r9=r25,r17
+       ;;
+       or r25=r8,r9
+       ;;
+       mov r26=ar.rnat
+       mov ar.unat=r25         // setup ar.unat (NaT bits for r1, r4-r7, and r12)
+       ;;
+       ld8.fill.nta sp=[r2],16 // r12 (sp)
+       ld8.fill.nta gp=[r3],16         // r1 (gp)
+       dep r11=-1,r23,3,6      // r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp)
+       ;;
+       ld8.nta r16=[r2],16             // caller's unat
+       ld8.nta r17=[r3],16             // fpsr
+       ;;
+       ld8.fill.nta r4=[r2],16 // r4
+       ld8.fill.nta r5=[r3],16         // r5 (gp)
+       cmp.geu p8,p0=r10,r11   // p8 <- (ar.bsp >= jmpbuf.ar_bsp)
+       ;;
+       ld8.fill.nta r6=[r2],16 // r6
+       ld8.fill.nta r7=[r3],16         // r7
+       ;;
+       mov ar.unat=r16                 // restore caller's unat
+       mov ar.fpsr=r17                 // restore fpsr
+       ;;
+       ld8.nta r16=[r2],16             // b0
+       ld8.nta r17=[r3],16             // b1
+       ;;
+(p8)   ld8 r26=[r11]           // r26 <- *ia64_rse_rnat_addr(jmpbuf.ar_bsp)
+       mov ar.bspstore=r23     // restore ar.bspstore
+       ;;
+       ld8.nta r18=[r2],16             // b2
+       ld8.nta r19=[r3],16             // b3
+       ;;
+       ld8.nta r20=[r2],16             // b4
+       ld8.nta r21=[r3],16             // b5
+       ;;
+       ld8.nta r11=[r2],16             // ar.pfs
+       ld8.nta r22=[r3],56             // ar.lc
+       ;;
+       ld8.nta r24=[r2],32             // pr
+       mov b0=r16
+       ;;
+       ldf.fill.nta f2=[r2],32
+       ldf.fill.nta f3=[r3],32
+       mov b1=r17
+       ;;
+       ldf.fill.nta f4=[r2],32
+       ldf.fill.nta f5=[r3],32
+       mov b2=r18
+       ;;
+       ldf.fill.nta f16=[r2],32
+       ldf.fill.nta f17=[r3],32
+       mov b3=r19
+       ;;
+       ldf.fill.nta f18=[r2],32
+       ldf.fill.nta f19=[r3],32
+       mov b4=r20
+       ;;
+       ldf.fill.nta f20=[r2],32
+       ldf.fill.nta f21=[r3],32
+       mov b5=r21
+       ;;
+       ldf.fill.nta f22=[r2],32
+       ldf.fill.nta f23=[r3],32
+       mov ar.lc=r22
+       ;;
+       ldf.fill.nta f24=[r2],32
+       ldf.fill.nta f25=[r3],32
+       cmp.eq p8,p9=0,in1
+       ;;
+       ldf.fill.nta f26=[r2],32
+       ldf.fill.nta f27=[r3],32
+       mov ar.pfs=r11
+       ;;
+       ldf.fill.nta f28=[r2],32
+       ldf.fill.nta f29=[r3],32
+       ;;
+       ldf.fill.nta f30=[r2]
+       ldf.fill.nta f31=[r3]
+(p8)   mov r8=1
+
+       mov ar.rnat=r26         // restore ar.rnat
+       ;;
+       mov ar.rsc=r27          // restore ar.rsc
+(p9)   mov r8=in1
+
+       invala                  // virt. -> phys. regnum mapping may change
+       mov pr=r24,-1
+       br.ret.dptk.few rp
+       .endp longjmp
diff --git a/normal/ia64/setjmp.S b/normal/ia64/setjmp.S
new file mode 100644 (file)
index 0000000..4bc2103
--- /dev/null
@@ -0,0 +1,171 @@
+/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Contributed by David Mosberger-Tang <davidm@hpl.hp.com>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   The layout of the jmp_buf is as follows.  This is subject to change
+   and user-code should never depend on the particular layout of
+   jmp_buf!
+
+
+       offset: description:
+       ------- ------------
+       0x000   stack pointer (r12)     ; unchangeable (see _JMPBUF_UNWINDS)
+       0x008   r1 (gp)
+       0x010   caller's unat
+       0x018   fpsr
+       0x020   r4
+       0x028   r5
+       0x030   r6
+       0x038   r7
+       0x040   rp (b0)
+       0x048   b1
+       0x050   b2
+       0x058   b3
+       0x060   b4
+       0x068   b5
+       0x070   ar.pfs
+       0x078   ar.lc
+       0x080   pr
+       0x088   ar.bsp                  ; unchangeable (see __longjmp.S)
+       0x090   ar.unat
+       0x098   &__jmp_buf      ; address of the jmpbuf (needed to locate NaT bits in unat)
+       0x0a0    f2
+       0x0b0    f3
+       0x0c0    f4
+       0x0d0    f5
+       0x0e0   f16
+       0x0f0   f17
+       0x100   f18
+       0x110   f19
+       0x120   f20
+       0x130   f21
+       0x130   f22
+       0x140   f23
+       0x150   f24
+       0x160   f25
+       0x170   f26
+       0x180   f27
+       0x190   f28
+       0x1a0   f29
+       0x1b0   f30
+       0x1c0   f31 */
+
+
+       /* The following two entry points are the traditional entry points: */
+
+       .text
+       .global setjmp
+       .proc setjmp
+setjmp:
+       alloc r8=ar.pfs,2,0,0,0
+       mov in1=1
+       br.cond.sptk.many __sigsetjmp
+       .endp setjmp
+
+       /* __sigsetjmp(__jmp_buf buf, int savemask) */
+
+       .proc __sigsetjmp
+__sigsetjmp:
+       //.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
+       alloc loc1=ar.pfs,2,2,2,0
+       mov r16=ar.unat
+       ;;
+       mov r17=ar.fpsr
+       mov r2=in0
+       add r3=8,in0
+       ;;
+       st8.spill.nta [r2]=sp,16        // r12 (sp)
+       st8.spill.nta [r3]=gp,16        // r1 (gp)
+       ;;
+       st8.nta [r2]=r16,16             // save caller's unat
+       st8.nta [r3]=r17,16             // save fpsr
+       add r8=0xa0,in0
+       ;;
+       st8.spill.nta [r2]=r4,16        // r4
+       st8.spill.nta [r3]=r5,16        // r5
+       add r9=0xb0,in0
+       ;;
+       stf.spill.nta [r8]=f2,32
+       stf.spill.nta [r9]=f3,32
+       mov loc0=rp
+       .body
+       ;;
+       stf.spill.nta [r8]=f4,32
+       stf.spill.nta [r9]=f5,32
+       mov r17=b1
+       ;;
+       stf.spill.nta [r8]=f16,32
+       stf.spill.nta [r9]=f17,32
+       mov r18=b2
+       ;;
+       stf.spill.nta [r8]=f18,32
+       stf.spill.nta [r9]=f19,32
+       mov r19=b3
+       ;;
+       stf.spill.nta [r8]=f20,32
+       stf.spill.nta [r9]=f21,32
+       mov r20=b4
+       ;;
+       stf.spill.nta [r8]=f22,32
+       stf.spill.nta [r9]=f23,32
+       mov r21=b5
+       ;;
+       stf.spill.nta [r8]=f24,32
+       stf.spill.nta [r9]=f25,32
+       mov r22=ar.lc
+       ;;
+       stf.spill.nta [r8]=f26,32
+       stf.spill.nta [r9]=f27,32
+       mov r24=pr
+       ;;
+       stf.spill.nta [r8]=f28,32
+       stf.spill.nta [r9]=f29,32
+       ;;
+       stf.spill.nta [r8]=f30
+       stf.spill.nta [r9]=f31
+
+       st8.spill.nta [r2]=r6,16        // r6
+       st8.spill.nta [r3]=r7,16        // r7
+       ;;
+       mov r23=ar.bsp
+       mov r25=ar.unat
+       mov out0=in0
+
+       st8.nta [r2]=loc0,16            // b0
+       st8.nta [r3]=r17,16             // b1
+       mov out1=in1
+       ;;
+       st8.nta [r2]=r18,16             // b2
+       st8.nta [r3]=r19,16             // b3
+       ;;
+       st8.nta [r2]=r20,16             // b4
+       st8.nta [r3]=r21,16             // b5
+       ;;
+       st8.nta [r2]=loc1,16            // ar.pfs
+       st8.nta [r3]=r22,16             // ar.lc
+       ;;
+       st8.nta [r2]=r24,16             // pr
+       st8.nta [r3]=r23,16             // ar.bsp
+       ;;
+       st8.nta [r2]=r25                // ar.unat
+       st8.nta [r3]=in0                // &__jmp_buf
+       mov r8=0
+       mov rp=loc0
+       mov ar.pfs=loc1
+       br.ret.sptk.many rp
+
+       .endp __sigsetjmp
diff --git a/util/ia64/efi/elf2pe.c b/util/ia64/efi/elf2pe.c
new file mode 100644 (file)
index 0000000..23687fe
--- /dev/null
@@ -0,0 +1,812 @@
+/* elf2pe.c - convert elf binary to PE/Coff.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <elf.h>
+
+#if defined(i386)
+#define USE_ELF32
+#define USE_PE32
+#define ELF_MACHINE EM_386
+#define EFI_MACHINE PE32_MACHINE_I386
+#elif defined(__ia64__)
+#define USE_ELF64
+#define USE_PE32PLUS
+#define ELF_MACHINE EM_IA_64
+#define EFI_MACHINE PE32_MACHINE_IA64
+#else
+#error "unknown architecture"
+#endif
+
+#include "pe32.h"
+
+const char *filename;
+
+int
+is_elf_header(uint8_t *buffer)
+{
+  return (buffer[EI_MAG0] == ELFMAG0
+         && buffer[EI_MAG1] == ELFMAG1
+         && buffer[EI_MAG2] == ELFMAG2
+         && buffer[EI_MAG3] == ELFMAG3);
+}
+
+#ifdef USE_ELF32
+typedef Elf32_Shdr Elf_Shdr;
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Rel Elf_Rel;
+typedef Elf32_Rela Elf_Rela;
+typedef Elf32_Sym Elf_Sym;
+#define ELFCLASS ELFCLASS32
+#define ELF_R_TYPE(r) ELF32_R_TYPE(r)
+#define ELF_R_SYM(r) ELF32_R_SYM(r)
+#else
+typedef Elf64_Shdr Elf_Shdr;
+typedef Elf64_Ehdr Elf_Ehdr;
+typedef Elf64_Rel Elf_Rel;
+typedef Elf64_Rela Elf_Rela;
+typedef Elf64_Sym Elf_Sym;
+#define ELFCLASS ELFCLASS64
+#define ELF_R_TYPE(r) ELF64_R_TYPE(r)
+#define ELF_R_SYM(r) ELF64_R_SYM(r)
+#endif
+
+#ifdef __ia64__
+#define ELF_ETYPE ET_DYN
+#else
+#define ELF_ETYPE ET_EXEC
+#endif
+
+/* Well known ELF structures.  */
+Elf_Ehdr *ehdr;
+Elf_Shdr *shdr_base;
+Elf_Shdr *shdr_dynamic;
+const uint8_t *shdr_str;
+
+/* PE section alignment.  */
+const uint32_t coff_alignment = 0x20;
+const uint32_t coff_nbr_sections = 4;
+
+/* Current offset in coff file.  */
+uint32_t coff_offset;
+
+/* Result Coff file in memory.  */
+uint8_t *coff_file;
+
+/* Offset in Coff file of headers and sections.  */
+uint32_t nt_hdr_offset;
+uint32_t table_offset;
+uint32_t text_offset;
+uint32_t data_offset;
+uint32_t reloc_offset;
+
+#ifdef __ia64__
+uint32_t coff_entry_descr_offset;
+uint32_t coff_entry_descr_func;
+uint64_t plt_base;
+#endif
+
+/* ELF sections to offset in Coff file.  */
+uint32_t *coff_sections_offset;
+
+struct pe32_fixup_block *coff_base_rel;
+uint16_t *coff_entry_rel;
+
+uint32_t
+coff_align(uint32_t offset)
+{
+  return (offset + coff_alignment - 1) & ~(coff_alignment - 1);
+}
+
+Elf_Shdr *
+get_shdr_by_index(uint32_t num)
+{
+  if (num >= ehdr->e_shnum)
+    return NULL;
+  return (Elf_Shdr*)((uint8_t*)shdr_base + num * ehdr->e_shentsize);
+}
+
+int
+check_elf_header (void)
+{
+  /* Note: Magic has already been tested.  */
+  if (ehdr->e_ident[EI_CLASS] != ELFCLASS)
+    return 0;
+  if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
+    return 0;
+  if (ehdr->e_type != ELF_ETYPE)
+    return 0;
+  if (ehdr->e_machine != ELF_MACHINE)
+    return 0;
+  if (ehdr->e_version != EV_CURRENT)
+    return 0;
+  
+  shdr_base = (Elf_Shdr *)((uint8_t *)ehdr + ehdr->e_shoff);
+
+  coff_sections_offset =
+    (uint32_t *)malloc (ehdr->e_shnum * sizeof (uint32_t));
+  memset (coff_sections_offset, 0, ehdr->e_shnum * sizeof(uint32_t));
+
+  if (ehdr->e_shstrndx != SHN_UNDEF)
+    shdr_str = (uint8_t*)ehdr + shdr_base[ehdr->e_shstrndx].sh_offset;
+  else
+    shdr_str = NULL;
+
+  return 1;
+}
+
+int
+is_text_shdr (Elf_Shdr *shdr)
+{
+  if (shdr->sh_type != SHT_PROGBITS) {
+    return 0;
+  }
+#ifdef __ia64__
+  return (shdr->sh_flags & (SHF_EXECINSTR | SHF_ALLOC))
+    == (SHF_ALLOC | SHF_EXECINSTR);
+#else
+  return (shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC;
+#endif
+}
+
+int
+is_data_shdr (Elf_Shdr *shdr)
+{
+  if (shdr->sh_type != SHT_PROGBITS && shdr->sh_type != SHT_NOBITS) {
+    return 0;
+  }
+  return (shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE);
+}
+
+void
+create_section_header (const char *name, uint32_t offset, uint32_t size,
+                      uint32_t flags)
+{
+  struct pe32_section_header *hdr;
+  hdr = (struct pe32_section_header*)(coff_file + table_offset);
+
+  strcpy (hdr->name, name);
+  hdr->virtual_size = size;
+  hdr->virtual_address = offset;
+  hdr->raw_data_size = size;
+  hdr->raw_data_offset = offset;
+  hdr->relocations_offset = 0;
+  hdr->line_numbers_offset = 0;
+  hdr->num_relocations = 0;
+  hdr->num_line_numbers = 0;
+  hdr->characteristics = flags;
+
+  table_offset += sizeof (struct pe32_section_header);
+}
+
+int
+scan_sections (void)
+{
+  uint32_t i;
+  struct pe32_dos_header *doshdr;
+  struct pe32_nt_header *nt_hdr;
+  uint32_t coff_entry = 0;
+  int status = 0;
+
+  coff_offset = 0;
+
+  /* Coff file start with a DOS header.  */
+  coff_offset = sizeof(struct pe32_dos_header);
+  nt_hdr_offset = coff_offset;
+  coff_offset += sizeof(struct pe32_nt_header);
+  table_offset = coff_offset;
+  coff_offset += coff_nbr_sections * sizeof(struct pe32_section_header);
+
+  /* First text sections.  */
+  coff_offset = coff_align(coff_offset);
+  text_offset = coff_offset;
+  for (i = 0; i < ehdr->e_shnum; i++) {
+    Elf_Shdr *shdr = get_shdr_by_index (i);
+    if (is_text_shdr (shdr)) {
+      /* Relocate entry.  */
+      if (ehdr->e_entry >= shdr->sh_addr
+         && ehdr->e_entry < shdr->sh_addr + shdr->sh_size) {
+       coff_entry = coff_offset + ehdr->e_entry - shdr->sh_addr;
+      }
+      coff_sections_offset[i] = coff_offset;
+      coff_offset += shdr->sh_size;
+#ifdef __ia64__
+      if (coff_sections_offset[i] != shdr->sh_addr) {
+       fprintf (stderr, 
+                "Section %s: Coff offset (%x) != Elf offset (%lx)",
+                shdr_str + shdr->sh_name,
+                coff_sections_offset[i],
+                shdr->sh_addr);
+       status = -1;
+      }
+#endif
+    }
+    if (shdr->sh_type == SHT_DYNAMIC) {
+      shdr_dynamic = shdr;
+    }
+  }
+#ifdef __ia64__
+  /* 16 bytes are reserved (by the ld script) for the entry point descriptor.
+   */
+  coff_entry_descr_offset = coff_offset - 16;
+#endif
+
+  coff_offset = coff_align (coff_offset);
+                      
+  /* Then data sections.  */
+  data_offset = coff_offset;
+  for (i = 0; i < ehdr->e_shnum; i++) {
+    Elf_Shdr *shdr = get_shdr_by_index (i);
+    if (is_data_shdr (shdr)) {
+      coff_sections_offset[i] = coff_offset;
+      coff_offset += shdr->sh_size;
+#ifdef __ia64__
+      if (coff_sections_offset[i] != shdr->sh_addr) {
+       fprintf (stderr,
+                "Section %s: Coff offset (%x) != Elf offset (%lx)",
+                shdr_str + shdr->sh_name,
+                coff_sections_offset[i],
+                shdr->sh_addr);
+       status = -1;
+      }
+#endif
+    }
+  }
+  coff_offset = coff_align (coff_offset);
+
+  reloc_offset = coff_offset;  
+
+  /* Allocate base Coff file.  Will be expanded later for relocations.  */
+  coff_file = (uint8_t *)malloc (coff_offset);
+  memset (coff_file, 0, coff_offset);
+
+  /* Fill headers.  */
+  doshdr = (struct pe32_dos_header *)coff_file;
+  doshdr->magic = 0x5A4D;
+  doshdr->new_hdr_offset = nt_hdr_offset;
+
+  nt_hdr = (struct pe32_nt_header*)(coff_file + nt_hdr_offset);
+
+  memcpy (nt_hdr->signature, "PE\0", 4);
+
+  nt_hdr->coff_header.machine = EFI_MACHINE;
+  nt_hdr->coff_header.num_sections = coff_nbr_sections;
+  nt_hdr->coff_header.time = time (NULL);
+  nt_hdr->coff_header.symtab_offset = 0;
+  nt_hdr->coff_header.num_symbols = 0;
+  nt_hdr->coff_header.optional_header_size = sizeof(nt_hdr->optional_header);
+  nt_hdr->coff_header.characteristics = PE32_EXECUTABLE_IMAGE
+    | PE32_LINE_NUMS_STRIPPED
+    | PE32_LOCAL_SYMS_STRIPPED
+    | PE32_32BIT_MACHINE;
+
+#ifdef USE_PE32
+  nt_hdr->optional_header.magic = PE32_PE32_MAGIC;
+#else
+  nt_hdr->optional_header.magic = PE32_PE64_MAGIC;
+#endif
+  nt_hdr->optional_header.code_size = data_offset - text_offset;
+  nt_hdr->optional_header.data_size = reloc_offset - data_offset;
+  nt_hdr->optional_header.bss_size = 0;
+#ifdef __ia64__
+  nt_hdr->optional_header.entry_addr = coff_entry_descr_offset;
+  coff_entry_descr_func = coff_entry;
+#else
+  nt_hdr->optional_header.entry_addr = coff_entry;
+#endif
+  nt_hdr->optional_header.code_base = text_offset;
+
+#ifdef USE_PE32
+  nt_hdr->optional_header.data_base = data_offset;
+#endif
+  nt_hdr->optional_header.image_base = 0;
+  nt_hdr->optional_header.section_alignment = coff_alignment;
+  nt_hdr->optional_header.file_alignment = coff_alignment;
+  nt_hdr->optional_header.image_size = 0;
+
+  nt_hdr->optional_header.header_size = text_offset;
+  nt_hdr->optional_header.num_data_directories = PE32_NUM_DATA_DIRECTORIES;
+
+  /* Section headers.  */
+  create_section_header (".text", text_offset, data_offset - text_offset,
+                        PE32_SCN_CNT_CODE
+                        | PE32_SCN_MEM_EXECUTE
+                        | PE32_SCN_MEM_READ);
+  create_section_header (".data", data_offset, reloc_offset - data_offset,
+                        PE32_SCN_CNT_INITIALIZED_DATA
+                        | PE32_SCN_MEM_WRITE
+                        | PE32_SCN_MEM_READ);
+#ifdef __ia64__
+  if (shdr_dynamic != NULL)
+    {
+      Elf64_Dyn *dyn = (Elf64_Dyn*)((uint8_t*)ehdr + shdr_dynamic->sh_offset);
+      while (dyn->d_tag != DT_NULL)
+       {
+         if (dyn->d_tag == DT_PLTGOT)
+           plt_base = dyn->d_un.d_ptr;
+         dyn++;
+       }
+    }
+#endif
+  return status;
+}
+
+int
+write_sections (int (*filter)(Elf_Shdr *))
+{
+  uint32_t idx;
+  int status = 0;
+
+  /* First: copy sections.  */
+  for (idx = 0; idx < ehdr->e_shnum; idx++)
+    {
+      Elf_Shdr *shdr = get_shdr_by_index (idx);
+      if ((*filter)(shdr))
+       {
+         switch (shdr->sh_type) {
+         case SHT_PROGBITS:
+           /* Copy.  */
+           memcpy (coff_file + coff_sections_offset[idx],
+                   (uint8_t*)ehdr + shdr->sh_offset,
+                   shdr->sh_size);
+           break;
+         case SHT_NOBITS:
+           memset (coff_file + coff_sections_offset[idx], 0, shdr->sh_size);
+           break;
+         case SHT_DYNAMIC:
+           break;
+         default:
+           fprintf (stderr, "unhandled section type %x",
+                    (unsigned int)shdr->sh_type);
+           status = -1;
+         }
+       }
+    }
+
+  /* Second: apply relocations.  */
+  for (idx = 0; idx < ehdr->e_shnum; idx++)
+    {
+      Elf_Shdr *rel_shdr = get_shdr_by_index (idx);
+      if (rel_shdr->sh_type != SHT_REL && rel_shdr->sh_type != SHT_RELA)
+       continue;
+      Elf_Shdr *sec_shdr = get_shdr_by_index (rel_shdr->sh_info);
+      uint32_t sec_offset = coff_sections_offset[rel_shdr->sh_info];
+
+      if (rel_shdr->sh_info == 0 || (*filter)(sec_shdr))
+       {
+         uint32_t rel_idx;
+         Elf_Shdr *symtab_shdr = get_shdr_by_index(rel_shdr->sh_link);
+         uint8_t *symtab = (uint8_t*)ehdr + symtab_shdr->sh_offset;
+
+         if (rel_shdr->sh_type == SHT_REL)
+           {
+             for (rel_idx = 0;
+                  rel_idx < rel_shdr->sh_size;
+                  rel_idx += rel_shdr->sh_entsize)
+               {
+                 Elf_Rel *rel = (Elf_Rel *)
+                   ((uint8_t*)ehdr + rel_shdr->sh_offset + rel_idx);
+                 Elf_Sym *sym = (Elf_Sym *)
+                   (symtab
+                    + ELF_R_SYM(rel->r_info) * symtab_shdr->sh_entsize);
+                 Elf_Shdr *sym_shdr;
+                 uint8_t *targ;
+
+                 if (sym->st_shndx == SHN_UNDEF
+                     || sym->st_shndx == SHN_ABS
+                     || sym->st_shndx > ehdr->e_shnum)
+                   {
+                     fprintf (stderr, "bad symbol definition");
+                     status = -1;
+                   }
+                 sym_shdr = get_shdr_by_index(sym->st_shndx);
+
+                 /* Note: r_offset in a memory address.
+                    Convert it to a pointer in the coff file.  */
+                 targ = coff_file + sec_offset
+                   + (rel->r_offset - sec_shdr->sh_addr);
+
+                 switch (ELF_R_TYPE(rel->r_info)) {
+                 case R_386_NONE:
+                   break;
+                 case R_386_32:
+                   /* Absolute relocation.  */
+                   *(uint32_t *)targ = *(uint32_t *)targ - sym_shdr->sh_addr
+                     + coff_sections_offset[sym->st_shndx];
+                   break;
+                 case R_386_PC32:
+                   /* Relative relocation: Symbol - Ip + Addend  */
+                   *(uint32_t *)targ = *(uint32_t *)targ
+                     + (coff_sections_offset[sym->st_shndx]
+                        - sym_shdr->sh_addr)
+                     - (sec_offset - sec_shdr->sh_addr);
+                   break;
+                 default:
+                   fprintf (stderr, "unhandled relocation type %lx",
+                            ELF_R_TYPE(rel->r_info));
+                   status = -1;
+                 }
+               }
+           }
+         else if (rel_shdr->sh_type == SHT_RELA)
+           {
+             for (rel_idx = 0;
+                  rel_idx < rel_shdr->sh_size;
+                  rel_idx += rel_shdr->sh_entsize) {
+               Elf_Rela *rela = (Elf_Rela *)
+                 ((uint8_t*)ehdr + rel_shdr->sh_offset + rel_idx);
+               Elf_Sym *sym = (Elf_Sym *)
+                 (symtab + ELF_R_SYM(rela->r_info) * symtab_shdr->sh_entsize);
+               Elf_Shdr *sym_shdr;
+               uint8_t *targ;
+               
+               if (ELF_R_TYPE(rela->r_info) == R_IA64_NONE)
+                 continue;
+               
+#if 0
+               if (sym->st_shndx == SHN_UNDEF
+                   || sym->st_shndx == SHN_ABS
+                   || sym->st_shndx > ehdr->e_shnum) {
+                 fprintf (stderr, "bad symbol definition %d",
+                          ELF_R_SYM(rela->r_info));
+               }
+#endif
+               sym_shdr = get_shdr_by_index (sym->st_shndx);
+               
+               /* Note: r_offset in a memory address.
+                  Convert it to a pointer in the coff file.  */
+               targ = coff_file + sec_offset
+                 + (rela->r_offset - sec_shdr->sh_addr);
+               
+               switch (ELF_R_TYPE(rela->r_info)) {
+               case R_IA64_IPLTLSB:
+                 /* If there is a descriptor with the same function
+                    pointer as the ELF entry point, use that
+                    descriptor for the PE/Coff entry.  */
+                 if (*(uint64_t*)targ == ehdr->e_entry) {
+                   struct pe32_nt_header *nt_hdr;
+                   
+                   nt_hdr = 
+                     (struct pe32_nt_header*)(coff_file + nt_hdr_offset);
+                   nt_hdr->optional_header.entry_addr = targ - coff_file;
+                 }
+                 break;
+               case R_IA64_REL64LSB:
+               case R_IA64_NONE:
+                 break;
+               default:
+                 fprintf (stderr,
+                          "unhandled relocation type %lx in section %d",
+                          ELF_R_TYPE(rela->r_info), rel_shdr->sh_info);
+                 status = -1;
+               }
+             }
+           }
+       }
+    }
+  return status;
+}
+
+void
+coff_add_fixup_entry (uint16_t val)
+{
+  *coff_entry_rel = val;
+  coff_entry_rel++;
+  coff_base_rel->block_size += 2;
+  coff_offset += 2;
+}
+
+void
+coff_add_fixup (uint32_t offset, uint8_t type)
+{
+  if (coff_base_rel == NULL
+      || coff_base_rel->page_rva != (offset & ~0xfff)) {
+    if (coff_base_rel != NULL) {
+      /* Add a null entry (is it required ?)  */
+      coff_add_fixup_entry (0);
+      /* Pad for alignment.  */
+      if (coff_offset % 4 != 0)
+       coff_add_fixup_entry (0);
+    }
+      
+    coff_file = realloc
+      (coff_file,
+       coff_offset + sizeof(struct pe32_fixup_block) + 2*0x1000);
+    memset(coff_file + coff_offset, 0,
+          sizeof(struct pe32_fixup_block) + 2*0x1000);
+
+    coff_base_rel = (struct pe32_fixup_block*)(coff_file + coff_offset);
+    coff_base_rel->page_rva = offset & ~0xfff;
+    coff_base_rel->block_size = sizeof(struct pe32_fixup_block);
+
+    coff_entry_rel = (uint16_t *)(coff_base_rel + 1);
+    coff_offset += sizeof(struct pe32_fixup_block);
+  }
+
+  /* Fill the entry.  */
+  coff_add_fixup_entry ((type << 12) | (offset & 0xfff));
+}
+
+int
+write_relocations(void)
+{
+  uint32_t idx;
+  struct pe32_nt_header *nt_hdr;
+  struct pe32_data_directory *dir;
+  int status = 0;
+
+  for (idx = 0; idx < ehdr->e_shnum; idx++)
+    {
+      Elf_Shdr *rel_shdr = get_shdr_by_index (idx);
+      if (rel_shdr->sh_type == SHT_REL)
+       {
+         Elf_Shdr *sec_shdr = get_shdr_by_index (rel_shdr->sh_info);
+         if (is_text_shdr(sec_shdr) || is_data_shdr(sec_shdr))
+           {
+             uint32_t rel_idx;
+             for (rel_idx = 0;
+                  rel_idx < rel_shdr->sh_size;
+                  rel_idx += rel_shdr->sh_entsize)
+               {
+                 Elf_Rel *rel = (Elf_Rel *)
+                   ((uint8_t*)ehdr + rel_shdr->sh_offset + rel_idx);
+
+                 switch (ELF_R_TYPE(rel->r_info))
+                   {
+                   case R_386_NONE:
+                   case R_386_PC32:
+                     break;
+                   case R_386_32:
+                     coff_add_fixup(coff_sections_offset[rel_shdr->sh_info]
+                                    + (rel->r_offset - sec_shdr->sh_addr),
+                                    PE32_REL_BASED_HIGHLOW);
+                     break;
+                   default:
+                     fprintf (stderr, "unhandled relocation type %lx",
+                              ELF_R_TYPE(rel->r_info));
+                     status = -1;
+                   }
+               }
+           }
+       }
+      else if (rel_shdr->sh_type == SHT_RELA)
+       {
+         Elf_Shdr *sec_shdr = get_shdr_by_index(rel_shdr->sh_info);
+         if (rel_shdr->sh_info == 0
+             || is_text_shdr(sec_shdr) || is_data_shdr(sec_shdr))
+           {
+             uint32_t rel_idx;
+             for (rel_idx = 0;
+                  rel_idx < rel_shdr->sh_size;
+                  rel_idx += rel_shdr->sh_entsize) {
+               Elf_Rela *rela = (Elf_Rela *)
+                 ((uint8_t*)ehdr + rel_shdr->sh_offset + rel_idx);
+               uint32_t Loc = coff_sections_offset[rel_shdr->sh_info]
+                 + (rela->r_offset - sec_shdr->sh_addr);
+
+               switch (ELF_R_TYPE(rela->r_info))
+                 {
+                 case R_IA64_IPLTLSB:
+                   coff_add_fixup(Loc, PE32_REL_BASED_DIR64);
+                   coff_add_fixup(Loc + 8, PE32_REL_BASED_DIR64);
+                   break;
+                 case R_IA64_REL64LSB:
+                   coff_add_fixup(Loc, PE32_REL_BASED_DIR64);
+                   break;
+                 case R_IA64_DIR64LSB:
+                   coff_add_fixup(Loc, PE32_REL_BASED_DIR64);
+                   break;
+                 case R_IA64_IMM64:
+                   coff_add_fixup(Loc, PE32_REL_BASED_IA64_IMM64);
+                   break;
+                 case R_IA64_PCREL21B:
+                 case R_IA64_PCREL64LSB:
+                 case R_IA64_SECREL32LSB:
+                 case R_IA64_SEGREL64LSB:
+                   break;
+                 case R_IA64_GPREL22:
+                 case R_IA64_LTOFF22X:
+                 case R_IA64_LDXMOV:
+                 case R_IA64_LTOFF_FPTR22:
+                 case R_IA64_NONE:
+                   break;
+                 default:
+                   fprintf (stderr, "unhandled relocation type %lx",
+                            ELF_R_TYPE(rela->r_info));
+                   status = -1;
+                 }
+             }
+           }
+       }
+    }
+  
+#ifdef __ia64__
+  coff_add_fixup (coff_entry_descr_offset, PE32_REL_BASED_DIR64);
+  coff_add_fixup (coff_entry_descr_offset + 8, PE32_REL_BASED_DIR64);
+#endif
+
+  /* Pad by adding empty entries.   */
+  while (coff_offset & (coff_alignment - 1))
+    coff_add_fixup_entry (0);
+
+  create_section_header (".reloc", reloc_offset, coff_offset - reloc_offset,
+                        PE32_SCN_CNT_INITIALIZED_DATA
+                        | PE32_SCN_MEM_DISCARDABLE
+                        | PE32_SCN_MEM_READ);
+  
+  nt_hdr = (struct pe32_nt_header *)(coff_file + nt_hdr_offset);
+  dir = &nt_hdr->optional_header.base_relocation_table;
+  dir->rva = reloc_offset;
+  dir->size = coff_offset - reloc_offset;
+  
+  return status;
+}
+
+void
+write_debug(void)
+{
+  uint32_t len = strlen(filename) + 1;
+  uint32_t debug_offset = coff_offset;
+  struct pe32_nt_header *nt_hdr;
+  struct pe32_data_directory *data_dir;
+  struct pe32_debug_directory_entry *dir;
+  struct pe32_debug_codeview_nb10_entry *nb10;
+
+  coff_offset += sizeof (struct pe32_debug_directory_entry)
+    + sizeof(struct pe32_debug_codeview_nb10_entry)
+    + len;
+  coff_offset = coff_align(coff_offset);
+
+  coff_file = realloc
+    (coff_file, coff_offset);
+  memset(coff_file + debug_offset, 0, coff_offset - debug_offset);
+  
+  dir = (struct pe32_debug_directory_entry*)(coff_file + debug_offset);
+  dir->type = PE32_DEBUG_TYPE_CODEVIEW;
+  dir->data_size = sizeof(struct pe32_debug_directory_entry) + len;
+  dir->rva = debug_offset + sizeof(struct pe32_debug_directory_entry);
+  dir->file_offset = debug_offset + sizeof(struct pe32_debug_directory_entry);
+  
+  nb10 = (struct pe32_debug_codeview_nb10_entry*)(dir + 1);
+  nb10->signature = PE32_CODEVIEW_SIGNATURE_NB10;
+  strcpy (nb10->filename, filename);
+
+  create_section_header (".debug", debug_offset, coff_offset - debug_offset,
+                      PE32_SCN_CNT_INITIALIZED_DATA
+                      | PE32_SCN_MEM_DISCARDABLE
+                      | PE32_SCN_MEM_READ);
+
+  nt_hdr = (struct pe32_nt_header *)(coff_file + nt_hdr_offset);
+  data_dir = &nt_hdr->optional_header.debug;
+  data_dir->rva = debug_offset;
+  data_dir->size = coff_offset - debug_offset;
+}
+
+int
+convert_elf (uint8_t **file_buffer, unsigned int *file_length)
+{
+  struct pe32_nt_header *nt_hdr;
+
+  /* Check header, read section table.  */
+  ehdr = (Elf_Ehdr*)*file_buffer;
+  if (!check_elf_header ())
+    return -1;
+
+  /* Compute sections new address.  */
+  if (scan_sections () != 0)
+    return -2;
+
+  /* Write and relocate sections.  */
+  if (write_sections (is_text_shdr) != 0)
+    return -3;
+
+#ifdef __ia64__
+  *(uint64_t*)(coff_file + coff_entry_descr_offset) = coff_entry_descr_func;
+  *(uint64_t*)(coff_file + coff_entry_descr_offset + 8) = plt_base;
+#endif
+
+  if (write_sections (is_data_shdr) != 0)
+    return -4;
+
+  /* Translate and write relocations.  */
+  if (write_relocations () != 0)
+    return -5;
+
+  /* Write debug info.  */
+  write_debug ();
+
+  nt_hdr = (struct pe32_nt_header *)(coff_file + nt_hdr_offset);
+  nt_hdr->optional_header.image_size = coff_offset;
+
+  nt_hdr->optional_header.subsystem = PE32_SUBSYSTEM_EFI_APPLICATION;
+
+  /* Replace.  */
+  free (*file_buffer);
+  *file_buffer = coff_file;
+  *file_length = coff_offset;
+
+  return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+  FILE *f;
+  unsigned int size;
+  uint8_t *buffer;
+  const char *outfile;
+  int status;
+
+  if (argc != 3)
+    {
+      fprintf (stderr, "usage: %s elf-file pe-file\n", argv[0]);
+      exit (1);
+    }
+
+  filename = argv[1];
+  outfile = argv[2];
+  f = fopen (filename, "rb");
+  fseek (f, 0, SEEK_END);
+  size = ftell (f);
+  fseek (f, 0, SEEK_SET);
+
+  buffer = malloc (size);
+  if (buffer == NULL)
+    {
+      fprintf (stderr, "cannot allocate %u bytes of memory\n", size);
+      exit (2);
+    }
+  if (fread (buffer, size, 1, f) != 1)
+    {
+      fprintf (stderr, "cannot read %s\n", filename);
+      exit (2);
+    }
+  fclose (f);
+
+  if (!is_elf_header (buffer))
+    {
+      fprintf (stderr, "%s is not an elf file\n", filename);
+      exit (2);
+    }
+  
+  status = convert_elf (&buffer, &size);
+  if (status != 0)
+    {
+      fprintf (stderr, "cannot convert %s to pe (err=%d)\n", filename, status);
+      exit (2);
+    }
+  
+  f = fopen (outfile, "wb");
+  if (f == NULL)
+    {
+      fprintf (stderr, "cannot open %s\n", outfile);
+      exit (2);
+    }
+  if (fwrite (buffer, size, 1, f) != 1)
+    {
+      fprintf (stderr, "cannot write to %s\n", outfile);
+      exit (2);
+    }
+  fclose (f);
+
+  return 0;
+}
diff --git a/util/ia64/efi/grub-install.in b/util/ia64/efi/grub-install.in
new file mode 100644 (file)
index 0000000..63b0c9f
--- /dev/null
@@ -0,0 +1,233 @@
+#! /bin/sh
+
+# Install GRUB on your EFI partition.
+# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008  Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+
+
+# Initialize some variables.
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+sbindir=@sbindir@
+bindir=@bindir@
+libdir=@libdir@
+datadir=@datadir@
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_TARNAME=@PACKAGE_TARNAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+target_cpu=@target_cpu@
+platform=@platform@
+pkglibdir=${libdir}/${PACKAGE_TARNAME}/${target_cpu}-${platform}
+pkgdatadir=${datadir}/${PACKAGE_TARNAME}
+
+
+TARGET_CC=@TARGET_CC@
+TARGET_CFLAGS="@TARGET_CFLAGS@"
+TARGET_CPPFLAGS="@TARGET_CPPFLAGS@"
+TARGET_LDFLAGS="@TARGET_LDFLAGS@"
+OBJCOPY=@OBJCOPY@
+
+grub_setup=${sbindir}/grub-setup
+grub_mkimage=${bindir}/grub-mkimage
+grub_mkdevicemap=${sbindir}/grub-mkdevicemap
+grub_probefs=${sbindir}/grub-probefs
+rootdir=
+grub_prefix=/boot/grub
+modules=
+
+install_device=
+recheck=no
+debug=no
+
+# Usage: usage
+# Print the usage.
+usage () {
+    cat <<EOF
+Usage: grub-install [OPTION] install_device
+Install GRUB on your drive.
+
+  -h, --help              print this message and exit
+  -v, --version           print the version information and exit
+  --modules=MODULES       pre-load specified modules MODULES
+  --root-directory=DIR    install GRUB images under the directory DIR
+                          instead of the root directory
+  --grub-setup=FILE       use FILE as grub-setup
+  --grub-mkimage=FILE     use FILE as grub-mkimage
+  --grub-mkdevicemap=FILE use FILE as grub-mkdevicemap
+  --grub-probefs=FILE     use FILE as grub-probefs
+  --no-floppy             do not probe any floppy drive
+  --recheck               probe a device map even if it already exists
+
+INSTALL_DEVICE can be a GRUB device name or a system device filename.
+
+grub-install copies GRUB images into the DIR/boot directory specfied by
+--root-directory, and uses grub-setup to install grub into the boot
+sector.
+
+Report bugs to <bug-grub@gnu.org>.
+EOF
+}
+
+# Check the arguments.
+for option in "$@"; do
+    case "$option" in
+    -h | --help)
+       usage
+       exit 0 ;;
+    -v | --version)
+       echo "grub-install (GNU GRUB ${PACKAGE_VERSION})"
+       exit 0 ;;
+    --modules=*)
+       modules=`echo "$option" | sed 's/--modules=//'` ;;
+    --root-directory=*)
+       rootdir=`echo "$option" | sed 's/--root-directory=//'` ;;
+    --grub-setup=*)
+       grub_setup=`echo "$option" | sed 's/--grub-setup=//'` ;;
+    --grub-mkimage=*)
+       grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;;
+    --grub-mkdevicemap=*)
+       grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;;
+    --grub-probefs=*)
+       grub_probefs=`echo "$option" | sed 's/--grub-probefs=//'` ;;
+    --pkglibdir=*)
+       pkglibdir=`echo "$option" | sed 's/--pkglibdir=//'` ;;
+    --pkgdatadir=*)
+       pkgdatadir=`echo "$option" | sed 's/--pkgdatadir=//'` ;;
+    --recheck)
+       recheck=yes ;;
+    # This is an undocumented feature...
+    --debug)
+       debug=yes ;;
+    -*)
+       echo "Unrecognized option \`$option'" 1>&2
+       usage
+       exit 1
+       ;;
+    *)
+       if test "x$install_device" != x; then
+           echo "More than one install_devices?" 1>&2
+           usage
+           exit 1
+       fi
+       install_device="${option}" ;;
+    esac
+done
+
+#if test "x$install_device" = x; then
+#    echo "install_device not specified." 1>&2
+#    usage
+#    exit 1
+#fi
+
+# If the debugging feature is enabled, print commands.
+if test $debug = yes; then
+    set -x
+fi
+
+# Initialize these directories here, since ROOTDIR was initialized.
+bootdir=${rootdir}/boot/efi
+
+grubdir=${bootdir}/grub
+device_map=${grubdir}/device.map
+
+# Create the GRUB directory if it is not present.
+test -d "$bootdir" || mkdir "$bootdir" || exit 1
+test -d "$grubdir" || mkdir "$grubdir" || exit 1
+
+# Copy the GRUB images to the GRUB directory.
+if false; then
+  for file in ${grubdir}/*.mod ${grubdir}/*.lst; do
+      if test -f $file; then
+         rm -f $file || exit 1
+      fi
+  done
+  for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst; do
+      cp -f $file ${grubdir} || exit 1
+  done
+fi
+
+# Create the core image. First, auto-detect the filesystme module.
+#fs_module=`$grub_probefs --device-map=${device_map} ${grubdir}`
+#if test "x$fs_module" = x -a "x$modules" = x; then
+#    echo "Auto-detection of a filesystem module failed." 1>&2
+#    echo "Please specify the module with the option \`--modules' explicitly." 1>&2
+#    exit 1
+#fi
+
+# Typically, _chain and pc are required.
+modules="$modules $fs_module _chain"
+
+modules="kernel gzio gpt fat normal ls cat fshelp help _linux linux $modules"
+modules="$modules memmap systab boot"
+
+if [ $debug = yes ]; then
+  tmpdir=.
+else
+  tmpdir=`mktemp -d /tmp/grub.XXXXXXXXXX` || exit 1
+  trap "rm -rf $tmpdir" 1 2 13 15
+fi
+
+# Generate init/fini for modules.
+modfile=$tmpdir/mod.c
+echo "/* Dummy modules.  */" > $modfile
+list=""
+init_list=""
+fini_list=""
+for m in $modules; do
+  file="$pkglibdir/${m}.mod"
+  name=`nm $file | sed -n "/ r grub_module_name/ s/.* r grub_module_name_\(.*\)/\1/p"`
+  init=`nm $file | sed -n "/ T grub_module_.*_init/ s/.* T //p"`
+  fini=`nm $file | sed -n "/ T grub_module_.*_fini/ s/.* T //p"`
+  init_list="$init_list $init"
+  fini_list="$fini_list $fini"
+  arg="\"$name\",${init:-0},${fini:-0}"
+  list="$list $arg"
+done
+echo "extern void grub_init_module (const char *, void (*init)(void *), void (*fini)(void));" >> $modfile
+echo "extern void grub_init_modules (void);" >> $modfile
+for m in $init_list; do
+  echo "extern void $m(void *);" >> $modfile
+done
+for m in $fini_list; do
+  echo "extern void $m(void);" >> $modfile
+done
+echo "void grub_init_modules (void)" >> $modfile
+echo "{" >> $modfile
+for m in $list; do
+  echo "  grub_init_module($m);" >> $modfile
+done
+echo "}" >> $modfile
+
+$TARGET_CC -c $TARGET_CFLAGS -o $tmpdir/mod.o $modfile
+
+mod_objs=
+for m in $modules; do mod_objs="$mod_objs $pkglibdir/${m}.mod"; done
+
+ld -pie -nostdlib -T $pkgdatadir/elf_ia64_efi.lds \
+ $mod_objs $tmpdir/mod.o -o $tmpdir/grub.elf 
+
+
+if ! $bindir/grub-elf2pe $tmpdir/grub.elf $grubdir/grub.efi; then
+  echo "Failed to build efi binary"
+  [ $debug = no ] && rm -rf $tmpdir
+  exit 1
+fi
+
+echo "grub.efi generated"
+
+[ $debug = no ] && rm -rf $tmpdir
+
+# Bye.
+exit 0
diff --git a/util/ia64/efi/pe32.h b/util/ia64/efi/pe32.h
new file mode 100644 (file)
index 0000000..391e70c
--- /dev/null
@@ -0,0 +1,237 @@
+/* pe32.h  - PE/Coff definitions.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifdef USE_PE32PLUS
+typedef uint64_t pe32_uintptr_t;
+#else
+typedef uint32_t pe32_uintptr_t;
+#endif
+
+struct pe32_coff_header
+{
+  uint16_t machine;
+  uint16_t num_sections;
+  uint32_t time;
+  uint32_t symtab_offset;
+  uint32_t num_symbols;
+  uint16_t optional_header_size;
+  uint16_t characteristics;
+};
+
+#define PE32_MACHINE_I386     0x014c
+#define PE32_MACHINE_IA64     0x0200
+#define PE32_MACHINE_EBC      0x0EBC
+#define PE32_MACHINE_X64      0x8664
+
+#define PE32_RELOCS_STRIPPED           0x0001
+#define PE32_EXECUTABLE_IMAGE          0x0002
+#define PE32_LINE_NUMS_STRIPPED                0x0004
+#define PE32_LOCAL_SYMS_STRIPPED       0x0008
+#define PE32_AGGRESSIVE_WS_TRIM                0x0010
+#define PE32_LARGE_ADDRESS_AWARE       0x0020
+#define PE32_16BIT_MACHINE             0x0040
+#define PE32_BYTES_REVERSED_LO         0x0080
+#define PE32_32BIT_MACHINE             0x0100
+#define PE32_DEBUG_STRIPPED            0x0200
+#define PE32_REMOVABLE_RUN_FROM_SWAP   0x0400
+#define PE32_SYSTEM                    0x1000
+#define PE32_DLL                       0x2000
+#define PE32_UP_SYSTEM_ONLY            0x4000
+#define PE32_BYTES_REVERSED_HI         0x8000
+
+struct pe32_data_directory
+{
+  uint32_t rva;
+  uint32_t size;
+};
+
+struct pe32_optional_header
+{
+  uint16_t magic;
+  uint8_t major_linker_version;
+  uint8_t minor_linker_version;
+  uint32_t code_size;
+  uint32_t data_size;
+  uint32_t bss_size;
+  uint32_t entry_addr;
+  uint32_t code_base;
+  
+#ifndef USE_PE32PLUS
+  uint32_t data_base;
+#endif
+
+  pe32_uintptr_t image_base;
+  uint32_t section_alignment;
+  uint32_t file_alignment;
+  uint16_t major_os_version;
+  uint16_t minor_os_version;
+  uint16_t major_image_version;
+  uint16_t minor_image_version;
+  uint16_t major_subsystem_version;
+  uint16_t minor_subsystem_version;
+  uint32_t reserved;
+  uint32_t image_size;
+  uint32_t header_size;
+  uint32_t checksum;
+  uint16_t subsystem;
+  uint16_t dll_characteristics;
+  pe32_uintptr_t stack_reserve_size;
+  pe32_uintptr_t stack_commit_size;
+  pe32_uintptr_t heap_reserve_size;
+  pe32_uintptr_t heap_commit_size;
+  uint32_t loader_flags;
+  uint32_t num_data_directories;
+  
+  /* Data directories.  */
+  struct pe32_data_directory export_table;
+  struct pe32_data_directory import_table;
+  struct pe32_data_directory resource_table;
+  struct pe32_data_directory exception_table;
+  struct pe32_data_directory certificate_table;
+  struct pe32_data_directory base_relocation_table;
+  struct pe32_data_directory debug;
+  struct pe32_data_directory architecture;
+  struct pe32_data_directory global_ptr;
+  struct pe32_data_directory tls_table;
+  struct pe32_data_directory load_config_table;
+  struct pe32_data_directory bound_import;
+  struct pe32_data_directory iat;
+  struct pe32_data_directory delay_import_descriptor;
+  struct pe32_data_directory com_runtime_header;
+  struct pe32_data_directory reserved_entry;
+};
+
+#define PE32_PE32_MAGIC        0x10b
+#define PE32_PE64_MAGIC        0x20b
+
+#define PE32_SUBSYSTEM_EFI_APPLICATION        10
+#define PE32_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
+#define PE32_SUBSYSTEM_EFI_RUNTIME_DRIVER      12
+#define PE32_SUBSYSTEM_EFI_EFI_ROM             13
+
+#define PE32_NUM_DATA_DIRECTORIES      16
+
+struct pe32_section_header
+{
+  char name[8];
+  uint32_t virtual_size;
+  uint32_t virtual_address;
+  uint32_t raw_data_size;
+  uint32_t raw_data_offset;
+  uint32_t relocations_offset;
+  uint32_t line_numbers_offset;
+  uint16_t num_relocations;
+  uint16_t num_line_numbers;
+  uint32_t characteristics;
+};
+
+#define PE32_SCN_CNT_CODE              0x00000020
+#define PE32_SCN_CNT_INITIALIZED_DATA  0x00000040
+#define PE32_SCN_MEM_DISCARDABLE       0x02000000
+#define PE32_SCN_MEM_EXECUTE           0x20000000
+#define PE32_SCN_MEM_READ              0x40000000
+#define PE32_SCN_MEM_WRITE             0x80000000
+
+struct pe32_dos_header
+{
+  uint16_t  magic;    // Magic number
+  uint16_t  cblp;     // Bytes on last page of file
+  uint16_t  cp;       // Pages in file
+  uint16_t  crlc;     // Relocations
+  uint16_t  cparhdr;  // Size of header in paragraphs
+  uint16_t  minalloc; // Minimum extra paragraphs needed
+  uint16_t  maxalloc; // Maximum extra paragraphs needed
+  uint16_t  ss;       // Initial (relative) SS value
+  uint16_t  sp;       // Initial SP value
+  uint16_t  csum;     // Checksum
+  uint16_t  ip;       // Initial IP value
+  uint16_t  cs;       // Initial (relative) CS value
+  uint16_t  lfa_rlc;   // File address of relocation table
+  uint16_t  ov_no;     // Overlay number
+  uint16_t  res[4];   // Reserved words
+  uint16_t  oem_id;    // OEM identifier (for e_oeminfo)
+  uint16_t  oem_info;  // OEM information; e_oemid specific
+  uint16_t  res2[10]; // Reserved words
+  uint32_t  new_hdr_offset;
+
+  uint16_t  stub[0x20];
+};
+
+struct pe32_nt_header
+{
+  /* This is always PE\0\0.  */
+  char signature[4];
+
+  /* The COFF file header.  */
+  struct pe32_coff_header coff_header;
+
+  /* The Optional header.  */
+  struct pe32_optional_header optional_header;
+};
+
+struct pe32_base_relocation
+{
+  uint32_t page_rva;
+  uint32_t block_size;
+};
+
+struct pe32_fixup_block
+{
+  uint32_t page_rva;
+  uint32_t block_size;
+  uint16_t entries[0];
+};
+
+#define PE32_FIXUP_ENTRY(type, offset) (((type) << 12) | (offset))
+
+#define PE32_REL_BASED_ABSOLUTE            0
+#define PE32_REL_BASED_HIGHLOW     3
+#define PE32_REL_BASED_IA64_IMM64   9
+#define PE32_REL_BASED_DIR64        10
+
+#define PE32_DEBUG_TYPE_CODEVIEW 2
+struct pe32_debug_directory_entry {
+  uint32_t  characteristics;
+  uint32_t  time;
+  uint16_t  major_version;
+  uint16_t  minor_version;
+  uint32_t  type;
+  uint32_t  data_size;
+  uint32_t  rva;
+  uint32_t  file_offset;
+};
+
+#define PE32_CODEVIEW_SIGNATURE_NB10 0x3031424E  // "NB10"
+struct pe32_debug_codeview_nb10_entry {
+  uint32_t  signature;                        // "NB10"
+  uint32_t  unknown[3];
+  char filename[0];  /* Filename of .PDB */
+};
+
+
+#if 1
+#define pe32_check(name, x) extern char pe32_check_##name [x ? 1 : -1]
+#ifdef USE_PE32PLUS
+#define PE32_HEADER_SIZE 112
+#else
+#define PE32_HEADER_SIZE 96
+#endif
+
+pe32_check(optional_header, sizeof (struct pe32_optional_header) == PE32_HEADER_SIZE + PE32_NUM_DATA_DIRECTORIES * 8);
+#endif
+