2008-01-28 Tristan Gingold * 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. * fs/fat.c (grub_fat_find_dir): Use case insensitive string compare as filenames are not case sensitive. * include/grub/efi/efi.h: Declare grub_efi_allocate_boot_pages and grub_efi_free_boot_pages. * include/grub/misc.h: Declare grub_strcasecmp. * 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/rescue.c: Silently accept empty lines. * kern/misc.c (grub_strcasecmp): New function. * 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. diff -ruNp -x '*~' -x CVS grub2.orig/Makefile.in grub2/Makefile.in --- grub2.orig/Makefile.in 2008-01-08 11:00:42.000000000 +0100 +++ grub2/Makefile.in 2008-01-28 16:29:58.000000000 +0100 @@ -67,6 +67,7 @@ TARGET_CFLAGS = @TARGET_CFLAGS@ TARGET_CPPFLAGS = @TARGET_CPPFLAGS@ -I. -Iinclude -I$(srcdir)/include \ -Wall -W TARGET_LDFLAGS = @TARGET_LDFLAGS@ +STRIP_FLAGS=--strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment OBJCOPY = @OBJCOPY@ STRIP = @STRIP@ NM = @NM@ @@ -83,7 +84,7 @@ enable_grub_emu = @enable_grub_emu@ ### General variables. RMKFILES = $(addprefix conf/,common.rmk i386-pc.rmk powerpc-ieee1275.rmk \ - sparc64-ieee1275.rmk i386-efi.rmk) + sparc64-ieee1275.rmk i386-efi.rmk ia64-efi.rmk) MKFILES = $(patsubst %.rmk,%.mk,$(RMKFILES)) PKGLIB = $(pkglib_IMAGES) $(pkglib_MODULES) $(pkglib_PROGRAMS) \ diff -ruNp -x '*~' -x CVS grub2.orig/commands/efi/acpi.c grub2/commands/efi/acpi.c --- grub2.orig/commands/efi/acpi.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2/commands/efi/acpi.c 2008-01-28 16:29:57.000000000 +0100 @@ -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 . + */ +#include +#include +#include +#include + +static grub_uint32_t read16 (grub_uint8_t *p) +{ + return p[0] | (p[1] << 8); +} + +static grub_uint32_t read32 (grub_uint8_t *p) +{ + return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +} + +static grub_uint64_t read64 (grub_uint8_t *p) +{ + grub_uint32_t l, h; + l = read32(p); + h = read32(p + 4); + return l | (((grub_uint64_t)h) << 32); +} + +static void +disp_acpi_table (grub_uint8_t *t) +{ + int i; + grub_printf ("%c%c%c%c %4dB rev=%d OEM=", t[0], t[1], t[2], t[3], + read32 (t + 4), t[8]); + for (i = 0; i < 6; i++) + grub_printf ("%c", t[10 + i]); + grub_printf (" "); + for (i = 0; i < 8; i++) + grub_printf ("%c", t[16 + i]); + grub_printf (" V=%08lx ", read32 (t + 24)); + for (i = 0; i < 4; i++) + grub_printf ("%c", t[28 + i]); + grub_printf (" %08lx\n", read32 (t + 32)); + +} + +static void +disp_acpi_apic_table (grub_uint8_t *t) +{ + grub_uint8_t *d; + grub_uint32_t len; + grub_uint32_t flags; + + disp_acpi_table (t); + grub_printf ("Local APIC=%08lx Flags=%08lx\n", + read32 (t + 36), read32 (t + 40)); + len = read32 (t + 4); + len -= 44; + d = t + 44; + while (len > 0) + { + grub_uint32_t l = d[1]; + grub_printf (" type=%x l=%d ", d[0], l); + + switch (d[0]) + { + case 2: + grub_printf ("Int Override bus=%x src=%x GSI=%08x Flags=%04x", + d[2], d[3], read32 (d + 4), read16 (d + 8)); + break; + case 6: + grub_printf ("IOSAPIC Id=%02x GSI=%08x Addr=%016llx", + d[2], read32 (d + 4), read64 (d + 8)); + break; + case 7: + flags = read32 (d + 8); + grub_printf ("LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x", + d[2], d[3], d[4], flags); + if (flags & 1) + grub_printf (" Enabled"); + else + grub_printf (" Disabled"); + if (l >= 17) + grub_printf ("\n" + " UID val=%08x, Str=%s", read32 (d + 12), d + 16); + break; + case 8: + grub_printf ("Platform INT flags=%04x type=%02x (", + read16 (d + 2), d[4]); + if (d[4] <= 3) + { + static const char * const platint_type[4] = + {"Nul", "PMI", "INIT", "CPEI"}; + grub_printf ("%s", platint_type[d[4]]); + } + else + grub_printf ("??"); + grub_printf (") ID=%02x EID=%02x\n", d[5], d[6]); + grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x", + d[7], read32 (d + 8), read32 (d + 12)); + break; + default: + grub_printf (" ??"); + } + grub_printf ("\n"); + d += l; + len -= l; + } +} + +static void +disp_acpi_xsdt_table (grub_uint8_t *t) +{ + grub_uint32_t len; + grub_uint8_t *desc; + + disp_acpi_table (t); + len = read32 (t + 4) - 36; + desc = t + 36; + while (len > 0) + { + t = read64 (desc); + + if (t[0] == 'A' && t[1] == 'P' && t[2] == 'I' && t[3] == 'C') + disp_acpi_apic_table (t); + else + disp_acpi_table (t); + desc += 8; + len -= 8; + } +} + +static void +disp_acpi_rsdt_table (grub_uint8_t *t) +{ + grub_uint32_t len; + grub_uint8_t *desc; + + disp_acpi_table (t); + len = read32 (t + 4) - 36; + desc = t + 36; + while (len > 0) + { + t = read32 (desc); + + if (t != NULL) + disp_acpi_table (t); + desc += 4; + len -= 4; + } +} + +void +disp_acpi_rsdp_table (grub_uint8_t *rsdp) +{ + grub_uint8_t *t = rsdp; + int i; + grub_uint8_t *xsdt; + + grub_printf ("RSDP signature:"); + for (i = 0; i < 8; i++) + grub_printf ("%c", t[i]); + grub_printf (" chksum:%02x, OEM-ID: ", t[8]); + for (i = 0; i < 6; i++) + grub_printf ("%c", t[9 + i]); + grub_printf (" rev=%d\n", t[15]); + grub_printf ("RSDT=%08lx", read32 (t + 16)); + if (t[15] == 2) + { + xsdt = read64 (t + 24); + grub_printf (" len=%d XSDT=%016llx\n", read32 (t + 20), xsdt); + grub_printf ("\n"); + disp_acpi_xsdt_table (xsdt); + } + else + { + grub_printf ("\n"); + disp_acpi_rsdt_table (read32 (t + 16)); + } +} diff -ruNp -x '*~' -x CVS grub2.orig/commands/efi/memmap.c grub2/commands/efi/memmap.c --- grub2.orig/commands/efi/memmap.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2/commands/efi/memmap.c 2008-01-28 16:29:57.000000000 +0100 @@ -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 . + */ +#include +#include +#include +#include +#include +#include + +#define ADD_MEMORY_DESCRIPTOR(desc, size) \ + ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) + +static grub_err_t +grub_cmd_memmap (struct grub_arg_list *state, int argc, char **args) +{ + grub_efi_uintn_t map_size; + grub_efi_memory_descriptor_t *memory_map; + grub_efi_memory_descriptor_t *memory_map_end; + grub_efi_memory_descriptor_t *desc; + grub_efi_uintn_t desc_size; + + map_size = 0; + if (grub_efi_get_memory_map (&map_size, NULL, NULL, &desc_size, 0) < 0) + return 0; + + memory_map = grub_malloc (map_size); + if (memory_map == NULL) + return 0; + if (grub_efi_get_memory_map (&map_size, memory_map, NULL, &desc_size, 0) < 0) + goto fail; + + grub_set_more (1); + + grub_printf + ("Type Physical start - end #Pages " + " Size Attributes\n"); + memory_map_end = ADD_MEMORY_DESCRIPTOR(memory_map, map_size); + for (desc = memory_map; + desc < memory_map_end; + desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size)) + { + grub_efi_uintn_t size; + grub_efi_uint64_t attr; + static const char types_str[][9] = + { + "reserved", + "ldr-code", + "ldr-data", + "BS-code ", + "BS-data ", + "RT-code ", + "RT-data ", + "conv-mem", + "unusable", + "ACPI-rec", + "ACPI-nvs", + "MMIO ", + "IO-ports", + "PAL-code" + }; + if (desc->type < sizeof (types_str) / sizeof (types_str[0])) + grub_printf ("%s ", types_str[desc->type]); + else + grub_printf ("Unk %02x ", desc->type); + + grub_printf (" %016llx-%016llx %08lx", + desc->physical_start, + desc->physical_start + (desc->num_pages << 12) - 1, + desc->num_pages); + + size = desc->num_pages << (12 - 10); + if (size < 1024) + grub_printf (" %4uKB", size); + else + { + size /= 1024; + if (size < 1024) + grub_printf (" %4uMB", size); + else + { + size /= 1024; + grub_printf (" %4uGB", size); + } + } + + attr = desc->attribute; + if (attr & GRUB_EFI_MEMORY_RUNTIME) + grub_printf (" RT"); + if (attr & GRUB_EFI_MEMORY_UC) + grub_printf (" UC"); + if (attr & GRUB_EFI_MEMORY_WC) + grub_printf (" WC"); + if (attr & GRUB_EFI_MEMORY_WT) + grub_printf (" WT"); + if (attr & GRUB_EFI_MEMORY_WB) + grub_printf (" WB"); + if (attr & GRUB_EFI_MEMORY_UCE) + grub_printf (" UCE"); + if (attr & GRUB_EFI_MEMORY_WP) + grub_printf (" WP"); + if (attr & GRUB_EFI_MEMORY_RP) + grub_printf (" RP"); + if (attr & GRUB_EFI_MEMORY_XP) + grub_printf (" XP"); + + grub_printf ("\n"); + } + + grub_set_more (0); + + fail: + grub_free (memory_map); + return 0; +} + +GRUB_MOD_INIT(memmap) +{ + (void)mod; /* To stop warning. */ + grub_register_command ("memmap", grub_cmd_memmap, GRUB_COMMAND_FLAG_BOTH, + "memmap", + "Display memory map.", NULL); +} + +GRUB_MOD_FINI(memmap) +{ + grub_unregister_command ("memmap"); +} diff -ruNp -x '*~' -x CVS grub2.orig/commands/efi/systab.c grub2/commands/efi/systab.c --- grub2.orig/commands/efi/systab.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2/commands/efi/systab.c 2008-01-28 16:29:57.000000000 +0100 @@ -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 . + */ +#include +#include +#include +#include +#include +#include + +#define ACPI_20_TABLE_GUID \ +{0x8868e871,0xe4f1,0x11d3,{0xbc,0x22,0x0,0x80,0xc7,0x3c,0x88,0x81}} +#define ACPI_TABLE_GUID \ +{0xeb9d2d30,0x2d88,0x11d3,{0x9a,0x16,0x0,0x90,0x27,0x3f,0xc1,0x4d}} +#define SAL_SYSTEM_TABLE_GUID \ +{0xeb9d2d32,0x2d88,0x11d3,{0x9a,0x16,0x0,0x90,0x27,0x3f,0xc1,0x4d}} +#define SMBIOS_TABLE_GUID \ +{0xeb9d2d31,0x2d88,0x11d3,{0x9a,0x16,0x0,0x90,0x27,0x3f,0xc1,0x4d}} +#define MPS_TABLE_GUID \ +{0xeb9d2d2f,0x2d88,0x11d3,{0x9a,0x16,0x0,0x90,0x27,0x3f,0xc1,0x4d}} +#define HCDP_TABLE_GUID \ +{0xf951938d,0x620b,0x42ef,{0x82,0x79,0xa8,0x4b,0x79,0x61,0x78,0x98}} + +struct guid_mapping +{ + grub_efi_guid_t guid; + const char *name; + void (*disp)(struct guid_mapping *map, void *table); +}; + +static void disp_sal (struct guid_mapping *map, void *table); +static void disp_acpi (struct guid_mapping *map, void *table); + +static const struct guid_mapping guid_mappings[] = + { + { ACPI_20_TABLE_GUID, "ACPI-2.0", disp_acpi}, + { ACPI_TABLE_GUID, "ACPI-1.0", disp_acpi}, + { SAL_SYSTEM_TABLE_GUID, "SAL", disp_sal}, + { SMBIOS_TABLE_GUID, "SMBIOS",NULL}, + { MPS_TABLE_GUID, "MPS", NULL}, + { HCDP_TABLE_GUID, "HCDP", NULL} + }; + +struct sal_system_table +{ + grub_uint32_t signature; + grub_uint32_t total_table_len; + grub_uint16_t sal_rev; + grub_uint16_t entry_count; + grub_uint8_t checksum; + grub_uint8_t reserved1[7]; + grub_uint16_t sal_a_version; + grub_uint16_t sal_b_version; + grub_uint8_t oem_id[32]; + grub_uint8_t product_id[32]; + grub_uint8_t reserved2[8]; +}; + +static void +disp_sal (struct guid_mapping *map, void *table) +{ + struct sal_system_table *t = table; + grub_uint8_t *desc = table; + grub_uint32_t len, l; + + grub_printf ("SAL rev: %02x, signature: %x, len:%x\n", + t->sal_rev, t->signature, t->total_table_len); + grub_printf ("nbr entry: %d, chksum: %02x, SAL version A: %02x B: %02x\n", + t->entry_count, t->checksum, + t->sal_a_version, t->sal_b_version); + grub_printf ("OEM-ID: %-32s\n", t->oem_id); + grub_printf ("Product-ID: %-32s\n", t->product_id); + + desc += sizeof (struct sal_system_table); + len = t->total_table_len - sizeof (struct sal_system_table); + while (len > 0) + { + switch (*desc) + { + case 0: + l = 48; + grub_printf (" Entry point: PAL=%016lx SAL=%016lx GP=%016lx\n", + *(grub_uint64_t*)(desc + 8), + *(grub_uint64_t*)(desc + 16), + *(grub_uint64_t*)(desc + 24)); + break; + case 1: + l = 32; + grub_printf (" Memory descriptor entry addr=%016llx len=%uKB\n", + *(grub_uint64_t*)(desc + 8), + *(grub_uint32_t*)(desc + 16) * 4); + grub_printf (" sal_used=%d attr=%x AR=%x attr_mask=%x " + "type=%x usage=%x\n", + desc[1], desc[2], desc[3], desc[4], desc[5], desc[6]); + break; + case 2: + l = 16; + grub_printf (" Platform features: %02x", desc[1]); + if (desc[1] & 0x01) + grub_printf (" BusLock"); + if (desc[1] & 0x02) + grub_printf (" IrqRedirect"); + if (desc[1] & 0x04) + grub_printf (" IPIRedirect"); + grub_printf ("\n"); + break; + case 3: + l = 32; + grub_printf (" TR type=%d num=%d va=%016llx pte=%016llx\n", + desc[1], desc[2], + *(grub_uint64_t *)(desc + 8), + *(grub_uint64_t *)(desc + 16)); + break; + case 4: + l = 16; + grub_printf (" PTC coherence nbr=%d addr=%016llx\n", + desc[1], *(grub_uint64_t *)(desc + 8)); + break; + case 5: + l = 16; + grub_printf (" AP wake-up: mec=%d vect=%x\n", + desc[1], *(grub_uint64_t *)(desc + 8)); + break; + default: + grub_printf (" unknown entry %d\n", *desc); + return; + } + desc += l; + len -= l; + } +} + +static void +disp_acpi (struct guid_mapping *map, void *table) +{ + disp_acpi_rsdp_table (table); +} + +static void +disp_systab (void) +{ + grub_efi_char16_t *vendor; + const grub_efi_system_table_t *st = grub_efi_system_table; + grub_efi_configuration_table_t *t; + unsigned int i; + + grub_printf ("Signature: %016llx revision: %08x\n", + st->hdr.signature, st->hdr.revision); + grub_printf ("Vendor: "); + for (vendor = st->firmware_vendor; *vendor; vendor++) + grub_printf ("%c", *vendor); + grub_printf (", Version=%x\n", st->firmware_revision); + + grub_printf ("%ld tables:\n", st->num_table_entries); + t = st->configuration_table; + for (i = 0; i < st->num_table_entries; i++) + { + unsigned int j; + + grub_printf ("%016llx ", (grub_uint64_t)t->vendor_table); + + grub_printf ("%08x-%04x-%04x-", + t->vendor_guid.data1, t->vendor_guid.data2, + t->vendor_guid.data3); + for (j = 0; j < 8; j++) + grub_printf ("%02x", t->vendor_guid.data4[j]); + + for (j = 0; j < sizeof (guid_mappings)/sizeof(guid_mappings[0]); j++) + if (grub_memcmp (&guid_mappings[j].guid, &t->vendor_guid, + sizeof (grub_efi_guid_t)) == 0) + grub_printf (" %s", guid_mappings[j].name); + + grub_printf ("\n"); + t++; + } +} + +static void +disp_systab_entry (const char *name) +{ + const grub_efi_system_table_t *st = grub_efi_system_table; + grub_efi_configuration_table_t *t; + unsigned int i; + struct guid_mapping *map; + + map = NULL; + for (i = 0; i < sizeof (guid_mappings)/sizeof(guid_mappings[0]); i++) + if (grub_strcmp (guid_mappings[i].name, name) == 0) + { + map = &guid_mappings[i]; + break; + } + if (map == NULL) + { + grub_printf ("System table '%s' unknown\n", name); + return; + } + if (map->disp == NULL) + { + grub_printf ("Don't know how to display table '%s'\n", name); + return; + } + t = st->configuration_table; + for (i = 0; i < st->num_table_entries; i++) + { + if (grub_memcmp (&map->guid, &t->vendor_guid, + sizeof (grub_efi_guid_t)) == 0) + { + grub_set_more (1); + (*map->disp)(map, t->vendor_table); + grub_set_more (0); + return; + } + t++; + } + grub_printf ("Systab '%s' not found\n", map->name); +} + +static grub_err_t +grub_cmd_systab (struct grub_arg_list *state, int argc, char **args) +{ + int i; + + if (argc == 0) + disp_systab (); + else + for (i = 0; i < argc; i++) + disp_systab_entry (args[i]); + return 0; +} + +GRUB_MOD_INIT(systab) +{ + (void)mod; /* To stop warning. */ + grub_register_command ("systab", grub_cmd_systab, GRUB_COMMAND_FLAG_BOTH, + "systab [NAME]", + "Display EFI system table.", NULL); +} + +GRUB_MOD_FINI(systab) +{ + grub_unregister_command ("systab"); +} diff -ruNp -x '*~' -x CVS grub2.orig/conf/ia64-efi.rmk grub2/conf/ia64-efi.rmk --- grub2.orig/conf/ia64-efi.rmk 1970-01-01 01:00:00.000000000 +0100 +++ grub2/conf/ia64-efi.rmk 2008-01-28 16:29:57.000000000 +0100 @@ -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 diff -ruNp -x '*~' -x CVS grub2.orig/configure.ac grub2/configure.ac --- grub2.orig/configure.ac 2008-01-15 21:05:44.000000000 +0100 +++ grub2/configure.ac 2008-01-28 16:29:57.000000000 +0100 @@ -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 diff -ruNp -x '*~' -x CVS grub2.orig/fs/fat.c grub2/fs/fat.c --- grub2.orig/fs/fat.c 2007-08-02 20:40:36.000000000 +0200 +++ grub2/fs/fat.c 2008-01-28 16:29:57.000000000 +0100 @@ -568,7 +568,7 @@ grub_fat_find_dir (grub_disk_t disk, str continue; } - if (grub_strcmp (dirname, filename) == 0) + if (grub_strcasecmp (dirname, filename) == 0) { if (call_hook) hook (filename, dir.attr & GRUB_FAT_ATTR_DIRECTORY); @@ -601,7 +601,7 @@ grub_fat_find_dir (grub_disk_t disk, str if (hook (filename, dir.attr & GRUB_FAT_ATTR_DIRECTORY)) break; } - else if (grub_strcmp (dirname, filename) == 0) + else if (grub_strcasecmp (dirname, filename) == 0) { if (call_hook) hook (filename, dir.attr & GRUB_FAT_ATTR_DIRECTORY); diff -ruNp -x '*~' -x CVS grub2.orig/geninit.sh grub2/geninit.sh --- grub2.orig/geninit.sh 2007-07-22 21:17:21.000000000 +0200 +++ grub2/geninit.sh 2008-01-28 16:29:57.000000000 +0100 @@ -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} diff -ruNp -x '*~' -x CVS grub2.orig/genmk.rb grub2/genmk.rb --- grub2.orig/genmk.rb 2008-01-25 23:33:56.000000000 +0100 +++ grub2/genmk.rb 2008-01-28 16:29:57.000000000 +0100 @@ -115,7 +115,7 @@ UNDSYMFILES += #{undsym} address@hidden: #{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 $@ diff -ruNp -x '*~' -x CVS grub2.orig/include/grub/dl.h grub2/include/grub/dl.h --- grub2.orig/include/grub/dl.h 2007-07-22 01:32:21.000000000 +0200 +++ grub2/include/grub/dl.h 2008-01-28 16:29:57.000000000 +0100 @@ -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 { diff -ruNp -x '*~' -x CVS grub2.orig/include/grub/efi/efi.h grub2/include/grub/efi/efi.h --- grub2.orig/include/grub/efi/efi.h 2007-07-22 01:32:23.000000000 +0200 +++ grub2/include/grub/efi/efi.h 2008-01-28 16:29:57.000000000 +0100 @@ -42,6 +42,13 @@ EXPORT_FUNC(grub_efi_allocate_pages) (gr grub_efi_uintn_t pages); void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address, grub_efi_uintn_t pages); +void * +EXPORT_FUNC(grub_efi_allocate_boot_pages) (grub_efi_physical_address_t address, + grub_efi_uintn_t pages); +void +EXPORT_FUNC(grub_efi_free_boot_pages) (grub_efi_physical_address_t address, + grub_efi_uintn_t pages); + int EXPORT_FUNC(grub_efi_get_memory_map) (grub_efi_uintn_t *memory_map_size, grub_efi_memory_descriptor_t *memory_map, diff -ruNp -x '*~' -x CVS grub2.orig/include/grub/ia64/efi/kernel.h grub2/include/grub/ia64/efi/kernel.h --- grub2.orig/include/grub/ia64/efi/kernel.h 1970-01-01 01:00:00.000000000 +0100 +++ grub2/include/grub/ia64/efi/kernel.h 2008-01-28 16:29:57.000000000 +0100 @@ -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 . + */ + +#ifndef GRUB_MACHINE_KERNEL_HEADER +#define GRUB_MACHINE_KERNEL_HEADER 1 + +/* The prefix which points to the directory where GRUB modules and its + configuration file are located. */ +extern char grub_prefix[]; + +/* The offset of GRUB_PREFIX. */ +#define GRUB_KERNEL_MACHINE_PREFIX 0x8 + +/* End of the data section. */ +#define GRUB_KERNEL_MACHINE_DATA_END 0x50 + +#endif /* ! GRUB_MACHINE_KERNEL_HEADER */ + diff -ruNp -x '*~' -x CVS grub2.orig/include/grub/ia64/efi/loader.h grub2/include/grub/ia64/efi/loader.h --- grub2.orig/include/grub/ia64/efi/loader.h 1970-01-01 01:00:00.000000000 +0100 +++ grub2/include/grub/ia64/efi/loader.h 2008-01-28 16:29:57.000000000 +0100 @@ -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 . + */ + +#ifndef GRUB_LOADER_MACHINE_HEADER +#define GRUB_LOADER_MACHINE_HEADER 1 + +/* It is necessary to export these functions, because normal mode commands + reuse rescue mode commands. */ +void grub_rescue_cmd_linux (int argc, char *argv[]); +void grub_rescue_cmd_initrd (int argc, char *argv[]); +void grub_rescue_cmd_module (int argc, char *argv[]); +void grub_rescue_cmd_relocate (int argc, char *argv[]); +void grub_rescue_cmd_fpswa (int argc, char *argv[]); + +#endif /* ! GRUB_LOADER_MACHINE_HEADER */ diff -ruNp -x '*~' -x CVS grub2.orig/include/grub/ia64/efi/misc.h grub2/include/grub/ia64/efi/misc.h --- grub2.orig/include/grub/ia64/efi/misc.h 1970-01-01 01:00:00.000000000 +0100 +++ grub2/include/grub/ia64/efi/misc.h 2008-01-28 16:29:57.000000000 +0100 @@ -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 . + */ + +void EXPORT_FUNC (memset) (void); +void EXPORT_FUNC (__ia64_trampoline) (void); +void EXPORT_FUNC (grub_init_modules) (void); + +extern unsigned long EXPORT_VAR (__gp); + diff -ruNp -x '*~' -x CVS grub2.orig/include/grub/ia64/efi/time.h grub2/include/grub/ia64/efi/time.h --- grub2.orig/include/grub/ia64/efi/time.h 1970-01-01 01:00:00.000000000 +0100 +++ grub2/include/grub/ia64/efi/time.h 2008-01-28 16:29:57.000000000 +0100 @@ -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 . + */ +#ifndef GRUB_MACHINE_TIME_HEADER +#define GRUB_MACHINE_TIME_HEADER 1 + +#include + +#endif /* ! GRUB_MACHINE_TIME_HEADER */ diff -ruNp -x '*~' -x CVS grub2.orig/include/grub/ia64/setjmp.h grub2/include/grub/ia64/setjmp.h --- grub2.orig/include/grub/ia64/setjmp.h 1970-01-01 01:00:00.000000000 +0100 +++ grub2/include/grub/ia64/setjmp.h 2008-01-28 16:29:57.000000000 +0100 @@ -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 . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* User code must not depend on the internal representation of jmp_buf. */ + +#define _JBLEN 70 + +/* the __jmp_buf element type should be __float80 per ABI... */ +typedef long grub_jmp_buf[_JBLEN] __attribute__ ((aligned (16))); /* guarantees 128-bit alignment! */ + +#define grub_setjmp setjmp +#define grub_longjmp longjmp + +int grub_setjmp (grub_jmp_buf env); +void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn)); diff -ruNp -x '*~' -x CVS grub2.orig/include/grub/ia64/time.h grub2/include/grub/ia64/time.h --- grub2.orig/include/grub/ia64/time.h 1970-01-01 01:00:00.000000000 +0100 +++ grub2/include/grub/ia64/time.h 2008-01-28 16:29:57.000000000 +0100 @@ -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 . + */ + +#ifndef KERNEL_CPU_TIME_HEADER +#define KERNEL_CPU_TIME_HEADER 1 + +static __inline void +grub_cpu_idle (void) +{ + /* FIXME: not implemented */ +} + +#endif /* ! KERNEL_CPU_TIME_HEADER */ diff -ruNp -x '*~' -x CVS grub2.orig/include/grub/ia64/types.h grub2/include/grub/ia64/types.h --- grub2.orig/include/grub/ia64/types.h 1970-01-01 01:00:00.000000000 +0100 +++ grub2/include/grub/ia64/types.h 2008-01-28 16:29:57.000000000 +0100 @@ -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 . + */ + +#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 */ diff -ruNp -x '*~' -x CVS grub2.orig/include/grub/kernel.h grub2/include/grub/kernel.h --- grub2.orig/include/grub/kernel.h 2008-01-21 01:04:04.000000000 +0100 +++ grub2/include/grub/kernel.h 2008-01-28 16:29:57.000000000 +0100 @@ -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); diff -ruNp -x '*~' -x CVS grub2.orig/include/grub/misc.h grub2/include/grub/misc.h --- grub2.orig/include/grub/misc.h 2007-11-05 15:54:00.000000000 +0100 +++ grub2/include/grub/misc.h 2008-01-28 16:29:57.000000000 +0100 @@ -46,6 +46,7 @@ int EXPORT_FUNC(grub_memcmp) (const void int EXPORT_FUNC(grub_strcmp) (const char *s1, const char *s2); int EXPORT_FUNC(grub_strncmp) (const char *s1, const char *s2, grub_size_t n); int EXPORT_FUNC(grub_strncasecmp) (const char *s1, const char *s2, int c); +int EXPORT_FUNC(grub_strcasecmp) (const char *s1, const char *s2); char *EXPORT_FUNC(grub_strchr) (const char *s, int c); char *EXPORT_FUNC(grub_strrchr) (const char *s, int c); int EXPORT_FUNC(grub_strword) (const char *s, const char *w); diff -ruNp -x '*~' -x CVS grub2.orig/kern/dl.c grub2/kern/dl.c --- grub2.orig/kern/dl.c 2008-01-26 21:34:58.000000000 +0100 +++ grub2/kern/dl.c 2008-01-28 16:29:58.000000000 +0100 @@ -579,6 +579,29 @@ grub_dl_load_core (void *addr, grub_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) diff -ruNp -x '*~' -x CVS grub2.orig/kern/efi/mm.c grub2/kern/efi/mm.c --- grub2.orig/kern/efi/mm.c 2007-07-22 01:32:26.000000000 +0200 +++ grub2/kern/efi/mm.c 2008-01-28 16:29:58.000000000 +0100 @@ -22,16 +22,14 @@ #include #include +//#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_ #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_physic { /* 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_a 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_desc 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_desc grub_mm_init_region (addr, PAGES_TO_BYTES (pages)); +#ifdef DEBUG_MM + grub_printf ("mm: add %lu pages from %p\n", pages, addr); +#endif + required_pages -= pages; if (required_pages == 0) break; @@ -344,6 +366,8 @@ grub_efi_mm_init (void) grub_efi_uintn_t desc_size; grub_efi_uint64_t total_pages; grub_efi_uint64_t required_pages; + grub_efi_uintn_t memory_map_size; + int res; /* First of all, allocate pages to maintain allocations. */ allocated_pages @@ -352,26 +376,35 @@ grub_efi_mm_init (void) grub_fatal ("cannot allocate memory"); grub_memset (allocated_pages, 0, ALLOCATED_PAGES_SIZE); - + /* Prepare a memory region to store two memory maps. */ - memory_map = grub_efi_allocate_pages (0, - 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + memory_map_size = 0; + res = grub_efi_get_memory_map (&memory_map_size, NULL, 0, &desc_size, 0); + if (res != 0) + grub_fatal ("cannot get memory map size"); + + /* Add space for a few more entries as allocating pages can increase + memory map size. */ + memory_map_size += 4 * desc_size; + + memory_map = grub_efi_allocate_pages + (0, 2 * BYTES_TO_PAGES (memory_map_size)); if (! memory_map) grub_fatal ("cannot allocate memory"); - filtered_memory_map = NEXT_MEMORY_DESCRIPTOR (memory_map, MEMORY_MAP_SIZE); + filtered_memory_map = NEXT_MEMORY_DESCRIPTOR (memory_map, memory_map_size); /* Obtain descriptors for available memory. */ - map_size = MEMORY_MAP_SIZE; + map_size = memory_map_size; - if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) < 0) + if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) <= 0) grub_fatal ("cannot get memory map"); memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size); filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map, desc_size, memory_map_end); - + /* By default, request a quarter of the available memory. */ total_pages = get_total_pages (filtered_memory_map, desc_size, filtered_memory_map_end); @@ -391,7 +424,7 @@ grub_efi_mm_init (void) #if 0 /* For debug. */ - map_size = MEMORY_MAP_SIZE; + map_size = memory_map_size; if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) < 0) grub_fatal ("cannot get memory map"); @@ -404,7 +437,7 @@ grub_efi_mm_init (void) /* Release the memory maps. */ grub_efi_free_pages ((grub_addr_t) memory_map, - 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + 2 * BYTES_TO_PAGES (memory_map_size)); } void @@ -420,10 +453,13 @@ grub_efi_mm_fini (void) p = allocated_pages + i; if (p->addr != 0) - grub_efi_free_pages ((grub_addr_t) p->addr, p->num_pages); + { + grub_efi_free_pages ((grub_addr_t) p->addr, p->num_pages); + } } grub_efi_free_pages ((grub_addr_t) allocated_pages, BYTES_TO_PAGES (ALLOCATED_PAGES_SIZE)); + allocated_pages = 0; } } diff -ruNp -x '*~' -x CVS grub2.orig/kern/ia64/efi/elf_ia64_efi.lds grub2/kern/ia64/efi/elf_ia64_efi.lds --- grub2.orig/kern/ia64/efi/elf_ia64_efi.lds 1970-01-01 01:00:00.000000000 +0100 +++ grub2/kern/ia64/efi/elf_ia64_efi.lds 2008-01-28 16:29:58.000000000 +0100 @@ -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 . + */ +OUTPUT_FORMAT("elf64-ia64-little") +OUTPUT_ARCH(ia64) +ENTRY(_start) +SECTIONS +{ + . = 0x240; + .text : + { + *(.text) + *(.text.*) + *(.rodata) + *(.rodata.*) + /* Reserve space for the entry point descriptor. */ + . = ALIGN(16); + QUAD(0) + QUAD(0) + } + . = ALIGN(0x20); + .got : + { + *(.got.plt) + *(.got) + . = ALIGN(0x10); + } + .opd : + { + *(.opd) + } + .sdata : + { + *(.srodata) + *(.sdata) + *(.sbss) + *(.scommon) + . = ALIGN(0x10); + } + .data : + { + *(.data*) + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(0x10); + } + .dynamic : { *(.dynamic) } + + . = ALIGN(4096); + .interp : { *(.interp) } + .plt : { *(.plt) } + .rela : + { + *(.rela.text*) + *(.rela.data*) + *(.rela.sdata) + *(.rela.got) + } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + /DISCARD/ : + { + *(.IA_64.unwind*) + *(.IA64.unwind*) + *(.moddeps) + *(.modname) + } +} diff -ruNp -x '*~' -x CVS grub2.orig/kern/ia64/efi/init.c grub2/kern/ia64/efi/init.c --- grub2.orig/kern/ia64/efi/init.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2/kern/ia64/efi/init.c 2008-01-28 16:29:58.000000000 +0100 @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +void +grub_machine_init (void) +{ + grub_efi_init (); + grub_init_modules (); +} + +void +grub_machine_fini (void) +{ + grub_efi_fini (); +} + +void +grub_machine_set_prefix (void) +{ + grub_efi_set_prefix (); +} + +void +grub_arch_sync_caches (void *address, grub_size_t len) +{ + /* Cache line length is at least 32. */ + grub_uint64_t a = (grub_uint64_t)address & ~0x1f; + + /* Flush data. */ + for (len = (len + 31) & ~0x1f; len > 0; len -= 0x20, a += 0x20) + asm volatile ("fc.i %0" : : "r" (a)); + /* Sync and serialize. Maybe extra. */ + asm volatile (";; sync.i;; srlz.i;;"); +} diff -ruNp -x '*~' -x CVS grub2.orig/kern/ia64/efi/startup.S grub2/kern/ia64/efi/startup.S --- grub2.orig/kern/ia64/efi/startup.S 1970-01-01 01:00:00.000000000 +0100 +++ grub2/kern/ia64/efi/startup.S 2008-01-28 16:29:58.000000000 +0100 @@ -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 . + */ + .text + .psr abi64 + .psr lsb + .lsb + + .global _start + .proc _start +_start: + alloc loc0=ar.pfs,2,4,0,0 + mov loc1=rp + addl address@hidden(grub_efi_image_handle),gp + addl address@hidden(grub_efi_system_table),gp + ;; + st8 [loc2]=in0 + st8 [loc3]=in1 + br.call.sptk.few rp=grub_main + ;; + mov ar.pfs=loc0 + mov rp=loc1 + ;; + br.ret.sptk.few rp + + .endp _start diff -ruNp -x '*~' -x CVS grub2.orig/kern/ia64/trampoline.S grub2/kern/ia64/trampoline.S --- grub2.orig/kern/ia64/trampoline.S 1970-01-01 01:00:00.000000000 +0100 +++ grub2/kern/ia64/trampoline.S 2008-01-28 16:29:58.000000000 +0100 @@ -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 . + */ + .text + .psr abi64 + .psr lsb + .lsb + + .proc __ia64_trampoline + .global __ia64_trampoline +__ia64_trampoline: + // Read address of the real descriptor + ld8 r2=[r1],8 + ;; + // Read chain + ld8 r15=[r1] + // Read pc + ld8 r3=[r2],8 + ;; + // Read gp + ld8 r1=[r2] + mov b6=r3 + br.many b6 + .endp __ia64_trampoline diff -ruNp -x '*~' -x CVS grub2.orig/kern/misc.c grub2/kern/misc.c --- grub2.orig/kern/misc.c 2008-01-15 18:22:09.000000000 +0100 +++ grub2/kern/misc.c 2008-01-28 16:29:58.000000000 +0100 @@ -193,6 +193,26 @@ grub_strcmp (const char *s1, const char } int +grub_strcasecmp (const char *s1, const char *s2) +{ + char c1, c2; + + while (*s1 && *s2) + { + c1 = grub_tolower (*s1); + c2 = grub_tolower (*s2); + if (c1 != c2) + return (int) c1 - (int) c2; + + s1++; + s2++; + } + + /* One of these is 0! */ + return (int) *s1 - (int) *s2; +} + +int grub_strncmp (const char *s1, const char *s2, grub_size_t n) { if (n == 0) diff -ruNp -x '*~' -x CVS grub2.orig/kern/rescue.c grub2/kern/rescue.c --- grub2.orig/kern/rescue.c 2007-09-03 22:28:23.000000000 +0200 +++ grub2/kern/rescue.c 2008-01-28 16:29:58.000000000 +0100 @@ -659,6 +659,8 @@ grub_enter_rescue_mode (void) /* Get a command line. */ grub_rescue_get_command_line ("grub rescue> "); + if (line[0] == 0) + continue; if (grub_parser_split_cmdline (line, getline, &n, &args) || n < 0) continue; diff -ruNp -x '*~' -x CVS grub2.orig/loader/ia64/efi/linux.c grub2/loader/ia64/efi/linux.c --- grub2.orig/loader/ia64/efi/linux.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2/loader/ia64/efi/linux.c 2008-01-28 16:29:58.000000000 +0100 @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +#include +#include +#include +#include + +#define ALIGN_MIN (256*1024*1024) + +#define GRUB_ELF_SEARCH 1024 + +#define BOOT_PARAM_SIZE 16384 + +struct ia64_boot_param { + grub_uint64_t command_line; /* physical address of command line. */ + grub_uint64_t efi_systab; /* physical address of EFI system table */ + grub_uint64_t efi_memmap; /* physical address of EFI memory map */ + grub_uint64_t efi_memmap_size; /* size of EFI memory map */ + grub_uint64_t efi_memdesc_size; /* size of an EFI memory map descriptor */ + grub_uint32_t efi_memdesc_version; /* memory descriptor version */ + struct { + grub_uint16_t num_cols; /* number of columns on console output dev */ + grub_uint16_t num_rows; /* number of rows on console output device */ + grub_uint16_t orig_x; /* cursor's x position */ + grub_uint16_t orig_y; /* cursor's y position */ + } console_info; + grub_uint64_t fpswa; /* physical address of the fpswa interface */ + grub_uint64_t initrd_start; + grub_uint64_t initrd_size; + grub_uint64_t domain_start; /* boot domain address. */ + grub_uint64_t domain_size; /* how big is the boot domain */ + grub_uint64_t modules_chain; + grub_uint64_t modules_nbr; +}; + +struct ia64_boot_module { + grub_uint64_t mod_start; + grub_uint64_t mod_end; + + /* Module command line */ + grub_uint64_t cmdline; + + grub_uint64_t next; +}; + +typedef struct { + grub_uint32_t revision; + grub_uint32_t reserved; + void *fpswa; +} fpswa_interface_t; +static fpswa_interface_t *fpswa; + +#define NEXT_MEMORY_DESCRIPTOR(desc, size) \ + ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) + +static grub_dl_t my_mod; + +static int loaded; + +/* Kernel base and size. */ +static void *kernel_mem; +static grub_efi_uintn_t kernel_pages; +static grub_uint64_t entry; + +/* Initrd base and size. */ +static void *initrd_mem; +static grub_efi_uintn_t initrd_pages; +static grub_efi_uintn_t initrd_size; + +static struct ia64_boot_param *boot_param; +static grub_efi_uintn_t boot_param_pages; +static struct ia64_boot_module *last_module = NULL; + +/* Can linux kernel be relocated ? */ +#define RELOCATE_OFF 0 /* No. */ +#define RELOCATE_ON 1 /* Yes. */ +#define RELOCATE_FORCE 2 /* Always - used to debug. */ +static int relocate = RELOCATE_OFF; + +static inline grub_size_t +page_align (grub_size_t size) +{ + return (size + (1 << 12) - 1) & (~((1 << 12) - 1)); +} + +static void +query_fpswa (void) +{ + grub_efi_handle_t fpswa_image; + grub_efi_boot_services_t *bs; + grub_efi_status_t status; + grub_efi_uintn_t size; + static const grub_efi_guid_t fpswa_protocol = + { 0xc41b6531, 0x97b9, 0x11d3, + {0x9a, 0x29, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }; + + if (fpswa != NULL) + return; + + size = sizeof(grub_efi_handle_t); + + bs = grub_efi_system_table->boot_services; + status = bs->locate_handle (GRUB_EFI_BY_PROTOCOL, + &fpswa_protocol, + NULL, &size, &fpswa_image); + if (status != GRUB_EFI_SUCCESS) + { + grub_printf("Could not locate FPSWA driver\n"); + return; + } + status = bs->handle_protocol (fpswa_image, &fpswa_protocol, &fpswa); + if (status != GRUB_EFI_SUCCESS) + { + grub_printf ("Fpswa protocol not able find the interface\n"); + return; + } +} + +/* Find the optimal number of pages for the memory map. Is it better to + move this code to efi/mm.c? */ +static grub_efi_uintn_t +find_mmap_size (void) +{ + static grub_efi_uintn_t mmap_size = 0; + + if (mmap_size != 0) + return mmap_size; + + mmap_size = (1 << 12); + while (1) + { + int ret; + grub_efi_memory_descriptor_t *mmap; + grub_efi_uintn_t desc_size; + + mmap = grub_malloc (mmap_size); + if (! mmap) + return 0; + + ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0); + grub_free (mmap); + + if (ret < 0) + grub_fatal ("cannot get memory map"); + else if (ret > 0) + break; + + mmap_size += (1 << 12); + } + + /* Increase the size a bit for safety, because GRUB allocates more on + later, and EFI itself may allocate more. */ + mmap_size += (1 << 12); + + return page_align (mmap_size); +} + +static void +free_pages (void) +{ + if (kernel_mem) + { + grub_efi_free_boot_pages ((grub_addr_t) kernel_mem, kernel_pages); + kernel_mem = 0; + } + + if (initrd_mem) + { + grub_efi_free_boot_pages ((grub_addr_t) initrd_mem, initrd_pages); + initrd_mem = 0; + } + + if (boot_param) + { + struct ia64_boot_module *mod; + struct ia64_boot_module *next_mod; + + /* Free modules. */ + mod = (struct ia64_boot_module *)boot_param->modules_chain; + while (mod != 0) + { + next_mod = (struct ia64_boot_module *)mod->next; + + grub_efi_free_boot_pages + (mod->mod_start, page_align (mod->mod_end - mod->mod_start) >> 12); + grub_efi_free_boot_pages ((grub_efi_physical_address_t)mod, 1); + + mod = next_mod; + } + + /* Free bootparam. */ + grub_efi_free_boot_pages ((grub_efi_physical_address_t)boot_param, + boot_param_pages); + boot_param = 0; + } +} + +static void * +allocate_pages (grub_uint64_t align, grub_uint64_t size_pages, + grub_uint64_t nobase) +{ + grub_uint64_t size; + grub_efi_uintn_t desc_size; + grub_efi_memory_descriptor_t *mmap, *mmap_end; + grub_efi_uintn_t mmap_size, tmp_mmap_size; + grub_efi_memory_descriptor_t *desc; + void *mem = NULL; + + size = size_pages << 12; + + mmap_size = find_mmap_size (); + + /* Read the memory map temporarily, to find free space. */ + mmap = grub_malloc (mmap_size); + if (! mmap) + return 0; + + tmp_mmap_size = mmap_size; + if (grub_efi_get_memory_map (&tmp_mmap_size, mmap, 0, &desc_size, 0) <= 0) + grub_fatal ("cannot get memory map"); + + mmap_end = NEXT_MEMORY_DESCRIPTOR (mmap, tmp_mmap_size); + + /* First, find free pages for the real mode code + and the memory map buffer. */ + for (desc = mmap; + desc < mmap_end; + desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) + { + grub_uint64_t start, end; + grub_uint64_t aligned_start; + + if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY) + continue; + + start = desc->physical_start; + end = start + (desc->num_pages << 12); + /* Align is a power of 2. */ + aligned_start = (start + align - 1) & ~(align - 1); + if (aligned_start + size > end) + continue; + if (aligned_start == nobase) + aligned_start += align; + if (aligned_start + size > end) + continue; + mem = grub_efi_allocate_pages (aligned_start, size_pages); + if (! mem) + grub_fatal ("cannot allocate pages"); + break; + } + + if (! mem) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory"); + goto fail; + } + + grub_free (mmap); + return mem; + + fail: + grub_free (mmap); + free_pages (); + return 0; +} + +static void +set_boot_param_console (void) +{ + grub_efi_simple_text_output_interface_t *conout; + grub_efi_uintn_t cols, rows; + + conout = grub_efi_system_table->con_out; + if (conout->query_mode (conout, conout->mode->mode, &cols, &rows) + != GRUB_EFI_SUCCESS) + return; + + grub_dprintf("linux", + "Console info: cols=%lu rows=%lu x=%u y=%u\n", + cols, rows, + conout->mode->cursor_column, conout->mode->cursor_row); + + boot_param->console_info.num_cols = cols; + boot_param->console_info.num_rows = rows; + boot_param->console_info.orig_x = conout->mode->cursor_column; + boot_param->console_info.orig_y = conout->mode->cursor_row; +} + +static grub_err_t +grub_linux_boot (void) +{ + grub_efi_uintn_t mmap_size; + grub_efi_uintn_t map_key; + grub_efi_uintn_t desc_size; + grub_efi_uint32_t desc_version; + grub_efi_memory_descriptor_t *mmap_buf; + + /* FPSWA. */ + query_fpswa (); + boot_param->fpswa = (grub_uint64_t)fpswa; + + /* Initrd. */ + boot_param->initrd_start = (grub_uint64_t)initrd_mem; + boot_param->initrd_size = (grub_uint64_t)initrd_size; + + set_boot_param_console (); + + grub_printf ("Jump to %016lx\n", entry); + + grub_machine_fini (); + + /* MDT. + Must be done after grub_machine_fini because map_key is used by + exit_boot_services. */ + mmap_size = find_mmap_size (); + mmap_buf = grub_efi_allocate_boot_pages (0, page_align (mmap_size) >> 12); + if (! mmap_buf) + grub_fatal ("cannot allocate memory map"); + if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key, + &desc_size, &desc_version) <= 0) + grub_fatal ("cannot get memory map"); + + boot_param->efi_memmap = (grub_uint64_t)mmap_buf; + boot_param->efi_memmap_size = mmap_size; + boot_param->efi_memdesc_size = desc_size; + boot_param->efi_memdesc_version = desc_version; + + if (! grub_efi_exit_boot_services (map_key)) + grub_fatal ("cannot exit boot services"); + + /* See you next boot. */ + asm volatile ("mov r28=%1; br.sptk.few %0" :: "b"(entry),"r"(boot_param)); + + /* Never reach here. */ + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_linux_unload (void) +{ + free_pages (); + grub_dl_unref (my_mod); + loaded = 0; + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_load_elf64 (grub_file_t file, void *buffer) +{ + Elf64_Ehdr *ehdr = (Elf64_Ehdr *) buffer; + Elf64_Phdr *phdr; + int i; + grub_uint64_t low_addr; + grub_uint64_t high_addr; + grub_uint64_t align; + grub_uint64_t reloc_offset; + + if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) + return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class"); + + if (ehdr->e_ident[EI_MAG0] != ELFMAG0 + || ehdr->e_ident[EI_MAG1] != ELFMAG1 + || ehdr->e_ident[EI_MAG2] != ELFMAG2 + || ehdr->e_ident[EI_MAG3] != ELFMAG3 + || ehdr->e_version != EV_CURRENT + || ehdr->e_ident[EI_DATA] != ELFDATA2LSB + || ehdr->e_machine != EM_IA_64) + return grub_error(GRUB_ERR_UNKNOWN_OS, "no valid ELF header found"); + + if (ehdr->e_type != ET_EXEC) + return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type"); + + /* FIXME: Should we support program headers at strange locations? */ + if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > GRUB_ELF_SEARCH) + return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset"); + + entry = ehdr->e_entry; + + /* Compute low, high and align addresses. */ + low_addr = ~0UL; + high_addr = 0; + align = 0; + for (i = 0; i < ehdr->e_phnum; i++) + { + phdr = (Elf64_Phdr *) ((char *) buffer + ehdr->e_phoff + + i * ehdr->e_phentsize); + if (phdr->p_type == PT_LOAD) + { + if (phdr->p_paddr < low_addr) + low_addr = phdr->p_paddr; + if (phdr->p_paddr + phdr->p_memsz > high_addr) + high_addr = phdr->p_paddr + phdr->p_memsz; + if (phdr->p_align > align) + align = phdr->p_align; + } + } + + if (align < ALIGN_MIN) + align = ALIGN_MIN; + + if (high_addr == 0) + return grub_error (GRUB_ERR_BAD_OS, "no program entries"); + + kernel_pages = page_align (high_addr - low_addr) >> 12; + + if (relocate != RELOCATE_FORCE) + { + kernel_mem = grub_efi_allocate_boot_pages (low_addr, kernel_pages); + reloc_offset = 0; + } + /* Try to relocate. */ + if (! kernel_mem && relocate != RELOCATE_OFF) + { + kernel_mem = allocate_pages (align, kernel_pages, low_addr); + if (kernel_mem) + { + reloc_offset = kernel_mem - low_addr; + grub_printf (" Relocated at %p (offset=%016llx)\n", + kernel_mem, reloc_offset); + entry += reloc_offset; + } + } + if (! kernel_mem) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "cannot allocate memory for OS"); + + /* Load every loadable segment in memory. */ + for (i = 0; i < ehdr->e_phnum; i++) + { + phdr = (Elf64_Phdr *) ((char *) buffer + ehdr->e_phoff + + i * ehdr->e_phentsize); + if (phdr->p_type == PT_LOAD) + { + grub_printf (" [paddr=%llx load=%llx memsz=%08llx " + "off=%lx flags=%x]\n", + phdr->p_paddr, phdr->p_paddr + reloc_offset, + phdr->p_memsz, phdr->p_offset, phdr->p_flags); + + if (grub_file_seek (file, phdr->p_offset) == -1) + return grub_error (GRUB_ERR_BAD_OS, + "invalid offset in program header"); + + if (grub_file_read (file, (void *)(phdr->p_paddr + reloc_offset), + phdr->p_filesz) + != (grub_ssize_t) phdr->p_filesz) + return grub_error (GRUB_ERR_BAD_OS, + "couldn't read segment from file"); + + if (phdr->p_filesz < phdr->p_memsz) + grub_memset + ((char *)(phdr->p_paddr + reloc_offset + phdr->p_filesz), + 0, phdr->p_memsz - phdr->p_filesz); + + /* Sync caches if necessary. */ + if (phdr->p_flags & PF_X) + grub_arch_sync_caches + ((void *)(phdr->p_paddr + reloc_offset), phdr->p_memsz); + } + } + loaded = 1; + return 0; +} + +void +grub_rescue_cmd_linux (int argc, char *argv[]) +{ + grub_file_t file = 0; + char buffer[GRUB_ELF_SEARCH]; + char *cmdline, *p; + grub_ssize_t len; + int i; + + grub_dl_ref (my_mod); + + grub_loader_unset (); + + if (argc == 0) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "No kernel specified"); + goto fail; + } + + file = grub_gzfile_open (argv[0], 1); + if (! file) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "Couldn't open file"); + goto fail; + } + + len = grub_file_read (file, buffer, sizeof (buffer)); + if (len < (grub_ssize_t)sizeof (Elf64_Ehdr)) + { + grub_error (GRUB_ERR_BAD_OS, "File too small"); + goto fail; + } + + grub_printf ("Loading linux: %s\n", argv[0]); + + if (grub_load_elf64 (file, buffer)) + goto fail; + + len = sizeof("BOOT_IMAGE=") + 8; + for (i = 0; i < argc; i++) + len += grub_strlen (argv[i]) + 1; + len += sizeof (struct ia64_boot_param) + 256; /* Room for extensions. */ + boot_param_pages = page_align (len) >> 12; + boot_param = grub_efi_allocate_boot_pages (0, boot_param_pages); + if (boot_param == 0) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, + "cannot allocate memory for bootparams"); + goto fail; + } + + grub_memset (boot_param, 0, len); + cmdline = ((char *)(boot_param + 1)) + 256; + + /* Build cmdline. */ + p = grub_stpcpy (cmdline, "BOOT_IMAGE"); + for (i = 0; i < argc; i++) + { + *p++ = ' '; + p = grub_stpcpy (p, argv[i]); + } + cmdline[10] = '='; + + boot_param->command_line = (grub_uint64_t)cmdline; + boot_param->efi_systab = (grub_uint64_t)grub_efi_system_table; + + grub_errno = GRUB_ERR_NONE; + + grub_loader_set (grub_linux_boot, grub_linux_unload, 0); + + fail: + if (file) + grub_file_close (file); + + if (grub_errno != GRUB_ERR_NONE) + { + grub_efi_free_boot_pages ((grub_efi_physical_address_t)boot_param, + boot_param_pages); + grub_dl_unref (my_mod); + } +} + +void +grub_rescue_cmd_initrd (int argc, char *argv[]) +{ + grub_file_t file = 0; + + if (argc == 0) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified"); + goto fail; + } + + if (! loaded) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "You need to load the kernel first."); + goto fail; + } + + file = grub_gzfile_open (argv[0], 1); + if (! file) + goto fail; + + grub_printf ("Loading initrd: %s\n",argv[0]); + + initrd_size = grub_file_size (file); + initrd_pages = (page_align (initrd_size) >> 12); + initrd_mem = grub_efi_allocate_boot_pages (0, initrd_pages); + if (! initrd_mem) + grub_fatal ("cannot allocate pages"); + + grub_printf (" [addr=0x%lx, size=0x%lx]\n", + (grub_uint64_t)initrd_mem, initrd_size); + + if (grub_file_read (file, initrd_mem, initrd_size) + != (grub_ssize_t)initrd_size) + { + grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file"); + goto fail; + } + fail: + if (file) + grub_file_close (file); +} + +void +grub_rescue_cmd_module (int argc, char *argv[]) +{ + grub_file_t file = 0; + grub_ssize_t size, len = 0; + char *module = 0, *cmdline = 0, *p; + struct ia64_boot_module *mod = NULL; + int i; + + if (argc == 0) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified"); + goto fail; + } + + if (!boot_param) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + "You need to load the multiboot kernel first"); + goto fail; + } + + file = grub_gzfile_open (argv[0], 1); + if (! file) + goto fail; + + size = grub_file_size (file); + module = grub_efi_allocate_boot_pages (0, page_align (size) >> 12); + if (! module) + goto fail; + + grub_printf ("Module %s [addr=%llx + %lx]\n", + argv[0], (grub_uint64_t)module, size); + + if (grub_file_read (file, module, size) != size) + { + grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file"); + goto fail; + } + + len = sizeof (struct ia64_boot_module); + for (i = 0; i < argc; i++) + len += grub_strlen (argv[i]) + 1; + + if (len > 4096) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "module command line too long"); + goto fail; + } + mod = grub_efi_allocate_boot_pages (0, 1); + if (! mod) + goto fail; + + p = (char *)(mod + 1); + + mod->mod_start = (grub_uint64_t)module; + mod->mod_end = (grub_uint64_t)module + size; + mod->cmdline = (grub_uint64_t)p; + mod->next = 0; + + if (last_module) + last_module->next = (grub_uint64_t)mod; + else + { + last_module = mod; + boot_param->modules_chain = (grub_uint64_t)mod; + } + boot_param->modules_nbr++; + + /* Copy command line. */ + for (i = 0; i < argc; i++) + { + p = grub_stpcpy (p, argv[i]); + *(p++) = ' '; + } + + /* Remove the space after the last word. */ + *(--p) = '\0'; + + + fail: + if (file) + grub_file_close (file); + + if (grub_errno != GRUB_ERR_NONE) + { + grub_free (module); + grub_free (cmdline); + } +} + +void +grub_rescue_cmd_relocate (int argc, char *argv[]) +{ + static const char * const vals[] = { "off", "on", "force"}; + unsigned int i; + + if (argc == 0) + { + grub_printf ("relocate is %s\n", vals[relocate]); + } + else if (argc == 1) + { + if (kernel_mem != NULL) + grub_printf ("Warning: kernel already loaded!\n"); + for (i = 0; i < sizeof (vals)/sizeof(vals[0]); i++) + if (grub_strcmp (argv[0], vals[i]) == 0) + { + relocate = i; + return; + } + grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown relocate value"); + } + else + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "accept 0 or 1 argument"); + } +} + + +void +grub_rescue_cmd_fpswa (int argc, char *argv[] __attribute__((unused))) +{ + if (argc != 0) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "Arguments not expected"); + return; + } + query_fpswa (); + if (fpswa == NULL) + grub_printf ("No FPSWA loaded\n"); + else + grub_printf ("FPSWA revision: %x\n", fpswa->revision); +} + +GRUB_MOD_INIT(linux) +{ + grub_rescue_register_command ("linux", + grub_rescue_cmd_linux, + "load linux"); + grub_rescue_register_command ("initrd", + grub_rescue_cmd_initrd, + "load initrd"); + grub_rescue_register_command ("module", grub_rescue_cmd_module, + "load a multiboot module"); + grub_rescue_register_command ("relocate", grub_rescue_cmd_relocate, + "set relocate feature"); + grub_rescue_register_command ("fpswa", grub_rescue_cmd_fpswa, + "load fpswa"); + my_mod = mod; +} + +GRUB_MOD_FINI(linux) +{ + grub_rescue_unregister_command ("linux"); + grub_rescue_unregister_command ("initrd"); + grub_rescue_unregister_command ("module"); + grub_rescue_unregister_command ("relocate"); + grub_rescue_unregister_command ("fpswa"); +} diff -ruNp -x '*~' -x CVS grub2.orig/loader/ia64/efi/linux_normal.c grub2/loader/ia64/efi/linux_normal.c --- grub2.orig/loader/ia64/efi/linux_normal.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2/loader/ia64/efi/linux_normal.c 2008-01-28 16:29:58.000000000 +0100 @@ -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 . + */ + +#include +#include +#include +#include + +static grub_err_t +grub_normal_linux_command (struct grub_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + grub_rescue_cmd_linux (argc, args); + return grub_errno; +} + + +static grub_err_t +grub_normal_initrd_command (struct grub_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + grub_rescue_cmd_initrd (argc, args); + return grub_errno; +} + +static grub_err_t +grub_normal_cmd_module (struct grub_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + grub_rescue_cmd_module (argc, args); + return grub_errno; +} + +static grub_err_t +grub_normal_cmd_relocate (struct grub_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + grub_rescue_cmd_relocate (argc, args); + return grub_errno; +} + +static grub_err_t +grub_normal_cmd_fpswa (struct grub_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + grub_rescue_cmd_fpswa (argc, args); + return grub_errno; +} + +GRUB_MOD_INIT(linux_normal) +{ + (void) mod; /* To stop warning. */ + grub_register_command + ("linux", grub_normal_linux_command, + GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, + "linux FILE [ARGS...]", + "Load a linux kernel.", 0); + + grub_register_command + ("initrd", grub_normal_initrd_command, + GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, + "initrd FILE", + "Load an initrd.", 0); + + grub_register_command + ("module", grub_normal_cmd_module, + GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, + "module FILE [ARGS...]", + "Load a Multiboot module.", 0); + + grub_register_command + ("relocate", grub_normal_cmd_relocate, + GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, + "relocate [on|off|force]", + "Set relocate feature.", 0); + + grub_register_command + ("fpswa", grub_normal_cmd_fpswa, + GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, + "fpswa", + "Display FPSWA version.", 0); +} + +GRUB_MOD_FINI(linux_normal) +{ + grub_unregister_command ("linux"); + grub_unregister_command ("initrd"); + grub_unregister_command ("normal"); + grub_unregister_command ("relocate"); + grub_unregister_command ("fpswa"); +} diff -ruNp -x '*~' -x CVS grub2.orig/normal/ia64/longjmp.S grub2/normal/ia64/longjmp.S --- grub2.orig/normal/ia64/longjmp.S 1970-01-01 01:00:00.000000000 +0100 +++ grub2/normal/ia64/longjmp.S 2008-01-28 16:29:58.000000000 +0100 @@ -0,0 +1,162 @@ +/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Contributed by David Mosberger-Tang . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Note that __sigsetjmp() did NOT flush the register stack. Instead, + we do it here since __longjmp() is usually much less frequently + invoked than __sigsetjmp(). The only difficulty is that __sigsetjmp() + didn't (and wouldn't be able to) save ar.rnat either. This is a problem + because if we're not careful, we could end up loading random NaT bits. + There are two cases: + + (i) ar.bsp < ia64_rse_rnat_addr(jmpbuf.ar_bsp) + ar.rnat contains the desired bits---preserve ar.rnat + across loadrs and write to ar.bspstore + + (ii) ar.bsp >= ia64_rse_rnat_addr(jmpbuf.ar_bsp) + The desired ar.rnat is stored in + ia64_rse_rnat_addr(jmpbuf.ar_bsp). Load those + bits into ar.rnat after setting ar.bspstore. */ + + + +# define pPos p6 /* is rotate count positive? */ +# define pNeg p7 /* is rotate count negative? */ + + + /* __longjmp(__jmp_buf buf, int val) */ + + .text + .global longjmp + .proc longjmp +longjmp: + alloc r8=ar.pfs,2,1,0,0 + mov r27=ar.rsc + add r2=0x98,in0 // r2 <- &jmpbuf.orig_jmp_buf_addr + ;; + ld8 r8=[r2],-16 // r8 <- orig_jmp_buf_addr + mov r10=ar.bsp + and r11=~0x3,r27 // clear ar.rsc.mode + ;; + flushrs // flush dirty regs to backing store (must be first in insn grp) + ld8 r23=[r2],8 // r23 <- jmpbuf.ar_bsp + sub r8=r8,in0 // r8 <- &orig_jmpbuf - &jmpbuf + ;; + ld8 r25=[r2] // r25 <- jmpbuf.ar_unat + extr.u r8=r8,3,6 // r8 <- (&orig_jmpbuf - &jmpbuf)/8 & 0x3f + ;; + cmp.lt pNeg,pPos=r8,r0 + mov r2=in0 + ;; +(pPos) mov r16=r8 +(pNeg) add r16=64,r8 +(pPos) sub r17=64,r8 +(pNeg) sub r17=r0,r8 + ;; + mov ar.rsc=r11 // put RSE in enforced lazy mode + shr.u r8=r25,r16 + add r3=8,in0 // r3 <- &jmpbuf.r1 + shl r9=r25,r17 + ;; + or r25=r8,r9 + ;; + mov r26=ar.rnat + mov ar.unat=r25 // setup ar.unat (NaT bits for r1, r4-r7, and r12) + ;; + ld8.fill.nta sp=[r2],16 // r12 (sp) + ld8.fill.nta gp=[r3],16 // r1 (gp) + dep r11=-1,r23,3,6 // r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp) + ;; + ld8.nta r16=[r2],16 // caller's unat + ld8.nta r17=[r3],16 // fpsr + ;; + ld8.fill.nta r4=[r2],16 // r4 + ld8.fill.nta r5=[r3],16 // r5 (gp) + cmp.geu p8,p0=r10,r11 // p8 <- (ar.bsp >= jmpbuf.ar_bsp) + ;; + ld8.fill.nta r6=[r2],16 // r6 + ld8.fill.nta r7=[r3],16 // r7 + ;; + mov ar.unat=r16 // restore caller's unat + mov ar.fpsr=r17 // restore fpsr + ;; + ld8.nta r16=[r2],16 // b0 + ld8.nta r17=[r3],16 // b1 + ;; +(p8) ld8 r26=[r11] // r26 <- *ia64_rse_rnat_addr(jmpbuf.ar_bsp) + mov ar.bspstore=r23 // restore ar.bspstore + ;; + ld8.nta r18=[r2],16 // b2 + ld8.nta r19=[r3],16 // b3 + ;; + ld8.nta r20=[r2],16 // b4 + ld8.nta r21=[r3],16 // b5 + ;; + ld8.nta r11=[r2],16 // ar.pfs + ld8.nta r22=[r3],56 // ar.lc + ;; + ld8.nta r24=[r2],32 // pr + mov b0=r16 + ;; + ldf.fill.nta f2=[r2],32 + ldf.fill.nta f3=[r3],32 + mov b1=r17 + ;; + ldf.fill.nta f4=[r2],32 + ldf.fill.nta f5=[r3],32 + mov b2=r18 + ;; + ldf.fill.nta f16=[r2],32 + ldf.fill.nta f17=[r3],32 + mov b3=r19 + ;; + ldf.fill.nta f18=[r2],32 + ldf.fill.nta f19=[r3],32 + mov b4=r20 + ;; + ldf.fill.nta f20=[r2],32 + ldf.fill.nta f21=[r3],32 + mov b5=r21 + ;; + ldf.fill.nta f22=[r2],32 + ldf.fill.nta f23=[r3],32 + mov ar.lc=r22 + ;; + ldf.fill.nta f24=[r2],32 + ldf.fill.nta f25=[r3],32 + cmp.eq p8,p9=0,in1 + ;; + ldf.fill.nta f26=[r2],32 + ldf.fill.nta f27=[r3],32 + mov ar.pfs=r11 + ;; + ldf.fill.nta f28=[r2],32 + ldf.fill.nta f29=[r3],32 + ;; + ldf.fill.nta f30=[r2] + ldf.fill.nta f31=[r3] +(p8) mov r8=1 + + mov ar.rnat=r26 // restore ar.rnat + ;; + mov ar.rsc=r27 // restore ar.rsc +(p9) mov r8=in1 + + invala // virt. -> phys. regnum mapping may change + mov pr=r24,-1 + br.ret.dptk.few rp + .endp longjmp diff -ruNp -x '*~' -x CVS grub2.orig/normal/ia64/setjmp.S grub2/normal/ia64/setjmp.S --- grub2.orig/normal/ia64/setjmp.S 1970-01-01 01:00:00.000000000 +0100 +++ grub2/normal/ia64/setjmp.S 2008-01-28 16:29:58.000000000 +0100 @@ -0,0 +1,171 @@ +/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Contributed by David Mosberger-Tang . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + The layout of the jmp_buf is as follows. This is subject to change + and user-code should never depend on the particular layout of + jmp_buf! + + + offset: description: + ------- ------------ + 0x000 stack pointer (r12) ; unchangeable (see _JMPBUF_UNWINDS) + 0x008 r1 (gp) + 0x010 caller's unat + 0x018 fpsr + 0x020 r4 + 0x028 r5 + 0x030 r6 + 0x038 r7 + 0x040 rp (b0) + 0x048 b1 + 0x050 b2 + 0x058 b3 + 0x060 b4 + 0x068 b5 + 0x070 ar.pfs + 0x078 ar.lc + 0x080 pr + 0x088 ar.bsp ; unchangeable (see __longjmp.S) + 0x090 ar.unat + 0x098 &__jmp_buf ; address of the jmpbuf (needed to locate NaT bits in unat) + 0x0a0 f2 + 0x0b0 f3 + 0x0c0 f4 + 0x0d0 f5 + 0x0e0 f16 + 0x0f0 f17 + 0x100 f18 + 0x110 f19 + 0x120 f20 + 0x130 f21 + 0x130 f22 + 0x140 f23 + 0x150 f24 + 0x160 f25 + 0x170 f26 + 0x180 f27 + 0x190 f28 + 0x1a0 f29 + 0x1b0 f30 + 0x1c0 f31 */ + + + /* The following two entry points are the traditional entry points: */ + + .text + .global setjmp + .proc setjmp +setjmp: + alloc r8=ar.pfs,2,0,0,0 + mov in1=1 + br.cond.sptk.many __sigsetjmp + .endp setjmp + + /* __sigsetjmp(__jmp_buf buf, int savemask) */ + + .proc __sigsetjmp +__sigsetjmp: + //.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2) + alloc loc1=ar.pfs,2,2,2,0 + mov r16=ar.unat + ;; + mov r17=ar.fpsr + mov r2=in0 + add r3=8,in0 + ;; + st8.spill.nta [r2]=sp,16 // r12 (sp) + st8.spill.nta [r3]=gp,16 // r1 (gp) + ;; + st8.nta [r2]=r16,16 // save caller's unat + st8.nta [r3]=r17,16 // save fpsr + add r8=0xa0,in0 + ;; + st8.spill.nta [r2]=r4,16 // r4 + st8.spill.nta [r3]=r5,16 // r5 + add r9=0xb0,in0 + ;; + stf.spill.nta [r8]=f2,32 + stf.spill.nta [r9]=f3,32 + mov loc0=rp + .body + ;; + stf.spill.nta [r8]=f4,32 + stf.spill.nta [r9]=f5,32 + mov r17=b1 + ;; + stf.spill.nta [r8]=f16,32 + stf.spill.nta [r9]=f17,32 + mov r18=b2 + ;; + stf.spill.nta [r8]=f18,32 + stf.spill.nta [r9]=f19,32 + mov r19=b3 + ;; + stf.spill.nta [r8]=f20,32 + stf.spill.nta [r9]=f21,32 + mov r20=b4 + ;; + stf.spill.nta [r8]=f22,32 + stf.spill.nta [r9]=f23,32 + mov r21=b5 + ;; + stf.spill.nta [r8]=f24,32 + stf.spill.nta [r9]=f25,32 + mov r22=ar.lc + ;; + stf.spill.nta [r8]=f26,32 + stf.spill.nta [r9]=f27,32 + mov r24=pr + ;; + stf.spill.nta [r8]=f28,32 + stf.spill.nta [r9]=f29,32 + ;; + stf.spill.nta [r8]=f30 + stf.spill.nta [r9]=f31 + + st8.spill.nta [r2]=r6,16 // r6 + st8.spill.nta [r3]=r7,16 // r7 + ;; + mov r23=ar.bsp + mov r25=ar.unat + mov out0=in0 + + st8.nta [r2]=loc0,16 // b0 + st8.nta [r3]=r17,16 // b1 + mov out1=in1 + ;; + st8.nta [r2]=r18,16 // b2 + st8.nta [r3]=r19,16 // b3 + ;; + st8.nta [r2]=r20,16 // b4 + st8.nta [r3]=r21,16 // b5 + ;; + st8.nta [r2]=loc1,16 // ar.pfs + st8.nta [r3]=r22,16 // ar.lc + ;; + st8.nta [r2]=r24,16 // pr + st8.nta [r3]=r23,16 // ar.bsp + ;; + st8.nta [r2]=r25 // ar.unat + st8.nta [r3]=in0 // &__jmp_buf + mov r8=0 + mov rp=loc0 + mov ar.pfs=loc1 + br.ret.sptk.many rp + + .endp __sigsetjmp diff -ruNp -x '*~' -x CVS grub2.orig/util/ia64/efi/elf2pe.c grub2/util/ia64/efi/elf2pe.c --- grub2.orig/util/ia64/efi/elf2pe.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2/util/ia64/efi/elf2pe.c 2008-01-28 16:29:58.000000000 +0100 @@ -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 . + */ +#include +#include +#include +#include +#include +#include + +#if defined(i386) +#define USE_ELF32 +#define USE_PE32 +#define ELF_MACHINE EM_386 +#define EFI_MACHINE PE32_MACHINE_I386 +#elif defined(__ia64__) +#define USE_ELF64 +#define USE_PE32PLUS +#define ELF_MACHINE EM_IA_64 +#define EFI_MACHINE PE32_MACHINE_IA64 +#else +#error "unknown architecture" +#endif + +#include "pe32.h" + +const char *filename; + +int +is_elf_header(uint8_t *buffer) +{ + return (buffer[EI_MAG0] == ELFMAG0 + && buffer[EI_MAG1] == ELFMAG1 + && buffer[EI_MAG2] == ELFMAG2 + && buffer[EI_MAG3] == ELFMAG3); +} + +#ifdef USE_ELF32 +typedef Elf32_Shdr Elf_Shdr; +typedef Elf32_Ehdr Elf_Ehdr; +typedef Elf32_Rel Elf_Rel; +typedef Elf32_Rela Elf_Rela; +typedef Elf32_Sym Elf_Sym; +#define ELFCLASS ELFCLASS32 +#define ELF_R_TYPE(r) ELF32_R_TYPE(r) +#define ELF_R_SYM(r) ELF32_R_SYM(r) +#else +typedef Elf64_Shdr Elf_Shdr; +typedef Elf64_Ehdr Elf_Ehdr; +typedef Elf64_Rel Elf_Rel; +typedef Elf64_Rela Elf_Rela; +typedef Elf64_Sym Elf_Sym; +#define ELFCLASS ELFCLASS64 +#define ELF_R_TYPE(r) ELF64_R_TYPE(r) +#define ELF_R_SYM(r) ELF64_R_SYM(r) +#endif + +#ifdef __ia64__ +#define ELF_ETYPE ET_DYN +#else +#define ELF_ETYPE ET_EXEC +#endif + +/* Well known ELF structures. */ +Elf_Ehdr *ehdr; +Elf_Shdr *shdr_base; +Elf_Shdr *shdr_dynamic; +const uint8_t *shdr_str; + +/* PE section alignment. */ +const uint32_t coff_alignment = 0x20; +const uint32_t coff_nbr_sections = 4; + +/* Current offset in coff file. */ +uint32_t coff_offset; + +/* Result Coff file in memory. */ +uint8_t *coff_file; + +/* Offset in Coff file of headers and sections. */ +uint32_t nt_hdr_offset; +uint32_t table_offset; +uint32_t text_offset; +uint32_t data_offset; +uint32_t reloc_offset; + +#ifdef __ia64__ +uint32_t coff_entry_descr_offset; +uint32_t coff_entry_descr_func; +uint64_t plt_base; +#endif + +/* ELF sections to offset in Coff file. */ +uint32_t *coff_sections_offset; + +struct pe32_fixup_block *coff_base_rel; +uint16_t *coff_entry_rel; + +uint32_t +coff_align(uint32_t offset) +{ + return (offset + coff_alignment - 1) & ~(coff_alignment - 1); +} + +Elf_Shdr * +get_shdr_by_index(uint32_t num) +{ + if (num >= ehdr->e_shnum) + return NULL; + return (Elf_Shdr*)((uint8_t*)shdr_base + num * ehdr->e_shentsize); +} + +int +check_elf_header (void) +{ + /* Note: Magic has already been tested. */ + if (ehdr->e_ident[EI_CLASS] != ELFCLASS) + return 0; + if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) + return 0; + if (ehdr->e_type != ELF_ETYPE) + return 0; + if (ehdr->e_machine != ELF_MACHINE) + return 0; + if (ehdr->e_version != EV_CURRENT) + return 0; + + shdr_base = (Elf_Shdr *)((uint8_t *)ehdr + ehdr->e_shoff); + + coff_sections_offset = + (uint32_t *)malloc (ehdr->e_shnum * sizeof (uint32_t)); + memset (coff_sections_offset, 0, ehdr->e_shnum * sizeof(uint32_t)); + + if (ehdr->e_shstrndx != SHN_UNDEF) + shdr_str = (uint8_t*)ehdr + shdr_base[ehdr->e_shstrndx].sh_offset; + else + shdr_str = NULL; + + return 1; +} + +int +is_text_shdr (Elf_Shdr *shdr) +{ + if (shdr->sh_type != SHT_PROGBITS) { + return 0; + } +#ifdef __ia64__ + return (shdr->sh_flags & (SHF_EXECINSTR | SHF_ALLOC)) + == (SHF_ALLOC | SHF_EXECINSTR); +#else + return (shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC; +#endif +} + +int +is_data_shdr (Elf_Shdr *shdr) +{ + if (shdr->sh_type != SHT_PROGBITS && shdr->sh_type != SHT_NOBITS) { + return 0; + } + return (shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE); +} + +void +create_section_header (const char *name, uint32_t offset, uint32_t size, + uint32_t flags) +{ + struct pe32_section_header *hdr; + hdr = (struct pe32_section_header*)(coff_file + table_offset); + + strcpy (hdr->name, name); + hdr->virtual_size = size; + hdr->virtual_address = offset; + hdr->raw_data_size = size; + hdr->raw_data_offset = offset; + hdr->relocations_offset = 0; + hdr->line_numbers_offset = 0; + hdr->num_relocations = 0; + hdr->num_line_numbers = 0; + hdr->characteristics = flags; + + table_offset += sizeof (struct pe32_section_header); +} + +int +scan_sections (void) +{ + uint32_t i; + struct pe32_dos_header *doshdr; + struct pe32_nt_header *nt_hdr; + uint32_t coff_entry = 0; + int status = 0; + + coff_offset = 0; + + /* Coff file start with a DOS header. */ + coff_offset = sizeof(struct pe32_dos_header); + nt_hdr_offset = coff_offset; + coff_offset += sizeof(struct pe32_nt_header); + table_offset = coff_offset; + coff_offset += coff_nbr_sections * sizeof(struct pe32_section_header); + + /* First text sections. */ + coff_offset = coff_align(coff_offset); + text_offset = coff_offset; + for (i = 0; i < ehdr->e_shnum; i++) { + Elf_Shdr *shdr = get_shdr_by_index (i); + if (is_text_shdr (shdr)) { + /* Relocate entry. */ + if (ehdr->e_entry >= shdr->sh_addr + && ehdr->e_entry < shdr->sh_addr + shdr->sh_size) { + coff_entry = coff_offset + ehdr->e_entry - shdr->sh_addr; + } + coff_sections_offset[i] = coff_offset; + coff_offset += shdr->sh_size; +#ifdef __ia64__ + if (coff_sections_offset[i] != shdr->sh_addr) { + fprintf (stderr, + "Section %s: Coff offset (%x) != Elf offset (%lx)", + shdr_str + shdr->sh_name, + coff_sections_offset[i], + shdr->sh_addr); + status = -1; + } +#endif + } + if (shdr->sh_type == SHT_DYNAMIC) { + shdr_dynamic = shdr; + } + } +#ifdef __ia64__ + /* 16 bytes are reserved (by the ld script) for the entry point descriptor. + */ + coff_entry_descr_offset = coff_offset - 16; +#endif + + coff_offset = coff_align (coff_offset); + + /* Then data sections. */ + data_offset = coff_offset; + for (i = 0; i < ehdr->e_shnum; i++) { + Elf_Shdr *shdr = get_shdr_by_index (i); + if (is_data_shdr (shdr)) { + coff_sections_offset[i] = coff_offset; + coff_offset += shdr->sh_size; +#ifdef __ia64__ + if (coff_sections_offset[i] != shdr->sh_addr) { + fprintf (stderr, + "Section %s: Coff offset (%x) != Elf offset (%lx)", + shdr_str + shdr->sh_name, + coff_sections_offset[i], + shdr->sh_addr); + status = -1; + } +#endif + } + } + coff_offset = coff_align (coff_offset); + + reloc_offset = coff_offset; + + /* Allocate base Coff file. Will be expanded later for relocations. */ + coff_file = (uint8_t *)malloc (coff_offset); + memset (coff_file, 0, coff_offset); + + /* Fill headers. */ + doshdr = (struct pe32_dos_header *)coff_file; + doshdr->magic = 0x5A4D; + doshdr->new_hdr_offset = nt_hdr_offset; + + nt_hdr = (struct pe32_nt_header*)(coff_file + nt_hdr_offset); + + memcpy (nt_hdr->signature, "PE\0", 4); + + nt_hdr->coff_header.machine = EFI_MACHINE; + nt_hdr->coff_header.num_sections = coff_nbr_sections; + nt_hdr->coff_header.time = time (NULL); + nt_hdr->coff_header.symtab_offset = 0; + nt_hdr->coff_header.num_symbols = 0; + nt_hdr->coff_header.optional_header_size = sizeof(nt_hdr->optional_header); + nt_hdr->coff_header.characteristics = PE32_EXECUTABLE_IMAGE + | PE32_LINE_NUMS_STRIPPED + | PE32_LOCAL_SYMS_STRIPPED + | PE32_32BIT_MACHINE; + +#ifdef USE_PE32 + nt_hdr->optional_header.magic = PE32_PE32_MAGIC; +#else + nt_hdr->optional_header.magic = PE32_PE64_MAGIC; +#endif + nt_hdr->optional_header.code_size = data_offset - text_offset; + nt_hdr->optional_header.data_size = reloc_offset - data_offset; + nt_hdr->optional_header.bss_size = 0; +#ifdef __ia64__ + nt_hdr->optional_header.entry_addr = coff_entry_descr_offset; + coff_entry_descr_func = coff_entry; +#else + nt_hdr->optional_header.entry_addr = coff_entry; +#endif + nt_hdr->optional_header.code_base = text_offset; + +#ifdef USE_PE32 + nt_hdr->optional_header.data_base = data_offset; +#endif + nt_hdr->optional_header.image_base = 0; + nt_hdr->optional_header.section_alignment = coff_alignment; + nt_hdr->optional_header.file_alignment = coff_alignment; + nt_hdr->optional_header.image_size = 0; + + nt_hdr->optional_header.header_size = text_offset; + nt_hdr->optional_header.num_data_directories = PE32_NUM_DATA_DIRECTORIES; + + /* Section headers. */ + create_section_header (".text", text_offset, data_offset - text_offset, + PE32_SCN_CNT_CODE + | PE32_SCN_MEM_EXECUTE + | PE32_SCN_MEM_READ); + create_section_header (".data", data_offset, reloc_offset - data_offset, + PE32_SCN_CNT_INITIALIZED_DATA + | PE32_SCN_MEM_WRITE + | PE32_SCN_MEM_READ); +#ifdef __ia64__ + if (shdr_dynamic != NULL) + { + Elf64_Dyn *dyn = (Elf64_Dyn*)((uint8_t*)ehdr + shdr_dynamic->sh_offset); + while (dyn->d_tag != DT_NULL) + { + if (dyn->d_tag == DT_PLTGOT) + plt_base = dyn->d_un.d_ptr; + dyn++; + } + } +#endif + return status; +} + +int +write_sections (int (*filter)(Elf_Shdr *)) +{ + uint32_t idx; + int status = 0; + + /* First: copy sections. */ + for (idx = 0; idx < ehdr->e_shnum; idx++) + { + Elf_Shdr *shdr = get_shdr_by_index (idx); + if ((*filter)(shdr)) + { + switch (shdr->sh_type) { + case SHT_PROGBITS: + /* Copy. */ + memcpy (coff_file + coff_sections_offset[idx], + (uint8_t*)ehdr + shdr->sh_offset, + shdr->sh_size); + break; + case SHT_NOBITS: + memset (coff_file + coff_sections_offset[idx], 0, shdr->sh_size); + break; + case SHT_DYNAMIC: + break; + default: + fprintf (stderr, "unhandled section type %x", + (unsigned int)shdr->sh_type); + status = -1; + } + } + } + + /* Second: apply relocations. */ + for (idx = 0; idx < ehdr->e_shnum; idx++) + { + Elf_Shdr *rel_shdr = get_shdr_by_index (idx); + if (rel_shdr->sh_type != SHT_REL && rel_shdr->sh_type != SHT_RELA) + continue; + Elf_Shdr *sec_shdr = get_shdr_by_index (rel_shdr->sh_info); + uint32_t sec_offset = coff_sections_offset[rel_shdr->sh_info]; + + if (rel_shdr->sh_info == 0 || (*filter)(sec_shdr)) + { + uint32_t rel_idx; + Elf_Shdr *symtab_shdr = get_shdr_by_index(rel_shdr->sh_link); + uint8_t *symtab = (uint8_t*)ehdr + symtab_shdr->sh_offset; + + if (rel_shdr->sh_type == SHT_REL) + { + for (rel_idx = 0; + rel_idx < rel_shdr->sh_size; + rel_idx += rel_shdr->sh_entsize) + { + Elf_Rel *rel = (Elf_Rel *) + ((uint8_t*)ehdr + rel_shdr->sh_offset + rel_idx); + Elf_Sym *sym = (Elf_Sym *) + (symtab + + ELF_R_SYM(rel->r_info) * symtab_shdr->sh_entsize); + Elf_Shdr *sym_shdr; + uint8_t *targ; + + if (sym->st_shndx == SHN_UNDEF + || sym->st_shndx == SHN_ABS + || sym->st_shndx > ehdr->e_shnum) + { + fprintf (stderr, "bad symbol definition"); + status = -1; + } + sym_shdr = get_shdr_by_index(sym->st_shndx); + + /* Note: r_offset in a memory address. + Convert it to a pointer in the coff file. */ + targ = coff_file + sec_offset + + (rel->r_offset - sec_shdr->sh_addr); + + switch (ELF_R_TYPE(rel->r_info)) { + case R_386_NONE: + break; + case R_386_32: + /* Absolute relocation. */ + *(uint32_t *)targ = *(uint32_t *)targ - sym_shdr->sh_addr + + coff_sections_offset[sym->st_shndx]; + break; + case R_386_PC32: + /* Relative relocation: Symbol - Ip + Addend */ + *(uint32_t *)targ = *(uint32_t *)targ + + (coff_sections_offset[sym->st_shndx] + - sym_shdr->sh_addr) + - (sec_offset - sec_shdr->sh_addr); + break; + default: + fprintf (stderr, "unhandled relocation type %lx", + ELF_R_TYPE(rel->r_info)); + status = -1; + } + } + } + else if (rel_shdr->sh_type == SHT_RELA) + { + for (rel_idx = 0; + rel_idx < rel_shdr->sh_size; + rel_idx += rel_shdr->sh_entsize) { + Elf_Rela *rela = (Elf_Rela *) + ((uint8_t*)ehdr + rel_shdr->sh_offset + rel_idx); + Elf_Sym *sym = (Elf_Sym *) + (symtab + ELF_R_SYM(rela->r_info) * symtab_shdr->sh_entsize); + Elf_Shdr *sym_shdr; + uint8_t *targ; + + if (ELF_R_TYPE(rela->r_info) == R_IA64_NONE) + continue; + +#if 0 + if (sym->st_shndx == SHN_UNDEF + || sym->st_shndx == SHN_ABS + || sym->st_shndx > ehdr->e_shnum) { + fprintf (stderr, "bad symbol definition %d", + ELF_R_SYM(rela->r_info)); + } +#endif + sym_shdr = get_shdr_by_index (sym->st_shndx); + + /* Note: r_offset in a memory address. + Convert it to a pointer in the coff file. */ + targ = coff_file + sec_offset + + (rela->r_offset - sec_shdr->sh_addr); + + switch (ELF_R_TYPE(rela->r_info)) { + case R_IA64_IPLTLSB: + /* If there is a descriptor with the same function + pointer as the ELF entry point, use that + descriptor for the PE/Coff entry. */ + if (*(uint64_t*)targ == ehdr->e_entry) { + struct pe32_nt_header *nt_hdr; + + nt_hdr = + (struct pe32_nt_header*)(coff_file + nt_hdr_offset); + nt_hdr->optional_header.entry_addr = targ - coff_file; + } + break; + case R_IA64_REL64LSB: + case R_IA64_NONE: + break; + default: + fprintf (stderr, + "unhandled relocation type %lx in section %d", + ELF_R_TYPE(rela->r_info), rel_shdr->sh_info); + status = -1; + } + } + } + } + } + return status; +} + +void +coff_add_fixup_entry (uint16_t val) +{ + *coff_entry_rel = val; + coff_entry_rel++; + coff_base_rel->block_size += 2; + coff_offset += 2; +} + +void +coff_add_fixup (uint32_t offset, uint8_t type) +{ + if (coff_base_rel == NULL + || coff_base_rel->page_rva != (offset & ~0xfff)) { + if (coff_base_rel != NULL) { + /* Add a null entry (is it required ?) */ + coff_add_fixup_entry (0); + /* Pad for alignment. */ + if (coff_offset % 4 != 0) + coff_add_fixup_entry (0); + } + + coff_file = realloc + (coff_file, + coff_offset + sizeof(struct pe32_fixup_block) + 2*0x1000); + memset(coff_file + coff_offset, 0, + sizeof(struct pe32_fixup_block) + 2*0x1000); + + coff_base_rel = (struct pe32_fixup_block*)(coff_file + coff_offset); + coff_base_rel->page_rva = offset & ~0xfff; + coff_base_rel->block_size = sizeof(struct pe32_fixup_block); + + coff_entry_rel = (uint16_t *)(coff_base_rel + 1); + coff_offset += sizeof(struct pe32_fixup_block); + } + + /* Fill the entry. */ + coff_add_fixup_entry ((type << 12) | (offset & 0xfff)); +} + +int +write_relocations(void) +{ + uint32_t idx; + struct pe32_nt_header *nt_hdr; + struct pe32_data_directory *dir; + int status = 0; + + for (idx = 0; idx < ehdr->e_shnum; idx++) + { + Elf_Shdr *rel_shdr = get_shdr_by_index (idx); + if (rel_shdr->sh_type == SHT_REL) + { + Elf_Shdr *sec_shdr = get_shdr_by_index (rel_shdr->sh_info); + if (is_text_shdr(sec_shdr) || is_data_shdr(sec_shdr)) + { + uint32_t rel_idx; + for (rel_idx = 0; + rel_idx < rel_shdr->sh_size; + rel_idx += rel_shdr->sh_entsize) + { + Elf_Rel *rel = (Elf_Rel *) + ((uint8_t*)ehdr + rel_shdr->sh_offset + rel_idx); + + switch (ELF_R_TYPE(rel->r_info)) + { + case R_386_NONE: + case R_386_PC32: + break; + case R_386_32: + coff_add_fixup(coff_sections_offset[rel_shdr->sh_info] + + (rel->r_offset - sec_shdr->sh_addr), + PE32_REL_BASED_HIGHLOW); + break; + default: + fprintf (stderr, "unhandled relocation type %lx", + ELF_R_TYPE(rel->r_info)); + status = -1; + } + } + } + } + else if (rel_shdr->sh_type == SHT_RELA) + { + Elf_Shdr *sec_shdr = get_shdr_by_index(rel_shdr->sh_info); + if (rel_shdr->sh_info == 0 + || is_text_shdr(sec_shdr) || is_data_shdr(sec_shdr)) + { + uint32_t rel_idx; + for (rel_idx = 0; + rel_idx < rel_shdr->sh_size; + rel_idx += rel_shdr->sh_entsize) { + Elf_Rela *rela = (Elf_Rela *) + ((uint8_t*)ehdr + rel_shdr->sh_offset + rel_idx); + uint32_t Loc = coff_sections_offset[rel_shdr->sh_info] + + (rela->r_offset - sec_shdr->sh_addr); + + switch (ELF_R_TYPE(rela->r_info)) + { + case R_IA64_IPLTLSB: + coff_add_fixup(Loc, PE32_REL_BASED_DIR64); + coff_add_fixup(Loc + 8, PE32_REL_BASED_DIR64); + break; + case R_IA64_REL64LSB: + coff_add_fixup(Loc, PE32_REL_BASED_DIR64); + break; + case R_IA64_DIR64LSB: + coff_add_fixup(Loc, PE32_REL_BASED_DIR64); + break; + case R_IA64_IMM64: + coff_add_fixup(Loc, PE32_REL_BASED_IA64_IMM64); + break; + case R_IA64_PCREL21B: + case R_IA64_PCREL64LSB: + case R_IA64_SECREL32LSB: + case R_IA64_SEGREL64LSB: + break; + case R_IA64_GPREL22: + case R_IA64_LTOFF22X: + case R_IA64_LDXMOV: + case R_IA64_LTOFF_FPTR22: + case R_IA64_NONE: + break; + default: + fprintf (stderr, "unhandled relocation type %lx", + ELF_R_TYPE(rela->r_info)); + status = -1; + } + } + } + } + } + +#ifdef __ia64__ + coff_add_fixup (coff_entry_descr_offset, PE32_REL_BASED_DIR64); + coff_add_fixup (coff_entry_descr_offset + 8, PE32_REL_BASED_DIR64); +#endif + + /* Pad by adding empty entries. */ + while (coff_offset & (coff_alignment - 1)) + coff_add_fixup_entry (0); + + create_section_header (".reloc", reloc_offset, coff_offset - reloc_offset, + PE32_SCN_CNT_INITIALIZED_DATA + | PE32_SCN_MEM_DISCARDABLE + | PE32_SCN_MEM_READ); + + nt_hdr = (struct pe32_nt_header *)(coff_file + nt_hdr_offset); + dir = &nt_hdr->optional_header.base_relocation_table; + dir->rva = reloc_offset; + dir->size = coff_offset - reloc_offset; + + return status; +} + +void +write_debug(void) +{ + uint32_t len = strlen(filename) + 1; + uint32_t debug_offset = coff_offset; + struct pe32_nt_header *nt_hdr; + struct pe32_data_directory *data_dir; + struct pe32_debug_directory_entry *dir; + struct pe32_debug_codeview_nb10_entry *nb10; + + coff_offset += sizeof (struct pe32_debug_directory_entry) + + sizeof(struct pe32_debug_codeview_nb10_entry) + + len; + coff_offset = coff_align(coff_offset); + + coff_file = realloc + (coff_file, coff_offset); + memset(coff_file + debug_offset, 0, coff_offset - debug_offset); + + dir = (struct pe32_debug_directory_entry*)(coff_file + debug_offset); + dir->type = PE32_DEBUG_TYPE_CODEVIEW; + dir->data_size = sizeof(struct pe32_debug_directory_entry) + len; + dir->rva = debug_offset + sizeof(struct pe32_debug_directory_entry); + dir->file_offset = debug_offset + sizeof(struct pe32_debug_directory_entry); + + nb10 = (struct pe32_debug_codeview_nb10_entry*)(dir + 1); + nb10->signature = PE32_CODEVIEW_SIGNATURE_NB10; + strcpy (nb10->filename, filename); + + create_section_header (".debug", debug_offset, coff_offset - debug_offset, + PE32_SCN_CNT_INITIALIZED_DATA + | PE32_SCN_MEM_DISCARDABLE + | PE32_SCN_MEM_READ); + + nt_hdr = (struct pe32_nt_header *)(coff_file + nt_hdr_offset); + data_dir = &nt_hdr->optional_header.debug; + data_dir->rva = debug_offset; + data_dir->size = coff_offset - debug_offset; +} + +int +convert_elf (uint8_t **file_buffer, unsigned int *file_length) +{ + struct pe32_nt_header *nt_hdr; + + /* Check header, read section table. */ + ehdr = (Elf_Ehdr*)*file_buffer; + if (!check_elf_header ()) + return -1; + + /* Compute sections new address. */ + if (scan_sections () != 0) + return -2; + + /* Write and relocate sections. */ + if (write_sections (is_text_shdr) != 0) + return -3; + +#ifdef __ia64__ + *(uint64_t*)(coff_file + coff_entry_descr_offset) = coff_entry_descr_func; + *(uint64_t*)(coff_file + coff_entry_descr_offset + 8) = plt_base; +#endif + + if (write_sections (is_data_shdr) != 0) + return -4; + + /* Translate and write relocations. */ + if (write_relocations () != 0) + return -5; + + /* Write debug info. */ + write_debug (); + + nt_hdr = (struct pe32_nt_header *)(coff_file + nt_hdr_offset); + nt_hdr->optional_header.image_size = coff_offset; + + nt_hdr->optional_header.subsystem = PE32_SUBSYSTEM_EFI_APPLICATION; + + /* Replace. */ + free (*file_buffer); + *file_buffer = coff_file; + *file_length = coff_offset; + + return 0; +} + +int +main (int argc, char **argv) +{ + FILE *f; + unsigned int size; + uint8_t *buffer; + const char *outfile; + int status; + + if (argc != 3) + { + fprintf (stderr, "usage: %s elf-file pe-file\n", argv[0]); + exit (1); + } + + filename = argv[1]; + outfile = argv[2]; + f = fopen (filename, "rb"); + fseek (f, 0, SEEK_END); + size = ftell (f); + fseek (f, 0, SEEK_SET); + + buffer = malloc (size); + if (buffer == NULL) + { + fprintf (stderr, "cannot allocate %u bytes of memory\n", size); + exit (2); + } + if (fread (buffer, size, 1, f) != 1) + { + fprintf (stderr, "cannot read %s\n", filename); + exit (2); + } + fclose (f); + + if (!is_elf_header (buffer)) + { + fprintf (stderr, "%s is not an elf file\n", filename); + exit (2); + } + + status = convert_elf (&buffer, &size); + if (status != 0) + { + fprintf (stderr, "cannot convert %s to pe (err=%d)\n", filename, status); + exit (2); + } + + f = fopen (outfile, "wb"); + if (f == NULL) + { + fprintf (stderr, "cannot open %s\n", outfile); + exit (2); + } + if (fwrite (buffer, size, 1, f) != 1) + { + fprintf (stderr, "cannot write to %s\n", outfile); + exit (2); + } + fclose (f); + + return 0; +} diff -ruNp -x '*~' -x CVS grub2.orig/util/ia64/efi/grub-install.in grub2/util/ia64/efi/grub-install.in --- grub2.orig/util/ia64/efi/grub-install.in 1970-01-01 01:00:00.000000000 +0100 +++ grub2/util/ia64/efi/grub-install.in 2008-01-28 16:29:58.000000000 +0100 @@ -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 . + + +# Initialize some variables. address@hidden@ address@hidden@ address@hidden@ address@hidden@ address@hidden@ address@hidden@ address@hidden@ address@hidden@ address@hidden@ address@hidden@ address@hidden@ +pkglibdir=${libdir}/${PACKAGE_TARNAME}/${target_cpu}-${platform} +pkgdatadir=${datadir}/${PACKAGE_TARNAME} + + address@hidden@ +TARGET_CFLAGS="@TARGET_CFLAGS@" +TARGET_CPPFLAGS="@TARGET_CPPFLAGS@" +TARGET_LDFLAGS="@TARGET_LDFLAGS@" address@hidden@ + +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 +} + +# Check the arguments. +for option in "$@"; do + case "$option" in + -h | --help) + usage + exit 0 ;; + -v | --version) + echo "grub-install (GNU GRUB ${PACKAGE_VERSION})" + exit 0 ;; + --modules=*) + modules=`echo "$option" | sed 's/--modules=//'` ;; + --root-directory=*) + rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + --grub-setup=*) + grub_setup=`echo "$option" | sed 's/--grub-setup=//'` ;; + --grub-mkimage=*) + grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; + --grub-mkdevicemap=*) + grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;; + --grub-probefs=*) + grub_probefs=`echo "$option" | sed 's/--grub-probefs=//'` ;; + --pkglibdir=*) + pkglibdir=`echo "$option" | sed 's/--pkglibdir=//'` ;; + --pkgdatadir=*) + pkgdatadir=`echo "$option" | sed 's/--pkgdatadir=//'` ;; + --recheck) + recheck=yes ;; + # This is an undocumented feature... + --debug) + debug=yes ;; + -*) + echo "Unrecognized option \`$option'" 1>&2 + usage + exit 1 + ;; + *) + if test "x$install_device" != x; then + echo "More than one install_devices?" 1>&2 + usage + exit 1 + fi + install_device="${option}" ;; + esac +done + +#if test "x$install_device" = x; then +# echo "install_device not specified." 1>&2 +# usage +# exit 1 +#fi + +# If the debugging feature is enabled, print commands. +if test $debug = yes; then + set -x +fi + +# Initialize these directories here, since ROOTDIR was initialized. +bootdir=${rootdir}/boot/efi + +grubdir=${bootdir}/grub +device_map=${grubdir}/device.map + +# Create the GRUB directory if it is not present. +test -d "$bootdir" || mkdir "$bootdir" || exit 1 +test -d "$grubdir" || mkdir "$grubdir" || exit 1 + +# Copy the GRUB images to the GRUB directory. +if false; then + for file in ${grubdir}/*.mod ${grubdir}/*.lst; do + if test -f $file; then + rm -f $file || exit 1 + fi + done + for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst; do + cp -f $file ${grubdir} || exit 1 + done +fi + +# Create the core image. First, auto-detect the filesystme module. +#fs_module=`$grub_probefs --device-map=${device_map} ${grubdir}` +#if test "x$fs_module" = x -a "x$modules" = x; then +# echo "Auto-detection of a filesystem module failed." 1>&2 +# echo "Please specify the module with the option \`--modules' explicitly." 1>&2 +# exit 1 +#fi + +# Typically, _chain and pc are required. +modules="$modules $fs_module _chain" + +modules="kernel gzio gpt fat normal ls cat fshelp help _linux linux $modules" +modules="$modules memmap systab boot" + +if [ $debug = yes ]; then + tmpdir=. +else + tmpdir=`mktemp -d /tmp/grub.XXXXXXXXXX` || exit 1 + trap "rm -rf $tmpdir" 1 2 13 15 +fi + +# Generate init/fini for modules. +modfile=$tmpdir/mod.c +echo "/* Dummy modules. */" > $modfile +list="" +init_list="" +fini_list="" +for m in $modules; do + file="$pkglibdir/${m}.mod" + name=`nm $file | sed -n "/ r grub_module_name/ s/.* r grub_module_name_\(.*\)/\1/p"` + init=`nm $file | sed -n "/ T grub_module_.*_init/ s/.* T //p"` + fini=`nm $file | sed -n "/ T grub_module_.*_fini/ s/.* T //p"` + init_list="$init_list $init" + fini_list="$fini_list $fini" + arg="\"$name\",${init:-0},${fini:-0}" + list="$list $arg" +done +echo "extern void grub_init_module (const char *, void (*init)(void *), void (*fini)(void));" >> $modfile +echo "extern void grub_init_modules (void);" >> $modfile +for m in $init_list; do + echo "extern void $m(void *);" >> $modfile +done +for m in $fini_list; do + echo "extern void $m(void);" >> $modfile +done +echo "void grub_init_modules (void)" >> $modfile +echo "{" >> $modfile +for m in $list; do + echo " grub_init_module($m);" >> $modfile +done +echo "}" >> $modfile + +$TARGET_CC -c $TARGET_CFLAGS -o $tmpdir/mod.o $modfile + +mod_objs= +for m in $modules; do mod_objs="$mod_objs $pkglibdir/${m}.mod"; done + +ld -pie -nostdlib -T $pkgdatadir/elf_ia64_efi.lds \ + $mod_objs $tmpdir/mod.o -o $tmpdir/grub.elf + + +if ! $bindir/grub-elf2pe $tmpdir/grub.elf $grubdir/grub.efi; then + echo "Failed to build efi binary" + [ $debug = no ] && rm -rf $tmpdir + exit 1 +fi + +echo "grub.efi generated" + +[ $debug = no ] && rm -rf $tmpdir + +# Bye. +exit 0 diff -ruNp -x '*~' -x CVS grub2.orig/util/ia64/efi/pe32.h grub2/util/ia64/efi/pe32.h --- grub2.orig/util/ia64/efi/pe32.h 1970-01-01 01:00:00.000000000 +0100 +++ grub2/util/ia64/efi/pe32.h 2008-01-28 16:29:58.000000000 +0100 @@ -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 . + */ +#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 +