Import Tristan Gingold's ia64 port

(based on patch sent to grub-devel by Tristan in 2008-01-28)
This commit is contained in:
Robert Millan 2010-01-18 14:17:47 +00:00
parent 11cc30ac40
commit 2c40cc7868
32 changed files with 3791 additions and 38 deletions

45
ChangeLog.ia64 Normal file
View file

@ -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.

View 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) \

193
commands/efi/acpi.c Normal file
View file

@ -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));
}
}

143
commands/efi/memmap.c Normal file
View file

@ -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");
}

258
commands/efi/systab.c Normal file
View file

@ -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");
}

122
conf/ia64-efi.rmk Normal file
View file

@ -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

View 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

View 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}

View file

@ -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 $@

View file

@ -26,25 +26,27 @@
#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
{

View 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,

View file

@ -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 */

View file

@ -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 */

View file

@ -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);

View file

@ -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 */

View file

@ -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));

28
include/grub/ia64/time.h Normal file
View file

@ -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 */

32
include/grub/ia64/types.h Normal file
View file

@ -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 */

View 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);

View file

@ -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)

View file

@ -22,16 +22,14 @@
#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;
}
}

View file

@ -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)
}
}

59
kern/ia64/efi/init.c Normal file
View file

@ -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;;");
}

40
kern/ia64/efi/startup.S Normal file
View file

@ -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

38
kern/ia64/trampoline.S Normal file
View file

@ -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

776
loader/ia64/efi/linux.c Normal file
View file

@ -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");
}

View file

@ -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");
}

162
normal/ia64/longjmp.S Normal file
View file

@ -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

171
normal/ia64/setjmp.S Normal file
View file

@ -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

812
util/ia64/efi/elf2pe.c Normal file
View file

@ -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;
}

View file

@ -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

237
util/ia64/efi/pe32.h Normal file
View file

@ -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