Import Tristan Gingold's ia64 port
(based on patch sent to grub-devel by Tristan in 2008-01-28)
This commit is contained in:
parent
11cc30ac40
commit
2c40cc7868
32 changed files with 3791 additions and 38 deletions
45
ChangeLog.ia64
Normal file
45
ChangeLog.ia64
Normal 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.
|
|
@ -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
193
commands/efi/acpi.c
Normal 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
143
commands/efi/memmap.c
Normal 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
258
commands/efi/systab.c
Normal 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
122
conf/ia64-efi.rmk
Normal 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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
2
genmk.rb
2
genmk.rb
|
@ -115,7 +115,7 @@ UNDSYMFILES += #{undsym}
|
|||
#{@name}: #{pre_obj} #{mod_obj}
|
||||
-rm -f $@
|
||||
$(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^
|
||||
$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
|
||||
$(STRIP) $(STRIP_FLAGS) $@
|
||||
|
||||
#{pre_obj}: $(#{prefix}_DEPENDENCIES) #{objs_str}
|
||||
-rm -f $@
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
33
include/grub/ia64/efi/kernel.h
Normal file
33
include/grub/ia64/efi/kernel.h
Normal 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 */
|
||||
|
30
include/grub/ia64/efi/loader.h
Normal file
30
include/grub/ia64/efi/loader.h
Normal 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 */
|
24
include/grub/ia64/efi/misc.h
Normal file
24
include/grub/ia64/efi/misc.h
Normal 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);
|
||||
|
23
include/grub/ia64/efi/time.h
Normal file
23
include/grub/ia64/efi/time.h
Normal 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 */
|
31
include/grub/ia64/setjmp.h
Normal file
31
include/grub/ia64/setjmp.h
Normal 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
28
include/grub/ia64/time.h
Normal 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
32
include/grub/ia64/types.h
Normal 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 */
|
|
@ -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);
|
||||
|
|
23
kern/dl.c
23
kern/dl.c
|
@ -579,6 +579,29 @@ grub_dl_load_core (void *addr, grub_size_t size)
|
|||
return mod;
|
||||
}
|
||||
|
||||
void
|
||||
grub_init_module (const char *name,
|
||||
void (*init)(grub_dl_t), void (*fini)(void))
|
||||
{
|
||||
grub_dl_t mod;
|
||||
|
||||
mod = (grub_dl_t) grub_malloc (sizeof (*mod));
|
||||
if (! mod)
|
||||
return;
|
||||
|
||||
mod->name = name;
|
||||
mod->ref_count = 1;
|
||||
mod->dep = 0;
|
||||
mod->segment = 0;
|
||||
mod->init = init;
|
||||
mod->fini = fini;
|
||||
|
||||
grub_dl_call_init (mod);
|
||||
|
||||
/* Can't fail. */
|
||||
grub_dl_add (mod);
|
||||
}
|
||||
|
||||
/* Load a module from the file FILENAME. */
|
||||
grub_dl_t
|
||||
grub_dl_load_file (const char *filename)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
84
kern/ia64/efi/elf_ia64_efi.lds
Normal file
84
kern/ia64/efi/elf_ia64_efi.lds
Normal 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
59
kern/ia64/efi/init.c
Normal 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
40
kern/ia64/efi/startup.S
Normal 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
38
kern/ia64/trampoline.S
Normal 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
776
loader/ia64/efi/linux.c
Normal 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");
|
||||
}
|
107
loader/ia64/efi/linux_normal.c
Normal file
107
loader/ia64/efi/linux_normal.c
Normal 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
162
normal/ia64/longjmp.S
Normal 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
171
normal/ia64/setjmp.S
Normal 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
812
util/ia64/efi/elf2pe.c
Normal 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;
|
||||
}
|
233
util/ia64/efi/grub-install.in
Normal file
233
util/ia64/efi/grub-install.in
Normal 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
237
util/ia64/efi/pe32.h
Normal 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
|
||||
|
Loading…
Reference in a new issue