From 2c40cc7868265137b8b8e0bbfc16f004d792c8cf Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Mon, 18 Jan 2010 14:17:47 +0000 Subject: [PATCH 001/406] Import Tristan Gingold's ia64 port (based on patch sent to grub-devel by Tristan in 2008-01-28) --- ChangeLog.ia64 | 45 ++ Makefile.in | 3 +- commands/efi/acpi.c | 193 ++++++++ commands/efi/memmap.c | 143 ++++++ commands/efi/systab.c | 258 +++++++++++ conf/ia64-efi.rmk | 122 +++++ configure.ac | 5 +- geninit.sh | 2 +- genmk.rb | 2 +- include/grub/dl.h | 14 +- include/grub/efi/efi.h | 7 + include/grub/ia64/efi/kernel.h | 33 ++ include/grub/ia64/efi/loader.h | 30 ++ include/grub/ia64/efi/misc.h | 24 + include/grub/ia64/efi/time.h | 23 + include/grub/ia64/setjmp.h | 31 ++ include/grub/ia64/time.h | 28 ++ include/grub/ia64/types.h | 32 ++ include/grub/kernel.h | 2 +- kern/dl.c | 23 + kern/efi/mm.c | 90 ++-- kern/ia64/efi/elf_ia64_efi.lds | 84 ++++ kern/ia64/efi/init.c | 59 +++ kern/ia64/efi/startup.S | 40 ++ kern/ia64/trampoline.S | 38 ++ loader/ia64/efi/linux.c | 776 +++++++++++++++++++++++++++++++ loader/ia64/efi/linux_normal.c | 107 +++++ normal/ia64/longjmp.S | 162 +++++++ normal/ia64/setjmp.S | 171 +++++++ util/ia64/efi/elf2pe.c | 812 +++++++++++++++++++++++++++++++++ util/ia64/efi/grub-install.in | 233 ++++++++++ util/ia64/efi/pe32.h | 237 ++++++++++ 32 files changed, 3791 insertions(+), 38 deletions(-) create mode 100644 ChangeLog.ia64 create mode 100644 commands/efi/acpi.c create mode 100644 commands/efi/memmap.c create mode 100644 commands/efi/systab.c create mode 100644 conf/ia64-efi.rmk create mode 100644 include/grub/ia64/efi/kernel.h create mode 100644 include/grub/ia64/efi/loader.h create mode 100644 include/grub/ia64/efi/misc.h create mode 100644 include/grub/ia64/efi/time.h create mode 100644 include/grub/ia64/setjmp.h create mode 100644 include/grub/ia64/time.h create mode 100644 include/grub/ia64/types.h create mode 100644 kern/ia64/efi/elf_ia64_efi.lds create mode 100644 kern/ia64/efi/init.c create mode 100644 kern/ia64/efi/startup.S create mode 100644 kern/ia64/trampoline.S create mode 100644 loader/ia64/efi/linux.c create mode 100644 loader/ia64/efi/linux_normal.c create mode 100644 normal/ia64/longjmp.S create mode 100644 normal/ia64/setjmp.S create mode 100644 util/ia64/efi/elf2pe.c create mode 100644 util/ia64/efi/grub-install.in create mode 100644 util/ia64/efi/pe32.h diff --git a/ChangeLog.ia64 b/ChangeLog.ia64 new file mode 100644 index 000000000..35417bec0 --- /dev/null +++ b/ChangeLog.ia64 @@ -0,0 +1,45 @@ +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. + * include/grub/efi/efi.h: Declare grub_efi_allocate_boot_pages and + grub_efi_free_boot_pages. + * include/grub/kernel.h: Export grub_machine_fini. + * include/grub/dl.h: Use attribute instead of raw asm statement. + Use grub_module as prefix to make identification easier. + * include/grub/ia64/efi/time.h: New file. + * include/grub/ia64/efi/misc.h: New file. + * include/grub/ia64/efi/loader.h: New file. + * include/grub/ia64/efi/kernel.h: New file. + * include/grub/ia64/time.h: New file. + * include/grub/ia64/setjmp.h: New file. + * include/grub/ia64/types.h: New file. + * kern/efi/mm.c (BYTES_TO_PAGES): Round instead of truncating. + (grub_efi_allocate_boot_pages): Low level interface to allocate_pages. + (grub_efi_free_boot_pages): Low level interface to free_pages. + (grub_efi_allocate_pages): Call grub_efi_allocate_boot_pages. + (grub_efi_free_pages): Call grubčefi_free_boot_pages. + (add_memory_regions): Add debug message in ifdef. + (add_memory_regions): Add debug message in ifdef. + (grub_efi_mm_init): Do not constraint memory map length, add space for + a few more entries. + * kern/dl.c (grub_init_module): New function. Register an already + linked module. + * kern/ia64/efi/elf_ia64_efi.lds: New file. + * kern/ia64/efi/startup.S: New file. + * kern/ia64/efi/init.c: New file. + * kern/ia64/trampoline.S: New file. diff --git a/Makefile.in b/Makefile.in index 84b4e9c7c..134505d3c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -67,6 +67,7 @@ TARGET_CFLAGS = @TARGET_CFLAGS@ TARGET_CPPFLAGS = @TARGET_CPPFLAGS@ -I. -Iinclude -I$(srcdir)/include \ -Wall -W TARGET_LDFLAGS = @TARGET_LDFLAGS@ +STRIP_FLAGS=--strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment OBJCOPY = @OBJCOPY@ STRIP = @STRIP@ NM = @NM@ @@ -83,7 +84,7 @@ enable_grub_emu = @enable_grub_emu@ ### General variables. RMKFILES = $(addprefix conf/,common.rmk i386-pc.rmk powerpc-ieee1275.rmk \ - sparc64-ieee1275.rmk i386-efi.rmk) + sparc64-ieee1275.rmk i386-efi.rmk ia64-efi.rmk) MKFILES = $(patsubst %.rmk,%.mk,$(RMKFILES)) PKGLIB = $(pkglib_IMAGES) $(pkglib_MODULES) $(pkglib_PROGRAMS) \ diff --git a/commands/efi/acpi.c b/commands/efi/acpi.c new file mode 100644 index 000000000..ea9783f00 --- /dev/null +++ b/commands/efi/acpi.c @@ -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 --git a/commands/efi/memmap.c b/commands/efi/memmap.c new file mode 100644 index 000000000..a3ce82841 --- /dev/null +++ b/commands/efi/memmap.c @@ -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 --git a/commands/efi/systab.c b/commands/efi/systab.c new file mode 100644 index 000000000..1d90ca9ca --- /dev/null +++ b/commands/efi/systab.c @@ -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 --git a/conf/ia64-efi.rmk b/conf/ia64-efi.rmk new file mode 100644 index 000000000..ce72d14c0 --- /dev/null +++ b/conf/ia64-efi.rmk @@ -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 --git a/configure.ac b/configure.ac index b3f73e0bd..895b5ffc3 100644 --- a/configure.ac +++ b/configure.ac @@ -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 --git a/geninit.sh b/geninit.sh index 43d2d1640..31a6d660b 100644 --- a/geninit.sh +++ b/geninit.sh @@ -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 --git a/genmk.rb b/genmk.rb index 43dbeacf5..e4abd56d5 100644 --- a/genmk.rb +++ b/genmk.rb @@ -115,7 +115,7 @@ UNDSYMFILES += #{undsym} #{@name}: #{pre_obj} #{mod_obj} -rm -f $@ $(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^ - $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ + $(STRIP) $(STRIP_FLAGS) $@ #{pre_obj}: $(#{prefix}_DEPENDENCIES) #{objs_str} -rm -f $@ diff --git a/include/grub/dl.h b/include/grub/dl.h index b630c6fcd..017846d79 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -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 --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h index fbc6be985..c45cbed02 100644 --- a/include/grub/efi/efi.h +++ b/include/grub/efi/efi.h @@ -42,6 +42,13 @@ EXPORT_FUNC(grub_efi_allocate_pages) (grub_efi_physical_address_t address, grub_efi_uintn_t pages); void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address, grub_efi_uintn_t pages); +void * +EXPORT_FUNC(grub_efi_allocate_boot_pages) (grub_efi_physical_address_t address, + grub_efi_uintn_t pages); +void +EXPORT_FUNC(grub_efi_free_boot_pages) (grub_efi_physical_address_t address, + grub_efi_uintn_t pages); + int EXPORT_FUNC(grub_efi_get_memory_map) (grub_efi_uintn_t *memory_map_size, grub_efi_memory_descriptor_t *memory_map, diff --git a/include/grub/ia64/efi/kernel.h b/include/grub/ia64/efi/kernel.h new file mode 100644 index 000000000..c0549f41a --- /dev/null +++ b/include/grub/ia64/efi/kernel.h @@ -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 --git a/include/grub/ia64/efi/loader.h b/include/grub/ia64/efi/loader.h new file mode 100644 index 000000000..623ae5c49 --- /dev/null +++ b/include/grub/ia64/efi/loader.h @@ -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 --git a/include/grub/ia64/efi/misc.h b/include/grub/ia64/efi/misc.h new file mode 100644 index 000000000..2037f7c24 --- /dev/null +++ b/include/grub/ia64/efi/misc.h @@ -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 --git a/include/grub/ia64/efi/time.h b/include/grub/ia64/efi/time.h new file mode 100644 index 000000000..897ce9c00 --- /dev/null +++ b/include/grub/ia64/efi/time.h @@ -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 --git a/include/grub/ia64/setjmp.h b/include/grub/ia64/setjmp.h new file mode 100644 index 000000000..c3b2d3be7 --- /dev/null +++ b/include/grub/ia64/setjmp.h @@ -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 --git a/include/grub/ia64/time.h b/include/grub/ia64/time.h new file mode 100644 index 000000000..5db7ff4f1 --- /dev/null +++ b/include/grub/ia64/time.h @@ -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 --git a/include/grub/ia64/types.h b/include/grub/ia64/types.h new file mode 100644 index 000000000..91a546dd2 --- /dev/null +++ b/include/grub/ia64/types.h @@ -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 --git a/include/grub/kernel.h b/include/grub/kernel.h index 4a4e2cc41..b1b8f5930 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -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 --git a/kern/dl.c b/kern/dl.c index 9e8c24aba..c6c6f00ec 100644 --- a/kern/dl.c +++ b/kern/dl.c @@ -579,6 +579,29 @@ grub_dl_load_core (void *addr, grub_size_t size) return mod; } +void +grub_init_module (const char *name, + void (*init)(grub_dl_t), void (*fini)(void)) +{ + grub_dl_t mod; + + mod = (grub_dl_t) grub_malloc (sizeof (*mod)); + if (! mod) + return; + + mod->name = name; + mod->ref_count = 1; + mod->dep = 0; + mod->segment = 0; + mod->init = init; + mod->fini = fini; + + grub_dl_call_init (mod); + + /* Can't fail. */ + grub_dl_add (mod); +} + /* Load a module from the file FILENAME. */ grub_dl_t grub_dl_load_file (const char *filename) diff --git a/kern/efi/mm.c b/kern/efi/mm.c index 9cd096d7d..6e55e3655 100644 --- a/kern/efi/mm.c +++ b/kern/efi/mm.c @@ -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_pages = 0; #define MIN_HEAP_SIZE 0x100000 #define MAX_HEAP_SIZE (16 * 0x100000) - /* Allocate pages. Return the pointer to the first of allocated pages. */ void * -grub_efi_allocate_pages (grub_efi_physical_address_t address, - grub_efi_uintn_t pages) +grub_efi_allocate_boot_pages (grub_efi_physical_address_t address, + grub_efi_uintn_t pages) { grub_efi_allocate_type_t type; grub_efi_status_t status; @@ -87,14 +84,34 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address, { /* Uggh, the address 0 was allocated... This is too annoying, so reallocate another one. */ - address = 0xffffffff; status = b->allocate_pages (type, GRUB_EFI_LOADER_DATA, pages, &address); - grub_efi_free_pages (0, pages); + grub_efi_free_boot_pages (0, pages); if (status != GRUB_EFI_SUCCESS) return 0; } - if (allocated_pages) + return (void *)address; +} + +/* Free pages starting from ADDRESS. */ +void +grub_efi_free_boot_pages (grub_efi_physical_address_t address, + grub_efi_uintn_t pages) +{ + grub_efi_boot_services_t *b; + + b = grub_efi_system_table->boot_services; + b->free_pages (address, pages); +} + +/* Allocate pages. Return the pointer to the first of allocated pages. */ +void * +grub_efi_allocate_pages (grub_efi_physical_address_t address, + grub_efi_uintn_t pages) +{ + address = grub_efi_allocate_boot_pages (address, pages); + + if (address != 0 && allocated_pages) { unsigned i; @@ -118,8 +135,6 @@ void grub_efi_free_pages (grub_efi_physical_address_t address, grub_efi_uintn_t pages) { - grub_efi_boot_services_t *b; - if (allocated_pages && ((grub_efi_physical_address_t) ((grub_addr_t) allocated_pages) != address)) @@ -133,9 +148,8 @@ grub_efi_free_pages (grub_efi_physical_address_t address, break; } } - - b = grub_efi_system_table->boot_services; - b->free_pages (address, pages); + + grub_efi_free_boot_pages (address, pages); } /* Get the memory map as defined in the EFI spec. Return 1 if successful, @@ -278,7 +292,11 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, grub_efi_uint64_t required_pages) { grub_efi_memory_descriptor_t *desc; - + +#ifdef DEBUG_MM + grub_printf ("mm: required_pages=%lu\n", required_pages); +#endif + for (desc = memory_map; desc < memory_map_end; desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) @@ -303,6 +321,10 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, grub_mm_init_region (addr, PAGES_TO_BYTES (pages)); +#ifdef DEBUG_MM + grub_printf ("mm: add %lu pages from %p\n", pages, addr); +#endif + required_pages -= pages; if (required_pages == 0) break; @@ -344,6 +366,8 @@ grub_efi_mm_init (void) grub_efi_uintn_t desc_size; grub_efi_uint64_t total_pages; grub_efi_uint64_t required_pages; + grub_efi_uintn_t memory_map_size; + int res; /* First of all, allocate pages to maintain allocations. */ allocated_pages @@ -352,26 +376,35 @@ grub_efi_mm_init (void) grub_fatal ("cannot allocate memory"); grub_memset (allocated_pages, 0, ALLOCATED_PAGES_SIZE); - + /* Prepare a memory region to store two memory maps. */ - memory_map = grub_efi_allocate_pages (0, - 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + memory_map_size = 0; + res = grub_efi_get_memory_map (&memory_map_size, NULL, 0, &desc_size, 0); + if (res != 0) + grub_fatal ("cannot get memory map size"); + + /* Add space for a few more entries as allocating pages can increase + memory map size. */ + memory_map_size += 4 * desc_size; + + memory_map = grub_efi_allocate_pages + (0, 2 * BYTES_TO_PAGES (memory_map_size)); if (! memory_map) grub_fatal ("cannot allocate memory"); - filtered_memory_map = NEXT_MEMORY_DESCRIPTOR (memory_map, MEMORY_MAP_SIZE); + filtered_memory_map = NEXT_MEMORY_DESCRIPTOR (memory_map, memory_map_size); /* Obtain descriptors for available memory. */ - map_size = MEMORY_MAP_SIZE; + map_size = memory_map_size; - if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) < 0) + if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) <= 0) grub_fatal ("cannot get memory map"); memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size); filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map, desc_size, memory_map_end); - + /* By default, request a quarter of the available memory. */ total_pages = get_total_pages (filtered_memory_map, desc_size, filtered_memory_map_end); @@ -391,7 +424,7 @@ grub_efi_mm_init (void) #if 0 /* For debug. */ - map_size = MEMORY_MAP_SIZE; + map_size = memory_map_size; if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) < 0) grub_fatal ("cannot get memory map"); @@ -404,7 +437,7 @@ grub_efi_mm_init (void) /* Release the memory maps. */ grub_efi_free_pages ((grub_addr_t) memory_map, - 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + 2 * BYTES_TO_PAGES (memory_map_size)); } void @@ -420,10 +453,13 @@ grub_efi_mm_fini (void) p = allocated_pages + i; if (p->addr != 0) - grub_efi_free_pages ((grub_addr_t) p->addr, p->num_pages); + { + grub_efi_free_pages ((grub_addr_t) p->addr, p->num_pages); + } } grub_efi_free_pages ((grub_addr_t) allocated_pages, BYTES_TO_PAGES (ALLOCATED_PAGES_SIZE)); + allocated_pages = 0; } } diff --git a/kern/ia64/efi/elf_ia64_efi.lds b/kern/ia64/efi/elf_ia64_efi.lds new file mode 100644 index 000000000..b6889d4af --- /dev/null +++ b/kern/ia64/efi/elf_ia64_efi.lds @@ -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 --git a/kern/ia64/efi/init.c b/kern/ia64/efi/init.c new file mode 100644 index 000000000..c85ef6c42 --- /dev/null +++ b/kern/ia64/efi/init.c @@ -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 --git a/kern/ia64/efi/startup.S b/kern/ia64/efi/startup.S new file mode 100644 index 000000000..9ba6858d9 --- /dev/null +++ b/kern/ia64/efi/startup.S @@ -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 loc2=@gprel(grub_efi_image_handle),gp + addl loc3=@gprel(grub_efi_system_table),gp + ;; + st8 [loc2]=in0 + st8 [loc3]=in1 + br.call.sptk.few rp=grub_main + ;; + mov ar.pfs=loc0 + mov rp=loc1 + ;; + br.ret.sptk.few rp + + .endp _start diff --git a/kern/ia64/trampoline.S b/kern/ia64/trampoline.S new file mode 100644 index 000000000..376b7bae0 --- /dev/null +++ b/kern/ia64/trampoline.S @@ -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 --git a/loader/ia64/efi/linux.c b/loader/ia64/efi/linux.c new file mode 100644 index 000000000..04c4638f8 --- /dev/null +++ b/loader/ia64/efi/linux.c @@ -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 --git a/loader/ia64/efi/linux_normal.c b/loader/ia64/efi/linux_normal.c new file mode 100644 index 000000000..3a567b09f --- /dev/null +++ b/loader/ia64/efi/linux_normal.c @@ -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 --git a/normal/ia64/longjmp.S b/normal/ia64/longjmp.S new file mode 100644 index 000000000..23dec8687 --- /dev/null +++ b/normal/ia64/longjmp.S @@ -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 --git a/normal/ia64/setjmp.S b/normal/ia64/setjmp.S new file mode 100644 index 000000000..4bc2103b7 --- /dev/null +++ b/normal/ia64/setjmp.S @@ -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 --git a/util/ia64/efi/elf2pe.c b/util/ia64/efi/elf2pe.c new file mode 100644 index 000000000..23687fe68 --- /dev/null +++ b/util/ia64/efi/elf2pe.c @@ -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 --git a/util/ia64/efi/grub-install.in b/util/ia64/efi/grub-install.in new file mode 100644 index 000000000..63b0c9f6c --- /dev/null +++ b/util/ia64/efi/grub-install.in @@ -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. +prefix=@prefix@ +exec_prefix=@exec_prefix@ +sbindir=@sbindir@ +bindir=@bindir@ +libdir=@libdir@ +datadir=@datadir@ +PACKAGE_NAME=@PACKAGE_NAME@ +PACKAGE_TARNAME=@PACKAGE_TARNAME@ +PACKAGE_VERSION=@PACKAGE_VERSION@ +target_cpu=@target_cpu@ +platform=@platform@ +pkglibdir=${libdir}/${PACKAGE_TARNAME}/${target_cpu}-${platform} +pkgdatadir=${datadir}/${PACKAGE_TARNAME} + + +TARGET_CC=@TARGET_CC@ +TARGET_CFLAGS="@TARGET_CFLAGS@" +TARGET_CPPFLAGS="@TARGET_CPPFLAGS@" +TARGET_LDFLAGS="@TARGET_LDFLAGS@" +OBJCOPY=@OBJCOPY@ + +grub_setup=${sbindir}/grub-setup +grub_mkimage=${bindir}/grub-mkimage +grub_mkdevicemap=${sbindir}/grub-mkdevicemap +grub_probefs=${sbindir}/grub-probefs +rootdir= +grub_prefix=/boot/grub +modules= + +install_device= +recheck=no +debug=no + +# Usage: usage +# Print the usage. +usage () { + cat <. +EOF +} + +# Check the arguments. +for option in "$@"; do + case "$option" in + -h | --help) + usage + exit 0 ;; + -v | --version) + echo "grub-install (GNU GRUB ${PACKAGE_VERSION})" + exit 0 ;; + --modules=*) + modules=`echo "$option" | sed 's/--modules=//'` ;; + --root-directory=*) + rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + --grub-setup=*) + grub_setup=`echo "$option" | sed 's/--grub-setup=//'` ;; + --grub-mkimage=*) + grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; + --grub-mkdevicemap=*) + grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;; + --grub-probefs=*) + grub_probefs=`echo "$option" | sed 's/--grub-probefs=//'` ;; + --pkglibdir=*) + pkglibdir=`echo "$option" | sed 's/--pkglibdir=//'` ;; + --pkgdatadir=*) + pkgdatadir=`echo "$option" | sed 's/--pkgdatadir=//'` ;; + --recheck) + recheck=yes ;; + # This is an undocumented feature... + --debug) + debug=yes ;; + -*) + echo "Unrecognized option \`$option'" 1>&2 + usage + exit 1 + ;; + *) + if test "x$install_device" != x; then + echo "More than one install_devices?" 1>&2 + usage + exit 1 + fi + install_device="${option}" ;; + esac +done + +#if test "x$install_device" = x; then +# echo "install_device not specified." 1>&2 +# usage +# exit 1 +#fi + +# If the debugging feature is enabled, print commands. +if test $debug = yes; then + set -x +fi + +# Initialize these directories here, since ROOTDIR was initialized. +bootdir=${rootdir}/boot/efi + +grubdir=${bootdir}/grub +device_map=${grubdir}/device.map + +# Create the GRUB directory if it is not present. +test -d "$bootdir" || mkdir "$bootdir" || exit 1 +test -d "$grubdir" || mkdir "$grubdir" || exit 1 + +# Copy the GRUB images to the GRUB directory. +if false; then + for file in ${grubdir}/*.mod ${grubdir}/*.lst; do + if test -f $file; then + rm -f $file || exit 1 + fi + done + for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst; do + cp -f $file ${grubdir} || exit 1 + done +fi + +# Create the core image. First, auto-detect the filesystme module. +#fs_module=`$grub_probefs --device-map=${device_map} ${grubdir}` +#if test "x$fs_module" = x -a "x$modules" = x; then +# echo "Auto-detection of a filesystem module failed." 1>&2 +# echo "Please specify the module with the option \`--modules' explicitly." 1>&2 +# exit 1 +#fi + +# Typically, _chain and pc are required. +modules="$modules $fs_module _chain" + +modules="kernel gzio gpt fat normal ls cat fshelp help _linux linux $modules" +modules="$modules memmap systab boot" + +if [ $debug = yes ]; then + tmpdir=. +else + tmpdir=`mktemp -d /tmp/grub.XXXXXXXXXX` || exit 1 + trap "rm -rf $tmpdir" 1 2 13 15 +fi + +# Generate init/fini for modules. +modfile=$tmpdir/mod.c +echo "/* Dummy modules. */" > $modfile +list="" +init_list="" +fini_list="" +for m in $modules; do + file="$pkglibdir/${m}.mod" + name=`nm $file | sed -n "/ r grub_module_name/ s/.* r grub_module_name_\(.*\)/\1/p"` + init=`nm $file | sed -n "/ T grub_module_.*_init/ s/.* T //p"` + fini=`nm $file | sed -n "/ T grub_module_.*_fini/ s/.* T //p"` + init_list="$init_list $init" + fini_list="$fini_list $fini" + arg="\"$name\",${init:-0},${fini:-0}" + list="$list $arg" +done +echo "extern void grub_init_module (const char *, void (*init)(void *), void (*fini)(void));" >> $modfile +echo "extern void grub_init_modules (void);" >> $modfile +for m in $init_list; do + echo "extern void $m(void *);" >> $modfile +done +for m in $fini_list; do + echo "extern void $m(void);" >> $modfile +done +echo "void grub_init_modules (void)" >> $modfile +echo "{" >> $modfile +for m in $list; do + echo " grub_init_module($m);" >> $modfile +done +echo "}" >> $modfile + +$TARGET_CC -c $TARGET_CFLAGS -o $tmpdir/mod.o $modfile + +mod_objs= +for m in $modules; do mod_objs="$mod_objs $pkglibdir/${m}.mod"; done + +ld -pie -nostdlib -T $pkgdatadir/elf_ia64_efi.lds \ + $mod_objs $tmpdir/mod.o -o $tmpdir/grub.elf + + +if ! $bindir/grub-elf2pe $tmpdir/grub.elf $grubdir/grub.efi; then + echo "Failed to build efi binary" + [ $debug = no ] && rm -rf $tmpdir + exit 1 +fi + +echo "grub.efi generated" + +[ $debug = no ] && rm -rf $tmpdir + +# Bye. +exit 0 diff --git a/util/ia64/efi/pe32.h b/util/ia64/efi/pe32.h new file mode 100644 index 000000000..391e70c26 --- /dev/null +++ b/util/ia64/efi/pe32.h @@ -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 + From c8298743f3b1caf683789c60c7daf0e00a34b48d Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Mon, 18 Jan 2010 14:24:17 +0000 Subject: [PATCH 002/406] Second version of the patch (sent to grub-devel in 2008-01-29) --- ChangeLog.ia64 | 1 - Makefile.in | 7 +++---- commands/efi/acpi.c | 11 ++++------- conf/ia64-efi.rmk | 9 +++++++-- config.h.in | 4 ++-- include/grub/ia64/efi/kernel.h | 2 +- include/grub/ia64/setjmp.h | 2 +- include/grub/ia64/time.h | 2 +- kern/ia64/trampoline.S | 8 ++++---- loader/ia64/efi/linux.c | 12 ++++++++---- loader/ia64/efi/linux_normal.c | 2 +- normal/ia64/longjmp.S | 2 +- normal/ia64/setjmp.S | 2 +- util/ia64/efi/elf2pe.c | 4 ++-- 14 files changed, 36 insertions(+), 32 deletions(-) diff --git a/ChangeLog.ia64 b/ChangeLog.ia64 index 35417bec0..64562fb23 100644 --- a/ChangeLog.ia64 +++ b/ChangeLog.ia64 @@ -3,7 +3,6 @@ * 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. diff --git a/Makefile.in b/Makefile.in index 134505d3c..5e8e07dbb 100644 --- a/Makefile.in +++ b/Makefile.in @@ -83,8 +83,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 ia64-efi.rmk) +RMKFILES = $(wildcard $(srcdir)/conf/*.rmk) MKFILES = $(patsubst %.rmk,%.mk,$(RMKFILES)) PKGLIB = $(pkglib_IMAGES) $(pkglib_MODULES) $(pkglib_PROGRAMS) \ @@ -98,13 +97,13 @@ MOSTLYCLEANFILES = DISTCLEANFILES = config.status config.cache config.log config.h \ Makefile stamp-h include/grub/cpu include/grub/machine \ gensymlist.sh genkernsyms.sh -MAINTAINER_CLEANFILES = $(srcdir)/configure $(addprefix $(srcdir)/,$(MKFILES)) +MAINTAINER_CLEANFILES = $(srcdir)/configure $(MKFILES) # The default target. all: all-local ### Include an arch-specific Makefile. -$(addprefix $(srcdir)/,$(MKFILES)): %.mk: %.rmk genmk.rb +$(MKFILES): %.mk: %.rmk genmk.rb if test "x$(RUBY)" = x; then \ touch $@; \ else \ diff --git a/commands/efi/acpi.c b/commands/efi/acpi.c index ea9783f00..e65fa0702 100644 --- a/commands/efi/acpi.c +++ b/commands/efi/acpi.c @@ -1,4 +1,4 @@ -/* acpi.c - Display acpi. */ +/* acpi.c - Display acpi tables. */ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 2008 Free Software Foundation, Inc. @@ -23,20 +23,17 @@ static grub_uint32_t read16 (grub_uint8_t *p) { - return p[0] | (p[1] << 8); + return grub_le_to_cpu16 (*(grub_uint16_t *)p); } static grub_uint32_t read32 (grub_uint8_t *p) { - return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); + return grub_le_to_cpu32 (*(grub_uint32_t *)p); } 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); + return grub_le_to_cpu64 (*(grub_uint64_t *)p); } static void diff --git a/conf/ia64-efi.rmk b/conf/ia64-efi.rmk index ce72d14c0..d65fda6d5 100644 --- a/conf/ia64-efi.rmk +++ b/conf/ia64-efi.rmk @@ -20,6 +20,7 @@ pkgdata_DATA += kern/ia64/efi/elf_ia64_efi.lds # For grub-elf2pe grub_elf2pe_SOURCES = util/ia64/efi/elf2pe.c +grub_elf2pe_CFLAGS = -DELF2PE_IA64 # For grub-emu. grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \ @@ -27,8 +28,12 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.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 \ + \ + fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \ + fs/hfsplus.c fs/iso9660.c fs/jfs.c fs/minix.c \ + fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c \ + fs/ufs.c fs/xfs.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 \ diff --git a/config.h.in b/config.h.in index 1aef2123b..c22d5b12b 100644 --- a/config.h.in +++ b/config.h.in @@ -88,10 +88,10 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION -/* The size of `long', as computed by sizeof. */ +/* The size of a `long', as computed by sizeof. */ #undef SIZEOF_LONG -/* The size of `void *', as computed by sizeof. */ +/* The size of a `void *', as computed by sizeof. */ #undef SIZEOF_VOID_P /* Define it to either start or _start */ diff --git a/include/grub/ia64/efi/kernel.h b/include/grub/ia64/efi/kernel.h index c0549f41a..af1a35b51 100644 --- a/include/grub/ia64/efi/kernel.h +++ b/include/grub/ia64/efi/kernel.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2007 Free Software Foundation, Inc. + * Copyright (C) 2002,2003,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 diff --git a/include/grub/ia64/setjmp.h b/include/grub/ia64/setjmp.h index c3b2d3be7..7689a73dd 100644 --- a/include/grub/ia64/setjmp.h +++ b/include/grub/ia64/setjmp.h @@ -1,5 +1,5 @@ /* Define the machine-dependent type `jmp_buf'. Linux/IA-64 version. - Copyright (C) 1999, 2000 Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2008 Free Software Foundation, Inc. Contributed by David Mosberger-Tang . The GNU C Library is free software; you can redistribute it and/or diff --git a/include/grub/ia64/time.h b/include/grub/ia64/time.h index 5db7ff4f1..03ee79fa4 100644 --- a/include/grub/ia64/time.h +++ b/include/grub/ia64/time.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2007 Free Software Foundation, Inc. + * Copyright (C) 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 diff --git a/kern/ia64/trampoline.S b/kern/ia64/trampoline.S index 376b7bae0..e91991041 100644 --- a/kern/ia64/trampoline.S +++ b/kern/ia64/trampoline.S @@ -23,15 +23,15 @@ .proc __ia64_trampoline .global __ia64_trampoline __ia64_trampoline: - // Read address of the real descriptor + /* Read address of the real descriptor. */ ld8 r2=[r1],8 ;; - // Read chain + /* Read chain. */ ld8 r15=[r1] - // Read pc + /* Read pc. */ ld8 r3=[r2],8 ;; - // Read gp + /* Read gp. */ ld8 r1=[r2] mov b6=r3 br.many b6 diff --git a/loader/ia64/efi/linux.c b/loader/ia64/efi/linux.c index 04c4638f8..47f51c5da 100644 --- a/loader/ia64/efi/linux.c +++ b/loader/ia64/efi/linux.c @@ -39,14 +39,16 @@ #define BOOT_PARAM_SIZE 16384 -struct ia64_boot_param { +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 { + 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 */ @@ -61,7 +63,8 @@ struct ia64_boot_param { grub_uint64_t modules_nbr; }; -struct ia64_boot_module { +struct ia64_boot_module +{ grub_uint64_t mod_start; grub_uint64_t mod_end; @@ -71,7 +74,8 @@ struct ia64_boot_module { grub_uint64_t next; }; -typedef struct { +typedef struct +{ grub_uint32_t revision; grub_uint32_t reserved; void *fpswa; diff --git a/loader/ia64/efi/linux_normal.c b/loader/ia64/efi/linux_normal.c index 3a567b09f..ec18c4b9b 100644 --- a/loader/ia64/efi/linux_normal.c +++ b/loader/ia64/efi/linux_normal.c @@ -101,7 +101,7 @@ GRUB_MOD_FINI(linux_normal) { grub_unregister_command ("linux"); grub_unregister_command ("initrd"); - grub_unregister_command ("normal"); + grub_unregister_command ("module"); grub_unregister_command ("relocate"); grub_unregister_command ("fpswa"); } diff --git a/normal/ia64/longjmp.S b/normal/ia64/longjmp.S index 23dec8687..729bdc76e 100644 --- a/normal/ia64/longjmp.S +++ b/normal/ia64/longjmp.S @@ -1,4 +1,4 @@ -/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +/* Copyright (C) 1999, 2000, 2001, 2002, 2008 Free Software Foundation, Inc. Contributed by David Mosberger-Tang . The GNU C Library is free software; you can redistribute it and/or diff --git a/normal/ia64/setjmp.S b/normal/ia64/setjmp.S index 4bc2103b7..0851885c5 100644 --- a/normal/ia64/setjmp.S +++ b/normal/ia64/setjmp.S @@ -1,4 +1,4 @@ -/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +/* Copyright (C) 1999, 2000, 2001, 2002, 2008 Free Software Foundation, Inc. Contributed by David Mosberger-Tang . The GNU C Library is free software; you can redistribute it and/or diff --git a/util/ia64/efi/elf2pe.c b/util/ia64/efi/elf2pe.c index 23687fe68..2840e3337 100644 --- a/util/ia64/efi/elf2pe.c +++ b/util/ia64/efi/elf2pe.c @@ -23,12 +23,12 @@ #include #include -#if defined(i386) +#if defined(ELF2PE_I386) #define USE_ELF32 #define USE_PE32 #define ELF_MACHINE EM_386 #define EFI_MACHINE PE32_MACHINE_I386 -#elif defined(__ia64__) +#elif defined(ELF2PE_IA64) #define USE_ELF64 #define USE_PE32PLUS #define ELF_MACHINE EM_IA_64 From 45220d832e50f01524abe27892ab4a71619868be Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Mon, 18 Jan 2010 14:28:03 +0000 Subject: [PATCH 003/406] Third version of the patch (sent to grub-devel in 2008-01-30) --- include/grub/ia64/efi/loader.h | 2 +- loader/ia64/efi/linux.c | 103 +++++++++++++++++---------------- loader/ia64/efi/linux_normal.c | 12 ++-- util/ia64/efi/elf2pe.c | 20 +++---- 4 files changed, 69 insertions(+), 68 deletions(-) diff --git a/include/grub/ia64/efi/loader.h b/include/grub/ia64/efi/loader.h index 623ae5c49..5471a81b5 100644 --- a/include/grub/ia64/efi/loader.h +++ b/include/grub/ia64/efi/loader.h @@ -23,7 +23,7 @@ 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_payload (int argc, char *argv[]); void grub_rescue_cmd_relocate (int argc, char *argv[]); void grub_rescue_cmd_fpswa (int argc, char *argv[]); diff --git a/loader/ia64/efi/linux.c b/loader/ia64/efi/linux.c index 47f51c5da..031bc20dd 100644 --- a/loader/ia64/efi/linux.c +++ b/loader/ia64/efi/linux.c @@ -27,7 +27,7 @@ #include #include #include -/* #include */ +#include #include #include #include @@ -59,16 +59,16 @@ struct ia64_boot_param 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; + grub_uint64_t payloads_chain; + grub_uint64_t payloads_nbr; }; -struct ia64_boot_module +struct ia64_boot_payload { - grub_uint64_t mod_start; - grub_uint64_t mod_end; + grub_uint64_t start; + grub_uint64_t length; - /* Module command line */ + /* Payload command line */ grub_uint64_t cmdline; grub_uint64_t next; @@ -101,7 +101,7 @@ 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; +static struct ia64_boot_payload *last_payload = NULL; /* Can linux kernel be relocated ? */ #define RELOCATE_OFF 0 /* No. */ @@ -133,14 +133,15 @@ query_fpswa (void) bs = grub_efi_system_table->boot_services; status = bs->locate_handle (GRUB_EFI_BY_PROTOCOL, - &fpswa_protocol, + (void *)&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); + status = bs->handle_protocol (fpswa_image, + (void *)&fpswa_protocol, (void *)&fpswa); if (status != GRUB_EFI_SUCCESS) { grub_printf ("Fpswa protocol not able find the interface\n"); @@ -204,20 +205,20 @@ free_pages (void) if (boot_param) { - struct ia64_boot_module *mod; - struct ia64_boot_module *next_mod; + struct ia64_boot_payload *payload; + struct ia64_boot_payload *next_payload; - /* Free modules. */ - mod = (struct ia64_boot_module *)boot_param->modules_chain; - while (mod != 0) + /* Free payloads. */ + payload = (struct ia64_boot_payload *)boot_param->payloads_chain; + while (payload != 0) { - next_mod = (struct ia64_boot_module *)mod->next; + next_payload = (struct ia64_boot_payload *)payload->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); + (payload->start, page_align (payload->length) >> 12); + grub_efi_free_boot_pages ((grub_efi_physical_address_t)payload, 1); - mod = next_mod; + payload = next_payload; } /* Free bootparam. */ @@ -446,8 +447,8 @@ grub_load_elf64 (grub_file_t file, void *buffer) 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", + reloc_offset = (grub_uint64_t)kernel_mem - low_addr; + grub_printf (" Relocated at %p (offset=%016lx)\n", kernel_mem, reloc_offset); entry += reloc_offset; } @@ -463,12 +464,12 @@ grub_load_elf64 (grub_file_t file, void *buffer) + i * ehdr->e_phentsize); if (phdr->p_type == PT_LOAD) { - grub_printf (" [paddr=%llx load=%llx memsz=%08llx " + grub_printf (" [paddr=%lx load=%lx memsz=%08lx " "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) + if (grub_file_seek (file, phdr->p_offset) == (grub_off_t)-1) return grub_error (GRUB_ERR_BAD_OS, "invalid offset in program header"); @@ -582,7 +583,7 @@ grub_rescue_cmd_initrd (int argc, char *argv[]) if (argc == 0) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified"); + grub_error (GRUB_ERR_BAD_ARGUMENT, "No filename specified"); goto fail; } @@ -619,12 +620,12 @@ grub_rescue_cmd_initrd (int argc, char *argv[]) } void -grub_rescue_cmd_module (int argc, char *argv[]) +grub_rescue_cmd_payload (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; + char *base = 0, *cmdline = 0, *p; + struct ia64_boot_payload *payload = NULL; int i; if (argc == 0) @@ -636,7 +637,7 @@ grub_rescue_cmd_module (int argc, char *argv[]) if (!boot_param) { grub_error (GRUB_ERR_BAD_ARGUMENT, - "You need to load the multiboot kernel first"); + "You need to load the kernel first"); goto fail; } @@ -645,47 +646,47 @@ grub_rescue_cmd_module (int argc, char *argv[]) goto fail; size = grub_file_size (file); - module = grub_efi_allocate_boot_pages (0, page_align (size) >> 12); - if (! module) + base = grub_efi_allocate_boot_pages (0, page_align (size) >> 12); + if (! base) goto fail; - grub_printf ("Module %s [addr=%llx + %lx]\n", - argv[0], (grub_uint64_t)module, size); + grub_printf ("Payload %s [addr=%lx + %lx]\n", + argv[0], (grub_uint64_t)base, size); - if (grub_file_read (file, module, size) != size) + if (grub_file_read (file, base, size) != size) { grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file"); goto fail; } - len = sizeof (struct ia64_boot_module); + len = sizeof (struct ia64_boot_payload); 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"); + grub_error (GRUB_ERR_OUT_OF_RANGE, "payload command line too long"); goto fail; } - mod = grub_efi_allocate_boot_pages (0, 1); - if (! mod) + payload = grub_efi_allocate_boot_pages (0, 1); + if (! payload) goto fail; - p = (char *)(mod + 1); + p = (char *)(payload + 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; + payload->start = (grub_uint64_t)base; + payload->length = size; + payload->cmdline = (grub_uint64_t)p; + payload->next = 0; - if (last_module) - last_module->next = (grub_uint64_t)mod; + if (last_payload) + last_payload->next = (grub_uint64_t)payload; else { - last_module = mod; - boot_param->modules_chain = (grub_uint64_t)mod; + last_payload = payload; + boot_param->payloads_chain = (grub_uint64_t)payload; } - boot_param->modules_nbr++; + boot_param->payloads_nbr++; /* Copy command line. */ for (i = 0; i < argc; i++) @@ -704,7 +705,7 @@ grub_rescue_cmd_module (int argc, char *argv[]) if (grub_errno != GRUB_ERR_NONE) { - grub_free (module); + grub_free (base); grub_free (cmdline); } } @@ -761,8 +762,8 @@ GRUB_MOD_INIT(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 ("payload", grub_rescue_cmd_payload, + "load an additional file"); grub_rescue_register_command ("relocate", grub_rescue_cmd_relocate, "set relocate feature"); grub_rescue_register_command ("fpswa", grub_rescue_cmd_fpswa, @@ -774,7 +775,7 @@ GRUB_MOD_FINI(linux) { grub_rescue_unregister_command ("linux"); grub_rescue_unregister_command ("initrd"); - grub_rescue_unregister_command ("module"); + grub_rescue_unregister_command ("payload"); grub_rescue_unregister_command ("relocate"); grub_rescue_unregister_command ("fpswa"); } diff --git a/loader/ia64/efi/linux_normal.c b/loader/ia64/efi/linux_normal.c index ec18c4b9b..b5ddffb0d 100644 --- a/loader/ia64/efi/linux_normal.c +++ b/loader/ia64/efi/linux_normal.c @@ -40,10 +40,10 @@ grub_normal_initrd_command (struct grub_arg_list *state __attribute__ ((unused)) } static grub_err_t -grub_normal_cmd_module (struct grub_arg_list *state __attribute__ ((unused)), +grub_normal_cmd_payload (struct grub_arg_list *state __attribute__ ((unused)), int argc, char **args) { - grub_rescue_cmd_module (argc, args); + grub_rescue_cmd_payload (argc, args); return grub_errno; } @@ -79,10 +79,10 @@ GRUB_MOD_INIT(linux_normal) "Load an initrd.", 0); grub_register_command - ("module", grub_normal_cmd_module, + ("payload", grub_normal_cmd_payload, GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, - "module FILE [ARGS...]", - "Load a Multiboot module.", 0); + "payload FILE [ARGS...]", + "Load an additional file.", 0); grub_register_command ("relocate", grub_normal_cmd_relocate, @@ -101,7 +101,7 @@ GRUB_MOD_FINI(linux_normal) { grub_unregister_command ("linux"); grub_unregister_command ("initrd"); - grub_unregister_command ("module"); + grub_unregister_command ("payload"); grub_unregister_command ("relocate"); grub_unregister_command ("fpswa"); } diff --git a/util/ia64/efi/elf2pe.c b/util/ia64/efi/elf2pe.c index 2840e3337..66d28bde8 100644 --- a/util/ia64/efi/elf2pe.c +++ b/util/ia64/efi/elf2pe.c @@ -70,7 +70,7 @@ typedef Elf64_Sym Elf_Sym; #define ELF_R_SYM(r) ELF64_R_SYM(r) #endif -#ifdef __ia64__ +#ifdef ELF2PE_IA64 #define ELF_ETYPE ET_DYN #else #define ELF_ETYPE ET_EXEC @@ -99,7 +99,7 @@ uint32_t text_offset; uint32_t data_offset; uint32_t reloc_offset; -#ifdef __ia64__ +#ifdef ELF2PE_IA64 uint32_t coff_entry_descr_offset; uint32_t coff_entry_descr_func; uint64_t plt_base; @@ -160,7 +160,7 @@ is_text_shdr (Elf_Shdr *shdr) if (shdr->sh_type != SHT_PROGBITS) { return 0; } -#ifdef __ia64__ +#ifdef ELF2PE_IA64 return (shdr->sh_flags & (SHF_EXECINSTR | SHF_ALLOC)) == (SHF_ALLOC | SHF_EXECINSTR); #else @@ -229,7 +229,7 @@ scan_sections (void) } coff_sections_offset[i] = coff_offset; coff_offset += shdr->sh_size; -#ifdef __ia64__ +#ifdef ELF2PE_IA64 if (coff_sections_offset[i] != shdr->sh_addr) { fprintf (stderr, "Section %s: Coff offset (%x) != Elf offset (%lx)", @@ -244,7 +244,7 @@ scan_sections (void) shdr_dynamic = shdr; } } -#ifdef __ia64__ +#ifdef ELF2PE_IA64 /* 16 bytes are reserved (by the ld script) for the entry point descriptor. */ coff_entry_descr_offset = coff_offset - 16; @@ -259,7 +259,7 @@ scan_sections (void) if (is_data_shdr (shdr)) { coff_sections_offset[i] = coff_offset; coff_offset += shdr->sh_size; -#ifdef __ia64__ +#ifdef ELF2PE_IA64 if (coff_sections_offset[i] != shdr->sh_addr) { fprintf (stderr, "Section %s: Coff offset (%x) != Elf offset (%lx)", @@ -307,7 +307,7 @@ scan_sections (void) 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__ +#ifdef ELF2PE_IA64 nt_hdr->optional_header.entry_addr = coff_entry_descr_offset; coff_entry_descr_func = coff_entry; #else @@ -335,7 +335,7 @@ scan_sections (void) PE32_SCN_CNT_INITIALIZED_DATA | PE32_SCN_MEM_WRITE | PE32_SCN_MEM_READ); -#ifdef __ia64__ +#ifdef ELF2PE_IA64 if (shdr_dynamic != NULL) { Elf64_Dyn *dyn = (Elf64_Dyn*)((uint8_t*)ehdr + shdr_dynamic->sh_offset); @@ -639,7 +639,7 @@ write_relocations(void) } } -#ifdef __ia64__ +#ifdef ELF2PE_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 @@ -719,7 +719,7 @@ convert_elf (uint8_t **file_buffer, unsigned int *file_length) if (write_sections (is_text_shdr) != 0) return -3; -#ifdef __ia64__ +#ifdef ELF2PE_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 From 85312e19336ae0f773b811f1f9f69832d6ef1f75 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Mon, 18 Jan 2010 16:14:58 +0000 Subject: [PATCH 004/406] kernel.h adjustments to fix build --- ChangeLog.ia64 | 2 ++ include/grub/ia64/efi/kernel.h | 13 +++++++------ include/grub/ia64/kernel.h | 25 +++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 include/grub/ia64/kernel.h diff --git a/ChangeLog.ia64 b/ChangeLog.ia64 index 64562fb23..453cbd88c 100644 --- a/ChangeLog.ia64 +++ b/ChangeLog.ia64 @@ -1,4 +1,5 @@ 2008-01-28 Tristan Gingold +2010-01-18 Robert Millan * geninit.sh: Call _init with a null argument. * configure.ac: Add ia64-efi target. @@ -24,6 +25,7 @@ * 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/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. diff --git a/include/grub/ia64/efi/kernel.h b/include/grub/ia64/efi/kernel.h index af1a35b51..ae75380f0 100644 --- a/include/grub/ia64/efi/kernel.h +++ b/include/grub/ia64/efi/kernel.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2007,2008 Free Software Foundation, Inc. + * Copyright (C) 2002,2003,2007,2008,2010 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 @@ -19,15 +19,16 @@ #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 */ +#ifndef ASM_FILE +/* The prefix which points to the directory where GRUB modules and its + configuration file are located. */ +extern char grub_prefix[]; +#endif +#endif /* ! GRUB_MACHINE_KERNEL_HEADER */ diff --git a/include/grub/ia64/kernel.h b/include/grub/ia64/kernel.h new file mode 100644 index 000000000..c5496a00b --- /dev/null +++ b/include/grub/ia64/kernel.h @@ -0,0 +1,25 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 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_CPU_KERNEL_HEADER +#define GRUB_CPU_KERNEL_HEADER 1 + +#define GRUB_MOD_ALIGN 0x1 +#define GRUB_MOD_GAP 0x0 + +#endif /* ! GRUB_CPU_KERNEL_HEADER */ From c5565c52925a729ffeb275ff1a848376dd6bd543 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Mon, 18 Jan 2010 17:35:27 +0000 Subject: [PATCH 005/406] Rewrite ia64-efi.rmk --- conf/ia64-efi.rmk | 138 ++++++++++++---------------------------------- 1 file changed, 36 insertions(+), 102 deletions(-) diff --git a/conf/ia64-efi.rmk b/conf/ia64-efi.rmk index d65fda6d5..34f028606 100644 --- a/conf/ia64-efi.rmk +++ b/conf/ia64-efi.rmk @@ -2,126 +2,60 @@ COMMON_ASFLAGS = -nostdinc -fno-builtin COMMON_CFLAGS = -fno-builtin -fpic -minline-int-divide-max-throughput -COMMON_LDFLAGS = -melf_64 -nostdlib +COMMON_LDFLAGS = -melf_64 -nostdlib -STRIP_FLAGS=-R .note -R .comment -X +STRIP_FLAGS = -R .note -R .comment -X -# Utilities. -bin_UTILITIES = grub-elf2pe -#sbin_UTILITIES = grub-emu +# Used by various components. These rules need to precede them. +script/lexer.c_DEPENDENCIES = grub_script.tab.h -# Scripts. -sbin_SCRIPTS = grub-install +bin_UTILITIES += grub-elf2pe +grub_elf2pe_SOURCES = util/ia64/efi/elf2pe.c +grub_elf2pe_CFLAGS = -DELF2PE_IA64 -# For grub-install. +sbin_SCRIPTS += 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 -grub_elf2pe_CFLAGS = -DELF2PE_IA64 +pkglib_MODULES = kernel.img -# 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/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \ - fs/hfsplus.c fs/iso9660.c fs/jfs.c fs/minix.c \ - fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c \ - fs/ufs.c fs/xfs.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 \ +kernel_img_EXPORTS = no +kernel_img_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/disk.c kern/file.c kern/fs.c kern/err.c \ + kern/misc.c kern/mm.c kern/term.c \ + kern/rescue_parser.c kern/rescue_reader.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) + term/efi/console.c disk/efi/efidisk.c \ + kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ + kern/generic/rtc_get_time_ms.c \ + kern/generic/millisleep.c \ + commands/boot.c \ + loader/ia64/efi/linux.c \ + commands/halt.c \ + commands/reboot.c \ + commands/efi/memmap.c \ + commands/efi/systab.c \ + commands/efi/acpi2.c +kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ + env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \ + partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \ + cache.h ia64/efi/misc.h \ + efi/efi.h efi/time.h efi/disk.h i386/pit.h list.h handler.h command.h i18n.h +kernel_img_CFLAGS = $(COMMON_CFLAGS) +kernel_img_ASFLAGS = $(COMMON_ASFLAGS) +kernel_img_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 +symlist.c: $(addprefix include/grub/,$(kernel_img_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 +kernel_syms.lst: $(addprefix include/grub/,$(kernel_img_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 From 4e9fe6a2940955d0e84e02b058391409e5c00e9d Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Mon, 18 Jan 2010 17:36:16 +0000 Subject: [PATCH 006/406] Adjust loader for new command interface. --- loader/ia64/efi/linux.c | 51 ++++++++++------ loader/ia64/efi/linux_normal.c | 107 --------------------------------- 2 files changed, 32 insertions(+), 126 deletions(-) delete mode 100644 loader/ia64/efi/linux_normal.c diff --git a/loader/ia64/efi/linux.c b/loader/ia64/efi/linux.c index 031bc20dd..9020efd28 100644 --- a/loader/ia64/efi/linux.c +++ b/loader/ia64/efi/linux.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008 Free Software Foundation, Inc. + * Copyright (C) 2008,2010 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 @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -756,26 +756,39 @@ grub_rescue_cmd_fpswa (int argc, char *argv[] __attribute__((unused))) 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 ("payload", grub_rescue_cmd_payload, - "load an additional file"); - grub_rescue_register_command ("relocate", grub_rescue_cmd_relocate, - "set relocate feature"); - grub_rescue_register_command ("fpswa", grub_rescue_cmd_fpswa, - "load fpswa"); + grub_register_extcmd ("linux", grub_normal_linux_command, + GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, + "linux FILE [ARGS...]", + "Load Linux.", 0); + + grub_register_extcmd ("initrd", grub_normal_initrd_command, + GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, + "initrd FILE", + "Load initrd.", 0); + + grub_register_extcmd ("payload", grub_normal_cmd_payload, + GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, + "payload FILE [ARGS...]", + "Load an additional file.", 0); + + grub_register_extcmd ("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_extcmd ("fpswa", grub_normal_cmd_fpswa, + GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, + "fpswa", + "Display FPSWA version.", 0); + my_mod = mod; } GRUB_MOD_FINI(linux) { - grub_rescue_unregister_command ("linux"); - grub_rescue_unregister_command ("initrd"); - grub_rescue_unregister_command ("payload"); - grub_rescue_unregister_command ("relocate"); - grub_rescue_unregister_command ("fpswa"); + grub_unregister_command ("linux"); + grub_unregister_command ("initrd"); + grub_unregister_command ("payload"); + grub_unregister_command ("relocate"); + grub_unregister_command ("fpswa"); } diff --git a/loader/ia64/efi/linux_normal.c b/loader/ia64/efi/linux_normal.c deleted file mode 100644 index b5ddffb0d..000000000 --- a/loader/ia64/efi/linux_normal.c +++ /dev/null @@ -1,107 +0,0 @@ -/* 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_payload (struct grub_arg_list *state __attribute__ ((unused)), - int argc, char **args) -{ - grub_rescue_cmd_payload (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 - ("payload", grub_normal_cmd_payload, - GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, - "payload FILE [ARGS...]", - "Load an additional file.", 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 ("payload"); - grub_unregister_command ("relocate"); - grub_unregister_command ("fpswa"); -} From cba4bdc6a3aa122435d5ec7c96192b01ad3efe9a Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Mon, 18 Jan 2010 17:36:55 +0000 Subject: [PATCH 007/406] Move normal/ia64 to lib/ia64 --- {normal => lib}/ia64/longjmp.S | 0 {normal => lib}/ia64/setjmp.S | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {normal => lib}/ia64/longjmp.S (100%) rename {normal => lib}/ia64/setjmp.S (100%) diff --git a/normal/ia64/longjmp.S b/lib/ia64/longjmp.S similarity index 100% rename from normal/ia64/longjmp.S rename to lib/ia64/longjmp.S diff --git a/normal/ia64/setjmp.S b/lib/ia64/setjmp.S similarity index 100% rename from normal/ia64/setjmp.S rename to lib/ia64/setjmp.S From 78cd36e08da585214aec7643d0d82b1dc5d643e2 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Mon, 18 Jan 2010 17:37:19 +0000 Subject: [PATCH 008/406] Disable grub-mkelfimage. --- conf/common.rmk | 7 ------- 1 file changed, 7 deletions(-) diff --git a/conf/common.rmk b/conf/common.rmk index ffcdf045c..d97461753 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -11,13 +11,6 @@ else grub_mkdevicemap_SOURCES += util/devicemap.c endif -# For grub-mkelfimage. -bin_UTILITIES += grub-mkelfimage -grub_mkelfimage_SOURCES = gnulib/progname.c \ - util/elf/grub-mkimage.c util/misc.c \ - util/resolve.c -util/elf/grub-mkimage.c_DEPENDENCIES = Makefile - # For grub-probe. sbin_UTILITIES += grub-probe util/grub-probe.c_DEPENDENCIES = grub_probe_init.h From cdefd058dc54e6538a98de6809cf28c729bc7b9e Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Mon, 18 Jan 2010 17:37:51 +0000 Subject: [PATCH 009/406] grub_*_init() has no argument. Also add branch-specific "module_" prefix. --- geninit.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geninit.sh b/geninit.sh index 31a6d660b..15e9c76a6 100644 --- a/geninit.sh +++ b/geninit.sh @@ -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 (0);/' + echo $line | sed -e 's/.*GRUB_MOD_INIT *(\([a-zA-Z0-9_]*\)).*/ grub_module_\1_init ();/' fi done < ${lst} @@ -66,7 +66,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_fini ();/' + echo $line | sed -e 's/.*GRUB_MOD_INIT *(\([a-zA-Z0-9_]*\)).*/ grub_module_\1_fini ();/' fi done < ${lst} From 394ec6b646e72f8831a3d61db15433d1471fcf3f Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Mon, 18 Jan 2010 17:38:39 +0000 Subject: [PATCH 010/406] Adjust for new command interface. --- commands/efi/memmap.c | 8 ++++---- commands/efi/systab.c | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/commands/efi/memmap.c b/commands/efi/memmap.c index a3ce82841..d49e02080 100644 --- a/commands/efi/memmap.c +++ b/commands/efi/memmap.c @@ -132,12 +132,12 @@ grub_cmd_memmap (struct grub_arg_list *state, int argc, char **args) 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_register_extcmd ("memmap", grub_cmd_memmap, GRUB_COMMAND_FLAG_BOTH, + "memmap", + "Display memory map.", NULL); } GRUB_MOD_FINI(memmap) { - grub_unregister_command ("memmap"); + grub_unregister_extcmd ("memmap"); } diff --git a/commands/efi/systab.c b/commands/efi/systab.c index 1d90ca9ca..27a2cde83 100644 --- a/commands/efi/systab.c +++ b/commands/efi/systab.c @@ -246,13 +246,13 @@ grub_cmd_systab (struct grub_arg_list *state, int argc, char **args) 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); + (void) mod; /* To stop warning. */ + grub_register_extcmd ("systab", grub_cmd_systab, GRUB_COMMAND_FLAG_BOTH, + "systab [NAME]", + "Display EFI system table.", NULL); } GRUB_MOD_FINI(systab) { - grub_unregister_command ("systab"); + grub_unregister_extcmd ("systab"); } From d8a7de8d019702c5448e47f2d19db034f73b051b Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Mon, 18 Jan 2010 17:39:04 +0000 Subject: [PATCH 011/406] Remove memset() declaration (provided by ) --- include/grub/ia64/efi/misc.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/grub/ia64/efi/misc.h b/include/grub/ia64/efi/misc.h index 2037f7c24..2b99dda62 100644 --- a/include/grub/ia64/efi/misc.h +++ b/include/grub/ia64/efi/misc.h @@ -16,7 +16,6 @@ * along with GRUB. If not, see . */ -void EXPORT_FUNC (memset) (void); void EXPORT_FUNC (__ia64_trampoline) (void); void EXPORT_FUNC (grub_init_modules) (void); From e300c41cb28abbfbd6cff98d2cfd3d38d870f3db Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Mon, 18 Jan 2010 17:39:35 +0000 Subject: [PATCH 012/406] Disable calls to loadable modules (not supported yet) --- kern/main.c | 4 +++- kern/mm.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/kern/main.c b/kern/main.c index 7250c73e0..8626c256d 100644 --- a/kern/main.c +++ b/kern/main.c @@ -57,6 +57,7 @@ grub_module_iterate (int (*hook) (struct grub_module_header *header)) static void grub_load_modules (void) { +#if 0 auto int hook (struct grub_module_header *); int hook (struct grub_module_header *header) { @@ -72,6 +73,7 @@ grub_load_modules (void) } grub_module_iterate (hook); +#endif } static void @@ -136,7 +138,7 @@ static void grub_load_normal_mode (void) { /* Load the module. */ - grub_dl_load ("normal"); +// grub_dl_load ("normal"); /* Something went wrong. Print errors here to let user know why we're entering rescue mode. */ grub_print_error (); diff --git a/kern/mm.c b/kern/mm.c index ef97b018e..5d008dc4a 100644 --- a/kern/mm.c +++ b/kern/mm.c @@ -330,7 +330,7 @@ grub_memalign (grub_size_t align, grub_size_t size) case 1: /* Unload unneeded modules. */ - grub_dl_unload_unneeded (); +// grub_dl_unload_unneeded (); count++; goto again; From 4931b0984b1a526c6c86a47b200c2dbb58d2fa50 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 3 Mar 2010 20:09:48 +0100 Subject: [PATCH 013/406] Network infrastructure --- commands/net.c | 296 ++++++++++++++++++++++++++++++++++++++++++ commands/probe.c | 2 +- conf/common.rmk | 6 + include/grub/device.h | 6 +- include/grub/err.h | 5 +- include/grub/net.h | 248 +++++++++++++++++++++++++++++------ kern/fs.c | 2 +- 7 files changed, 522 insertions(+), 43 deletions(-) create mode 100644 commands/net.c diff --git a/commands/net.c b/commands/net.c new file mode 100644 index 000000000..288ba4c2a --- /dev/null +++ b/commands/net.c @@ -0,0 +1,296 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 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 + +struct grub_net_route *grub_net_routes = NULL; +struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL; +struct grub_net_card *grub_net_cards = NULL; +struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; + +grub_err_t +grub_net_resolve_address (struct grub_net_network_level_protocol **prot, + char *name, + grub_net_network_level_address_t *addr) +{ + FOR_NET_NETWORK_LEVEL_PROTOCOLS (*prot) + { + grub_err_t err; + err = grub_net_resolve_address_in_protocol (*prot, name, addr); + if (err == GRUB_ERR_NET_BAD_ADDRESS) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + if (err) + return err; + return GRUB_ERR_NONE; + } + return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("Unrecognised address %s"), + name); +} + +grub_err_t +grub_net_route_address (grub_net_network_level_address_t addr, + grub_net_network_level_address_t *gateway, + struct grub_net_network_level_interface **interf) +{ + struct grub_net_route *route; + int depth = 0; + int routecnt = 0; + struct grub_net_network_level_protocol *prot = NULL; + grub_net_network_level_address_t curtarget = addr; + + *gateway = addr; + + FOR_NET_ROUTES(route) + routecnt++; + + for (depth = 0; depth < routecnt + 2; depth++) + { + FOR_NET_ROUTES(route) + { + if (depth && prot != route->prot) + continue; + prot = route->prot; + if (!route->prot->match_net (route->target, curtarget)) + continue; + + if (route->is_gateway) + { + if (depth == 0) + *gateway = route->gw; + curtarget = route->gw; + break; + } + *interf = route->interface; + return GRUB_ERR_NONE; + } + if (route == NULL) + return grub_error (GRUB_ERR_NET_NO_ROUTE, "destination unreachable"); + } + + return grub_error (GRUB_ERR_NET_ROUTE_LOOP, "route loop detected"); +} + +static grub_err_t +grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_network_level_interface *inter; + + if (argc != 4) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + if (grub_strcmp (inter->name, args[1])) + break; + if (inter == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found")); + + inter->protocol->fini (inter); + grub_net_network_level_interface_unregister (inter); + grub_free (inter->name); + grub_free (inter); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_card *card; + struct grub_net_network_level_protocol *prot; + grub_err_t err; + grub_net_network_level_address_t addr; + struct grub_net_network_level_interface *inter; + + if (argc != 4) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("four arguments expected")); + + FOR_NET_CARDS (card) + if (grub_strcmp (card->name, args[1])) + break; + if (card == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found")); + + FOR_NET_NETWORK_LEVEL_PROTOCOLS (prot) + if (grub_strcmp (prot->name, args[2])) + break; + + if (card == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("protocol not found")); + + err = grub_net_resolve_address_in_protocol (prot, args[3], &addr); + if (err) + return err; + + inter = grub_zalloc (sizeof (*inter)); + if (!inter) + return grub_errno; + + inter->name = grub_strdup (args[0]); + inter->protocol = prot; + grub_memcpy (&(inter->address), &addr, sizeof (inter->address)); + inter->card = card; + + err = prot->init (inter); + if (err) + { + grub_free (inter->name); + grub_free (inter); + return err; + } + grub_net_network_level_interface_register (inter); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_delroute (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_route *route; + struct grub_net_route **prev; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + + for (prev = &grub_net_routes, route = *prev; route; prev = &((*prev)->next), + route = *prev) + if (grub_strcmp (route->name, args[0]) == 0) + { + *prev = route->next; + grub_free (route->name); + grub_free (route); + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_network_level_protocol *prot; + struct grub_net_route *route; + + if (argc < 3) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("At least 3 arguments are expected")); + + route = grub_zalloc (sizeof (*route)); + if (!route) + return grub_errno; + + route->name = grub_strdup (args[0]); + if (!route->name) + { + grub_free (route); + return grub_errno; + } + + FOR_NET_NETWORK_LEVEL_PROTOCOLS(prot) + { + grub_err_t err; + err = prot->net_ntoa (args[1], &(route->target)); + if (err == GRUB_ERR_NET_BAD_ADDRESS) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + if (err) + return err; + break; + } + + if (!prot) + { + grub_free (route->name); + grub_free (route); + return grub_error (GRUB_ERR_NET_BAD_ADDRESS, + N_("Unrecognised address %s"), args[1]); + } + + if (grub_strcmp (args[2], "gw") == 0 && argc >= 4) + { + grub_err_t err; + route->is_gateway = 1; + err = grub_net_resolve_address_in_protocol (prot, + args[3], &(route->gw)); + if (err) + { + grub_free (route->name); + grub_free (route); + return err; + } + } + else + { + struct grub_net_network_level_interface *inter; + route->is_gateway = 0; + + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + if (grub_strcmp (inter->name, args[2])) + break; + + if (!inter) + { + grub_free (route->name); + grub_free (route); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("Unrecognised interface %s"), args[2]); + } + route->interface = inter; + } + + grub_net_route_register (route); + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; + +GRUB_MOD_INIT(net) +{ + cmd_addaddr = grub_register_command ("net_add_addr", grub_cmd_addaddr, + "SHORTNAME CARD PROTOCOL ADDRESS", + N_("Add a network address.")); + cmd_deladdr = grub_register_command ("net_del_addr", grub_cmd_deladdr, + "SHORTNAME", + N_("Delete a network address.")); + cmd_addroute = grub_register_command ("net_add_route", grub_cmd_addroute, + "SHORTNAME NET [INTERFACE| gw GATEWAY]", + N_("Add a network route.")); + cmd_delroute = grub_register_command ("net_del_route", grub_cmd_delroute, + "SHORTNAME", + N_("Delete a network route.")); +} + +GRUB_MOD_FINI(net) +{ + grub_unregister_command (cmd_addaddr); + grub_unregister_command (cmd_deladdr); + grub_unregister_command (cmd_addroute); + grub_unregister_command (cmd_delroute); +} diff --git a/commands/probe.c b/commands/probe.c index c2cc599e9..002ede85e 100644 --- a/commands/probe.c +++ b/commands/probe.c @@ -72,7 +72,7 @@ grub_cmd_probe (grub_extcmd_t cmd, int argc, char **args) { const char *val = "none"; if (dev->net) - val = dev->net->dev->name; + val = dev->net->name; if (dev->disk) val = dev->disk->dev->name; if (state[0].set) diff --git a/conf/common.rmk b/conf/common.rmk index 0f67622b5..cee808a35 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -828,4 +828,10 @@ bin_UTILITIES += grub-mkpasswd-pbkdf2 grub_mkpasswd_pbkdf2_SOURCES = gnulib/progname.c gnulib/getdelim.c gnulib/getline.c util/grub-mkpasswd-pbkdf2.c lib/crypto.c lib/libgcrypt-grub/cipher/sha512.c lib/pbkdf2.c util/misc.c kern/emu/misc.c kern/emu/mm.c kern/err.c grub_mkpasswd_pbkdf2_CFLAGS += -Wno-missing-field-initializers -Wno-error -I$(srcdir)/lib/libgcrypt_wrap -DGRUB_MKPASSWD=1 +pkglib_MODULES += net.mod +net_mod_SOURCES = commands/net.c +net_mod_CFLAGS = $(COMMON_CFLAGS) +net_mod_LDFLAGS = $(COMMON_LDFLAGS) + include $(srcdir)/conf/gcry.mk + diff --git a/include/grub/device.h b/include/grub/device.h index f0e8a8ca8..d68c26e66 100644 --- a/include/grub/device.h +++ b/include/grub/device.h @@ -24,8 +24,12 @@ #include struct grub_disk; -struct grub_net; struct grub_fs; +struct grub_net +{ + char *name; + struct grub_fs *fs; +}; struct grub_device { diff --git a/include/grub/err.h b/include/grub/err.h index e44705389..493796d62 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -54,7 +54,10 @@ typedef enum GRUB_ERR_MENU, GRUB_ERR_TIMEOUT, GRUB_ERR_IO, - GRUB_ERR_ACCESS_DENIED + GRUB_ERR_ACCESS_DENIED, + GRUB_ERR_NET_BAD_ADDRESS, + GRUB_ERR_NET_ROUTE_LOOP, + GRUB_ERR_NET_NO_ROUTE } grub_err_t; diff --git a/include/grub/net.h b/include/grub/net.h index c6d71d5b6..4ca873f74 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2007 Free Software Foundation, Inc. + * Copyright (C) 2010 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 @@ -19,54 +19,224 @@ #ifndef GRUB_NET_HEADER #define GRUB_NET_HEADER 1 -#include -#include #include +#include +#include -struct grub_net; +struct grub_net_card; -struct grub_net_dev +struct grub_net_card_driver { - /* The device name. */ - const char *name; - - /* FIXME: Just a template. */ - int (*probe) (struct grub_net *net, const void *addr); - void (*reset) (struct grub_net *net); - int (*poll) (struct grub_net *net); - void (*transmit) (struct grub_net *net, const void *destip, - unsigned srcsock, unsigned destsock, const void *packet); - void (*disable) (struct grub_net *net); - - /* The next net device. */ - struct grub_net_dev *next; + grub_err_t (*send) (struct grub_net_card *dev, void *buf, + grub_size_t buflen); + grub_size_t (*recv) (struct grub_net_card *dev, void *buf, + grub_size_t buflen); }; -typedef struct grub_net_dev *grub_net_dev_t; -struct grub_fs; - -struct grub_net +struct grub_net_card { - /* The net name. */ - const char *name; - - /* The underlying disk device. */ - grub_net_dev_t dev; - - /* The binding filesystem. */ - struct grub_fs *fs; - - /* FIXME: More data would be required, such as an IP address, a mask, - a gateway, etc. */ - - /* Device-specific data. */ + struct grub_net_card *next; + char *name; + struct grub_net_card_driver *driver; void *data; }; -typedef struct grub_net *grub_net_t; -/* FIXME: How to abstract networks? More consideration is necessary. */ +struct grub_net_network_level_interface; + +typedef union grub_net_network_level_address +{ + grub_uint32_t ipv4; +} grub_net_network_level_netaddress_t; + +typedef union grub_net_network_level_netaddress +{ + struct { + grub_uint32_t base; + int masksize; + } ipv4; +} grub_net_network_level_address_t; + +typedef enum grub_network_level_protocol_id +{ + GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 +} grub_network_level_protocol_id_t; + +struct grub_net_network_level_interface; + +struct grub_net_network_level_protocol +{ + struct grub_net_network_level_protocol *next; + char *name; + grub_network_level_protocol_id_t id; + grub_err_t (*ntoa) (char *name, grub_net_network_level_address_t *addr); + char * (*aton) (union grub_net_network_level_address addr); + grub_err_t (*net_ntoa) (char *name, + grub_net_network_level_netaddress_t *addr); + char * (*net_aton) (grub_net_network_level_netaddress_t addr); + int (* match_net) (grub_net_network_level_netaddress_t net, + grub_net_network_level_address_t addr); + grub_err_t (*init) (struct grub_net_network_level_interface *dev); + grub_err_t (*fini) (struct grub_net_network_level_interface *dev); + grub_err_t (*send) (struct grub_net_network_level_interface *dev, void *buf, + grub_size_t buflen); + grub_size_t (*recv) (struct grub_net_network_level_interface *dev, void *buf, + grub_size_t buflen); +}; + +struct grub_net_network_level_interface +{ + struct grub_net_network_level_interface *next; + char *name; + /* Underlying protocol. */ + struct grub_net_network_level_protocol *protocol; + struct grub_net_card *card; + union grub_net_network_level_address address; + void *data; +}; + +struct grub_net_route +{ + struct grub_net_route *next; + grub_net_network_level_netaddress_t target; + char *name; + struct grub_net_network_level_protocol *prot; + int is_gateway; + union + { + struct grub_net_network_level_interface *interface; + grub_net_network_level_address_t gw; + }; +}; + +struct grub_net_session; + +struct grub_net_session_level_protocol +{ + void (*close) (struct grub_net_session *session); + grub_ssize_t (*recv) (struct grub_net_session *session, void *buf, + grub_size_t size); + grub_err_t (*send) (struct grub_net_session *session, void *buf, + grub_size_t size); +}; + +struct grub_net_session +{ + struct grub_net_session_level_protocol *protocol; + void *data; +}; + +static inline void +grub_net_session_close (struct grub_net_session *session) +{ + session->protocol->close (session); +} + +static inline grub_err_t +grub_net_session_send (struct grub_net_session *session, void *buf, + grub_size_t size) +{ + return session->protocol->send (session, buf, size); +} + +static inline grub_ssize_t +grub_net_session_recv (struct grub_net_session *session, void *buf, + grub_size_t size) +{ + return session->protocol->recv (session, buf, size); +} + +extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; + +static inline void +grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + GRUB_AS_LIST (inter)); +} + +static inline void +grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + GRUB_AS_LIST (inter)); +} + +#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) + +extern struct grub_net_route *grub_net_routes; + +static inline void +grub_net_route_register (struct grub_net_route *route) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_routes), + GRUB_AS_LIST (route)); +} + +static inline void +grub_net_route_unregister (struct grub_net_route *route) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_routes), + GRUB_AS_LIST (route)); +} + +#define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next) + +extern struct grub_net_card *grub_net_cards; + +static inline void +grub_net_card_register (struct grub_net_card *card) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_cards), + GRUB_AS_LIST (card)); +} + +static inline void +grub_net_card_unregister (struct grub_net_card *card) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_cards), + GRUB_AS_LIST (card)); +} + +#define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) + +extern struct grub_net_network_level_protocol *grub_net_network_level_protocols; + +static inline void +grub_net_network_level_protocol_register (struct grub_net_network_level_protocol *prot) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_protocols), + GRUB_AS_LIST (prot)); +} + +static inline void +grub_net_network_level_protocol_unregister (struct grub_net_network_level_protocol *prot) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_protocols), + GRUB_AS_LIST (prot)); +} + +#define FOR_NET_NETWORK_LEVEL_PROTOCOLS(var) for ((var) = grub_net_network_level_protocols; (var); (var) = (var)->next) + +static inline grub_err_t +grub_net_resolve_address_in_protocol (struct grub_net_network_level_protocol *prot, + char *name, + grub_net_network_level_address_t *addr) +{ + return prot->ntoa (name, addr); +} + +struct grub_net_session * +grub_net_open_tcp (char *address, grub_uint16_t port); + +grub_err_t +grub_net_resolve_address (struct grub_net_network_level_protocol **prot, + char *name, + grub_net_network_level_address_t *addr); + +grub_err_t +grub_net_route_address (grub_net_network_level_address_t addr, + grub_net_network_level_address_t *gateway, + struct grub_net_network_level_interface **interf); -/* Note: Networks are very different from disks, because networks must - be initialized before used, and the status is persistent. */ #endif /* ! GRUB_NET_HEADER */ diff --git a/kern/fs.c b/kern/fs.c index cf800f4cc..8ffb93c8b 100644 --- a/kern/fs.c +++ b/kern/fs.c @@ -94,7 +94,7 @@ grub_fs_probe (grub_device_t device) count--; } } - else if (device->net->fs) + else if (device->net) return device->net->fs; grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem"); From 1bf0e31cfb90a05389715ebda22734dff7f38d7c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 3 Mar 2010 20:09:48 +0100 Subject: [PATCH 014/406] Network infrastructure --- commands/net.c | 296 ++++++++++++++++++++++++++++++++++++++++++ commands/probe.c | 2 +- conf/common.rmk | 6 + include/grub/device.h | 6 +- include/grub/err.h | 5 +- include/grub/net.h | 248 +++++++++++++++++++++++++++++------ kern/fs.c | 2 +- 7 files changed, 522 insertions(+), 43 deletions(-) create mode 100644 commands/net.c diff --git a/commands/net.c b/commands/net.c new file mode 100644 index 000000000..288ba4c2a --- /dev/null +++ b/commands/net.c @@ -0,0 +1,296 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 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 + +struct grub_net_route *grub_net_routes = NULL; +struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL; +struct grub_net_card *grub_net_cards = NULL; +struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; + +grub_err_t +grub_net_resolve_address (struct grub_net_network_level_protocol **prot, + char *name, + grub_net_network_level_address_t *addr) +{ + FOR_NET_NETWORK_LEVEL_PROTOCOLS (*prot) + { + grub_err_t err; + err = grub_net_resolve_address_in_protocol (*prot, name, addr); + if (err == GRUB_ERR_NET_BAD_ADDRESS) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + if (err) + return err; + return GRUB_ERR_NONE; + } + return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("Unrecognised address %s"), + name); +} + +grub_err_t +grub_net_route_address (grub_net_network_level_address_t addr, + grub_net_network_level_address_t *gateway, + struct grub_net_network_level_interface **interf) +{ + struct grub_net_route *route; + int depth = 0; + int routecnt = 0; + struct grub_net_network_level_protocol *prot = NULL; + grub_net_network_level_address_t curtarget = addr; + + *gateway = addr; + + FOR_NET_ROUTES(route) + routecnt++; + + for (depth = 0; depth < routecnt + 2; depth++) + { + FOR_NET_ROUTES(route) + { + if (depth && prot != route->prot) + continue; + prot = route->prot; + if (!route->prot->match_net (route->target, curtarget)) + continue; + + if (route->is_gateway) + { + if (depth == 0) + *gateway = route->gw; + curtarget = route->gw; + break; + } + *interf = route->interface; + return GRUB_ERR_NONE; + } + if (route == NULL) + return grub_error (GRUB_ERR_NET_NO_ROUTE, "destination unreachable"); + } + + return grub_error (GRUB_ERR_NET_ROUTE_LOOP, "route loop detected"); +} + +static grub_err_t +grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_network_level_interface *inter; + + if (argc != 4) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + if (grub_strcmp (inter->name, args[1])) + break; + if (inter == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found")); + + inter->protocol->fini (inter); + grub_net_network_level_interface_unregister (inter); + grub_free (inter->name); + grub_free (inter); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_card *card; + struct grub_net_network_level_protocol *prot; + grub_err_t err; + grub_net_network_level_address_t addr; + struct grub_net_network_level_interface *inter; + + if (argc != 4) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("four arguments expected")); + + FOR_NET_CARDS (card) + if (grub_strcmp (card->name, args[1])) + break; + if (card == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found")); + + FOR_NET_NETWORK_LEVEL_PROTOCOLS (prot) + if (grub_strcmp (prot->name, args[2])) + break; + + if (card == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("protocol not found")); + + err = grub_net_resolve_address_in_protocol (prot, args[3], &addr); + if (err) + return err; + + inter = grub_zalloc (sizeof (*inter)); + if (!inter) + return grub_errno; + + inter->name = grub_strdup (args[0]); + inter->protocol = prot; + grub_memcpy (&(inter->address), &addr, sizeof (inter->address)); + inter->card = card; + + err = prot->init (inter); + if (err) + { + grub_free (inter->name); + grub_free (inter); + return err; + } + grub_net_network_level_interface_register (inter); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_delroute (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_route *route; + struct grub_net_route **prev; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + + for (prev = &grub_net_routes, route = *prev; route; prev = &((*prev)->next), + route = *prev) + if (grub_strcmp (route->name, args[0]) == 0) + { + *prev = route->next; + grub_free (route->name); + grub_free (route); + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_network_level_protocol *prot; + struct grub_net_route *route; + + if (argc < 3) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("At least 3 arguments are expected")); + + route = grub_zalloc (sizeof (*route)); + if (!route) + return grub_errno; + + route->name = grub_strdup (args[0]); + if (!route->name) + { + grub_free (route); + return grub_errno; + } + + FOR_NET_NETWORK_LEVEL_PROTOCOLS(prot) + { + grub_err_t err; + err = prot->net_ntoa (args[1], &(route->target)); + if (err == GRUB_ERR_NET_BAD_ADDRESS) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + if (err) + return err; + break; + } + + if (!prot) + { + grub_free (route->name); + grub_free (route); + return grub_error (GRUB_ERR_NET_BAD_ADDRESS, + N_("Unrecognised address %s"), args[1]); + } + + if (grub_strcmp (args[2], "gw") == 0 && argc >= 4) + { + grub_err_t err; + route->is_gateway = 1; + err = grub_net_resolve_address_in_protocol (prot, + args[3], &(route->gw)); + if (err) + { + grub_free (route->name); + grub_free (route); + return err; + } + } + else + { + struct grub_net_network_level_interface *inter; + route->is_gateway = 0; + + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + if (grub_strcmp (inter->name, args[2])) + break; + + if (!inter) + { + grub_free (route->name); + grub_free (route); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("Unrecognised interface %s"), args[2]); + } + route->interface = inter; + } + + grub_net_route_register (route); + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; + +GRUB_MOD_INIT(net) +{ + cmd_addaddr = grub_register_command ("net_add_addr", grub_cmd_addaddr, + "SHORTNAME CARD PROTOCOL ADDRESS", + N_("Add a network address.")); + cmd_deladdr = grub_register_command ("net_del_addr", grub_cmd_deladdr, + "SHORTNAME", + N_("Delete a network address.")); + cmd_addroute = grub_register_command ("net_add_route", grub_cmd_addroute, + "SHORTNAME NET [INTERFACE| gw GATEWAY]", + N_("Add a network route.")); + cmd_delroute = grub_register_command ("net_del_route", grub_cmd_delroute, + "SHORTNAME", + N_("Delete a network route.")); +} + +GRUB_MOD_FINI(net) +{ + grub_unregister_command (cmd_addaddr); + grub_unregister_command (cmd_deladdr); + grub_unregister_command (cmd_addroute); + grub_unregister_command (cmd_delroute); +} diff --git a/commands/probe.c b/commands/probe.c index c2cc599e9..002ede85e 100644 --- a/commands/probe.c +++ b/commands/probe.c @@ -72,7 +72,7 @@ grub_cmd_probe (grub_extcmd_t cmd, int argc, char **args) { const char *val = "none"; if (dev->net) - val = dev->net->dev->name; + val = dev->net->name; if (dev->disk) val = dev->disk->dev->name; if (state[0].set) diff --git a/conf/common.rmk b/conf/common.rmk index 7effa8af3..f1ed1478d 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -779,4 +779,10 @@ bin_UTILITIES += grub-mkpasswd-pbkdf2 grub_mkpasswd_pbkdf2_SOURCES = gnulib/progname.c gnulib/getdelim.c gnulib/getline.c util/grub-mkpasswd-pbkdf2.c lib/crypto.c lib/libgcrypt-grub/cipher/sha512.c lib/pbkdf2.c util/misc.c kern/err.c grub_mkpasswd_pbkdf2_CFLAGS += -Wno-missing-field-initializers -Wno-error -I$(srcdir)/lib/libgcrypt_wrap -DGRUB_MKPASSWD=1 +pkglib_MODULES += net.mod +net_mod_SOURCES = commands/net.c +net_mod_CFLAGS = $(COMMON_CFLAGS) +net_mod_LDFLAGS = $(COMMON_LDFLAGS) + include $(srcdir)/conf/gcry.mk + diff --git a/include/grub/device.h b/include/grub/device.h index f0e8a8ca8..d68c26e66 100644 --- a/include/grub/device.h +++ b/include/grub/device.h @@ -24,8 +24,12 @@ #include struct grub_disk; -struct grub_net; struct grub_fs; +struct grub_net +{ + char *name; + struct grub_fs *fs; +}; struct grub_device { diff --git a/include/grub/err.h b/include/grub/err.h index e44705389..493796d62 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -54,7 +54,10 @@ typedef enum GRUB_ERR_MENU, GRUB_ERR_TIMEOUT, GRUB_ERR_IO, - GRUB_ERR_ACCESS_DENIED + GRUB_ERR_ACCESS_DENIED, + GRUB_ERR_NET_BAD_ADDRESS, + GRUB_ERR_NET_ROUTE_LOOP, + GRUB_ERR_NET_NO_ROUTE } grub_err_t; diff --git a/include/grub/net.h b/include/grub/net.h index c6d71d5b6..4ca873f74 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2007 Free Software Foundation, Inc. + * Copyright (C) 2010 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 @@ -19,54 +19,224 @@ #ifndef GRUB_NET_HEADER #define GRUB_NET_HEADER 1 -#include -#include #include +#include +#include -struct grub_net; +struct grub_net_card; -struct grub_net_dev +struct grub_net_card_driver { - /* The device name. */ - const char *name; - - /* FIXME: Just a template. */ - int (*probe) (struct grub_net *net, const void *addr); - void (*reset) (struct grub_net *net); - int (*poll) (struct grub_net *net); - void (*transmit) (struct grub_net *net, const void *destip, - unsigned srcsock, unsigned destsock, const void *packet); - void (*disable) (struct grub_net *net); - - /* The next net device. */ - struct grub_net_dev *next; + grub_err_t (*send) (struct grub_net_card *dev, void *buf, + grub_size_t buflen); + grub_size_t (*recv) (struct grub_net_card *dev, void *buf, + grub_size_t buflen); }; -typedef struct grub_net_dev *grub_net_dev_t; -struct grub_fs; - -struct grub_net +struct grub_net_card { - /* The net name. */ - const char *name; - - /* The underlying disk device. */ - grub_net_dev_t dev; - - /* The binding filesystem. */ - struct grub_fs *fs; - - /* FIXME: More data would be required, such as an IP address, a mask, - a gateway, etc. */ - - /* Device-specific data. */ + struct grub_net_card *next; + char *name; + struct grub_net_card_driver *driver; void *data; }; -typedef struct grub_net *grub_net_t; -/* FIXME: How to abstract networks? More consideration is necessary. */ +struct grub_net_network_level_interface; + +typedef union grub_net_network_level_address +{ + grub_uint32_t ipv4; +} grub_net_network_level_netaddress_t; + +typedef union grub_net_network_level_netaddress +{ + struct { + grub_uint32_t base; + int masksize; + } ipv4; +} grub_net_network_level_address_t; + +typedef enum grub_network_level_protocol_id +{ + GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 +} grub_network_level_protocol_id_t; + +struct grub_net_network_level_interface; + +struct grub_net_network_level_protocol +{ + struct grub_net_network_level_protocol *next; + char *name; + grub_network_level_protocol_id_t id; + grub_err_t (*ntoa) (char *name, grub_net_network_level_address_t *addr); + char * (*aton) (union grub_net_network_level_address addr); + grub_err_t (*net_ntoa) (char *name, + grub_net_network_level_netaddress_t *addr); + char * (*net_aton) (grub_net_network_level_netaddress_t addr); + int (* match_net) (grub_net_network_level_netaddress_t net, + grub_net_network_level_address_t addr); + grub_err_t (*init) (struct grub_net_network_level_interface *dev); + grub_err_t (*fini) (struct grub_net_network_level_interface *dev); + grub_err_t (*send) (struct grub_net_network_level_interface *dev, void *buf, + grub_size_t buflen); + grub_size_t (*recv) (struct grub_net_network_level_interface *dev, void *buf, + grub_size_t buflen); +}; + +struct grub_net_network_level_interface +{ + struct grub_net_network_level_interface *next; + char *name; + /* Underlying protocol. */ + struct grub_net_network_level_protocol *protocol; + struct grub_net_card *card; + union grub_net_network_level_address address; + void *data; +}; + +struct grub_net_route +{ + struct grub_net_route *next; + grub_net_network_level_netaddress_t target; + char *name; + struct grub_net_network_level_protocol *prot; + int is_gateway; + union + { + struct grub_net_network_level_interface *interface; + grub_net_network_level_address_t gw; + }; +}; + +struct grub_net_session; + +struct grub_net_session_level_protocol +{ + void (*close) (struct grub_net_session *session); + grub_ssize_t (*recv) (struct grub_net_session *session, void *buf, + grub_size_t size); + grub_err_t (*send) (struct grub_net_session *session, void *buf, + grub_size_t size); +}; + +struct grub_net_session +{ + struct grub_net_session_level_protocol *protocol; + void *data; +}; + +static inline void +grub_net_session_close (struct grub_net_session *session) +{ + session->protocol->close (session); +} + +static inline grub_err_t +grub_net_session_send (struct grub_net_session *session, void *buf, + grub_size_t size) +{ + return session->protocol->send (session, buf, size); +} + +static inline grub_ssize_t +grub_net_session_recv (struct grub_net_session *session, void *buf, + grub_size_t size) +{ + return session->protocol->recv (session, buf, size); +} + +extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; + +static inline void +grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + GRUB_AS_LIST (inter)); +} + +static inline void +grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + GRUB_AS_LIST (inter)); +} + +#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) + +extern struct grub_net_route *grub_net_routes; + +static inline void +grub_net_route_register (struct grub_net_route *route) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_routes), + GRUB_AS_LIST (route)); +} + +static inline void +grub_net_route_unregister (struct grub_net_route *route) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_routes), + GRUB_AS_LIST (route)); +} + +#define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next) + +extern struct grub_net_card *grub_net_cards; + +static inline void +grub_net_card_register (struct grub_net_card *card) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_cards), + GRUB_AS_LIST (card)); +} + +static inline void +grub_net_card_unregister (struct grub_net_card *card) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_cards), + GRUB_AS_LIST (card)); +} + +#define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) + +extern struct grub_net_network_level_protocol *grub_net_network_level_protocols; + +static inline void +grub_net_network_level_protocol_register (struct grub_net_network_level_protocol *prot) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_protocols), + GRUB_AS_LIST (prot)); +} + +static inline void +grub_net_network_level_protocol_unregister (struct grub_net_network_level_protocol *prot) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_protocols), + GRUB_AS_LIST (prot)); +} + +#define FOR_NET_NETWORK_LEVEL_PROTOCOLS(var) for ((var) = grub_net_network_level_protocols; (var); (var) = (var)->next) + +static inline grub_err_t +grub_net_resolve_address_in_protocol (struct grub_net_network_level_protocol *prot, + char *name, + grub_net_network_level_address_t *addr) +{ + return prot->ntoa (name, addr); +} + +struct grub_net_session * +grub_net_open_tcp (char *address, grub_uint16_t port); + +grub_err_t +grub_net_resolve_address (struct grub_net_network_level_protocol **prot, + char *name, + grub_net_network_level_address_t *addr); + +grub_err_t +grub_net_route_address (grub_net_network_level_address_t addr, + grub_net_network_level_address_t *gateway, + struct grub_net_network_level_interface **interf); -/* Note: Networks are very different from disks, because networks must - be initialized before used, and the status is persistent. */ #endif /* ! GRUB_NET_HEADER */ diff --git a/kern/fs.c b/kern/fs.c index 0c456377f..7bd1445b0 100644 --- a/kern/fs.c +++ b/kern/fs.c @@ -124,7 +124,7 @@ grub_fs_probe (grub_device_t device) count--; } } - else if (device->net->fs) + else if (device->net) return device->net->fs; grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem"); From 066528b4b18ed5870be40ef333bc85d2344ee812 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Tue, 27 Apr 2010 18:05:35 -0300 Subject: [PATCH 015/406] Initial Implementation of TFTP protocol and new protocol structs. --- conf/powerpc-ieee1275.rmk | 8 +- include/grub/net.h | 19 ++++- include/grub/net/arp.h | 23 ++++++ include/grub/net/device.h | 7 ++ include/grub/net/ethernet.h | 12 +++ include/grub/net/ieee1275/interface.h | 21 ++++++ include/grub/net/interface.h | 17 +++++ include/grub/net/ip.h | 25 +++++++ include/grub/net/netbuff.h | 27 +++++++ include/grub/net/protocol.h | 50 +++++++++++++ include/grub/net/tftp.h | 74 +++++++++++++++++++ include/grub/net/type_net.h | 7 ++ include/grub/net/udp.h | 22 ++++++ net/arp.c | 0 net/device.c | 0 net/ethernet.c | 54 ++++++++++++++ net/ieee1275/interface.c | 80 ++++++++++++++++++++ net/interface.c | 0 net/ip.c | 95 ++++++++++++++++++++++++ net/netbuff.c | 72 ++++++++++++++++++ net/protocol.c | 21 ++++++ net/tftp.c | 102 ++++++++++++++++++++++++++ net/udp.c | 59 +++++++++++++++ 23 files changed, 789 insertions(+), 6 deletions(-) create mode 100644 include/grub/net/arp.h create mode 100644 include/grub/net/device.h create mode 100644 include/grub/net/ethernet.h create mode 100644 include/grub/net/ieee1275/interface.h create mode 100644 include/grub/net/interface.h create mode 100644 include/grub/net/ip.h create mode 100644 include/grub/net/netbuff.h create mode 100644 include/grub/net/protocol.h create mode 100644 include/grub/net/tftp.h create mode 100644 include/grub/net/type_net.h create mode 100644 include/grub/net/udp.h create mode 100644 net/arp.c create mode 100644 net/device.c create mode 100644 net/ethernet.c create mode 100644 net/ieee1275/interface.c create mode 100644 net/interface.c create mode 100644 net/ip.c create mode 100644 net/netbuff.c create mode 100644 net/protocol.c create mode 100644 net/tftp.c create mode 100644 net/udp.c diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index be95b30ba..14d04f93e 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -3,7 +3,10 @@ # Images. -kernel_img_HEADERS += ieee1275/ieee1275.h +<<<<<<< TREE +kernel_img_HEADERS += ieee1275/ieee1275.h \ + command.h i18n.h env_private.h net/ip.h net/udp.h net/ethernet.h net/arp.h net/tftp.h\ + net/ieee1275/interface.h net/type_net.h net.h net/interface.h net/protocol.h net/netbuff.h # Programs pkglib_PROGRAMS = kernel.img @@ -20,7 +23,8 @@ kernel_img_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \ kern/ieee1275/openfw.c disk/ieee1275/ofdisk.c \ kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c \ kern/generic/millisleep.c kern/time.c \ - symlist.c kern/$(target_cpu)/cache.S + symlist.c kern/$(target_cpu)/cache.S net/ip.c net/tftp.c net/udp.c net/ethernet.c net/arp.c \ + net/ieee1275/interface.c net/interface.c net/protocol.c net/netbuff.c kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS += $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x200000,-Bstatic diff --git a/include/grub/net.h b/include/grub/net.h index 4ca873f74..75efd51d6 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -22,15 +22,20 @@ #include #include #include +#include struct grub_net_card; struct grub_net_card_driver { - grub_err_t (*send) (struct grub_net_card *dev, void *buf, - grub_size_t buflen); - grub_size_t (*recv) (struct grub_net_card *dev, void *buf, - grub_size_t buflen); + grub_err_t (*send) (struct grub_net_card *dev,struct grub_net_buff *nb); + grub_size_t (*recv) (struct grub_net_card *dev,struct grub_net_buff *nb); +}; + +struct grub_net_addr +{ + grub_uint8_t *addr; + grub_size_t len; }; struct grub_net_card @@ -38,6 +43,12 @@ struct grub_net_card struct grub_net_card *next; char *name; struct grub_net_card_driver *driver; + /*transport layer address*/ + struct grub_net_addr *tla; + /*internet layer address*/ + struct grub_net_addr *ila; + /*link layer address*/ + struct grub_net_addr *lla; void *data; }; diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h new file mode 100644 index 000000000..0ac2ec832 --- /dev/null +++ b/include/grub/net/arp.h @@ -0,0 +1,23 @@ +#ifndef GRUB_NET_ARP_HEADER +#define GRUB_NET_ARP_HEADER 1 + +#include +struct arprequest { + grub_int16_t hwtype; /* hardware type (must be ARPHRD_ETHER) */ + grub_int16_t protocol; /* protocol type (must be ETH_P_IP) */ + grub_int8_t hwlen; /* hardware address length (must be 6) */ + grub_int8_t protolen; /* protocol address length (must be 4) */ + grub_uint16_t opcode; /* ARP opcode */ + grub_uint8_t shwaddr[6]; /* sender's hardware address */ + grub_uint32_t sipaddr; /* sender's IP address */ + grub_uint8_t thwaddr[6]; /* target's hardware address */ + grub_uint32_t tipaddr; /* target's IP address */ +}__attribute__ ((packed)); + + +struct arp_pkt{ + struct etherhdr ether; + struct arprequest arpr; +} __attribute__ ((packed)); + +#endif diff --git a/include/grub/net/device.h b/include/grub/net/device.h new file mode 100644 index 000000000..9f1b9bf1d --- /dev/null +++ b/include/grub/net/device.h @@ -0,0 +1,7 @@ +struct grub_net_card +{ + struct grub_net_card *next; + char *name; + struct grub_net_card_driver *driver; + void *data; +}; diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h new file mode 100644 index 000000000..46aa04f60 --- /dev/null +++ b/include/grub/net/ethernet.h @@ -0,0 +1,12 @@ +#ifndef GRUB_NET_ETHERNET_HEADER +#define GRUB_NET_ETHERNET_HEADER 1 +#include +struct etherhdr { + grub_uint8_t dst[6]; + grub_uint8_t src[6]; + grub_uint16_t type; +} __attribute__ ((packed)) ; + +void ethernet_ini(void); +void ethernet_fini(void); +#endif diff --git a/include/grub/net/ieee1275/interface.h b/include/grub/net/ieee1275/interface.h new file mode 100644 index 000000000..edc242cab --- /dev/null +++ b/include/grub/net/ieee1275/interface.h @@ -0,0 +1,21 @@ +#ifndef GRUB_IEEE1275_INTERFACE_HEADER +#define GRUB_IEEE1275_INTERFACE_HEADER 1 + +#include +#include +#include + +grub_ofnet_t EXPORT_VAR(grub_net); + +grub_bootp_t EXPORT_VAR(bootp_pckt); +grub_uint32_t get_server_ip(void); +grub_uint32_t get_client_ip(void); +grub_uint8_t* get_server_mac (void); +grub_uint8_t* get_client_mac (void); + +int send_card_buffer (void *buffer,int buff_len); +int get_card_buffer (void *buffer,int buff_len); +int card_open (void); +int card_close (void); + +#endif diff --git a/include/grub/net/interface.h b/include/grub/net/interface.h new file mode 100644 index 000000000..0e11c86ba --- /dev/null +++ b/include/grub/net/interface.h @@ -0,0 +1,17 @@ +#ifndef GRUB_INTERFACE_HEADER +#define GRUB_INTERFACE_HEADER +#include +#include +/* +extern struct grub_net_topprotocol; + +struct grub_net_interface +{ + struct grub_net_card *card; + struct grub_net_topprotocol* topprot; + struct grub_net_addr *tla; + struct grub_net_addr *ila; + struct grub_net_addr *lla; +}; +*/ +#endif diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h new file mode 100644 index 000000000..e1f45dcfa --- /dev/null +++ b/include/grub/net/ip.h @@ -0,0 +1,25 @@ +#ifndef GRUB_NET_IP_HEADER +#define GRUB_NET_IP_HEADER 1 +#include + + +struct iphdr { + grub_uint8_t verhdrlen; + grub_uint8_t service; + grub_uint16_t len; + grub_uint16_t ident; + grub_uint16_t frags; + grub_uint8_t ttl; + grub_uint8_t protocol; + grub_uint16_t chksum; + grub_uint32_t src; + grub_uint32_t dest; +} __attribute__ ((packed)) ; + +#define IP_UDP 17 /* UDP protocol */ +#define IP_BROADCAST 0xFFFFFFFF + +grub_uint16_t ipchksum(void *ipv, int len); +void ipv4_ini(void); +void ipv4_fini(void); +#endif diff --git a/include/grub/net/netbuff.h b/include/grub/net/netbuff.h new file mode 100644 index 000000000..7d63be1f5 --- /dev/null +++ b/include/grub/net/netbuff.h @@ -0,0 +1,27 @@ +#ifndef GRUB_NETBUFF_HEADER +#define GRUB_NETBUFF_HEADER + +#include + +#define NETBUFF_ALIGN 2048 +#define NETBUFFMINLEN 64 + +struct grub_net_buff +{ + /*Pointer to the start of the buffer*/ + char *head; + /*Pointer to the data */ + char *data; + /*Pointer to the tail */ + char *tail; + /*Pointer to the end of the buffer*/ + char *end; +}; + +grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len); +struct grub_net_buff * grub_netbuff_alloc ( grub_size_t len ); +#endif diff --git a/include/grub/net/protocol.h b/include/grub/net/protocol.h new file mode 100644 index 000000000..2c979481b --- /dev/null +++ b/include/grub/net/protocol.h @@ -0,0 +1,50 @@ +#ifndef GRUB_PROTOCOL_HEADER +#define GRUB_PROTOCOL_HEADER +#include +#include +#include +#include +struct protocol_operations; +struct grub_net_protocol; +struct grub_net_interface; + +struct grub_net_protocol +{ + struct grub_net_protocol *next; + char *name; + grub_err_t (*open) (struct grub_net_interface* inf, + struct grub_net_protocol *prot, struct grub_net_buff *nb); + grub_err_t (*open_confirm) (struct grub_net_interface *inf, + struct grub_net_protocol *prot, struct grub_net_buff *nb); + grub_err_t (*get_payload) (struct grub_net_interface *inf, + struct grub_net_protocol *prot, struct grub_net_buff *nb); + grub_err_t (*get_payload_confirm) (struct grub_net_interface* inf, + struct grub_net_protocol *prot, struct grub_net_buff *nb); + grub_err_t (*close) (struct grub_net_interface *inf, + struct grub_net_protocol *prot, struct grub_net_buff *nb); + grub_err_t (*send) (struct grub_net_interface *inf , + struct grub_net_protocol *prot, struct grub_net_buff *nb); + grub_err_t (*recv) (struct grub_net_interface *inf , + struct grub_net_protocol *prot, struct grub_net_buff *nb); +}; + +typedef struct grub_net_protocol *grub_net_protocol_t; + +struct grub_net_interface +{ + struct grub_net_card *card; + struct grub_net_protocol* prot; + char *path; + char *username; + char *password; + /*transport layer addres*/ + struct grub_net_addr *tla; + /*internet layer addres*/ + struct grub_net_addr *ila; + /*link layer addres*/ + struct grub_net_addr *lla; +}; + +void grub_protocol_register (grub_net_protocol_t prot); +void grub_protocol_unregister (grub_net_protocol_t prot); +#endif diff --git a/include/grub/net/tftp.h b/include/grub/net/tftp.h new file mode 100644 index 000000000..4148096c5 --- /dev/null +++ b/include/grub/net/tftp.h @@ -0,0 +1,74 @@ +#ifndef GRUB_NET_TFTP_HEADER +#define GRUB_NET_TFTP_HEADER 1 + +#include +#include +#include + +/* IP port for the MTFTP server used for Intel's PXE */ +#define MTFTP_SERVER_PORT 75 +#define MTFTP_CLIENT_PORT 76 + +#define TFTP_DEFAULTSIZE_PACKET 512 +#define TFTP_MAX_PACKET 1432 + +/* IP port for the TFTP server */ +#define TFTP_SERVER_PORT 69 +#define TFTP_CLIENT_PORT 2000 + + +/* We define these based on what's in arpa/tftp.h. We just like our + * names better, cause they're clearer */ +#define TFTP_RRQ 1 +#define TFTP_WRQ 2 +#define TFTP_DATA 3 +#define TFTP_ACK 4 +#define TFTP_ERROR 5 +#define TFTP_OACK 6 + +#define TFTP_CODE_EOF 1 +#define TFTP_CODE_MORE 2 +#define TFTP_CODE_ERROR 3 +#define TFTP_CODE_BOOT 4 +#define TFTP_CODE_CFG 5 + +#define TFTP_EUNDEF 0 /* not defined */ +#define TFTP_ENOTFOUND 1 /* file not found */ +#define TFTP_EACCESS 2 /* access violation */ +#define TFTP_ENOSPACE 3 /* disk full or allocation exceeded */ +#define TFTP_EBADOP 4 /* illegal TFTP operation */ +#define TFTP_EBADID 5 /* unknown transfer ID */ +#define TFTP_EEXISTS 6 /* file already exists */ +#define TFTP_ENOUSER 7 /* no such user */ +#define TFTP_DEFAULT_FILENAME "kernel" + + + + + + /* * own here because this is cleaner, and maps to the same data layout. + * */ +struct tftphdr { + grub_uint16_t opcode; + union { + grub_int8_t rrq[TFTP_DEFAULTSIZE_PACKET]; + struct { + grub_uint16_t block; + grub_int8_t download[TFTP_MAX_PACKET]; + } data; + struct { + grub_uint16_t block; + } ack; + struct { + grub_uint16_t errcode; + grub_int8_t errmsg[TFTP_DEFAULTSIZE_PACKET]; + } err; + struct { + grub_int8_t data[TFTP_DEFAULTSIZE_PACKET+2]; + } oack; + } u; +} __attribute__ ((packed)) ; + +void tftp_ini(void); +void tftp_fini(void); +#endif diff --git a/include/grub/net/type_net.h b/include/grub/net/type_net.h new file mode 100644 index 000000000..33f2d802d --- /dev/null +++ b/include/grub/net/type_net.h @@ -0,0 +1,7 @@ +#ifndef GRUB_TYPES_NET_HEADER +#define GRUB_TYPES_NET_HEADER 1 + +#define UDP_PCKT 0x11 +#define IP_PCKT 0x0800 + +#endif diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h new file mode 100644 index 000000000..dbfcecef0 --- /dev/null +++ b/include/grub/net/udp.h @@ -0,0 +1,22 @@ +#ifndef GRUB_NET_UDP_HEADER +#define GRUB_NET_UDP_HEADER 1 +#include +/* +typedef enum + { + GRUB_PROT_TFTP + } protocol_type; +*/ + +#define GRUB_PROT_TFTP 1 + +struct udphdr { + grub_uint16_t src; + grub_uint16_t dst; + grub_uint16_t len; + grub_uint16_t chksum; +} __attribute__ ((packed)); + +void udp_ini(void); +void udp_fini(void); +#endif diff --git a/net/arp.c b/net/arp.c new file mode 100644 index 000000000..e69de29bb diff --git a/net/device.c b/net/device.c new file mode 100644 index 000000000..e69de29bb diff --git a/net/ethernet.c b/net/ethernet.c new file mode 100644 index 000000000..fc64803e7 --- /dev/null +++ b/net/ethernet.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +static grub_err_t +send_ethernet_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot __attribute__ ((unused)) + ,struct grub_net_buff *nb) +{ + + struct etherhdr *eth; + grub_err_t err; + + if((err = grub_netbuff_push (nb,sizeof(*eth)) ) != GRUB_ERR_NONE) + return err; + eth = (struct etherhdr *) nb->data; + grub_memcpy (eth->src,inf->card->lla->addr,6 * sizeof (grub_uint8_t )); + grub_memcpy (eth->dst,inf->lla->addr,6 * sizeof (grub_uint8_t )); + eth->type = 0x0800; + + return inf->card->driver->send(inf->card,nb); +} + +static struct grub_net_protocol grub_ethernet_protocol = +{ + .name = "udp", + .send = send_ethernet_packet +}; + +void ethernet_ini(void) +{ + grub_protocol_register (&grub_ethernet_protocol); +} + +void ethernet_fini(void) +{ + grub_protocol_unregister (&grub_ethernet_protocol); +} +/* +int read_ethernet_packet(buffer,bufflen, int type) +{ + + struct etherhdr eth; + eth.type = 0; + + get_card_buffer (ð,sizeof (eth)); + + + +}*/ diff --git a/net/ieee1275/interface.c b/net/ieee1275/interface.c new file mode 100644 index 000000000..5a246ffa5 --- /dev/null +++ b/net/ieee1275/interface.c @@ -0,0 +1,80 @@ +#include +#include + +grub_uint32_t get_server_ip (void) +{ + return bootp_pckt->siaddr; +} + +grub_uint32_t get_client_ip (void) +{ + return bootp_pckt->yiaddr; +} + +grub_uint8_t* get_server_mac (void) +{ + grub_uint8_t *mac; + + mac = grub_malloc (6 * sizeof(grub_uint8_t)); + mac[0] = 0x00 ; + mac[1] = 0x11 ; + mac[2] = 0x25 ; + mac[3] = 0xca ; + mac[4] = 0x1f ; + mac[5] = 0x01 ; + + return mac; + +} + +grub_uint8_t* get_client_mac (void) +{ + grub_uint8_t *mac; + + mac = grub_malloc (6 * sizeof (grub_uint8_t)); + mac[0] = 0x0a ; + mac[1] = 0x11 ; + mac[2] = 0xbd ; + mac[3] = 0xe3 ; + mac[4] = 0xe3 ; + mac[5] = 0x04 ; + + return mac; +} + +static grub_ieee1275_ihandle_t handle; +int card_open (void) +{ + + grub_ieee1275_open (grub_net->dev , &handle); + return 1;//error + +} +int card_close (void) +{ + + if (handle) + grub_ieee1275_close (handle); + return 0; +} + + +int send_card_buffer (void *buffer,int buff_len) +{ + + int actual; + + grub_ieee1275_write (handle,buffer,buff_len,&actual); + + return actual; +} + +int get_card_buffer (void *buffer,int buff_len) +{ + + int actual; + + grub_ieee1275_read (handle,buffer,buff_len,&actual); + + return actual; +} diff --git a/net/interface.c b/net/interface.c new file mode 100644 index 000000000..e69de29bb diff --git a/net/ip.c b/net/ip.c new file mode 100644 index 000000000..c669ff6d7 --- /dev/null +++ b/net/ip.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +struct grub_net_protocol *grub_ipv4_prot; + +grub_uint16_t +ipchksum(void *ipv, int len) +{ + grub_uint16_t *ip = (grub_uint16_t *)ipv; + grub_uint32_t sum = 0; + + + len >>= 1; + while (len--) { + sum += *(ip++); + if (sum > 0xFFFF) + sum -= 0xFFFF; + } + + return((~sum) & 0x0000FFFF); +} + + +static grub_err_t +send_ip_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot, struct grub_net_buff *nb ) +{ + + struct iphdr *iph; + grub_err_t err; + + if((err = grub_netbuff_push(nb,sizeof(*iph)) ) != GRUB_ERR_NONE) + return err; + iph = (struct iphdr *) nb->data; + + /*FIXME dont work in litte endian machines*/ + //grub_uint8_t ver = 4; + //grub_uint8_t hdrlen = sizeof (struct iphdr)/4; + iph->verhdrlen = (4<<4 | 5); + iph->service = 0; + iph->len = sizeof(*iph); + iph->ident = 0x2b5f; + iph->frags = 0; + iph->ttl = 0xff; + iph->protocol = 0x11; + //grub_memcpy(&(iph->src) ,inf->card->ila->addr,inf->card->ila->len); + iph->src = *((grub_uint32_t *)inf->card->ila->addr); + //grub_memcpy(&(iph->dest) ,inf->ila->addr,inf->ila->len); + iph->dest = *((grub_uint32_t *)inf->ila->addr); + + iph->chksum = 0 ; + iph->chksum = ipchksum((void *)nb->head, sizeof(*iph)); + + + return prot->next->send(inf,prot->next,nb); +} + +static struct grub_net_protocol grub_ipv4_protocol = +{ + .name = "ipv4", + .send = send_ip_packet, + .recv = NULL +}; + +void ipv4_ini(void) +{ + grub_protocol_register (&grub_ipv4_protocol); +} + +void ipv4_fini(void) +{ + grub_protocol_unregister (&grub_ipv4_protocol); +} + +/* +int read_ip_packet (void *buffer,int *bufflen) +{ + struct iphdr iph; + iph.protocol = 0; + + while ( iph.protocol != IP_UDP) + { + read_ethernet_packet(buffer,bufflen,IP_PROTOCOL); + grub_memcpy (&iph,buffer,sizeof (iph)); + } + + buffer += sizeof (iph); + *buff_len -= sizeof (iph); + +}*/ diff --git a/net/netbuff.c b/net/netbuff.c new file mode 100644 index 000000000..342260f43 --- /dev/null +++ b/net/netbuff.c @@ -0,0 +1,72 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 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 + + +grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len) +{ + net_buff->tail += len; + if (net_buff->tail > net_buff->end) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return GRUB_ERR_NONE; +} + +grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len) +{ + net_buff->tail -= len; + if (net_buff->tail < net_buff->head) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return GRUB_ERR_NONE; +} + +grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len) +{ + net_buff->data -= len; + if (net_buff->data < net_buff->head) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return GRUB_ERR_NONE; +} + +grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len) +{ + net_buff->data += len; + if (net_buff->data > net_buff->end) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return GRUB_ERR_NONE; +} + +grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len) +{ + net_buff->data += len; + net_buff->tail += len; + if ((net_buff->tail > net_buff->end) || (net_buff->data > net_buff->end)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return GRUB_ERR_NONE; +} + +struct grub_net_buff * grub_netbuff_alloc ( grub_size_t len ) +{ + if (len < NETBUFFMINLEN) + len = NETBUFFMINLEN; + len = ALIGN_UP (len,NETBUFF_ALIGN); + return (struct grub_net_buff *) grub_memalign (len,NETBUFF_ALIGN); +} diff --git a/net/protocol.c b/net/protocol.c new file mode 100644 index 000000000..a6117dc2c --- /dev/null +++ b/net/protocol.c @@ -0,0 +1,21 @@ +#include + +static grub_net_protocol_t grub_net_protocols; + +void grub_protocol_register (grub_net_protocol_t prot) +{ + prot->next = grub_net_protocols; + grub_net_protocols = prot; +} + +void grub_protocol_unregister (grub_net_protocol_t prot) +{ + grub_net_protocol_t *p, q; + + for (p = &grub_net_protocols, q = *p; q; p = &(q->next), q = q->next) + if (q == prot) + { + *p = q->next; + break; + } +} diff --git a/net/tftp.c b/net/tftp.c new file mode 100644 index 000000000..fdca184e9 --- /dev/null +++ b/net/tftp.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*send read request*/ +static grub_err_t +send_tftp_rr (struct grub_net_interface *inf, struct grub_net_protocol *prot,struct grub_net_buff *nb) +{ + /*Start TFTP header*/ + + struct tftphdr *tftph; + char *rrq; + int rrqlen; + int hdrlen; + grub_err_t err; + + if((err = grub_netbuff_push (nb,sizeof(*tftph))) != GRUB_ERR_NONE) + return err; + + tftph = (struct tftphdr *) nb->data; + + rrq = (char *) tftph->u.rrq; + rrqlen = 0; + + tftph->opcode = TFTP_RRQ; + grub_strcpy (rrq,inf->path); + rrqlen += grub_strlen (inf->path) + 1; + rrq += grub_strlen (inf->path) + 1; + /*passar opcoes como parametro ou usar default?*/ + + grub_strcpy (rrq,"octet"); + rrqlen += grub_strlen ("octet") + 1; + rrq += grub_strlen ("octet") + 1; + + grub_strcpy (rrq,"blksize"); + rrqlen += grub_strlen("blksize") + 1; + rrq += grub_strlen ("blksize") + 1; + + grub_strcpy (rrq,"1024"); + rrqlen += grub_strlen ("1024") + 1; + rrq += grub_strlen ("1024") + 1; + + grub_strcpy (rrq,"tsize"); + rrqlen += grub_strlen ("tsize") + 1; + rrq += grub_strlen ("tsize") + 1; + + grub_strcpy (rrq,"0"); + rrqlen += grub_strlen ("0") + 1; + rrq += grub_strlen ("0") + 1; + hdrlen = sizeof (tftph->opcode) + rrqlen; + + grub_netbuff_unput (nb,nb->tail - (nb->data+hdrlen)); + + return prot->next->send(inf,prot->next,nb); +} + +/* +int send_tftp_ack(int block, int port){ + + tftp_t pckt; + int pcktlen; + pckt.opcode = TFTP_ACK; + pckt.u.ack.block = block; + pcktlen = sizeof (pckt.opcode) + sizeof (pckt.u.ack.block); + + port = 4; + return 0;// send_udp_packet (&pckt,pcktlen,TFTP_CLIENT_PORT,port); +} + +*/ + +static struct grub_net_protocol grub_tftp_protocol = +{ + .name = "tftp", + .open = send_tftp_rr + +}; + +void tftp_ini(void) +{ + grub_protocol_register (&grub_tftp_protocol); +} + +void tftp_fini(void) +{ + grub_protocol_unregister (&grub_tftp_protocol); +} +/* +int read_tftp_pckt (grub_uint16_t port, void *buffer, int &buff_len){ + + + read_udp_packet (port,buffer,buff_len); + + +}*/ diff --git a/net/udp.c b/net/udp.c new file mode 100644 index 000000000..600eec542 --- /dev/null +++ b/net/udp.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +/*Assumes that there is allocated memory to the header before the buffer address. */ +static grub_err_t +send_udp_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot, struct grub_net_buff *nb) +{ + + struct udphdr *udph; + grub_err_t err; + + if((err = grub_netbuff_push (nb,sizeof(*udph)) ) != GRUB_ERR_NONE) + return err; + + udph = (struct udphdr *) nb->data; + udph->src = *((grub_uint16_t *) inf->card->tla->addr); + udph->dst = *((grub_uint16_t *) inf->tla->addr); + /*no chksum*/ + udph->chksum = 0; + udph->len = sizeof (sizeof (*udph)) + nb->end - nb->head; + + return prot->next->send(inf,prot->next,nb); +} + +static struct grub_net_protocol grub_udp_protocol = +{ + .name = "udp", + .send = send_udp_packet +}; + +void udp_ini(void) +{ + grub_protocol_register (&grub_udp_protocol); +} + +void udp_fini(void) +{ + grub_protocol_unregister (&grub_udp_protocol); +} + +/* +int read_udp_packet (grub_uint16_t port,void *buffer,int *buff_len) +{ + + struct udphdr udph; + udph.dst = 0; + + while ( udph.dst != port) + { + read_ip_packet (buffer,bufflen); + grub_memcpy (&udph,buffer,sizeof (udph)); + } + + buffer += sizeof (udph); + *buff_len -= sizeof (udph); + +}*/ From 8d402bc9a8041f0ed15290901e0ff5f115ed5cc0 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 29 Apr 2010 17:56:09 -0300 Subject: [PATCH 016/406] small change in the interface structure. --- include/grub/net.h | 14 ++++++++++++++ include/grub/net/interface.h | 18 ++++++++++++++---- include/grub/net/protocol.h | 33 +++++++++------------------------ net/ethernet.c | 3 ++- net/ip.c | 5 +++-- net/tftp.c | 5 +++-- net/udp.c | 5 +++-- 7 files changed, 48 insertions(+), 35 deletions(-) diff --git a/include/grub/net.h b/include/grub/net.h index 75efd51d6..f021f0e9c 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -26,8 +26,22 @@ struct grub_net_card; +typedef enum +{ + GRUB_NET_TFTP_ID, + GRUB_NET_UDP_ID, + GRUB_NET_IPV4_ID, + GRUB_NET_IPV6_ID, + GRUB_NET_ETHERNET_ID, + GRUB_NET_ARP_ID, + GRUB_NET_DHCP_ID + +}protocol_type_t; + struct grub_net_card_driver { + grub_err_t (*init) (struct grub_net_card *dev); + grub_err_t (*fini) (struct grub_net_card *dev); grub_err_t (*send) (struct grub_net_card *dev,struct grub_net_buff *nb); grub_size_t (*recv) (struct grub_net_card *dev,struct grub_net_buff *nb); }; diff --git a/include/grub/net/interface.h b/include/grub/net/interface.h index 0e11c86ba..2e0ddfcc8 100644 --- a/include/grub/net/interface.h +++ b/include/grub/net/interface.h @@ -2,16 +2,26 @@ #define GRUB_INTERFACE_HEADER #include #include -/* -extern struct grub_net_topprotocol; + +struct grub_net_protstack +{ + struct grub_net_protstack *next; + struct grub_net_protocol* prot; +}; struct grub_net_interface { struct grub_net_card *card; - struct grub_net_topprotocol* topprot; + struct grub_net_protstack* protstack; + char *path; + char *username; + char *password; + /*transport layer addres*/ struct grub_net_addr *tla; + /*internet layer addres*/ struct grub_net_addr *ila; + /*link layer addres*/ struct grub_net_addr *lla; }; -*/ + #endif diff --git a/include/grub/net/protocol.h b/include/grub/net/protocol.h index 2c979481b..1efc2ab7b 100644 --- a/include/grub/net/protocol.h +++ b/include/grub/net/protocol.h @@ -4,47 +4,32 @@ #include #include #include -struct protocol_operations; + struct grub_net_protocol; struct grub_net_interface; +struct grub_net_protstack; struct grub_net_protocol { struct grub_net_protocol *next; char *name; grub_err_t (*open) (struct grub_net_interface* inf, - struct grub_net_protocol *prot, struct grub_net_buff *nb); + struct grub_net_protstack *protstack, struct grub_net_buff *nb); grub_err_t (*open_confirm) (struct grub_net_interface *inf, - struct grub_net_protocol *prot, struct grub_net_buff *nb); + struct grub_net_protstack *protstack, struct grub_net_buff *nb); grub_err_t (*get_payload) (struct grub_net_interface *inf, - struct grub_net_protocol *prot, struct grub_net_buff *nb); + struct grub_net_protstack *protstack, struct grub_net_buff *nb); grub_err_t (*get_payload_confirm) (struct grub_net_interface* inf, - struct grub_net_protocol *prot, struct grub_net_buff *nb); + struct grub_net_protstack *protstack, struct grub_net_buff *nb); grub_err_t (*close) (struct grub_net_interface *inf, - struct grub_net_protocol *prot, struct grub_net_buff *nb); + struct grub_net_protstack *protstack, struct grub_net_buff *nb); grub_err_t (*send) (struct grub_net_interface *inf , - struct grub_net_protocol *prot, struct grub_net_buff *nb); + struct grub_net_protstack *protstack, struct grub_net_buff *nb); grub_err_t (*recv) (struct grub_net_interface *inf , - struct grub_net_protocol *prot, struct grub_net_buff *nb); + struct grub_net_protstack *protstack, struct grub_net_buff *nb); }; typedef struct grub_net_protocol *grub_net_protocol_t; - -struct grub_net_interface -{ - struct grub_net_card *card; - struct grub_net_protocol* prot; - char *path; - char *username; - char *password; - /*transport layer addres*/ - struct grub_net_addr *tla; - /*internet layer addres*/ - struct grub_net_addr *ila; - /*link layer addres*/ - struct grub_net_addr *lla; -}; - void grub_protocol_register (grub_net_protocol_t prot); void grub_protocol_unregister (grub_net_protocol_t prot); #endif diff --git a/net/ethernet.c b/net/ethernet.c index fc64803e7..8c13966c1 100644 --- a/net/ethernet.c +++ b/net/ethernet.c @@ -6,9 +6,10 @@ #include #include #include +#include static grub_err_t -send_ethernet_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot __attribute__ ((unused)) +send_ethernet_packet (struct grub_net_interface *inf,struct grub_net_protstack *protstack __attribute__ ((unused)) ,struct grub_net_buff *nb) { diff --git a/net/ip.c b/net/ip.c index c669ff6d7..6fe58adb0 100644 --- a/net/ip.c +++ b/net/ip.c @@ -5,6 +5,7 @@ #include #include #include +#include #include struct grub_net_protocol *grub_ipv4_prot; @@ -28,7 +29,7 @@ ipchksum(void *ipv, int len) static grub_err_t -send_ip_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot, struct grub_net_buff *nb ) +send_ip_packet (struct grub_net_interface *inf, struct grub_net_protstack *protstack, struct grub_net_buff *nb ) { struct iphdr *iph; @@ -57,7 +58,7 @@ send_ip_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot, iph->chksum = ipchksum((void *)nb->head, sizeof(*iph)); - return prot->next->send(inf,prot->next,nb); + return protstack->next->prot->send(inf,protstack->next,nb); } static struct grub_net_protocol grub_ipv4_protocol = diff --git a/net/tftp.c b/net/tftp.c index fdca184e9..3f481fe58 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -8,10 +8,11 @@ #include #include #include +#include /*send read request*/ static grub_err_t -send_tftp_rr (struct grub_net_interface *inf, struct grub_net_protocol *prot,struct grub_net_buff *nb) +send_tftp_rr (struct grub_net_interface *inf, struct grub_net_protstack *protstack,struct grub_net_buff *nb) { /*Start TFTP header*/ @@ -58,7 +59,7 @@ send_tftp_rr (struct grub_net_interface *inf, struct grub_net_protocol *prot,str grub_netbuff_unput (nb,nb->tail - (nb->data+hdrlen)); - return prot->next->send(inf,prot->next,nb); + return protstack->next->prot->send(inf,protstack->next,nb); } /* diff --git a/net/udp.c b/net/udp.c index 600eec542..2a4a7690b 100644 --- a/net/udp.c +++ b/net/udp.c @@ -3,9 +3,10 @@ #include #include #include +#include /*Assumes that there is allocated memory to the header before the buffer address. */ static grub_err_t -send_udp_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot, struct grub_net_buff *nb) +send_udp_packet (struct grub_net_interface *inf, struct grub_net_protstack *protstack, struct grub_net_buff *nb) { struct udphdr *udph; @@ -21,7 +22,7 @@ send_udp_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot, udph->chksum = 0; udph->len = sizeof (sizeof (*udph)) + nb->end - nb->head; - return prot->next->send(inf,prot->next,nb); + return protstack->next->prot->send(inf,protstack->next,nb); } static struct grub_net_protocol grub_udp_protocol = From d17a9fea4ac98b3aebea13f2b280c98afcd19c03 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Mon, 21 Jun 2010 19:05:14 -0300 Subject: [PATCH 017/406] Add interface struct for communication between protocols and protocols stack. Changed the protocols structs to use one struct for each layer. --- include/grub/net/arp.h | 8 +- include/grub/net/ieee1275/interface.h | 14 ++-- include/grub/net/interface.h | 77 ++++++++++++++---- include/grub/net/netbuff.h | 3 + include/grub/net/protocol.h | 110 ++++++++++++++++++++------ include/grub/net/tftp.h | 6 +- include/grub/net/type_net.h | 25 ++++++ include/grub/net/udp.h | 19 ++--- 8 files changed, 194 insertions(+), 68 deletions(-) diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h index 0ac2ec832..86ae2deea 100644 --- a/include/grub/net/arp.h +++ b/include/grub/net/arp.h @@ -2,7 +2,7 @@ #define GRUB_NET_ARP_HEADER 1 #include -struct arprequest { +struct arphdr{ grub_int16_t hwtype; /* hardware type (must be ARPHRD_ETHER) */ grub_int16_t protocol; /* protocol type (must be ETH_P_IP) */ grub_int8_t hwlen; /* hardware address length (must be 6) */ @@ -14,10 +14,4 @@ struct arprequest { grub_uint32_t tipaddr; /* target's IP address */ }__attribute__ ((packed)); - -struct arp_pkt{ - struct etherhdr ether; - struct arprequest arpr; -} __attribute__ ((packed)); - #endif diff --git a/include/grub/net/ieee1275/interface.h b/include/grub/net/ieee1275/interface.h index edc242cab..16f624c05 100644 --- a/include/grub/net/ieee1275/interface.h +++ b/include/grub/net/ieee1275/interface.h @@ -4,17 +4,15 @@ #include #include #include +#include -grub_ofnet_t EXPORT_VAR(grub_net); -grub_bootp_t EXPORT_VAR(bootp_pckt); -grub_uint32_t get_server_ip(void); -grub_uint32_t get_client_ip(void); -grub_uint8_t* get_server_mac (void); -grub_uint8_t* get_client_mac (void); +grub_ofnet_t grub_net; -int send_card_buffer (void *buffer,int buff_len); -int get_card_buffer (void *buffer,int buff_len); +grub_bootp_t bootp_pckt; + +int send_card_buffer (struct grub_net_buff *pack); +int get_card_packet (struct grub_net_buff *pack); int card_open (void); int card_close (void); diff --git a/include/grub/net/interface.h b/include/grub/net/interface.h index 2e0ddfcc8..4d100fd75 100644 --- a/include/grub/net/interface.h +++ b/include/grub/net/interface.h @@ -1,27 +1,70 @@ #ifndef GRUB_INTERFACE_HEADER #define GRUB_INTERFACE_HEADER -#include -#include +//#include +#include +#include +#include -struct grub_net_protstack +struct grub_net_protocol_stack { - struct grub_net_protstack *next; - struct grub_net_protocol* prot; + struct grub_net_protocol_stack *next; + char *name; + grub_net_protocol_id_t id; + void *interface; }; -struct grub_net_interface +struct grub_net_application_transport_interface { - struct grub_net_card *card; - struct grub_net_protstack* protstack; - char *path; - char *username; - char *password; - /*transport layer addres*/ - struct grub_net_addr *tla; - /*internet layer addres*/ - struct grub_net_addr *ila; - /*link layer addres*/ - struct grub_net_addr *lla; + struct grub_net_transport_network_interface *inner_layer; + void *data; + struct grub_net_application_layer_protocol *app_prot; + struct grub_net_transport_layer_protocol *trans_prot; }; +struct grub_net_transport_network_interface +{ + struct grub_net_network_link_interface *inner_layer; + void *data; + struct grub_net_transport_layer_protocol *trans_prot; + struct grub_net_network_layer_protocol *net_prot; +}; + +struct grub_net_network_link_interface +{ + void *data; + struct grub_net_network_layer_protocol *net_prot; + struct grub_net_link_layer_protocol *link_prot; +}; + + +extern struct grub_net_protocol_stack *grub_net_protocol_stacks; +static inline void +grub_net_stack_register (struct grub_net_protocol_stack *stack) +{ + + grub_list_push (GRUB_AS_LIST_P (&grub_net_protocol_stacks), + GRUB_AS_LIST (stack)); +} +/* +void grub_net_stack_unregister (struct grub_net_protocol_stack *stack) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_protocol_stacks), + GRUB_AS_LIST (stack)); +}*/ + +struct grub_net_protocol_stack *grub_net_protocol_stack_get (char *name); + +/* +static inline void +grub_net_interface_application_transport_register (struct grub_net_application_transport_interface); +static inline void +grub_net_interface_application_transport_unregister (struct grub_net_application_transport_interface); +static inline void +grub_net_interface_transport_network_register (struct grub_net_transport_network_interface); +static inline void +grub_net_interface_transport_network_unregister (struct grub_net_transport_network_interface); +static inline void +grub_net_interface_network_link_register (struct grub_net_network_link_interface); +static inline void +grub_net_interface_network_link_unregister (struct grub_net_network_link_interface);*/ #endif diff --git a/include/grub/net/netbuff.h b/include/grub/net/netbuff.h index 7d63be1f5..8ce508ead 100644 --- a/include/grub/net/netbuff.h +++ b/include/grub/net/netbuff.h @@ -23,5 +23,8 @@ grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len); grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len); grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len); grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff); struct grub_net_buff * grub_netbuff_alloc ( grub_size_t len ); +grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff); +grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff); #endif diff --git a/include/grub/net/protocol.h b/include/grub/net/protocol.h index 1efc2ab7b..b7a3e5d3b 100644 --- a/include/grub/net/protocol.h +++ b/include/grub/net/protocol.h @@ -1,35 +1,101 @@ #ifndef GRUB_PROTOCOL_HEADER #define GRUB_PROTOCOL_HEADER #include -#include +#include #include -#include +#include struct grub_net_protocol; -struct grub_net_interface; -struct grub_net_protstack; +struct grub_net_protocol_stack; +struct grub_net_network_layer_interface; -struct grub_net_protocol + +typedef enum grub_network_layer_protocol_id { - struct grub_net_protocol *next; + GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 +} grub_network_layer_protocol_id_t; + +struct grub_net_application_layer_protocol +{ + struct grub_net_application_layer_protocol *next; char *name; - grub_err_t (*open) (struct grub_net_interface* inf, - struct grub_net_protstack *protstack, struct grub_net_buff *nb); - grub_err_t (*open_confirm) (struct grub_net_interface *inf, - struct grub_net_protstack *protstack, struct grub_net_buff *nb); - grub_err_t (*get_payload) (struct grub_net_interface *inf, - struct grub_net_protstack *protstack, struct grub_net_buff *nb); - grub_err_t (*get_payload_confirm) (struct grub_net_interface* inf, - struct grub_net_protstack *protstack, struct grub_net_buff *nb); - grub_err_t (*close) (struct grub_net_interface *inf, - struct grub_net_protstack *protstack, struct grub_net_buff *nb); - grub_err_t (*send) (struct grub_net_interface *inf , - struct grub_net_protstack *protstack, struct grub_net_buff *nb); - grub_err_t (*recv) (struct grub_net_interface *inf , - struct grub_net_protstack *protstack, struct grub_net_buff *nb); + grub_net_protocol_id_t id; + int (*get_file_size) (struct grub_net_network_layer_interface* inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb,char *filename); + grub_err_t (*open) (struct grub_net_network_layer_interface* inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb,char *filename); + grub_err_t (*send_ack) (struct grub_net_network_layer_interface* inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb); + grub_err_t (*send) (struct grub_net_network_layer_interface *inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb); + grub_err_t (*recv) (struct grub_net_network_layer_interface *inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb); + grub_err_t (*close) (struct grub_net_network_layer_interface *inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb); }; +struct grub_net_transport_layer_protocol +{ + struct grub_net_transport_layer_protocol *next; + char *name; + grub_net_protocol_id_t id; + //grub_transport_layer_protocol_id_t id; + grub_err_t (*open) (struct grub_net_network_layer_interface* inf, + struct grub_net_application_transport_interface *app_trans_inf, struct grub_net_buff *nb); + grub_err_t (*send_ack) (struct grub_net_network_layer_interface* inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb); + grub_err_t (*send) (struct grub_net_network_layer_interface *inf, + struct grub_net_application_transport_interface *app_trans_inf, struct grub_net_buff *nb); + grub_err_t (*recv) (struct grub_net_network_layer_interface *inf, + struct grub_net_application_transport_interface *app_trans_inf, struct grub_net_buff *nb); + grub_err_t (*close) (struct grub_net_network_layer_interface *inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb); +}; + +struct grub_net_network_layer_protocol +{ + struct grub_net_network_layer_protocol *next; + char *name; + grub_net_protocol_id_t id; + //grub_network_layer_protocol_id_t id; + grub_err_t (*ntoa) (char *name, grub_net_network_layer_address_t *addr); + char * (*aton) (union grub_net_network_layer_address addr); + grub_err_t (*net_ntoa) (char *name, + grub_net_network_layer_netaddress_t *addr); + char * (*net_aton) (grub_net_network_layer_netaddress_t addr); + int (* match_net) (grub_net_network_layer_netaddress_t net, + grub_net_network_layer_address_t addr); + grub_err_t (*send) (struct grub_net_network_layer_interface *inf , + struct grub_net_transport_network_interface *trans_net_inf, struct grub_net_buff *nb); + grub_err_t (*recv) (struct grub_net_network_layer_interface *inf , + struct grub_net_transport_network_interface *trans_net_inf, struct grub_net_buff *nb); +}; + +struct grub_net_link_layer_protocol +{ + + struct grub_net_link_layer_protocol *next; + char *name; + grub_net_protocol_id_t id; + grub_err_t (*send) (struct grub_net_network_layer_interface *inf , + struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb); + grub_err_t (*recv) (struct grub_net_network_layer_interface *inf , + struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb); +}; + +extern struct grub_net_network_layer_protocol *grub_net_network_layer_protocols; + typedef struct grub_net_protocol *grub_net_protocol_t; -void grub_protocol_register (grub_net_protocol_t prot); -void grub_protocol_unregister (grub_net_protocol_t prot); +void grub_net_application_layer_protocol_register (struct grub_net_application_layer_protocol *prot); +void grub_net_application_layer_protocol_unregister (struct grub_net_application_layer_protocol *prot); +struct grub_net_application_layer_protocol *grub_net_application_layer_protocol_get (grub_net_protocol_id_t id); +void grub_net_transport_layer_protocol_register (struct grub_net_transport_layer_protocol *prot); +void grub_net_transport_layer_protocol_unregister (struct grub_net_transport_layer_protocol *prot); +struct grub_net_transport_layer_protocol *grub_net_transport_layer_protocol_get (grub_net_protocol_id_t id); +void grub_net_network_layer_protocol_register (struct grub_net_network_layer_protocol *prot); +void grub_net_network_layer_protocol_unregister (struct grub_net_network_layer_protocol *prot); +struct grub_net_network_layer_protocol *grub_net_network_layer_protocol_get (grub_net_protocol_id_t id); +void grub_net_link_layer_protocol_register (struct grub_net_link_layer_protocol *prot); +void grub_net_link_layer_protocol_unregister (struct grub_net_link_layer_protocol *prot); +struct grub_net_link_layer_protocol *grub_net_link_layer_protocol_get (grub_net_protocol_id_t id); #endif diff --git a/include/grub/net/tftp.h b/include/grub/net/tftp.h index 4148096c5..1f1c48616 100644 --- a/include/grub/net/tftp.h +++ b/include/grub/net/tftp.h @@ -14,7 +14,7 @@ /* IP port for the TFTP server */ #define TFTP_SERVER_PORT 69 -#define TFTP_CLIENT_PORT 2000 +#define TFTP_CLIENT_PORT 26300 /* We define these based on what's in arpa/tftp.h. We just like our @@ -42,10 +42,6 @@ #define TFTP_ENOUSER 7 /* no such user */ #define TFTP_DEFAULT_FILENAME "kernel" - - - - /* * own here because this is cleaner, and maps to the same data layout. * */ struct tftphdr { diff --git a/include/grub/net/type_net.h b/include/grub/net/type_net.h index 33f2d802d..276c50bf9 100644 --- a/include/grub/net/type_net.h +++ b/include/grub/net/type_net.h @@ -1,7 +1,32 @@ #ifndef GRUB_TYPES_NET_HEADER #define GRUB_TYPES_NET_HEADER 1 +#include + #define UDP_PCKT 0x11 #define IP_PCKT 0x0800 +typedef enum +{ + GRUB_NET_TFTP_ID, + GRUB_NET_UDP_ID, + GRUB_NET_IPV4_ID, + GRUB_NET_IPV6_ID, + GRUB_NET_ETHERNET_ID, + GRUB_NET_ARP_ID, + GRUB_NET_DHCP_ID +}grub_net_protocol_id_t; + +typedef union grub_net_network_layer_address +{ + grub_uint32_t ipv4; +} grub_net_network_layer_netaddress_t; + +typedef union grub_net_network_layer_netaddress +{ + struct { + grub_uint32_t base; + int masksize; + } ipv4; +} grub_net_network_layer_address_t; #endif diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h index dbfcecef0..dfc1776a4 100644 --- a/include/grub/net/udp.h +++ b/include/grub/net/udp.h @@ -1,22 +1,23 @@ #ifndef GRUB_NET_UDP_HEADER #define GRUB_NET_UDP_HEADER 1 #include -/* -typedef enum - { - GRUB_PROT_TFTP - } protocol_type; -*/ -#define GRUB_PROT_TFTP 1 - -struct udphdr { +struct udphdr +{ grub_uint16_t src; grub_uint16_t dst; grub_uint16_t len; grub_uint16_t chksum; } __attribute__ ((packed)); +struct udp_interf +{ + grub_uint16_t src; + grub_uint16_t dst; +}; + + + void udp_ini(void); void udp_fini(void); #endif From c3639ae731b7043f641090b38995a73aceda70c9 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Mon, 21 Jun 2010 19:13:26 -0300 Subject: [PATCH 018/406] File manipulation. Based in OF implementation. For debug porpouse and will be changed later. --- fs/ieee1275/ofnet.c | 355 ++++++++++++++++++++++++++++++++++ include/grub/ieee1275/ofnet.h | 95 +++++++++ 2 files changed, 450 insertions(+) create mode 100644 fs/ieee1275/ofnet.c create mode 100644 include/grub/ieee1275/ofnet.h diff --git a/fs/ieee1275/ofnet.c b/fs/ieee1275/ofnet.c new file mode 100644 index 000000000..196aadcf2 --- /dev/null +++ b/fs/ieee1275/ofnet.c @@ -0,0 +1,355 @@ +/* ofnet.c - Driver to provide access to the ofnet filesystem */ +/* + * 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 +#include +#include + +#define BUFFERADDR 0X00000000 +#define BUFFERSIZE 0x02000000 +#define U64MAXSIZE 18446744073709551615ULL + + +//static grub_ieee1275_ihandle_t handle = 0; + + +static int +grub_ofnet_iterate (int (*hook) (const char *name)) +{ + if (hook ("net")) + return 1; + return 0; +} + +static grub_err_t +grub_ofnet_open (const char *name, grub_disk_t disk) +{ + + + if (grub_strcmp (name, "network")) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a net disk"); + + disk->total_sectors = U64MAXSIZE; + disk->id = (unsigned long) "net"; + + disk->has_partitions = 0; + disk->data = 0; + + return GRUB_ERR_NONE; +} + +static void +grub_ofnet_close (grub_disk_t disk __attribute((unused))) +{ +} + +static grub_err_t +grub_ofnet_read (grub_disk_t disk __attribute((unused)), + grub_disk_addr_t sector __attribute((unused)), + grub_size_t size __attribute((unused)), + char *buf __attribute((unused))) +{ + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_ofnet_write (grub_disk_t disk __attribute((unused)), + grub_disk_addr_t sector __attribute((unused)), + grub_size_t size __attribute((unused)), + const char *buf __attribute((unused))) +{ + return GRUB_ERR_NONE; +} + +static struct grub_disk_dev grub_ofnet_dev = + { + .name = "net", + .id = GRUB_DISK_DEVICE_OFNET_ID, + .iterate = grub_ofnet_iterate, + .open = grub_ofnet_open, + .close = grub_ofnet_close, + .read = grub_ofnet_read, + .write = grub_ofnet_write, + .next = 0 + }; + +static grub_err_t +grub_ofnetfs_dir (grub_device_t device , + const char *path __attribute((unused)), + int (*hook) (const char *filename, + const struct grub_dirhook_info *info) __attribute((unused))) +{ + if(grub_strcmp (device->disk->name,"network")) + { + return grub_error (GRUB_ERR_BAD_FS, "not an net filesystem"); + } + return GRUB_ERR_NONE; +} + +static grub_ssize_t +grub_ofnetfs_read (grub_file_t file, char *buf, grub_size_t len) +{ + grub_size_t actual; + actual = len <= (file->size - file->offset)?len:file->size - file->offset; + grub_memcpy(buf, (void *)( (grub_addr_t) file->data + (grub_addr_t)file->offset), actual); + return actual; +} + +static grub_err_t +grub_ofnetfs_close (grub_file_t file) +{ + grub_ieee1275_release ((grub_addr_t) file->data,file->size); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_ofnetfs_open (struct grub_file *file , const char *name ) +{ + //void *buffer; + //grub_addr_t addr; + if (name[0] == '/') + name++; + if(grub_strcmp (file->device->disk->name,"network")) + { + + return 1; + } + grub_printf("name = %s\n",name); + + struct grub_net_protocol_stack *stack; + struct grub_net_buff *pack; + struct grub_net_application_transport_interface *app_interface; + int file_size; + char *datap; + int amount = 0; + grub_addr_t found_addr; + + stack = grub_net_protocol_stack_get ("tftp"); + app_interface = (struct grub_net_application_transport_interface *) stack->interface; + pack = grub_netbuff_alloc (80*1024); + grub_netbuff_reserve (pack,80*1024); + file_size = app_interface->app_prot->get_file_size(NULL,stack,pack,(char *) name); + + + for (found_addr = 0x800000; found_addr < + 2000 * 0x100000; found_addr += 0x100000) + { + grub_printf("traing to claim %d bytes at 0x%x\n",file_size,found_addr); + if (grub_claimmap (found_addr , file_size) != -1) + break; + } + grub_printf("Claimed %d bytes at 0x%x\n",file_size,found_addr); + file->data = (void *) found_addr; + grub_printf("file->data = 0x%x\n",(int)file->data); + grub_printf("file_size = %d\n",file_size); + grub_printf("OPEN\n"); + grub_netbuff_clear(pack); + grub_netbuff_reserve (pack,80*1024); + app_interface->app_prot->open (NULL,stack,pack,(char *) name); + + do { + //if (app_interface->app_prot->recv (NULL,stack,pack) == GRUB_ERR_NONE) + grub_printf("RECEIVE PACKET\n"); + grub_netbuff_clear(pack); + grub_netbuff_reserve (pack,80*1024); + app_interface->app_prot->recv (NULL,stack,pack); + if (grub_errno != GRUB_ERR_NONE) + return grub_errno; + grub_printf("RECEIVED PACKET\n"); + // { + grub_printf("payload_size= %d\n",pack->tail - pack->data); + grub_printf("amount= %d\n",amount); + grub_printf("file_size= %d\n",file_size); + datap = (char *)file->data + amount; + amount += (pack->tail - pack->data); + grub_printf("datap = 0x%x\n",(int)datap ); + // amount += pack->tail - pack->data; + grub_memcpy(datap, pack->data, pack->tail - pack->data); + grub_printf("SEND ACK\n"); + + grub_netbuff_clear(pack); + grub_netbuff_reserve (pack,80*1024); + app_interface->app_prot->send_ack (NULL,stack,pack); + + if (grub_errno != GRUB_ERR_NONE) + return grub_errno; + + grub_printf("SENT ACK\n"); + //} + // file->data = grub_realloc(file->data,amount); + + }while (amount < file_size); + grub_printf("transfer complete\n"); + file->size = file_size; + +// grub_netbuff_free(pack); + /*Start ARP header*/ + // arp.arpr.hwtype = 0x1; /* hardware type (must be ARPHRD_ETHER) */ + // arp.arpr.protocol = 0x0800; /* protocol type (must be ETH_P_IP) */ + // arp.arpr.hwlen = 0x6; /* hardware address length (must be 6) */ + // arp.arpr.protolen = 0x4; /* protocol address length (must be 4) */ + // arp.arpr.opcode = 0x1; /* ARP opcode */ + + + /*arp.arpr.shwaddr[0] =0x0a ; + arp.arpr.shwaddr[1] =0x11 ; + arp.arpr.shwaddr[2] =0xbd ; + arp.arpr.shwaddr[3] =0xe3 ; + arp.arpr.shwaddr[4] =0xe3 ; + arp.arpr.shwaddr[5] =0x04 ; + arp.arpr.sipaddr = dhcp_pckt -> yiaddr; */ /* sender's IP address */ + /*arp.arpr.thwaddr[0] =0; + arp.arpr.thwaddr[1] =0; + arp.arpr.thwaddr[2] =0; + arp.arpr.thwaddr[3] =0; + arp.arpr.thwaddr[4] =0; + arp.arpr.thwaddr[5] =0; + arp.arpr.tipaddr = dhcp_pckt -> siaddr; */ /* target's IP address */ + /*END ARP header */ + return grub_errno; +} + + +static grub_err_t +grub_ofnetfs_label (grub_device_t device __attribute ((unused)), + char **label __attribute ((unused))) +{ + *label = 0; + return GRUB_ERR_NONE; +} + +static struct grub_fs grub_ofnetfs_fs = + { + .name = "ofnetfs", + .dir = grub_ofnetfs_dir, + .open = grub_ofnetfs_open, + .read = grub_ofnetfs_read, + .close = grub_ofnetfs_close, + .label = grub_ofnetfs_label, + .next = 0 + }; + +static char * +grub_ieee1275_get_devargs (const char *path) +{ + int len; + char *colon = grub_strchr (path, ':'); + len = colon - path; + if (! colon) + return 0; + + return grub_strndup (path,len); +} + +static int +grub_ofnet_detect (void) +{ + + char *devalias; + char bootpath[64]; /* XXX check length */ + grub_ieee1275_phandle_t root; + grub_uint32_t net_type; + + grub_ieee1275_finddevice ("/chosen", &grub_ieee1275_chosen); + if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath, + sizeof (bootpath), 0)) + { + /* Should never happen. */ + grub_printf ("/chosen/bootpath property missing!\n"); + return 0; + } + devalias = grub_ieee1275_get_aliasdevname (bootpath); + + if (grub_strcmp(devalias ,"network")) + return 0; + + grub_net = grub_malloc (sizeof *grub_net ); + grub_net->name = "net"; + grub_net->dev = grub_ieee1275_get_devargs (bootpath); + grub_ieee1275_finddevice ("/", &root); + grub_ieee1275_get_integer_property (root, "ibm,fw-net-compatibility", + &net_type, sizeof net_type, 0); + grub_printf("root = %d\n",root); + grub_printf("net_type= %d\n",net_type); + grub_net->type = net_type; + + return 1; +} + + +#define IPMASK 0x000000FF +#define IPSIZE 16 +#define IPTEMPLATE "%d.%d.%d.%d" +char * +grub_ip2str (grub_uint32_t ip) +{ + char* str_ip; +// str_ip = grub_malloc(IPSIZE); + str_ip = grub_xasprintf (IPTEMPLATE, ip >> 24 & IPMASK, ip >> 16 & IPMASK, ip >> 8 & IPMASK, ip & IPMASK); + grub_printf ("str_ip = %s\n",str_ip); + grub_printf ("template = "IPTEMPLATE"\n" , ip >> 24 & IPMASK, ip >> 16 & IPMASK, ip >> 8 & IPMASK, ip & IPMASK); + return str_ip; +} + +void +grub_get_netinfo (grub_ofnet_t netinfo,grub_bootp_t packet) +{ + netinfo->sip = grub_ip2str(packet->siaddr); + netinfo->cip = grub_ip2str(packet->yiaddr); + netinfo->gat = grub_ip2str(packet->giaddr); + grub_printf("packet->siaddr = %x\n",packet->siaddr); + grub_printf("netinfo-> = %s\n",netinfo->sip); + grub_printf("packet->yiaddr = %x\n",packet->yiaddr); + grub_printf("netinfo-> = %s\n",netinfo->cip); + grub_printf("packet->giaddr = %x\n",packet->giaddr); + grub_printf("netinfo-> = %s\n",netinfo->gat); +} +void +grub_ofnet_init(void) +{ + tftp_ini (); + bootp_pckt = grub_getbootp (); + if(grub_ofnet_detect ()) + { + grub_get_netinfo (grub_net, bootp_pckt ); + grub_disk_dev_register (&grub_ofnet_dev); + grub_fs_register (&grub_ofnetfs_fs); + } + card_open (); +} +void +grub_ofnet_fini(void) +{ + grub_fs_unregister (&grub_ofnetfs_fs); + grub_disk_dev_unregister (&grub_ofnet_dev); +} diff --git a/include/grub/ieee1275/ofnet.h b/include/grub/ieee1275/ofnet.h new file mode 100644 index 000000000..7daadf61d --- /dev/null +++ b/include/grub/ieee1275/ofnet.h @@ -0,0 +1,95 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,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_OFNET_HEADER +#define GRUB_OFNET_HEADER 1 + +#include +#include +#include + +extern void grub_ofnet_init(void); +extern void grub_ofnet_fini(void); +/* +struct grub_net; + +struct grub_net_dev +{ + / The device name. / + const char *name; + + / FIXME: Just a template. / + int (*probe) (struct grub_net *net, const void *addr); + void (*reset) (struct grub_net *net); + int (*poll) (struct grub_net *net); + void (*transmit) (struct grub_net *net, const void *destip, + unsigned srcsock, unsigned destsock, const void *packet); + void (*disable) (struct grub_net *net); + + / The next net device. / + struct grub_net_dev *next; +}; +typedef struct grub_net_dev *grub_net_dev_t; + +struct grub_fs; +*/ +struct grub_ofnet +{ + /* The net name. */ + const char *name; + + /* The OF device string. */ + char *dev; + /*server ip*/ + char *sip; + /*client ip*/ + char *cip; + /*gateway*/ + char *gat; + /**/ + int type; +}; + +typedef struct grub_ofnet *grub_ofnet_t; + +struct grub_bootp { + grub_uint8_t op; /* 1 = BOOTREQUEST, 2 = BOOTREPLY */ + grub_uint8_t htype; /* Hardware address type. */ + grub_uint8_t hlen; /* Hardware address length */ + grub_uint8_t hops; /* Used by gateways in cross-gateway booting. */ + grub_uint32_t xid; /* Transaction ID */ + grub_uint16_t secs; /* Seconds elapsed. */ + grub_uint16_t unused; /* Unused. */ + grub_uint32_t ciaddr; /* Client IP address, */ + grub_uint32_t yiaddr; /* Client IP address filled by server. */ + grub_uint32_t siaddr; /* Server IP address. */ + grub_uint32_t giaddr; /* Gateway IP address. */ + unsigned char chaddr [16]; /* Client hardware address */ + char sname [64]; /* Server name */ + char file [128]; /* Boot filename */ +// grub_uint32_t filesize ; /*File size (testing)*/ + unsigned char vend [64]; +}; + +typedef struct grub_bootp* grub_bootp_t; + +char * grub_get_filestr(const char * ); +char * grub_ip2str (grub_uint32_t ip); +void grub_get_netinfo (grub_ofnet_t netinfo,grub_bootp_t packet); +grub_bootp_t grub_getbootp (void); +#endif /* ! GRUB_NET_HEADER */ From 60cdb895da65aaa09dcb256d03063c3a711a61e2 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Mon, 21 Jun 2010 19:15:45 -0300 Subject: [PATCH 019/406] Adaptation for the new protocols and interface structs. implementation of receive in the protocols. Also all unwanted packets are discarded. --- commands/net.c | 38 ++++---- include/grub/net.h | 118 ++++++------------------ net/ethernet.c | 88 ++++++++++++------ net/interface.c | 38 ++++++++ net/ip.c | 66 ++++++++++---- net/netbuff.c | 41 +++++++-- net/protocol.c | 50 ++++++---- net/tftp.c | 223 ++++++++++++++++++++++++++++++++++++++------- net/udp.c | 69 +++++++++++--- 9 files changed, 505 insertions(+), 226 deletions(-) diff --git a/commands/net.c b/commands/net.c index 288ba4c2a..b8ceb36f4 100644 --- a/commands/net.c +++ b/commands/net.c @@ -23,14 +23,14 @@ #include struct grub_net_route *grub_net_routes = NULL; -struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL; +struct grub_net_network_layer_interface *grub_net_network_layer_interfaces = NULL; struct grub_net_card *grub_net_cards = NULL; -struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; +struct grub_net_network_layer_protocol *grub_net_network_layer_protocols = NULL; grub_err_t -grub_net_resolve_address (struct grub_net_network_level_protocol **prot, +grub_net_resolve_address (struct grub_net_network_layer_protocol **prot, char *name, - grub_net_network_level_address_t *addr) + grub_net_network_layer_address_t *addr) { FOR_NET_NETWORK_LEVEL_PROTOCOLS (*prot) { @@ -50,15 +50,15 @@ grub_net_resolve_address (struct grub_net_network_level_protocol **prot, } grub_err_t -grub_net_route_address (grub_net_network_level_address_t addr, - grub_net_network_level_address_t *gateway, - struct grub_net_network_level_interface **interf) +grub_net_route_address (grub_net_network_layer_address_t addr, + grub_net_network_layer_address_t *gateway, + struct grub_net_network_layer_interface **interf) { struct grub_net_route *route; int depth = 0; int routecnt = 0; - struct grub_net_network_level_protocol *prot = NULL; - grub_net_network_level_address_t curtarget = addr; + struct grub_net_network_layer_protocol *prot = NULL; + grub_net_network_layer_address_t curtarget = addr; *gateway = addr; @@ -96,7 +96,7 @@ static grub_err_t grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), int argc, char **args) { - struct grub_net_network_level_interface *inter; + struct grub_net_network_layer_interface *inter; if (argc != 4) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); @@ -107,8 +107,8 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), if (inter == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found")); - inter->protocol->fini (inter); - grub_net_network_level_interface_unregister (inter); +// inter->protocol->fini (inter); + grub_net_network_layer_interface_unregister (inter); grub_free (inter->name); grub_free (inter); @@ -120,10 +120,10 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), int argc, char **args) { struct grub_net_card *card; - struct grub_net_network_level_protocol *prot; + struct grub_net_network_layer_protocol *prot; grub_err_t err; - grub_net_network_level_address_t addr; - struct grub_net_network_level_interface *inter; + grub_net_network_layer_address_t addr; + struct grub_net_network_layer_interface *inter; if (argc != 4) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("four arguments expected")); @@ -154,14 +154,14 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), grub_memcpy (&(inter->address), &addr, sizeof (inter->address)); inter->card = card; - err = prot->init (inter); + // err = prot->init (inter); if (err) { grub_free (inter->name); grub_free (inter); return err; } - grub_net_network_level_interface_register (inter); + grub_net_network_layer_interface_register (inter); return GRUB_ERR_NONE; } @@ -192,7 +192,7 @@ static grub_err_t grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), int argc, char **args) { - struct grub_net_network_level_protocol *prot; + struct grub_net_network_layer_protocol *prot; struct grub_net_route *route; if (argc < 3) @@ -247,7 +247,7 @@ grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), } else { - struct grub_net_network_level_interface *inter; + struct grub_net_network_layer_interface *inter; route->is_gateway = 0; FOR_NET_NETWORK_LEVEL_INTERFACES (inter) diff --git a/include/grub/net.h b/include/grub/net.h index f021f0e9c..abb8a3167 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -23,20 +23,11 @@ #include #include #include +#include +#include struct grub_net_card; -typedef enum -{ - GRUB_NET_TFTP_ID, - GRUB_NET_UDP_ID, - GRUB_NET_IPV4_ID, - GRUB_NET_IPV6_ID, - GRUB_NET_ETHERNET_ID, - GRUB_NET_ARP_ID, - GRUB_NET_DHCP_ID - -}protocol_type_t; struct grub_net_card_driver { @@ -66,76 +57,36 @@ struct grub_net_card void *data; }; -struct grub_net_network_level_interface; +//struct grub_net_network_layer_interface; -typedef union grub_net_network_level_address +struct grub_net_network_layer_interface { - grub_uint32_t ipv4; -} grub_net_network_level_netaddress_t; - -typedef union grub_net_network_level_netaddress -{ - struct { - grub_uint32_t base; - int masksize; - } ipv4; -} grub_net_network_level_address_t; - -typedef enum grub_network_level_protocol_id -{ - GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 -} grub_network_level_protocol_id_t; - -struct grub_net_network_level_interface; - -struct grub_net_network_level_protocol -{ - struct grub_net_network_level_protocol *next; - char *name; - grub_network_level_protocol_id_t id; - grub_err_t (*ntoa) (char *name, grub_net_network_level_address_t *addr); - char * (*aton) (union grub_net_network_level_address addr); - grub_err_t (*net_ntoa) (char *name, - grub_net_network_level_netaddress_t *addr); - char * (*net_aton) (grub_net_network_level_netaddress_t addr); - int (* match_net) (grub_net_network_level_netaddress_t net, - grub_net_network_level_address_t addr); - grub_err_t (*init) (struct grub_net_network_level_interface *dev); - grub_err_t (*fini) (struct grub_net_network_level_interface *dev); - grub_err_t (*send) (struct grub_net_network_level_interface *dev, void *buf, - grub_size_t buflen); - grub_size_t (*recv) (struct grub_net_network_level_interface *dev, void *buf, - grub_size_t buflen); -}; - -struct grub_net_network_level_interface -{ - struct grub_net_network_level_interface *next; + struct grub_net_network_layer_interface *next; char *name; /* Underlying protocol. */ - struct grub_net_network_level_protocol *protocol; + struct grub_net_network_layer_protocol *protocol; struct grub_net_card *card; - union grub_net_network_level_address address; + union grub_net_network_layer_address address; void *data; }; struct grub_net_route { struct grub_net_route *next; - grub_net_network_level_netaddress_t target; + grub_net_network_layer_netaddress_t target; char *name; - struct grub_net_network_level_protocol *prot; + struct grub_net_network_layer_protocol *prot; int is_gateway; union { - struct grub_net_network_level_interface *interface; - grub_net_network_level_address_t gw; + struct grub_net_network_layer_interface *interface; + grub_net_network_layer_address_t gw; }; }; struct grub_net_session; -struct grub_net_session_level_protocol +struct grub_net_session_layer_protocol { void (*close) (struct grub_net_session *session); grub_ssize_t (*recv) (struct grub_net_session *session, void *buf, @@ -146,7 +97,7 @@ struct grub_net_session_level_protocol struct grub_net_session { - struct grub_net_session_level_protocol *protocol; + struct grub_net_session_layer_protocol *protocol; void *data; }; @@ -170,23 +121,23 @@ grub_net_session_recv (struct grub_net_session *session, void *buf, return session->protocol->recv (session, buf, size); } -extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; +struct grub_net_network_layer_interface *grub_net_network_layer_interfaces; static inline void -grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) +grub_net_network_layer_interface_register (struct grub_net_network_layer_interface *inter) { - grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + grub_list_push (GRUB_AS_LIST_P (&grub_net_network_layer_interfaces), GRUB_AS_LIST (inter)); } static inline void -grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) +grub_net_network_layer_interface_unregister (struct grub_net_network_layer_interface *inter) { - grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_layer_interfaces), GRUB_AS_LIST (inter)); } -#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) +#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_layer_interfaces; var; var = var->next) extern struct grub_net_route *grub_net_routes; @@ -224,28 +175,13 @@ grub_net_card_unregister (struct grub_net_card *card) #define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) -extern struct grub_net_network_level_protocol *grub_net_network_level_protocols; -static inline void -grub_net_network_level_protocol_register (struct grub_net_network_level_protocol *prot) -{ - grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_protocols), - GRUB_AS_LIST (prot)); -} - -static inline void -grub_net_network_level_protocol_unregister (struct grub_net_network_level_protocol *prot) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_protocols), - GRUB_AS_LIST (prot)); -} - -#define FOR_NET_NETWORK_LEVEL_PROTOCOLS(var) for ((var) = grub_net_network_level_protocols; (var); (var) = (var)->next) +#define FOR_NET_NETWORK_LEVEL_PROTOCOLS(var) for ((var) = grub_net_network_layer_protocols; (var); (var) = (var)->next) static inline grub_err_t -grub_net_resolve_address_in_protocol (struct grub_net_network_level_protocol *prot, +grub_net_resolve_address_in_protocol (struct grub_net_network_layer_protocol *prot, char *name, - grub_net_network_level_address_t *addr) + grub_net_network_layer_address_t *addr) { return prot->ntoa (name, addr); } @@ -254,14 +190,14 @@ struct grub_net_session * grub_net_open_tcp (char *address, grub_uint16_t port); grub_err_t -grub_net_resolve_address (struct grub_net_network_level_protocol **prot, +grub_net_resolve_address (struct grub_net_network_layer_protocol **prot, char *name, - grub_net_network_level_address_t *addr); + grub_net_network_layer_address_t *addr); grub_err_t -grub_net_route_address (grub_net_network_level_address_t addr, - grub_net_network_level_address_t *gateway, - struct grub_net_network_level_interface **interf); +grub_net_route_address (grub_net_network_layer_address_t addr, + grub_net_network_layer_address_t *gateway, + struct grub_net_network_layer_interface **interf); #endif /* ! GRUB_NET_HEADER */ diff --git a/net/ethernet.c b/net/ethernet.c index 8c13966c1..a4bdbff5b 100644 --- a/net/ethernet.c +++ b/net/ethernet.c @@ -5,51 +5,85 @@ #include #include #include -#include #include +#include static grub_err_t -send_ethernet_packet (struct grub_net_interface *inf,struct grub_net_protstack *protstack __attribute__ ((unused)) - ,struct grub_net_buff *nb) +send_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ ((unused)), + struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb) { - struct etherhdr *eth; - grub_err_t err; - - if((err = grub_netbuff_push (nb,sizeof(*eth)) ) != GRUB_ERR_NONE) - return err; + struct etherhdr *eth; + + grub_netbuff_push (nb,sizeof(*eth)); eth = (struct etherhdr *) nb->data; - grub_memcpy (eth->src,inf->card->lla->addr,6 * sizeof (grub_uint8_t )); - grub_memcpy (eth->dst,inf->lla->addr,6 * sizeof (grub_uint8_t )); + eth->dst[0] =0x00; + eth->dst[1] =0x11; + eth->dst[2] =0x25; + eth->dst[3] =0xca; + eth->dst[4] =0x1f; + eth->dst[5] =0x01; + eth->src[0] =0x0a; + eth->src[1] =0x11; + eth->src[2] =0xbd; + eth->src[3] =0xe3; + eth->src[4] =0xe3; + eth->src[5] =0x04; + eth->type = 0x0800; - - return inf->card->driver->send(inf->card,nb); + + return send_card_buffer(nb); +// return inf->card->driver->send(inf->card,nb); } -static struct grub_net_protocol grub_ethernet_protocol = + +static grub_err_t +recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ ((unused)), + struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb) { - .name = "udp", - .send = send_ethernet_packet + struct etherhdr *eth; + while (1) + { + get_card_packet (nb); + eth = (struct etherhdr *) nb->data; + /*change for grub_memcmp*/ + if( eth->src[0] == 0x00 && eth->src[1] == 0x11 && eth->src[2] == 0x25 && + eth->src[3] == 0xca && eth->src[4] == 0x1f && eth->src[5] == 0x01 && eth->type == 0x800) + { + //grub_printf("ethernet eth->dst %x:%x:%x:%x:%x:%x\n",eth->dst[0], + // eth->dst[1],eth->dst[2],eth->dst[3],eth->dst[4],eth->dst[5]); + // grub_printf("ethernet eth->src %x:%x:%x:%x:%x:%x\n",eth->src[0],eth->src[1], + // eth->src[2],eth->src[3],eth->src[4],eth->src[5]); + //grub_printf("ethernet eth->type 0x%x\n",eth->type); + //grub_printf("out from ethernet\n"); + grub_netbuff_pull(nb,sizeof(*eth)); + return 0; + } + } +/* - get ethernet header + - verify if the next layer is the desired one. + - if not. get another packet. + - remove ethernet header from buffer*/ + return 0; +} + + +static struct grub_net_link_layer_protocol grub_ethernet_protocol = +{ + .name = "ethernet", + .id = GRUB_NET_ETHERNET_ID, + .send = send_ethernet_packet, + .recv = recv_ethernet_packet }; void ethernet_ini(void) { - grub_protocol_register (&grub_ethernet_protocol); + grub_net_link_layer_protocol_register (&grub_ethernet_protocol); } void ethernet_fini(void) { - grub_protocol_unregister (&grub_ethernet_protocol); + grub_net_link_layer_protocol_unregister (&grub_ethernet_protocol); } -/* -int read_ethernet_packet(buffer,bufflen, int type) -{ - - struct etherhdr eth; - eth.type = 0; - - get_card_buffer (ð,sizeof (eth)); - -}*/ diff --git a/net/interface.c b/net/interface.c index e69de29bb..bacabf4cb 100644 --- a/net/interface.c +++ b/net/interface.c @@ -0,0 +1,38 @@ +/*#include + +#define INTERFACE_REGISTER_FUNCTIONS(layerprevious,layernext) \ +struct grub_net_##layername_layer_protocol *grub_net_##layername_layer_protocols;\ +\ +void grub_net_##layerprevious_##layernext_interface_register (struct grub_net_##layername_layer_protocol *prot)\ +{\ + grub_list_push (GRUB_AS_LIST_P (&grub_net_##layername_layer_protocols),\ + GRUB_AS_LIST (prot));\ +}\ +\ +void grub_net_##layerprevious_##layernext_interface_unregister (struct grub_net_##layername_layer_protocol *prot);\ +{\ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_##layername_layer_protocols),\ + GRUB_AS_LIST (prot));\ +}\ + +INTERFACE_REGISTER_FUNCTIONS("application","transport"); +INTERFACE_REGISTER_FUNCTIONS("transport","network"); +INTERFACE_REGISTER_FUNCTIONS("network","link"); +INTERFACE_REGISTER_FUNCTIONS("link");*/ + +#include +#include +struct grub_net_protocol_stack *grub_net_protocol_stacks; +struct grub_net_protocol_stack + *grub_net_protocol_stack_get (char *name) +{ + struct grub_net_protocol_stack *p; + + for (p = grub_net_protocol_stacks; p; p = p->next) + { + if (!grub_strcmp(p->name,name)) + return p; + } + + return NULL; +} diff --git a/net/ip.c b/net/ip.c index 6fe58adb0..5eaa74f90 100644 --- a/net/ip.c +++ b/net/ip.c @@ -1,11 +1,11 @@ #include -#include #include #include #include -#include -#include #include +#include +#include +#include #include struct grub_net_protocol *grub_ipv4_prot; @@ -29,14 +29,14 @@ ipchksum(void *ipv, int len) static grub_err_t -send_ip_packet (struct grub_net_interface *inf, struct grub_net_protstack *protstack, struct grub_net_buff *nb ) +send_ip_packet (struct grub_net_network_layer_interface *inf, + struct grub_net_transport_network_interface *trans_net_inf, struct grub_net_buff *nb ) { struct iphdr *iph; - grub_err_t err; + static int id = 0x2400; - if((err = grub_netbuff_push(nb,sizeof(*iph)) ) != GRUB_ERR_NONE) - return err; + grub_netbuff_push(nb,sizeof(*iph)); iph = (struct iphdr *) nb->data; /*FIXME dont work in litte endian machines*/ @@ -44,38 +44,64 @@ send_ip_packet (struct grub_net_interface *inf, struct grub_net_protstack *prots //grub_uint8_t hdrlen = sizeof (struct iphdr)/4; iph->verhdrlen = (4<<4 | 5); iph->service = 0; - iph->len = sizeof(*iph); - iph->ident = 0x2b5f; + iph->len = nb->tail - nb-> data;//sizeof(*iph); + iph->ident = ++id; iph->frags = 0; iph->ttl = 0xff; iph->protocol = 0x11; - //grub_memcpy(&(iph->src) ,inf->card->ila->addr,inf->card->ila->len); - iph->src = *((grub_uint32_t *)inf->card->ila->addr); - //grub_memcpy(&(iph->dest) ,inf->ila->addr,inf->ila->len); - iph->dest = *((grub_uint32_t *)inf->ila->addr); + iph->src = (grub_uint32_t) bootp_pckt -> yiaddr; //inf->address.ipv4; // *((grub_uint32_t *)inf->card->ila->addr); + iph->dest = (grub_uint32_t) bootp_pckt -> siaddr;//inf->address.ipv4;// *((grub_uint32_t *)inf->ila->addr); iph->chksum = 0 ; - iph->chksum = ipchksum((void *)nb->head, sizeof(*iph)); + iph->chksum = ipchksum((void *)nb->data, sizeof(*iph)); - - return protstack->next->prot->send(inf,protstack->next,nb); + return trans_net_inf->inner_layer->link_prot->send(inf,trans_net_inf->inner_layer,nb); + //return protstack->next->prot->send(inf,protstack->next,nb); } -static struct grub_net_protocol grub_ipv4_protocol = +static grub_err_t +recv_ip_packet (struct grub_net_network_layer_interface *inf, + struct grub_net_transport_network_interface *trans_net_inf, struct grub_net_buff *nb ) +{ + + struct iphdr *iph; + while (1) + { + trans_net_inf->inner_layer->link_prot->recv(inf,trans_net_inf->inner_layer,nb); + iph = (struct iphdr *) nb->data; + if (iph->dest == 0x0908eaaa && iph->src == 0x0908ea92 && iph->protocol == 0x11) + { + grub_netbuff_pull(nb,sizeof(*iph)); + return 0; + } + } +/* grub_printf("ip.src 0x%x\n",iph->src); + grub_printf("ip.dst 0x%x\n",iph->dest); + grub_printf("ip.len 0x%x\n",iph->len); + grub_printf("ip.protocol 0x%x\n",iph->protocol); + */ + /* - get ip header + - verify if is the next layer is correct + -*/ + return 0; +} + +static struct grub_net_network_layer_protocol grub_ipv4_protocol = { .name = "ipv4", + .id = GRUB_NET_IPV4_ID, .send = send_ip_packet, - .recv = NULL + .recv = recv_ip_packet }; void ipv4_ini(void) { - grub_protocol_register (&grub_ipv4_protocol); + grub_net_network_layer_protocol_register (&grub_ipv4_protocol); } void ipv4_fini(void) { - grub_protocol_unregister (&grub_ipv4_protocol); + grub_net_network_layer_protocol_unregister (&grub_ipv4_protocol); } /* diff --git a/net/netbuff.c b/net/netbuff.c index 342260f43..136d55bc4 100644 --- a/net/netbuff.c +++ b/net/netbuff.c @@ -26,7 +26,7 @@ grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len) { net_buff->tail += len; if (net_buff->tail > net_buff->end) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return grub_error (GRUB_ERR_OUT_OF_RANGE, "put out of the packet range."); return GRUB_ERR_NONE; } @@ -34,15 +34,20 @@ grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len) { net_buff->tail -= len; if (net_buff->tail < net_buff->head) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return grub_error (GRUB_ERR_OUT_OF_RANGE, "unput out of the packet range."); return GRUB_ERR_NONE; } grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len) { net_buff->data -= len; +/* grub_printf("push len =%d\n",len); + grub_printf("pack->head =%x\n",(unsigned int)net_buff->head); + grub_printf("pack->data =%x\n",(unsigned int)net_buff->data); + grub_printf("pack->tail =%x\n",(unsigned int)net_buff->tail); + grub_printf("pack->end =%x\n",(unsigned int)net_buff->end);*/ if (net_buff->data < net_buff->head) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return grub_error (GRUB_ERR_OUT_OF_RANGE, "push out of the packet range."); return GRUB_ERR_NONE; } @@ -50,7 +55,7 @@ grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len) { net_buff->data += len; if (net_buff->data > net_buff->end) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return grub_error (GRUB_ERR_OUT_OF_RANGE, "pull out of the packet range."); return GRUB_ERR_NONE; } @@ -59,14 +64,36 @@ grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len net_buff->data += len; net_buff->tail += len; if ((net_buff->tail > net_buff->end) || (net_buff->data > net_buff->end)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return grub_error (GRUB_ERR_OUT_OF_RANGE, "reserve out of the packet range."); return GRUB_ERR_NONE; } -struct grub_net_buff * grub_netbuff_alloc ( grub_size_t len ) +struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len ) { + struct grub_net_buff *nb; + void *data; + if (len < NETBUFFMINLEN) len = NETBUFFMINLEN; + len = ALIGN_UP (len,NETBUFF_ALIGN); - return (struct grub_net_buff *) grub_memalign (len,NETBUFF_ALIGN); + data = grub_memalign (len + sizeof (*nb),NETBUFF_ALIGN); + nb = (struct grub_net_buff *) ((int)data + len); + nb->head = nb->data = nb->tail = data; + nb->end = (char *) nb; + + return nb; +} + +grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff) +{ + grub_free (net_buff); + return 0; + +} + +grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff) +{ + net_buff->data = net_buff->tail = net_buff->head; + return 0; } diff --git a/net/protocol.c b/net/protocol.c index a6117dc2c..05d4471d2 100644 --- a/net/protocol.c +++ b/net/protocol.c @@ -1,21 +1,37 @@ #include +#include +#include -static grub_net_protocol_t grub_net_protocols; - -void grub_protocol_register (grub_net_protocol_t prot) -{ - prot->next = grub_net_protocols; - grub_net_protocols = prot; +#define PROTOCOL_REGISTER_FUNCTIONS(layername) \ +struct grub_net_##layername##_layer_protocol *grub_net_##layername##_layer_protocols;\ +\ +void grub_net_##layername##_layer_protocol_register (struct grub_net_##layername##_layer_protocol *prot)\ +{\ + grub_list_push (GRUB_AS_LIST_P (&grub_net_##layername##_layer_protocols),\ + GRUB_AS_LIST (prot));\ +}\ +\ +void grub_net_##layername##_layer_protocol_unregister (struct grub_net_##layername##_layer_protocol *prot)\ +{\ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_##layername##_layer_protocols),\ + GRUB_AS_LIST (prot));\ +}\ +\ +struct grub_net_##layername##_layer_protocol \ + *grub_net_##layername##_layer_protocol_get (grub_net_protocol_id_t id)\ +{\ + struct grub_net_##layername##_layer_protocol *p;\ +\ + for (p = grub_net_##layername##_layer_protocols; p; p = p->next)\ + {\ + if (p->id == id)\ + return p;\ + }\ + \ + return NULL; \ } -void grub_protocol_unregister (grub_net_protocol_t prot) -{ - grub_net_protocol_t *p, q; - - for (p = &grub_net_protocols, q = *p; q; p = &(q->next), q = q->next) - if (q == prot) - { - *p = q->next; - break; - } -} +PROTOCOL_REGISTER_FUNCTIONS(application); +PROTOCOL_REGISTER_FUNCTIONS(transport); +PROTOCOL_REGISTER_FUNCTIONS(network); +PROTOCOL_REGISTER_FUNCTIONS(link); diff --git a/net/tftp.c b/net/tftp.c index 3f481fe58..1f04ef47e 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -4,42 +4,94 @@ #include #include #include -#include #include #include -#include #include +#include +#include +#include + +int block,rrq_count=0; +struct { + int block_size; + int size; +} tftp_file; + + +char *get_tok_val(char **tok, char **val, char **str_opt,char *end); +void process_option(char *tok, char *val); + +char *get_tok_val(char **tok, char **val,char **str_opt,char *end) +{ + char *p = *str_opt; + *tok = p; + p += grub_strlen(p) + 1; + + if(p > end) + return NULL; + + *val = p; + p += grub_strlen(p) + 1; + *str_opt = p; + return *tok; +} + +void process_option(char *tok, char *val) +{ + if (!grub_strcmp(tok,"blksize")) + { + tftp_file.block_size = grub_strtoul (val,NULL,0); + return; + } + + if (!grub_strcmp(tok,"tsize")) + { + tftp_file.size = grub_strtoul (val,NULL,0); + return; + } + +} + +//void tftp_open (char *options); /*send read request*/ static grub_err_t -send_tftp_rr (struct grub_net_interface *inf, struct grub_net_protstack *protstack,struct grub_net_buff *nb) +tftp_open (struct grub_net_network_layer_interface *inf __attribute((unused)), + struct grub_net_protocol_stack *protstack,struct grub_net_buff *nb, char *filename) { - /*Start TFTP header*/ - struct tftphdr *tftph; char *rrq; int rrqlen; int hdrlen; - grub_err_t err; + struct udp_interf *udp_interf; + struct grub_net_application_transport_interface *app_interface = (struct grub_net_application_transport_interface *) protstack->interface; - if((err = grub_netbuff_push (nb,sizeof(*tftph))) != GRUB_ERR_NONE) - return err; + app_interface = (struct grub_net_application_transport_interface *) protstack->interface; + grub_netbuff_push (nb,sizeof (*tftph)); + udp_interf = (struct udp_interf *) app_interface->data; + udp_interf->src = TFTP_CLIENT_PORT + rrq_count++; + grub_printf("open tfpt udp_port = %d\n",udp_interf->src); + udp_interf->dst = TFTP_SERVER_PORT; tftph = (struct tftphdr *) nb->data; rrq = (char *) tftph->u.rrq; rrqlen = 0; tftph->opcode = TFTP_RRQ; - grub_strcpy (rrq,inf->path); - rrqlen += grub_strlen (inf->path) + 1; - rrq += grub_strlen (inf->path) + 1; + grub_strcpy (rrq,filename); + rrqlen += grub_strlen (filename) + 1; + rrq += grub_strlen (filename) + 1; /*passar opcoes como parametro ou usar default?*/ grub_strcpy (rrq,"octet"); rrqlen += grub_strlen ("octet") + 1; rrq += grub_strlen ("octet") + 1; + //grub_strcpy (rrq,"netascii"); + //rrqlen += grub_strlen ("netascii") + 1; + //rrq += grub_strlen ("netascii") + 1; + grub_strcpy (rrq,"blksize"); rrqlen += grub_strlen("blksize") + 1; rrq += grub_strlen ("blksize") + 1; @@ -59,39 +111,146 @@ send_tftp_rr (struct grub_net_interface *inf, struct grub_net_protstack *protsta grub_netbuff_unput (nb,nb->tail - (nb->data+hdrlen)); - return protstack->next->prot->send(inf,protstack->next,nb); + app_interface->trans_prot->send (inf,protstack->interface,nb); + /*Receive OACK*/ + return app_interface->app_prot->recv(inf,protstack,nb); } -/* -int send_tftp_ack(int block, int port){ - - tftp_t pckt; - int pcktlen; - pckt.opcode = TFTP_ACK; - pckt.u.ack.block = block; - pcktlen = sizeof (pckt.opcode) + sizeof (pckt.u.ack.block); - - port = 4; - return 0;// send_udp_packet (&pckt,pcktlen,TFTP_CLIENT_PORT,port); -} - -*/ - -static struct grub_net_protocol grub_tftp_protocol = +static grub_err_t +tftp_receive (struct grub_net_network_layer_interface *inf __attribute((unused)), + struct grub_net_protocol_stack *protstack,struct grub_net_buff *nb) { - .name = "tftp", - .open = send_tftp_rr + struct tftphdr *tftph; + char *token,*value,*temp; + struct grub_net_application_transport_interface *app_interface = + (struct grub_net_application_transport_interface *) protstack->interface; + + app_interface->trans_prot->recv (inf,protstack->interface,nb); + + tftph = (struct tftphdr *) nb->data; + switch (tftph->opcode) + { + case TFTP_OACK: + /*process oack packet*/ + temp = (char *) tftph->u.oack.data; + while(get_tok_val(&token,&value,&temp,nb->tail)) + { + grub_printf("tok = <%s> val = <%s>\n",token,value); + process_option(token,value); + } + + //buff_clean + nb->data = nb->tail; + grub_printf("OACK---------------------------------------------------------\n"); + grub_printf("block_size=%d\n",tftp_file.block_size); + grub_printf("file_size=%d\n",tftp_file.size); + grub_printf("OACK---------------------------------------------------------\n"); + block = 0; + break; + case TFTP_DATA: + grub_netbuff_pull (nb,sizeof (tftph->opcode) + sizeof (tftph->u.data.block)); + if (tftph->u.data.block == block + 1) + block = tftph->u.data.block; + else + grub_netbuff_clear(nb); + break; + case TFTP_ERROR: + nb->data = nb->tail; + break; + } + return 0;// tftp_send_ack (inf,protstack,nb,tftph->u.data.block); + /*remove tftp header and return. + nb should now contain only the payload*/ +} + +static grub_err_t +tftp_send_ack (struct grub_net_network_layer_interface *inf __attribute((unused)), + struct grub_net_protocol_stack *protstack,struct grub_net_buff *nb) +{ + struct tftphdr *tftph; + struct grub_net_application_transport_interface *app_interface = (struct grub_net_application_transport_interface *) protstack->interface; + + nb->data = nb->tail = nb->end; + + grub_netbuff_push (nb,sizeof (tftph->opcode) + sizeof (tftph->u.ack.block)); + + tftph = (struct tftphdr *) nb->data; + tftph->opcode = TFTP_ACK; + tftph->u.ack.block = block; + + return app_interface->trans_prot->send (inf,protstack->interface,nb); +} + +static int tftp_file_size (struct grub_net_network_layer_interface* inf , + struct grub_net_protocol_stack *protocol_stack , struct grub_net_buff *nb ,char *filename ) +{ + + tftp_open (inf, protocol_stack,nb, filename); + return tftp_file.size; +} + +static grub_err_t +tftp_close (struct grub_net_network_layer_interface *inf __attribute((unused)), + struct grub_net_protocol_stack *protstack __attribute((unused)),struct grub_net_buff *nb __attribute((unused))) +{ + + return 0; +} + +static struct grub_net_application_transport_interface grub_net_tftp_app_trans_interf; +static struct grub_net_transport_network_interface grub_net_tftp_trans_net_interf; +static struct grub_net_network_link_interface grub_net_tftp_net_link_interf; +static struct grub_net_protocol_stack grub_net_tftp_stack = +{ + .name = "tftp", + .id = GRUB_NET_TFTP_ID, + .interface = (void *) &grub_net_tftp_app_trans_interf + }; +static struct grub_net_application_layer_protocol grub_tftp_protocol = +{ + .name = "tftp", + .id = GRUB_NET_TFTP_ID, + .open = tftp_open, + .recv = tftp_receive, + .send_ack = tftp_send_ack, + .get_file_size = tftp_file_size, + .close = tftp_close +}; + +static struct udp_interf tftp_udp_interf; + void tftp_ini(void) { - grub_protocol_register (&grub_tftp_protocol); + + ethernet_ini (); + ipv4_ini (); + udp_ini (); + grub_net_application_layer_protocol_register (&grub_tftp_protocol); + grub_net_stack_register (&grub_net_tftp_stack); + + grub_net_tftp_app_trans_interf.app_prot = &grub_tftp_protocol; + grub_net_tftp_app_trans_interf.trans_prot = grub_net_transport_layer_protocol_get (GRUB_NET_UDP_ID); + grub_net_tftp_app_trans_interf.inner_layer = &grub_net_tftp_trans_net_interf; + grub_net_tftp_app_trans_interf.data = &tftp_udp_interf; + + grub_net_tftp_trans_net_interf.trans_prot = grub_net_tftp_app_trans_interf.trans_prot; + grub_net_tftp_trans_net_interf.net_prot = grub_net_network_layer_protocol_get (GRUB_NET_IPV4_ID); + grub_net_tftp_trans_net_interf.inner_layer = &grub_net_tftp_net_link_interf; + + grub_net_tftp_net_link_interf.net_prot = grub_net_tftp_trans_net_interf.net_prot; + grub_net_tftp_net_link_interf.link_prot = grub_net_link_layer_protocol_get (GRUB_NET_ETHERNET_ID) ; + + } void tftp_fini(void) { - grub_protocol_unregister (&grub_tftp_protocol); + + + grub_net_application_layer_protocol_unregister (&grub_tftp_protocol); } /* int read_tftp_pckt (grub_uint16_t port, void *buffer, int &buff_len){ diff --git a/net/udp.c b/net/udp.c index 2a4a7690b..fb81aef93 100644 --- a/net/udp.c +++ b/net/udp.c @@ -4,41 +4,84 @@ #include #include #include -/*Assumes that there is allocated memory to the header before the buffer address. */ + static grub_err_t -send_udp_packet (struct grub_net_interface *inf, struct grub_net_protstack *protstack, struct grub_net_buff *nb) +send_udp_packet (struct grub_net_network_layer_interface *inf, + struct grub_net_application_transport_interface *app_trans_inf, struct grub_net_buff *nb) { struct udphdr *udph; - grub_err_t err; + struct udp_interf *udp_interf; - if((err = grub_netbuff_push (nb,sizeof(*udph)) ) != GRUB_ERR_NONE) - return err; + grub_netbuff_push (nb,sizeof(*udph)); udph = (struct udphdr *) nb->data; - udph->src = *((grub_uint16_t *) inf->card->tla->addr); - udph->dst = *((grub_uint16_t *) inf->tla->addr); + udp_interf = (struct udp_interf *) app_trans_inf->data; + udph->src = udp_interf->src; + udph->dst = udp_interf->dst; + /*no chksum*/ udph->chksum = 0; - udph->len = sizeof (sizeof (*udph)) + nb->end - nb->head; + udph->len = nb->tail - nb->data; - return protstack->next->prot->send(inf,protstack->next,nb); + return app_trans_inf->inner_layer->net_prot->send(inf,app_trans_inf->inner_layer,nb); } -static struct grub_net_protocol grub_udp_protocol = +static grub_err_t +receive_udp_packet (struct grub_net_network_layer_interface *inf, + struct grub_net_application_transport_interface *app_trans_inf, struct grub_net_buff *nb) +{ + + struct udphdr *udph; + struct udp_interf *udp_interf; + udp_interf = (struct udp_interf *) app_trans_inf->data; + + while(1) + { + app_trans_inf->inner_layer->net_prot->recv(inf,app_trans_inf->inner_layer,nb); + + udph = (struct udphdr *) nb->data; + // grub_printf("udph->dst %d\n",udph->dst); + // grub_printf("udp_interf->src %d\n",udp_interf->src); + if (udph->dst == udp_interf->src) + { + grub_netbuff_pull (nb,sizeof(*udph)); + + // udp_interf->src = udph->dst; + udp_interf->dst = udph->src; + + // grub_printf("udph->dst %d\n",udph->dst); + // grub_printf("udph->src %d\n",udph->src); + // grub_printf("udph->len %d\n",udph->len); + // grub_printf("udph->chksum %x\n",udph->chksum); + + /* - get udp header.. + - verify if is in the desired port + - if not. get another packet + - remove udp header*/ + + return 0; + } + } +} + + +static struct grub_net_transport_layer_protocol grub_udp_protocol = { .name = "udp", - .send = send_udp_packet + .id = GRUB_NET_UDP_ID, + .send = send_udp_packet, + .recv = receive_udp_packet }; void udp_ini(void) { - grub_protocol_register (&grub_udp_protocol); + grub_net_transport_layer_protocol_register (&grub_udp_protocol); } void udp_fini(void) { - grub_protocol_unregister (&grub_udp_protocol); + grub_net_transport_layer_protocol_unregister (&grub_udp_protocol); } /* From 8c599704a75bad68bd4d903fc1b111cba91bd354 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Mon, 21 Jun 2010 19:20:55 -0300 Subject: [PATCH 020/406] Network code specific for ieee1275 machines. Used to parse BOOTP packet from the server and use write/read on the network card. May be removed later. --- conf/powerpc-ieee1275.rmk | 3 +- include/grub/disk.h | 3 +- include/grub/ieee1275/ieee1275.h | 3 +- kern/ieee1275/init.c | 4 +- kern/ieee1275/openfw.c | 68 ++++++++++++++++-- kern/main.c | 8 +-- net/ieee1275/interface.c | 120 ++++++++++++++++++------------- 7 files changed, 144 insertions(+), 65 deletions(-) diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index 14d04f93e..ead6d4230 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -24,7 +24,8 @@ kernel_img_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \ kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c \ kern/generic/millisleep.c kern/time.c \ symlist.c kern/$(target_cpu)/cache.S net/ip.c net/tftp.c net/udp.c net/ethernet.c net/arp.c \ - net/ieee1275/interface.c net/interface.c net/protocol.c net/netbuff.c + net/ieee1275/interface.c net/interface.c net/protocol.c net/netbuff.c \ + fs/ieee1275/ofnet.c kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS += $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x200000,-Bstatic diff --git a/include/grub/disk.h b/include/grub/disk.h index e7f807e0e..1bdfb639b 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -42,7 +42,8 @@ enum grub_disk_dev_id GRUB_DISK_DEVICE_PXE_ID, GRUB_DISK_DEVICE_SCSI_ID, GRUB_DISK_DEVICE_FILE_ID, - GRUB_DISK_DEVICE_LUKS_ID + GRUB_DISK_DEVICE_LUKS_ID, + GRUB_DISK_DEVICE_OFNET_ID }; struct grub_disk; diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index b30909c68..f4c8b4edf 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -182,9 +182,8 @@ EXPORT_FUNC(grub_ieee1275_map) (grub_addr_t phys, grub_addr_t virt, char *EXPORT_FUNC(grub_ieee1275_encode_devname) (const char *path); char *EXPORT_FUNC(grub_ieee1275_get_filename) (const char *path); - int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook) (struct grub_ieee1275_devalias * alias)); - +char *EXPORT_FUNC(grub_ieee1275_get_aliasdevname) (const char *path); #endif /* ! GRUB_IEEE1275_HEADER */ diff --git a/kern/ieee1275/init.c b/kern/ieee1275/init.c index b7e5c337e..1e108c920 100644 --- a/kern/ieee1275/init.c +++ b/kern/ieee1275/init.c @@ -32,6 +32,7 @@ #include #include #include +#include /* The minimal heap size we can live with. */ #define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024) @@ -223,13 +224,14 @@ grub_machine_init (void) grub_ssize_t actual; grub_ieee1275_init (); - + grub_console_init (); #ifdef __i386__ grub_get_extended_memory (); #endif grub_claim_heap (); grub_ofdisk_init (); + grub_ofnet_init(); /* Process commandline. */ if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args, diff --git a/kern/ieee1275/openfw.c b/kern/ieee1275/openfw.c index 5693f3be0..337fc4b7e 100644 --- a/kern/ieee1275/openfw.c +++ b/kern/ieee1275/openfw.c @@ -22,11 +22,13 @@ #include #include #include +#include enum grub_ieee1275_parse_type { GRUB_PARSE_FILENAME, GRUB_PARSE_PARTITION, + GRUB_PARSE_DEVICE }; /* Walk children of 'devpath', calling hook for each. */ @@ -366,12 +368,14 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype) ret = grub_strndup (args, (grub_size_t)(comma - args)); } } - else + + else if (!grub_strcmp ("network", type)) + { + if (ptype == GRUB_PARSE_DEVICE) + ret = grub_strdup(device); + } + else { - /* XXX Handle net devices by configuring & registering a grub_net_dev - here, then return its name? - Example path: "net:,,,,,". */ grub_printf ("Unsupported type %s for device %s\n", type, device); } @@ -381,6 +385,12 @@ fail: return ret; } +char * +grub_ieee1275_get_aliasdevname (const char *path) +{ + return grub_ieee1275_parse_args (path, GRUB_PARSE_DEVICE); +} + char * grub_ieee1275_get_filename (const char *path) { @@ -432,3 +442,51 @@ grub_halt (void) grub_ieee1275_interpret ("power-off", 0); grub_ieee1275_interpret ("poweroff", 0); } + +static const struct +{ + char *name; + int offset; +} + +bootp_response_properties[] = +{ + { .name = "bootp-response", .offset = 0 }, + { .name = "dhcp-response", .offset = 0 }, + { .name = "bootpreply-packet", .offset = 0x2a }, +}; + +#define SIZE(X) ( sizeof (X) / sizeof(X[0])) + +grub_bootp_t +grub_getbootp( void ) +{ + grub_bootp_t packet = grub_malloc(sizeof *packet); + void *bootp_response = NULL; + grub_ssize_t size; + unsigned int i; + // grub_ieee1275_finddevice ("/chosen", &grub_ieee1275_chosen); + for ( i = 0; i < SIZE(bootp_response_properties); i++) + { + if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, + bootp_response_properties[i].name, &size)>=0) + break; + } + + if ( size <0 ) + { + grub_printf("Error to get bootp\n"); + return NULL; + } + + if (grub_ieee1275_get_property (grub_ieee1275_chosen, bootp_response_properties[i].name , bootp_response , + size, 0) < 0) + { + grub_printf("Error to get bootp\n"); + return NULL; + } + + packet = (void *) ((int)bootp_response + bootp_response_properties[i].offset); + return packet; +} + diff --git a/kern/main.c b/kern/main.c index 8b6c8a180..3320c4a68 100644 --- a/kern/main.c +++ b/kern/main.c @@ -95,14 +95,14 @@ grub_load_modules (void) grub_module_iterate (hook); } - +/* static void grub_load_config (void) { auto int hook (struct grub_module_header *); int hook (struct grub_module_header *header) { - /* Not an embedded config, skip. */ + / Not an embedded config, skip. / if (header->type != OBJ_TYPE_CONFIG) return 0; @@ -113,7 +113,7 @@ grub_load_config (void) grub_module_iterate (hook); } - +*/ /* Write hook for the environment variables of root. Remove surrounding parentheses, if any. */ static char * @@ -192,7 +192,7 @@ grub_main (void) grub_register_core_commands (); - grub_load_config (); + //grub_load_config (); grub_load_normal_mode (); grub_rescue_run (); } diff --git a/net/ieee1275/interface.c b/net/ieee1275/interface.c index 5a246ffa5..fbd887ad2 100644 --- a/net/ieee1275/interface.c +++ b/net/ieee1275/interface.c @@ -1,55 +1,21 @@ #include +#include #include - -grub_uint32_t get_server_ip (void) -{ - return bootp_pckt->siaddr; -} - -grub_uint32_t get_client_ip (void) -{ - return bootp_pckt->yiaddr; -} - -grub_uint8_t* get_server_mac (void) -{ - grub_uint8_t *mac; - - mac = grub_malloc (6 * sizeof(grub_uint8_t)); - mac[0] = 0x00 ; - mac[1] = 0x11 ; - mac[2] = 0x25 ; - mac[3] = 0xca ; - mac[4] = 0x1f ; - mac[5] = 0x01 ; - - return mac; - -} - -grub_uint8_t* get_client_mac (void) -{ - grub_uint8_t *mac; - - mac = grub_malloc (6 * sizeof (grub_uint8_t)); - mac[0] = 0x0a ; - mac[1] = 0x11 ; - mac[2] = 0xbd ; - mac[3] = 0xe3 ; - mac[4] = 0xe3 ; - mac[5] = 0x04 ; - - return mac; -} +#include +#include +#include +#include +#include static grub_ieee1275_ihandle_t handle; int card_open (void) { grub_ieee1275_open (grub_net->dev , &handle); - return 1;//error + return 0; } + int card_close (void) { @@ -59,22 +25,74 @@ int card_close (void) } -int send_card_buffer (void *buffer,int buff_len) +int send_card_buffer (struct grub_net_buff *pack) { - int actual; - - grub_ieee1275_write (handle,buffer,buff_len,&actual); + int actual; + //grub_printf("packet size transmited: %d\n",pack->tail - pack->data); + grub_ieee1275_write (handle,pack->data,pack->tail - pack->data,&actual); +// grub_printf("actual transmited %d\n",actual); return actual; } -int get_card_buffer (void *buffer,int buff_len) +int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) { - int actual; + int actual; + char *datap; + struct iphdr *iph; + struct etherhdr *eth; + struct arphdr *arph; + pack->data = pack->tail = pack->head; + datap = pack->data; + do + { + grub_ieee1275_read (handle,datap,sizeof (*eth),&actual); + // if (actual <= 0) + // grub_millisleep(10); - grub_ieee1275_read (handle,buffer,buff_len,&actual); - - return actual; + }while (actual <= 0); + eth = (struct etherhdr *) datap; + datap += sizeof(*eth); + + // grub_printf("ethernet eth->dst %x:%x:%x:%x:%x:%x\n",eth->dst[0], + // eth->dst[1],eth->dst[2],eth->dst[3],eth->dst[4],eth->dst[5]); + // grub_printf("ethernet eth->src %x:%x:%x:%x:%x:%x\n",eth->src[0],eth->src[1], + // eth->src[2],eth->src[3],eth->src[4],eth->src[5]); +// grub_printf ("eth.type 0x%x\n",eth->type); + + switch (eth->type) + { + case 0x806: + + grub_ieee1275_read (handle,datap,sizeof (*arph),&actual); + arph = (struct arphdr *) datap; + + grub_netbuff_put (pack,sizeof (*eth) + sizeof (*arph)); + break; + case 0x800: + grub_ieee1275_read (handle,datap,sizeof (*iph),&actual); + iph = (struct iphdr *) datap; + datap += sizeof(*iph); + + // grub_printf("ip.src 0x%x\n",iph->src); + // grub_printf("ip.dst 0x%x\n",iph->dest); + // grub_printf("ip.len 0x%x\n",iph->len); + // grub_printf("ip.protocol 0x%x\n",iph->protocol); + + grub_ieee1275_read (handle,datap,iph->len - sizeof (*iph),&actual); + + + grub_netbuff_put (pack,sizeof (*eth) + iph->len); + break; + case 0x86DD: + grub_printf("Ipv6 not yet implemented.\n"); + break; + default: + grub_printf("Unknow packet %x\n",eth->type); + break; + } +// grub_printf("packsize %d\n",pack->tail - pack->data); + return 0;// sizeof (eth) + iph.len; } From bf6d9eeb531e19d88c1705688468b89ea44c9031 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Wed, 23 Jun 2010 14:47:55 -0300 Subject: [PATCH 021/406] Abort transference when getting file size. --- net/tftp.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/net/tftp.c b/net/tftp.c index 1f04ef47e..8e89ed1f4 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -71,7 +71,6 @@ tftp_open (struct grub_net_network_layer_interface *inf __attribute((unused)), udp_interf = (struct udp_interf *) app_interface->data; udp_interf->src = TFTP_CLIENT_PORT + rrq_count++; - grub_printf("open tfpt udp_port = %d\n",udp_interf->src); udp_interf->dst = TFTP_SERVER_PORT; tftph = (struct tftphdr *) nb->data; @@ -135,16 +134,15 @@ tftp_receive (struct grub_net_network_layer_interface *inf __attribute((unused)) temp = (char *) tftph->u.oack.data; while(get_tok_val(&token,&value,&temp,nb->tail)) { - grub_printf("tok = <%s> val = <%s>\n",token,value); process_option(token,value); } //buff_clean nb->data = nb->tail; - grub_printf("OACK---------------------------------------------------------\n"); - grub_printf("block_size=%d\n",tftp_file.block_size); - grub_printf("file_size=%d\n",tftp_file.size); - grub_printf("OACK---------------------------------------------------------\n"); + // grub_printf("OACK---------------------------------------------------------\n"); + //grub_printf("block_size=%d\n",tftp_file.block_size); + // grub_printf("file_size=%d\n",tftp_file.size); + // grub_printf("OACK---------------------------------------------------------\n"); block = 0; break; case TFTP_DATA: @@ -182,11 +180,39 @@ tftp_send_ack (struct grub_net_network_layer_interface *inf __attribute((unused) return app_interface->trans_prot->send (inf,protstack->interface,nb); } +static grub_err_t +tftp_send_err (struct grub_net_network_layer_interface *inf __attribute((unused)), + struct grub_net_protocol_stack *protstack,struct grub_net_buff *nb, char *errmsg, int errcode) +{ + + struct tftphdr *tftph; + struct grub_net_application_transport_interface *app_interface + = (struct grub_net_application_transport_interface *) protstack->interface; + int msglen = 0; + int hdrlen = 0; + nb->data = nb->tail = nb->end; + + grub_netbuff_push (nb,sizeof (*tftph)); + + tftph = (struct tftphdr *) nb->data; + tftph->opcode = TFTP_ERROR; + tftph->u.err.errcode = errcode; + + grub_strcpy ((char *)tftph->u.err.errmsg,errmsg); + msglen += grub_strlen (errmsg) + 1; + hdrlen = sizeof (tftph->opcode) + sizeof (tftph->u.err.errcode) + msglen; + grub_netbuff_unput (nb,nb->tail - (nb->data + hdrlen)); + + return app_interface->trans_prot->send (inf,protstack->interface,nb); +} + static int tftp_file_size (struct grub_net_network_layer_interface* inf , struct grub_net_protocol_stack *protocol_stack , struct grub_net_buff *nb ,char *filename ) { tftp_open (inf, protocol_stack,nb, filename); + tftp_send_err (inf, protocol_stack,nb,"Abort transference.",0); + return tftp_file.size; } From 1edb7287ff681aa6889e397ab4c891ea93246f2f Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Wed, 23 Jun 2010 14:49:46 -0300 Subject: [PATCH 022/406] Parse ipv6 header on incoming packets. --- conf/powerpc-ieee1275.rmk | 1 - fs/ieee1275/ofnet.c | 31 +++++++++++++++---------------- include/grub/net/ip.h | 12 ++++++++++++ net/ieee1275/interface.c | 14 ++++++++++++-- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index ead6d4230..f0faef489 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -3,7 +3,6 @@ # Images. -<<<<<<< TREE kernel_img_HEADERS += ieee1275/ieee1275.h \ command.h i18n.h env_private.h net/ip.h net/udp.h net/ethernet.h net/arp.h net/tftp.h\ net/ieee1275/interface.h net/type_net.h net.h net/interface.h net/protocol.h net/netbuff.h diff --git a/fs/ieee1275/ofnet.c b/fs/ieee1275/ofnet.c index 196aadcf2..3bbb5c227 100644 --- a/fs/ieee1275/ofnet.c +++ b/fs/ieee1275/ofnet.c @@ -145,7 +145,7 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) return 1; } - grub_printf("name = %s\n",name); + // grub_printf("name = %s\n",name); struct grub_net_protocol_stack *stack; struct grub_net_buff *pack; @@ -164,38 +164,37 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) for (found_addr = 0x800000; found_addr < + 2000 * 0x100000; found_addr += 0x100000) { - grub_printf("traing to claim %d bytes at 0x%x\n",file_size,found_addr); +// grub_printf("trying to claim %d bytes at 0x%x\n",file_size,found_addr); if (grub_claimmap (found_addr , file_size) != -1) break; } - grub_printf("Claimed %d bytes at 0x%x\n",file_size,found_addr); +// grub_printf("Claimed %d bytes at 0x%x\n",file_size,found_addr); file->data = (void *) found_addr; - grub_printf("file->data = 0x%x\n",(int)file->data); - grub_printf("file_size = %d\n",file_size); - grub_printf("OPEN\n"); +// grub_printf("file->data = 0x%x\n",(int)file->data); +// grub_printf("file_size = %d\n",file_size); +// grub_printf("OPEN\n"); grub_netbuff_clear(pack); grub_netbuff_reserve (pack,80*1024); app_interface->app_prot->open (NULL,stack,pack,(char *) name); do { //if (app_interface->app_prot->recv (NULL,stack,pack) == GRUB_ERR_NONE) - grub_printf("RECEIVE PACKET\n"); +// grub_printf("RECEIVE PACKET\n"); grub_netbuff_clear(pack); grub_netbuff_reserve (pack,80*1024); app_interface->app_prot->recv (NULL,stack,pack); if (grub_errno != GRUB_ERR_NONE) return grub_errno; - grub_printf("RECEIVED PACKET\n"); +// grub_printf("RECEIVED PACKET\n"); // { - grub_printf("payload_size= %d\n",pack->tail - pack->data); - grub_printf("amount= %d\n",amount); - grub_printf("file_size= %d\n",file_size); +// grub_printf("payload_size= %d\n",pack->tail - pack->data); +// grub_printf("amount= %d\n",amount); +// grub_printf("file_size= %d\n",file_size); datap = (char *)file->data + amount; amount += (pack->tail - pack->data); - grub_printf("datap = 0x%x\n",(int)datap ); - // amount += pack->tail - pack->data; +// grub_printf("datap = 0x%x\n",(int)datap ); grub_memcpy(datap, pack->data, pack->tail - pack->data); - grub_printf("SEND ACK\n"); +// grub_printf("SEND ACK\n"); grub_netbuff_clear(pack); grub_netbuff_reserve (pack,80*1024); @@ -204,12 +203,12 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) if (grub_errno != GRUB_ERR_NONE) return grub_errno; - grub_printf("SENT ACK\n"); +// grub_printf("SENT ACK\n"); //} // file->data = grub_realloc(file->data,amount); }while (amount < file_size); - grub_printf("transfer complete\n"); +// grub_printf("transfer complete\n"); file->size = file_size; // grub_netbuff_free(pack); diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index e1f45dcfa..cb119ac6f 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -16,6 +16,18 @@ struct iphdr { grub_uint32_t dest; } __attribute__ ((packed)) ; +struct ip6hdr +{ + grub_uint8_t version:4, + priority:4; + grub_uint8_t flow_lbl[3]; + grub_uint16_t payload_len; + grub_uint8_t nexthdr; + grub_uint8_t hop_limit; + grub_uint8_t saddr[16]; + grub_uint8_t daddr[16]; +} __attribute__ ((packed)); + #define IP_UDP 17 /* UDP protocol */ #define IP_BROADCAST 0xFFFFFFFF diff --git a/net/ieee1275/interface.c b/net/ieee1275/interface.c index fbd887ad2..1100ee85d 100644 --- a/net/ieee1275/interface.c +++ b/net/ieee1275/interface.c @@ -44,6 +44,7 @@ int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) struct iphdr *iph; struct etherhdr *eth; struct arphdr *arph; + struct ip6hdr *ip6h; pack->data = pack->tail = pack->head; datap = pack->data; do @@ -86,11 +87,20 @@ int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) grub_netbuff_put (pack,sizeof (*eth) + iph->len); break; + case 0x86DD: - grub_printf("Ipv6 not yet implemented.\n"); + grub_printf("!!!!!!!!!!!!!!!!!IPV6 packet received!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + grub_ieee1275_read (handle,datap,sizeof (*ip6h),&actual); + ip6h = (struct ip6hdr *) datap; + grub_printf("ip6hdr->payload_len = %x\n",ip6h->payload_len); + grub_printf("ip6hdr->nexthdr = %x\n",ip6h->nexthdr); + + datap += sizeof(*ip6h); + grub_ieee1275_read (handle,datap,ip6h->payload_len - sizeof (*ip6h),&actual); break; + default: - grub_printf("Unknow packet %x\n",eth->type); + grub_printf("Unknow packet %x\n",eth->type); break; } // grub_printf("packsize %d\n",pack->tail - pack->data); From 3ec6213b179b3b82611e4caa35dae37a16fd2045 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Tue, 29 Jun 2010 06:50:15 -0300 Subject: [PATCH 023/406] Clean Debug messages --- fs/ieee1275/ofnet.c | 75 ++++++++++--------------------------- include/grub/net/type_net.h | 1 + net/ethernet.c | 6 +++ net/ieee1275/interface.c | 16 -------- net/ip.c | 7 ++++ net/netbuff.c | 7 +--- net/tftp.c | 6 ++- net/udp.c | 8 +++- 8 files changed, 46 insertions(+), 80 deletions(-) diff --git a/fs/ieee1275/ofnet.c b/fs/ieee1275/ofnet.c index 3bbb5c227..a9d16e7e0 100644 --- a/fs/ieee1275/ofnet.c +++ b/fs/ieee1275/ofnet.c @@ -56,7 +56,7 @@ grub_ofnet_open (const char *name, grub_disk_t disk) { - if (grub_strcmp (name, "network")) + if (grub_strcmp (name, "net")) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a net disk"); disk->total_sectors = U64MAXSIZE; @@ -109,7 +109,7 @@ grub_ofnetfs_dir (grub_device_t device , int (*hook) (const char *filename, const struct grub_dirhook_info *info) __attribute((unused))) { - if(grub_strcmp (device->disk->name,"network")) + if(grub_strcmp (device->disk->name,"net")) { return grub_error (GRUB_ERR_BAD_FS, "not an net filesystem"); } @@ -140,7 +140,7 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) //grub_addr_t addr; if (name[0] == '/') name++; - if(grub_strcmp (file->device->disk->name,"network")) + if(grub_strcmp (file->device->disk->name,"net")) { return 1; @@ -161,80 +161,43 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) grub_netbuff_reserve (pack,80*1024); file_size = app_interface->app_prot->get_file_size(NULL,stack,pack,(char *) name); - for (found_addr = 0x800000; found_addr < + 2000 * 0x100000; found_addr += 0x100000) { -// grub_printf("trying to claim %d bytes at 0x%x\n",file_size,found_addr); if (grub_claimmap (found_addr , file_size) != -1) break; } -// grub_printf("Claimed %d bytes at 0x%x\n",file_size,found_addr); file->data = (void *) found_addr; -// grub_printf("file->data = 0x%x\n",(int)file->data); -// grub_printf("file_size = %d\n",file_size); -// grub_printf("OPEN\n"); + grub_netbuff_clear(pack); grub_netbuff_reserve (pack,80*1024); app_interface->app_prot->open (NULL,stack,pack,(char *) name); - do { - //if (app_interface->app_prot->recv (NULL,stack,pack) == GRUB_ERR_NONE) -// grub_printf("RECEIVE PACKET\n"); + do + { grub_netbuff_clear(pack); grub_netbuff_reserve (pack,80*1024); app_interface->app_prot->recv (NULL,stack,pack); if (grub_errno != GRUB_ERR_NONE) - return grub_errno; -// grub_printf("RECEIVED PACKET\n"); - // { -// grub_printf("payload_size= %d\n",pack->tail - pack->data); -// grub_printf("amount= %d\n",amount); -// grub_printf("file_size= %d\n",file_size); - datap = (char *)file->data + amount; - amount += (pack->tail - pack->data); -// grub_printf("datap = 0x%x\n",(int)datap ); - grub_memcpy(datap, pack->data, pack->tail - pack->data); -// grub_printf("SEND ACK\n"); - + goto error; + if ((pack->tail - pack->data)) + { + // file->data = grub_realloc(file->data,amount + pack->tail - pack->data); + datap = (char *)file->data + amount; + amount += (pack->tail - pack->data); + grub_memcpy(datap , pack->data, pack->tail - pack->data); + } grub_netbuff_clear(pack); grub_netbuff_reserve (pack,80*1024); app_interface->app_prot->send_ack (NULL,stack,pack); if (grub_errno != GRUB_ERR_NONE) - return grub_errno; - -// grub_printf("SENT ACK\n"); - //} - // file->data = grub_realloc(file->data,amount); + goto error; }while (amount < file_size); -// grub_printf("transfer complete\n"); - file->size = file_size; - -// grub_netbuff_free(pack); - /*Start ARP header*/ - // arp.arpr.hwtype = 0x1; /* hardware type (must be ARPHRD_ETHER) */ - // arp.arpr.protocol = 0x0800; /* protocol type (must be ETH_P_IP) */ - // arp.arpr.hwlen = 0x6; /* hardware address length (must be 6) */ - // arp.arpr.protolen = 0x4; /* protocol address length (must be 4) */ - // arp.arpr.opcode = 0x1; /* ARP opcode */ - - - /*arp.arpr.shwaddr[0] =0x0a ; - arp.arpr.shwaddr[1] =0x11 ; - arp.arpr.shwaddr[2] =0xbd ; - arp.arpr.shwaddr[3] =0xe3 ; - arp.arpr.shwaddr[4] =0xe3 ; - arp.arpr.shwaddr[5] =0x04 ; - arp.arpr.sipaddr = dhcp_pckt -> yiaddr; */ /* sender's IP address */ - /*arp.arpr.thwaddr[0] =0; - arp.arpr.thwaddr[1] =0; - arp.arpr.thwaddr[2] =0; - arp.arpr.thwaddr[3] =0; - arp.arpr.thwaddr[4] =0; - arp.arpr.thwaddr[5] =0; - arp.arpr.tipaddr = dhcp_pckt -> siaddr; */ /* target's IP address */ - /*END ARP header */ + file->size = file_size; + + error: + grub_netbuff_free(pack); return grub_errno; } diff --git a/include/grub/net/type_net.h b/include/grub/net/type_net.h index 276c50bf9..a1717d6a7 100644 --- a/include/grub/net/type_net.h +++ b/include/grub/net/type_net.h @@ -5,6 +5,7 @@ #define UDP_PCKT 0x11 #define IP_PCKT 0x0800 +#define TIMEOUT_TIME_MS 3*1000 typedef enum { GRUB_NET_TFTP_ID, diff --git a/net/ethernet.c b/net/ethernet.c index a4bdbff5b..2bcb8107d 100644 --- a/net/ethernet.c +++ b/net/ethernet.c @@ -7,6 +7,7 @@ #include #include #include +#include static grub_err_t send_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ ((unused)), @@ -42,6 +43,8 @@ recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb) { struct etherhdr *eth; + grub_uint64_t start_time, current_time; + start_time = grub_get_time_ms(); while (1) { get_card_packet (nb); @@ -59,6 +62,9 @@ recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ grub_netbuff_pull(nb,sizeof(*eth)); return 0; } + current_time = grub_get_time_ms(); + if (current_time - start_time > TIMEOUT_TIME_MS) + return grub_error (GRUB_ERR_TIMEOUT, "Time out."); } /* - get ethernet header - verify if the next layer is the desired one. diff --git a/net/ieee1275/interface.c b/net/ieee1275/interface.c index 1100ee85d..be9810fb2 100644 --- a/net/ieee1275/interface.c +++ b/net/ieee1275/interface.c @@ -29,9 +29,7 @@ int send_card_buffer (struct grub_net_buff *pack) { int actual; - //grub_printf("packet size transmited: %d\n",pack->tail - pack->data); grub_ieee1275_write (handle,pack->data,pack->tail - pack->data,&actual); -// grub_printf("actual transmited %d\n",actual); return actual; } @@ -50,18 +48,11 @@ int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) do { grub_ieee1275_read (handle,datap,sizeof (*eth),&actual); - // if (actual <= 0) - // grub_millisleep(10); }while (actual <= 0); eth = (struct etherhdr *) datap; datap += sizeof(*eth); - // grub_printf("ethernet eth->dst %x:%x:%x:%x:%x:%x\n",eth->dst[0], - // eth->dst[1],eth->dst[2],eth->dst[3],eth->dst[4],eth->dst[5]); - // grub_printf("ethernet eth->src %x:%x:%x:%x:%x:%x\n",eth->src[0],eth->src[1], - // eth->src[2],eth->src[3],eth->src[4],eth->src[5]); -// grub_printf ("eth.type 0x%x\n",eth->type); switch (eth->type) { @@ -77,10 +68,6 @@ int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) iph = (struct iphdr *) datap; datap += sizeof(*iph); - // grub_printf("ip.src 0x%x\n",iph->src); - // grub_printf("ip.dst 0x%x\n",iph->dest); - // grub_printf("ip.len 0x%x\n",iph->len); - // grub_printf("ip.protocol 0x%x\n",iph->protocol); grub_ieee1275_read (handle,datap,iph->len - sizeof (*iph),&actual); @@ -89,11 +76,8 @@ int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) break; case 0x86DD: - grub_printf("!!!!!!!!!!!!!!!!!IPV6 packet received!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); grub_ieee1275_read (handle,datap,sizeof (*ip6h),&actual); ip6h = (struct ip6hdr *) datap; - grub_printf("ip6hdr->payload_len = %x\n",ip6h->payload_len); - grub_printf("ip6hdr->nexthdr = %x\n",ip6h->nexthdr); datap += sizeof(*ip6h); grub_ieee1275_read (handle,datap,ip6h->payload_len - sizeof (*ip6h),&actual); diff --git a/net/ip.c b/net/ip.c index 5eaa74f90..044cfde6b 100644 --- a/net/ip.c +++ b/net/ip.c @@ -7,6 +7,7 @@ #include #include #include +#include struct grub_net_protocol *grub_ipv4_prot; @@ -65,6 +66,8 @@ recv_ip_packet (struct grub_net_network_layer_interface *inf, { struct iphdr *iph; + grub_uint64_t start_time, current_time; + start_time = grub_get_time_ms(); while (1) { trans_net_inf->inner_layer->link_prot->recv(inf,trans_net_inf->inner_layer,nb); @@ -74,6 +77,10 @@ recv_ip_packet (struct grub_net_network_layer_interface *inf, grub_netbuff_pull(nb,sizeof(*iph)); return 0; } + + current_time = grub_get_time_ms(); + if (current_time - start_time > TIMEOUT_TIME_MS) + return grub_error (GRUB_ERR_TIMEOUT, "Time out."); } /* grub_printf("ip.src 0x%x\n",iph->src); grub_printf("ip.dst 0x%x\n",iph->dest); diff --git a/net/netbuff.c b/net/netbuff.c index 136d55bc4..ce52233b6 100644 --- a/net/netbuff.c +++ b/net/netbuff.c @@ -41,11 +41,6 @@ grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len) grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len) { net_buff->data -= len; -/* grub_printf("push len =%d\n",len); - grub_printf("pack->head =%x\n",(unsigned int)net_buff->head); - grub_printf("pack->data =%x\n",(unsigned int)net_buff->data); - grub_printf("pack->tail =%x\n",(unsigned int)net_buff->tail); - grub_printf("pack->end =%x\n",(unsigned int)net_buff->end);*/ if (net_buff->data < net_buff->head) return grub_error (GRUB_ERR_OUT_OF_RANGE, "push out of the packet range."); return GRUB_ERR_NONE; @@ -87,7 +82,7 @@ struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len ) grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff) { - grub_free (net_buff); + grub_free (net_buff->head); return 0; } diff --git a/net/tftp.c b/net/tftp.c index 8e89ed1f4..dff0f134c 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -70,7 +70,7 @@ tftp_open (struct grub_net_network_layer_interface *inf __attribute((unused)), grub_netbuff_push (nb,sizeof (*tftph)); udp_interf = (struct udp_interf *) app_interface->data; - udp_interf->src = TFTP_CLIENT_PORT + rrq_count++; + udp_interf->src = TFTP_CLIENT_PORT;// + rrq_count++; udp_interf->dst = TFTP_SERVER_PORT; tftph = (struct tftphdr *) nb->data; @@ -112,6 +112,8 @@ tftp_open (struct grub_net_network_layer_interface *inf __attribute((unused)), app_interface->trans_prot->send (inf,protstack->interface,nb); /*Receive OACK*/ + grub_netbuff_clear (nb); + grub_netbuff_reserve (nb,80*1024); return app_interface->app_prot->recv(inf,protstack,nb); } @@ -211,6 +213,8 @@ static int tftp_file_size (struct grub_net_network_layer_interface* inf , { tftp_open (inf, protocol_stack,nb, filename); + grub_netbuff_clear (nb); + grub_netbuff_reserve (nb,80*1024); tftp_send_err (inf, protocol_stack,nb,"Abort transference.",0); return tftp_file.size; diff --git a/net/udp.c b/net/udp.c index fb81aef93..0321fd58a 100644 --- a/net/udp.c +++ b/net/udp.c @@ -4,6 +4,7 @@ #include #include #include +#include static grub_err_t send_udp_packet (struct grub_net_network_layer_interface *inf, @@ -35,7 +36,8 @@ receive_udp_packet (struct grub_net_network_layer_interface *inf, struct udphdr *udph; struct udp_interf *udp_interf; udp_interf = (struct udp_interf *) app_trans_inf->data; - + grub_uint64_t start_time, current_time; + start_time = grub_get_time_ms(); while(1) { app_trans_inf->inner_layer->net_prot->recv(inf,app_trans_inf->inner_layer,nb); @@ -62,6 +64,10 @@ receive_udp_packet (struct grub_net_network_layer_interface *inf, return 0; } + current_time = grub_get_time_ms(); + if (current_time - start_time > TIMEOUT_TIME_MS) + return grub_error (GRUB_ERR_TIMEOUT, "Time out."); + } } From f8795693f1c3caa557b8658ac3d8661b1f84b739 Mon Sep 17 00:00:00 2001 From: Paulo de Rezende Pinatti Date: Tue, 13 Jul 2010 11:22:35 -0300 Subject: [PATCH 024/406] Added support to netdisk specified in the form (net,protocol,server_ip,username,password) an to list its information with command ls. * fs/ieee1275/ofnet.c (grub_ofnet_open): parse parameters to determine netdisk data * fs/ieee1275/ofnet.c (grub_ofnet_close): dealloc netdisk data * include/grub/disk.h: added struct grub_netdisk_data * include/grub/ieee1275/ofnet.h: added newline * kern/disk.c (grub_disk_open): ignore partition check for netdisk * normal/misc.c (grub_normal_print_device_info): added support to list netdisk information --- fs/ieee1275/ofnet.c | 159 ++++++++++++++++++++++++++++++++-- include/grub/disk.h | 17 ++++ include/grub/ieee1275/ofnet.h | 1 + kern/disk.c | 4 +- normal/misc.c | 39 +++++++++ 5 files changed, 213 insertions(+), 7 deletions(-) diff --git a/fs/ieee1275/ofnet.c b/fs/ieee1275/ofnet.c index a9d16e7e0..9010317ba 100644 --- a/fs/ieee1275/ofnet.c +++ b/fs/ieee1275/ofnet.c @@ -42,6 +42,85 @@ //static grub_ieee1275_ihandle_t handle = 0; +static const char * +find_sep (const char *name) +{ + const char *p = name; + char c = *p; + + if (c == '\0') + return NULL; + + do + { + if (c == '\\' && *p == ',') + p++; + else if (c == ',') + return p - 1; + } while ((c = *p++) != '\0'); + return p - 1; +} + +static grub_err_t +retrieve_field(const char *src, char **field, const char **rest) +{ + const char *p; + grub_size_t len; + + p = find_sep(src); + if (! p) + { + *field = NULL; + *rest = src; + return 0; + } + + len = p - src; + *field = grub_malloc (len + 1); + if (! *field) + { + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + } + + grub_memcpy (*field, src, len); + (*field)[len] = '\0'; + + if (*p == '\0') + *rest = p; + else + *rest = p + 1; + return 0; +} + +static grub_err_t +parse_ip (const char *val, grub_uint32_t *ip, const char **rest) +{ + grub_uint32_t newip = 0; + unsigned long t; + int i; + const char *ptr = val; + + for (i = 0; i < 4; i++) + { + t = grub_strtoul (ptr, (char **) &ptr, 0); + if (grub_errno) + return grub_errno; + if (t & ~0xff) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); + newip >>= 8; + newip |= (t << 24); + if (i != 3 && *ptr != '.') + return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); + ptr++; + } + ptr = ptr - 1; + if ( *ptr != '\0' && *ptr != ',') + return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); + *ip = newip; + if (rest) + *rest = ptr; + return 0; +} static int grub_ofnet_iterate (int (*hook) (const char *name)) @@ -54,23 +133,93 @@ grub_ofnet_iterate (int (*hook) (const char *name)) static grub_err_t grub_ofnet_open (const char *name, grub_disk_t disk) { - + grub_err_t err; + const char *p1, *p2; + char *user = NULL, *pwd = NULL; + grub_netdisk_data_t data; + grub_netdisk_protocol_t proto; + grub_uint32_t server_ip = 0; if (grub_strcmp (name, "net")) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a net disk"); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a net disk"); - disk->total_sectors = U64MAXSIZE; + p1 = find_sep(disk->name); + if (! p1 || *p1 == '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments missing"); + p1++; + + // parse protocol + p2 = find_sep(p1); + if (! p2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no protocol specified"); + if ((p2 - p1 == 4) && (! grub_strncasecmp(p1, "tftp", p2 - p1))) + proto = GRUB_NETDISK_PROTOCOL_TFTP; + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid protocol specified"); + + // parse server ip + if ( *p2 == '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no server ip specified"); + p1 = p2 + 1; + err = parse_ip(p1, &server_ip, &p2); + if (err) + return err; + + // parse username (optional) + if ( *p2 == ',') + p2++; + err = retrieve_field(p2, &user, &p1); + if (err) + return err; + if (user) + { + // parse password (optional) + err = retrieve_field(p1, &pwd, &p2); + if (err) + { + grub_free(user); + return err; + } + } + + if (! disk->data) + { + data = grub_malloc (sizeof(*data)); + disk->data = data; + } + else + { + data = disk->data; + if (data->username) + grub_free(data->username); + if (data->password) + grub_free(data->password); + } + data->protocol = proto; + data->server_ip = server_ip; + data->username = user; + data->password = pwd; + + disk->total_sectors = 0; disk->id = (unsigned long) "net"; disk->has_partitions = 0; - disk->data = 0; return GRUB_ERR_NONE; } static void -grub_ofnet_close (grub_disk_t disk __attribute((unused))) +grub_ofnet_close (grub_disk_t disk) { + grub_netdisk_data_t data = disk->data; + if (data) + { + if (data->username) + grub_free(data->username); + if (data->password) + grub_free(data->password); + grub_free(data); + } } static grub_err_t diff --git a/include/grub/disk.h b/include/grub/disk.h index 1bdfb639b..dc8bc5018 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -119,6 +119,23 @@ struct grub_disk }; typedef struct grub_disk *grub_disk_t; +/* Net Disk */ +enum grub_netdisk_protocol +{ + GRUB_NETDISK_PROTOCOL_TFTP +}; +typedef enum grub_netdisk_protocol grub_netdisk_protocol_t; + +struct grub_netdisk_data +{ + grub_netdisk_protocol_t protocol; + grub_uint32_t server_ip; + grub_uint32_t port; + char *username; + char *password; +}; +typedef struct grub_netdisk_data *grub_netdisk_data_t; + #ifdef GRUB_UTIL struct grub_disk_memberlist { diff --git a/include/grub/ieee1275/ofnet.h b/include/grub/ieee1275/ofnet.h index 7daadf61d..a26c22235 100644 --- a/include/grub/ieee1275/ofnet.h +++ b/include/grub/ieee1275/ofnet.h @@ -25,6 +25,7 @@ extern void grub_ofnet_init(void); extern void grub_ofnet_fini(void); + /* struct grub_net; diff --git a/kern/disk.c b/kern/disk.c index ccd5f200f..051e59aca 100644 --- a/kern/disk.c +++ b/kern/disk.c @@ -281,7 +281,7 @@ grub_disk_open (const char *name) goto fail; } - if (p && ! disk->has_partitions) + if (p && ! disk->has_partitions && grub_strcmp (raw, "net")) { grub_error (GRUB_ERR_BAD_DEVICE, "no partition on this disk"); goto fail; @@ -289,7 +289,7 @@ grub_disk_open (const char *name) disk->dev = dev; - if (p) + if (p && grub_strcmp (raw, "net")) { disk->partition = grub_partition_probe (disk, p + 1); if (! disk->partition) diff --git a/normal/misc.c b/normal/misc.c index 17ba372ce..d53fe711c 100644 --- a/normal/misc.c +++ b/normal/misc.c @@ -32,8 +32,47 @@ grub_err_t grub_normal_print_device_info (const char *name) { grub_device_t dev; + grub_netdisk_data_t data; char *p; + if ((! grub_strcmp(name, "net")) || (! grub_strncmp(name, "net,", 4))) + { + grub_printf_ (N_("Device network:")); + grub_putchar (' '); + + dev = grub_device_open (name); + if (! dev || ! dev->disk || ! dev->disk->data) + grub_printf ("%s", _("Network information not available")); + else + { + data = dev->disk->data; + grub_putchar ('\n'); + grub_putchar ('\t'); + if (data->protocol == GRUB_NETDISK_PROTOCOL_TFTP) + grub_printf_(N_("Protocol: %s"), "TFTP"); + else + grub_printf_(N_("Protocol: %s"), "Unknown"); + grub_putchar ('\n'); + grub_putchar ('\t'); + grub_printf_(N_("Server IP: %d.%d.%d.%d"), data->server_ip & 0xff, data->server_ip >> 8 & 0xff, data->server_ip >> 16 & 0xff, data->server_ip >> 24 & 0xff); + if (data->username) + { + grub_putchar ('\n'); + grub_putchar ('\t'); + grub_printf_(N_("Username: %s"), data->username); + if (data->password) + { + grub_putchar ('\n'); + grub_putchar ('\t'); + grub_printf_(N_("Password: %s"), data->password); + } + } + } + grub_putchar ('\n'); + + return GRUB_ERR_NONE; + } + p = grub_strchr (name, ','); if (p) { From 7e8b77c03359b2537dee39ded103b2f126157dd8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 19 Jul 2010 21:22:54 +0200 Subject: [PATCH 025/406] AHCI skeleton --- conf/i386.rmk | 5 + disk/ahci.c | 311 ++++++++++++++++++++++++++++++++++++++++++++ include/grub/scsi.h | 3 +- 3 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 disk/ahci.c diff --git a/conf/i386.rmk b/conf/i386.rmk index b1df584a6..54edb468b 100644 --- a/conf/i386.rmk +++ b/conf/i386.rmk @@ -36,6 +36,11 @@ ata_mod_SOURCES = disk/ata.c ata_mod_CFLAGS = $(COMMON_CFLAGS) ata_mod_LDFLAGS = $(COMMON_LDFLAGS) +pkglib_MODULES += ahci.mod +ahci_mod_SOURCES = disk/ahci.c +ahci_mod_CFLAGS = $(COMMON_CFLAGS) +ahci_mod_LDFLAGS = $(COMMON_LDFLAGS) + # For setpci.mod pkglib_MODULES += setpci.mod setpci_mod_SOURCES = commands/setpci.c diff --git a/disk/ahci.c b/disk/ahci.c new file mode 100644 index 000000000..1372fd651 --- /dev/null +++ b/disk/ahci.c @@ -0,0 +1,311 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007, 2008, 2009, 2010 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 + +struct grub_ahci_cmd_head +{ + grub_uint32_t unused[8]; +}; + +struct grub_ahci_hba_port +{ + grub_uint64_t command_list_base; + grub_uint32_t unused[12]; + grub_uint32_t sata_active; + grub_uint32_t command_issue; + grub_uint32_t unused[16]; +}; + +struct grub_ahci_hba +{ + grub_uint32_t cap; +#define GRUB_AHCI_HBA_CAP_MASK 0x1f + grub_uint32_t global_control; +#define GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN 0x80000000 + grub_uint32_t ports_implemented; + grub_uint32_t unused1[7]; + grub_uint32_t bios_handoff; +#define GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED 1 +#define GRUB_AHCI_BIOS_HANDOFF_OS_OWNED 2 +#define GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED 8 +#define GRUB_AHCI_BIOS_HANDOFF_RWC 8 + grub_uint32_t unused2[53]; + struct grub_ahci_hba_port ports[32]; +}; + +struct grub_ahci_device +{ + struct grub_ahci_device *next; + volatile struct grub_ahci_hba *hba; + int port; + int num; + struct grub_pci_dma_chunk *command_list_chunk; + volatile struct grub_ahci_cmd_head *command_list; +}; + +static struct grub_ahci_device *grub_ahci_devices; +static int numdevs; + +static int NESTED_FUNC_ATTR +grub_ahci_pciinit (grub_pci_device_t dev, + grub_pci_id_t pciid __attribute__ ((unused))) +{ + grub_pci_address_t addr; + grub_uint32_t class; + grub_uint32_t bar; + int nports; + volatile struct grub_ahci_hba *hba; + + /* Read class. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + /* Check if this class ID matches that of a PCI IDE Controller. */ + if (class >> 8 != 0x010601) + return 0; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG5); + bar = grub_pci_read (addr); + + if (bar & (GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_TYPE_MASK + | GRUB_PCI_ADDR_MEM_PREFETCH) + != (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32)) + return 0; + + hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK, + sizeof (hba)); + + hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; + + nports = hba->cap & GRUB_AHCI_HBA_CAP_MASK; + + if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED)) + { + grub_uint64_t endtime; + + grub_dprintf ("ahci", "Requesting AHCI ownership\n"); + hba->bios_handoff = (hba->bios_handoff & ~GRUB_AHCI_BIOS_HANDOFF_RWC) + | GRUB_AHCI_BIOS_HANDOFF_OS_OWNED; + grub_dprintf ("ahci", "Waiting for BIOS to give up ownership\n"); + endtime = grub_get_time_ms () + 1000; + while ((hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED) + && grub_get_time_ms () < endtime); + if (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED) + { + grub_dprintf ("ahci", "Forcibly taking ownership\n"); + hba->bios_handoff = GRUB_AHCI_BIOS_HANDOFF_OS_OWNED; + hba->bios_handoff |= GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED; + } + else + grub_dprintf ("ahci", "AHCI ownership obtained\n"); + } + else + grub_dprintf ("ahci", "AHCI is already in OS mode\n"); + + for (i = 0; i < nports; i++) + { + struct grub_ahci_device *adev; + struct grub_pci_dma_chunk *command_list; + + if (!(hba->ports_implemented & (1 << i))) + continue; + + command_list = grub_memalign_dma32 (1024, + sizeof (struct grub_ahci_cmd_head)); + if (!command_list) + return 1; + + adev = grub_malloc (sizeof (*adev)); + if (!adev) + { + grub_dma_free (command_list); + return 1; + } + + adev->hba = hba; + adev->port = i; + adev->num = numdevs++; + adev->command_list_chunk = command_list; + adev->command_list = grub_dma_get_virt (command_list); + adev->hba->ports[i].command_list_base = grub_dma_get_phys (command_list); + grub_list_push (GRUB_AS_LIST_P (&grub_ahci_devices), + GRUB_AS_LIST (adev)); + } + + return 0; +} + +static grub_err_t +grub_ahci_initialize (void) +{ + grub_pci_iterate (grub_ahci_pciinit); + return grub_errno; +} + + + + +static int +grub_ahci_iterate (int (*hook) (int bus, int luns)) +{ + struct grub_ahci_device *dev; + + FOR_LIST_ELEMENTS(dev, grub_ahci_devices) + if (hook (dev->num, 1)) + return 1; + + return 0; +} + +#if 0 +static int +find_free_cmd_slot (struct grub_ahci_device *dev) +{ + int i; + for (i = 0; i < 32; i++) + { + if (dev->hda->ports[dev->port].command_issue & (1 << i)) + continue; + if (dev->hda->ports[dev->port].sata_active & (1 << i)) + continue; + return i; + } + return -1; +} +#endif + +static grub_err_t +grub_ahci_packet (struct grub_ahci_device *dev, char *packet, + grub_size_t size) +{ + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_ahci_read (struct grub_scsi *scsi, + grub_size_t cmdsize __attribute__((unused)), + char *cmd, grub_size_t size, char *buf) +{ + struct grub_ahci_device *dev = (struct grub_ahci_device *) scsi->data; + + grub_dprintf("ahci", "grub_ahci_read (size=%llu)\n", (unsigned long long) size); + + if (grub_atapi_packet (dev, cmd, size)) + return grub_errno; + + grub_size_t nread = 0; + while (nread < size) + { + /* Wait for !BSY, DRQ, I/O, !C/D. */ + if (grub_atapi_wait_drq (dev, GRUB_ATAPI_IREASON_DATA_IN, GRUB_ATA_TOUT_DATA)) + return grub_errno; + + /* Get byte count for this DRQ assertion. */ + unsigned cnt = grub_ata_regget (dev, GRUB_ATAPI_REG_CNTHIGH) << 8 + | grub_ata_regget (dev, GRUB_ATAPI_REG_CNTLOW); + grub_dprintf("ata", "DRQ count=%u\n", cnt); + + /* Count of last transfer may be uneven. */ + if (! (0 < cnt && cnt <= size - nread && (! (cnt & 1) || cnt == size - nread))) + return grub_error (GRUB_ERR_READ_ERROR, "invalid ATAPI transfer count"); + + /* Read the data. */ + grub_ata_pio_read (dev, buf + nread, cnt); + + if (cnt & 1) + buf[nread + cnt - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress + GRUB_ATA_REG_DATA)); + + nread += cnt; + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_ahci_write (struct grub_scsi *scsi __attribute__((unused)), + grub_size_t cmdsize __attribute__((unused)), + char *cmd __attribute__((unused)), + grub_size_t size __attribute__((unused)), + char *buf __attribute__((unused))) +{ + // XXX: scsi.mod does not use write yet. + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "AHCI write not implemented"); +} + +static grub_err_t +grub_ahci_open (int devnum, struct grub_scsi *scsi) +{ + struct grub_ahci_device *dev; + + FOR_LIST_ELEMENTS(dev, grub_ahci_devices) + { + if (dev->num == devnum) + break; + } + + grub_dprintf ("ata", "opening AHCI dev `ahci%d'\n", devnum); + + if (! dev) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such AHCI device"); + + scsi->data = dev; + + return GRUB_ERR_NONE; +} + + +static struct grub_scsi_dev grub_ahci_dev = + { + .name = "ahci", + .id = GRUB_SCSI_SUBSYSTEM_AHCI, + .iterate = grub_ahci_iterate, + .open = grub_ahci_open, + .read = grub_ahci_read, + .write = grub_ahci_write + }; + + + +GRUB_MOD_INIT(ahci) +{ + /* To prevent two drivers operating on the same disks. */ + grub_disk_firmware_is_tainted = 1; + if (grub_disk_firmware_fini) + { + grub_disk_firmware_fini (); + grub_disk_firmware_fini = NULL; + } + + /* AHCI initialization. */ + grub_ahci_initialize (); + + /* AHCI devices are handled by scsi.mod. */ + grub_scsi_dev_register (&grub_ahci_dev); +} + +GRUB_MOD_FINI(ahci) +{ + grub_scsi_dev_unregister (&grub_ahci_dev); +} diff --git a/include/grub/scsi.h b/include/grub/scsi.h index b3c60f3e8..289cd8e4a 100644 --- a/include/grub/scsi.h +++ b/include/grub/scsi.h @@ -29,7 +29,8 @@ struct grub_scsi; enum { GRUB_SCSI_SUBSYSTEM_USBMS, - GRUB_SCSI_SUBSYSTEM_ATAPI + GRUB_SCSI_SUBSYSTEM_ATAPI, + GRUB_SCSI_SUBSYSTEM_AHCI }; #define GRUB_SCSI_ID_SUBSYSTEM_SHIFT 24 From 818a356eb196a2c2ca5af7d580b9920c8564ebcc Mon Sep 17 00:00:00 2001 From: Paulo de Rezende Pinatti Date: Thu, 29 Jul 2010 16:36:17 -0300 Subject: [PATCH 026/406] Fixed get_card_packet to correctly read data from network card into buffer. * net/ieee1275/interface.c (get_card_packet): read data regardless of ethernet header --- net/ieee1275/interface.c | 54 +++------------------------------------- 1 file changed, 4 insertions(+), 50 deletions(-) diff --git a/net/ieee1275/interface.c b/net/ieee1275/interface.c index be9810fb2..342044041 100644 --- a/net/ieee1275/interface.c +++ b/net/ieee1275/interface.c @@ -1,9 +1,4 @@ #include -#include -#include -#include -#include -#include #include #include @@ -37,56 +32,15 @@ int send_card_buffer (struct grub_net_buff *pack) int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) { - int actual; - char *datap; - struct iphdr *iph; - struct etherhdr *eth; - struct arphdr *arph; - struct ip6hdr *ip6h; + int actual, rc; pack->data = pack->tail = pack->head; - datap = pack->data; do { - grub_ieee1275_read (handle,datap,sizeof (*eth),&actual); + rc = grub_ieee1275_read (handle,pack->data,1500,&actual); - }while (actual <= 0); - eth = (struct etherhdr *) datap; - datap += sizeof(*eth); - + }while (actual <= 0 || rc < 0); + grub_netbuff_put (pack, actual); - switch (eth->type) - { - case 0x806: - - grub_ieee1275_read (handle,datap,sizeof (*arph),&actual); - arph = (struct arphdr *) datap; - - grub_netbuff_put (pack,sizeof (*eth) + sizeof (*arph)); - break; - case 0x800: - grub_ieee1275_read (handle,datap,sizeof (*iph),&actual); - iph = (struct iphdr *) datap; - datap += sizeof(*iph); - - - grub_ieee1275_read (handle,datap,iph->len - sizeof (*iph),&actual); - - - grub_netbuff_put (pack,sizeof (*eth) + iph->len); - break; - - case 0x86DD: - grub_ieee1275_read (handle,datap,sizeof (*ip6h),&actual); - ip6h = (struct ip6hdr *) datap; - - datap += sizeof(*ip6h); - grub_ieee1275_read (handle,datap,ip6h->payload_len - sizeof (*ip6h),&actual); - break; - - default: - grub_printf("Unknow packet %x\n",eth->type); - break; - } // grub_printf("packsize %d\n",pack->tail - pack->data); return 0;// sizeof (eth) + iph.len; } From 11d1ea5df607d8d2e6463f482f24e92c9cb609be Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 29 Jul 2010 17:52:54 -0300 Subject: [PATCH 027/406] Use server and client IP from the bootp packet. --- net/ip.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/net/ip.c b/net/ip.c index 044cfde6b..65b0f2b70 100644 --- a/net/ip.c +++ b/net/ip.c @@ -72,7 +72,9 @@ recv_ip_packet (struct grub_net_network_layer_interface *inf, { trans_net_inf->inner_layer->link_prot->recv(inf,trans_net_inf->inner_layer,nb); iph = (struct iphdr *) nb->data; - if (iph->dest == 0x0908eaaa && iph->src == 0x0908ea92 && iph->protocol == 0x11) + if (iph->protocol == 0x11 && + iph->dest == (grub_uint32_t) bootp_pckt -> yiaddr && + iph->src == (grub_uint32_t) bootp_pckt -> siaddr ) { grub_netbuff_pull(nb,sizeof(*iph)); return 0; @@ -82,11 +84,11 @@ recv_ip_packet (struct grub_net_network_layer_interface *inf, if (current_time - start_time > TIMEOUT_TIME_MS) return grub_error (GRUB_ERR_TIMEOUT, "Time out."); } -/* grub_printf("ip.src 0x%x\n",iph->src); - grub_printf("ip.dst 0x%x\n",iph->dest); - grub_printf("ip.len 0x%x\n",iph->len); - grub_printf("ip.protocol 0x%x\n",iph->protocol); - */ +// grub_printf("ip.src 0x%x\n",iph->src); +// grub_printf("ip.dst 0x%x\n",iph->dest); +// grub_printf("ip.len 0x%x\n",iph->len); +// grub_printf("ip.protocol 0x%x\n",iph->protocol); + /* - get ip header - verify if is the next layer is correct -*/ From f89661762a82b0784965ca27d88473e704648cf2 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 29 Jul 2010 18:07:09 -0300 Subject: [PATCH 028/406] Only open the card in netboot. --- fs/ieee1275/ofnet.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/fs/ieee1275/ofnet.c b/fs/ieee1275/ofnet.c index 9010317ba..82b5235cc 100644 --- a/fs/ieee1275/ofnet.c +++ b/fs/ieee1275/ofnet.c @@ -141,6 +141,7 @@ grub_ofnet_open (const char *name, grub_disk_t disk) grub_uint32_t server_ip = 0; if (grub_strcmp (name, "net")) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a net disk"); p1 = find_sep(disk->name); @@ -258,7 +259,7 @@ grub_ofnetfs_dir (grub_device_t device , int (*hook) (const char *filename, const struct grub_dirhook_info *info) __attribute((unused))) { - if(grub_strcmp (device->disk->name,"net")) + if(grub_strncmp (device->disk->name,"net",3)) { return grub_error (GRUB_ERR_BAD_FS, "not an net filesystem"); } @@ -287,9 +288,10 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) { //void *buffer; //grub_addr_t addr; + if (name[0] == '/') name++; - if(grub_strcmp (file->device->disk->name,"net")) + if(grub_strncmp (file->device->disk->name,"net",3)) { return 1; @@ -311,15 +313,17 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) file_size = app_interface->app_prot->get_file_size(NULL,stack,pack,(char *) name); for (found_addr = 0x800000; found_addr < + 2000 * 0x100000; found_addr += 0x100000) - { - if (grub_claimmap (found_addr , file_size) != -1) - break; - } + { + if (grub_claimmap (found_addr , file_size) != -1) + break; + } file->data = (void *) found_addr; grub_netbuff_clear(pack); grub_netbuff_reserve (pack,80*1024); app_interface->app_prot->open (NULL,stack,pack,(char *) name); + if (grub_errno != GRUB_ERR_NONE) + goto error; do { @@ -401,7 +405,7 @@ grub_ofnet_detect (void) } devalias = grub_ieee1275_get_aliasdevname (bootpath); - if (grub_strcmp(devalias ,"network")) + if (grub_strncmp(devalias ,"net",3)) return 0; grub_net = grub_malloc (sizeof *grub_net ); @@ -455,8 +459,8 @@ grub_ofnet_init(void) grub_get_netinfo (grub_net, bootp_pckt ); grub_disk_dev_register (&grub_ofnet_dev); grub_fs_register (&grub_ofnetfs_fs); + card_open (); } - card_open (); } void grub_ofnet_fini(void) From 17ef14c91669b1c7a8c32f106148c142a488a9c4 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 29 Jul 2010 18:13:00 -0300 Subject: [PATCH 029/406] Process errot packets in TFTP reply. --- net/tftp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/tftp.c b/net/tftp.c index dff0f134c..0fb43105d 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -140,7 +140,7 @@ tftp_receive (struct grub_net_network_layer_interface *inf __attribute((unused)) } //buff_clean - nb->data = nb->tail; + grub_netbuff_clear(nb); // grub_printf("OACK---------------------------------------------------------\n"); //grub_printf("block_size=%d\n",tftp_file.block_size); // grub_printf("file_size=%d\n",tftp_file.size); @@ -155,7 +155,8 @@ tftp_receive (struct grub_net_network_layer_interface *inf __attribute((unused)) grub_netbuff_clear(nb); break; case TFTP_ERROR: - nb->data = nb->tail; + grub_netbuff_clear (nb); + return grub_error (GRUB_ERR_ACCESS_DENIED, (char *)tftph->u.err.errmsg); break; } From 7c978f06900fc81e185bc0c8977f935c0185927c Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 29 Jul 2010 18:17:01 -0300 Subject: [PATCH 030/406] Implement the size field. --- include/grub/net/ethernet.h | 24 ++++++++++++-- net/ethernet.c | 65 ++++++++++++++++++++----------------- 2 files changed, 58 insertions(+), 31 deletions(-) diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h index 46aa04f60..9043a5f02 100644 --- a/include/grub/net/ethernet.h +++ b/include/grub/net/ethernet.h @@ -1,11 +1,31 @@ #ifndef GRUB_NET_ETHERNET_HEADER #define GRUB_NET_ETHERNET_HEADER 1 #include -struct etherhdr { +#define LLCADDRMASK 0x7f + +struct etherhdr +{ grub_uint8_t dst[6]; grub_uint8_t src[6]; grub_uint16_t type; -} __attribute__ ((packed)) ; +} __attribute__ ((packed)); + +#define PCP (x) x & 0xe000 +#define CFI (x) x & 0x1000 +#define VID (x) x & 0x0fff + +struct llchdr +{ +grub_uint8_t dsap; +grub_uint8_t ssap; +grub_uint8_t ctrl; +} __attribute__ ((packed)); + +struct snaphdr +{ +grub_uint8_t oui[3]; +grub_uint16_t type; +} __attribute__ ((packed)); void ethernet_ini(void); void ethernet_fini(void); diff --git a/net/ethernet.c b/net/ethernet.c index 2bcb8107d..ab5992133 100644 --- a/net/ethernet.c +++ b/net/ethernet.c @@ -18,19 +18,13 @@ send_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ grub_netbuff_push (nb,sizeof(*eth)); eth = (struct etherhdr *) nb->data; - eth->dst[0] =0x00; - eth->dst[1] =0x11; - eth->dst[2] =0x25; - eth->dst[3] =0xca; - eth->dst[4] =0x1f; - eth->dst[5] =0x01; - eth->src[0] =0x0a; - eth->src[1] =0x11; - eth->src[2] =0xbd; - eth->src[3] =0xe3; - eth->src[4] =0xe3; - eth->src[5] =0x04; - + eth->dst[0] = 0x00; + eth->dst[1] = 0x11; + eth->dst[2] = 0x25; + eth->dst[3] = 0xca; + eth->dst[4] = 0x1f; + eth->dst[5] = 0x01; + grub_memcpy (eth->src, bootp_pckt -> chaddr,6); eth->type = 0x0800; return send_card_buffer(nb); @@ -44,25 +38,38 @@ recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ { struct etherhdr *eth; grub_uint64_t start_time, current_time; + struct llchdr *llch; + struct snaphdr *snaph; + grub_uint16_t type; start_time = grub_get_time_ms(); - while (1) - { - get_card_packet (nb); - eth = (struct etherhdr *) nb->data; + while (1) + { + get_card_packet (nb); + eth = (struct etherhdr *) nb->data; + type = eth->type; + grub_netbuff_pull(nb,sizeof (*eth)); + // grub_printf("ethernet type 58 %x\n",type); + // grub_printf("ethernet eth->type 58 %x\n",type); + if (eth->type <=1500) + { + llch = (struct llchdr *) nb->data; + type = llch->dsap & LLCADDRMASK; + + if (llch->dsap == 0xaa && llch->ssap == 0xaa && llch->ctrl == 0x3) + { + grub_netbuff_pull (nb,sizeof(*llch)); + snaph = (struct snaphdr *) nb->data; + type = snaph->type; + } + } + /*change for grub_memcmp*/ - if( eth->src[0] == 0x00 && eth->src[1] == 0x11 && eth->src[2] == 0x25 && - eth->src[3] == 0xca && eth->src[4] == 0x1f && eth->src[5] == 0x01 && eth->type == 0x800) - { - //grub_printf("ethernet eth->dst %x:%x:%x:%x:%x:%x\n",eth->dst[0], - // eth->dst[1],eth->dst[2],eth->dst[3],eth->dst[4],eth->dst[5]); - // grub_printf("ethernet eth->src %x:%x:%x:%x:%x:%x\n",eth->src[0],eth->src[1], - // eth->src[2],eth->src[3],eth->src[4],eth->src[5]); - //grub_printf("ethernet eth->type 0x%x\n",eth->type); - //grub_printf("out from ethernet\n"); - grub_netbuff_pull(nb,sizeof(*eth)); + //if( eth->src[0] == 0x00 && eth->src[1] == 0x11 && eth->src[2] == 0x25 && + // eth->src[3] == 0xca && eth->src[4] == 0x1f && eth->src[5] == 0x01 && type == 0x800) + if(type == 0x800) return 0; - } - current_time = grub_get_time_ms(); + + current_time = grub_get_time_ms (); if (current_time - start_time > TIMEOUT_TIME_MS) return grub_error (GRUB_ERR_TIMEOUT, "Time out."); } From 10830203a09d8afdb8f10ab322042bbcdecece16 Mon Sep 17 00:00:00 2001 From: Paulo de Rezende Pinatti Date: Fri, 13 Aug 2010 14:42:16 -0300 Subject: [PATCH 031/406] Added ARP protocol to network stack and fixed bug in grub_netbuff_alloc function. * include/grub/net/arp.h: added arp header, arp cache entry and related constants and functions * net/arp.c: added functions arp_init_table, arp_find_entry, arp_resolve and arp_receive * net/ethernet.c (send_ethernet_packet): replaced hardcoded hardware address by parameter target_addr * net/ethernet.c (recv_ethernet_packet): added call to arp_receive when packet is of type 0x803 (ARP) and only return when packet is of type determined by parameter ethertype * net/ip.c (send_ip_packet): added call to arp_resolve to determine hardware address of destination * net/netbuff.c (grub_netbuff_alloc): fixed swapped parameters in call to grub_memalign --- fs/ieee1275/ofnet.c | 48 +++++--- include/grub/net/arp.h | 49 +++++++-- include/grub/net/interface.h | 2 +- include/grub/net/ip.h | 1 + include/grub/net/protocol.h | 10 +- net/arp.c | 207 +++++++++++++++++++++++++++++++++++ net/ethernet.c | 38 ++++--- net/interface.c | 1 - net/ip.c | 27 ++++- net/netbuff.c | 2 +- net/tftp.c | 4 +- normal/misc.c | 2 +- 12 files changed, 335 insertions(+), 56 deletions(-) diff --git a/fs/ieee1275/ofnet.c b/fs/ieee1275/ofnet.c index 82b5235cc..cf7eeb5b2 100644 --- a/fs/ieee1275/ofnet.c +++ b/fs/ieee1275/ofnet.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -95,7 +96,7 @@ retrieve_field(const char *src, char **field, const char **rest) static grub_err_t parse_ip (const char *val, grub_uint32_t *ip, const char **rest) { - grub_uint32_t newip = 0; + grub_uint8_t *p = (grub_uint8_t *) ip; unsigned long t; int i; const char *ptr = val; @@ -107,8 +108,7 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest) return grub_errno; if (t & ~0xff) return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); - newip >>= 8; - newip |= (t << 24); + p[i] = (grub_uint8_t) t; if (i != 3 && *ptr != '.') return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); ptr++; @@ -116,7 +116,6 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest) ptr = ptr - 1; if ( *ptr != '\0' && *ptr != ',') return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); - *ip = newip; if (rest) *rest = ptr; return 0; @@ -305,12 +304,33 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) char *datap; int amount = 0; grub_addr_t found_addr; + grub_netdisk_data_t netdisk_data = (grub_netdisk_data_t) file->device->disk->data; + // TODO: replace getting IP and MAC from bootp by routing functions + struct grub_net_network_layer_interface net_interface; + struct grub_net_card net_card; + struct grub_net_addr ila, lla; + ila.addr = (grub_uint8_t *) &(bootp_pckt->yiaddr); + ila.len = 4; + lla.addr = (grub_uint8_t *) &(bootp_pckt->chaddr); + lla.len = 6; + net_card.ila = &ila; + net_card.lla = &lla; + net_interface.card = &net_card; + // END TODO + + if(! netdisk_data) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments missing"); + + if(netdisk_data->protocol == GRUB_NETDISK_PROTOCOL_TFTP) + stack = grub_net_protocol_stack_get ("tftp"); + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid protocol specified"); - stack = grub_net_protocol_stack_get ("tftp"); app_interface = (struct grub_net_application_transport_interface *) stack->interface; - pack = grub_netbuff_alloc (80*1024); - grub_netbuff_reserve (pack,80*1024); - file_size = app_interface->app_prot->get_file_size(NULL,stack,pack,(char *) name); + app_interface->inner_layer->data = (void *) &(netdisk_data->server_ip); + pack = grub_netbuff_alloc (2048); + grub_netbuff_reserve (pack,2048); + file_size = app_interface->app_prot->get_file_size(&net_interface,stack,pack,(char *) name); for (found_addr = 0x800000; found_addr < + 2000 * 0x100000; found_addr += 0x100000) { @@ -320,16 +340,16 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) file->data = (void *) found_addr; grub_netbuff_clear(pack); - grub_netbuff_reserve (pack,80*1024); - app_interface->app_prot->open (NULL,stack,pack,(char *) name); + grub_netbuff_reserve (pack,2048); + app_interface->app_prot->open (&net_interface,stack,pack,(char *) name); if (grub_errno != GRUB_ERR_NONE) goto error; do { grub_netbuff_clear(pack); - grub_netbuff_reserve (pack,80*1024); - app_interface->app_prot->recv (NULL,stack,pack); + grub_netbuff_reserve (pack,2048); + app_interface->app_prot->recv (&net_interface,stack,pack); if (grub_errno != GRUB_ERR_NONE) goto error; if ((pack->tail - pack->data)) @@ -340,8 +360,8 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) grub_memcpy(datap , pack->data, pack->tail - pack->data); } grub_netbuff_clear(pack); - grub_netbuff_reserve (pack,80*1024); - app_interface->app_prot->send_ack (NULL,stack,pack); + grub_netbuff_reserve (pack,2048); + app_interface->app_prot->send_ack (&net_interface,stack,pack); if (grub_errno != GRUB_ERR_NONE) goto error; diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h index 86ae2deea..75260aeb3 100644 --- a/include/grub/net/arp.h +++ b/include/grub/net/arp.h @@ -1,17 +1,42 @@ #ifndef GRUB_NET_ARP_HEADER #define GRUB_NET_ARP_HEADER 1 +#include +#include +#include -#include -struct arphdr{ - grub_int16_t hwtype; /* hardware type (must be ARPHRD_ETHER) */ - grub_int16_t protocol; /* protocol type (must be ETH_P_IP) */ - grub_int8_t hwlen; /* hardware address length (must be 6) */ - grub_int8_t protolen; /* protocol address length (must be 4) */ - grub_uint16_t opcode; /* ARP opcode */ - grub_uint8_t shwaddr[6]; /* sender's hardware address */ - grub_uint32_t sipaddr; /* sender's IP address */ - grub_uint8_t thwaddr[6]; /* target's hardware address */ - grub_uint32_t tipaddr; /* target's IP address */ -}__attribute__ ((packed)); +/* IANA ARP constant to define hardware type as ethernet */ +#define ARPHRD_ETHERNET 1 +/* IANA Ethertype */ +#define ARP_ETHERTYPE 0x806 + +/* Size for cache table */ +#define SIZE_ARP_TABLE 5 + +/* ARP header operation codes */ +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +struct arp_entry { + grub_uint8_t avail; + struct grub_net_network_layer_protocol *nl_protocol; + struct grub_net_link_layer_protocol *ll_protocol; + struct grub_net_addr nl_address; + struct grub_net_addr ll_address; +}; + +struct arphdr { + grub_uint16_t hrd; + grub_uint16_t pro; + grub_uint8_t hln; + grub_uint8_t pln; + grub_uint16_t op; +} __attribute__ ((packed)); + +extern grub_err_t arp_receive(struct grub_net_network_layer_interface *inf __attribute__ ((unused)), +struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb); + +extern grub_err_t arp_resolve(struct grub_net_network_layer_interface *inf __attribute__ ((unused)), +struct grub_net_network_link_interface *net_link_inf, struct grub_net_addr *proto_addr, +struct grub_net_addr *hw_addr); #endif diff --git a/include/grub/net/interface.h b/include/grub/net/interface.h index 4d100fd75..cf24dd22e 100644 --- a/include/grub/net/interface.h +++ b/include/grub/net/interface.h @@ -37,7 +37,7 @@ struct grub_net_network_link_interface }; -extern struct grub_net_protocol_stack *grub_net_protocol_stacks; +struct grub_net_protocol_stack *grub_net_protocol_stacks; static inline void grub_net_stack_register (struct grub_net_protocol_stack *stack) { diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index cb119ac6f..5baacd439 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -2,6 +2,7 @@ #define GRUB_NET_IP_HEADER 1 #include +#define IP_ETHERTYPE 0x800 /* IANA Ethertype */ struct iphdr { grub_uint8_t verhdrlen; diff --git a/include/grub/net/protocol.h b/include/grub/net/protocol.h index b7a3e5d3b..ffc3dd719 100644 --- a/include/grub/net/protocol.h +++ b/include/grub/net/protocol.h @@ -8,7 +8,7 @@ struct grub_net_protocol; struct grub_net_protocol_stack; struct grub_net_network_layer_interface; - +struct grub_net_addr; typedef enum grub_network_layer_protocol_id { @@ -57,6 +57,7 @@ struct grub_net_network_layer_protocol struct grub_net_network_layer_protocol *next; char *name; grub_net_protocol_id_t id; + grub_uint16_t type; /* IANA Ethertype */ //grub_network_layer_protocol_id_t id; grub_err_t (*ntoa) (char *name, grub_net_network_layer_address_t *addr); char * (*aton) (union grub_net_network_layer_address addr); @@ -76,11 +77,14 @@ struct grub_net_link_layer_protocol struct grub_net_link_layer_protocol *next; char *name; + grub_uint16_t type; /* ARP hardware type */ grub_net_protocol_id_t id; grub_err_t (*send) (struct grub_net_network_layer_interface *inf , - struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb); + struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb, + struct grub_net_addr target_addr, grub_uint16_t ethertype); grub_err_t (*recv) (struct grub_net_network_layer_interface *inf , - struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb); + struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb, + grub_uint16_t ethertype); }; extern struct grub_net_network_layer_protocol *grub_net_network_layer_protocols; diff --git a/net/arp.c b/net/arp.c index e69de29bb..c02ea011d 100644 --- a/net/arp.c +++ b/net/arp.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct arp_entry arp_table[SIZE_ARP_TABLE]; +static grub_int8_t new_table_entry = -1; + +static void arp_init_table(void) +{ + struct arp_entry *entry = &(arp_table[0]); + for(;entry<=&(arp_table[SIZE_ARP_TABLE-1]);entry++) + { + entry->avail = 0; + entry->nl_protocol = NULL; + entry->ll_protocol = NULL; + entry->nl_address.addr = NULL; + entry->nl_address.len = 0; + entry->ll_address.addr = NULL; + entry->ll_address.len = 0; + } + new_table_entry = 0; +} + +static struct arp_entry * +arp_find_entry(struct grub_net_network_link_interface *net_link_inf, const void *proto_address, grub_uint8_t address_len) +{ + grub_uint8_t i; + for(i=0;i < SIZE_ARP_TABLE; i++) + { + if(arp_table[i].avail == 1 && + arp_table[i].nl_protocol->type == net_link_inf->net_prot->type && + arp_table[i].ll_protocol->type == net_link_inf->link_prot->type && + (!grub_memcmp(arp_table[i].nl_address.addr, proto_address, address_len))) + return &(arp_table[i]); + } + return NULL; +} + +grub_err_t arp_resolve(struct grub_net_network_layer_interface *inf __attribute__ ((unused)), +struct grub_net_network_link_interface *net_link_inf, struct grub_net_addr *proto_addr, +struct grub_net_addr *hw_addr) +{ + struct arp_entry *entry; + struct grub_net_buff *nb; + struct arphdr *arp_header; + struct grub_net_addr target_hw_addr; + grub_uint8_t *aux, i; + + /* Check cache table */ + entry = arp_find_entry(net_link_inf, proto_addr->addr, proto_addr->len); + if (entry) + { + hw_addr->addr = grub_malloc(entry->ll_address.len); + if (! hw_addr->addr) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + grub_memcpy(hw_addr->addr, entry->ll_address.addr, entry->ll_address.len); + hw_addr->len = entry->ll_address.len; + return GRUB_ERR_NONE; + } + /* Build a request packet */ + nb = grub_netbuff_alloc (2048); + grub_netbuff_reserve(nb, 2048); + grub_netbuff_push(nb, sizeof(*arp_header) + 2*(inf->card->lla->len + inf->card->ila->len)); + arp_header = (struct arphdr *)nb->data; + arp_header->hrd = net_link_inf->link_prot->type; + arp_header->pro = net_link_inf->net_prot->type; + arp_header->hln = inf->card->lla->len; + arp_header->pln = inf->card->ila->len; + arp_header->op = ARP_REQUEST; + aux = (grub_uint8_t *)arp_header + sizeof(*arp_header); + /* Sender hardware address */ + grub_memcpy(aux, inf->card->lla->addr, inf->card->lla->len); + aux += inf->card->lla->len; + /* Sender protocol address */ + grub_memcpy(aux, inf->card->ila->addr, inf->card->ila->len); + aux += inf->card->ila->len; + /* Target hardware address */ + for(i=0; i < inf->card->lla->len; i++) + aux[i] = 0x00; + aux += inf->card->lla->len; + /* Target protocol address */ + grub_memcpy(aux, proto_addr->addr, inf->card->ila->len); + + target_hw_addr.addr = grub_malloc(inf->card->lla->len); + target_hw_addr.len = inf->card->lla->len; + for(i=0; i < target_hw_addr.len; i++) + (target_hw_addr.addr)[i] = 0xFF; + net_link_inf->link_prot->send(inf, net_link_inf, nb, target_hw_addr, ARP_ETHERTYPE); + grub_free(target_hw_addr.addr); + grub_netbuff_clear(nb); + grub_netbuff_reserve(nb, 2048); + + grub_uint64_t start_time, current_time; + start_time = grub_get_time_ms(); + do + { + net_link_inf->link_prot->recv(inf, net_link_inf, nb, ARP_ETHERTYPE); + /* Now check cache table again */ + entry = arp_find_entry(net_link_inf, proto_addr->addr, proto_addr->len); + if (entry) + { + hw_addr->addr = grub_malloc(entry->ll_address.len); + if (! hw_addr->addr) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + grub_memcpy(hw_addr->addr, entry->ll_address.addr, entry->ll_address.len); + hw_addr->len = entry->ll_address.len; + grub_netbuff_clear(nb); + return GRUB_ERR_NONE; + } + current_time = grub_get_time_ms(); + if (current_time - start_time > TIMEOUT_TIME_MS) + break; + } while (! entry); + grub_netbuff_clear(nb); + return grub_error (GRUB_ERR_TIMEOUT, "Timeout: could not resolve hardware address."); +} + +grub_err_t arp_receive(struct grub_net_network_layer_interface *inf __attribute__ ((unused)), +struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb) +{ + struct arphdr *arp_header = (struct arphdr *)nb->data; + struct arp_entry *entry; + grub_uint8_t merge = 0; + + /* Verify hardware type, protocol type, hardware address length, protocol address length */ + if (arp_header->hrd != net_link_inf->link_prot->type || arp_header->pro != net_link_inf->net_prot->type || + arp_header->hln != inf->card->lla->len || arp_header->pln != inf->card->ila->len) + return GRUB_ERR_NONE; + + grub_uint8_t *sender_hardware_address, *sender_protocol_address, *target_hardware_address, *target_protocol_address; + sender_hardware_address = (grub_uint8_t *)arp_header + sizeof(*arp_header); + sender_protocol_address = sender_hardware_address + arp_header->hln; + target_hardware_address = sender_protocol_address + arp_header->pln; + target_protocol_address = target_hardware_address + arp_header->hln; + /* Check if the sender is in the cache table */ + entry = arp_find_entry(net_link_inf, sender_protocol_address, arp_header->pln); + /* Update sender hardware address */ + if (entry) + { + if (entry->ll_address.addr) + grub_free(entry->ll_address.addr); + entry->ll_address.addr = grub_malloc(arp_header->hln); + if (! entry->ll_address.addr) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + grub_memcpy(entry->ll_address.addr, sender_hardware_address, arp_header->hln); + entry->ll_address.len = arp_header->hln; + merge = 1; + } + /* Am I the protocol address target? */ + if (! grub_memcmp(target_protocol_address, inf->card->ila->addr, arp_header->pln)) + { + /* Add sender to cache table */ + if (! merge) + { + if (new_table_entry == -1) + arp_init_table(); + entry = &(arp_table[new_table_entry]); + entry->avail = 1; + entry->ll_protocol = net_link_inf->link_prot; + entry->nl_protocol = net_link_inf->net_prot; + if (entry->nl_address.addr) + grub_free(entry->nl_address.addr); + entry->nl_address.addr = grub_malloc(arp_header->pln); + if (! entry->nl_address.addr) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + grub_memcpy(entry->nl_address.addr, sender_protocol_address, arp_header->pln); + entry->nl_address.len = arp_header->pln; + if (entry->ll_address.addr) + grub_free(entry->ll_address.addr); + entry->ll_address.addr = grub_malloc(arp_header->hln); + if (! entry->ll_address.addr) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + grub_memcpy(entry->ll_address.addr, sender_hardware_address, arp_header->hln); + entry->ll_address.len = arp_header->hln; + new_table_entry++; + if (new_table_entry == SIZE_ARP_TABLE) + new_table_entry = 0; + } + if (arp_header->op == ARP_REQUEST) + { + struct grub_net_addr aux; + /* Swap hardware fields */ + grub_memcpy(target_hardware_address, sender_hardware_address, arp_header->hln); + grub_memcpy(sender_hardware_address, inf->card->lla->addr, arp_header->hln); + /* Swap protocol fields */ + aux.addr = grub_malloc(arp_header->pln); + if (! aux.addr) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + grub_memcpy(aux.addr, sender_protocol_address, arp_header->pln); + grub_memcpy(sender_protocol_address, target_protocol_address, arp_header->pln); + grub_memcpy(target_protocol_address, aux.addr, arp_header->pln); + grub_free(aux.addr); + /* Change operation to REPLY and send packet */ + arp_header->op = ARP_REPLY; + aux.addr = target_hardware_address; + aux.len = arp_header->hln; + net_link_inf->link_prot->send(inf, net_link_inf, nb, aux, ARP_ETHERTYPE); + } + } + return GRUB_ERR_NONE; +} diff --git a/net/ethernet.c b/net/ethernet.c index ab5992133..14bc41c5b 100644 --- a/net/ethernet.c +++ b/net/ethernet.c @@ -8,24 +8,21 @@ #include #include #include +#include static grub_err_t send_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ ((unused)), - struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb) +struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb, +struct grub_net_addr target_addr, grub_uint16_t ethertype) { struct etherhdr *eth; grub_netbuff_push (nb,sizeof(*eth)); eth = (struct etherhdr *) nb->data; - eth->dst[0] = 0x00; - eth->dst[1] = 0x11; - eth->dst[2] = 0x25; - eth->dst[3] = 0xca; - eth->dst[4] = 0x1f; - eth->dst[5] = 0x01; - grub_memcpy (eth->src, bootp_pckt -> chaddr,6); - eth->type = 0x0800; + grub_memcpy(eth->dst, target_addr.addr, target_addr.len); + grub_memcpy(eth->src, bootp_pckt->chaddr, 6); + eth->type = ethertype; return send_card_buffer(nb); // return inf->card->driver->send(inf->card,nb); @@ -34,7 +31,8 @@ send_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ static grub_err_t recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ ((unused)), - struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb) +struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb, +grub_uint16_t ethertype) { struct etherhdr *eth; grub_uint64_t start_time, current_time; @@ -63,12 +61,17 @@ recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ } } - /*change for grub_memcmp*/ - //if( eth->src[0] == 0x00 && eth->src[1] == 0x11 && eth->src[2] == 0x25 && - // eth->src[3] == 0xca && eth->src[4] == 0x1f && eth->src[5] == 0x01 && type == 0x800) - if(type == 0x800) - return 0; - + /* ARP packet */ + if (type == ARP_ETHERTYPE) + { + arp_receive(inf, net_link_inf, nb); + if (ethertype == ARP_ETHERTYPE) + return GRUB_ERR_NONE; + } + /* IP packet */ + else if(type == IP_ETHERTYPE && ethertype == IP_ETHERTYPE) + return GRUB_ERR_NONE; + current_time = grub_get_time_ms (); if (current_time - start_time > TIMEOUT_TIME_MS) return grub_error (GRUB_ERR_TIMEOUT, "Time out."); @@ -77,7 +80,7 @@ recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ - verify if the next layer is the desired one. - if not. get another packet. - remove ethernet header from buffer*/ - return 0; + return GRUB_ERR_NONE; } @@ -85,6 +88,7 @@ static struct grub_net_link_layer_protocol grub_ethernet_protocol = { .name = "ethernet", .id = GRUB_NET_ETHERNET_ID, + .type = ARPHRD_ETHERNET, .send = send_ethernet_packet, .recv = recv_ethernet_packet }; diff --git a/net/interface.c b/net/interface.c index bacabf4cb..f17b3e66b 100644 --- a/net/interface.c +++ b/net/interface.c @@ -22,7 +22,6 @@ INTERFACE_REGISTER_FUNCTIONS("link");*/ #include #include -struct grub_net_protocol_stack *grub_net_protocol_stacks; struct grub_net_protocol_stack *grub_net_protocol_stack_get (char *name) { diff --git a/net/ip.c b/net/ip.c index 65b0f2b70..142f33e70 100644 --- a/net/ip.c +++ b/net/ip.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,8 @@ send_ip_packet (struct grub_net_network_layer_interface *inf, struct iphdr *iph; static int id = 0x2400; + struct grub_net_addr nl_target_addr, ll_target_addr; + grub_err_t rc; grub_netbuff_push(nb,sizeof(*iph)); iph = (struct iphdr *) nb->data; @@ -51,12 +54,26 @@ send_ip_packet (struct grub_net_network_layer_interface *inf, iph->ttl = 0xff; iph->protocol = 0x11; iph->src = (grub_uint32_t) bootp_pckt -> yiaddr; //inf->address.ipv4; // *((grub_uint32_t *)inf->card->ila->addr); - iph->dest = (grub_uint32_t) bootp_pckt -> siaddr;//inf->address.ipv4;// *((grub_uint32_t *)inf->ila->addr); + // iph->dest = (grub_uint32_t) bootp_pckt -> siaddr;//inf->address.ipv4;// *((grub_uint32_t *)inf->ila->addr); + iph->dest = *((grub_uint32_t *) (trans_net_inf->data)); iph->chksum = 0 ; iph->chksum = ipchksum((void *)nb->data, sizeof(*iph)); - return trans_net_inf->inner_layer->link_prot->send(inf,trans_net_inf->inner_layer,nb); + /* Determine link layer target address via ARP */ + nl_target_addr.len = sizeof(iph->dest); + nl_target_addr.addr = grub_malloc(nl_target_addr.len); + if (! nl_target_addr.addr) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + grub_memcpy(nl_target_addr.addr, &(iph->dest), nl_target_addr.len); + rc = arp_resolve(inf, trans_net_inf->inner_layer, &nl_target_addr, &ll_target_addr); + grub_free(nl_target_addr.addr); + if (rc != GRUB_ERR_NONE) + return rc; + + rc = trans_net_inf->inner_layer->link_prot->send(inf,trans_net_inf->inner_layer,nb,ll_target_addr, IP_ETHERTYPE); + grub_free(ll_target_addr.addr); + return rc; //return protstack->next->prot->send(inf,protstack->next,nb); } @@ -70,11 +87,12 @@ recv_ip_packet (struct grub_net_network_layer_interface *inf, start_time = grub_get_time_ms(); while (1) { - trans_net_inf->inner_layer->link_prot->recv(inf,trans_net_inf->inner_layer,nb); + trans_net_inf->inner_layer->link_prot->recv(inf,trans_net_inf->inner_layer,nb,IP_ETHERTYPE); iph = (struct iphdr *) nb->data; if (iph->protocol == 0x11 && iph->dest == (grub_uint32_t) bootp_pckt -> yiaddr && - iph->src == (grub_uint32_t) bootp_pckt -> siaddr ) + //iph->src == (grub_uint32_t) bootp_pckt -> siaddr ) + iph->src == *((grub_uint32_t *) (trans_net_inf->data)) ) { grub_netbuff_pull(nb,sizeof(*iph)); return 0; @@ -99,6 +117,7 @@ static struct grub_net_network_layer_protocol grub_ipv4_protocol = { .name = "ipv4", .id = GRUB_NET_IPV4_ID, + .type = IP_ETHERTYPE, .send = send_ip_packet, .recv = recv_ip_packet }; diff --git a/net/netbuff.c b/net/netbuff.c index ce52233b6..4f6a1da84 100644 --- a/net/netbuff.c +++ b/net/netbuff.c @@ -72,7 +72,7 @@ struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len ) len = NETBUFFMINLEN; len = ALIGN_UP (len,NETBUFF_ALIGN); - data = grub_memalign (len + sizeof (*nb),NETBUFF_ALIGN); + data = grub_memalign (NETBUFF_ALIGN, len + sizeof (*nb)); nb = (struct grub_net_buff *) ((int)data + len); nb->head = nb->data = nb->tail = data; nb->end = (char *) nb; diff --git a/net/tftp.c b/net/tftp.c index 0fb43105d..2aeae38e9 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -113,7 +113,7 @@ tftp_open (struct grub_net_network_layer_interface *inf __attribute((unused)), app_interface->trans_prot->send (inf,protstack->interface,nb); /*Receive OACK*/ grub_netbuff_clear (nb); - grub_netbuff_reserve (nb,80*1024); + grub_netbuff_reserve (nb,2048); return app_interface->app_prot->recv(inf,protstack,nb); } @@ -215,7 +215,7 @@ static int tftp_file_size (struct grub_net_network_layer_interface* inf , tftp_open (inf, protocol_stack,nb, filename); grub_netbuff_clear (nb); - grub_netbuff_reserve (nb,80*1024); + grub_netbuff_reserve (nb,2048); tftp_send_err (inf, protocol_stack,nb,"Abort transference.",0); return tftp_file.size; diff --git a/normal/misc.c b/normal/misc.c index d53fe711c..30967e174 100644 --- a/normal/misc.c +++ b/normal/misc.c @@ -54,7 +54,7 @@ grub_normal_print_device_info (const char *name) grub_printf_(N_("Protocol: %s"), "Unknown"); grub_putchar ('\n'); grub_putchar ('\t'); - grub_printf_(N_("Server IP: %d.%d.%d.%d"), data->server_ip & 0xff, data->server_ip >> 8 & 0xff, data->server_ip >> 16 & 0xff, data->server_ip >> 24 & 0xff); + grub_printf_(N_("Server IP: %d.%d.%d.%d"), data->server_ip >> 24 & 0xff, data->server_ip >> 16 & 0xff, data->server_ip >> 8 & 0xff, data->server_ip & 0xff); if (data->username) { grub_putchar ('\n'); From f15f9c5029692d3ff5c4731cde9bc11e1214f7ac Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 1 Sep 2010 02:41:21 +0200 Subject: [PATCH 032/406] Remove leftover modules --- grub-core/Makefile.core.def | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 76437f5a5..925f2b7f6 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1425,15 +1425,3 @@ module = { common = commands/efi/memmap.c; enable = ia64_efi; }; - -module = { - name = systab; - common = commands/efi/systab.c; - enable = ia64_efi; -}; - -module = { - name = acpi2; - common = commands/efi/acpi2.c; - enable = ia64_efi; -}; From b764f436e78a5899c4b6912cc68768fcf68aeef3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 1 Sep 2010 03:03:15 +0200 Subject: [PATCH 033/406] Add ia64 setjmp implementation to the list --- grub-core/lib/setjmp.S | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/grub-core/lib/setjmp.S b/grub-core/lib/setjmp.S index c39c91b9c..b04fd7439 100644 --- a/grub-core/lib/setjmp.S +++ b/grub-core/lib/setjmp.S @@ -8,6 +8,8 @@ #include "./mips/setjmp.S" #elif defined(__powerpc__) #include "./powerpc/setjmp.S" +#elif defined(__ia64__) +#include "./ia64/setjmp.S" #else -#error "Unknwon target cpu type" +#error "Unknown target cpu type" #endif From afef75b254473c065af83beb605857ca8b8a21dd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 1 Sep 2010 03:05:36 +0200 Subject: [PATCH 034/406] Use finish boot services and switch to new command line interface in linux loader --- grub-core/loader/ia64/efi/linux.c | 95 ++++++++++++++++--------------- 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/grub-core/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c index 9020efd28..12c769a16 100644 --- a/grub-core/loader/ia64/efi/linux.c +++ b/grub-core/loader/ia64/efi/linux.c @@ -327,6 +327,7 @@ grub_linux_boot (void) grub_efi_uintn_t desc_size; grub_efi_uint32_t desc_version; grub_efi_memory_descriptor_t *mmap_buf; + grub_err_t err; /* FPSWA. */ query_fpswa (); @@ -349,18 +350,16 @@ grub_linux_boot (void) 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"); + err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, &map_key, + &desc_size, &desc_version); + if (err) + return err; 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)); @@ -494,8 +493,9 @@ grub_load_elf64 (grub_file_t file, void *buffer) return 0; } -void -grub_rescue_cmd_linux (int argc, char *argv[]) +static grub_err_t +grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) { grub_file_t file = 0; char buffer[GRUB_ELF_SEARCH]; @@ -574,10 +574,12 @@ grub_rescue_cmd_linux (int argc, char *argv[]) boot_param_pages); grub_dl_unref (my_mod); } + return grub_errno; } -void -grub_rescue_cmd_initrd (int argc, char *argv[]) +static grub_err_t +grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) { grub_file_t file = 0; @@ -617,10 +619,12 @@ grub_rescue_cmd_initrd (int argc, char *argv[]) fail: if (file) grub_file_close (file); + return grub_errno; } -void -grub_rescue_cmd_payload (int argc, char *argv[]) +static grub_err_t +grub_cmd_payload (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) { grub_file_t file = 0; grub_ssize_t size, len = 0; @@ -708,10 +712,12 @@ grub_rescue_cmd_payload (int argc, char *argv[]) grub_free (base); grub_free (cmdline); } + return grub_errno; } -void -grub_rescue_cmd_relocate (int argc, char *argv[]) +static grub_err_t +grub_cmd_relocate (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) { static const char * const vals[] = { "off", "on", "force"}; unsigned int i; @@ -719,6 +725,7 @@ grub_rescue_cmd_relocate (int argc, char *argv[]) if (argc == 0) { grub_printf ("relocate is %s\n", vals[relocate]); + return GRUB_ERR_NONE; } else if (argc == 1) { @@ -728,67 +735,63 @@ grub_rescue_cmd_relocate (int argc, char *argv[]) if (grub_strcmp (argv[0], vals[i]) == 0) { relocate = i; - return; + return GRUB_ERR_NONE; } - grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown relocate value"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown relocate value"); } else { - grub_error (GRUB_ERR_BAD_ARGUMENT, "accept 0 or 1 argument"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "accept 0 or 1 argument"); } + } -void -grub_rescue_cmd_fpswa (int argc, char *argv[] __attribute__((unused))) +static grub_err_t +grub_cmd_fpswa (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[] __attribute__((unused))) { if (argc != 0) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "Arguments not expected"); - return; + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Arguments not expected"); } query_fpswa (); if (fpswa == NULL) grub_printf ("No FPSWA loaded\n"); else grub_printf ("FPSWA revision: %x\n", fpswa->revision); + return GRUB_ERR_NONE; } +static grub_command_t cmd_linux, cmd_initrd, cmd_payload, cmd_relocate, cmd_fpswa; + GRUB_MOD_INIT(linux) { - grub_register_extcmd ("linux", grub_normal_linux_command, - GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, - "linux FILE [ARGS...]", - "Load Linux.", 0); + cmd_linux = grub_register_command ("linux", grub_cmd_linux, + "FILE [ARGS...]", "Load Linux."); - grub_register_extcmd ("initrd", grub_normal_initrd_command, - GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, - "initrd FILE", - "Load initrd.", 0); + cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, + "FILE", "Load initrd."); - grub_register_extcmd ("payload", grub_normal_cmd_payload, - GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, - "payload FILE [ARGS...]", - "Load an additional file.", 0); + cmd_payload = grub_register_command ("payload", grub_cmd_payload, + "FILE [ARGS...]", + "Load an additional file."); - grub_register_extcmd ("relocate", grub_normal_cmd_relocate, - GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, - "relocate [on|off|force]", - "Set relocate feature.", 0); + cmd_relocate = grub_register_command ("relocate", grub_cmd_relocate, + "[on|off|force]", + "Set relocate feature."); - grub_register_extcmd ("fpswa", grub_normal_cmd_fpswa, - GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_NO_ARG_PARSE, - "fpswa", - "Display FPSWA version.", 0); + cmd_fpswa = grub_register_command ("fpswa", grub_cmd_fpswa, + "", "Display FPSWA version."); my_mod = mod; } GRUB_MOD_FINI(linux) { - grub_unregister_command ("linux"); - grub_unregister_command ("initrd"); - grub_unregister_command ("payload"); - grub_unregister_command ("relocate"); - grub_unregister_command ("fpswa"); + grub_unregister_command (cmd_linux); + grub_unregister_command (cmd_initrd); + grub_unregister_command (cmd_payload); + grub_unregister_command (cmd_relocate); + grub_unregister_command (cmd_fpswa); } From c84a9b54ad9e957adb8414620af52a2a414419d0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 1 Sep 2010 09:43:36 +0200 Subject: [PATCH 035/406] remove allocate_boot_pages and free_boot_pages. They are pointless now --- grub-core/loader/ia64/efi/linux.c | 32 +++++++++++++++---------------- include/grub/efi/efi.h | 7 ------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/grub-core/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c index 12c769a16..61b261599 100644 --- a/grub-core/loader/ia64/efi/linux.c +++ b/grub-core/loader/ia64/efi/linux.c @@ -193,13 +193,13 @@ free_pages (void) { if (kernel_mem) { - grub_efi_free_boot_pages ((grub_addr_t) kernel_mem, kernel_pages); + grub_efi_free_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); + grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages); initrd_mem = 0; } @@ -214,16 +214,16 @@ free_pages (void) { next_payload = (struct ia64_boot_payload *)payload->next; - grub_efi_free_boot_pages + grub_efi_free_pages (payload->start, page_align (payload->length) >> 12); - grub_efi_free_boot_pages ((grub_efi_physical_address_t)payload, 1); + grub_efi_free_pages ((grub_efi_physical_address_t)payload, 1); payload = next_payload; } /* Free bootparam. */ - grub_efi_free_boot_pages ((grub_efi_physical_address_t)boot_param, - boot_param_pages); + grub_efi_free_pages ((grub_efi_physical_address_t)boot_param, + boot_param_pages); boot_param = 0; } } @@ -347,7 +347,7 @@ grub_linux_boot (void) 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); + mmap_buf = grub_efi_allocate_pages (0, page_align (mmap_size) >> 12); if (! mmap_buf) grub_fatal ("cannot allocate memory map"); err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, &map_key, @@ -437,7 +437,7 @@ grub_load_elf64 (grub_file_t file, void *buffer) if (relocate != RELOCATE_FORCE) { - kernel_mem = grub_efi_allocate_boot_pages (low_addr, kernel_pages); + kernel_mem = grub_efi_allocate_pages (low_addr, kernel_pages); reloc_offset = 0; } /* Try to relocate. */ @@ -537,7 +537,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), 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); + boot_param = grub_efi_allocate_pages (0, boot_param_pages); if (boot_param == 0) { grub_error (GRUB_ERR_OUT_OF_MEMORY, @@ -557,8 +557,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), } cmdline[10] = '='; - boot_param->command_line = (grub_uint64_t)cmdline; - boot_param->efi_systab = (grub_uint64_t)grub_efi_system_table; + boot_param->command_line = (grub_uint64_t) cmdline; + boot_param->efi_systab = (grub_uint64_t) grub_efi_system_table; grub_errno = GRUB_ERR_NONE; @@ -570,8 +570,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (grub_errno != GRUB_ERR_NONE) { - grub_efi_free_boot_pages ((grub_efi_physical_address_t)boot_param, - boot_param_pages); + grub_efi_free_pages ((grub_efi_physical_address_t) boot_param, + boot_param_pages); grub_dl_unref (my_mod); } return grub_errno; @@ -603,7 +603,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), initrd_size = grub_file_size (file); initrd_pages = (page_align (initrd_size) >> 12); - initrd_mem = grub_efi_allocate_boot_pages (0, initrd_pages); + initrd_mem = grub_efi_allocate_pages (0, initrd_pages); if (! initrd_mem) grub_fatal ("cannot allocate pages"); @@ -650,7 +650,7 @@ grub_cmd_payload (grub_command_t cmd __attribute__ ((unused)), goto fail; size = grub_file_size (file); - base = grub_efi_allocate_boot_pages (0, page_align (size) >> 12); + base = grub_efi_allocate_pages (0, page_align (size) >> 12); if (! base) goto fail; @@ -672,7 +672,7 @@ grub_cmd_payload (grub_command_t cmd __attribute__ ((unused)), grub_error (GRUB_ERR_OUT_OF_RANGE, "payload command line too long"); goto fail; } - payload = grub_efi_allocate_boot_pages (0, 1); + payload = grub_efi_allocate_pages (0, 1); if (! payload) goto fail; diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h index ea354e5ce..e9c57dd11 100644 --- a/include/grub/efi/efi.h +++ b/include/grub/efi/efi.h @@ -42,13 +42,6 @@ EXPORT_FUNC(grub_efi_allocate_pages) (grub_efi_physical_address_t address, grub_efi_uintn_t pages); void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address, grub_efi_uintn_t pages); -void * -EXPORT_FUNC(grub_efi_allocate_boot_pages) (grub_efi_physical_address_t address, - grub_efi_uintn_t pages); -void -EXPORT_FUNC(grub_efi_free_boot_pages) (grub_efi_physical_address_t address, - grub_efi_uintn_t pages); - int EXPORT_FUNC(grub_efi_get_memory_map) (grub_efi_uintn_t *memory_map_size, grub_efi_memory_descriptor_t *memory_map, From 07329a9ac9a2ea530d4e904541d1587e0b2c5cf1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 1 Sep 2010 09:44:32 +0200 Subject: [PATCH 036/406] Fix some compilation problems --- Makefile.util.def | 1 + grub-core/commands/efi/memmap.c | 27 +++++++++++++++------------ grub-core/kern/dl.c | 10 +++++++++- include/grub/dl.h | 8 ++++---- include/grub/ia64/efi/memory.h | 1 + include/grub/ia64/efi/misc.h | 4 ++++ 6 files changed, 34 insertions(+), 17 deletions(-) create mode 100644 include/grub/ia64/efi/memory.h diff --git a/Makefile.util.def b/Makefile.util.def index 28e66a067..24adba282 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -365,6 +365,7 @@ script = { i386_efi = util/i386/efi/grub-install.in; x86_64_efi = util/i386/efi/grub-install.in; + ia64_efi = util/grub-install.in; i386_ieee1275 = util/ieee1275/grub-install.in; powerpc_ieee1275 = util/ieee1275/grub-install.in; diff --git a/grub-core/commands/efi/memmap.c b/grub-core/commands/efi/memmap.c index d49e02080..e7c140cff 100644 --- a/grub-core/commands/efi/memmap.c +++ b/grub-core/commands/efi/memmap.c @@ -22,12 +22,15 @@ #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_cmd_memmap (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) { grub_efi_uintn_t map_size; grub_efi_memory_descriptor_t *memory_map; @@ -80,22 +83,22 @@ grub_cmd_memmap (struct grub_arg_list *state, int argc, char **args) 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); + (unsigned long long) desc->physical_start, + (unsigned long long) desc->physical_start + (desc->num_pages << 12) - 1, + (unsigned long) desc->num_pages); size = desc->num_pages << (12 - 10); if (size < 1024) - grub_printf (" %4uKB", size); + grub_printf (" %4uKB", (unsigned) size); else { size /= 1024; if (size < 1024) - grub_printf (" %4uMB", size); + grub_printf (" %4uMB", (unsigned) size); else { size /= 1024; - grub_printf (" %4uGB", size); + grub_printf (" %4uGB", (unsigned) size); } } @@ -129,15 +132,15 @@ grub_cmd_memmap (struct grub_arg_list *state, int argc, char **args) return 0; } +static grub_command_t cmd; + GRUB_MOD_INIT(memmap) { - (void)mod; /* To stop warning. */ - grub_register_extcmd ("memmap", grub_cmd_memmap, GRUB_COMMAND_FLAG_BOTH, - "memmap", - "Display memory map.", NULL); + cmd = grub_register_command ("memmap", grub_cmd_memmap, + "", "Display memory map."); } GRUB_MOD_FINI(memmap) { - grub_unregister_extcmd ("memmap"); + grub_unregister_command (cmd); } diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index fe3fd0014..4d7929073 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -37,6 +37,10 @@ #define GRUB_MODULES_MACHINE_READONLY #endif +#ifdef __ia64__ +#include +#endif + grub_dl_t grub_dl_head = 0; @@ -545,6 +549,7 @@ grub_dl_load_core (void *addr, grub_size_t size) return mod; } +#ifdef __ia64__ void grub_init_module (const char *name, void (*init)(grub_dl_t), void (*fini)(void)) @@ -555,7 +560,7 @@ grub_init_module (const char *name, if (! mod) return; - mod->name = name; + mod->name = (char *) name; mod->ref_count = 1; mod->dep = 0; mod->segment = 0; @@ -567,6 +572,7 @@ grub_init_module (const char *name, /* Can't fail. */ grub_dl_add (mod); } +#endif /* Load a module from the file FILENAME. */ grub_dl_t @@ -686,6 +692,7 @@ grub_dl_unload (grub_dl_t mod) return 1; } +#ifdef __ia64__ /* Unload unneeded modules. */ void grub_dl_unload_unneeded (void) @@ -705,3 +712,4 @@ grub_dl_unload_unneeded (void) p = p->next; } } +#endif diff --git a/include/grub/dl.h b/include/grub/dl.h index 04577a003..8195e948c 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -34,9 +34,9 @@ #ifndef GRUB_MOD_INIT #define GRUB_MOD_INIT(name) \ static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \ -void grub_module_##name##_init (grub_dl_t); \ +void grub_##name##_init (grub_dl_t); \ void \ -grub_module_##name##_init (grub_dl_t mod) { grub_mod_init (mod); } \ +grub_##name##_init (grub_dl_t mod) { grub_mod_init (mod); } \ static void \ grub_mod_init (grub_dl_t mod __attribute__ ((unused))) #endif @@ -44,9 +44,9 @@ grub_mod_init (grub_dl_t mod __attribute__ ((unused))) #ifndef GRUB_MOD_FINI #define GRUB_MOD_FINI(name) \ static void grub_mod_fini (void) __attribute__ ((used)); \ -void grub_module_##name##_fini (void); \ +void grub_##name##_fini (void); \ void \ -grub_module_##name##_fini (void) { grub_mod_fini (); } \ +grub_##name##_fini (void) { grub_mod_fini (); } \ static void \ grub_mod_fini (void) #endif diff --git a/include/grub/ia64/efi/memory.h b/include/grub/ia64/efi/memory.h new file mode 100644 index 000000000..c9a61bb77 --- /dev/null +++ b/include/grub/ia64/efi/memory.h @@ -0,0 +1 @@ +#include diff --git a/include/grub/ia64/efi/misc.h b/include/grub/ia64/efi/misc.h index 2b99dda62..4f9c69e32 100644 --- a/include/grub/ia64/efi/misc.h +++ b/include/grub/ia64/efi/misc.h @@ -19,5 +19,9 @@ void EXPORT_FUNC (__ia64_trampoline) (void); void EXPORT_FUNC (grub_init_modules) (void); +void +grub_init_module (const char *name, + void (*init)(grub_dl_t), void (*fini)(void)); + extern unsigned long EXPORT_VAR (__gp); From 4bec80482ea423c27c6de7a008d15ba44f8fbbfd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 1 Sep 2010 10:21:05 +0200 Subject: [PATCH 037/406] Remove few bad hunks --- grub-core/kern/dl.c | 2 -- grub-core/loader/ia64/efi/linux.c | 1 - include/grub/ia64/efi/loader.h | 30 ------------------------------ 3 files changed, 33 deletions(-) delete mode 100644 include/grub/ia64/efi/loader.h diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 4d7929073..4d112811f 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -692,7 +692,6 @@ grub_dl_unload (grub_dl_t mod) return 1; } -#ifdef __ia64__ /* Unload unneeded modules. */ void grub_dl_unload_unneeded (void) @@ -712,4 +711,3 @@ grub_dl_unload_unneeded (void) p = p->next; } } -#endif diff --git a/grub-core/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c index 61b261599..d9b4c338b 100644 --- a/grub-core/loader/ia64/efi/linux.c +++ b/grub-core/loader/ia64/efi/linux.c @@ -17,7 +17,6 @@ */ #include -#include #include #include #include diff --git a/include/grub/ia64/efi/loader.h b/include/grub/ia64/efi/loader.h deleted file mode 100644 index 5471a81b5..000000000 --- a/include/grub/ia64/efi/loader.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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_payload (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 */ From 9a9852df79f459b52d51214ed51863b1828d42b1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 2 Sep 2010 00:07:55 +0200 Subject: [PATCH 038/406] Hook network protocols --- grub-core/Makefile.am | 1 + grub-core/commands/net.c | 33 +++++++++++++++++++++++++++++++++ grub-core/kern/device.c | 23 ++++++++++++++++------- grub-core/kern/fs.c | 2 +- include/grub/device.h | 7 +------ include/grub/net.h | 37 +++++++++++++++++++++++++++++++++++-- 6 files changed, 87 insertions(+), 16 deletions(-) diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 5d13d0313..1fcc3d00d 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -74,6 +74,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h if COND_i386_pc KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h diff --git a/grub-core/commands/net.c b/grub-core/commands/net.c index 288ba4c2a..904c61a92 100644 --- a/grub-core/commands/net.c +++ b/grub-core/commands/net.c @@ -269,6 +269,37 @@ grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } +grub_net_app_level_t grub_net_app_level_list; + +static grub_net_t +grub_net_open_real (const char *name) +{ + const char *comma = grub_strchr (name, ','); + grub_net_app_level_t proto; + + if (!comma) + comma = name + grub_strlen (name); + FOR_NET_APP_LEVEL (proto) + { + if (comma - name == (grub_ssize_t) grub_strlen (proto->name) + && grub_memcmp (proto->name, name, comma - name) == 0) + { + grub_net_t ret = grub_malloc (sizeof (*ret)); + if (!ret) + return NULL; + ret->protocol = proto; + ret->name = grub_strdup (name); + if (!ret->name) + { + grub_free (ret); + return NULL; + } + return ret; + } + } + return NULL; +} + static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; GRUB_MOD_INIT(net) @@ -285,6 +316,7 @@ GRUB_MOD_INIT(net) cmd_delroute = grub_register_command ("net_del_route", grub_cmd_delroute, "SHORTNAME", N_("Delete a network route.")); + grub_net_open = grub_net_open_real; } GRUB_MOD_FINI(net) @@ -293,4 +325,5 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_deladdr); grub_unregister_command (cmd_addroute); grub_unregister_command (cmd_delroute); + grub_net_open = NULL; } diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c index 4273fedfe..9de545910 100644 --- a/grub-core/kern/device.c +++ b/grub-core/kern/device.c @@ -26,6 +26,8 @@ #include #include +grub_net_t (*grub_net_open) (const char *name) = NULL; + grub_device_t grub_device_open (const char *name) { @@ -46,15 +48,16 @@ grub_device_open (const char *name) if (! dev) goto fail; + dev->net = NULL; /* Try to open a disk. */ - disk = grub_disk_open (name); - if (! disk) - goto fail; + dev->disk = grub_disk_open (name); + if (dev->disk) + return dev; + if (grub_net_open) + dev->net = grub_net_open (name); - dev->disk = disk; - dev->net = 0; /* FIXME */ - - return dev; + if (dev->net) + return dev; fail: if (disk) @@ -71,6 +74,12 @@ grub_device_close (grub_device_t device) if (device->disk) grub_disk_close (device->disk); + if (device->net) + { + grub_free (device->net->name); + grub_free (device->net); + } + grub_free (device); return grub_errno; diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c index 8ffb93c8b..c4d6efa96 100644 --- a/grub-core/kern/fs.c +++ b/grub-core/kern/fs.c @@ -95,7 +95,7 @@ grub_fs_probe (grub_device_t device) } } else if (device->net) - return device->net->fs; + return device->net->protocol; grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem"); return 0; diff --git a/include/grub/device.h b/include/grub/device.h index d68c26e66..f3e43bf60 100644 --- a/include/grub/device.h +++ b/include/grub/device.h @@ -24,12 +24,7 @@ #include struct grub_disk; -struct grub_fs; -struct grub_net -{ - char *name; - struct grub_fs *fs; -}; +struct grub_net; struct grub_device { diff --git a/include/grub/net.h b/include/grub/net.h index 4ca873f74..b5e852f9b 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -22,6 +22,17 @@ #include #include #include +#include + +typedef struct grub_fs *grub_net_app_level_t; + +typedef struct grub_net +{ + char *name; + grub_net_app_level_t protocol; +} *grub_net_t; + +extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); struct grub_net_card; @@ -46,7 +57,7 @@ struct grub_net_network_level_interface; typedef union grub_net_network_level_address { grub_uint32_t ipv4; -} grub_net_network_level_netaddress_t; +} grub_net_network_level_address_t; typedef union grub_net_network_level_netaddress { @@ -54,7 +65,7 @@ typedef union grub_net_network_level_netaddress grub_uint32_t base; int masksize; } ipv4; -} grub_net_network_level_address_t; +} grub_net_network_level_netaddress_t; typedef enum grub_network_level_protocol_id { @@ -163,6 +174,28 @@ grub_net_network_level_interface_unregister (struct grub_net_network_level_inter #define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) +extern grub_net_app_level_t grub_net_app_level_list; + +#ifndef GRUB_LST_GENERATOR +static inline void +grub_net_app_level_register (grub_net_app_level_t proto) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_app_level_list), + GRUB_AS_LIST (proto)); +} +#endif + +static inline void +grub_net_app_level_unregister (grub_net_app_level_t proto) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_app_level_list), + GRUB_AS_LIST (proto)); +} + +#define FOR_NET_APP_LEVEL(var) FOR_LIST_ELEMENTS((var), \ + (grub_net_app_level_list)) + + extern struct grub_net_route *grub_net_routes; static inline void From 03b170647d564e2211bb9f3745b18d67eb0c4158 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 2 Sep 2010 17:18:02 +0200 Subject: [PATCH 039/406] Restructure pxe --- Makefile.util.def | 1 + grub-core/commands/ls.c | 13 ++ grub-core/commands/net.c | 361 +++++++++++++++++++++++++++---------- grub-core/fs/i386/pc/pxe.c | 268 +++++++++++++-------------- include/grub/net.h | 131 +++----------- 5 files changed, 433 insertions(+), 341 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index 35bcd81b2..fe6894306 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -30,6 +30,7 @@ library = { common = grub-core/commands/blocklist.c; common = grub-core/commands/extcmd.c; common = grub-core/commands/ls.c; + common = grub-core/commands/net.c; common = grub-core/disk/dmraid_nvidia.c; common = grub-core/disk/host.c; common = grub-core/disk/loopback.c; diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index 9ee0a7a31..3179d271e 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -31,6 +31,7 @@ #include #include #include +#include static const struct grub_arg_option options[] = { @@ -45,6 +46,8 @@ static const char grub_human_sizes[] = {' ', 'K', 'M', 'G', 'T'}; static grub_err_t grub_ls_list_devices (int longlist) { + grub_net_app_level_t proto; + auto int grub_ls_print_devices (const char *name); int grub_ls_print_devices (const char *name) { @@ -58,6 +61,16 @@ grub_ls_list_devices (int longlist) grub_device_iterate (grub_ls_print_devices); grub_xputs ("\n"); + + grub_puts_ (N_ ("Network protocols:\n")); + + FOR_NET_APP_LEVEL (proto) + { + grub_printf ("%s ", proto->name); + } + + grub_xputs ("\n"); + grub_refresh (); return 0; diff --git a/grub-core/commands/net.c b/grub-core/commands/net.c index 904c61a92..2062e1bd0 100644 --- a/grub-core/commands/net.c +++ b/grub-core/commands/net.c @@ -22,30 +22,135 @@ #include #include +struct grub_net_route +{ + struct grub_net_route *next; + grub_net_network_level_netaddress_t target; + char *name; + struct grub_net_network_level_protocol *prot; + int is_gateway; + union + { + struct grub_net_network_level_interface *interface; + grub_net_network_level_address_t gw; + }; +}; + struct grub_net_route *grub_net_routes = NULL; struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL; struct grub_net_card *grub_net_cards = NULL; struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; -grub_err_t -grub_net_resolve_address (struct grub_net_network_level_protocol **prot, - char *name, - grub_net_network_level_address_t *addr) +static inline void +grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) { - FOR_NET_NETWORK_LEVEL_PROTOCOLS (*prot) + grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + GRUB_AS_LIST (inter)); +} + +static inline void +grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + GRUB_AS_LIST (inter)); +} + +#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) + +static inline void +grub_net_route_register (struct grub_net_route *route) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_routes), + GRUB_AS_LIST (route)); +} + +static inline void +grub_net_route_unregister (struct grub_net_route *route) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_routes), + GRUB_AS_LIST (route)); +} + +#define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next) + +static int +parse_ip (const char *val, grub_uint32_t *ip, const char **rest) +{ + grub_uint32_t newip = 0; + unsigned long t; + int i; + const char *ptr = val; + + for (i = 0; i < 4; i++) { - grub_err_t err; - err = grub_net_resolve_address_in_protocol (*prot, name, addr); - if (err == GRUB_ERR_NET_BAD_ADDRESS) + t = grub_strtoul (ptr, (char **) &ptr, 0); + if (grub_errno) { grub_errno = GRUB_ERR_NONE; - continue; + return 0; } - if (err) - return err; + if (t & ~0xff) + return 0; + newip >>= 8; + newip |= (t << 24); + if (i != 3 && *ptr != '.') + return 0; + ptr++; + } + *ip = newip; + if (rest) + *rest = ptr - 1; + return 0; +} + +static int +match_net (const grub_net_network_level_netaddress_t *net, + const grub_net_network_level_address_t *addr) +{ + if (net->type != addr->type) + return 0; + switch (net->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + { + grub_int32_t mask = (1 << net->ipv4.masksize) - 1; + return ((net->ipv4.base & mask) == (addr->ipv4 & mask)); + } + } + return 0; +} + +grub_err_t +grub_net_resolve_address (const char *name, + grub_net_network_level_address_t *addr) +{ + if (parse_ip (name, &addr->ipv4, NULL)) + { + addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; return GRUB_ERR_NONE; } - return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("Unrecognised address %s"), + return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("unrecognised address %s"), + name); +} + +grub_err_t +grub_net_resolve_net_address (const char *name, + grub_net_network_level_netaddress_t *addr) +{ + const char *rest; + if (parse_ip (name, &addr->ipv4.base, &rest)) + { + addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + if (*rest == '/') + { + addr->ipv4.masksize = grub_strtoul (rest + 1, NULL, 0); + if (!grub_errno) + return GRUB_ERR_NONE; + } + addr->ipv4.masksize = 32; + return GRUB_ERR_NONE; + } + return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("unrecognised address %s"), name); } @@ -71,8 +176,7 @@ grub_net_route_address (grub_net_network_level_address_t addr, { if (depth && prot != route->prot) continue; - prot = route->prot; - if (!route->prot->match_net (route->target, curtarget)) + if (!match_net (&route->target, &curtarget)) continue; if (route->is_gateway) @@ -107,7 +211,6 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), if (inter == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found")); - inter->protocol->fini (inter); grub_net_network_level_interface_unregister (inter); grub_free (inter->name); grub_free (inter); @@ -115,18 +218,35 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } +struct grub_net_network_level_interface * +grub_net_add_addr (const char *name, struct grub_net_card *card, + grub_net_network_level_address_t addr) +{ + struct grub_net_network_level_interface *inter; + + inter = grub_zalloc (sizeof (*inter)); + if (!inter) + return NULL; + + inter->name = grub_strdup (name); + grub_memcpy (&(inter->address), &addr, sizeof (inter->address)); + inter->card = card; + + grub_net_network_level_interface_register (inter); + + return inter; +} + static grub_err_t grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), int argc, char **args) { struct grub_net_card *card; - struct grub_net_network_level_protocol *prot; - grub_err_t err; grub_net_network_level_address_t addr; - struct grub_net_network_level_interface *inter; + grub_err_t err; - if (argc != 4) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("four arguments expected")); + if (argc != 3) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected")); FOR_NET_CARDS (card) if (grub_strcmp (card->name, args[1])) @@ -134,36 +254,12 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), if (card == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found")); - FOR_NET_NETWORK_LEVEL_PROTOCOLS (prot) - if (grub_strcmp (prot->name, args[2])) - break; - - if (card == NULL) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("protocol not found")); - - err = grub_net_resolve_address_in_protocol (prot, args[3], &addr); + err = grub_net_resolve_address (args[2], &addr); if (err) return err; - inter = grub_zalloc (sizeof (*inter)); - if (!inter) - return grub_errno; - - inter->name = grub_strdup (args[0]); - inter->protocol = prot; - grub_memcpy (&(inter->address), &addr, sizeof (inter->address)); - inter->card = card; - - err = prot->init (inter); - if (err) - { - grub_free (inter->name); - grub_free (inter); - return err; - } - grub_net_network_level_interface_register (inter); - - return GRUB_ERR_NONE; + grub_net_add_addr (args[0], card, addr); + return grub_errno; } static grub_err_t @@ -188,84 +284,157 @@ grub_cmd_delroute (struct grub_command *cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } -static grub_err_t -grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), - int argc, char **args) +grub_err_t +grub_net_add_route (const char *name, + grub_net_network_level_netaddress_t target, + struct grub_net_network_level_interface *inter) { - struct grub_net_network_level_protocol *prot; struct grub_net_route *route; - if (argc < 3) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - N_("At least 3 arguments are expected")); - route = grub_zalloc (sizeof (*route)); if (!route) return grub_errno; - route->name = grub_strdup (args[0]); + route->name = grub_strdup (name); if (!route->name) { grub_free (route); return grub_errno; } - FOR_NET_NETWORK_LEVEL_PROTOCOLS(prot) - { - grub_err_t err; - err = prot->net_ntoa (args[1], &(route->target)); - if (err == GRUB_ERR_NET_BAD_ADDRESS) - { - grub_errno = GRUB_ERR_NONE; - continue; - } - if (err) - return err; - break; - } - - if (!prot) + route->target = target; + route->is_gateway = 0; + route->interface = inter; + + grub_net_route_register (route); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_net_add_route_gw (const char *name, + grub_net_network_level_netaddress_t target, + grub_net_network_level_address_t gw) +{ + struct grub_net_route *route; + + route = grub_zalloc (sizeof (*route)); + if (!route) + return grub_errno; + + route->name = grub_strdup (name); + if (!route->name) { - grub_free (route->name); grub_free (route); - return grub_error (GRUB_ERR_NET_BAD_ADDRESS, - N_("Unrecognised address %s"), args[1]); + return grub_errno; } + route->target = target; + route->is_gateway = 1; + route->gw = gw; + + grub_net_route_register (route); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_net_network_level_netaddress_t target; + if (argc < 3) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("At least 3 arguments are expected")); + + grub_net_resolve_net_address (args[1], &target); + if (grub_strcmp (args[2], "gw") == 0 && argc >= 4) { grub_err_t err; - route->is_gateway = 1; - err = grub_net_resolve_address_in_protocol (prot, - args[3], &(route->gw)); + grub_net_network_level_address_t gw; + + err = grub_net_resolve_address (args[3], &gw); if (err) - { - grub_free (route->name); - grub_free (route); - return err; - } + return err; + return grub_net_add_route_gw (args[0], target, gw); } else { struct grub_net_network_level_interface *inter; - route->is_gateway = 0; FOR_NET_NETWORK_LEVEL_INTERFACES (inter) if (grub_strcmp (inter->name, args[2])) break; if (!inter) - { - grub_free (route->name); - grub_free (route); - return grub_error (GRUB_ERR_BAD_ARGUMENT, - N_("Unrecognised interface %s"), args[2]); - } - route->interface = inter; + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unrecognised interface %s"), args[2]); + return grub_net_add_route (args[0], target, inter); } +} - grub_net_route_register (route); +static void +print_net_address (const grub_net_network_level_netaddress_t *target) +{ + switch (target->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + grub_printf ("%d.%d.%d.%d/%d ", ((target->ipv4.base >> 24) & 0xff), + ((target->ipv4.base >> 16) & 0xff), + ((target->ipv4.base >> 8) & 0xff), + ((target->ipv4.base >> 0) & 0xff), + target->ipv4.masksize); + break; + } +} +static void +print_address (const grub_net_network_level_address_t *target) +{ + switch (target->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + grub_printf ("%d.%d.%d.%d ", ((target->ipv4 >> 24) & 0xff), + ((target->ipv4 >> 16) & 0xff), + ((target->ipv4 >> 8) & 0xff), + ((target->ipv4 >> 0) & 0xff)); + break; + } +} + +static grub_err_t +grub_cmd_listroutes (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + struct grub_net_route *route; + FOR_NET_ROUTES(route) + { + grub_printf ("%s ", route->name); + print_net_address (&route->target); + if (route->is_gateway) + { + grub_printf ("gw "); + print_address (&route->gw); + } + else + grub_printf ("%s", route->interface->name); + } + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + struct grub_net_card *card; + FOR_NET_CARDS(card) + { + grub_printf ("%s ", card->name); + } + grub_printf ("\n"); return GRUB_ERR_NONE; } @@ -301,11 +470,12 @@ grub_net_open_real (const char *name) } static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; +static grub_command_t cmd_lsroutes, cmd_lscards; GRUB_MOD_INIT(net) { cmd_addaddr = grub_register_command ("net_add_addr", grub_cmd_addaddr, - "SHORTNAME CARD PROTOCOL ADDRESS", + "SHORTNAME CARD ADDRESS", N_("Add a network address.")); cmd_deladdr = grub_register_command ("net_del_addr", grub_cmd_deladdr, "SHORTNAME", @@ -316,6 +486,11 @@ GRUB_MOD_INIT(net) cmd_delroute = grub_register_command ("net_del_route", grub_cmd_delroute, "SHORTNAME", N_("Delete a network route.")); + cmd_lsroutes = grub_register_command ("net_ls_routes", grub_cmd_listroutes, + "", N_("list network routes")); + cmd_lscards = grub_register_command ("net_ls_cards", grub_cmd_listcards, + "", N_("list network cards")); + grub_net_open = grub_net_open_real; } @@ -325,5 +500,7 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_deladdr); grub_unregister_command (cmd_addroute); grub_unregister_command (cmd_delroute); + grub_unregister_command (cmd_lsroutes); + grub_unregister_command (cmd_lscards); grub_net_open = NULL; } diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index 0dd44a30a..20d0e1979 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -18,9 +18,8 @@ */ #include -#include +#include #include -#include #include #include #include @@ -33,13 +32,7 @@ #define SEGMENT(x) ((x) >> 4) #define OFFSET(x) ((x) & 0xF) #define SEGOFS(x) ((SEGMENT(x) << 16) + OFFSET(x)) -#define LINEAR(x) (void *) (((x >> 16) <<4) + (x & 0xFFFF)) - -struct grub_pxe_disk_data -{ - grub_uint32_t server_ip; - grub_uint32_t gateway_ip; -}; +#define LINEAR(x) (void *) (((x >> 16) << 4) + (x & 0xFFFF)) struct grub_pxenv *grub_pxe_pxenv; static grub_uint32_t grub_pxe_your_ip; @@ -53,6 +46,8 @@ struct grub_pxe_data { grub_uint32_t packet_number; grub_uint32_t block_size; + grub_uint32_t server_ip; + grub_uint32_t gateway_ip; char filename[0]; }; @@ -95,55 +90,33 @@ grub_pxe_scan (void) return ret; } -static int -grub_pxe_iterate (int (*hook) (const char *name)) +static grub_err_t +grub_pxefs_dir (grub_device_t device __attribute__ ((unused)), + const char *path __attribute__ ((unused)), + int (*hook) (const char *filename, + const struct grub_dirhook_info *info) + __attribute__ ((unused))) { - if (hook ("pxe")) - return 1; - return 0; + return GRUB_ERR_NONE; } static grub_err_t -parse_ip (const char *val, grub_uint32_t *ip, const char **rest) +grub_pxefs_open (struct grub_file *file, const char *name) { - grub_uint32_t newip = 0; - unsigned long t; - int i; - const char *ptr = val; - - for (i = 0; i < 4; i++) + union { - t = grub_strtoul (ptr, (char **) &ptr, 0); - if (grub_errno) - return grub_errno; - if (t & ~0xff) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); - newip >>= 8; - newip |= (t << 24); - if (i != 3 && *ptr != '.') - return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); - ptr++; - } - *ip = newip; - if (rest) - *rest = ptr - 1; - return 0; -} - -static grub_err_t -grub_pxe_open (const char *name, grub_disk_t disk) -{ - struct grub_pxe_disk_data *data; - - if (grub_strcmp (name, "pxe") != 0 - && grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) != 0) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a pxe disk"); + struct grub_pxenv_tftp_get_fsize c1; + struct grub_pxenv_tftp_open c2; + } c; + struct grub_pxe_data *data; + grub_file_t file_int, bufio; data = grub_malloc (sizeof (*data)); if (!data) return grub_errno; - if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0) +#if 0 + if (grub_strncmp (file->device->net->name, "pxe:", sizeof ("pxe:") - 1) == 0) { const char *ptr; grub_err_t err; @@ -161,93 +134,44 @@ grub_pxe_open (const char *name, grub_disk_t disk) else data->gateway_ip = grub_pxe_default_gateway_ip; } - else + else +#endif { - data->server_ip = grub_pxe_default_server_ip; - data->gateway_ip = grub_pxe_default_gateway_ip; + grub_net_network_level_address_t addr; + grub_net_network_level_address_t gateway; + struct grub_net_network_level_interface *interf; + grub_err_t err; + + if (grub_strncmp (file->device->net->name, + "pxe,", sizeof ("pxe,") - 1) == 0) + { + const char *ptr; + + ptr = name + sizeof ("pxe,") - 1; + err = grub_net_resolve_address (name + sizeof ("pxe,") - 1, &addr); + if (err) + return err; + } + else + { + addr.ipv4 = grub_pxe_default_server_ip; + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + } + err = grub_net_route_address (addr, &gateway, &interf); + if (err) + return err; + data->server_ip = addr.ipv4; + data->gateway_ip = gateway.ipv4; } - disk->total_sectors = 0; - disk->id = (unsigned long) data; - - disk->has_partitions = 0; - disk->data = data; - - return GRUB_ERR_NONE; -} - -static void -grub_pxe_close (grub_disk_t disk) -{ - grub_free (disk->data); -} - -static grub_err_t -grub_pxe_read (grub_disk_t disk __attribute((unused)), - grub_disk_addr_t sector __attribute((unused)), - grub_size_t size __attribute((unused)), - char *buf __attribute((unused))) -{ - return GRUB_ERR_OUT_OF_RANGE; -} - -static grub_err_t -grub_pxe_write (grub_disk_t disk __attribute((unused)), - grub_disk_addr_t sector __attribute((unused)), - grub_size_t size __attribute((unused)), - const char *buf __attribute((unused))) -{ - return GRUB_ERR_OUT_OF_RANGE; -} - -static struct grub_disk_dev grub_pxe_dev = - { - .name = "pxe", - .id = GRUB_DISK_DEVICE_PXE_ID, - .iterate = grub_pxe_iterate, - .open = grub_pxe_open, - .close = grub_pxe_close, - .read = grub_pxe_read, - .write = grub_pxe_write, - .next = 0 - }; - -static grub_err_t -grub_pxefs_dir (grub_device_t device, - const char *path __attribute__ ((unused)), - int (*hook) (const char *filename, - const struct grub_dirhook_info *info) - __attribute__ ((unused))) -{ - if (device->disk->dev->id != GRUB_DISK_DEVICE_PXE_ID) - return grub_error (GRUB_ERR_IO, "not a pxe disk"); - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_pxefs_open (struct grub_file *file, const char *name) -{ - union - { - struct grub_pxenv_tftp_get_fsize c1; - struct grub_pxenv_tftp_open c2; - } c; - struct grub_pxe_data *data; - struct grub_pxe_disk_data *disk_data = file->device->disk->data; - grub_file_t file_int, bufio; - - if (file->device->disk->dev->id != GRUB_DISK_DEVICE_PXE_ID) - return grub_error (GRUB_ERR_IO, "not a pxe disk"); - if (curr_file != 0) { grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c.c2, pxe_rm_entry); curr_file = 0; } - c.c1.server_ip = disk_data->server_ip; - c.c1.gateway_ip = disk_data->gateway_ip; + c.c1.server_ip = data->server_ip; + c.c1.gateway_ip = data->gateway_ip; grub_strcpy ((char *)&c.c1.filename[0], name); grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1, pxe_rm_entry); if (c.c1.status) @@ -297,7 +221,6 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_pxenv_tftp_read c; struct grub_pxe_data *data; - struct grub_pxe_disk_data *disk_data = file->device->disk->data; grub_uint32_t pn, r; data = file->data; @@ -317,8 +240,8 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len) if (curr_file != 0) grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o, pxe_rm_entry); - o.server_ip = disk_data->server_ip; - o.gateway_ip = disk_data->gateway_ip; + o.server_ip = data->server_ip; + o.gateway_ip = data->gateway_ip; grub_strcpy ((char *)&o.filename[0], data->filename); o.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT); o.packet_size = grub_pxe_blksize; @@ -513,18 +436,46 @@ grub_pxe_detect (void) grub_pxe_pxenv = pxenv; } +static grub_size_t +grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused)), + void *buf __attribute__ ((unused)), + grub_size_t buflen __attribute__ ((unused))) +{ + return 0; +} + +static grub_err_t +grub_pxe_send (struct grub_net_card *dev __attribute__ ((unused)), + void *buf __attribute__ ((unused)), + grub_size_t buflen __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "not implemented"); +} + +struct grub_net_card_driver grub_pxe_card_driver = +{ + .send = grub_pxe_send, + .recv = grub_pxe_recv +}; + +struct grub_net_card grub_pxe_card = +{ + .driver = &grub_pxe_card_driver, + .name = "pxe" +}; + void grub_pxe_unload (void) { if (grub_pxe_pxenv) { - grub_fs_unregister (&grub_pxefs_fs); - grub_disk_dev_unregister (&grub_pxe_dev); - + grub_net_app_level_unregister (&grub_pxefs_fs); + grub_net_card_unregister (&grub_pxe_card); grub_pxe_pxenv = 0; } } +#if 0 static void set_ip_env (char *varname, grub_uint32_t ip) { @@ -556,7 +507,9 @@ write_ip_env (grub_uint32_t *ip, const char *val) return buf; } +#endif +#if 0 static char * grub_env_write_pxe_default_server (struct grub_env_var *var __attribute__ ((unused)), @@ -572,6 +525,7 @@ grub_env_write_pxe_default_gateway (struct grub_env_var *var { return write_ip_env (&grub_pxe_default_gateway_ip, val); } +#endif static char * grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__ ((unused)), @@ -598,34 +552,58 @@ grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__ ((unused)), return buf; } - GRUB_MOD_INIT(pxe) { grub_pxe_detect (); if (grub_pxe_pxenv) { char *buf; + grub_net_network_level_address_t addr; + struct grub_net_network_level_interface *inter; + +#if 0 + grub_register_variable_hook ("pxe_default_server", 0, + grub_env_write_pxe_default_server); + grub_register_variable_hook ("pxe_default_gateway", 0, + grub_env_write_pxe_default_gateway); +#endif + grub_register_variable_hook ("pxe_blksize", 0, + grub_env_write_pxe_blocksize); buf = grub_xasprintf ("%d", grub_pxe_blksize); if (buf) grub_env_set ("pxe_blksize", buf); grub_free (buf); +#if 0 set_ip_env ("pxe_default_server", grub_pxe_default_server_ip); - set_ip_env ("pxe_default_gateway", grub_pxe_default_gateway_ip); - set_ip_env ("net_pxe_ip", grub_pxe_your_ip); - grub_register_variable_hook ("pxe_default_server", 0, - grub_env_write_pxe_default_server); - grub_register_variable_hook ("pxe_default_gateway", 0, - grub_env_write_pxe_default_gateway); +#endif - /* XXX: Is it possible to change IP in PXE? */ - grub_register_variable_hook ("net_pxe_ip", 0, - grub_env_write_readonly); - grub_register_variable_hook ("pxe_blksize", 0, - grub_env_write_pxe_blocksize); - grub_disk_dev_register (&grub_pxe_dev); - grub_fs_register (&grub_pxefs_fs); + grub_net_app_level_register (&grub_pxefs_fs); + grub_net_card_register (&grub_pxe_card); + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + addr.ipv4 = grub_pxe_your_ip; + inter = grub_net_add_addr ("pxe", &grub_pxe_card, addr); + if (grub_pxe_default_gateway_ip) + { + grub_net_network_level_netaddress_t target; + grub_net_network_level_address_t gw; + + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = grub_pxe_default_server_ip; + target.ipv4.masksize = 32; + gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + gw.ipv4 = grub_pxe_default_gateway_ip; + grub_net_add_route_gw ("pxe_default", target, gw); + } + { + grub_net_network_level_netaddress_t target; + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = grub_pxe_default_gateway_ip ? + : grub_pxe_default_server_ip; + target.ipv4.masksize = 32; + grub_net_add_route ("pxe_default", target, inter); + } } } diff --git a/include/grub/net.h b/include/grub/net.h index b5e852f9b..84e881efe 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -54,71 +54,37 @@ struct grub_net_card struct grub_net_network_level_interface; +typedef enum grub_network_level_protocol_id +{ + GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 +} grub_network_level_protocol_id_t; + typedef union grub_net_network_level_address { + grub_network_level_protocol_id_t type; grub_uint32_t ipv4; } grub_net_network_level_address_t; typedef union grub_net_network_level_netaddress { + grub_network_level_protocol_id_t type; struct { grub_uint32_t base; int masksize; } ipv4; } grub_net_network_level_netaddress_t; -typedef enum grub_network_level_protocol_id -{ - GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 -} grub_network_level_protocol_id_t; - struct grub_net_network_level_interface; -struct grub_net_network_level_protocol -{ - struct grub_net_network_level_protocol *next; - char *name; - grub_network_level_protocol_id_t id; - grub_err_t (*ntoa) (char *name, grub_net_network_level_address_t *addr); - char * (*aton) (union grub_net_network_level_address addr); - grub_err_t (*net_ntoa) (char *name, - grub_net_network_level_netaddress_t *addr); - char * (*net_aton) (grub_net_network_level_netaddress_t addr); - int (* match_net) (grub_net_network_level_netaddress_t net, - grub_net_network_level_address_t addr); - grub_err_t (*init) (struct grub_net_network_level_interface *dev); - grub_err_t (*fini) (struct grub_net_network_level_interface *dev); - grub_err_t (*send) (struct grub_net_network_level_interface *dev, void *buf, - grub_size_t buflen); - grub_size_t (*recv) (struct grub_net_network_level_interface *dev, void *buf, - grub_size_t buflen); -}; - struct grub_net_network_level_interface { struct grub_net_network_level_interface *next; char *name; - /* Underlying protocol. */ - struct grub_net_network_level_protocol *protocol; struct grub_net_card *card; union grub_net_network_level_address address; void *data; }; -struct grub_net_route -{ - struct grub_net_route *next; - grub_net_network_level_netaddress_t target; - char *name; - struct grub_net_network_level_protocol *prot; - int is_gateway; - union - { - struct grub_net_network_level_interface *interface; - grub_net_network_level_address_t gw; - }; -}; - struct grub_net_session; struct grub_net_session_level_protocol @@ -156,24 +122,12 @@ grub_net_session_recv (struct grub_net_session *session, void *buf, return session->protocol->recv (session, buf, size); } +struct grub_net_network_level_interface * +grub_net_add_addr (const char *name, struct grub_net_card *card, + grub_net_network_level_address_t addr); + extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; -static inline void -grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) -{ - grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), - GRUB_AS_LIST (inter)); -} - -static inline void -grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), - GRUB_AS_LIST (inter)); -} - -#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) - extern grub_net_app_level_t grub_net_app_level_list; #ifndef GRUB_LST_GENERATOR @@ -195,25 +149,6 @@ grub_net_app_level_unregister (grub_net_app_level_t proto) #define FOR_NET_APP_LEVEL(var) FOR_LIST_ELEMENTS((var), \ (grub_net_app_level_list)) - -extern struct grub_net_route *grub_net_routes; - -static inline void -grub_net_route_register (struct grub_net_route *route) -{ - grub_list_push (GRUB_AS_LIST_P (&grub_net_routes), - GRUB_AS_LIST (route)); -} - -static inline void -grub_net_route_unregister (struct grub_net_route *route) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_routes), - GRUB_AS_LIST (route)); -} - -#define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next) - extern struct grub_net_card *grub_net_cards; static inline void @@ -232,44 +167,32 @@ grub_net_card_unregister (struct grub_net_card *card) #define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) -extern struct grub_net_network_level_protocol *grub_net_network_level_protocols; - -static inline void -grub_net_network_level_protocol_register (struct grub_net_network_level_protocol *prot) -{ - grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_protocols), - GRUB_AS_LIST (prot)); -} - -static inline void -grub_net_network_level_protocol_unregister (struct grub_net_network_level_protocol *prot) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_protocols), - GRUB_AS_LIST (prot)); -} - -#define FOR_NET_NETWORK_LEVEL_PROTOCOLS(var) for ((var) = grub_net_network_level_protocols; (var); (var) = (var)->next) - -static inline grub_err_t -grub_net_resolve_address_in_protocol (struct grub_net_network_level_protocol *prot, - char *name, - grub_net_network_level_address_t *addr) -{ - return prot->ntoa (name, addr); -} - struct grub_net_session * grub_net_open_tcp (char *address, grub_uint16_t port); grub_err_t -grub_net_resolve_address (struct grub_net_network_level_protocol **prot, - char *name, +grub_net_resolve_address (const char *name, grub_net_network_level_address_t *addr); +grub_err_t +grub_net_resolve_net_address (const char *name, + grub_net_network_level_netaddress_t *addr); + grub_err_t grub_net_route_address (grub_net_network_level_address_t addr, grub_net_network_level_address_t *gateway, struct grub_net_network_level_interface **interf); +grub_err_t +grub_net_add_route (const char *name, + grub_net_network_level_netaddress_t target, + struct grub_net_network_level_interface *inter); + +grub_err_t +grub_net_add_route_gw (const char *name, + grub_net_network_level_netaddress_t target, + grub_net_network_level_address_t gw); + + #endif /* ! GRUB_NET_HEADER */ From e571f2332e90dec534f0b8beb1a943b699c1271b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 2 Sep 2010 18:15:59 +0200 Subject: [PATCH 040/406] Fix regressions by previous commits --- grub-core/commands/ls.c | 6 ++++-- grub-core/commands/net.c | 38 +++++++++++++++++++++++++------------- grub-core/fs/i386/pc/pxe.c | 8 ++++---- grub-core/kern/device.c | 7 +++++-- include/grub/net.h | 22 ++++++++++++++-------- 5 files changed, 52 insertions(+), 29 deletions(-) diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index 3179d271e..300c21cc9 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -47,6 +47,7 @@ static grub_err_t grub_ls_list_devices (int longlist) { grub_net_app_level_t proto; + int first = 1; auto int grub_ls_print_devices (const char *name); int grub_ls_print_devices (const char *name) @@ -62,10 +63,11 @@ grub_ls_list_devices (int longlist) grub_device_iterate (grub_ls_print_devices); grub_xputs ("\n"); - grub_puts_ (N_ ("Network protocols:\n")); - FOR_NET_APP_LEVEL (proto) { + if (first) + grub_puts_ (N_ ("Network protocols:")); + first = 0; grub_printf ("%s ", proto->name); } diff --git a/grub-core/commands/net.c b/grub-core/commands/net.c index 2062e1bd0..9d28c2ff7 100644 --- a/grub-core/commands/net.c +++ b/grub-core/commands/net.c @@ -97,7 +97,7 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest) return 0; ptr++; } - *ip = newip; + *ip = grub_cpu_to_le32 (newip); if (rest) *rest = ptr - 1; return 0; @@ -114,7 +114,8 @@ match_net (const grub_net_network_level_netaddress_t *net, case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { grub_int32_t mask = (1 << net->ipv4.masksize) - 1; - return ((net->ipv4.base & mask) == (addr->ipv4 & mask)); + return ((grub_be_to_cpu32 (net->ipv4.base) & mask) + == (grub_be_to_cpu32 (addr->ipv4) & mask)); } } return 0; @@ -380,13 +381,17 @@ print_net_address (const grub_net_network_level_netaddress_t *target) switch (target->type) { case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: - grub_printf ("%d.%d.%d.%d/%d ", ((target->ipv4.base >> 24) & 0xff), - ((target->ipv4.base >> 16) & 0xff), - ((target->ipv4.base >> 8) & 0xff), - ((target->ipv4.base >> 0) & 0xff), - target->ipv4.masksize); - break; + { + grub_uint32_t n = grub_be_to_cpu32 (target->ipv4.base); + grub_printf ("%d.%d.%d.%d/%d ", ((n >> 24) & 0xff), + ((n >> 16) & 0xff), + ((n >> 8) & 0xff), + ((n >> 0) & 0xff), + target->ipv4.masksize); + } + return; } + grub_printf ("Unknown address type %d\n", target->type); } static void @@ -395,12 +400,16 @@ print_address (const grub_net_network_level_address_t *target) switch (target->type) { case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: - grub_printf ("%d.%d.%d.%d ", ((target->ipv4 >> 24) & 0xff), - ((target->ipv4 >> 16) & 0xff), - ((target->ipv4 >> 8) & 0xff), - ((target->ipv4 >> 0) & 0xff)); - break; + { + grub_uint32_t n = grub_be_to_cpu32 (target->ipv4); + grub_printf ("%d.%d.%d.%d ", ((n >> 24) & 0xff), + ((n >> 16) & 0xff), + ((n >> 8) & 0xff), + ((n >> 0) & 0xff)); + } + return; } + grub_printf ("Unknown address type %d\n", target->type); } static grub_err_t @@ -420,6 +429,7 @@ grub_cmd_listroutes (struct grub_command *cmd __attribute__ ((unused)), } else grub_printf ("%s", route->interface->name); + grub_printf ("\n"); } return GRUB_ERR_NONE; } @@ -466,6 +476,8 @@ grub_net_open_real (const char *name) return ret; } } + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such device"); + return NULL; } diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index eac3bf770..85d138bb0 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -306,7 +306,7 @@ grub_pxefs_label (grub_device_t device __attribute ((unused)), static struct grub_fs grub_pxefs_fs = { - .name = "pxefs", + .name = "pxe", .dir = grub_pxefs_dir, .open = grub_pxefs_open, .read = grub_pxefs_read, @@ -590,7 +590,7 @@ GRUB_MOD_INIT(pxe) addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; addr.ipv4 = grub_pxe_your_ip; inter = grub_net_add_addr ("pxe", &grub_pxe_card, addr); - if (grub_pxe_default_gateway_ip) + if (grub_pxe_default_gateway_ip != grub_pxe_default_server_ip) { grub_net_network_level_netaddress_t target; grub_net_network_level_address_t gw; @@ -600,7 +600,7 @@ GRUB_MOD_INIT(pxe) target.ipv4.masksize = 32; gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; gw.ipv4 = grub_pxe_default_gateway_ip; - grub_net_add_route_gw ("pxe_default", target, gw); + grub_net_add_route_gw ("pxe_gw", target, gw); } { grub_net_network_level_netaddress_t target; @@ -608,7 +608,7 @@ GRUB_MOD_INIT(pxe) target.ipv4.base = grub_pxe_default_gateway_ip ? : grub_pxe_default_server_ip; target.ipv4.masksize = 32; - grub_net_add_route ("pxe_default", target, inter); + grub_net_add_route ("pxe", target, inter); } } } diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c index 9de545910..545487a6b 100644 --- a/grub-core/kern/device.c +++ b/grub-core/kern/device.c @@ -53,8 +53,11 @@ grub_device_open (const char *name) dev->disk = grub_disk_open (name); if (dev->disk) return dev; - if (grub_net_open) - dev->net = grub_net_open (name); + if (grub_net_open && grub_errno == GRUB_ERR_UNKNOWN_DEVICE) + { + grub_errno = GRUB_ERR_NONE; + dev->net = grub_net_open (name); + } if (dev->net) return dev; diff --git a/include/grub/net.h b/include/grub/net.h index 84e881efe..4efd79f79 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -59,19 +59,25 @@ typedef enum grub_network_level_protocol_id GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 } grub_network_level_protocol_id_t; -typedef union grub_net_network_level_address +typedef struct grub_net_network_level_address { grub_network_level_protocol_id_t type; - grub_uint32_t ipv4; + union + { + grub_uint32_t ipv4; + }; } grub_net_network_level_address_t; -typedef union grub_net_network_level_netaddress +typedef struct grub_net_network_level_netaddress { grub_network_level_protocol_id_t type; - struct { - grub_uint32_t base; - int masksize; - } ipv4; + union + { + struct { + grub_uint32_t base; + int masksize; + } ipv4; + }; } grub_net_network_level_netaddress_t; struct grub_net_network_level_interface; @@ -81,7 +87,7 @@ struct grub_net_network_level_interface struct grub_net_network_level_interface *next; char *name; struct grub_net_card *card; - union grub_net_network_level_address address; + grub_net_network_level_address_t address; void *data; }; From 0f37e4936515fb9d2c2204d3640d33a2a5ae4595 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 2 Sep 2010 20:00:56 +0200 Subject: [PATCH 041/406] Implement few variables --- grub-core/commands/net.c | 141 +++++++++++++++++++++++++++++++------ grub-core/fs/i386/pc/pxe.c | 35 +++------ include/grub/net.h | 35 ++++++++- 3 files changed, 161 insertions(+), 50 deletions(-) diff --git a/grub-core/commands/net.c b/grub-core/commands/net.c index 9d28c2ff7..5a21178e5 100644 --- a/grub-core/commands/net.c +++ b/grub-core/commands/net.c @@ -21,6 +21,7 @@ #include #include #include +#include struct grub_net_route { @@ -41,13 +42,6 @@ struct grub_net_network_level_interface *grub_net_network_level_interfaces = NUL struct grub_net_card *grub_net_cards = NULL; struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; -static inline void -grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) -{ - grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), - GRUB_AS_LIST (inter)); -} - static inline void grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) { @@ -212,6 +206,10 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), if (inter == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found")); + if (inter->flags & GRUB_NET_INTERFACE_PERMANENT) + return grub_error (GRUB_ERR_IO, + N_("you can't delete this address")); + grub_net_network_level_interface_unregister (inter); grub_free (inter->name); grub_free (inter); @@ -219,9 +217,104 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } +/* + Currently suppoerted adresses: + IPv4: XXX.XXX.XXX.XXX + */ +#define MAX_STR_ADDR_LEN sizeof ("XXX.XXX.XXX.XXX") + +static void +addr_to_str (const grub_net_network_level_address_t *target, char *buf) +{ + switch (target->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + { + grub_uint32_t n = grub_be_to_cpu32 (target->ipv4); + grub_snprintf (buf, MAX_STR_ADDR_LEN, "%d.%d.%d.%d", + ((n >> 24) & 0xff), ((n >> 16) & 0xff), + ((n >> 8) & 0xff), ((n >> 0) & 0xff)); + } + return; + } + grub_printf ("Unknown address type %d\n", target->type); +} + +/* + Currently suppoerted adresses: + ethernet: XX:XX:XX:XX:XX:XX + */ + +#define MAX_STR_HWADDR_LEN (sizeof ("XX:XX:XX:XX:XX:XX")) + +static void +hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str) +{ + str[0] = 0; + switch (addr->type) + { + case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET: + { + char *ptr; + unsigned i; + for (ptr = str, i = 0; i < ARRAY_SIZE (addr->mac); i++) + { + grub_snprintf (ptr, MAX_STR_HWADDR_LEN - (ptr - str), + "%02x:", addr->mac[i] & 0xff); + ptr += (sizeof ("XX:") - 1); + } + return; + } + } + grub_printf ("Unsupported hw address type %d\n", addr->type); +} + +/* FIXME: implement this. */ +static char * +hwaddr_set_env (struct grub_env_var *var __attribute__ ((unused)), + const char *val __attribute__ ((unused))) +{ + return NULL; +} + +/* FIXME: implement this. */ +static char * +addr_set_env (struct grub_env_var *var __attribute__ ((unused)), + const char *val __attribute__ ((unused))) +{ + return NULL; +} + +static void +grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) +{ + { + char buf[MAX_STR_HWADDR_LEN]; + char name[grub_strlen (inter->name) + sizeof ("net__mac")]; + hwaddr_to_str (&inter->hwaddress, buf); + grub_snprintf (name, sizeof (name), "net_%s_mac", inter->name); + grub_env_set (name, buf); + grub_register_variable_hook (name, 0, hwaddr_set_env); + } + + { + char buf[MAX_STR_ADDR_LEN]; + char name[grub_strlen (inter->name) + sizeof ("net__ip")]; + addr_to_str (&inter->address, buf); + grub_snprintf (name, sizeof (name), "net_%s_ip", inter->name); + grub_env_set (name, buf); + grub_register_variable_hook (name, 0, addr_set_env); + } + + grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + GRUB_AS_LIST (inter)); +} + struct grub_net_network_level_interface * grub_net_add_addr (const char *name, struct grub_net_card *card, - grub_net_network_level_address_t addr) + grub_net_network_level_address_t addr, + grub_net_link_level_address_t hwaddress, + grub_net_interface_flags_t flags) { struct grub_net_network_level_interface *inter; @@ -231,6 +324,8 @@ grub_net_add_addr (const char *name, struct grub_net_card *card, inter->name = grub_strdup (name); grub_memcpy (&(inter->address), &addr, sizeof (inter->address)); + grub_memcpy (&(inter->hwaddress), &hwaddress, sizeof (inter->hwaddress)); + inter->flags = flags; inter->card = card; grub_net_network_level_interface_register (inter); @@ -238,6 +333,7 @@ grub_net_add_addr (const char *name, struct grub_net_card *card, return inter; } +/* FIXME: support MAC specifying. */ static grub_err_t grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), int argc, char **args) @@ -245,6 +341,7 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), struct grub_net_card *card; grub_net_network_level_address_t addr; grub_err_t err; + grub_net_interface_flags_t flags = 0; if (argc != 3) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected")); @@ -259,7 +356,15 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), if (err) return err; - grub_net_add_addr (args[0], card, addr); + if (card->flags & GRUB_NET_CARD_NO_MANUAL_INTERFACES) + return grub_error (GRUB_ERR_IO, + "this card doesn't support address addition"); + + if (card->flags & GRUB_NET_CARD_HWADDRESS_IMMUTABLE) + flags |= GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE; + + grub_net_add_addr (args[0], card, addr, card->default_address, + flags); return grub_errno; } @@ -397,19 +502,9 @@ print_net_address (const grub_net_network_level_netaddress_t *target) static void print_address (const grub_net_network_level_address_t *target) { - switch (target->type) - { - case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: - { - grub_uint32_t n = grub_be_to_cpu32 (target->ipv4); - grub_printf ("%d.%d.%d.%d ", ((n >> 24) & 0xff), - ((n >> 16) & 0xff), - ((n >> 8) & 0xff), - ((n >> 0) & 0xff)); - } - return; - } - grub_printf ("Unknown address type %d\n", target->type); + char buf[MAX_STR_ADDR_LEN]; + addr_to_str (target, buf); + grub_xputs (buf); } static grub_err_t @@ -487,7 +582,7 @@ static grub_command_t cmd_lsroutes, cmd_lscards; GRUB_MOD_INIT(net) { cmd_addaddr = grub_register_command ("net_add_addr", grub_cmd_addaddr, - "SHORTNAME CARD ADDRESS", + "SHORTNAME CARD ADDRESS [HWADDRESS]", N_("Add a network address.")); cmd_deladdr = grub_register_command ("net_del_addr", grub_cmd_deladdr, "SHORTNAME", diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index 85d138bb0..1d9ea8f89 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -41,6 +41,7 @@ static grub_uint32_t grub_pxe_default_gateway_ip; static unsigned grub_pxe_blksize = GRUB_PXE_MIN_BLKSIZE; static grub_file_t curr_file = 0; +static grub_net_link_level_address_t pxe_hwaddr; struct grub_pxe_data { @@ -322,29 +323,6 @@ grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), return NULL; } -static void -set_mac_env (grub_uint8_t *mac_addr, grub_size_t mac_len) -{ - char buf[(sizeof ("XX:") - 1) * mac_len + 1]; - char *ptr = buf; - unsigned i; - - for (i = 0; i < mac_len; i++) - { - grub_snprintf (ptr, sizeof (buf) - (ptr - buf), - "%02x:", mac_addr[i] & 0xff); - ptr += (sizeof ("XX:") - 1); - } - if (mac_len) - *(ptr - 1) = 0; - else - buf[0] = 0; - - grub_env_set ("net_pxe_mac", buf); - /* XXX: Is it possible to change MAC in PXE? */ - grub_register_variable_hook ("net_pxe_mac", 0, grub_env_write_readonly); -} - static void set_env_limn_ro (const char *varname, char *value, grub_size_t len) { @@ -432,8 +410,10 @@ grub_pxe_detect (void) grub_pxe_your_ip = bp->your_ip; grub_pxe_default_server_ip = bp->server_ip; grub_pxe_default_gateway_ip = bp->gateway_ip; - set_mac_env (bp->mac_addr, bp->hw_len < sizeof (bp->mac_addr) ? bp->hw_len - : sizeof (bp->mac_addr)); + grub_memcpy (pxe_hwaddr.mac, bp->mac_addr, + bp->hw_len < sizeof (pxe_hwaddr.mac) + ? bp->hw_len : sizeof (pxe_hwaddr.mac)); + pxe_hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; set_env_limn_ro ("net_pxe_boot_file", (char *) bp->boot_file, sizeof (bp->boot_file)); set_env_limn_ro ("net_pxe_dhcp_server_name", (char *) bp->server_name, @@ -589,7 +569,10 @@ GRUB_MOD_INIT(pxe) grub_net_card_register (&grub_pxe_card); addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; addr.ipv4 = grub_pxe_your_ip; - inter = grub_net_add_addr ("pxe", &grub_pxe_card, addr); + inter = grub_net_add_addr ("pxe", &grub_pxe_card, addr, pxe_hwaddr, + GRUB_NET_INTERFACE_PERMANENT + | GRUB_NET_INTERFACE_ADDRESS_IMMUTABLE + | GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE); if (grub_pxe_default_gateway_ip != grub_pxe_default_server_ip) { grub_net_network_level_netaddress_t target; diff --git a/include/grub/net.h b/include/grub/net.h index 4efd79f79..649bf4096 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -34,6 +34,33 @@ typedef struct grub_net extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); +typedef enum grub_link_level_protocol_id +{ + GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET +} grub_link_level_protocol_id_t; + +typedef struct grub_net_link_level_address +{ + grub_link_level_protocol_id_t type; + union + { + grub_uint8_t mac[6]; + }; +} grub_net_link_level_address_t; + +typedef enum grub_net_interface_flags + { + GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE = 1, + GRUB_NET_INTERFACE_ADDRESS_IMMUTABLE = 2, + GRUB_NET_INTERFACE_PERMANENT = 4 + } grub_net_interface_flags_t; + +typedef enum grub_net_card_flags + { + GRUB_NET_CARD_HWADDRESS_IMMUTABLE = 1, + GRUB_NET_CARD_NO_MANUAL_INTERFACES = 2 + } grub_net_card_flags_t; + struct grub_net_card; struct grub_net_card_driver @@ -49,6 +76,8 @@ struct grub_net_card struct grub_net_card *next; char *name; struct grub_net_card_driver *driver; + grub_net_link_level_address_t default_address; + grub_net_card_flags_t flags; void *data; }; @@ -88,6 +117,8 @@ struct grub_net_network_level_interface char *name; struct grub_net_card *card; grub_net_network_level_address_t address; + grub_net_link_level_address_t hwaddress; + grub_net_interface_flags_t flags; void *data; }; @@ -130,7 +161,9 @@ grub_net_session_recv (struct grub_net_session *session, void *buf, struct grub_net_network_level_interface * grub_net_add_addr (const char *name, struct grub_net_card *card, - grub_net_network_level_address_t addr); + grub_net_network_level_address_t addr, + grub_net_link_level_address_t hwaddress, + grub_net_interface_flags_t flags); extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; From 308fad6dc87b752d32e383d8670a8a7fcf4bafa9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 2 Sep 2010 22:10:55 +0200 Subject: [PATCH 042/406] Move DHCP parsing to net module and reintroduce most variables --- grub-core/commands/net.c | 161 +++++++++++++++++++++++-- grub-core/fs/i386/pc/pxe.c | 235 ++++++++++--------------------------- include/grub/i386/pc/pxe.h | 38 +----- include/grub/net.h | 43 +++++++ 4 files changed, 257 insertions(+), 220 deletions(-) diff --git a/grub-core/commands/net.c b/grub-core/commands/net.c index 5a21178e5..f1838569b 100644 --- a/grub-core/commands/net.c +++ b/grub-core/commands/net.c @@ -217,21 +217,15 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } -/* - Currently suppoerted adresses: - IPv4: XXX.XXX.XXX.XXX - */ -#define MAX_STR_ADDR_LEN sizeof ("XXX.XXX.XXX.XXX") - -static void -addr_to_str (const grub_net_network_level_address_t *target, char *buf) +void +grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf) { switch (target->type) { case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { grub_uint32_t n = grub_be_to_cpu32 (target->ipv4); - grub_snprintf (buf, MAX_STR_ADDR_LEN, "%d.%d.%d.%d", + grub_snprintf (buf, GRUB_NET_MAX_STR_ADDR_LEN, "%d.%d.%d.%d", ((n >> 24) & 0xff), ((n >> 16) & 0xff), ((n >> 8) & 0xff), ((n >> 0) & 0xff)); } @@ -298,9 +292,9 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa } { - char buf[MAX_STR_ADDR_LEN]; + char buf[GRUB_NET_MAX_STR_ADDR_LEN]; char name[grub_strlen (inter->name) + sizeof ("net__ip")]; - addr_to_str (&inter->address, buf); + grub_net_addr_to_str (&inter->address, buf); grub_snprintf (name, sizeof (name), "net_%s_ip", inter->name); grub_env_set (name, buf); grub_register_variable_hook (name, 0, addr_set_env); @@ -327,6 +321,8 @@ grub_net_add_addr (const char *name, struct grub_net_card *card, grub_memcpy (&(inter->hwaddress), &hwaddress, sizeof (inter->hwaddress)); inter->flags = flags; inter->card = card; + inter->dhcp_ack = NULL; + inter->dhcp_acklen = 0; grub_net_network_level_interface_register (inter); @@ -502,8 +498,8 @@ print_net_address (const grub_net_network_level_netaddress_t *target) static void print_address (const grub_net_network_level_address_t *target) { - char buf[MAX_STR_ADDR_LEN]; - addr_to_str (target, buf); + char buf[GRUB_NET_MAX_STR_ADDR_LEN]; + grub_net_addr_to_str (target, buf); grub_xputs (buf); } @@ -576,6 +572,145 @@ grub_net_open_real (const char *name) return NULL; } +static char * +grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), + const char *val __attribute__ ((unused))) +{ + return NULL; +} + +static void +set_env_limn_ro (const char *intername, const char *suffix, + char *value, grub_size_t len) +{ + char c; + char varname[sizeof ("net_") + grub_strlen (intername) + sizeof ("_") + + grub_strlen (suffix)]; + grub_snprintf (varname, sizeof (varname), "net_%s_%s", intername, suffix); + c = value[len]; + value[len] = 0; + grub_env_set (varname, value); + value[len] = c; + grub_register_variable_hook (varname, 0, grub_env_write_readonly); +} + +static void +parse_dhcp_vendor (const char *name, void *vend, int limit) +{ + grub_uint8_t *ptr, *ptr0; + + ptr = ptr0 = vend; + + if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr) != GRUB_NET_BOOTP_RFC1048_MAGIC) + return; + ptr = ptr + sizeof (grub_uint32_t); + while (ptr - ptr0 < limit) + { + grub_uint8_t tagtype; + grub_uint8_t taglength; + + tagtype = *ptr++; + + /* Pad tag. */ + if (tagtype == 0) + continue; + + /* End tag. */ + if (tagtype == 0xff) + return; + + taglength = *ptr++; + + switch (tagtype) + { + case 12: + set_env_limn_ro (name, "hostname", (char *) ptr, taglength); + break; + + case 15: + set_env_limn_ro (name, "domain", (char *) ptr, taglength); + break; + + case 17: + set_env_limn_ro (name, "rootpath", (char *) ptr, taglength); + break; + + case 18: + set_env_limn_ro (name, "extensionspath", (char *) ptr, taglength); + break; + + /* If you need any other options please contact GRUB + developpement team. */ + } + + ptr += taglength; + } +} + +#define OFFSET_OF(x, y) ((grub_uint8_t *)((y)->x) - (grub_uint8_t *)(y)) + +struct grub_net_network_level_interface * +grub_net_configure_by_dhcp_ack (const char *name, struct grub_net_card *card, + grub_net_interface_flags_t flags, + struct grub_net_bootp_ack *bp, + grub_size_t size) +{ + grub_net_network_level_address_t addr; + grub_net_link_level_address_t hwaddr; + struct grub_net_network_level_interface *inter; + + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + addr.ipv4 = bp->your_ip; + + grub_memcpy (hwaddr.mac, bp->mac_addr, + bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len + : sizeof (hwaddr.mac)); + hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + + inter = grub_net_add_addr (name, card, addr, hwaddr, flags); + if (bp->gateway_ip != bp->server_ip) + { + grub_net_network_level_netaddress_t target; + grub_net_network_level_address_t gw; + char rname[grub_strlen (name) + sizeof ("_gw")]; + + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = bp->server_ip; + target.ipv4.masksize = 32; + gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + gw.ipv4 = bp->gateway_ip; + grub_snprintf (rname, sizeof (rname), "%s_gw", name); + grub_net_add_route_gw (rname, target, gw); + } + { + grub_net_network_level_netaddress_t target; + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = bp->gateway_ip; + target.ipv4.masksize = 32; + grub_net_add_route (name, target, inter); + } + + if (size > OFFSET_OF (boot_file, bp)) + set_env_limn_ro (name, "boot_file", (char *) bp->boot_file, + sizeof (bp->boot_file)); + if (size > OFFSET_OF (server_name, bp)) + set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name, + sizeof (bp->server_name)); + if (size > OFFSET_OF (vendor, bp)) + parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp)); + + inter->dhcp_ack = grub_malloc (size); + if (inter->dhcp_ack) + { + grub_memcpy (inter->dhcp_ack, bp, size); + inter->dhcp_acklen = size; + } + else + grub_errno = GRUB_ERR_NONE; + + return inter; +} + static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; static grub_command_t cmd_lsroutes, cmd_lscards; diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index 1d9ea8f89..513a8cb7d 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -35,13 +35,13 @@ #define LINEAR(x) (void *) (((x >> 16) << 4) + (x & 0xFFFF)) struct grub_pxe_bangpxe *grub_pxe_pxenv; -static grub_uint32_t grub_pxe_your_ip; static grub_uint32_t grub_pxe_default_server_ip; +#if 0 static grub_uint32_t grub_pxe_default_gateway_ip; +#endif static unsigned grub_pxe_blksize = GRUB_PXE_MIN_BLKSIZE; - +static grub_uint32_t pxe_rm_entry = 0; static grub_file_t curr_file = 0; -static grub_net_link_level_address_t pxe_hwaddr; struct grub_pxe_data { @@ -52,7 +52,6 @@ struct grub_pxe_data char filename[0]; }; -static grub_uint32_t pxe_rm_entry = 0; static struct grub_pxe_bangpxe * grub_pxe_scan (void) @@ -316,112 +315,6 @@ static struct grub_fs grub_pxefs_fs = .next = 0 }; -static char * -grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), - const char *val __attribute__ ((unused))) -{ - return NULL; -} - -static void -set_env_limn_ro (const char *varname, char *value, grub_size_t len) -{ - char c; - c = value[len]; - value[len] = 0; - grub_env_set (varname, value); - value[len] = c; - grub_register_variable_hook (varname, 0, grub_env_write_readonly); -} - -static void -parse_dhcp_vendor (void *vend, int limit) -{ - grub_uint8_t *ptr, *ptr0; - - ptr = ptr0 = vend; - - if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr) != 0x63825363) - return; - ptr = ptr + sizeof (grub_uint32_t); - while (ptr - ptr0 < limit) - { - grub_uint8_t tagtype; - grub_uint8_t taglength; - - tagtype = *ptr++; - - /* Pad tag. */ - if (tagtype == 0) - continue; - - /* End tag. */ - if (tagtype == 0xff) - return; - - taglength = *ptr++; - - switch (tagtype) - { - case 12: - set_env_limn_ro ("net_pxe_hostname", (char *) ptr, taglength); - break; - - case 15: - set_env_limn_ro ("net_pxe_domain", (char *) ptr, taglength); - break; - - case 17: - set_env_limn_ro ("net_pxe_rootpath", (char *) ptr, taglength); - break; - - case 18: - set_env_limn_ro ("net_pxe_extensionspath", (char *) ptr, taglength); - break; - - /* If you need any other options please contact GRUB - developpement team. */ - } - - ptr += taglength; - } -} - -static void -grub_pxe_detect (void) -{ - struct grub_pxe_bangpxe *pxenv; - struct grub_pxenv_get_cached_info ci; - struct grub_pxenv_boot_player *bp; - - pxenv = grub_pxe_scan (); - if (! pxenv) - return; - - ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK; - ci.buffer = 0; - ci.buffer_size = 0; - grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry); - if (ci.status) - return; - - bp = LINEAR (ci.buffer); - - grub_pxe_your_ip = bp->your_ip; - grub_pxe_default_server_ip = bp->server_ip; - grub_pxe_default_gateway_ip = bp->gateway_ip; - grub_memcpy (pxe_hwaddr.mac, bp->mac_addr, - bp->hw_len < sizeof (pxe_hwaddr.mac) - ? bp->hw_len : sizeof (pxe_hwaddr.mac)); - pxe_hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - set_env_limn_ro ("net_pxe_boot_file", (char *) bp->boot_file, - sizeof (bp->boot_file)); - set_env_limn_ro ("net_pxe_dhcp_server_name", (char *) bp->server_name, - sizeof (bp->server_name)); - parse_dhcp_vendor (&bp->vendor, sizeof (bp->vendor)); - grub_pxe_pxenv = pxenv; -} - static grub_size_t grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused)), void *buf __attribute__ ((unused)), @@ -461,14 +354,15 @@ grub_pxe_unload (void) } } -#if 0 static void set_ip_env (char *varname, grub_uint32_t ip) { - char buf[sizeof ("XXX.XXX.XXX.XXX")]; + char buf[GRUB_NET_MAX_STR_ADDR_LEN]; + grub_net_network_level_address_t addr; + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + addr.ipv4 = ip; - grub_snprintf (buf, sizeof (buf), "%d.%d.%d.%d", (ip & 0xff), - (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff); + grub_net_addr_to_str (&addr, buf); grub_env_set (varname, buf); } @@ -477,25 +371,25 @@ write_ip_env (grub_uint32_t *ip, const char *val) { char *buf; grub_err_t err; - grub_uint32_t newip; - - err = parse_ip (val, &newip, 0); + grub_net_network_level_address_t addr; + + err = grub_net_resolve_address (val, &addr); if (err) return 0; + if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + return NULL; /* Normalize the IP. */ - buf = grub_xasprintf ("%d.%d.%d.%d", (newip & 0xff), (newip >> 8) & 0xff, - (newip >> 16) & 0xff, (newip >> 24) & 0xff); + buf = grub_malloc (GRUB_NET_MAX_STR_ADDR_LEN); if (!buf) return 0; + grub_net_addr_to_str (&addr, buf); - *ip = newip; + *ip = addr.ipv4; return buf; } -#endif -#if 0 static char * grub_env_write_pxe_default_server (struct grub_env_var *var __attribute__ ((unused)), @@ -504,6 +398,7 @@ grub_env_write_pxe_default_server (struct grub_env_var *var return write_ip_env (&grub_pxe_default_server_ip, val); } +#if 0 static char * grub_env_write_pxe_default_gateway (struct grub_env_var *var __attribute__ ((unused)), @@ -540,60 +435,58 @@ grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__ ((unused)), GRUB_MOD_INIT(pxe) { - grub_pxe_detect (); - if (grub_pxe_pxenv) - { - char *buf; - grub_net_network_level_address_t addr; - struct grub_net_network_level_interface *inter; - -#if 0 - grub_register_variable_hook ("pxe_default_server", 0, - grub_env_write_pxe_default_server); - grub_register_variable_hook ("pxe_default_gateway", 0, - grub_env_write_pxe_default_gateway); -#endif - grub_register_variable_hook ("pxe_blksize", 0, - grub_env_write_pxe_blocksize); + struct grub_pxe_bangpxe *pxenv; + struct grub_pxenv_get_cached_info ci; + struct grub_net_bootp_ack *bp; + char *buf; - buf = grub_xasprintf ("%d", grub_pxe_blksize); - if (buf) - grub_env_set ("pxe_blksize", buf); - grub_free (buf); + pxenv = grub_pxe_scan (); + if (! pxenv) + return; + + ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK; + ci.buffer = 0; + ci.buffer_size = 0; + grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry); + if (ci.status) + return; + + bp = LINEAR (ci.buffer); + + grub_pxe_default_server_ip = bp->server_ip; + grub_pxe_pxenv = pxenv; + + set_ip_env ("pxe_default_server", grub_pxe_default_server_ip); + grub_register_variable_hook ("pxe_default_server", 0, + grub_env_write_pxe_default_server); #if 0 - set_ip_env ("pxe_default_server", grub_pxe_default_server_ip); + grub_pxe_default_gateway_ip = bp->gateway_ip; + + grub_register_variable_hook ("pxe_default_gateway", 0, + grub_env_write_pxe_default_gateway); #endif - grub_net_app_level_register (&grub_pxefs_fs); - grub_net_card_register (&grub_pxe_card); - addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - addr.ipv4 = grub_pxe_your_ip; - inter = grub_net_add_addr ("pxe", &grub_pxe_card, addr, pxe_hwaddr, - GRUB_NET_INTERFACE_PERMANENT - | GRUB_NET_INTERFACE_ADDRESS_IMMUTABLE - | GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE); - if (grub_pxe_default_gateway_ip != grub_pxe_default_server_ip) - { - grub_net_network_level_netaddress_t target; - grub_net_network_level_address_t gw; - - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4.base = grub_pxe_default_server_ip; - target.ipv4.masksize = 32; - gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - gw.ipv4 = grub_pxe_default_gateway_ip; - grub_net_add_route_gw ("pxe_gw", target, gw); - } - { - grub_net_network_level_netaddress_t target; - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4.base = grub_pxe_default_gateway_ip ? - : grub_pxe_default_server_ip; - target.ipv4.masksize = 32; - grub_net_add_route ("pxe", target, inter); - } - } + buf = grub_xasprintf ("%d", grub_pxe_blksize); + if (buf) + grub_env_set ("pxe_blksize", buf); + grub_free (buf); + + grub_register_variable_hook ("pxe_blksize", 0, + grub_env_write_pxe_blocksize); + + grub_memcpy (grub_pxe_card.default_address.mac, bp->mac_addr, + bp->hw_len < sizeof (grub_pxe_card.default_address.mac) + ? bp->hw_len : sizeof (grub_pxe_card.default_address.mac)); + grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + + grub_net_app_level_register (&grub_pxefs_fs); + grub_net_card_register (&grub_pxe_card); + grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, + GRUB_NET_INTERFACE_PERMANENT + | GRUB_NET_INTERFACE_ADDRESS_IMMUTABLE + | GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE, + bp, GRUB_PXE_BOOTP_SIZE); } GRUB_MOD_FINI(pxe) diff --git a/include/grub/i386/pc/pxe.h b/include/grub/i386/pc/pxe.h index 62ece21b0..781b53df5 100644 --- a/include/grub/i386/pc/pxe.h +++ b/include/grub/i386/pc/pxe.h @@ -152,9 +152,9 @@ #define GRUB_PXE_BOOTP_BCAST 0x8000 #if 1 -#define GRUB_PXE_BOOTP_DHCPVEND 1024 /* DHCP extended vendor field size. */ +#define GRUB_PXE_BOOTP_SIZE (1024 + 236) /* DHCP extended vendor field size. */ #else -#define GRUB_PXE_BOOTP_DHCPVEND 312 /* DHCP standard vendor field size. */ +#define GRUB_PXE_BOOTP_SIZE (312 + 236) /* DHCP standard vendor field size. */ #endif #define GRUB_PXE_MIN_BLKSIZE 512 @@ -162,8 +162,6 @@ #define GRUB_PXE_TFTP_PORT 69 -#define GRUB_PXE_VM_RFC1048 0x63825363L - #define GRUB_PXE_ERR_LEN 0xFFFFFFFF #ifndef ASM_FILE @@ -214,38 +212,6 @@ struct grub_pxenv_get_cached_info grub_uint16_t buffer_limit; } __attribute__ ((packed)); -#define GRUB_PXE_MAC_ADDR_LEN 16 - -typedef grub_uint8_t grub_pxe_mac_addr_t[GRUB_PXE_MAC_ADDR_LEN]; - -struct grub_pxenv_boot_player -{ - grub_uint8_t opcode; - grub_uint8_t hw_type; /* hardware type. */ - grub_uint8_t hw_len; /* hardware addr len. */ - grub_uint8_t gate_hops; /* zero it. */ - grub_uint32_t ident; /* random number chosen by client. */ - grub_uint16_t seconds; /* seconds since did initial bootstrap. */ - grub_uint16_t flags; - grub_uint32_t client_ip; - grub_uint32_t your_ip; - grub_uint32_t server_ip; - grub_uint32_t gateway_ip; - grub_pxe_mac_addr_t mac_addr; - grub_uint8_t server_name[64]; - grub_uint8_t boot_file[128]; - union - { - grub_uint8_t d[GRUB_PXE_BOOTP_DHCPVEND]; /* raw array of vendor/dhcp options. */ - struct - { - grub_uint32_t magic; /* DHCP magic cookie. */ - grub_uint32_t flags; /* bootp flags/opcodes. */ - grub_uint8_t padding[56]; - } v; - } vendor; -} __attribute__ ((packed)); - struct grub_pxenv_tftp_open { grub_uint16_t status; diff --git a/include/grub/net.h b/include/grub/net.h index 649bf4096..ec334092d 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -119,6 +119,8 @@ struct grub_net_network_level_interface grub_net_network_level_address_t address; grub_net_link_level_address_t hwaddress; grub_net_interface_flags_t flags; + struct grub_net_bootp_ack *dhcp_ack; + grub_size_t dhcp_acklen; void *data; }; @@ -234,4 +236,45 @@ grub_net_add_route_gw (const char *name, grub_net_network_level_address_t gw); +#define GRUB_NET_BOOTP_MAC_ADDR_LEN 16 + +typedef grub_uint8_t grub_net_bootp_mac_addr_t[GRUB_NET_BOOTP_MAC_ADDR_LEN]; + +struct grub_net_bootp_ack +{ + grub_uint8_t opcode; + grub_uint8_t hw_type; /* hardware type. */ + grub_uint8_t hw_len; /* hardware addr len. */ + grub_uint8_t gate_hops; /* zero it. */ + grub_uint32_t ident; /* random number chosen by client. */ + grub_uint16_t seconds; /* seconds since did initial bootstrap. */ + grub_uint16_t flags; + grub_uint32_t client_ip; + grub_uint32_t your_ip; + grub_uint32_t server_ip; + grub_uint32_t gateway_ip; + grub_net_bootp_mac_addr_t mac_addr; + grub_uint8_t server_name[64]; + grub_uint8_t boot_file[128]; + grub_uint8_t vendor[0]; +} __attribute__ ((packed)); + +#define GRUB_NET_BOOTP_RFC1048_MAGIC 0x63825363L + +struct grub_net_network_level_interface * +grub_net_configure_by_dhcp_ack (const char *name, struct grub_net_card *card, + grub_net_interface_flags_t flags, + struct grub_net_bootp_ack *bp, + grub_size_t size); + +/* + Currently suppoerted adresses: + IPv4: XXX.XXX.XXX.XXX + */ +#define GRUB_NET_MAX_STR_ADDR_LEN sizeof ("XXX.XXX.XXX.XXX") + +void +grub_net_addr_to_str (const grub_net_network_level_address_t *target, + char *buf); + #endif /* ! GRUB_NET_HEADER */ From 9daa20394429830d83a26c4eda35ab1a085fadd9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 2 Sep 2010 22:12:37 +0200 Subject: [PATCH 043/406] Reintroduce pxe: syntax --- grub-core/fs/i386/pc/pxe.c | 77 ++++++++++++++------------------------ 1 file changed, 29 insertions(+), 48 deletions(-) diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index 513a8cb7d..dc447d92c 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -121,54 +121,35 @@ grub_pxefs_open (struct grub_file *file, const char *name) if (!data) return grub_errno; -#if 0 - if (grub_strncmp (file->device->net->name, "pxe:", sizeof ("pxe:") - 1) == 0) - { - const char *ptr; - grub_err_t err; - - ptr = name + sizeof ("pxe:") - 1; - err = parse_ip (ptr, &(data->server_ip), &ptr); - if (err) - return err; - if (*ptr == ':') - { - err = parse_ip (ptr + 1, &(data->gateway_ip), 0); - if (err) - return err; - } - else - data->gateway_ip = grub_pxe_default_gateway_ip; - } - else -#endif - { - grub_net_network_level_address_t addr; - grub_net_network_level_address_t gateway; - struct grub_net_network_level_interface *interf; - grub_err_t err; - - if (grub_strncmp (file->device->net->name, - "pxe,", sizeof ("pxe,") - 1) == 0) - { - const char *ptr; - - ptr = name + sizeof ("pxe,") - 1; - err = grub_net_resolve_address (name + sizeof ("pxe,") - 1, &addr); - if (err) - return err; - } - else - { - addr.ipv4 = grub_pxe_default_server_ip; - addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - } - err = grub_net_route_address (addr, &gateway, &interf); - if (err) - return err; - data->server_ip = addr.ipv4; - data->gateway_ip = gateway.ipv4; - } + { + grub_net_network_level_address_t addr; + grub_net_network_level_address_t gateway; + struct grub_net_network_level_interface *interf; + grub_err_t err; + + if (grub_strncmp (file->device->net->name, + "pxe,", sizeof ("pxe,") - 1) == 0 + || grub_strncmp (file->device->net->name, + "pxe:", sizeof ("pxe:") - 1) == 0) + { + const char *ptr; + + ptr = name + sizeof ("pxe,") - 1; + err = grub_net_resolve_address (name + sizeof ("pxe,") - 1, &addr); + if (err) + return err; + } + else + { + addr.ipv4 = grub_pxe_default_server_ip; + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + } + err = grub_net_route_address (addr, &gateway, &interf); + if (err) + return err; + data->server_ip = addr.ipv4; + data->gateway_ip = gateway.ipv4; + } if (curr_file != 0) { From c04256771534fc5dcd1ce71e335b37d5cacc7b42 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 2 Sep 2010 22:20:48 +0200 Subject: [PATCH 044/406] Create directory net and move all net files there --- Makefile.util.def | 2 +- grub-core/Makefile.core.def | 4 ++-- grub-core/{fs => net}/i386/pc/pxe.c | 0 grub-core/{commands => net}/net.c | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename grub-core/{fs => net}/i386/pc/pxe.c (100%) rename grub-core/{commands => net}/net.c (100%) diff --git a/Makefile.util.def b/Makefile.util.def index 5fd53680d..68c105a9b 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -30,7 +30,7 @@ library = { common = grub-core/commands/blocklist.c; common = grub-core/commands/extcmd.c; common = grub-core/commands/ls.c; - common = grub-core/commands/net.c; + common = grub-core/net/net.c; common = grub-core/disk/dmraid_nvidia.c; common = grub-core/disk/host.c; common = grub-core/disk/loopback.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index fb68f344c..bd5d78160 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -930,7 +930,7 @@ module = { module = { name = pxe; - i386_pc = fs/i386/pc/pxe.c; + i386_pc = net/i386/pc/pxe.c; enable = i386_pc; }; @@ -1379,5 +1379,5 @@ module = { module = { name = net; - common = commands/net.c; + common = net/net.c; }; \ No newline at end of file diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/net/i386/pc/pxe.c similarity index 100% rename from grub-core/fs/i386/pc/pxe.c rename to grub-core/net/i386/pc/pxe.c diff --git a/grub-core/commands/net.c b/grub-core/net/net.c similarity index 100% rename from grub-core/commands/net.c rename to grub-core/net/net.c From 30b4166fdea35a49e1712efe6997de210cd17ca3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 4 Sep 2010 17:23:51 +0200 Subject: [PATCH 045/406] Reimport setjmp from Tristan's branch. --- ChangeLog.ia64-emu | 6 ++ grub-core/lib/ia64/longjmp.S | 162 +++++++++++++++++++++++++++++++++ grub-core/lib/ia64/setjmp.S | 171 +++++++++++++++++++++++++++++++++++ grub-core/lib/setjmp.S | 2 + 4 files changed, 341 insertions(+) create mode 100644 ChangeLog.ia64-emu create mode 100644 grub-core/lib/ia64/longjmp.S create mode 100644 grub-core/lib/ia64/setjmp.S diff --git a/ChangeLog.ia64-emu b/ChangeLog.ia64-emu new file mode 100644 index 000000000..61a3ca6de --- /dev/null +++ b/ChangeLog.ia64-emu @@ -0,0 +1,6 @@ +2008-01-28 Tristan Gingold +2010-01-18 Robert Millan + + * grub-core/lib/ia64/setjmp.S: New file (from glibc). + * grub-core/lib/ia64/longjmp.S: New file (from glibc). + * grub-core/lib/setjmp.S [__ia64__]: include ia64/setjmp.S. diff --git a/grub-core/lib/ia64/longjmp.S b/grub-core/lib/ia64/longjmp.S new file mode 100644 index 000000000..729bdc76e --- /dev/null +++ b/grub-core/lib/ia64/longjmp.S @@ -0,0 +1,162 @@ +/* Copyright (C) 1999, 2000, 2001, 2002, 2008 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 --git a/grub-core/lib/ia64/setjmp.S b/grub-core/lib/ia64/setjmp.S new file mode 100644 index 000000000..0851885c5 --- /dev/null +++ b/grub-core/lib/ia64/setjmp.S @@ -0,0 +1,171 @@ +/* Copyright (C) 1999, 2000, 2001, 2002, 2008 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 --git a/grub-core/lib/setjmp.S b/grub-core/lib/setjmp.S index c39c91b9c..7e669d4ff 100644 --- a/grub-core/lib/setjmp.S +++ b/grub-core/lib/setjmp.S @@ -8,6 +8,8 @@ #include "./mips/setjmp.S" #elif defined(__powerpc__) #include "./powerpc/setjmp.S" +#elif defined(__ia64__) +#include "./ia64/setjmp.S" #else #error "Unknwon target cpu type" #endif From 3b2bdd6f73c0e7bf082f8553503b27c3806eb224 Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Wed, 8 Sep 2010 01:50:12 +0200 Subject: [PATCH 046/406] Add missing headers for ia64 --- include/grub/ia64/setjmp.h | 28 ++++++++++++++++++++++++++++ include/grub/ia64/time.h | 28 ++++++++++++++++++++++++++++ include/grub/ia64/types.h | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 include/grub/ia64/setjmp.h create mode 100644 include/grub/ia64/time.h create mode 100644 include/grub/ia64/types.h diff --git a/include/grub/ia64/setjmp.h b/include/grub/ia64/setjmp.h new file mode 100644 index 000000000..a71c9c56d --- /dev/null +++ b/include/grub/ia64/setjmp.h @@ -0,0 +1,28 @@ +/* Define the machine-dependent type `jmp_buf'. Linux/IA-64 version. + Copyright (C) 1999, 2000, 2008 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! */ + +int grub_setjmp (grub_jmp_buf env); +void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn)); diff --git a/include/grub/ia64/time.h b/include/grub/ia64/time.h new file mode 100644 index 000000000..03ee79fa4 --- /dev/null +++ b/include/grub/ia64/time.h @@ -0,0 +1,28 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 . + */ + +#ifndef KERNEL_CPU_TIME_HEADER +#define KERNEL_CPU_TIME_HEADER 1 + +static __inline void +grub_cpu_idle (void) +{ + /* FIXME: not implemented */ +} + +#endif /* ! KERNEL_CPU_TIME_HEADER */ diff --git a/include/grub/ia64/types.h b/include/grub/ia64/types.h new file mode 100644 index 000000000..91a546dd2 --- /dev/null +++ b/include/grub/ia64/types.h @@ -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 */ From 22a85f6b0abc04e881b8e376cc0793992dc23e16 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 8 Sep 2010 01:51:31 +0200 Subject: [PATCH 047/406] Add ia64-specific libgcc symbols --- configure.ac | 2 +- include/grub/libgcc.h | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d362f68a5..ca886b5dc 100644 --- a/configure.ac +++ b/configure.ac @@ -542,7 +542,7 @@ CFLAGS="$CFLAGS -Wl,--defsym,abort=main" fi # Check for libgcc symbols -AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2 _restgpr_14_x) +AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2 _restgpr_14_x __ia64_trampoline __udivsi3 __umoddi3 __udivdi3 __divsi3 __modsi3 __umodsi3) if test "x$TARGET_APPLE_CC" = x1 ; then CFLAGS="$TARGET_CFLAGS -nostdlib" diff --git a/include/grub/libgcc.h b/include/grub/libgcc.h index d0adae8c1..703182577 100644 --- a/include/grub/libgcc.h +++ b/include/grub/libgcc.h @@ -38,8 +38,30 @@ void EXPORT_FUNC (__bswapsi2) (void); # ifdef HAVE___BSWAPDI2 void EXPORT_FUNC (__bswapdi2) (void); # endif +# ifdef HAVE___UDIVSI3 +void EXPORT_FUNC (__udivsi3) (void); +# endif +# ifdef HAVE___UMODSI3 +void EXPORT_FUNC (__umodsi3) (void); +# endif +# ifdef HAVE___UMODDI3 +void EXPORT_FUNC (__umoddi3) (void); +# endif +# ifdef HAVE___UDIVDI3 +void EXPORT_FUNC (__udivdi3) (void); +# endif +# ifdef HAVE___DIVSI3 +void EXPORT_FUNC (__divsi3) (void); +# endif +# ifdef HAVE___UMODSI3 +void EXPORT_FUNC (__modsi3) (void); +# endif #endif +# ifdef HAVE___IA64_TRAMPOLINE +void EXPORT_FUNC (__ia64_trampoline) (void); +# endif + #ifdef HAVE___TRAMPOLINE_SETUP void EXPORT_FUNC (__trampoline_setup) (void); #endif From 779e9dc48071591aa3205bb6087459902820c746 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 00:44:57 +0200 Subject: [PATCH 048/406] Support Solaris DHCP ACK parsing --- grub-core/loader/i386/multiboot_mbi.c | 29 ++++++++++++++++++++++++++- grub-core/net/net.c | 2 -- include/grub/net.h | 4 ++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c index bf17863cf..9d6497442 100644 --- a/grub-core/loader/i386/multiboot_mbi.c +++ b/grub-core/loader/i386/multiboot_mbi.c @@ -32,6 +32,7 @@ #include #include #include +#include /* The bits in the required part of flags field we don't support. */ #define UNSUPPORTED_FLAGS 0x0000fff8 @@ -189,12 +190,24 @@ grub_multiboot_load (grub_file_t file) static grub_size_t grub_multiboot_get_mbi_size (void) { - return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4) + grub_size_t ret; + struct grub_net_network_level_interface *net; + + ret = sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4) + modcnt * sizeof (struct multiboot_mod_list) + total_modcmd + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry) + elf_sec_entsize * elf_sec_num + 256 * sizeof (struct multiboot_color); + + FOR_NET_NETWORK_LEVEL_INTERFACES(net) + if (net->dhcp_ack) + { + ret += net->dhcp_acklen; + break; + } + + return ret; } /* Fill previously allocated Multiboot mmap. */ @@ -401,6 +414,20 @@ grub_multiboot_make_mbi (grub_uint32_t *target) mbi->flags |= MULTIBOOT_INFO_BOOTDEV; } + { + struct grub_net_network_level_interface *net; + FOR_NET_NETWORK_LEVEL_INTERFACES(net) + if (net->dhcp_ack) + { + grub_memcpy (ptrorig, net->dhcp_ack, net->dhcp_acklen); + mbi->drives_addr = ptrdest; + mbi->drives_length = net->dhcp_acklen; + ptrorig += net->dhcp_acklen; + ptrdest += net->dhcp_acklen; + break; + } + } + if (elf_sec_num) { mbi->u.elf_sec.addr = ptrdest; diff --git a/grub-core/net/net.c b/grub-core/net/net.c index f1838569b..7c8992f8d 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -49,8 +49,6 @@ grub_net_network_level_interface_unregister (struct grub_net_network_level_inter GRUB_AS_LIST (inter)); } -#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) - static inline void grub_net_route_register (struct grub_net_route *route) { diff --git a/include/grub/net.h b/include/grub/net.h index ec334092d..a0737d574 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -277,4 +277,8 @@ void grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf); +extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; +#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) + + #endif /* ! GRUB_NET_HEADER */ From 21e4963bcc9cd307c54762d1715a0d38d502dd9f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 01:12:47 +0200 Subject: [PATCH 049/406] Support net_get_dhcp_option --- grub-core/net/net.c | 128 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 7c8992f8d..5205e1938 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -709,8 +709,130 @@ grub_net_configure_by_dhcp_ack (const char *name, struct grub_net_card *card, return inter; } +static char +hexdigit (grub_uint8_t val) +{ + if (val < 10) + return val + '0'; + return val + 'a' - 10; +} + +static grub_err_t +grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_network_level_interface *inter; + int num; + grub_uint8_t *ptr; + grub_uint8_t taglength; + + if (argc < 4) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "4 arguments expected"); + + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + if (grub_strcmp (inter->name, args[1])) + break; + + if (!inter) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unrecognised interface %s"), args[1]); + + if (!inter->dhcp_ack) + return grub_error (GRUB_ERR_IO, N_("no DHCP info found")); + + if (inter->dhcp_acklen <= OFFSET_OF (vendor, inter->dhcp_ack)) + return grub_error (GRUB_ERR_IO, N_("no DHCP options found")); + + num = grub_strtoul (args[2], 0, 0); + if (grub_errno) + return grub_errno; + + ptr = inter->dhcp_ack->vendor; + + if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr) + != GRUB_NET_BOOTP_RFC1048_MAGIC) + return grub_error (GRUB_ERR_IO, N_("no DHCP options found")); + ptr = ptr + sizeof (grub_uint32_t); + while (1) + { + grub_uint8_t tagtype; + + if (ptr >= ((grub_uint8_t *) inter->dhcp_ack) + inter->dhcp_acklen) + return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num); + + tagtype = *ptr++; + + /* Pad tag. */ + if (tagtype == 0) + continue; + + /* End tag. */ + if (tagtype == 0xff) + return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num); + + taglength = *ptr++; + + if (tagtype == num) + break; + ptr += taglength; + } + + if (grub_strcmp (args[3], "string") == 0) + { + char *val = grub_malloc (taglength + 1); + if (!val) + return grub_errno; + grub_memcpy (val, ptr, taglength); + val[taglength] = 0; + if (args[0][0] == '-' && args[0][1] == 0) + grub_printf ("%s\n", val); + else + return grub_env_set (args[0], val); + return GRUB_ERR_NONE; + } + + if (grub_strcmp (args[3], "number") == 0) + { + grub_uint64_t val = 0; + int i; + for (i = 0; i < taglength; i++) + val = (val << 8) | ptr[i]; + if (args[0][0] == '-' && args[0][1] == 0) + grub_printf ("%llu\n", (unsigned long long) val); + else + { + char valn[64]; + grub_printf (valn, sizeof (valn), "%lld\n", (unsigned long long) val); + return grub_env_set (args[0], valn); + } + return GRUB_ERR_NONE; + } + + if (grub_strcmp (args[3], "hex") == 0) + { + char *val = grub_malloc (2 * taglength + 1); + int i; + if (!val) + return grub_errno; + for (i = 0; i < taglength; i++) + { + val[2 * i] = hexdigit (ptr[i] >> 4); + val[2 * i + 1] = hexdigit (ptr[i] & 0xf); + } + val[2 * taglength] = 0; + if (args[0][0] == '-' && args[0][1] == 0) + grub_printf ("%s\n", val); + else + return grub_env_set (args[0], val); + return GRUB_ERR_NONE; + } + + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "unrecognised format specification %s", args[3]); +} + static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; -static grub_command_t cmd_lsroutes, cmd_lscards; +static grub_command_t cmd_lsroutes, cmd_lscards, cmd_getdhcp; GRUB_MOD_INIT(net) { @@ -730,6 +852,9 @@ GRUB_MOD_INIT(net) "", N_("list network routes")); cmd_lscards = grub_register_command ("net_ls_cards", grub_cmd_listcards, "", N_("list network cards")); + cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt, + N_("VAR INTERFACE NUMBER DESCRIPTION"), + N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); grub_net_open = grub_net_open_real; } @@ -742,5 +867,6 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_delroute); grub_unregister_command (cmd_lsroutes); grub_unregister_command (cmd_lscards); + grub_unregister_command (cmd_getdhcp); grub_net_open = NULL; } From 9a9cee4e4347c0480fb9e19ce2732a2132c4e3f9 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Wed, 15 Sep 2010 13:00:51 -0300 Subject: [PATCH 050/406] Use the correct address types in net.c. implement ntoa ipv4 function. --- commands/net.c | 40 +++++++++++++++++++++++++++---------- include/grub/net.h | 29 +++++++++++++++++++++++---- include/grub/net/protocol.h | 5 +++-- include/grub/net/type_net.h | 8 ++++---- net/ip.c | 38 +++++++++++++++++++++++++++++++++-- 5 files changed, 97 insertions(+), 23 deletions(-) diff --git a/commands/net.c b/commands/net.c index b8ceb36f4..2558a309b 100644 --- a/commands/net.c +++ b/commands/net.c @@ -22,11 +22,8 @@ #include #include -struct grub_net_route *grub_net_routes = NULL; -struct grub_net_network_layer_interface *grub_net_network_layer_interfaces = NULL; -struct grub_net_card *grub_net_cards = NULL; -struct grub_net_network_layer_protocol *grub_net_network_layer_protocols = NULL; +/*Find which protocol understands the given address*/ grub_err_t grub_net_resolve_address (struct grub_net_network_layer_protocol **prot, char *name, @@ -102,7 +99,7 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); FOR_NET_NETWORK_LEVEL_INTERFACES (inter) - if (grub_strcmp (inter->name, args[1])) + if ( !grub_strcmp (inter->name, args[1])) break; if (inter == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found")); @@ -124,21 +121,36 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), grub_err_t err; grub_net_network_layer_address_t addr; struct grub_net_network_layer_interface *inter; + grub_printf("Enter add addr function.\n"); + + grub_printf("card list address in net.c = %x\n", (int) grub_net_cards); if (argc != 4) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("four arguments expected")); FOR_NET_CARDS (card) - if (grub_strcmp (card->name, args[1])) + { + grub_printf("card address = %x\n", (int) card); + grub_printf("card->name = %s\n",card->name); + grub_printf("args[1] = %s\n",args[1]); + if ( !grub_strcmp (card->name, args[1])) break; + } + + grub_printf("Out of the loop.\n"); + grub_printf("card address = %x\n", (int) card); + if (card == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found")); + grub_printf("protocols loop.\n"); FOR_NET_NETWORK_LEVEL_PROTOCOLS (prot) - if (grub_strcmp (prot->name, args[2])) + if ( !grub_strcmp (prot->name, args[2])) break; - if (card == NULL) + grub_printf("end protocols loop.\n"); + + if (prot == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("protocol not found")); err = grub_net_resolve_address_in_protocol (prot, args[3], &addr); @@ -163,6 +175,12 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), } grub_net_network_layer_interface_register (inter); + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + { + grub_printf("inter->name = %s\n",inter->name); + grub_printf("inter->address = %x\n",(int) (inter->address.ipv4)); + + } return GRUB_ERR_NONE; } @@ -178,7 +196,7 @@ grub_cmd_delroute (struct grub_command *cmd __attribute__ ((unused)), for (prev = &grub_net_routes, route = *prev; route; prev = &((*prev)->next), route = *prev) - if (grub_strcmp (route->name, args[0]) == 0) + if ( !grub_strcmp (route->name, args[0]) == 0) { *prev = route->next; grub_free (route->name); @@ -232,7 +250,7 @@ grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), N_("Unrecognised address %s"), args[1]); } - if (grub_strcmp (args[2], "gw") == 0 && argc >= 4) + if ( !grub_strcmp (args[2], "gw") == 0 && argc >= 4) { grub_err_t err; route->is_gateway = 1; @@ -251,7 +269,7 @@ grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), route->is_gateway = 0; FOR_NET_NETWORK_LEVEL_INTERFACES (inter) - if (grub_strcmp (inter->name, args[2])) + if ( !grub_strcmp (inter->name, args[2])) break; if (!inter) diff --git a/include/grub/net.h b/include/grub/net.h index abb8a3167..18779dabe 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -31,6 +31,8 @@ struct grub_net_card; struct grub_net_card_driver { + struct grub_net_card_driver *next; + char *name; grub_err_t (*init) (struct grub_net_card *dev); grub_err_t (*fini) (struct grub_net_card *dev); grub_err_t (*send) (struct grub_net_card *dev,struct grub_net_buff *nb); @@ -66,7 +68,7 @@ struct grub_net_network_layer_interface /* Underlying protocol. */ struct grub_net_network_layer_protocol *protocol; struct grub_net_card *card; - union grub_net_network_layer_address address; + grub_net_network_layer_address_t address; void *data; }; @@ -121,7 +123,7 @@ grub_net_session_recv (struct grub_net_session *session, void *buf, return session->protocol->recv (session, buf, size); } -struct grub_net_network_layer_interface *grub_net_network_layer_interfaces; +extern struct grub_net_network_layer_interface *EXPORT_VAR(grub_net_network_layer_interfaces); static inline void grub_net_network_layer_interface_register (struct grub_net_network_layer_interface *inter) @@ -139,7 +141,7 @@ grub_net_network_layer_interface_unregister (struct grub_net_network_layer_inter #define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_layer_interfaces; var; var = var->next) -extern struct grub_net_route *grub_net_routes; +extern struct grub_net_route *EXPORT_VAR(grub_net_routes); static inline void grub_net_route_register (struct grub_net_route *route) @@ -157,7 +159,7 @@ grub_net_route_unregister (struct grub_net_route *route) #define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next) -extern struct grub_net_card *grub_net_cards; +extern struct grub_net_card *EXPORT_VAR(grub_net_cards); static inline void grub_net_card_register (struct grub_net_card *card) @@ -174,7 +176,26 @@ grub_net_card_unregister (struct grub_net_card *card) } #define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) +struct grub_net_card_driver *grub_net_card_drivers; +static inline void +grub_net_card_driver_register (struct grub_net_card_driver *driver) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_card_drivers), + GRUB_AS_LIST (driver)); +} + +static inline void +grub_net_card_driver_unregister (struct grub_net_card_driver *driver) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_card_drivers), + GRUB_AS_LIST (driver)); +} + +void ofdriver_ini(void); +void ofdriver_fini(void); + +#define FOR_NET_CARD_DRIVERS(var) for (var = grub_net_card_drivers; var; var = var->next) #define FOR_NET_NETWORK_LEVEL_PROTOCOLS(var) for ((var) = grub_net_network_layer_protocols; (var); (var) = (var)->next) diff --git a/include/grub/net/protocol.h b/include/grub/net/protocol.h index ffc3dd719..ce37404bc 100644 --- a/include/grub/net/protocol.h +++ b/include/grub/net/protocol.h @@ -1,6 +1,7 @@ #ifndef GRUB_PROTOCOL_HEADER #define GRUB_PROTOCOL_HEADER #include +#include #include #include #include @@ -60,7 +61,7 @@ struct grub_net_network_layer_protocol grub_uint16_t type; /* IANA Ethertype */ //grub_network_layer_protocol_id_t id; grub_err_t (*ntoa) (char *name, grub_net_network_layer_address_t *addr); - char * (*aton) (union grub_net_network_layer_address addr); + char * (*aton) (grub_net_network_layer_address_t addr); grub_err_t (*net_ntoa) (char *name, grub_net_network_layer_netaddress_t *addr); char * (*net_aton) (grub_net_network_layer_netaddress_t addr); @@ -87,7 +88,7 @@ struct grub_net_link_layer_protocol grub_uint16_t ethertype); }; -extern struct grub_net_network_layer_protocol *grub_net_network_layer_protocols; +extern struct grub_net_network_layer_protocol *EXPORT_VAR(grub_net_network_layer_protocols); typedef struct grub_net_protocol *grub_net_protocol_t; void grub_net_application_layer_protocol_register (struct grub_net_application_layer_protocol *prot); diff --git a/include/grub/net/type_net.h b/include/grub/net/type_net.h index a1717d6a7..f159b1de0 100644 --- a/include/grub/net/type_net.h +++ b/include/grub/net/type_net.h @@ -18,16 +18,16 @@ typedef enum }grub_net_protocol_id_t; -typedef union grub_net_network_layer_address +typedef union grub_net_network_layer_netaddress { grub_uint32_t ipv4; -} grub_net_network_layer_netaddress_t; +} grub_net_network_layer_address_t; -typedef union grub_net_network_layer_netaddress +typedef union grub_net_network_layer_address { struct { grub_uint32_t base; int masksize; } ipv4; -} grub_net_network_layer_address_t; +} grub_net_network_layer_netaddress_t; #endif diff --git a/net/ip.c b/net/ip.c index 142f33e70..8237603f2 100644 --- a/net/ip.c +++ b/net/ip.c @@ -68,8 +68,10 @@ send_ip_packet (struct grub_net_network_layer_interface *inf, grub_memcpy(nl_target_addr.addr, &(iph->dest), nl_target_addr.len); rc = arp_resolve(inf, trans_net_inf->inner_layer, &nl_target_addr, &ll_target_addr); grub_free(nl_target_addr.addr); - if (rc != GRUB_ERR_NONE) + if (rc != GRUB_ERR_NONE){ + grub_printf("Error in the ARP resolve.\n"); return rc; + } rc = trans_net_inf->inner_layer->link_prot->send(inf,trans_net_inf->inner_layer,nb,ll_target_addr, IP_ETHERTYPE); grub_free(ll_target_addr.addr); @@ -113,13 +115,45 @@ recv_ip_packet (struct grub_net_network_layer_interface *inf, return 0; } + +static grub_err_t +ipv4_ntoa (char *val, grub_net_network_layer_address_t *addr ) +{ + grub_uint8_t *p = (grub_uint8_t *) addr; + unsigned long t; + int i; + + for (i = 0; i < 4; i++) + { + t = grub_strtoul (val, (char **) &val, 0); + if (grub_errno) + return grub_errno; + + if (t & ~0xff) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); + + p[i] = (grub_uint8_t) t; + if (i != 3 && *val != '.') + return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); + + val++; + } + + val = val - 1; + if (*val != '\0') + return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); + + return GRUB_ERR_NONE; +} + static struct grub_net_network_layer_protocol grub_ipv4_protocol = { .name = "ipv4", .id = GRUB_NET_IPV4_ID, .type = IP_ETHERTYPE, .send = send_ip_packet, - .recv = recv_ip_packet + .recv = recv_ip_packet, + .ntoa = ipv4_ntoa }; void ipv4_ini(void) From 87fdc7e8d28f20f355240219ea7e7a580e0f7303 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Wed, 15 Sep 2010 13:23:23 -0300 Subject: [PATCH 051/406] Create Open firmware pseudo driver. Change ofnet.c to disknet.c and remove almost all ieee1275 specific code. Create grub_net_malloc to handle iee1275 memory issues in a temporary solution. --- conf/powerpc-ieee1275.rmk | 6 +- fs/{ieee1275/ofnet.c => netdisk.c} | 142 ++++++++------------------ include/grub/ieee1275/ieee1275.h | 10 +- include/grub/ieee1275/ofnet.h | 29 +----- include/grub/net/disknet.h | 5 + include/grub/net/ethernet.h | 15 ++- include/grub/net/ieee1275/interface.h | 9 -- include/grub/net/mem.h | 9 ++ kern/ieee1275/openfw.c | 64 ++++++++++++ net/drivers/ieee1275/ofdriver.c | 74 ++++++++++++++ net/ethernet.c | 9 +- net/i386/mem.c | 10 ++ net/ieee1275/interface.c | 46 --------- net/ieee1275/mem.c | 32 ++++++ net/protocol.c | 2 + 15 files changed, 272 insertions(+), 190 deletions(-) rename fs/{ieee1275/ofnet.c => netdisk.c} (77%) create mode 100644 include/grub/net/disknet.h create mode 100644 include/grub/net/mem.h create mode 100644 net/drivers/ieee1275/ofdriver.c create mode 100644 net/i386/mem.c delete mode 100644 net/ieee1275/interface.c create mode 100644 net/ieee1275/mem.c diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index f0faef489..a70a1e962 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -5,7 +5,7 @@ kernel_img_HEADERS += ieee1275/ieee1275.h \ command.h i18n.h env_private.h net/ip.h net/udp.h net/ethernet.h net/arp.h net/tftp.h\ - net/ieee1275/interface.h net/type_net.h net.h net/interface.h net/protocol.h net/netbuff.h + net/ieee1275/interface.h net/type_net.h net.h net/interface.h net/protocol.h net/netbuff.h net/mem.h # Programs pkglib_PROGRAMS = kernel.img @@ -23,8 +23,8 @@ kernel_img_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \ kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c \ kern/generic/millisleep.c kern/time.c \ symlist.c kern/$(target_cpu)/cache.S net/ip.c net/tftp.c net/udp.c net/ethernet.c net/arp.c \ - net/ieee1275/interface.c net/interface.c net/protocol.c net/netbuff.c \ - fs/ieee1275/ofnet.c + net/drivers/ieee1275/ofdriver.c net/interface.c net/protocol.c net/netbuff.c \ + fs/netdisk.c net/ieee1275/mem.c kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS += $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x200000,-Bstatic diff --git a/fs/ieee1275/ofnet.c b/fs/netdisk.c similarity index 77% rename from fs/ieee1275/ofnet.c rename to fs/netdisk.c index cf7eeb5b2..2f6e97d52 100644 --- a/fs/ieee1275/ofnet.c +++ b/fs/netdisk.c @@ -23,26 +23,25 @@ #include #include #include -#include -#include -#include #include #include #include #include #include -#include #include #include #include +#include +#include + +struct grub_net_card *grub_net_cards = NULL; +struct grub_net_network_layer_interface *grub_net_network_layer_interfaces = NULL; +struct grub_net_route *grub_net_routes = NULL; #define BUFFERADDR 0X00000000 #define BUFFERSIZE 0x02000000 #define U64MAXSIZE 18446744073709551615ULL - -//static grub_ieee1275_ihandle_t handle = 0; - static const char * find_sep (const char *name) { @@ -295,29 +294,45 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) return 1; } - // grub_printf("name = %s\n",name); +/*TESt*/ + // grub_printf("name = %s\n",name); + struct grub_net_card *card; + struct grub_ofnetcard_data *ofdata; + FOR_NET_CARDS(card) + { + grub_printf("card address = %x\n", (int) card); + grub_printf ("card name = %s\n", card->name); + ofdata = card->data; + grub_printf("card path = %s\n", (char *) ofdata->path); + grub_printf("card handle = %d\n", ofdata->handle); + } + grub_printf("card list address in disknet.c = %x\n",(int) grub_net_cards); + card = grub_net_cards; + grub_printf("card address = %x\n", (int) card); +/*TESt*/ + struct grub_net_protocol_stack *stack; struct grub_net_buff *pack; struct grub_net_application_transport_interface *app_interface; int file_size; char *datap; int amount = 0; - grub_addr_t found_addr; grub_netdisk_data_t netdisk_data = (grub_netdisk_data_t) file->device->disk->data; + // TODO: replace getting IP and MAC from bootp by routing functions struct grub_net_network_layer_interface net_interface; - struct grub_net_card net_card; struct grub_net_addr ila, lla; - ila.addr = (grub_uint8_t *) &(bootp_pckt->yiaddr); + ila.addr = (grub_uint8_t *) & (bootp_pckt->yiaddr); ila.len = 4; - lla.addr = (grub_uint8_t *) &(bootp_pckt->chaddr); + lla.addr = (grub_uint8_t *) & (bootp_pckt->chaddr); lla.len = 6; - net_card.ila = &ila; - net_card.lla = &lla; - net_interface.card = &net_card; // END TODO + card->ila = &ila; + card->lla = &lla; + net_interface.card = card; + if(! netdisk_data) return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments missing"); @@ -328,37 +343,35 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) app_interface = (struct grub_net_application_transport_interface *) stack->interface; app_interface->inner_layer->data = (void *) &(netdisk_data->server_ip); + pack = grub_netbuff_alloc (2048); grub_netbuff_reserve (pack,2048); + file_size = app_interface->app_prot->get_file_size(&net_interface,stack,pack,(char *) name); - for (found_addr = 0x800000; found_addr < + 2000 * 0x100000; found_addr += 0x100000) - { - if (grub_claimmap (found_addr , file_size) != -1) - break; - } - file->data = (void *) found_addr; + file->data = grub_net_malloc (file_size); grub_netbuff_clear(pack); grub_netbuff_reserve (pack,2048); + app_interface->app_prot->open (&net_interface,stack,pack,(char *) name); if (grub_errno != GRUB_ERR_NONE) goto error; do { - grub_netbuff_clear(pack); - grub_netbuff_reserve (pack,2048); app_interface->app_prot->recv (&net_interface,stack,pack); + if (grub_errno != GRUB_ERR_NONE) goto error; + if ((pack->tail - pack->data)) { - // file->data = grub_realloc(file->data,amount + pack->tail - pack->data); datap = (char *)file->data + amount; amount += (pack->tail - pack->data); - grub_memcpy(datap , pack->data, pack->tail - pack->data); + grub_memcpy (datap , pack->data, pack->tail - pack->data); } + grub_netbuff_clear(pack); grub_netbuff_reserve (pack,2048); app_interface->app_prot->send_ack (&net_interface,stack,pack); @@ -394,54 +407,6 @@ static struct grub_fs grub_ofnetfs_fs = .next = 0 }; -static char * -grub_ieee1275_get_devargs (const char *path) -{ - int len; - char *colon = grub_strchr (path, ':'); - len = colon - path; - if (! colon) - return 0; - - return grub_strndup (path,len); -} - -static int -grub_ofnet_detect (void) -{ - - char *devalias; - char bootpath[64]; /* XXX check length */ - grub_ieee1275_phandle_t root; - grub_uint32_t net_type; - - grub_ieee1275_finddevice ("/chosen", &grub_ieee1275_chosen); - if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath, - sizeof (bootpath), 0)) - { - /* Should never happen. */ - grub_printf ("/chosen/bootpath property missing!\n"); - return 0; - } - devalias = grub_ieee1275_get_aliasdevname (bootpath); - - if (grub_strncmp(devalias ,"net",3)) - return 0; - - grub_net = grub_malloc (sizeof *grub_net ); - grub_net->name = "net"; - grub_net->dev = grub_ieee1275_get_devargs (bootpath); - grub_ieee1275_finddevice ("/", &root); - grub_ieee1275_get_integer_property (root, "ibm,fw-net-compatibility", - &net_type, sizeof net_type, 0); - grub_printf("root = %d\n",root); - grub_printf("net_type= %d\n",net_type); - grub_net->type = net_type; - - return 1; -} - - #define IPMASK 0x000000FF #define IPSIZE 16 #define IPTEMPLATE "%d.%d.%d.%d" @@ -456,34 +421,17 @@ grub_ip2str (grub_uint32_t ip) return str_ip; } + void -grub_get_netinfo (grub_ofnet_t netinfo,grub_bootp_t packet) +grub_disknet_init(void) { - netinfo->sip = grub_ip2str(packet->siaddr); - netinfo->cip = grub_ip2str(packet->yiaddr); - netinfo->gat = grub_ip2str(packet->giaddr); - grub_printf("packet->siaddr = %x\n",packet->siaddr); - grub_printf("netinfo-> = %s\n",netinfo->sip); - grub_printf("packet->yiaddr = %x\n",packet->yiaddr); - grub_printf("netinfo-> = %s\n",netinfo->cip); - grub_printf("packet->giaddr = %x\n",packet->giaddr); - grub_printf("netinfo-> = %s\n",netinfo->gat); + + grub_disk_dev_register (&grub_ofnet_dev); + grub_fs_register (&grub_ofnetfs_fs); } + void -grub_ofnet_init(void) -{ - tftp_ini (); - bootp_pckt = grub_getbootp (); - if(grub_ofnet_detect ()) - { - grub_get_netinfo (grub_net, bootp_pckt ); - grub_disk_dev_register (&grub_ofnet_dev); - grub_fs_register (&grub_ofnetfs_fs); - card_open (); - } -} -void -grub_ofnet_fini(void) +grub_disknet_fini(void) { grub_fs_unregister (&grub_ofnetfs_fs); grub_disk_dev_unregister (&grub_ofnet_dev); diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index f4c8b4edf..8fb558fa7 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -24,7 +24,6 @@ #include #include -/* Maps a device alias to a pathname. */ struct grub_ieee1275_devalias { char *name; @@ -65,6 +64,13 @@ struct grub_ieee1275_common_hdr typedef grub_uint32_t grub_ieee1275_ihandle_t; typedef grub_uint32_t grub_ieee1275_phandle_t; +struct grub_ofnetcard_data +{ + char *path; + grub_ieee1275_ihandle_t handle; +}; + +/* Maps a device alias to a pathname. */ extern grub_ieee1275_phandle_t EXPORT_VAR(grub_ieee1275_chosen); extern grub_ieee1275_ihandle_t EXPORT_VAR(grub_ieee1275_mmu); extern int (* EXPORT_VAR(grub_ieee1275_entry_fn)) (void *); @@ -186,4 +192,6 @@ int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook) (struct grub_ieee1275_devalias * alias)); char *EXPORT_FUNC(grub_ieee1275_get_aliasdevname) (const char *path); +void EXPORT_FUNC(grub_ofnet_findcards) (void); +void EXPORT_FUNC(grub_ofnet_probecards) (void); #endif /* ! GRUB_IEEE1275_HEADER */ diff --git a/include/grub/ieee1275/ofnet.h b/include/grub/ieee1275/ofnet.h index a26c22235..ba4c62630 100644 --- a/include/grub/ieee1275/ofnet.h +++ b/include/grub/ieee1275/ofnet.h @@ -23,32 +23,9 @@ #include #include -extern void grub_ofnet_init(void); -extern void grub_ofnet_fini(void); +void grub_ofnet_init(void); +void grub_ofnet_fini(void); -/* -struct grub_net; - -struct grub_net_dev -{ - / The device name. / - const char *name; - - / FIXME: Just a template. / - int (*probe) (struct grub_net *net, const void *addr); - void (*reset) (struct grub_net *net); - int (*poll) (struct grub_net *net); - void (*transmit) (struct grub_net *net, const void *destip, - unsigned srcsock, unsigned destsock, const void *packet); - void (*disable) (struct grub_net *net); - - / The next net device. / - struct grub_net_dev *next; -}; -typedef struct grub_net_dev *grub_net_dev_t; - -struct grub_fs; -*/ struct grub_ofnet { /* The net name. */ @@ -85,7 +62,7 @@ struct grub_bootp { char file [128]; /* Boot filename */ // grub_uint32_t filesize ; /*File size (testing)*/ unsigned char vend [64]; -}; +}; typedef struct grub_bootp* grub_bootp_t; diff --git a/include/grub/net/disknet.h b/include/grub/net/disknet.h new file mode 100644 index 000000000..59aa2a320 --- /dev/null +++ b/include/grub/net/disknet.h @@ -0,0 +1,5 @@ +#ifndef GRUB_DISKNET_HEADER +#define GRUB_DISKNET_HEADER 1 + void grub_disknet_init(void); + void grub_disknet_fini(void); +#endif /* ! GRUB_NET_HEADER */ diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h index 9043a5f02..f4a6c22cf 100644 --- a/include/grub/net/ethernet.h +++ b/include/grub/net/ethernet.h @@ -10,9 +10,18 @@ struct etherhdr grub_uint16_t type; } __attribute__ ((packed)); -#define PCP (x) x & 0xe000 -#define CFI (x) x & 0x1000 -#define VID (x) x & 0x0fff +#define PCP(x) x & 0xe000 +#define CFI(x) x & 0x1000 +#define VID(x) x & 0x0fff +#define PRINT_ETH_ADDR(name,addr) grub_printf("%s %x:%x:%x:%x:%x:%x\n",\ + name,\ + addr[0],\ + addr[1],\ + addr[2],\ + addr[3],\ + addr[4],\ + addr[5]\ + ) struct llchdr { diff --git a/include/grub/net/ieee1275/interface.h b/include/grub/net/ieee1275/interface.h index 16f624c05..c369e35a6 100644 --- a/include/grub/net/ieee1275/interface.h +++ b/include/grub/net/ieee1275/interface.h @@ -6,14 +6,5 @@ #include #include - -grub_ofnet_t grub_net; - grub_bootp_t bootp_pckt; - -int send_card_buffer (struct grub_net_buff *pack); -int get_card_packet (struct grub_net_buff *pack); -int card_open (void); -int card_close (void); - #endif diff --git a/include/grub/net/mem.h b/include/grub/net/mem.h new file mode 100644 index 000000000..bbdac512b --- /dev/null +++ b/include/grub/net/mem.h @@ -0,0 +1,9 @@ +#ifndef GRUB_NETMM_H +#define GRUB_NETMM_H 1 + +#include +#include + +void *EXPORT_FUNC(grub_net_malloc) (grub_size_t size); + +#endif /* ! GRUB_MM_H */ diff --git a/kern/ieee1275/openfw.c b/kern/ieee1275/openfw.c index 337fc4b7e..2650ff3d4 100644 --- a/kern/ieee1275/openfw.c +++ b/kern/ieee1275/openfw.c @@ -23,6 +23,10 @@ #include #include #include +#include +#include +#include +#include enum grub_ieee1275_parse_type { @@ -490,3 +494,63 @@ grub_getbootp( void ) return packet; } +void grub_ofnet_findcards (void) +{ + struct grub_net_card *card; + int i = 0; + + auto int search_net_devices (struct grub_ieee1275_devalias *alias); + + int search_net_devices (struct grub_ieee1275_devalias *alias) + { + if ( !grub_strcmp (alias->type,"network") ) + { + + card = grub_malloc (sizeof (struct grub_net_card)); + struct grub_ofnetcard_data *ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data)); + ofdata->path = grub_strdup (alias->path); + card->data = ofdata; + card->name = grub_xasprintf("eth%d",i++); // grub_strdup (alias->name); + grub_net_card_register (card); + } + return 0; + } + + /*Look at all nodes for devices of the type network*/ + grub_ieee1275_devices_iterate (search_net_devices); + +} + +void grub_ofnet_probecards (void) +{ + struct grub_net_card *card; + struct grub_net_card_driver *driver; + + /*Assign correspondent driver for each device. */ + FOR_NET_CARDS (card) + { + FOR_NET_CARD_DRIVERS (driver) + { + if (driver->init(card) == GRUB_ERR_NONE) + { + card->driver = driver; + continue; + } + } + } +} + +void +grub_ofnet_init(void) +{ + + ofdriver_ini(); + grub_ofnet_findcards(); + grub_ofnet_probecards(); + + /*init tftp stack - will be handled by module subsystem in the future*/ + tftp_ini (); + /*get bootp packet - won't be needed in the future*/ + bootp_pckt = grub_getbootp (); + grub_disknet_init(); +} diff --git a/net/drivers/ieee1275/ofdriver.c b/net/drivers/ieee1275/ofdriver.c new file mode 100644 index 000000000..5f6c3c2f6 --- /dev/null +++ b/net/drivers/ieee1275/ofdriver.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include + +static +grub_err_t card_open (struct grub_net_card *dev) +{ + + struct grub_ofnetcard_data *data = dev->data; + return grub_ieee1275_open (data->path,&(data->handle)); +} + +static +grub_err_t card_close (struct grub_net_card *dev) +{ + + struct grub_ofnetcard_data *data = dev->data; + + if (data->handle) + grub_ieee1275_close (data->handle); + return GRUB_ERR_NONE; +} + +static +grub_err_t send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) +{ + + int actual; + struct grub_ofnetcard_data *data = dev->data; + + return grub_ieee1275_write (data->handle,pack->data,pack->tail - pack->data,&actual); +} + +static +grub_err_t get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pack) +{ + + int actual, rc; + struct grub_ofnetcard_data *data = dev->data; + grub_netbuff_clear(pack); + + do + { + rc = grub_ieee1275_read (data->handle,pack->data,1500,&actual); + + }while (actual <= 0 || rc < 0); + grub_netbuff_put (pack, actual); + + return GRUB_ERR_NONE; +} + +static struct grub_net_card_driver ofdriver = +{ + .name = "ofnet", + .init = card_open, + .fini = card_close, + .send = send_card_buffer, + .recv = get_card_packet + +}; + +void ofdriver_ini(void) +{ + grub_net_card_driver_register (&ofdriver); +} + +void ofdriver_fini(void) +{ + grub_net_card_driver_unregister (&ofdriver); +} + + + diff --git a/net/ethernet.c b/net/ethernet.c index 14bc41c5b..7b578abab 100644 --- a/net/ethernet.c +++ b/net/ethernet.c @@ -22,10 +22,10 @@ struct grub_net_addr target_addr, grub_uint16_t ethertype) eth = (struct etherhdr *) nb->data; grub_memcpy(eth->dst, target_addr.addr, target_addr.len); grub_memcpy(eth->src, bootp_pckt->chaddr, 6); + eth->type = ethertype; - return send_card_buffer(nb); -// return inf->card->driver->send(inf->card,nb); + return inf->card->driver->send (inf->card,nb); } @@ -42,12 +42,11 @@ grub_uint16_t ethertype) start_time = grub_get_time_ms(); while (1) { - get_card_packet (nb); + inf->card->driver->recv (inf->card,nb); eth = (struct etherhdr *) nb->data; type = eth->type; grub_netbuff_pull(nb,sizeof (*eth)); - // grub_printf("ethernet type 58 %x\n",type); - // grub_printf("ethernet eth->type 58 %x\n",type); + if (eth->type <=1500) { llch = (struct llchdr *) nb->data; diff --git a/net/i386/mem.c b/net/i386/mem.c new file mode 100644 index 000000000..d6c98ea80 --- /dev/null +++ b/net/i386/mem.c @@ -0,0 +1,10 @@ +#include +#include +#include +#include + + +void *grub_net_malloc (grub_size_t size) +{ + return grub_malloc (size); +} diff --git a/net/ieee1275/interface.c b/net/ieee1275/interface.c deleted file mode 100644 index 342044041..000000000 --- a/net/ieee1275/interface.c +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include -#include - -static grub_ieee1275_ihandle_t handle; -int card_open (void) -{ - - grub_ieee1275_open (grub_net->dev , &handle); - return 0; - -} - -int card_close (void) -{ - - if (handle) - grub_ieee1275_close (handle); - return 0; -} - - -int send_card_buffer (struct grub_net_buff *pack) -{ - - int actual; - grub_ieee1275_write (handle,pack->data,pack->tail - pack->data,&actual); - - return actual; -} - -int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) -{ - - int actual, rc; - pack->data = pack->tail = pack->head; - do - { - rc = grub_ieee1275_read (handle,pack->data,1500,&actual); - - }while (actual <= 0 || rc < 0); - grub_netbuff_put (pack, actual); - -// grub_printf("packsize %d\n",pack->tail - pack->data); - return 0;// sizeof (eth) + iph.len; -} diff --git a/net/ieee1275/mem.c b/net/ieee1275/mem.c new file mode 100644 index 000000000..416a04253 --- /dev/null +++ b/net/ieee1275/mem.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include +#include +#define TRASHOLD_SIZE 5 * 1024 * 1024 + +void *grub_net_malloc (grub_size_t size) +{ + + int found = 0; + grub_addr_t found_addr; + + if (size <= TRASHOLD_SIZE) + return grub_malloc (size); + + for (found_addr = 0x800000; found_addr < + 2000 * 0x100000; found_addr += 0x100000) + { + if (grub_claimmap (found_addr , size) != -1) + { + found = 1; + break; + } + } + + if (!found) + grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + + return found?(void *) found_addr:NULL; + +} diff --git a/net/protocol.c b/net/protocol.c index 05d4471d2..bdd7f3671 100644 --- a/net/protocol.c +++ b/net/protocol.c @@ -2,6 +2,8 @@ #include #include +struct grub_net_network_layer_protocol *grub_net_network_layer_protocols = NULL; + #define PROTOCOL_REGISTER_FUNCTIONS(layername) \ struct grub_net_##layername##_layer_protocol *grub_net_##layername##_layer_protocols;\ \ From 6b1b3423dd0d5c38d561d5b7ab5ea082ca7ef620 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 22 Sep 2010 17:14:14 +0200 Subject: [PATCH 052/406] Fix error handling in ofnet --- grub-core/net/drivers/ieee1275/ofnet.c | 42 +++++++++++++++----------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 064f3d280..ce5276efe 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -3,18 +3,21 @@ #include #include -static -grub_err_t card_open (struct grub_net_card *dev) +static grub_err_t +card_open (struct grub_net_card *dev) { - + int status; struct grub_ofnetcard_data *data = dev->data; - return grub_ieee1275_open (data->path,&(data->handle)); + status = grub_ieee1275_open (data->path,&(data->handle)); + + if (status) + return grub_error (GRUB_ERR_IO, "couldn't open network card"); + return GRUB_ERR_NONE; } -static -grub_err_t card_close (struct grub_net_card *dev) +static grub_err_t +card_close (struct grub_net_card *dev) { - struct grub_ofnetcard_data *data = dev->data; if (data->handle) @@ -22,18 +25,23 @@ grub_err_t card_close (struct grub_net_card *dev) return GRUB_ERR_NONE; } -static -grub_err_t send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) -{ - +static grub_err_t +send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) +{ int actual; + int status; struct grub_ofnetcard_data *data = dev->data; - return grub_ieee1275_write (data->handle,pack->data,pack->tail - pack->data,&actual); + status = grub_ieee1275_write (data->handle, pack->data, + pack->tail - pack->data, &actual); + + if (status) + return grub_error (GRUB_ERR_IO, "couldn't send network packet"); + return GRUB_ERR_NONE; } -static -grub_err_t get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pack) +static grub_err_t +get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pack) { int actual, rc; @@ -41,10 +49,8 @@ grub_err_t get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pac grub_netbuff_clear(pack); do - { - rc = grub_ieee1275_read (data->handle,pack->data,1500,&actual); - - }while (actual <= 0 || rc < 0); + rc = grub_ieee1275_read (data->handle, pack->data, 1500, &actual); + while (actual <= 0 || rc < 0); grub_netbuff_put (pack, actual); return GRUB_ERR_NONE; From 90451bb1c951bbc90f479084b28ddb1e09d8ac8d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 22 Sep 2010 17:14:43 +0200 Subject: [PATCH 053/406] networking in grub-emu --- grub-core/Makefile.core.def | 6 +++ grub-core/net/drivers/emu/emunet.c | 69 ++++++++++++++++++++++++++++++ include/grub/net.h | 6 ++- 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 grub-core/net/drivers/emu/emunet.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 5cacb6851..2f55ba5ec 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1398,3 +1398,9 @@ module = { ieee1275 = net/drivers/ieee1275/ofnet.c; enable = ieee1275; }; + +module = { + name = emunet; + emu = net/drivers/emu/emunet.c; + enable = ieee1275; +}; diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c new file mode 100644 index 000000000..8914a1d95 --- /dev/null +++ b/grub-core/net/drivers/emu/emunet.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include /* the L2 protocols */ +#include + +static grub_err_t +card_open (struct grub_net_card *dev) +{ + dev->data_num = socket (AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (dev->data_num < 0) + return grub_error (GRUB_ERR_IO, "couldn't open packet interface"); + return GRUB_ERR_NONE; +} + +static grub_err_t +card_close (struct grub_net_card *dev) +{ + close (dev->data_num); + return GRUB_ERR_NONE; +} + +static grub_err_t +send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) +{ + ssize_t actual; + + actual = write (dev->data_num, pack->data, pack->tail - pack->data); + if (actual < 0) + return grub_error (GRUB_ERR_IO, "couldn't send packets"); + + return GRUB_ERR_NONE; +} + +static grub_err_t +get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pack) +{ + ssize_t actual; + + grub_netbuff_clear(pack); + actual = read (dev->data_num, pack->data, 1500); + if (actual < 0) + return grub_error (GRUB_ERR_IO, "couldn't receive packets"); + grub_netbuff_put (pack, actual); + + return GRUB_ERR_NONE; +} + +static struct grub_net_card_driver emudriver = +{ + .name = "emu", + .init = card_open, + .fini = card_close, + .send = send_card_buffer, + .recv = get_card_packet +}; + +GRUB_MOD_INIT(emunet) +{ + grub_net_card_driver_register (&emudriver); +} + +GRUB_MODE_FINI(emunet) +{ + grub_net_card_driver_unregister (&emudriver); +} + + + diff --git a/include/grub/net.h b/include/grub/net.h index ad553a69a..de188f615 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -84,7 +84,11 @@ struct grub_net_card struct grub_net_card_driver *driver; grub_net_link_level_address_t default_address; grub_net_card_flags_t flags; - void *data; + union + { + void *data; + int data_num; + }; }; struct grub_net_network_level_interface; From ce3a2ec0256a6442cc9a3b47a6d218baf3412c39 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 22 Sep 2010 20:34:20 +0200 Subject: [PATCH 054/406] Remove some dead code --- grub-core/Makefile.core.def | 1 - grub-core/net/arp.c | 3 +- grub-core/net/ethernet.c | 1 - grub-core/net/interface.c | 37 ------------------- grub-core/net/ip.c | 2 -- grub-core/net/netbuff.c | 2 +- grub-core/net/tftp.c | 2 -- grub-core/net/udp.c | 3 -- include/grub/net.h | 3 +- include/grub/net/arp.h | 1 - include/grub/net/interface.h | 70 ------------------------------------ include/grub/net/protocol.h | 9 ----- include/grub/net/type_net.h | 33 ----------------- 13 files changed, 3 insertions(+), 164 deletions(-) delete mode 100644 grub-core/net/interface.c delete mode 100644 include/grub/net/interface.h delete mode 100644 include/grub/net/protocol.h delete mode 100644 include/grub/net/type_net.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index d48c5d505..49dbd3f60 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1438,7 +1438,6 @@ module = { common = net/udp.c; common = net/ethernet.c; common = net/arp.c; - common = net/interface.c; common = net/netbuff.c; }; diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index 5e10938ae..541b89411 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -92,7 +91,7 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, return GRUB_ERR_NONE; } current_time = grub_get_time_ms(); - if (current_time - start_time > TIMEOUT_TIME_MS) + if (current_time - start_time > 3000) break; } while (! entry); grub_netbuff_clear(nb); diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index d3a34aec6..a40e1f795 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include diff --git a/grub-core/net/interface.c b/grub-core/net/interface.c deleted file mode 100644 index f17b3e66b..000000000 --- a/grub-core/net/interface.c +++ /dev/null @@ -1,37 +0,0 @@ -/*#include - -#define INTERFACE_REGISTER_FUNCTIONS(layerprevious,layernext) \ -struct grub_net_##layername_layer_protocol *grub_net_##layername_layer_protocols;\ -\ -void grub_net_##layerprevious_##layernext_interface_register (struct grub_net_##layername_layer_protocol *prot)\ -{\ - grub_list_push (GRUB_AS_LIST_P (&grub_net_##layername_layer_protocols),\ - GRUB_AS_LIST (prot));\ -}\ -\ -void grub_net_##layerprevious_##layernext_interface_unregister (struct grub_net_##layername_layer_protocol *prot);\ -{\ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_##layername_layer_protocols),\ - GRUB_AS_LIST (prot));\ -}\ - -INTERFACE_REGISTER_FUNCTIONS("application","transport"); -INTERFACE_REGISTER_FUNCTIONS("transport","network"); -INTERFACE_REGISTER_FUNCTIONS("network","link"); -INTERFACE_REGISTER_FUNCTIONS("link");*/ - -#include -#include -struct grub_net_protocol_stack - *grub_net_protocol_stack_get (char *name) -{ - struct grub_net_protocol_stack *p; - - for (p = grub_net_protocol_stacks; p; p = p->next) - { - if (!grub_strcmp(p->name,name)) - return p; - } - - return NULL; -} diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 264195ad3..023564a5a 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -2,8 +2,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c index 4f6a1da84..cc366ae09 100644 --- a/grub-core/net/netbuff.c +++ b/grub-core/net/netbuff.c @@ -73,7 +73,7 @@ struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len ) len = ALIGN_UP (len,NETBUFF_ALIGN); data = grub_memalign (NETBUFF_ALIGN, len + sizeof (*nb)); - nb = (struct grub_net_buff *) ((int)data + len); + nb = (struct grub_net_buff *) ((grub_uint8_t *) data + len); nb->head = nb->data = nb->tail = data; nb->end = (char *) nb; diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index bb518b78f..b9e3f49c4 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -4,8 +4,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 27e23e826..a73431f83 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -1,10 +1,7 @@ #include #include #include -#include #include -#include -#include #include grub_err_t diff --git a/include/grub/net.h b/include/grub/net.h index de188f615..20bf3c0e6 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -23,9 +23,8 @@ #include #include #include +#include #include -#include -#include typedef struct grub_fs *grub_net_app_level_t; diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h index e547669a2..1475086e4 100644 --- a/include/grub/net/arp.h +++ b/include/grub/net/arp.h @@ -2,7 +2,6 @@ #define GRUB_NET_ARP_HEADER 1 #include #include -#include /* IANA ARP constant to define hardware type as ethernet */ #define ARPHRD_ETHERNET 1 diff --git a/include/grub/net/interface.h b/include/grub/net/interface.h deleted file mode 100644 index cf24dd22e..000000000 --- a/include/grub/net/interface.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef GRUB_INTERFACE_HEADER -#define GRUB_INTERFACE_HEADER -//#include -#include -#include -#include - -struct grub_net_protocol_stack -{ - struct grub_net_protocol_stack *next; - char *name; - grub_net_protocol_id_t id; - void *interface; -}; - -struct grub_net_application_transport_interface -{ - struct grub_net_transport_network_interface *inner_layer; - void *data; - struct grub_net_application_layer_protocol *app_prot; - struct grub_net_transport_layer_protocol *trans_prot; -}; - -struct grub_net_transport_network_interface -{ - struct grub_net_network_link_interface *inner_layer; - void *data; - struct grub_net_transport_layer_protocol *trans_prot; - struct grub_net_network_layer_protocol *net_prot; -}; - -struct grub_net_network_link_interface -{ - void *data; - struct grub_net_network_layer_protocol *net_prot; - struct grub_net_link_layer_protocol *link_prot; -}; - - -struct grub_net_protocol_stack *grub_net_protocol_stacks; -static inline void -grub_net_stack_register (struct grub_net_protocol_stack *stack) -{ - - grub_list_push (GRUB_AS_LIST_P (&grub_net_protocol_stacks), - GRUB_AS_LIST (stack)); -} -/* -void grub_net_stack_unregister (struct grub_net_protocol_stack *stack) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_protocol_stacks), - GRUB_AS_LIST (stack)); -}*/ - -struct grub_net_protocol_stack *grub_net_protocol_stack_get (char *name); - -/* -static inline void -grub_net_interface_application_transport_register (struct grub_net_application_transport_interface); -static inline void -grub_net_interface_application_transport_unregister (struct grub_net_application_transport_interface); -static inline void -grub_net_interface_transport_network_register (struct grub_net_transport_network_interface); -static inline void -grub_net_interface_transport_network_unregister (struct grub_net_transport_network_interface); -static inline void -grub_net_interface_network_link_register (struct grub_net_network_link_interface); -static inline void -grub_net_interface_network_link_unregister (struct grub_net_network_link_interface);*/ -#endif diff --git a/include/grub/net/protocol.h b/include/grub/net/protocol.h deleted file mode 100644 index da54b073f..000000000 --- a/include/grub/net/protocol.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef GRUB_PROTOCOL_HEADER -#define GRUB_PROTOCOL_HEADER -#include -#include -#include -#include -#include - -#endif diff --git a/include/grub/net/type_net.h b/include/grub/net/type_net.h deleted file mode 100644 index f159b1de0..000000000 --- a/include/grub/net/type_net.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef GRUB_TYPES_NET_HEADER -#define GRUB_TYPES_NET_HEADER 1 -#include - - -#define UDP_PCKT 0x11 -#define IP_PCKT 0x0800 -#define TIMEOUT_TIME_MS 3*1000 -typedef enum -{ - GRUB_NET_TFTP_ID, - GRUB_NET_UDP_ID, - GRUB_NET_IPV4_ID, - GRUB_NET_IPV6_ID, - GRUB_NET_ETHERNET_ID, - GRUB_NET_ARP_ID, - GRUB_NET_DHCP_ID -}grub_net_protocol_id_t; - - -typedef union grub_net_network_layer_netaddress -{ - grub_uint32_t ipv4; -} grub_net_network_layer_address_t; - -typedef union grub_net_network_layer_address -{ - struct { - grub_uint32_t base; - int masksize; - } ipv4; -} grub_net_network_layer_netaddress_t; -#endif From 04d22dddd985e49779fbdd570d1b4f0847dc4347 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Sep 2010 00:45:39 +0200 Subject: [PATCH 055/406] Fix a bunch of net issues --- grub-core/net/arp.c | 85 ++++++++-------- grub-core/net/drivers/emu/emunet.c | 84 ++++++++++------ grub-core/net/ethernet.c | 14 +-- grub-core/net/ip.c | 11 +- grub-core/net/net.c | 6 +- grub-core/net/tftp.c | 155 +++++++++++------------------ include/grub/net/arp.h | 12 +-- include/grub/net/ethernet.h | 8 ++ include/grub/net/ip.h | 2 - 9 files changed, 181 insertions(+), 196 deletions(-) diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index 541b89411..c7b5d0573 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -6,7 +6,7 @@ #include #include -static struct arp_entry arp_table[SIZE_ARP_TABLE]; +static struct arp_entry arp_table[10]; static grub_int8_t new_table_entry = -1; static @@ -19,8 +19,8 @@ void arp_init_table(void) static struct arp_entry * arp_find_entry (const grub_net_network_level_address_t *proto) { - grub_uint8_t i; - for(i=0;i < SIZE_ARP_TABLE; i++) + unsigned i; + for(i = 0; i < ARRAY_SIZE (arp_table); i++) { if(arp_table[i].avail == 1 && arp_table[i].nl_address.ipv4 == proto->ipv4) @@ -48,24 +48,26 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, return GRUB_ERR_NONE; } /* Build a request packet */ - nb = grub_malloc (2048); + nb = grub_netbuff_alloc (2048); + if (!nb) + return grub_errno; grub_netbuff_reserve(nb, 2048); grub_netbuff_push(nb, sizeof(*arp_header) + 2 * (6 + 6)); arp_header = (struct arphdr *)nb->data; - arp_header->hrd = 0; - arp_header->pro = 0; + arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET); + arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP); arp_header->hln = 6; - arp_header->pln = 6; - arp_header->op = ARP_REQUEST; + arp_header->pln = 4; + arp_header->op = grub_cpu_to_be16 (ARP_REQUEST); aux = (grub_uint8_t *)arp_header + sizeof(*arp_header); /* Sender hardware address */ grub_memcpy(aux, &inf->hwaddress.mac, 6); aux += 6; /* Sender protocol address */ grub_memcpy(aux, &inf->address.ipv4, 4); - aux += 6; + aux += 4; /* Target hardware address */ - for(i=0; i < 6; i++) + for(i = 0; i < 6; i++) aux[i] = 0x00; aux += 6; /* Target protocol address */ @@ -73,7 +75,7 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, grub_memset (&target_hw_addr.mac, 0xff, 6); - send_ethernet_packet (inf, nb, target_hw_addr, ARP_ETHERTYPE); + send_ethernet_packet (inf, nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); grub_netbuff_clear(nb); grub_netbuff_reserve(nb, 2048); @@ -81,7 +83,7 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, start_time = grub_get_time_ms(); do { - grub_net_recv_ethernet_packet (inf, nb, ARP_ETHERTYPE); + grub_net_recv_ethernet_packet (inf, nb, GRUB_NET_ETHERTYPE_ARP); /* Now check cache table again */ entry = arp_find_entry(proto_addr); if (entry) @@ -90,7 +92,7 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, grub_netbuff_clear(nb); return GRUB_ERR_NONE; } - current_time = grub_get_time_ms(); + current_time = grub_get_time_ms(); if (current_time - start_time > 3000) break; } while (! entry); @@ -99,17 +101,16 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, } grub_err_t -grub_net_arp_receive(struct grub_net_network_level_interface *inf, - struct grub_net_buff *nb) +grub_net_arp_receive (struct grub_net_network_level_interface *inf, + struct grub_net_buff *nb) { struct arphdr *arp_header = (struct arphdr *)nb->data; struct arp_entry *entry; - grub_uint8_t merge = 0; grub_uint8_t *sender_hardware_address, *sender_protocol_address; grub_uint8_t *target_hardware_address, *target_protocol_address; grub_net_network_level_address_t hwaddress; - sender_hardware_address = (grub_uint8_t *)arp_header + sizeof(*arp_header); + sender_hardware_address = (grub_uint8_t *) arp_header + sizeof(*arp_header); sender_protocol_address = sender_hardware_address + arp_header->hln; target_hardware_address = sender_protocol_address + arp_header->pln; target_protocol_address = target_hardware_address + arp_header->hln; @@ -118,40 +119,36 @@ grub_net_arp_receive(struct grub_net_network_level_interface *inf, entry = arp_find_entry(&hwaddress); /* Update sender hardware address */ if (entry) + grub_memcpy(entry->ll_address.mac, sender_hardware_address, 6); + else { - grub_memcpy(entry->ll_address.mac, sender_hardware_address, 6); - merge = 1; - } - /* Am I the protocol address target? */ - if (! grub_memcmp(target_protocol_address, inf->hwaddress.mac, 6)) - { - /* Add sender to cache table */ - if (! merge) - { + /* Add sender to cache table */ if (new_table_entry == -1) - arp_init_table(); + arp_init_table(); entry = &(arp_table[new_table_entry]); entry->avail = 1; grub_memcpy(&entry->nl_address.ipv4, sender_protocol_address, 4); grub_memcpy(entry->ll_address.mac, sender_hardware_address, 6); new_table_entry++; - if (new_table_entry == SIZE_ARP_TABLE) - new_table_entry = 0; - } - if (arp_header->op == ARP_REQUEST) - { - grub_net_link_level_address_t aux; - /* Swap hardware fields */ - grub_memcpy(target_hardware_address, sender_hardware_address, arp_header->hln); - grub_memcpy(sender_hardware_address, inf->hwaddress.mac, 6); - grub_memcpy(aux.mac, sender_protocol_address, 6); - grub_memcpy(sender_protocol_address, target_protocol_address, arp_header->pln); - grub_memcpy(target_protocol_address, aux.mac, arp_header->pln); - /* Change operation to REPLY and send packet */ - arp_header->op = ARP_REPLY; - grub_memcpy (aux.mac, target_hardware_address, 6); - send_ethernet_packet (inf, nb, aux, ARP_ETHERTYPE); - } + if (new_table_entry == ARRAY_SIZE (arp_table)) + new_table_entry = 0; + } + + /* Am I the protocol address target? */ + if (grub_memcmp(target_protocol_address, inf->hwaddress.mac, 6) == 0 + && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) + { + grub_net_link_level_address_t aux; + /* Swap hardware fields */ + grub_memcpy(target_hardware_address, sender_hardware_address, arp_header->hln); + grub_memcpy(sender_hardware_address, inf->hwaddress.mac, 6); + grub_memcpy(aux.mac, sender_protocol_address, 6); + grub_memcpy(sender_protocol_address, target_protocol_address, arp_header->pln); + grub_memcpy(target_protocol_address, aux.mac, arp_header->pln); + /* Change operation to REPLY and send packet */ + arp_header->op = grub_be_to_cpu16 (ARP_REPLY); + grub_memcpy (aux.mac, target_hardware_address, 6); + send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP); } return GRUB_ERR_NONE; } diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c index 8914a1d95..9e4e66dce 100644 --- a/grub-core/net/drivers/emu/emunet.c +++ b/grub-core/net/drivers/emu/emunet.c @@ -1,68 +1,92 @@ + +#include #include #include -#include -#include /* the L2 protocols */ #include +#include +#include +#include +#include +#include +#include +#include + +static int fd; static grub_err_t -card_open (struct grub_net_card *dev) -{ - dev->data_num = socket (AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (dev->data_num < 0) - return grub_error (GRUB_ERR_IO, "couldn't open packet interface"); - return GRUB_ERR_NONE; -} - -static grub_err_t -card_close (struct grub_net_card *dev) -{ - close (dev->data_num); - return GRUB_ERR_NONE; -} - -static grub_err_t -send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) +send_card_buffer (struct grub_net_card *dev __attribute__ ((unused)), + struct grub_net_buff *pack) { ssize_t actual; - actual = write (dev->data_num, pack->data, pack->tail - pack->data); + actual = write (fd, pack->data, pack->tail - pack->data); if (actual < 0) return grub_error (GRUB_ERR_IO, "couldn't send packets"); return GRUB_ERR_NONE; } -static grub_err_t -get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pack) +static grub_size_t +get_card_packet (struct grub_net_card *dev __attribute__ ((unused)), + struct grub_net_buff *pack) { ssize_t actual; grub_netbuff_clear(pack); - actual = read (dev->data_num, pack->data, 1500); + actual = read (fd, pack->data, 1500); if (actual < 0) - return grub_error (GRUB_ERR_IO, "couldn't receive packets"); + { + grub_error (GRUB_ERR_IO, "couldn't receive packets"); + return -1; + } grub_netbuff_put (pack, actual); - return GRUB_ERR_NONE; + return actual; } static struct grub_net_card_driver emudriver = { .name = "emu", - .init = card_open, - .fini = card_close, .send = send_card_buffer, .recv = get_card_packet }; +static struct grub_net_card emucard = +{ + .name = "emu0", + .driver = &emudriver, + .default_address = { + .type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET, + { .mac = { 0, 1, 2, 3, 4, 5} } + }, + .flags = 0 +}; + GRUB_MOD_INIT(emunet) { - grub_net_card_driver_register (&emudriver); + struct ifreq ifr; + // char fullname[64]; + fd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK); + if (fd < 0) + return; + grub_memset (&ifr, 0, sizeof (ifr)); + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + if (ioctl (fd, TUNSETIFF, &ifr) < 0) + { + close (fd); + fd = -1; + return; + } + grub_net_card_register (&emucard); } -GRUB_MODE_FINI(emunet) +GRUB_MOD_FINI(emunet) { - grub_net_card_driver_unregister (&emudriver); + if (fd >= 0) + { + close (fd); + grub_net_card_unregister (&emucard); + } } diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index a40e1f795..cbda4c875 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -38,10 +38,10 @@ grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf, inf->card->driver->recv (inf->card, nb); eth = (struct etherhdr *) nb->data; - type = eth->type; + type = grub_be_to_cpu16 (eth->type); grub_netbuff_pull(nb,sizeof (*eth)); - if (eth->type <=1500) + if (type <= 1500) { llch = (struct llchdr *) nb->data; type = llch->dsap & LLCADDRMASK; @@ -55,14 +55,10 @@ grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf, } /* ARP packet */ - if (type == ARP_ETHERTYPE) - { - grub_net_arp_receive(inf, nb); - if (ethertype == ARP_ETHERTYPE) - return GRUB_ERR_NONE; - } + if (type == GRUB_NET_ETHERTYPE_ARP) + grub_net_arp_receive(inf, nb); /* IP packet */ - else if(type == IP_ETHERTYPE && ethertype == IP_ETHERTYPE) + if(type == GRUB_NET_ETHERTYPE_IP && ethertype == GRUB_NET_ETHERTYPE_IP) return GRUB_ERR_NONE; return GRUB_ERR_NONE; diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 023564a5a..9a96ef532 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -54,7 +54,7 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, if (err) return err; - return send_ethernet_packet (inf, nb, ll_target_addr, IP_ETHERTYPE); + return send_ethernet_packet (inf, nb, ll_target_addr, GRUB_NET_ETHERTYPE_IP); } static int @@ -84,8 +84,11 @@ ip_filter (struct grub_net_buff *nb, grub_err_t grub_net_recv_ip_packets (struct grub_net_network_level_interface *inf) { - struct grub_net_buff nb; - grub_net_recv_ethernet_packet (inf, &nb, IP_ETHERTYPE); - ip_filter (&nb, inf); + struct grub_net_buff *nb; + nb = grub_netbuff_alloc (2048); + if (!nb) + return grub_errno; + grub_net_recv_ethernet_packet (inf, nb, GRUB_NET_ETHERTYPE_IP); + ip_filter (nb, inf); return GRUB_ERR_NONE; } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 5205e1938..54663f4b0 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -92,7 +92,7 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest) *ip = grub_cpu_to_le32 (newip); if (rest) *rest = ptr - 1; - return 0; + return 1; } static int @@ -341,7 +341,7 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected")); FOR_NET_CARDS (card) - if (grub_strcmp (card->name, args[1])) + if (grub_strcmp (card->name, args[1]) == 0) break; if (card == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found")); @@ -464,7 +464,7 @@ grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), struct grub_net_network_level_interface *inter; FOR_NET_NETWORK_LEVEL_INTERFACES (inter) - if (grub_strcmp (inter->name, args[2])) + if (grub_strcmp (inter->name, args[2]) == 0) break; if (!inter) diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index b9e3f49c4..16b60eeb6 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -9,60 +9,15 @@ #include #include -struct { - int block_size; - int size; -} tftp_file; -static int block; - - -static char *get_tok_val(char **tok, char **val, char **str_opt,char *end); -static void process_option(char *tok, char *val); - -static char * -get_tok_val(char **tok, char **val,char **str_opt,char *end) -{ - char *p = *str_opt; - *tok = p; - p += grub_strlen(p) + 1; - - if(p > end) - return NULL; - - *val = p; - p += grub_strlen(p) + 1; - *str_opt = p; - return *tok; -} - -static void -process_option(char *tok, char *val) -{ - if (!grub_strcmp(tok,"blksize")) - { - tftp_file.block_size = grub_strtoul (val,NULL,0); - return; - } - - if (!grub_strcmp(tok,"tsize")) - { - tftp_file.size = grub_strtoul (val,NULL,0); - return; - } - -} - -//void tftp_open (char *options); - -/*send read request*/ static grub_err_t tftp_open (struct grub_file *file, const char *filename) { struct tftphdr *tftph; char *rrq; + char *ptr; int rrqlen; int hdrlen; - struct grub_net_buff nb; + struct grub_net_buff *nb; grub_net_network_level_address_t addr; grub_err_t err; @@ -70,29 +25,28 @@ tftp_open (struct grub_file *file, const char *filename) + sizeof ("tftp,") - 1, &addr); if (err) return err; - - grub_memset (&nb, 0, sizeof (nb)); - grub_netbuff_push (&nb,sizeof (*tftph)); - tftph = (struct tftphdr *) nb.data; + nb = grub_netbuff_alloc (2048); + if (!nb) + return grub_errno; + + grub_netbuff_reserve (nb,2048); + grub_netbuff_push (nb,sizeof (*tftph)); + + tftph = (struct tftphdr *) nb->data; rrq = (char *) tftph->u.rrq; rrqlen = 0; - tftph->opcode = TFTP_RRQ; + tftph->opcode = grub_cpu_to_be16 (TFTP_RRQ); grub_strcpy (rrq, filename); rrqlen += grub_strlen (filename) + 1; rrq += grub_strlen (filename) + 1; - /*passar opcoes como parametro ou usar default?*/ grub_strcpy (rrq,"octet"); rrqlen += grub_strlen ("octet") + 1; rrq += grub_strlen ("octet") + 1; - //grub_strcpy (rrq,"netascii"); - //rrqlen += grub_strlen ("netascii") + 1; - //rrq += grub_strlen ("netascii") + 1; - grub_strcpy (rrq,"blksize"); rrqlen += grub_strlen("blksize") + 1; rrq += grub_strlen ("blksize") + 1; @@ -107,29 +61,53 @@ tftp_open (struct grub_file *file, const char *filename) grub_strcpy (rrq,"0"); rrqlen += grub_strlen ("0") + 1; - rrq += grub_strlen ("0") + 1; + rrq += grub_strlen ("0") + 1; hdrlen = sizeof (tftph->opcode) + rrqlen; - grub_netbuff_unput (&nb,nb.tail - (nb.data+hdrlen)); + grub_netbuff_unput (nb,nb->tail - (nb->data+hdrlen)); - grub_net_send_udp_packet (&addr, - &nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT); + err = grub_net_send_udp_packet (&addr, + nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT); + if (err) + return err; - grub_net_send_udp_packet (&addr, &nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT); - /*Receive OACK*/ - grub_netbuff_clear (&nb); - grub_netbuff_reserve (&nb,2048); - file->size = tftp_file.size; + /* Receive OACK. */ + grub_netbuff_clear (nb); + grub_netbuff_reserve (nb,2048); - return grub_net_recv_udp_packet (&addr, &nb, - TFTP_CLIENT_PORT, TFTP_SERVER_PORT); + do + { + err = grub_net_recv_udp_packet (&addr, nb, + TFTP_CLIENT_PORT, TFTP_SERVER_PORT); + if (err) + return err; + } + while (nb->tail == nb->data); + + file->size = 0; + + for (ptr = nb->data; ptr < nb->tail; ) + grub_printf ("%02x ", *ptr); + + for (ptr = nb->data; ptr < nb->tail; ) + { + if (grub_memcmp (ptr, "tsize\0=", sizeof ("tsize\0=") - 1) == 0) + { + file->size = grub_strtoul (ptr + sizeof ("tsize\0=") - 1, 0, 0); + grub_errno = GRUB_ERR_NONE; + } + while (ptr < nb->tail && *ptr) + ptr++; + ptr++; + } + return GRUB_ERR_NONE; } static grub_ssize_t tftp_receive (struct grub_file *file, char *buf, grub_size_t len) { struct tftphdr *tftph; - char *token,*value,*temp; + // char *token,*value,*temp; grub_err_t err; grub_net_network_level_address_t addr; struct grub_net_buff nb; @@ -143,38 +121,21 @@ tftp_receive (struct grub_file *file, char *buf, grub_size_t len) TFTP_CLIENT_PORT, TFTP_SERVER_PORT); tftph = (struct tftphdr *) nb.data; - switch (tftph->opcode) + switch (grub_be_to_cpu16 (tftph->opcode)) { - case TFTP_OACK: - /*process oack packet*/ - temp = (char *) tftph->u.oack.data; - while(get_tok_val(&token,&value,&temp,nb.tail)) - { - process_option(token,value); - } - - //buff_clean - grub_netbuff_clear(&nb); - // grub_printf("OACK---------------------------------------------------------\n"); - //grub_printf("block_size=%d\n",tftp_file.block_size); - // grub_printf("file_size=%d\n",tftp_file.size); - // grub_printf("OACK---------------------------------------------------------\n"); - block = 0; - break; case TFTP_DATA: grub_netbuff_pull (&nb,sizeof (tftph->opcode) + sizeof (tftph->u.data.block)); - if (tftph->u.data.block == block + 1) - { - block = tftph->u.data.block; + // if (tftph->u.data.block == block + 1) + //{ + // block = tftph->u.data.block; grub_memcpy (buf, nb.data, len); - } - else - grub_netbuff_clear(&nb); - break; + //} + //else + //grub_netbuff_clear(&nb); + break; case TFTP_ERROR: grub_netbuff_clear (&nb); - return grub_error (GRUB_ERR_ACCESS_DENIED, (char *)tftph->u.err.errmsg); - break; + return grub_error (GRUB_ERR_IO, (char *)tftph->u.err.errmsg); } nb.data = nb.tail = nb.end; @@ -182,8 +143,8 @@ tftp_receive (struct grub_file *file, char *buf, grub_size_t len) grub_netbuff_push (&nb,sizeof (tftph->opcode) + sizeof (tftph->u.ack.block)); tftph = (struct tftphdr *) nb.data; - tftph->opcode = TFTP_ACK; - tftph->u.ack.block = block; + tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); + // tftph->u.ack.block = block; return grub_net_send_udp_packet (&addr, &nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT); } diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h index 1475086e4..691fda307 100644 --- a/include/grub/net/arp.h +++ b/include/grub/net/arp.h @@ -3,13 +3,11 @@ #include #include -/* IANA ARP constant to define hardware type as ethernet */ -#define ARPHRD_ETHERNET 1 -/* IANA Ethertype */ -#define ARP_ETHERTYPE 0x806 - -/* Size for cache table */ -#define SIZE_ARP_TABLE 5 +enum +{ +/* IANA ARP constant to define hardware type as ethernet. */ + GRUB_NET_ARPHRD_ETHERNET = 1 +}; /* ARP header operation codes */ #define ARP_REQUEST 1 diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h index b4f07992b..7a0235be6 100644 --- a/include/grub/net/ethernet.h +++ b/include/grub/net/ethernet.h @@ -38,6 +38,14 @@ struct snaphdr grub_uint16_t type; } __attribute__ ((packed)); +/* IANA Ethertype */ +enum +{ + GRUB_NET_ETHERTYPE_IP = 0x0800, + GRUB_NET_ETHERTYPE_ARP = 0x0806 +}; + + grub_err_t send_ethernet_packet (struct grub_net_network_level_interface *inf, struct grub_net_buff *nb, diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index 765d8005e..6f748bbf3 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -2,8 +2,6 @@ #define GRUB_NET_IP_HEADER 1 #include -#define IP_ETHERTYPE 0x800 /* IANA Ethertype */ - struct iphdr { grub_uint8_t verhdrlen; grub_uint8_t service; From a06eb03ad020dd530f635e2936ea29270e222c47 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 13 Nov 2010 21:27:08 +0100 Subject: [PATCH 056/406] Support long command lines as per 2.06 Linux boot protocol --- grub-core/loader/i386/linux.c | 19 ++++++++++++++----- grub-core/loader/i386/pc/linux.c | 25 +++++++++++++++++-------- include/grub/i386/linux.h | 5 ++++- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index de4bec106..bdf66c6f6 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -54,7 +54,6 @@ #endif #define GRUB_LINUX_CL_OFFSET 0x1000 -#define GRUB_LINUX_CL_END_OFFSET 0x2000 static grub_dl_t my_mod; @@ -71,6 +70,7 @@ static grub_uint32_t prot_mode_pages; static grub_uint32_t initrd_pages; static struct grub_relocator *relocator = NULL; static void *efi_mmap_buf; +static grub_size_t maximal_cmdline_size; #ifdef GRUB_MACHINE_EFI static grub_efi_uintn_t efi_mmap_size; #else @@ -185,7 +185,7 @@ allocate_pages (grub_size_t prot_size) grub_err_t err; /* Make sure that each size is aligned to a page boundary. */ - real_size = GRUB_LINUX_CL_END_OFFSET; + real_size = GRUB_LINUX_CL_OFFSET + maximal_cmdline_size; prot_size = page_align (prot_size); mmap_size = find_mmap_size (); @@ -630,6 +630,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), goto fail; } + if (grub_le_to_cpu16 (lh.version) >= 0x0206) + maximal_cmdline_size = grub_le_to_cpu32 (lh.cmdline_size) + 1; + else + maximal_cmdline_size = 256; + + if (maximal_cmdline_size < 128) + maximal_cmdline_size = 128; + setup_sects = lh.setup_sects; /* If SETUP_SECTS is not set, set it to the default (4). */ @@ -643,7 +651,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), goto fail; params = (struct linux_kernel_params *) real_mode_mem; - grub_memset (params, 0, GRUB_LINUX_CL_END_OFFSET); + grub_memset (params, 0, GRUB_LINUX_CL_OFFSET + maximal_cmdline_size); grub_memcpy (¶ms->setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1); params->ps_mouse = params->padding10 = 0; @@ -845,8 +853,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* Copy kernel parameters. */ for (i = 1; i < argc - && dest + grub_strlen (argv[i]) + 1 < ((char *) real_mode_mem - + GRUB_LINUX_CL_END_OFFSET); + && dest + grub_strlen (argv[i]) + 2 < ((char *) real_mode_mem + + GRUB_LINUX_CL_OFFSET + + maximal_cmdline_size); i++) { *dest++ = ' '; diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c index 90de70f66..44da0ad90 100644 --- a/grub-core/loader/i386/pc/linux.c +++ b/grub-core/loader/i386/pc/linux.c @@ -36,7 +36,6 @@ #include #define GRUB_LINUX_CL_OFFSET 0x9000 -#define GRUB_LINUX_CL_END_OFFSET 0x90FF static grub_dl_t my_mod; @@ -46,6 +45,7 @@ static struct grub_relocator *relocator = NULL; static grub_addr_t grub_linux_real_target; static char *grub_linux_real_chunk; static grub_size_t grub_linux16_prot_size; +static grub_size_t maximal_cmdline_size; static grub_err_t grub_linux16_boot (void) @@ -126,15 +126,20 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), setup_sects = lh.setup_sects; linux_mem_size = 0; + maximal_cmdline_size = 256; + if (lh.header == grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE) && grub_le_to_cpu16 (lh.version) >= 0x0200) { grub_linux_is_bzimage = (lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL); lh.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE; + if (grub_le_to_cpu16 (lh.version) >= 0x0206) + maximal_cmdline_size = grub_le_to_cpu32 (lh.cmdline_size) + 1; + /* Put the real mode part at as a high location as possible. */ grub_linux_real_target = grub_mmap_get_lower () - - GRUB_LINUX_SETUP_MOVE_SIZE; + - (GRUB_LINUX_CL_OFFSET + maximal_cmdline_size); /* But it must not exceed the traditional area. */ if (grub_linux_real_target > GRUB_LINUX_OLD_REAL_MODE_ADDR) grub_linux_real_target = GRUB_LINUX_OLD_REAL_MODE_ADDR; @@ -151,7 +156,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), { lh.cl_magic = grub_cpu_to_le16 (GRUB_LINUX_CL_MAGIC); lh.cl_offset = grub_cpu_to_le16 (GRUB_LINUX_CL_OFFSET); - lh.setup_move_size = grub_cpu_to_le16 (GRUB_LINUX_SETUP_MOVE_SIZE); + lh.setup_move_size = grub_cpu_to_le16 (GRUB_LINUX_CL_OFFSET + + maximal_cmdline_size); } } else @@ -183,12 +189,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), goto fail; } - if (grub_linux_real_target + GRUB_LINUX_SETUP_MOVE_SIZE + if (grub_linux_real_target + GRUB_LINUX_CL_OFFSET + maximal_cmdline_size > grub_mmap_get_lower ()) { grub_error (GRUB_ERR_OUT_OF_RANGE, "too small lower memory (0x%x > 0x%x)", - grub_linux_real_target + GRUB_LINUX_SETUP_MOVE_SIZE, + grub_linux_real_target + GRUB_LINUX_CL_OFFSET + + maximal_cmdline_size, (int) grub_mmap_get_lower ()); goto fail; } @@ -261,7 +268,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_addr (relocator, &ch, grub_linux_real_target, - GRUB_LINUX_SETUP_MOVE_SIZE); + GRUB_LINUX_CL_OFFSET + + maximal_cmdline_size); if (err) return err; grub_linux_real_chunk = get_virtual_current_address (ch); @@ -294,8 +302,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* Copy kernel parameters. */ for (i = 1; i < argc - && dest + grub_strlen (argv[i]) + 1 < (grub_linux_real_chunk - + GRUB_LINUX_CL_END_OFFSET); + && dest + grub_strlen (argv[i]) + 2 < (grub_linux_real_chunk + + GRUB_LINUX_CL_OFFSET + + maximal_cmdline_size); i++) { *dest++ = ' '; diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h index 63f99db62..ad59b3452 100644 --- a/include/grub/i386/linux.h +++ b/include/grub/i386/linux.h @@ -41,7 +41,6 @@ #define GRUB_LINUX_VID_MODE_ASK 0xFFFD #define GRUB_LINUX_VID_MODE_VESA_START 0x0300 -#define GRUB_LINUX_SETUP_MOVE_SIZE 0x9100 #define GRUB_LINUX_CL_MAGIC 0xA33F #ifdef __x86_64__ @@ -126,6 +125,10 @@ struct linux_kernel_header grub_uint16_t pad1; /* Unused */ grub_uint32_t cmd_line_ptr; /* Points to the kernel command line */ grub_uint32_t initrd_addr_max; /* Highest address for initrd */ + grub_uint32_t kernel_alignment; + grub_uint8_t relocatable; + grub_uint8_t pad[3]; + grub_uint32_t cmdline_size; } __attribute__ ((packed)); /* Boot parameters for Linux based on 2.6.12. This is used by the setup From 332fa368872a57f945a7387cc1b931e83f197cb0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 8 Dec 2010 21:22:46 +0100 Subject: [PATCH 057/406] some squash4 code. Works only in very easy cases. --- Makefile.util.def | 1 + grub-core/Makefile.core.def | 5 + grub-core/fs/squash4.c | 384 ++++++++++++++++++++++++++++++++++++ 3 files changed, 390 insertions(+) create mode 100644 grub-core/fs/squash4.c diff --git a/Makefile.util.def b/Makefile.util.def index f3cd1d234..8eec8d0f7 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -65,6 +65,7 @@ library = { common = grub-core/fs/ntfscomp.c; common = grub-core/fs/reiserfs.c; common = grub-core/fs/sfs.c; + common = grub-core/fs/squash4.c; common = grub-core/fs/tar.c; common = grub-core/fs/udf.c; common = grub-core/fs/ufs2.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index c62d7d12f..583218372 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -983,6 +983,11 @@ module = { common = fs/sfs.c; }; +module = { + name = squash4; + common = fs/squash4.c; +}; + module = { name = tar; common = fs/tar.c; diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c new file mode 100644 index 000000000..889f8b94c --- /dev/null +++ b/grub-core/fs/squash4.c @@ -0,0 +1,384 @@ +/* squash4.c - SquashFS */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 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 + +/* + object format Pointed by + superblock RAW Fixed offset (0) + data RAW ? Fixed offset (60) + inode table Chunk superblock + dir table Chunk superblock + unk3 Chunk unk1 + unk1 RAW, Chunk superblock + unk2 RAW superblock + UID/GID Chunk exttblptr + exttblptr RAW superblock + + UID/GID table is the array ot uint32_t + unk1 contains pointer to unk3 followed by some chunk. + unk2 containts one uint64_t +*/ + +struct grub_squash_super +{ + grub_uint32_t magic; +#define SQUASH_MAGIC 0x73717368 + grub_uint32_t dummy1; + grub_uint32_t creation_time; + grub_uint32_t dummy2; + grub_uint32_t dummy3[4]; + grub_uint32_t dummy4[2]; + grub_uint64_t total_size; + grub_uint64_t exttbloffset; + grub_uint32_t dummy5[2]; + grub_uint64_t inodeoffset; + grub_uint64_t diroffset; + grub_uint64_t unk1offset; + grub_uint64_t unk2offset; +}; + + +/* Chunk-based */ +struct grub_squash_inode +{ + /* Same values as direlem types. */ + grub_uint16_t type; + grub_uint16_t dummy1[3]; + grub_uint32_t mtime; + grub_uint16_t dummy2[6]; + grub_uint32_t offset; + grub_uint16_t size; + grub_uint16_t dummy3; +} __attribute__ ((packed)); + +/* Chunk-based. */ +struct grub_squash_dirent_header +{ + /* Actually the value is the number of elements - 1. */ + grub_uint16_t nelems; + grub_uint16_t dummy[5]; +}; + +struct grub_squash_dirent +{ + grub_uint16_t ino; + grub_uint16_t dummy; + grub_uint16_t type; +#define SQUASH_TYPE_DIR 1 +#define SQUASH_TYPE_REGULAR 2 + /* Actually the value is the length of name - 1. */ + grub_uint16_t namelen; + char name[0]; +}; + +#define SQUASH_CHUNK_SIZE 0x2000 +#define SQUASH_CHUNK_FLAGS 0x8000 +#define SQUASH_CHUNK_UNCOMPRESSED 0x8000 + +static grub_err_t +read_chunk (grub_disk_t disk, void *buf, grub_size_t len, + grub_uint64_t chunk_start, grub_uint64_t offset) +{ + while (len > 0) + { + grub_uint64_t csize; + grub_uint16_t d; + grub_err_t err; + while (1) + { + err = grub_disk_read (disk, chunk_start >> GRUB_DISK_SECTOR_BITS, + chunk_start & (GRUB_DISK_SECTOR_SIZE - 1), + sizeof (d), &d); + if (err) + return err; + if (offset < SQUASH_CHUNK_SIZE) + break; + offset -= SQUASH_CHUNK_SIZE; + chunk_start += 2 + (grub_le_to_cpu16 (d) & ~SQUASH_CHUNK_FLAGS); + } + + csize = SQUASH_CHUNK_SIZE - offset; + if (csize > len) + csize = len; + + if (grub_le_to_cpu16 (d) & SQUASH_CHUNK_UNCOMPRESSED) + { + grub_disk_addr_t a = chunk_start + 2 + offset; + err = grub_disk_read (disk, (a >> GRUB_DISK_SECTOR_BITS), + a & (GRUB_DISK_SECTOR_SIZE - 1), + csize, buf); + if (err) + return err; + } + else + { + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "compression not implemented yet"); + } + len -= csize; + offset += csize; + buf = (char *) buf + csize; + } + return GRUB_ERR_NONE; +} + +struct grub_squash_data +{ + grub_disk_t disk; + struct grub_squash_super sb; + struct grub_squash_inode ino; +}; + +struct grub_fshelp_node +{ + struct grub_squash_data *data; + struct grub_squash_inode ino; +}; + +static struct grub_squash_data * +squash_mount (grub_disk_t disk) +{ + struct grub_squash_super sb; + grub_err_t err; + struct grub_squash_data *data; + + err = grub_disk_read (disk, 0, 0, sizeof (sb), &sb); + if (grub_errno == GRUB_ERR_OUT_OF_RANGE) + grub_error (GRUB_ERR_BAD_FS, "not a squash4"); + if (err) + return NULL; + if (grub_le_to_cpu32 (sb.magic) != SQUASH_MAGIC) + { + grub_error (GRUB_ERR_BAD_FS, "not squash4"); + return NULL; + } + data = grub_malloc (sizeof (*data)); + if (!data) + return NULL; + data->sb = sb; + data->disk = disk; + + return data; +} + +static int +grub_squash_iterate_dir (grub_fshelp_node_t dir, + int NESTED_FUNC_ATTR + (*hook) (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node)) +{ + grub_uint32_t off = grub_le_to_cpu32 (dir->ino.offset) >> 16; + /* FIXME: determine this. */ + unsigned numheaders = 1; + unsigned i, j; + for (j = 0; j < numheaders; j++) + { + struct grub_squash_dirent_header dh; + grub_err_t err; + + err = read_chunk (dir->data->disk, &dh, sizeof (dh), + grub_le_to_cpu64 (dir->data->sb.diroffset), off); + if (err) + return 0; + off += sizeof (dh); + for (i = 0; i < (unsigned) grub_le_to_cpu16 (dh.nelems) + 1; i++) + { + char *buf; + int r; + struct grub_fshelp_node *node; + enum grub_fshelp_filetype filetype = GRUB_FSHELP_REG; + struct grub_squash_dirent di; + struct grub_squash_inode ino; + + err = read_chunk (dir->data->disk, &di, sizeof (di), + grub_le_to_cpu64 (dir->data->sb.diroffset), off); + if (err) + return 0; + off += sizeof (di); + + err = read_chunk (dir->data->disk, &ino, sizeof (ino), + grub_le_to_cpu64 (dir->data->sb.inodeoffset), + grub_le_to_cpu16 (di.ino)); + if (err) + return 0; + + buf = grub_malloc (grub_le_to_cpu16 (di.namelen) + 2); + if (!buf) + return 0; + err = read_chunk (dir->data->disk, buf, + grub_le_to_cpu16 (di.namelen) + 1, + grub_le_to_cpu64 (dir->data->sb.diroffset), off); + if (err) + return 0; + + off += grub_le_to_cpu16 (di.namelen) + 1; + buf[grub_le_to_cpu16 (di.namelen) + 1] = 0; + if (grub_le_to_cpu16 (ino.type) == SQUASH_TYPE_DIR) + filetype = GRUB_FSHELP_DIR; + node = grub_malloc (sizeof (*node)); + if (! node) + return 0; + *node = *dir; + node->ino = ino; + r = hook (buf, filetype, node); + + grub_free (buf); + if (r) + return r; + } + } + return 0; +} + +static grub_err_t +make_root_node (struct grub_squash_data *data, struct grub_fshelp_node *root) +{ + /* FIXME */ + grub_memset (root, 0, sizeof (*root)); + root->data = data; + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_squash_dir (grub_device_t device, const char *path, + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) +{ + auto int NESTED_FUNC_ATTR iterate (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node); + + int NESTED_FUNC_ATTR iterate (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node __attribute__ ((unused))) + { + struct grub_dirhook_info info; + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + return hook (filename, &info); + } + + struct grub_squash_data *data = 0; + struct grub_fshelp_node *fdiro = 0; + struct grub_fshelp_node root; + grub_err_t err; + + data = squash_mount (device->disk); + if (! data) + return grub_errno; + + err = make_root_node (data, &root); + if (err) + return err; + + grub_fshelp_find_file (path, &root, &fdiro, grub_squash_iterate_dir, + NULL, GRUB_FSHELP_DIR); + if (!grub_errno) + grub_squash_iterate_dir (fdiro, iterate); + + grub_free (data); + + return grub_errno; +} + +static grub_err_t +grub_squash_open (struct grub_file *file, const char *name) +{ + struct grub_squash_data *data = 0; + struct grub_fshelp_node *fdiro = 0; + struct grub_fshelp_node root; + grub_err_t err; + + data = squash_mount (file->device->disk); + if (! data) + return grub_errno; + + err = make_root_node (data, &root); + if (err) + return err; + + grub_fshelp_find_file (name, &root, &fdiro, grub_squash_iterate_dir, + NULL, GRUB_FSHELP_REG); + if (grub_errno) + { + grub_free (data); + return grub_errno; + } + file->data = data; + data->ino = fdiro->ino; + file->size = grub_le_to_cpu16 (fdiro->ino.size); + return GRUB_ERR_NONE; +} + +static grub_ssize_t +grub_squash_read (grub_file_t file, char *buf, grub_size_t len) +{ + grub_err_t err; + grub_uint64_t a; + struct grub_squash_data *data = file->data; + + a = sizeof (struct grub_squash_super) + grub_le_to_cpu32 (data->ino.offset); + + err = grub_disk_read (file->device->disk, a >> GRUB_DISK_SECTOR_BITS, + a & (GRUB_DISK_SECTOR_SIZE - 1), len, buf); + if (err) + return -1; + return len; +} + +static grub_err_t +grub_squash_close (grub_file_t file) +{ + grub_free (file->data); + return GRUB_ERR_NONE; +} + +static struct grub_fs grub_squash_fs = + { + .name = "squash4", + .dir = grub_squash_dir, + .open = grub_squash_open, + .read = grub_squash_read, + .close = grub_squash_close, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif + .next = 0 + }; + +GRUB_MOD_INIT(squash4) +{ + grub_fs_register (&grub_squash_fs); +} + +GRUB_MOD_FINI(squash4) +{ + grub_fs_unregister (&grub_squash_fs); +} + From 1deadc83f55187f1ba889d6533341850cb3a5f50 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 8 Dec 2010 23:03:59 +0100 Subject: [PATCH 058/406] extend size to 32-bit and handle file->offset --- grub-core/fs/squash4.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 889f8b94c..f3ac1f474 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -72,8 +72,7 @@ struct grub_squash_inode grub_uint32_t mtime; grub_uint16_t dummy2[6]; grub_uint32_t offset; - grub_uint16_t size; - grub_uint16_t dummy3; + grub_uint32_t size; } __attribute__ ((packed)); /* Chunk-based. */ @@ -330,9 +329,10 @@ grub_squash_open (struct grub_file *file, const char *name) grub_free (data); return grub_errno; } + file->data = data; data->ino = fdiro->ino; - file->size = grub_le_to_cpu16 (fdiro->ino.size); + file->size = grub_le_to_cpu32 (fdiro->ino.size); return GRUB_ERR_NONE; } @@ -343,7 +343,8 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len) grub_uint64_t a; struct grub_squash_data *data = file->data; - a = sizeof (struct grub_squash_super) + grub_le_to_cpu32 (data->ino.offset); + a = sizeof (struct grub_squash_super) + grub_le_to_cpu32 (data->ino.offset) + + file->offset; err = grub_disk_read (file->device->disk, a >> GRUB_DISK_SECTOR_BITS, a & (GRUB_DISK_SECTOR_SIZE - 1), len, buf); From 0a040470e53c4620d93249d5aba40097c93740d8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 9 Dec 2010 00:04:36 +0100 Subject: [PATCH 059/406] determine root inode on squash4fs --- grub-core/fs/squash4.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index f3ac1f474..bd50265a8 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -52,7 +52,8 @@ struct grub_squash_super grub_uint32_t creation_time; grub_uint32_t dummy2; grub_uint32_t dummy3[4]; - grub_uint32_t dummy4[2]; + grub_uint32_t root_ino; + grub_uint32_t dummy4; grub_uint64_t total_size; grub_uint64_t exttbloffset; grub_uint32_t dummy5[2]; @@ -258,10 +259,12 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, static grub_err_t make_root_node (struct grub_squash_data *data, struct grub_fshelp_node *root) { - /* FIXME */ grub_memset (root, 0, sizeof (*root)); root->data = data; - return GRUB_ERR_NONE; + + return read_chunk (data->disk, &root->ino, sizeof (root->ino), + grub_le_to_cpu64 (data->sb.inodeoffset), + grub_le_to_cpu32 (data->sb.root_ino)); } static grub_err_t From 7ed6c3e85f51a59d0758de6363d7acd9804c2e21 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 9 Dec 2010 02:48:59 +0100 Subject: [PATCH 060/406] Honor chunk number for directories --- grub-core/fs/squash4.c | 48 ++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index bd50265a8..1622d3736 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -52,7 +52,8 @@ struct grub_squash_super grub_uint32_t creation_time; grub_uint32_t dummy2; grub_uint32_t dummy3[4]; - grub_uint32_t root_ino; + grub_uint16_t root_ino_offset; + grub_uint16_t root_ino_chunk; grub_uint32_t dummy4; grub_uint64_t total_size; grub_uint64_t exttbloffset; @@ -71,11 +72,19 @@ struct grub_squash_inode grub_uint16_t type; grub_uint16_t dummy1[3]; grub_uint32_t mtime; - grub_uint16_t dummy2[6]; + grub_uint16_t dummy2[2]; + grub_uint16_t chunk; + grub_uint16_t dummy3[3]; grub_uint32_t offset; grub_uint32_t size; } __attribute__ ((packed)); +static inline unsigned +decode_chunk_number (grub_uint16_t in) +{ + return (grub_le_to_cpu16 (in) & 0xff) / 2; +} + /* Chunk-based. */ struct grub_squash_dirent_header { @@ -102,8 +111,10 @@ struct grub_squash_dirent static grub_err_t read_chunk (grub_disk_t disk, void *buf, grub_size_t len, - grub_uint64_t chunk_start, grub_uint64_t offset) + grub_uint64_t chunk, unsigned nchunk, grub_off_t offset) { + grub_uint64_t chunk_start; + chunk_start = grub_le_to_cpu64 (chunk); while (len > 0) { grub_uint64_t csize; @@ -116,9 +127,12 @@ read_chunk (grub_disk_t disk, void *buf, grub_size_t len, sizeof (d), &d); if (err) return err; - if (offset < SQUASH_CHUNK_SIZE) + if (!nchunk && offset < SQUASH_CHUNK_SIZE) break; - offset -= SQUASH_CHUNK_SIZE; + if (nchunk) + nchunk--; + else + offset -= SQUASH_CHUNK_SIZE; chunk_start += 2 + (grub_le_to_cpu16 (d) & ~SQUASH_CHUNK_FLAGS); } @@ -197,13 +211,15 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, /* FIXME: determine this. */ unsigned numheaders = 1; unsigned i, j; + for (j = 0; j < numheaders; j++) { struct grub_squash_dirent_header dh; grub_err_t err; err = read_chunk (dir->data->disk, &dh, sizeof (dh), - grub_le_to_cpu64 (dir->data->sb.diroffset), off); + dir->data->sb.diroffset, + decode_chunk_number (dir->ino.chunk), off); if (err) return 0; off += sizeof (dh); @@ -217,14 +233,16 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, struct grub_squash_inode ino; err = read_chunk (dir->data->disk, &di, sizeof (di), - grub_le_to_cpu64 (dir->data->sb.diroffset), off); + dir->data->sb.diroffset, + decode_chunk_number (dir->ino.chunk), off); if (err) return 0; off += sizeof (di); err = read_chunk (dir->data->disk, &ino, sizeof (ino), - grub_le_to_cpu64 (dir->data->sb.inodeoffset), - grub_le_to_cpu16 (di.ino)); + dir->data->sb.inodeoffset, + 0, + grub_cpu_to_le16 (di.ino)); if (err) return 0; @@ -233,7 +251,8 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, return 0; err = read_chunk (dir->data->disk, buf, grub_le_to_cpu16 (di.namelen) + 1, - grub_le_to_cpu64 (dir->data->sb.diroffset), off); + dir->data->sb.diroffset, + decode_chunk_number (dir->ino.chunk), off); if (err) return 0; @@ -261,10 +280,11 @@ make_root_node (struct grub_squash_data *data, struct grub_fshelp_node *root) { grub_memset (root, 0, sizeof (*root)); root->data = data; - - return read_chunk (data->disk, &root->ino, sizeof (root->ino), - grub_le_to_cpu64 (data->sb.inodeoffset), - grub_le_to_cpu32 (data->sb.root_ino)); + + return read_chunk (data->disk, &root->ino, sizeof (root->ino), + data->sb.inodeoffset, + decode_chunk_number (data->sb.root_ino_chunk), + grub_cpu_to_le16 (data->sb.root_ino_offset)); } static grub_err_t From 948ebd7e91f29efea22bc4987582efb827940294 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 9 Dec 2010 17:06:49 +0100 Subject: [PATCH 061/406] Support fragments and chunks for data --- grub-core/fs/squash4.c | 91 +++++++++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 1622d3736..6fc2bc11b 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -28,16 +28,16 @@ #include /* - object format Pointed by - superblock RAW Fixed offset (0) - data RAW ? Fixed offset (60) - inode table Chunk superblock - dir table Chunk superblock - unk3 Chunk unk1 - unk1 RAW, Chunk superblock - unk2 RAW superblock - UID/GID Chunk exttblptr - exttblptr RAW superblock + object format Pointed by + superblock RAW Fixed offset (0) + data RAW ? Fixed offset (60) + inode table Chunk superblock + dir table Chunk superblock + fragment table Chunk unk1 + unk1 RAW, Chunk superblock + unk2 RAW superblock + UID/GID Chunk exttblptr + exttblptr RAW superblock UID/GID table is the array ot uint32_t unk1 contains pointer to unk3 followed by some chunk. @@ -73,8 +73,8 @@ struct grub_squash_inode grub_uint16_t dummy1[3]; grub_uint32_t mtime; grub_uint16_t dummy2[2]; - grub_uint16_t chunk; - grub_uint16_t dummy3[3]; + grub_uint32_t chunk; + grub_uint32_t fragment; grub_uint32_t offset; grub_uint32_t size; } __attribute__ ((packed)); @@ -105,10 +105,30 @@ struct grub_squash_dirent char name[0]; }; +struct grub_squash_frag_desc +{ + grub_uint64_t offset; + grub_uint64_t dummy; +}; + #define SQUASH_CHUNK_SIZE 0x2000 #define SQUASH_CHUNK_FLAGS 0x8000 #define SQUASH_CHUNK_UNCOMPRESSED 0x8000 +struct grub_squash_data +{ + grub_disk_t disk; + struct grub_squash_super sb; + struct grub_squash_inode ino; + grub_uint64_t fragments; +}; + +struct grub_fshelp_node +{ + struct grub_squash_data *data; + struct grub_squash_inode ino; +}; + static grub_err_t read_chunk (grub_disk_t disk, void *buf, grub_size_t len, grub_uint64_t chunk, unsigned nchunk, grub_off_t offset) @@ -161,25 +181,13 @@ read_chunk (grub_disk_t disk, void *buf, grub_size_t len, return GRUB_ERR_NONE; } -struct grub_squash_data -{ - grub_disk_t disk; - struct grub_squash_super sb; - struct grub_squash_inode ino; -}; - -struct grub_fshelp_node -{ - struct grub_squash_data *data; - struct grub_squash_inode ino; -}; - static struct grub_squash_data * squash_mount (grub_disk_t disk) { struct grub_squash_super sb; grub_err_t err; struct grub_squash_data *data; + grub_uint64_t frag; err = grub_disk_read (disk, 0, 0, sizeof (sb), &sb); if (grub_errno == GRUB_ERR_OUT_OF_RANGE) @@ -191,11 +199,22 @@ squash_mount (grub_disk_t disk) grub_error (GRUB_ERR_BAD_FS, "not squash4"); return NULL; } + + err = grub_disk_read (disk, grub_le_to_cpu32 (sb.unk1offset) + >> GRUB_DISK_SECTOR_BITS, + grub_le_to_cpu32 (sb.unk1offset) + & (GRUB_DISK_SECTOR_SIZE - 1), sizeof (frag), &frag); + if (grub_errno == GRUB_ERR_OUT_OF_RANGE) + grub_error (GRUB_ERR_BAD_FS, "not a squash4"); + if (err) + return NULL; + data = grub_malloc (sizeof (*data)); if (!data) return NULL; data->sb = sb; data->disk = disk; + data->fragments = frag; return data; } @@ -356,6 +375,7 @@ grub_squash_open (struct grub_file *file, const char *name) file->data = data; data->ino = fdiro->ino; file->size = grub_le_to_cpu32 (fdiro->ino.size); + return GRUB_ERR_NONE; } @@ -366,8 +386,25 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len) grub_uint64_t a; struct grub_squash_data *data = file->data; - a = sizeof (struct grub_squash_super) + grub_le_to_cpu32 (data->ino.offset) - + file->offset; + a = grub_le_to_cpu32 (data->ino.offset) + file->offset; + if (grub_le_to_cpu16 (data->ino.fragment) == 0xffff) + { + if (grub_le_to_cpu32 (data->ino.chunk)) + a += grub_le_to_cpu32 (data->ino.chunk); + else + a += sizeof (struct grub_squash_super); + } + else + { + struct grub_squash_frag_desc frag; + err = read_chunk (file->device->disk, &frag, sizeof (frag), + data->fragments, 0, sizeof (frag) + * grub_le_to_cpu16 (data->ino.fragment)); + if (err) + return -1; + a += grub_le_to_cpu64 (frag.offset); + a += grub_le_to_cpu32 (data->ino.chunk); + } err = grub_disk_read (file->device->disk, a >> GRUB_DISK_SECTOR_BITS, a & (GRUB_DISK_SECTOR_SIZE - 1), len, buf); From 99f0735fb8f961f4281eae3c76366f2eb8afdad2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 9 Dec 2010 18:22:38 +0100 Subject: [PATCH 062/406] Support multi-header directories --- grub-core/fs/squash4.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 6fc2bc11b..5bb128f58 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -227,11 +227,13 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, grub_fshelp_node_t node)) { grub_uint32_t off = grub_le_to_cpu32 (dir->ino.offset) >> 16; - /* FIXME: determine this. */ - unsigned numheaders = 1; - unsigned i, j; + grub_uint32_t endoff; + unsigned i; - for (j = 0; j < numheaders; j++) + /* FIXME: why - 3 ? */ + endoff = (grub_le_to_cpu32 (dir->ino.offset) & 0xffff) + off - 3; + + while (off < endoff) { struct grub_squash_dirent_header dh; grub_err_t err; From 76e39dc8711ce85d43fa06a0a4ee9e0683091d45 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 9 Dec 2010 19:23:35 +0100 Subject: [PATCH 063/406] Compressed metadata support --- grub-core/fs/squash4.c | 74 +++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 5bb128f58..8eca185f3 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -79,23 +79,19 @@ struct grub_squash_inode grub_uint32_t size; } __attribute__ ((packed)); -static inline unsigned -decode_chunk_number (grub_uint16_t in) -{ - return (grub_le_to_cpu16 (in) & 0xff) / 2; -} - /* Chunk-based. */ struct grub_squash_dirent_header { /* Actually the value is the number of elements - 1. */ grub_uint16_t nelems; - grub_uint16_t dummy[5]; + grub_uint16_t dummy1; + grub_uint32_t ino_chunk; + grub_uint16_t dummy2[2]; }; struct grub_squash_dirent { - grub_uint16_t ino; + grub_uint16_t ino_offset; grub_uint16_t dummy; grub_uint16_t type; #define SQUASH_TYPE_DIR 1 @@ -131,7 +127,7 @@ struct grub_fshelp_node static grub_err_t read_chunk (grub_disk_t disk, void *buf, grub_size_t len, - grub_uint64_t chunk, unsigned nchunk, grub_off_t offset) + grub_uint64_t chunk, grub_off_t offset) { grub_uint64_t chunk_start; chunk_start = grub_le_to_cpu64 (chunk); @@ -147,12 +143,9 @@ read_chunk (grub_disk_t disk, void *buf, grub_size_t len, sizeof (d), &d); if (err) return err; - if (!nchunk && offset < SQUASH_CHUNK_SIZE) + if (offset < SQUASH_CHUNK_SIZE) break; - if (nchunk) - nchunk--; - else - offset -= SQUASH_CHUNK_SIZE; + offset -= SQUASH_CHUNK_SIZE; chunk_start += 2 + (grub_le_to_cpu16 (d) & ~SQUASH_CHUNK_FLAGS); } @@ -171,8 +164,29 @@ read_chunk (grub_disk_t disk, void *buf, grub_size_t len, } else { - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "compression not implemented yet"); + char *tmp; + grub_size_t bsize = grub_le_to_cpu16 (d) & ~SQUASH_CHUNK_FLAGS; + grub_disk_addr_t a = chunk_start + 2; + tmp = grub_malloc (bsize); + if (!tmp) + return grub_errno; + /* FIXME: buffer uncompressed data. */ + err = grub_disk_read (disk, (a >> GRUB_DISK_SECTOR_BITS), + a & (GRUB_DISK_SECTOR_SIZE - 1), + bsize, tmp); + if (err) + { + grub_free (tmp); + return err; + } + + if (grub_zlib_decompress (tmp, bsize, offset, + buf, csize) < 0) + { + grub_free (tmp); + return grub_errno; + } + grub_free (tmp); } len -= csize; offset += csize; @@ -239,8 +253,8 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, grub_err_t err; err = read_chunk (dir->data->disk, &dh, sizeof (dh), - dir->data->sb.diroffset, - decode_chunk_number (dir->ino.chunk), off); + grub_le_to_cpu64 (dir->data->sb.diroffset) + + grub_le_to_cpu32 (dir->ino.chunk), off); if (err) return 0; off += sizeof (dh); @@ -254,16 +268,16 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, struct grub_squash_inode ino; err = read_chunk (dir->data->disk, &di, sizeof (di), - dir->data->sb.diroffset, - decode_chunk_number (dir->ino.chunk), off); + grub_le_to_cpu64 (dir->data->sb.diroffset) + + grub_le_to_cpu32 (dir->ino.chunk), off); if (err) return 0; off += sizeof (di); err = read_chunk (dir->data->disk, &ino, sizeof (ino), - dir->data->sb.inodeoffset, - 0, - grub_cpu_to_le16 (di.ino)); + grub_le_to_cpu64 (dir->data->sb.inodeoffset) + + grub_le_to_cpu32 (dh.ino_chunk), + grub_cpu_to_le16 (di.ino_offset)); if (err) return 0; @@ -272,14 +286,14 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, return 0; err = read_chunk (dir->data->disk, buf, grub_le_to_cpu16 (di.namelen) + 1, - dir->data->sb.diroffset, - decode_chunk_number (dir->ino.chunk), off); + grub_le_to_cpu64 (dir->data->sb.diroffset) + + grub_le_to_cpu32 (dir->ino.chunk), off); if (err) return 0; off += grub_le_to_cpu16 (di.namelen) + 1; buf[grub_le_to_cpu16 (di.namelen) + 1] = 0; - if (grub_le_to_cpu16 (ino.type) == SQUASH_TYPE_DIR) + if (grub_le_to_cpu16 (di.type) == SQUASH_TYPE_DIR) filetype = GRUB_FSHELP_DIR; node = grub_malloc (sizeof (*node)); if (! node) @@ -303,9 +317,9 @@ make_root_node (struct grub_squash_data *data, struct grub_fshelp_node *root) root->data = data; return read_chunk (data->disk, &root->ino, sizeof (root->ino), - data->sb.inodeoffset, - decode_chunk_number (data->sb.root_ino_chunk), - grub_cpu_to_le16 (data->sb.root_ino_offset)); + grub_le_to_cpu64 (data->sb.inodeoffset) + + grub_le_to_cpu16 (data->sb.root_ino_chunk), + grub_cpu_to_le16 (data->sb.root_ino_offset)); } static grub_err_t @@ -400,7 +414,7 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_squash_frag_desc frag; err = read_chunk (file->device->disk, &frag, sizeof (frag), - data->fragments, 0, sizeof (frag) + data->fragments, sizeof (frag) * grub_le_to_cpu16 (data->ino.fragment)); if (err) return -1; From e4eaf625553ddf07f6cade56651fda7038542ea2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 9 Dec 2010 19:40:11 +0100 Subject: [PATCH 064/406] Small restructuring of squash_read --- grub-core/fs/squash4.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 8eca185f3..1a121c2cf 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -402,13 +402,12 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len) grub_uint64_t a; struct grub_squash_data *data = file->data; - a = grub_le_to_cpu32 (data->ino.offset) + file->offset; if (grub_le_to_cpu16 (data->ino.fragment) == 0xffff) { if (grub_le_to_cpu32 (data->ino.chunk)) - a += grub_le_to_cpu32 (data->ino.chunk); + a = grub_le_to_cpu32 (data->ino.chunk); else - a += sizeof (struct grub_squash_super); + a = sizeof (struct grub_squash_super); } else { @@ -418,10 +417,11 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len) * grub_le_to_cpu16 (data->ino.fragment)); if (err) return -1; - a += grub_le_to_cpu64 (frag.offset); - a += grub_le_to_cpu32 (data->ino.chunk); + a = grub_le_to_cpu64 (frag.offset) + grub_le_to_cpu32 (data->ino.chunk); } + a += grub_le_to_cpu32 (data->ino.offset) + file->offset; + err = grub_disk_read (file->device->disk, a >> GRUB_DISK_SECTOR_BITS, a & (GRUB_DISK_SECTOR_SIZE - 1), len, buf); if (err) From 8eef1f8244a91a1beb18bc7a94fad7347382e65e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 9 Dec 2010 20:41:41 +0100 Subject: [PATCH 065/406] Compressed fragments and compressed data support --- grub-core/fs/squash4.c | 26 +++++++++++++++------ grub-core/io/gzio.c | 53 +++++++++++++++++++++++++++++++++++++++--- include/grub/deflate.h | 4 ++++ 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 1a121c2cf..50e5c3090 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -51,13 +51,18 @@ struct grub_squash_super grub_uint32_t dummy1; grub_uint32_t creation_time; grub_uint32_t dummy2; - grub_uint32_t dummy3[4]; + grub_uint32_t dummy3[2]; + grub_uint8_t flags; +#define SQUASH_FLAG_UNCOMPRESSED_INODES 1 +#define SQUASH_FLAG_UNCOMPRESSED_DATA 2 +#define SQUASH_FLAG_UNCOMPRESSED_FRAGMENTS 8 + grub_uint8_t dummy4[7]; grub_uint16_t root_ino_offset; grub_uint16_t root_ino_chunk; - grub_uint32_t dummy4; + grub_uint32_t dummy5; grub_uint64_t total_size; grub_uint64_t exttbloffset; - grub_uint32_t dummy5[2]; + grub_uint32_t dummy6[2]; grub_uint64_t inodeoffset; grub_uint64_t diroffset; grub_uint64_t unk1offset; @@ -399,8 +404,9 @@ static grub_ssize_t grub_squash_read (grub_file_t file, char *buf, grub_size_t len) { grub_err_t err; - grub_uint64_t a; + grub_uint64_t a, b; struct grub_squash_data *data = file->data; + int compressed = 0; if (grub_le_to_cpu16 (data->ino.fragment) == 0xffff) { @@ -408,6 +414,7 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len) a = grub_le_to_cpu32 (data->ino.chunk); else a = sizeof (struct grub_squash_super); + compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_DATA); } else { @@ -418,12 +425,17 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len) if (err) return -1; a = grub_le_to_cpu64 (frag.offset) + grub_le_to_cpu32 (data->ino.chunk); + compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_FRAGMENTS); } - a += grub_le_to_cpu32 (data->ino.offset) + file->offset; + b = grub_le_to_cpu32 (data->ino.offset) + file->offset; - err = grub_disk_read (file->device->disk, a >> GRUB_DISK_SECTOR_BITS, - a & (GRUB_DISK_SECTOR_SIZE - 1), len, buf); + /* FIXME: cache uncompressed chunks. */ + if (compressed) + err = grub_zlib_disk_read (file->device->disk, a, b, buf, len); + else + err = grub_disk_read (file->device->disk, (a + b) >> GRUB_DISK_SECTOR_BITS, + (a + b) & (GRUB_DISK_SECTOR_SIZE - 1), len, buf); if (err) return -1; return len; diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c index 248a1750e..61227b4fc 100644 --- a/grub-core/io/gzio.c +++ b/grub-core/io/gzio.c @@ -41,6 +41,7 @@ #include #include #include +#include #include /* @@ -62,6 +63,9 @@ struct grub_gzio /* If input is in memory following fields are used instead of file. */ grub_size_t mem_input_size, mem_input_off; grub_uint8_t *mem_input; + grub_disk_addr_t disk_input_off; + grub_disk_addr_t disk_input_start; + grub_disk_t disk_input; /* The offset at which the data starts in the underlying file. */ grub_off_t data_offset; /* The type of current block. */ @@ -383,8 +387,21 @@ get_byte (grub_gzio_t gzio) return 0; } - if (grub_file_tell (gzio->file) == (grub_off_t) gzio->data_offset - || gzio->inbuf_d == INBUFSIZ) + if (gzio->disk_input && (gzio->disk_input_off == gzio->data_offset + || gzio->inbuf_d == INBUFSIZ)) + { + grub_disk_addr_t d = gzio->disk_input_start + gzio->disk_input_off; + gzio->inbuf_d = 0; + grub_disk_read (gzio->disk_input, + d >> GRUB_DISK_SECTOR_BITS, + d & (GRUB_DISK_SECTOR_SIZE - 1), + INBUFSIZ, gzio->inbuf); + gzio->disk_input_off += INBUFSIZ; + } + + if (gzio->file && (grub_file_tell (gzio->file) + == (grub_off_t) gzio->data_offset + || gzio->inbuf_d == INBUFSIZ)) { gzio->inbuf_d = 0; grub_file_read (gzio->file, gzio->inbuf, INBUFSIZ); @@ -402,8 +419,10 @@ gzio_seek (grub_gzio_t gzio, grub_off_t off) grub_error (GRUB_ERR_OUT_OF_RANGE, "attempt to seek outside of the file"); else - gzio->mem_input_off = gzio->data_offset; + gzio->mem_input_off = off; } + else if (gzio->disk_input) + gzio->disk_input_off = off; else grub_file_seek (gzio->file, off); } @@ -1297,6 +1316,34 @@ grub_zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off, return ret; } +grub_err_t +grub_zlib_disk_read (grub_disk_t disk, grub_disk_addr_t zlibstart, + grub_off_t off, char *outbuf, grub_size_t outsize) +{ + grub_gzio_t gzio = 0; + grub_ssize_t ret; + + gzio = grub_zalloc (sizeof (*gzio)); + if (! gzio) + return -1; + + gzio->disk_input_off = 0; + gzio->disk_input_start = zlibstart; + gzio->disk_input = disk; + + if (!test_zlib_header (gzio)) + { + grub_free (gzio); + return -1; + } + + ret = grub_gzio_read_real (gzio, off, outbuf, outsize); + grub_free (gzio); + + /* FIXME: Check Adler. */ + return ret < 0 ? grub_errno : GRUB_ERR_NONE; +} + static struct grub_fs grub_gzio_fs = diff --git a/include/grub/deflate.h b/include/grub/deflate.h index 6ec4eaa99..ae4a1f244 100644 --- a/include/grub/deflate.h +++ b/include/grub/deflate.h @@ -23,4 +23,8 @@ grub_ssize_t grub_zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off, char *outbuf, grub_size_t outsize); +grub_err_t +grub_zlib_disk_read (grub_disk_t disk, grub_disk_addr_t zlibstart, + grub_off_t off, char *outbuf, grub_size_t outsize); + #endif From 1fc7203971e91efde3645b97fac776872ecf7e5a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 9 Dec 2010 20:48:03 +0100 Subject: [PATCH 066/406] Split grub_squash_read_data --- grub-core/fs/squash4.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 50e5c3090..2fa429803 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -401,17 +401,18 @@ grub_squash_open (struct grub_file *file, const char *name) } static grub_ssize_t -grub_squash_read (grub_file_t file, char *buf, grub_size_t len) +grub_squash_read_data (struct grub_squash_data *data, + grub_disk_t disk, const struct grub_squash_inode *ino, + grub_off_t off, char *buf, grub_size_t len) { grub_err_t err; grub_uint64_t a, b; - struct grub_squash_data *data = file->data; int compressed = 0; - if (grub_le_to_cpu16 (data->ino.fragment) == 0xffff) + if (grub_le_to_cpu16 (ino->fragment) == 0xffff) { - if (grub_le_to_cpu32 (data->ino.chunk)) - a = grub_le_to_cpu32 (data->ino.chunk); + if (grub_le_to_cpu32 (ino->chunk)) + a = grub_le_to_cpu32 (ino->chunk); else a = sizeof (struct grub_squash_super); compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_DATA); @@ -419,28 +420,37 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len) else { struct grub_squash_frag_desc frag; - err = read_chunk (file->device->disk, &frag, sizeof (frag), + err = read_chunk (disk, &frag, sizeof (frag), data->fragments, sizeof (frag) - * grub_le_to_cpu16 (data->ino.fragment)); + * grub_le_to_cpu16 (ino->fragment)); if (err) return -1; - a = grub_le_to_cpu64 (frag.offset) + grub_le_to_cpu32 (data->ino.chunk); + a = grub_le_to_cpu64 (frag.offset) + grub_le_to_cpu32 (ino->chunk); compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_FRAGMENTS); } - b = grub_le_to_cpu32 (data->ino.offset) + file->offset; + b = grub_le_to_cpu32 (data->ino.offset) + off; /* FIXME: cache uncompressed chunks. */ if (compressed) - err = grub_zlib_disk_read (file->device->disk, a, b, buf, len); + err = grub_zlib_disk_read (disk, a, b, buf, len); else - err = grub_disk_read (file->device->disk, (a + b) >> GRUB_DISK_SECTOR_BITS, + err = grub_disk_read (disk, (a + b) >> GRUB_DISK_SECTOR_BITS, (a + b) & (GRUB_DISK_SECTOR_SIZE - 1), len, buf); if (err) return -1; return len; } +static grub_ssize_t +grub_squash_read (grub_file_t file, char *buf, grub_size_t len) +{ + struct grub_squash_data *data = file->data; + + return grub_squash_read_data (data, file->device->disk, &data->ino, + file->offset, buf, len); +} + static grub_err_t grub_squash_close (grub_file_t file) { From 627a62fc70e75578ebcfbef71428afd1700f7e7d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 9 Dec 2010 21:14:42 +0100 Subject: [PATCH 067/406] Make type-dependent portion of inode an union --- grub-core/fs/squash4.c | 49 ++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 2fa429803..409d91e47 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -75,13 +75,26 @@ struct grub_squash_inode { /* Same values as direlem types. */ grub_uint16_t type; - grub_uint16_t dummy1[3]; + grub_uint16_t dummy[3]; grub_uint32_t mtime; - grub_uint16_t dummy2[2]; - grub_uint32_t chunk; - grub_uint32_t fragment; - grub_uint32_t offset; - grub_uint32_t size; + union + { + struct { + grub_uint16_t dummy[2]; + grub_uint32_t chunk; + grub_uint32_t fragment; + grub_uint32_t offset; + grub_uint32_t size; + } file; + struct { + grub_uint16_t dummy1[2]; + grub_uint32_t chunk; + grub_uint16_t dummy2[2]; + grub_uint16_t size; + grub_uint16_t offset; + grub_uint16_t dummy3[2]; + } dir; + }; } __attribute__ ((packed)); /* Chunk-based. */ @@ -245,12 +258,12 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, enum grub_fshelp_filetype filetype, grub_fshelp_node_t node)) { - grub_uint32_t off = grub_le_to_cpu32 (dir->ino.offset) >> 16; + grub_uint32_t off = grub_le_to_cpu16 (dir->ino.dir.offset); grub_uint32_t endoff; unsigned i; /* FIXME: why - 3 ? */ - endoff = (grub_le_to_cpu32 (dir->ino.offset) & 0xffff) + off - 3; + endoff = grub_le_to_cpu32 (dir->ino.dir.size) + off - 3; while (off < endoff) { @@ -259,7 +272,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, err = read_chunk (dir->data->disk, &dh, sizeof (dh), grub_le_to_cpu64 (dir->data->sb.diroffset) - + grub_le_to_cpu32 (dir->ino.chunk), off); + + grub_le_to_cpu32 (dir->ino.dir.chunk), off); if (err) return 0; off += sizeof (dh); @@ -274,7 +287,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, err = read_chunk (dir->data->disk, &di, sizeof (di), grub_le_to_cpu64 (dir->data->sb.diroffset) - + grub_le_to_cpu32 (dir->ino.chunk), off); + + grub_le_to_cpu32 (dir->ino.dir.chunk), off); if (err) return 0; off += sizeof (di); @@ -292,7 +305,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, err = read_chunk (dir->data->disk, buf, grub_le_to_cpu16 (di.namelen) + 1, grub_le_to_cpu64 (dir->data->sb.diroffset) - + grub_le_to_cpu32 (dir->ino.chunk), off); + + grub_le_to_cpu32 (dir->ino.dir.chunk), off); if (err) return 0; @@ -395,7 +408,7 @@ grub_squash_open (struct grub_file *file, const char *name) file->data = data; data->ino = fdiro->ino; - file->size = grub_le_to_cpu32 (fdiro->ino.size); + file->size = grub_le_to_cpu32 (fdiro->ino.file.size); return GRUB_ERR_NONE; } @@ -409,10 +422,10 @@ grub_squash_read_data (struct grub_squash_data *data, grub_uint64_t a, b; int compressed = 0; - if (grub_le_to_cpu16 (ino->fragment) == 0xffff) + if (grub_le_to_cpu16 (ino->file.fragment) == 0xffff) { - if (grub_le_to_cpu32 (ino->chunk)) - a = grub_le_to_cpu32 (ino->chunk); + if (grub_le_to_cpu32 (ino->file.chunk)) + a = grub_le_to_cpu32 (ino->file.chunk); else a = sizeof (struct grub_squash_super); compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_DATA); @@ -422,14 +435,14 @@ grub_squash_read_data (struct grub_squash_data *data, struct grub_squash_frag_desc frag; err = read_chunk (disk, &frag, sizeof (frag), data->fragments, sizeof (frag) - * grub_le_to_cpu16 (ino->fragment)); + * grub_le_to_cpu16 (ino->file.fragment)); if (err) return -1; - a = grub_le_to_cpu64 (frag.offset) + grub_le_to_cpu32 (ino->chunk); + a = grub_le_to_cpu64 (frag.offset) + grub_le_to_cpu32 (ino->file.chunk); compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_FRAGMENTS); } - b = grub_le_to_cpu32 (data->ino.offset) + off; + b = grub_le_to_cpu32 (data->ino.file.offset) + off; /* FIXME: cache uncompressed chunks. */ if (compressed) From e330e4f3830f0c0cab6dfc753c1c9b31c7b909bf Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 9 Dec 2010 21:17:27 +0100 Subject: [PATCH 068/406] support file mtime --- grub-core/fs/squash4.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 409d91e47..9637496d9 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -351,11 +351,13 @@ grub_squash_dir (grub_device_t device, const char *path, int NESTED_FUNC_ATTR iterate (const char *filename, enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node __attribute__ ((unused))) + grub_fshelp_node_t node) { struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = grub_le_to_cpu32 (node->ino.mtime); return hook (filename, &info); } From 4a91cd82203200b8c636f4659905449e5ae1395a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 9 Dec 2010 22:29:36 +0100 Subject: [PATCH 069/406] symlink support --- grub-core/fs/squash4.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 9637496d9..95797998a 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -94,6 +94,11 @@ struct grub_squash_inode grub_uint16_t offset; grub_uint16_t dummy3[2]; } dir; + struct { + grub_uint16_t dummy[4]; + grub_uint32_t namelen; + char name[0]; + } symlink; }; } __attribute__ ((packed)); @@ -114,6 +119,7 @@ struct grub_squash_dirent grub_uint16_t type; #define SQUASH_TYPE_DIR 1 #define SQUASH_TYPE_REGULAR 2 +#define SQUASH_TYPE_SYMLINK 3 /* Actually the value is the length of name - 1. */ grub_uint16_t namelen; char name[0]; @@ -141,6 +147,8 @@ struct grub_fshelp_node { struct grub_squash_data *data; struct grub_squash_inode ino; + grub_uint32_t ino_chunk; + grub_uint16_t ino_offset; }; static grub_err_t @@ -251,6 +259,28 @@ squash_mount (grub_disk_t disk) return data; } +static char * +grub_squash_read_symlink (grub_fshelp_node_t node) +{ + char *ret; + grub_err_t err; + ret = grub_malloc (grub_le_to_cpu32 (node->ino.symlink.namelen) + 1); + + err = read_chunk (node->data->disk, ret, + grub_le_to_cpu32 (node->ino.symlink.namelen), + grub_le_to_cpu64 (node->data->sb.inodeoffset) + + node->ino_chunk, + node->ino_offset + (node->ino.symlink.name + - (char *) &node->ino)); + if (err) + { + grub_free (ret); + return NULL; + } + ret[grub_le_to_cpu32 (node->ino.symlink.namelen)] = 0; + return ret; +} + static int grub_squash_iterate_dir (grub_fshelp_node_t dir, int NESTED_FUNC_ATTR @@ -313,11 +343,17 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, buf[grub_le_to_cpu16 (di.namelen) + 1] = 0; if (grub_le_to_cpu16 (di.type) == SQUASH_TYPE_DIR) filetype = GRUB_FSHELP_DIR; + if (grub_le_to_cpu16 (di.type) == SQUASH_TYPE_SYMLINK) + filetype = GRUB_FSHELP_SYMLINK; + node = grub_malloc (sizeof (*node)); if (! node) return 0; *node = *dir; node->ino = ino; + node->ino_chunk = grub_le_to_cpu32 (dh.ino_chunk); + node->ino_offset = grub_le_to_cpu16 (di.ino_offset); + r = hook (buf, filetype, node); grub_free (buf); @@ -375,7 +411,7 @@ grub_squash_dir (grub_device_t device, const char *path, return err; grub_fshelp_find_file (path, &root, &fdiro, grub_squash_iterate_dir, - NULL, GRUB_FSHELP_DIR); + grub_squash_read_symlink, GRUB_FSHELP_DIR); if (!grub_errno) grub_squash_iterate_dir (fdiro, iterate); @@ -401,7 +437,7 @@ grub_squash_open (struct grub_file *file, const char *name) return err; grub_fshelp_find_file (name, &root, &fdiro, grub_squash_iterate_dir, - NULL, GRUB_FSHELP_REG); + grub_squash_read_symlink, GRUB_FSHELP_REG); if (grub_errno) { grub_free (data); From db64f5b16769168329c3269d5907acca7328de6c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 10 Dec 2010 08:42:40 +0100 Subject: [PATCH 070/406] mtime support for cpio and tar --- grub-core/fs/cpio.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index c087b4f90..486d8215c 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -78,7 +78,7 @@ static grub_dl_t my_mod; static grub_err_t grub_cpio_find_file (struct grub_cpio_data *data, char **name, - grub_uint32_t * ofs) + grub_int32_t *mtime, grub_uint32_t * ofs) { #ifndef MODE_USTAR struct head hd; @@ -91,6 +91,8 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive"); data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2; + if (mtime) + *mtime = (((grub_uint32_t) hd.mtime_1) << 16) + hd.mtime_2; if (hd.namesize & 1) hd.namesize++; @@ -139,6 +141,8 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE; *ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) & ~(GRUB_DISK_SECTOR_SIZE - 1)); + if (mtime) + *mtime = grub_strtoul (hd.mtime, NULL, 8); #endif return GRUB_ERR_NONE; } @@ -204,7 +208,9 @@ grub_cpio_dir (grub_device_t device, const char *path, data->hofs = 0; while (1) { - if (grub_cpio_find_file (data, &name, &ofs)) + grub_int32_t mtime; + + if (grub_cpio_find_file (data, &name, &mtime, &ofs)) goto fail; if (!ofs) @@ -227,6 +233,8 @@ grub_cpio_dir (grub_device_t device, const char *path, struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); info.dir = (p != NULL); + info.mtime = mtime; + info.mtimeset = 1; hook (name + len, &info); if (prev) @@ -269,7 +277,7 @@ grub_cpio_open (grub_file_t file, const char *name) data->hofs = 0; while (1) { - if (grub_cpio_find_file (data, &fn, &ofs)) + if (grub_cpio_find_file (data, &fn, NULL, &ofs)) goto fail; if (!ofs) From a2de6bf6ed9b2e3e4dcc9347f6d780608e11e95c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 10 Dec 2010 10:32:50 +0100 Subject: [PATCH 071/406] filesystem mtime support for iso9660 --- grub-core/fs/iso9660.c | 130 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 6dc465f25..96753ac69 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -27,6 +27,7 @@ #include #include #include +#include #define GRUB_ISO9660_FSTYPE_DIR 0040000 #define GRUB_ISO9660_FSTYPE_REG 0100000 @@ -153,6 +154,108 @@ struct grub_fshelp_node static grub_dl_t my_mod; +#define SECPERMIN 60 +#define SECPERHOUR (60*SECPERMIN) +#define SECPERDAY (24*SECPERHOUR) +#define SECPERYEAR (365*SECPERDAY) +#define SECPER4YEARS (4*SECPERYEAR+SECPERDAY) + +static grub_err_t +grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) +{ + grub_int32_t ret; + int y4, ay; + grub_uint16_t monthssum[12] + = { 0, + 31, + 31 + 28, + 31 + 28 + 31, + 31 + 28 + 31 + 30, + 31 + 28 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30, + 31 + 28 + 31 + 30 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30}; + grub_uint8_t months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + if (datetime->year > 2038 || datetime->year < 1902) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "outside of UNIX epoch"); + if (datetime->month > 12 || datetime->month < 1) + return grub_error (GRUB_ERR_BAD_NUMBER, "not a valid month"); + + /* In the period of validity of unixtime all years divisible by 4 + are bissextile*/ + /* Convenience: let's have 3 consecutive non-bissextile years + at the beginning of the epoch. So count from 1973 instead of 1970 */ + ret = 3*SECPERYEAR + SECPERDAY; + + /* Transform C divisions and modulos to mathematical ones */ + y4 = (datetime->year - 1973) / 4; + if (datetime->year < 1973) + y4--; + ay = datetime->year - 1973 - 4 * y4; + ret += y4 * SECPER4YEARS; + ret += ay * SECPERYEAR; + + ret += monthssum[datetime->month - 1] * SECPERDAY; + if (ay == 0 && datetime->month >= 3) + ret += SECPERDAY; + + ret += (datetime->day - 1) * SECPERDAY; + if ((datetime->day > months[datetime->month - 1] + && (!ay || datetime->month != 2 || datetime->day != 29)) + || datetime->day < 1) + return grub_error (GRUB_ERR_BAD_NUMBER, "invalid day"); + + ret += datetime->hour * SECPERHOUR; + if (datetime->hour > 23) + return grub_error (GRUB_ERR_BAD_NUMBER, "invalid hour"); + ret += datetime->minute * 60; + if (datetime->minute > 59) + return grub_error (GRUB_ERR_BAD_NUMBER, "invalid minute"); + + ret += datetime->second; + /* Accept leap seconds. */ + if (datetime->second > 60) + return grub_error (GRUB_ERR_BAD_NUMBER, "invalid second"); + + if ((datetime->year > 1980 && ret < 0) + || (datetime->year < 1960 && ret > 0)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "outside of UNIX epoch"); + *nix = ret; + return GRUB_ERR_NONE; +} + +static grub_err_t +iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix) +{ + grub_err_t err; + struct grub_datetime datetime; + + if (! i->year[0] && ! i->year[1] + && ! i->year[2] && ! i->year[3] + && ! i->month[0] && ! i->month[1] + && ! i->day[0] && ! i->day[1] + && ! i->hour[0] && ! i->hour[1] + && ! i->minute[0] && ! i->minute[1] + && ! i->second[0] && ! i->second[1] + && ! i->hundredth[0] && ! i->hundredth[1]) + return grub_error (GRUB_ERR_BAD_NUMBER, "empty date"); + datetime.year = (i->year[0] - '0') * 1000 + (i->year[1] - '0') * 100 + + (i->year[2] - '0') * 10 + (i->year[3] - '0'); + datetime.month = (i->month[0] - '0') * 10 + (i->month[1] - '0'); + datetime.day = (i->day[0] - '0') * 10 + (i->day[1] - '0'); + datetime.hour = (i->hour[0] - '0') * 10 + (i->hour[1] - '0'); + datetime.minute = (i->minute[0] - '0') * 10 + (i->minute[1] - '0'); + datetime.second = (i->second[0] - '0') * 10 + (i->second[1] - '0'); + + err = grub_datetime2unixtime (&datetime, nix); + *nix -= i->offset * 60 * 15; + return err; +} + /* Iterate over the susp entries, starting with block SUA_BLOCK on the offset SUA_POS with a size of SUA_SIZE bytes. Hook is called for every entry. */ @@ -871,6 +974,32 @@ grub_iso9660_uuid (grub_device_t device, char **uuid) return grub_errno; } +/* Get writing time of filesystem. */ +static grub_err_t +grub_iso9660_mtime (grub_device_t device, grub_int32_t *timebuf) +{ + struct grub_iso9660_data *data; + grub_disk_t disk = device->disk; + grub_err_t err; + + grub_dl_ref (my_mod); + + data = grub_iso9660_mount (disk); + if (!data) + { + grub_dl_unref (my_mod); + return grub_errno; + } + err = iso9660_to_unixtime (&data->voldesc.modified, timebuf); + + grub_dl_unref (my_mod); + + grub_free (data); + + return err; +} + + static struct grub_fs grub_iso9660_fs = @@ -882,6 +1011,7 @@ static struct grub_fs grub_iso9660_fs = .close = grub_iso9660_close, .label = grub_iso9660_label, .uuid = grub_iso9660_uuid, + .mtime = grub_iso9660_mtime, .next = 0 }; From c50d99c5e531a6a7cedebd6de51d98fcfda5f694 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 10 Dec 2010 11:12:59 +0100 Subject: [PATCH 072/406] file mtime support for iso9660 --- grub-core/fs/iso9660.c | 60 +++++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 96753ac69..03bfd3e92 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -54,6 +54,17 @@ struct grub_iso9660_voldesc grub_uint8_t version; } __attribute__ ((packed)); +struct grub_iso9660_date2 +{ + grub_uint8_t year; + grub_uint8_t month; + grub_uint8_t day; + grub_uint8_t hour; + grub_uint8_t minute; + grub_uint8_t second; + grub_uint8_t offset; +} __attribute__ ((packed)); + /* A directory entry. */ struct grub_iso9660_dir { @@ -63,7 +74,7 @@ struct grub_iso9660_dir grub_uint32_t first_sector_be; grub_uint32_t size; grub_uint32_t size_be; - grub_uint8_t unused1[7]; + struct grub_iso9660_date2 mtime; grub_uint8_t flags; grub_uint8_t unused2[6]; grub_uint8_t namelen; @@ -145,6 +156,7 @@ struct grub_iso9660_data struct grub_fshelp_node { struct grub_iso9660_data *data; + struct grub_iso9660_dir dirent; unsigned int size; unsigned int blk; unsigned int dir_blk; @@ -188,14 +200,14 @@ grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) /* In the period of validity of unixtime all years divisible by 4 are bissextile*/ /* Convenience: let's have 3 consecutive non-bissextile years - at the beginning of the epoch. So count from 1973 instead of 1970 */ - ret = 3*SECPERYEAR + SECPERDAY; + at the beginning of the epoch. So count from 1971 instead of 1970 */ + ret = SECPERYEAR + SECPERDAY; /* Transform C divisions and modulos to mathematical ones */ - y4 = (datetime->year - 1973) / 4; - if (datetime->year < 1973) + y4 = (datetime->year - 1971) / 4; + if (datetime->year < 1971) y4--; - ay = datetime->year - 1973 - 4 * y4; + ay = datetime->year - 1971 - 4 * y4; ret += y4 * SECPER4YEARS; ret += ay * SECPERYEAR; @@ -256,6 +268,24 @@ iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix) return err; } +static grub_err_t +iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix) +{ + grub_err_t err; + struct grub_datetime datetime; + + datetime.year = i->year + 1900; + datetime.month = i->month; + datetime.day = i->day; + datetime.hour = i->hour; + datetime.minute = i->minute; + datetime.second = i->second; + + err = grub_datetime2unixtime (&datetime, nix); + *nix -= i->offset * 60 * 15; + return err; +} + /* Iterate over the susp entries, starting with block SUA_BLOCK on the offset SUA_POS with a size of SUA_SIZE bytes. Hook is called for every entry. */ @@ -467,7 +497,6 @@ grub_iso9660_mount (grub_disk_t disk) static char * grub_iso9660_read_symlink (grub_fshelp_node_t node) { - struct grub_iso9660_dir dirent; int sua_off; int sua_size; char *symlink = 0; @@ -545,13 +574,10 @@ grub_iso9660_read_symlink (grub_fshelp_node_t node) return 0; } - if (grub_disk_read (node->data->disk, node->dir_blk, node->dir_off, - sizeof (dirent), (char *) &dirent)) - return 0; - - sua_off = (sizeof (dirent) + dirent.namelen + 1 - (dirent.namelen % 2) + sua_off = (sizeof (node->dirent) + node->dirent.namelen + 1 + - (node->dirent.namelen % 2) + node->data->susp_skip); - sua_size = dirent.len - sua_off; + sua_size = node->dirent.len - sua_off; symlink = grub_malloc (1); if (!symlink) @@ -748,6 +774,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, filename_alloc = 1; } + node->dirent = dirent; if (hook (filename, type, node)) { if (filename_alloc) @@ -784,8 +811,15 @@ grub_iso9660_dir (grub_device_t device, const char *path, grub_fshelp_node_t node) { struct grub_dirhook_info info; + grub_err_t err; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + err = iso9660_to_unixtime2 (&node->dirent.mtime, &info.mtime); + if (err) + grub_errno = GRUB_ERR_NONE; + else + info.mtimeset = 1; + grub_free (node); return hook (filename, &info); } From 3b95531920bdd3bd96706ef6fb01ee6a0cfab8f1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 10 Dec 2010 15:04:12 +0100 Subject: [PATCH 073/406] fix unix range --- grub-core/fs/iso9660.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 03bfd3e92..3b0da5e53 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -192,7 +192,7 @@ grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30}; grub_uint8_t months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - if (datetime->year > 2038 || datetime->year < 1902) + if (datetime->year > 2038 || datetime->year < 1901) return grub_error (GRUB_ERR_OUT_OF_RANGE, "outside of UNIX epoch"); if (datetime->month > 12 || datetime->month < 1) return grub_error (GRUB_ERR_BAD_NUMBER, "not a valid month"); From 5706da04438db67180e6b08a3f62aa4ba0b58b75 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 10 Dec 2010 16:19:24 +0100 Subject: [PATCH 074/406] mtime support for xfs --- grub-core/fs/xfs.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 9dffe31d1..966bade1b 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -98,13 +98,22 @@ struct grub_xfs_btree_root grub_uint64_t keys[1]; } __attribute__ ((packed)); +struct grub_xfs_time +{ + grub_uint32_t sec; + grub_uint32_t nanosec; +} __attribute__ ((packed)); + struct grub_xfs_inode { grub_uint8_t magic[2]; grub_uint16_t mode; grub_uint8_t version; grub_uint8_t format; - grub_uint8_t unused2[50]; + grub_uint8_t unused2[26]; + struct grub_xfs_time atime; + struct grub_xfs_time mtime; + struct grub_xfs_time ctime; grub_uint64_t size; grub_uint64_t nblocks; grub_uint32_t extsize; @@ -643,6 +652,11 @@ grub_xfs_dir (grub_device_t device, const char *path, { struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); + if (node->inode_read) + { + info.mtimeset = 1; + info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec); + } info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); grub_free (node); return hook (filename, &info); From f22c12e8524f69b3482f6965d8d9b3480b8a9588 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 10 Dec 2010 17:37:32 +0100 Subject: [PATCH 075/406] mtime for UDF support --- grub-core/fs/iso9660.c | 97 ++++------------------------------------- grub-core/fs/udf.c | 29 ++++++++++++ include/grub/datetime.h | 73 +++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 88 deletions(-) diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 3b0da5e53..f2f4b5a97 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -166,84 +166,9 @@ struct grub_fshelp_node static grub_dl_t my_mod; -#define SECPERMIN 60 -#define SECPERHOUR (60*SECPERMIN) -#define SECPERDAY (24*SECPERHOUR) -#define SECPERYEAR (365*SECPERDAY) -#define SECPER4YEARS (4*SECPERYEAR+SECPERDAY) - -static grub_err_t -grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) -{ - grub_int32_t ret; - int y4, ay; - grub_uint16_t monthssum[12] - = { 0, - 31, - 31 + 28, - 31 + 28 + 31, - 31 + 28 + 31 + 30, - 31 + 28 + 31 + 30 + 31, - 31 + 28 + 31 + 30 + 31 + 30, - 31 + 28 + 31 + 30 + 31 + 30 + 31, - 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31, - 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30, - 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, - 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30}; - grub_uint8_t months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - - if (datetime->year > 2038 || datetime->year < 1901) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "outside of UNIX epoch"); - if (datetime->month > 12 || datetime->month < 1) - return grub_error (GRUB_ERR_BAD_NUMBER, "not a valid month"); - - /* In the period of validity of unixtime all years divisible by 4 - are bissextile*/ - /* Convenience: let's have 3 consecutive non-bissextile years - at the beginning of the epoch. So count from 1971 instead of 1970 */ - ret = SECPERYEAR + SECPERDAY; - - /* Transform C divisions and modulos to mathematical ones */ - y4 = (datetime->year - 1971) / 4; - if (datetime->year < 1971) - y4--; - ay = datetime->year - 1971 - 4 * y4; - ret += y4 * SECPER4YEARS; - ret += ay * SECPERYEAR; - - ret += monthssum[datetime->month - 1] * SECPERDAY; - if (ay == 0 && datetime->month >= 3) - ret += SECPERDAY; - - ret += (datetime->day - 1) * SECPERDAY; - if ((datetime->day > months[datetime->month - 1] - && (!ay || datetime->month != 2 || datetime->day != 29)) - || datetime->day < 1) - return grub_error (GRUB_ERR_BAD_NUMBER, "invalid day"); - - ret += datetime->hour * SECPERHOUR; - if (datetime->hour > 23) - return grub_error (GRUB_ERR_BAD_NUMBER, "invalid hour"); - ret += datetime->minute * 60; - if (datetime->minute > 59) - return grub_error (GRUB_ERR_BAD_NUMBER, "invalid minute"); - - ret += datetime->second; - /* Accept leap seconds. */ - if (datetime->second > 60) - return grub_error (GRUB_ERR_BAD_NUMBER, "invalid second"); - - if ((datetime->year > 1980 && ret < 0) - || (datetime->year < 1960 && ret > 0)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "outside of UNIX epoch"); - *nix = ret; - return GRUB_ERR_NONE; -} - static grub_err_t iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix) { - grub_err_t err; struct grub_datetime datetime; if (! i->year[0] && ! i->year[1] @@ -263,17 +188,17 @@ iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix) datetime.minute = (i->minute[0] - '0') * 10 + (i->minute[1] - '0'); datetime.second = (i->second[0] - '0') * 10 + (i->second[1] - '0'); - err = grub_datetime2unixtime (&datetime, nix); + if (!grub_datetime2unixtime (&datetime, nix)) + return grub_error (GRUB_ERR_BAD_NUMBER, "incorrect date"); *nix -= i->offset * 60 * 15; - return err; + return GRUB_ERR_NONE; } -static grub_err_t +static int iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix) { - grub_err_t err; struct grub_datetime datetime; - + datetime.year = i->year + 1900; datetime.month = i->month; datetime.day = i->day; @@ -281,9 +206,10 @@ iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix) datetime.minute = i->minute; datetime.second = i->second; - err = grub_datetime2unixtime (&datetime, nix); + if (!grub_datetime2unixtime (&datetime, nix)) + return 0; *nix -= i->offset * 60 * 15; - return err; + return 1; } /* Iterate over the susp entries, starting with block SUA_BLOCK on the @@ -811,14 +737,9 @@ grub_iso9660_dir (grub_device_t device, const char *path, grub_fshelp_node_t node) { struct grub_dirhook_info info; - grub_err_t err; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - err = iso9660_to_unixtime2 (&node->dirent.mtime, &info.mtime); - if (err) - grub_errno = GRUB_ERR_NONE; - else - info.mtimeset = 1; + info.mtimeset = !!iso9660_to_unixtime2 (&node->dirent.mtime, &info.mtime); grub_free (node); return hook (filename, &info); diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index 7041e619e..0c5da996e 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -26,6 +26,7 @@ #include #include #include +#include #define GRUB_UDF_MAX_PDS 2 #define GRUB_UDF_MAX_PMS 6 @@ -904,8 +905,36 @@ grub_udf_dir (grub_device_t device, const char *path, grub_fshelp_node_t node) { struct grub_dirhook_info info; + const struct grub_udf_timestamp *tstamp = NULL; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + if (U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE) + tstamp = &node->fe.modification_time; + else if (U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_EFE) + tstamp = &node->efe.modification_time; + + if (tstamp && (U16 (tstamp->type_and_timezone) & 0xf000) == 0x1000) + { + grub_int16_t tz; + struct grub_datetime datetime; + + datetime.year = U16 (tstamp->year); + datetime.month = tstamp->month; + datetime.day = tstamp->day; + datetime.hour = tstamp->hour; + datetime.minute = tstamp->minute; + datetime.second = tstamp->second; + + tz = U16 (tstamp->type_and_timezone) & 0xfff; + if (tz & 0x800) + tz |= 0xf000; + if (tz == -2047) + tz = 0; + + info.mtimeset = !!grub_datetime2unixtime (&datetime, &info.mtime); + + info.mtime -= 60 * tz; + } grub_free (node); return hook (filename, &info); } diff --git a/include/grub/datetime.h b/include/grub/datetime.h index e721e89af..c20fc8c36 100644 --- a/include/grub/datetime.h +++ b/include/grub/datetime.h @@ -51,5 +51,78 @@ char *grub_get_weekday_name (struct grub_datetime *datetime); void grub_unixtime2datetime (grub_int32_t nix, struct grub_datetime *datetime); +static inline int +grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) +{ + grub_int32_t ret; + int y4, ay; + const grub_uint16_t monthssum[12] + = { 0, + 31, + 31 + 28, + 31 + 28 + 31, + 31 + 28 + 31 + 30, + 31 + 28 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30, + 31 + 28 + 31 + 30 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30}; + const grub_uint8_t months[12] = {31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31}; + const int SECPERMIN = 60; + const int SECPERHOUR = 60 * SECPERMIN; + const int SECPERDAY = 24 * SECPERHOUR; + const int SECPERYEAR = 365 * SECPERDAY; + const int SECPER4YEARS = 4 * SECPERYEAR + SECPERDAY; + + if (datetime->year > 2038 || datetime->year < 1901) + return 0; + if (datetime->month > 12 || datetime->month < 1) + return 0; + + /* In the period of validity of unixtime all years divisible by 4 + are bissextile*/ + /* Convenience: let's have 3 consecutive non-bissextile years + at the beginning of the epoch. So count from 1971 instead of 1970 */ + ret = SECPERYEAR + SECPERDAY; + + /* Transform C divisions and modulos to mathematical ones */ + y4 = (datetime->year - 1971) / 4; + if (datetime->year < 1971) + y4--; + ay = datetime->year - 1971 - 4 * y4; + ret += y4 * SECPER4YEARS; + ret += ay * SECPERYEAR; + + ret += monthssum[datetime->month - 1] * SECPERDAY; + if (ay == 0 && datetime->month >= 3) + ret += SECPERDAY; + + ret += (datetime->day - 1) * SECPERDAY; + if ((datetime->day > months[datetime->month - 1] + && (!ay || datetime->month != 2 || datetime->day != 29)) + || datetime->day < 1) + return 0; + + ret += datetime->hour * SECPERHOUR; + if (datetime->hour > 23) + return 0; + ret += datetime->minute * 60; + if (datetime->minute > 59) + return 0; + + ret += datetime->second; + /* Accept leap seconds. */ + if (datetime->second > 60) + return 0; + + if ((datetime->year > 1980 && ret < 0) + || (datetime->year < 1960 && ret > 0)) + return 0; + *nix = ret; + return 1; +} #endif /* ! KERNEL_DATETIME_HEADER */ From 52832c554c3f4393819ad8fc67a92efc85fc8562 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 10 Dec 2010 16:45:58 +0000 Subject: [PATCH 076/406] Move gfxmenu color handling to video, so that gfxterm can use it too. * grub-core/gfxmenu/named_colors.c: Move to ... * grub-core/video/colors.c: ... here. Rename grub_gui_get_named_color to grub_video_get_named_color. * grub-core/gfxmenu/gui_string_util.c (my_isxdigit): Move to ... * grub-core/video/colors.c (my_isxdigit): ... here. * grub-core/gfxmenu/gui_string_util.c (parse_hex_color_component): Move to ... * grub-core/video/colors.c (parse_hex_color_component): ... here. * grub-core/gfxmenu/gui_string_util.c (grub_gui_parse_color): Move to ... * grub-core/video/colors.c (grub_video_parse_color): ... here. * include/grub/gui.h (grub_gui_color_t): Move to ... * include/grub/video.h (grub_video_rgba_color_t): ... here. * include/grub/gui.h (grub_gui_color_rgb): Move to ... * include/grub/video.h (grub_video_rgba_color_rgb): ... here. * include/grub/gui.h (grub_gui_map_color): Move to ... * include/grub/video.h (grub_video_map_rgba_color): ... here. * include/grub/gui_string_util.h (grub_gui_get_named_color): Move to ... * include/grub/video.h (grub_video_get_named_color): ... here. * include/grub/gui_string_util.h (grub_gui_parse_color): Move to ... * include/grub/video.h (grub_video_parse_color): ... here. * grub-core/Makefile.core.def (kernel) [videoinkernel]: Add video/colors.c. (gfxmenu): Remove gfxmenu/named_colors.c. (video_colors) [videomodules]: New module, containing video/colors.c. --- ChangeLog.parse-color | 34 +++++ grub-core/Makefile.core.def | 8 +- grub-core/gfxmenu/gui_label.c | 6 +- grub-core/gfxmenu/gui_list.c | 16 +-- grub-core/gfxmenu/gui_progress_bar.c | 31 ++--- grub-core/gfxmenu/gui_string_util.c | 121 ----------------- grub-core/gfxmenu/theme_loader.c | 8 +- grub-core/gfxmenu/view.c | 16 +-- .../named_colors.c => video/colors.c} | 127 +++++++++++++++++- include/grub/gfxmenu_view.h | 8 +- include/grub/gui.h | 27 ---- include/grub/gui_string_util.h | 4 - include/grub/video.h | 32 +++++ 13 files changed, 240 insertions(+), 198 deletions(-) create mode 100644 ChangeLog.parse-color rename grub-core/{gfxmenu/named_colors.c => video/colors.c} (70%) diff --git a/ChangeLog.parse-color b/ChangeLog.parse-color new file mode 100644 index 000000000..93d696c6c --- /dev/null +++ b/ChangeLog.parse-color @@ -0,0 +1,34 @@ +2010-12-10 Colin Watson + + Move gfxmenu color handling to video, so that gfxterm can use it + too. + + * grub-core/gfxmenu/named_colors.c: Move to ... + * grub-core/video/colors.c: ... here. Rename + grub_gui_get_named_color to grub_video_get_named_color. + * grub-core/gfxmenu/gui_string_util.c (my_isxdigit): Move to ... + * grub-core/video/colors.c (my_isxdigit): ... here. + * grub-core/gfxmenu/gui_string_util.c (parse_hex_color_component): + Move to ... + * grub-core/video/colors.c (parse_hex_color_component): ... here. + * grub-core/gfxmenu/gui_string_util.c (grub_gui_parse_color): Move + to ... + * grub-core/video/colors.c (grub_video_parse_color): ... here. + + * include/grub/gui.h (grub_gui_color_t): Move to ... + * include/grub/video.h (grub_video_rgba_color_t): ... here. + * include/grub/gui.h (grub_gui_color_rgb): Move to ... + * include/grub/video.h (grub_video_rgba_color_rgb): ... here. + * include/grub/gui.h (grub_gui_map_color): Move to ... + * include/grub/video.h (grub_video_map_rgba_color): ... here. + * include/grub/gui_string_util.h (grub_gui_get_named_color): Move + to ... + * include/grub/video.h (grub_video_get_named_color): ... here. + * include/grub/gui_string_util.h (grub_gui_parse_color): Move to ... + * include/grub/video.h (grub_video_parse_color): ... here. + + * grub-core/Makefile.core.def (kernel) [videoinkernel]: Add + video/colors.c. + (gfxmenu): Remove gfxmenu/named_colors.c. + (video_colors) [videomodules]: New module, containing + video/colors.c. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 37c0ce970..fdf7d0826 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -178,6 +178,7 @@ kernel = { videoinkernel = io/bufio.c; videoinkernel = video/bitmap.c; videoinkernel = video/bitmap_scale.c; + videoinkernel = video/colors.c; videoinkernel = video/fb/fbblit.c; videoinkernel = video/fb/fbfill.c; videoinkernel = video/fb/fbutil.c; @@ -1049,7 +1050,6 @@ module = { common = gfxmenu/gui_progress_bar.c; common = gfxmenu/gui_util.c; common = gfxmenu/gui_string_util.c; - common = gfxmenu/named_colors.c; }; module = { @@ -1442,6 +1442,12 @@ module = { enable = i386_pc; }; +module = { + name = video_colors; + common = video/colors.c; + enable = videomodules; +}; + module = { name = video_fb; common = video/fb/video_fb.c; diff --git a/grub-core/gfxmenu/gui_label.c b/grub-core/gfxmenu/gui_label.c index 15a352f84..a7dc95afc 100644 --- a/grub-core/gfxmenu/gui_label.c +++ b/grub-core/gfxmenu/gui_label.c @@ -48,7 +48,7 @@ struct grub_gui_label char *text; char *template; grub_font_t font; - grub_gui_color_t color; + grub_video_rgba_color_t color; int value; enum align_mode align; }; @@ -107,7 +107,7 @@ label_paint (void *vself, const grub_video_rect_t *region) grub_gui_set_viewport (&self->bounds, &vpsave); grub_font_draw_string (self->text, self->font, - grub_gui_map_color (self->color), + grub_video_map_rgba_color (self->color), left_x, grub_font_get_ascent (self->font)); grub_gui_restore_viewport (&vpsave); @@ -186,7 +186,7 @@ label_set_property (void *vself, const char *name, const char *value) } else if (grub_strcmp (name, "color") == 0) { - grub_gui_parse_color (value, &self->color); + grub_video_parse_color (value, &self->color); } else if (grub_strcmp (name, "align") == 0) { diff --git a/grub-core/gfxmenu/gui_list.c b/grub-core/gfxmenu/gui_list.c index b6b07dfd6..ca2061795 100644 --- a/grub-core/gfxmenu/gui_list.c +++ b/grub-core/gfxmenu/gui_list.c @@ -41,9 +41,9 @@ struct grub_gui_list_impl int item_spacing; grub_font_t item_font; grub_font_t selected_item_font; - grub_gui_color_t item_color; + grub_video_rgba_color_t item_color; int selected_item_color_set; - grub_gui_color_t selected_item_color; + grub_video_rgba_color_t selected_item_color; int draw_scrollbar; int need_to_recreate_scrollbar; @@ -267,13 +267,13 @@ draw_menu (list_impl_t self, int num_shown_items) (is_selected && self->selected_item_font ? self->selected_item_font : self->item_font); - grub_gui_color_t text_color = + grub_video_rgba_color_t text_color = ((is_selected && self->selected_item_color_set) ? self->selected_item_color : self->item_color); grub_font_draw_string (item_title, font, - grub_gui_map_color (text_color), + grub_video_map_rgba_color (text_color), sel_leftpad + self->icon_width + icon_text_space, (item_top + (item_height - (ascent + descent)) / 2 + ascent)); @@ -429,7 +429,7 @@ list_set_property (void *vself, const char *name, const char *value) } else if (grub_strcmp (name, "item_color") == 0) { - grub_gui_parse_color (value, &self->item_color); + grub_video_parse_color (value, &self->item_color); } else if (grub_strcmp (name, "selected_item_color") == 0) { @@ -439,7 +439,7 @@ list_set_property (void *vself, const char *name, const char *value) } else { - if (grub_gui_parse_color (value, &self->selected_item_color) + if (grub_video_parse_color (value, &self->selected_item_color) == GRUB_ERR_NONE) self->selected_item_color_set = 1; } @@ -562,7 +562,7 @@ grub_gui_list_new (void) { list_impl_t self; grub_font_t default_font; - grub_gui_color_t default_fg_color; + grub_video_rgba_color_t default_fg_color; self = grub_zalloc (sizeof (*self)); if (! self) @@ -574,7 +574,7 @@ grub_gui_list_new (void) self->visible = 1; default_font = grub_font_get ("Unknown Regular 16"); - default_fg_color = grub_gui_color_rgb (0, 0, 0); + default_fg_color = grub_video_rgba_color_rgb (0, 0, 0); self->icon_width = 32; self->icon_height = 32; diff --git a/grub-core/gfxmenu/gui_progress_bar.c b/grub-core/gfxmenu/gui_progress_bar.c index e1b31794f..db89ccbf7 100644 --- a/grub-core/gfxmenu/gui_progress_bar.c +++ b/grub-core/gfxmenu/gui_progress_bar.c @@ -40,10 +40,10 @@ struct grub_gui_progress_bar int show_text; char *template; grub_font_t font; - grub_gui_color_t text_color; - grub_gui_color_t border_color; - grub_gui_color_t bg_color; - grub_gui_color_t fg_color; + grub_video_rgba_color_t text_color; + grub_video_rgba_color_t border_color; + grub_video_rgba_color_t bg_color; + grub_video_rgba_color_t fg_color; char *theme_dir; int need_to_recreate_pixmaps; @@ -109,7 +109,7 @@ draw_filled_rect_bar (grub_gui_progress_bar_t self) f.height = self->bounds.height - 2; /* Border. */ - grub_video_fill_rect (grub_gui_map_color (self->border_color), + grub_video_fill_rect (grub_video_map_rgba_color (self->border_color), f.x - 1, f.y - 1, f.width + 2, f.height + 2); @@ -117,12 +117,12 @@ draw_filled_rect_bar (grub_gui_progress_bar_t self) int barwidth = (f.width * (self->value - self->start) / (self->end - self->start)); - grub_video_fill_rect (grub_gui_map_color (self->bg_color), + grub_video_fill_rect (grub_video_map_rgba_color (self->bg_color), f.x + barwidth, f.y, f.width - barwidth, f.height); /* Bar foreground. */ - grub_video_fill_rect (grub_gui_map_color (self->fg_color), + grub_video_fill_rect (grub_video_map_rgba_color (self->fg_color), f.x, f.y, barwidth, f.height); } @@ -161,7 +161,8 @@ draw_text (grub_gui_progress_bar_t self) if (self->template) { grub_font_t font = self->font; - grub_video_color_t text_color = grub_gui_map_color (self->text_color); + grub_video_color_t text_color = + grub_video_map_rgba_color (self->text_color); int width = self->bounds.width; int height = self->bounds.height; char *text; @@ -298,19 +299,19 @@ progress_bar_set_property (void *vself, const char *name, const char *value) } else if (grub_strcmp (name, "text_color") == 0) { - grub_gui_parse_color (value, &self->text_color); + grub_video_parse_color (value, &self->text_color); } else if (grub_strcmp (name, "border_color") == 0) { - grub_gui_parse_color (value, &self->border_color); + grub_video_parse_color (value, &self->border_color); } else if (grub_strcmp (name, "bg_color") == 0) { - grub_gui_parse_color (value, &self->bg_color); + grub_video_parse_color (value, &self->bg_color); } else if (grub_strcmp (name, "fg_color") == 0) { - grub_gui_parse_color (value, &self->fg_color); + grub_video_parse_color (value, &self->fg_color); } else if (grub_strcmp (name, "bar_style") == 0) { @@ -379,9 +380,9 @@ grub_gui_progress_bar_new (void) self->progress.component.ops = &progress_bar_ops; self->visible = 1; self->font = grub_font_get ("Unknown Regular 16"); - grub_gui_color_t black = { .red = 0, .green = 0, .blue = 0, .alpha = 255 }; - grub_gui_color_t gray = { .red = 128, .green = 128, .blue = 128, .alpha = 255 }; - grub_gui_color_t lightgray = { .red = 200, .green = 200, .blue = 200, .alpha = 255 }; + grub_video_rgba_color_t black = { .red = 0, .green = 0, .blue = 0, .alpha = 255 }; + grub_video_rgba_color_t gray = { .red = 128, .green = 128, .blue = 128, .alpha = 255 }; + grub_video_rgba_color_t lightgray = { .red = 200, .green = 200, .blue = 200, .alpha = 255 }; self->text_color = black; self->border_color = black; self->bg_color = gray; diff --git a/grub-core/gfxmenu/gui_string_util.c b/grub-core/gfxmenu/gui_string_util.c index 8c51e396a..a9a415e31 100644 --- a/grub-core/gfxmenu/gui_string_util.c +++ b/grub-core/gfxmenu/gui_string_util.c @@ -204,124 +204,3 @@ grub_get_dirname (const char *file_path) return grub_new_substring (file_path, 0, last_slash + 1); } - -static __inline int -my_isxdigit (char c) -{ - return ((c >= '0' && c <= '9') - || (c >= 'a' && c <= 'f') - || (c >= 'A' && c <= 'F')); -} - -static int -parse_hex_color_component (const char *s, unsigned start, unsigned end) -{ - unsigned len; - char buf[3]; - - len = end - start; - /* Check the limits so we don't overrun the buffer. */ - if (len < 1 || len > 2) - return 0; - - if (len == 1) - { - buf[0] = s[start]; /* Get the first and only hex digit. */ - buf[1] = buf[0]; /* Duplicate the hex digit. */ - } - else if (len == 2) - { - buf[0] = s[start]; - buf[1] = s[start + 1]; - } - - buf[2] = '\0'; - - return grub_strtoul (buf, 0, 16); -} - -/* Parse a color string of the form "r, g, b", "#RGB", "#RGBA", - "#RRGGBB", or "#RRGGBBAA". */ -grub_err_t -grub_gui_parse_color (const char *s, grub_gui_color_t *color) -{ - grub_gui_color_t c; - - /* Skip whitespace. */ - while (*s && grub_isspace (*s)) - s++; - - if (*s == '#') - { - /* HTML-style. Number if hex digits: - [6] #RRGGBB [3] #RGB - [8] #RRGGBBAA [4] #RGBA */ - - s++; /* Skip the '#'. */ - /* Count the hexits to determine the format. */ - int hexits = 0; - const char *end = s; - while (my_isxdigit (*end)) - { - end++; - hexits++; - } - - /* Parse the color components based on the format. */ - if (hexits == 3 || hexits == 4) - { - c.red = parse_hex_color_component (s, 0, 1); - c.green = parse_hex_color_component (s, 1, 2); - c.blue = parse_hex_color_component (s, 2, 3); - if (hexits == 4) - c.alpha = parse_hex_color_component (s, 3, 4); - else - c.alpha = 255; - } - else if (hexits == 6 || hexits == 8) - { - c.red = parse_hex_color_component (s, 0, 2); - c.green = parse_hex_color_component (s, 2, 4); - c.blue = parse_hex_color_component (s, 4, 6); - if (hexits == 8) - c.alpha = parse_hex_color_component (s, 6, 8); - else - c.alpha = 255; - } - else - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid HTML-type color string `%s'", s); - } - else if (grub_isdigit (*s)) - { - /* Comma separated decimal values. */ - c.red = grub_strtoul (s, 0, 0); - if ((s = grub_strchr (s, ',')) == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "missing 1st comma separator in color `%s'", s); - s++; - c.green = grub_strtoul (s, 0, 0); - if ((s = grub_strchr (s, ',')) == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "missing 2nd comma separator in color `%s'", s); - s++; - c.blue = grub_strtoul (s, 0, 0); - if ((s = grub_strchr (s, ',')) == 0) - c.alpha = 255; - else - { - s++; - c.alpha = grub_strtoul (s, 0, 0); - } - } - else - { - if (! grub_gui_get_named_color (s, &c)) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid named color `%s'", s); - } - - if (grub_errno == GRUB_ERR_NONE) - *color = c; - return grub_errno; -} diff --git a/grub-core/gfxmenu/theme_loader.c b/grub-core/gfxmenu/theme_loader.c index 3854c6c53..f9c711d3e 100644 --- a/grub-core/gfxmenu/theme_loader.c +++ b/grub-core/gfxmenu/theme_loader.c @@ -135,11 +135,11 @@ theme_set_string (grub_gfxmenu_view_t view, return grub_errno; } else if (! grub_strcmp ("title-color", name)) - grub_gui_parse_color (value, &view->title_color); + grub_video_parse_color (value, &view->title_color); else if (! grub_strcmp ("message-color", name)) - grub_gui_parse_color (value, &view->message_color); + grub_video_parse_color (value, &view->message_color); else if (! grub_strcmp ("message-bg-color", name)) - grub_gui_parse_color (value, &view->message_bg_color); + grub_video_parse_color (value, &view->message_bg_color); else if (! grub_strcmp ("desktop-image", name)) { struct grub_video_bitmap *raw_bitmap; @@ -170,7 +170,7 @@ theme_set_string (grub_gfxmenu_view_t view, view->desktop_image = scaled_bitmap; } else if (! grub_strcmp ("desktop-color", name)) - grub_gui_parse_color (value, &view->desktop_color); + grub_video_parse_color (value, &view->desktop_color); else if (! grub_strcmp ("terminal-box", name)) { grub_err_t err; diff --git a/grub-core/gfxmenu/view.c b/grub-core/gfxmenu/view.c index 901cdc889..836a9884d 100644 --- a/grub-core/gfxmenu/view.c +++ b/grub-core/gfxmenu/view.c @@ -50,8 +50,8 @@ grub_gfxmenu_view_new (const char *theme_path, { grub_gfxmenu_view_t view; grub_font_t default_font; - grub_gui_color_t default_fg_color; - grub_gui_color_t default_bg_color; + grub_video_rgba_color_t default_fg_color; + grub_video_rgba_color_t default_bg_color; view = grub_malloc (sizeof (*view)); if (! view) @@ -63,8 +63,8 @@ grub_gfxmenu_view_new (const char *theme_path, view->screen.height = height; default_font = grub_font_get ("Unknown Regular 16"); - default_fg_color = grub_gui_color_rgb (0, 0, 0); - default_bg_color = grub_gui_color_rgb (255, 255, 255); + default_fg_color = grub_video_rgba_color_rgb (0, 0, 0); + default_bg_color = grub_video_rgba_color_rgb (255, 255, 255); view->canvas = 0; @@ -131,7 +131,7 @@ redraw_background (grub_gfxmenu_view_t view, } else { - grub_video_fill_rect (grub_gui_map_color (view->desktop_color), + grub_video_fill_rect (grub_video_map_rgba_color (view->desktop_color), bounds->x, bounds->y, bounds->width, bounds->height); } @@ -150,7 +150,7 @@ draw_title (grub_gfxmenu_view_t view) int y = 40 + grub_font_get_ascent (view->title_font); grub_font_draw_string (view->title_text, view->title_font, - grub_gui_map_color (view->title_color), + grub_video_map_rgba_color (view->title_color), x, y); } @@ -244,13 +244,13 @@ draw_message (grub_gfxmenu_view_t view) return; grub_font_t font = view->message_font; - grub_video_color_t color = grub_gui_map_color (view->message_color); + grub_video_color_t color = grub_video_map_rgba_color (view->message_color); /* Border. */ grub_video_fill_rect (color, f.x-1, f.y-1, f.width+2, f.height+2); /* Fill. */ - grub_video_fill_rect (grub_gui_map_color (view->message_bg_color), + grub_video_fill_rect (grub_video_map_rgba_color (view->message_bg_color), f.x, f.y, f.width, f.height); /* Center the text. */ diff --git a/grub-core/gfxmenu/named_colors.c b/grub-core/video/colors.c similarity index 70% rename from grub-core/gfxmenu/named_colors.c rename to grub-core/video/colors.c index eedbc47fb..0637c5508 100644 --- a/grub-core/gfxmenu/named_colors.c +++ b/grub-core/video/colors.c @@ -25,7 +25,7 @@ struct named_color { const char *name; - grub_gui_color_t color; + grub_video_rgba_color_t color; }; /* @@ -193,8 +193,8 @@ static struct named_color named_colors[] = stores the color into *COLOR. If the color was not found, returns 0 and does not modify *COLOR. */ int -grub_gui_get_named_color (const char *name, - grub_gui_color_t *color) +grub_video_get_named_color (const char *name, + grub_video_rgba_color_t *color) { int i; for (i = 0; named_colors[i].name; i++) @@ -207,3 +207,124 @@ grub_gui_get_named_color (const char *name, } return 0; } + +static __inline int +my_isxdigit (char c) +{ + return ((c >= '0' && c <= '9') + || (c >= 'a' && c <= 'f') + || (c >= 'A' && c <= 'F')); +} + +static int +parse_hex_color_component (const char *s, unsigned start, unsigned end) +{ + unsigned len; + char buf[3]; + + len = end - start; + /* Check the limits so we don't overrun the buffer. */ + if (len < 1 || len > 2) + return 0; + + if (len == 1) + { + buf[0] = s[start]; /* Get the first and only hex digit. */ + buf[1] = buf[0]; /* Duplicate the hex digit. */ + } + else if (len == 2) + { + buf[0] = s[start]; + buf[1] = s[start + 1]; + } + + buf[2] = '\0'; + + return grub_strtoul (buf, 0, 16); +} + +/* Parse a color string of the form "r, g, b", "#RGB", "#RGBA", + "#RRGGBB", or "#RRGGBBAA". */ +grub_err_t +grub_video_parse_color (const char *s, grub_video_rgba_color_t *color) +{ + grub_video_rgba_color_t c; + + /* Skip whitespace. */ + while (*s && grub_isspace (*s)) + s++; + + if (*s == '#') + { + /* HTML-style. Number if hex digits: + [6] #RRGGBB [3] #RGB + [8] #RRGGBBAA [4] #RGBA */ + + s++; /* Skip the '#'. */ + /* Count the hexits to determine the format. */ + int hexits = 0; + const char *end = s; + while (my_isxdigit (*end)) + { + end++; + hexits++; + } + + /* Parse the color components based on the format. */ + if (hexits == 3 || hexits == 4) + { + c.red = parse_hex_color_component (s, 0, 1); + c.green = parse_hex_color_component (s, 1, 2); + c.blue = parse_hex_color_component (s, 2, 3); + if (hexits == 4) + c.alpha = parse_hex_color_component (s, 3, 4); + else + c.alpha = 255; + } + else if (hexits == 6 || hexits == 8) + { + c.red = parse_hex_color_component (s, 0, 2); + c.green = parse_hex_color_component (s, 2, 4); + c.blue = parse_hex_color_component (s, 4, 6); + if (hexits == 8) + c.alpha = parse_hex_color_component (s, 6, 8); + else + c.alpha = 255; + } + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "invalid HTML-type color string `%s'", s); + } + else if (grub_isdigit (*s)) + { + /* Comma separated decimal values. */ + c.red = grub_strtoul (s, 0, 0); + if ((s = grub_strchr (s, ',')) == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "missing 1st comma separator in color `%s'", s); + s++; + c.green = grub_strtoul (s, 0, 0); + if ((s = grub_strchr (s, ',')) == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "missing 2nd comma separator in color `%s'", s); + s++; + c.blue = grub_strtoul (s, 0, 0); + if ((s = grub_strchr (s, ',')) == 0) + c.alpha = 255; + else + { + s++; + c.alpha = grub_strtoul (s, 0, 0); + } + } + else + { + if (! grub_video_get_named_color (s, &c)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "invalid named color `%s'", s); + } + + if (grub_errno == GRUB_ERR_NONE) + *color = c; + return grub_errno; +} diff --git a/include/grub/gfxmenu_view.h b/include/grub/gfxmenu_view.h index c52a3c71c..f858e9d49 100644 --- a/include/grub/gfxmenu_view.h +++ b/include/grub/gfxmenu_view.h @@ -87,11 +87,11 @@ struct grub_gfxmenu_view grub_font_t title_font; grub_font_t message_font; char *terminal_font_name; - grub_gui_color_t title_color; - grub_gui_color_t message_color; - grub_gui_color_t message_bg_color; + grub_video_rgba_color_t title_color; + grub_video_rgba_color_t message_color; + grub_video_rgba_color_t message_bg_color; struct grub_video_bitmap *desktop_image; - grub_gui_color_t desktop_color; + grub_video_rgba_color_t desktop_color; grub_gfxmenu_box_t terminal_box; char *title_text; char *progress_message_text; diff --git a/include/grub/gui.h b/include/grub/gui.h index 6e4a11cbe..ef0795cf7 100644 --- a/include/grub/gui.h +++ b/include/grub/gui.h @@ -31,16 +31,6 @@ status changes. */ #define GRUB_GFXMENU_TIMEOUT_COMPONENT_ID "__timeout__" -/* A representation of a color. Unlike grub_video_color_t, this - representation is independent of any video mode specifics. */ -typedef struct grub_gui_color -{ - grub_uint8_t red; - grub_uint8_t green; - grub_uint8_t blue; - grub_uint8_t alpha; -} grub_gui_color_t; - typedef struct grub_gui_component *grub_gui_component_t; typedef struct grub_gui_container *grub_gui_container_t; typedef struct grub_gui_list *grub_gui_list_t; @@ -242,23 +232,6 @@ grub_gui_set_viewport (const grub_video_rect_t *r, grub_video_rect_t *old) r->height); } -static __inline grub_gui_color_t -grub_gui_color_rgb (int r, int g, int b) -{ - grub_gui_color_t c; - c.red = r; - c.green = g; - c.blue = b; - c.alpha = 255; - return c; -} - -static __inline grub_video_color_t -grub_gui_map_color (grub_gui_color_t c) -{ - return grub_video_map_rgba (c.red, c.green, c.blue, c.alpha); -} - static inline int grub_video_have_common_points (const grub_video_rect_t *a, const grub_video_rect_t *b) diff --git a/include/grub/gui_string_util.h b/include/grub/gui_string_util.h index 1baa2eede..34f9a090d 100644 --- a/include/grub/gui_string_util.h +++ b/include/grub/gui_string_util.h @@ -30,8 +30,4 @@ char *grub_resolve_relative_path (const char *base, const char *path); char *grub_get_dirname (const char *file_path); -int grub_gui_get_named_color (const char *name, grub_gui_color_t *color); - -grub_err_t grub_gui_parse_color (const char *s, grub_gui_color_t *color); - #endif /* GRUB_GUI_STRING_UTIL_HEADER */ diff --git a/include/grub/video.h b/include/grub/video.h index 5350d87eb..97bd85bd1 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -27,6 +27,15 @@ specific coding format. */ typedef grub_uint32_t grub_video_color_t; +/* Video color in hardware independent format. */ +typedef struct grub_video_rgba_color +{ + grub_uint8_t red; + grub_uint8_t green; + grub_uint8_t blue; + grub_uint8_t alpha; +} grub_video_rgba_color_t; + /* This structure is driver specific and should not be accessed directly by outside code. */ struct grub_video_render_target; @@ -428,4 +437,27 @@ grub_video_check_mode_flag (grub_video_mode_type_t flags, grub_video_driver_id_t EXPORT_FUNC (grub_video_get_driver_id) (void); +static __inline grub_video_rgba_color_t +grub_video_rgba_color_rgb (int r, int g, int b) +{ + grub_video_rgba_color_t c; + c.red = r; + c.green = g; + c.blue = b; + c.alpha = 255; + return c; +} + +static __inline grub_video_color_t +grub_video_map_rgba_color (grub_video_rgba_color_t c) +{ + return grub_video_map_rgba (c.red, c.green, c.blue, c.alpha); +} + +int EXPORT_FUNC (grub_video_get_named_color) (const char *name, + grub_video_rgba_color_t *color); + +grub_err_t EXPORT_FUNC (grub_video_parse_color) (const char *s, + grub_video_rgba_color_t *color); + #endif /* ! GRUB_VIDEO_HEADER */ From f8e2e451e6e19fa94b9e7cc331104eae9b29135d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 10 Dec 2010 18:34:46 +0100 Subject: [PATCH 077/406] handle UTF16 UDF label --- grub-core/fs/udf.c | 68 ++++++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index 0c5da996e..aaf1565f7 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -789,6 +789,43 @@ fail: return 0; } +static char * +read_string (grub_uint8_t *raw, grub_size_t sz) +{ + grub_uint16_t *utf16; + char *ret; + grub_size_t utf16len = 0; + + if (raw[0] != 8 && raw[0] != 16) + return NULL; + + if (raw[0] == 8) + { + unsigned i; + utf16len = sz - 1; + utf16 = grub_malloc (utf16len * sizeof (utf16[0])); + if (!utf16) + return NULL; + for (i = 0; i < utf16len; i++) + utf16[i] = raw[i + 1]; + } + if (raw[0] == 16) + { + unsigned i; + utf16len = (sz - 1) / 2; + utf16 = grub_malloc (utf16len * sizeof (utf16[0])); + if (!utf16) + return NULL; + for (i = 0; i < utf16len; i++) + utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; + } + ret = grub_malloc (utf16len * 3 + 1); + if (ret) + *grub_utf16_to_utf8 ((grub_uint8_t *) ret, utf16, utf16len) = '\0'; + grub_free (utf16); + return ret; +} + static int grub_udf_iterate_dir (grub_fshelp_node_t dir, int NESTED_FUNC_ATTR @@ -842,10 +879,8 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, else { enum grub_fshelp_filetype type; + char *filename; grub_uint8_t raw[dirent.file_ident_length]; - grub_uint16_t utf16[dirent.file_ident_length - 1]; - grub_uint8_t filename[dirent.file_ident_length * 2]; - grub_size_t utf16len = 0; type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ? (GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG)); @@ -856,27 +891,14 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, != dirent.file_ident_length) return 0; - if (raw[0] == 8) - { - unsigned i; - utf16len = dirent.file_ident_length - 1; - for (i = 0; i < utf16len; i++) - utf16[i] = raw[i + 1]; - } - if (raw[0] == 16) - { - unsigned i; - utf16len = (dirent.file_ident_length - 1) / 2; - for (i = 0; i < utf16len; i++) - utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; - } - if (raw[0] == 8 || raw[0] == 16) - { - *grub_utf16_to_utf8 (filename, utf16, utf16len) = '\0'; + filename = read_string (raw, dirent.file_ident_length); - if (hook ((char *) filename, type, child)) - return 1; + if (filename && hook (filename, type, child)) + { + grub_free (filename); + return 1; } + grub_free (filename); } } @@ -1033,7 +1055,7 @@ grub_udf_label (grub_device_t device, char **label) if (data) { - *label = grub_strdup ((char *) &data->lvd.ident[1]); + *label = read_string (data->lvd.ident, sizeof (data->lvd.ident)); grub_free (data); } else From 9c55cbe8e70353e078b884b7c8d86f3e7ccf0ada Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 10 Dec 2010 17:47:38 +0000 Subject: [PATCH 078/406] Add a background_color command. * grub-core/term/gfxterm.c (grub_gfxterm_background_color_cmd): New function. (GRUB_MOD_INIT): Register background_color command. (GRUB_MOD_FINI): Unregister background_color command. --- ChangeLog.parse-color | 7 +++++ grub-core/term/gfxterm.c | 63 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/ChangeLog.parse-color b/ChangeLog.parse-color index 93d696c6c..ccba06d3c 100644 --- a/ChangeLog.parse-color +++ b/ChangeLog.parse-color @@ -32,3 +32,10 @@ (gfxmenu): Remove gfxmenu/named_colors.c. (video_colors) [videomodules]: New module, containing video/colors.c. + + Add a background_color command. + + * grub-core/term/gfxterm.c (grub_gfxterm_background_color_cmd): New + function. + (GRUB_MOD_INIT): Register background_color command. + (GRUB_MOD_FINI): Unregister background_color command. diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c index 9a10d47b0..93367f2bb 100644 --- a/grub-core/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -1180,6 +1180,62 @@ grub_gfxterm_background_image_cmd (grub_extcmd_context_t ctxt, return grub_errno; } +static grub_err_t +grub_gfxterm_background_color_cmd (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_video_rgba_color_t color; + grub_uint8_t *data; + unsigned int i; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing operand"); + + /* Check that we have video adapter active. */ + if (grub_video_get_info (NULL) != GRUB_ERR_NONE) + return grub_errno; + + if (grub_video_parse_color (args[0], &color) != GRUB_ERR_NONE) + return grub_errno; + + /* Destroy existing background bitmap if loaded. */ + if (bitmap) + { + grub_video_bitmap_destroy (bitmap); + bitmap = 0; + + /* Mark whole screen as dirty. */ + dirty_region_add (0, 0, window.width, window.height); + } + + /* Create a filled bitmap so that we get suitable text blending. */ + grub_video_bitmap_create (&bitmap, window.width, window.height, + GRUB_VIDEO_BLIT_FORMAT_RGB_888); + if (grub_errno != GRUB_ERR_NONE) + return grub_errno; + + data = bitmap->data; + for (i = 0; i < window.height * window.width; i++) + { + *data++ = color.red; + *data++ = color.green; + *data++ = color.blue; + } + + bitmap_width = window.width; + bitmap_height = window.height; + + /* Set the border color. */ + virtual_screen.bg_color_display = grub_video_map_rgba_color (color); + + /* Mark whole screen as dirty. */ + dirty_region_add (0, 0, window.width, window.height); + + /* All was ok. */ + grub_errno = GRUB_ERR_NONE; + return grub_errno; +} + static struct grub_term_output grub_video_term = { .name = "gfxterm", @@ -1201,6 +1257,7 @@ static struct grub_term_output grub_video_term = }; static grub_extcmd_t background_image_cmd_handle; +static grub_command_t background_color_cmd_handle; GRUB_MOD_INIT(gfxterm) { @@ -1211,10 +1268,16 @@ GRUB_MOD_INIT(gfxterm) N_("[-m (stretch|normal)] FILE"), N_("Load background image for active terminal."), background_image_cmd_options); + background_color_cmd_handle = + grub_register_command ("background_color", + grub_gfxterm_background_color_cmd, + N_("COLOR"), + N_("Set background color for active terminal.")); } GRUB_MOD_FINI(gfxterm) { + grub_unregister_command (background_color_cmd_handle); grub_unregister_extcmd (background_image_cmd_handle); grub_term_unregister_output (&grub_video_term); } From 591baceb34e93e0ebef73f24f581414472804548 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 06:04:21 +0100 Subject: [PATCH 079/406] UDF symlink support --- grub-core/fs/udf.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index aaf1565f7..48aeca3c8 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -884,6 +884,8 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ? (GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG)); + if (child->fe.icbtag.file_type == GRUB_UDF_ICBTAG_TYPE_SYMLINK) + type = GRUB_FSHELP_SYMLINK; if ((grub_udf_read_file (dir, 0, offset, dirent.file_ident_length, @@ -909,6 +911,25 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, return 0; } +static char * +grub_ufs_read_symlink (grub_fshelp_node_t node) +{ + grub_size_t sz = U64 (node->fe.file_size); + grub_uint8_t *raw; + char *ret; + + if (sz < 4) + return NULL; + raw = grub_malloc (sz - 4); + if (!raw) + return NULL; + if (grub_udf_read_file (node, NULL, 4, sz - 4, (char *) raw) < 0) + return NULL; + ret = read_string (raw, sz - 4); + grub_free (raw); + return ret; +} + static grub_err_t grub_udf_dir (grub_device_t device, const char *path, int (*hook) (const char *filename, @@ -972,7 +993,8 @@ grub_udf_dir (grub_device_t device, const char *path, if (grub_fshelp_find_file (path, &rootnode, &foundnode, - grub_udf_iterate_dir, 0, GRUB_FSHELP_DIR)) + grub_udf_iterate_dir, grub_ufs_read_symlink, + GRUB_FSHELP_DIR)) goto fail; grub_udf_iterate_dir (foundnode, iterate); @@ -1006,7 +1028,8 @@ grub_udf_open (struct grub_file *file, const char *name) if (grub_fshelp_find_file (name, &rootnode, &foundnode, - grub_udf_iterate_dir, 0, GRUB_FSHELP_REG)) + grub_udf_iterate_dir, grub_ufs_read_symlink, + GRUB_FSHELP_REG)) goto fail; file->data = foundnode; From 88db5b694a1fe9772fb21afe24d1dadbb6a1254f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 06:23:33 +0100 Subject: [PATCH 080/406] file mtime support for reiserfs --- grub-core/fs/reiserfs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c index e92279554..443d71b6f 100644 --- a/grub-core/fs/reiserfs.c +++ b/grub-core/fs/reiserfs.c @@ -222,6 +222,7 @@ struct grub_fshelp_node grub_uint32_t block_number; /* 0 if node is not found. */ grub_uint16_t block_position; grub_uint64_t next_offset; + grub_int32_t mtime; enum grub_reiserfs_item_type type; /* To know how to read the header. */ struct grub_reiserfs_item_header header; }; @@ -868,6 +869,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, entry_v1_stat.rdev, entry_v1_stat.first_direct_byte); #endif + entry_item->mtime = grub_le_to_cpu32 (entry_v1_stat.mtime); if ((grub_le_to_cpu16 (entry_v1_stat.mode) & S_IFLNK) == S_IFLNK) entry_type = GRUB_FSHELP_SYMLINK; @@ -914,6 +916,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, entry_v2_stat.blocks, entry_v2_stat.first_direct_byte); #endif + entry_item->mtime = grub_le_to_cpu32 (entry_v2_stat.mtime); if ((grub_le_to_cpu16 (entry_v2_stat.mode) & S_IFLNK) == S_IFLNK) entry_type = GRUB_FSHELP_SYMLINK; @@ -1276,6 +1279,8 @@ grub_reiserfs_dir (grub_device_t device, const char *path, struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = node->mtime; grub_free (node); return hook (filename, &info); } From ebec6850b9a62caa24cc886bdaf647c5a731f4b2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 07:00:31 +0100 Subject: [PATCH 081/406] HFS filesystem mtime support --- grub-core/fs/hfs.c | 18 ++++++++++++++++++ include/grub/hfs.h | 4 +++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index cef856326..a40171dbd 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -1072,6 +1072,23 @@ grub_hfs_label (grub_device_t device, char **label) return grub_errno; } +static grub_err_t +grub_hfs_mtime (grub_device_t device, grub_int32_t *tm) +{ + struct grub_hfs_data *data; + + data = grub_hfs_mount (device->disk); + + if (data) + *tm = grub_be_to_cpu32 (data->sblock.mtime) - 2082844800; + else + *tm = 0; + + grub_free (data); + return grub_errno; +} + + static grub_err_t grub_hfs_uuid (grub_device_t device, char **uuid) { @@ -1107,6 +1124,7 @@ static struct grub_fs grub_hfs_fs = .close = grub_hfs_close, .label = grub_hfs_label, .uuid = grub_hfs_uuid, + .mtime = grub_hfs_mtime, .next = 0 }; diff --git a/include/grub/hfs.h b/include/grub/hfs.h index d93b9a2c9..bf98610d9 100644 --- a/include/grub/hfs.h +++ b/include/grub/hfs.h @@ -39,7 +39,9 @@ typedef struct grub_hfs_extent grub_hfs_datarecord_t[3]; struct grub_hfs_sblock { grub_uint16_t magic; - grub_uint8_t unused[18]; + grub_uint32_t ctime; + grub_uint32_t mtime; + grub_uint8_t unused[10]; grub_uint32_t blksz; grub_uint8_t unused2[4]; grub_uint16_t first_block; From 58fa13fc7c03fdc605103e9a476267dcc3fe7190 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 07:15:44 +0100 Subject: [PATCH 082/406] HFS mtime support --- grub-core/fs/hfs.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index a40171dbd..e4cc23c17 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -131,6 +131,8 @@ struct grub_hfs_dirrec grub_uint8_t type; grub_uint8_t unused[5]; grub_uint32_t dirid; + grub_uint32_t ctime; + grub_uint32_t mtime; } __attribute__ ((packed)); /* Information about a file. */ @@ -142,7 +144,9 @@ struct grub_hfs_filerec grub_uint32_t fileid; grub_uint8_t unused2[2]; grub_uint32_t size; - grub_uint8_t unused3[44]; + grub_uint8_t unused3[18]; + grub_uint32_t mtime; + grub_uint8_t unused4[22]; /* The first 3 extents of the file. The other extents can be found in the extent overflow file. */ @@ -951,19 +955,29 @@ grub_hfs_dir (grub_device_t device, const char *path, int dir_hook (struct grub_hfs_record *rec) { char fname[32] = { 0 }; - char *filetype = rec->data; + struct grub_hfs_dirrec *drec = rec->data; + struct grub_hfs_filerec *frec = rec->data; struct grub_hfs_catalog_key *ckey = rec->key; struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); grub_strncpy (fname, (char *) (ckey->str), ckey->strlen); - if (*filetype == GRUB_HFS_FILETYPE_DIR - || *filetype == GRUB_HFS_FILETYPE_FILE) + if (drec->type == GRUB_HFS_FILETYPE_DIR) { - info.dir = (*filetype == GRUB_HFS_FILETYPE_DIR); + info.dir = 1; + info.mtimeset = 1; + info.mtime = grub_be_to_cpu32 (drec->mtime) - 2082844800; return hook (fname, &info); } + if (frec->type == GRUB_HFS_FILETYPE_FILE) + { + info.dir = 0; + info.mtimeset = 1; + info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800; + return hook (fname, &info); + } + return 0; } @@ -1088,7 +1102,6 @@ grub_hfs_mtime (grub_device_t device, grub_int32_t *tm) return grub_errno; } - static grub_err_t grub_hfs_uuid (grub_device_t device, char **uuid) { From 7ac6c4842d57817bd35c74d49668422c9f43ba7a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 14:26:34 +0100 Subject: [PATCH 083/406] JFS mtime support --- grub-core/fs/jfs.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index 76ef2e540..9e45f56d2 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -153,6 +153,12 @@ struct grub_jfs_leaf_next_dirent grub_uint16_t namepart[15]; } __attribute__ ((packed)); +struct grub_jfs_time +{ + grub_int32_t sec; + grub_int32_t nanosec; +} __attribute__ ((packed)); + struct grub_jfs_inode { grub_uint32_t stamp; @@ -162,7 +168,10 @@ struct grub_jfs_inode grub_uint64_t size; grub_uint8_t unused2[20]; grub_uint32_t mode; - grub_uint8_t unused3[72]; + struct grub_jfs_time atime; + struct grub_jfs_time ctime; + struct grub_jfs_time mtime; + grub_uint8_t unused3[48]; grub_uint8_t unused4[96]; union @@ -751,6 +760,8 @@ grub_jfs_dir (grub_device_t device, const char *path, info.dir = (grub_le_to_cpu32 (inode.mode) & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR; + info.mtimeset = 1; + info.mtime = grub_le_to_cpu32 (inode.mtime.sec); if (hook (diro->name, &info)) goto fail; } From f5ff296240e8575a35b14fc3ec8ca8263b6161c4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 17:46:16 +0100 Subject: [PATCH 084/406] minix mtime support --- grub-core/fs/minix.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 679e1ec51..e0ca09bd7 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -480,6 +480,13 @@ grub_minix_dir (grub_device_t device, const char *path, grub_minix_read_inode (data, grub_le_to_cpu16 (ino)); info.dir = ((GRUB_MINIX_INODE_MODE (data) & GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR); + info.mtimeset = 1; +#ifndef MODE_MINIX2 + info.mtime = grub_le_to_cpu32 (data->inode.ctime); +#else + info.mtime = grub_le_to_cpu32 (data->inode.mtime); +#endif + if (hook (filename, &info) ? 1 : 0) break; From 4aab26313076d3fdb10264cd0b38d9d51741646f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 18:20:45 +0100 Subject: [PATCH 085/406] SquashFS mtime support --- grub-core/fs/squash4.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 95797998a..882f5c959 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -509,6 +509,19 @@ grub_squash_close (grub_file_t file) return GRUB_ERR_NONE; } +static grub_err_t +grub_squash_mtime (grub_device_t dev, grub_int32_t *tm) +{ + struct grub_squash_data *data = 0; + + data = squash_mount (dev->disk); + if (! data) + return grub_errno; + *tm = grub_le_to_cpu32 (data->sb.creation_time); + grub_free (data); + return GRUB_ERR_NONE; +} + static struct grub_fs grub_squash_fs = { .name = "squash4", @@ -516,6 +529,7 @@ static struct grub_fs grub_squash_fs = .open = grub_squash_open, .read = grub_squash_read, .close = grub_squash_close, + .mtime = grub_squash_mtime, #ifdef GRUB_UTIL .reserved_first_sector = 0, #endif From 80113a62583c1c1622a1ed2d7ea73dfe2b72e4ce Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 18:21:39 +0100 Subject: [PATCH 086/406] declare AFFS, CPIO, TAR and XFS as non-installable explicitly --- grub-core/fs/affs.c | 3 +++ grub-core/fs/cpio.c | 3 +++ grub-core/fs/xfs.c | 3 +++ 3 files changed, 9 insertions(+) diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 3dc80752d..27e03c0c4 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -535,6 +535,9 @@ static struct grub_fs grub_affs_fs = .read = grub_affs_read, .close = grub_affs_close, .label = grub_affs_label, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif .next = 0 }; diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index 486d8215c..a6c7a1261 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -362,6 +362,9 @@ static struct grub_fs grub_cpio_fs = { .open = grub_cpio_open, .read = grub_cpio_read, .close = grub_cpio_close, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif }; #ifdef MODE_USTAR diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 966bade1b..dbe957470 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -822,6 +822,9 @@ static struct grub_fs grub_xfs_fs = .close = grub_xfs_close, .label = grub_xfs_label, .uuid = grub_xfs_uuid, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif .next = 0 }; From ea17ec49ae1d5d20b93ad7f1c303aa4d1c0682ff Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 18:32:08 +0100 Subject: [PATCH 087/406] Extend fields in dirent header --- grub-core/fs/squash4.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 882f5c959..1c522f893 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -106,11 +106,9 @@ struct grub_squash_inode struct grub_squash_dirent_header { /* Actually the value is the number of elements - 1. */ - grub_uint16_t nelems; - grub_uint16_t dummy1; - grub_uint32_t ino_chunk; - grub_uint16_t dummy2[2]; -}; + grub_uint32_t nelems; + grub_uint64_t ino_chunk; +} __attribute__ ((packed)); struct grub_squash_dirent { From 5e96cb4452735c9e2beb82dbfbb03b90ec6c2d1f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 18:41:42 +0100 Subject: [PATCH 088/406] Extend few other fields --- grub-core/fs/squash4.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 1c522f893..0f94ae0a2 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -51,23 +51,23 @@ struct grub_squash_super grub_uint32_t dummy1; grub_uint32_t creation_time; grub_uint32_t dummy2; - grub_uint32_t dummy3[2]; + grub_uint64_t dummy3; grub_uint8_t flags; #define SQUASH_FLAG_UNCOMPRESSED_INODES 1 #define SQUASH_FLAG_UNCOMPRESSED_DATA 2 #define SQUASH_FLAG_UNCOMPRESSED_FRAGMENTS 8 grub_uint8_t dummy4[7]; grub_uint16_t root_ino_offset; - grub_uint16_t root_ino_chunk; - grub_uint32_t dummy5; + grub_uint32_t root_ino_chunk; + grub_uint16_t dummy5; grub_uint64_t total_size; grub_uint64_t exttbloffset; - grub_uint32_t dummy6[2]; + grub_uint64_t dummy6; grub_uint64_t inodeoffset; grub_uint64_t diroffset; grub_uint64_t unk1offset; grub_uint64_t unk2offset; -}; +} __attribute__ ((packed)); /* Chunk-based */ @@ -80,25 +80,25 @@ struct grub_squash_inode union { struct { - grub_uint16_t dummy[2]; + grub_uint32_t dummy; grub_uint32_t chunk; grub_uint32_t fragment; grub_uint32_t offset; grub_uint32_t size; - } file; + } __attribute__ ((packed)) file; struct { - grub_uint16_t dummy1[2]; + grub_uint32_t dummy1; grub_uint32_t chunk; - grub_uint16_t dummy2[2]; + grub_uint32_t dummy2; grub_uint16_t size; - grub_uint16_t offset; - grub_uint16_t dummy3[2]; - } dir; + grub_uint32_t offset; + grub_uint16_t dummy3; + } __attribute__ ((packed)) dir; struct { - grub_uint16_t dummy[4]; + grub_uint64_t dummy; grub_uint32_t namelen; char name[0]; - } symlink; + } __attribute__ ((packed)) symlink; }; } __attribute__ ((packed)); From 81ecffbfc19293dd6b14050c775926d9b5478eb8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 18:42:44 +0100 Subject: [PATCH 089/406] Add missing packed attribute --- grub-core/fs/squash4.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 0f94ae0a2..8e8388628 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -99,7 +99,7 @@ struct grub_squash_inode grub_uint32_t namelen; char name[0]; } __attribute__ ((packed)) symlink; - }; + } __attribute__ ((packed)); } __attribute__ ((packed)); /* Chunk-based. */ @@ -121,13 +121,13 @@ struct grub_squash_dirent /* Actually the value is the length of name - 1. */ grub_uint16_t namelen; char name[0]; -}; +} __attribute__ ((packed)); struct grub_squash_frag_desc { grub_uint64_t offset; grub_uint64_t dummy; -}; +} __attribute__ ((packed)); #define SQUASH_CHUNK_SIZE 0x2000 #define SQUASH_CHUNK_FLAGS 0x8000 From 9959c6a70b7bd4d5cccad712a747f90f33f85fa9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 21:15:25 +0100 Subject: [PATCH 090/406] Fix AFFS rootblock detection --- grub-core/fs/affs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 27e03c0c4..40be4b2f6 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -208,7 +208,7 @@ grub_affs_mount (grub_disk_t disk) rblock = (struct grub_affs_rblock *) rootblock; /* Read the rootblock. */ - grub_disk_read (disk, (disk->total_sectors >> 1) + blocksize, 0, + grub_disk_read (disk, grub_be_to_cpu32 (data->bblock.rootblock), 0, GRUB_DISK_SECTOR_SIZE * 16, rootblock); if (grub_errno) goto fail; @@ -240,7 +240,7 @@ grub_affs_mount (grub_disk_t disk) data->disk = disk; data->htsize = grub_be_to_cpu32 (rblock->htsize); data->diropen.data = data; - data->diropen.block = (disk->total_sectors >> 1); + data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock); grub_free (rootblock); @@ -507,7 +507,7 @@ grub_affs_label (grub_device_t device, char **label) { /* The rootblock maps quite well on a file header block, it's something we can use here. */ - grub_disk_read (data->disk, disk->total_sectors >> 1, + grub_disk_read (data->disk, grub_be_to_cpu32 (data->bblock.rootblock), data->blocksize * (GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION), sizeof (file), &file); From e21c35641397325aa9411b41239e4779212ebe0e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 21:59:22 +0100 Subject: [PATCH 091/406] restructure AFFS fshelp_node-related code --- grub-core/fs/affs.c | 84 ++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 40be4b2f6..343af6681 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -50,12 +50,20 @@ struct grub_affs_rblock grub_uint32_t hashtable[1]; } __attribute__ ((packed)); +struct grub_affs_time +{ + grub_int32_t day; + grub_uint32_t min; + grub_uint32_t fractions_of_sec; +} __attribute__ ((packed)); + /* The second part of a file header block. */ struct grub_affs_file { grub_uint8_t unused1[12]; grub_uint32_t size; - grub_uint8_t unused2[104]; + grub_uint8_t unused2[92]; + struct grub_affs_time mtime; grub_uint8_t namelen; grub_uint8_t name[30]; grub_uint8_t unused3[33]; @@ -85,9 +93,9 @@ struct grub_affs_file struct grub_fshelp_node { struct grub_affs_data *data; - int block; - int size; - int parent; + grub_disk_addr_t block; + struct grub_fshelp_node *parent; + struct grub_affs_file di; }; /* Information about a "mounted" affs filesystem. */ @@ -154,7 +162,7 @@ grub_affs_read_file (grub_fshelp_node_t node, { return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_affs_read_block, - node->size, 0); + grub_be_to_cpu32 (node->di.size), 0); } @@ -241,6 +249,8 @@ grub_affs_mount (grub_disk_t disk) data->htsize = grub_be_to_cpu32 (rblock->htsize); data->diropen.data = data; data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock); + data->diropen.parent = NULL; + grub_memcpy (&data->diropen.di, rootblock, sizeof (data->diropen.di)); grub_free (rootblock); @@ -291,12 +301,15 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, struct grub_affs_data *data = dir->data; grub_uint32_t *hashtable; - auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int block, - int size, int type); + auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, + grub_disk_addr_t block, + const struct grub_affs_file *fil); - int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int block, - int size, int type) + int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, + grub_disk_addr_t block, + const struct grub_affs_file *fil) { + int type; node = grub_malloc (sizeof (*node)); if (!node) { @@ -304,10 +317,19 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, return 1; } + if ((int) grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_DIR) + type = GRUB_FSHELP_REG; + else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_REG) + type = GRUB_FSHELP_DIR; + else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_SYMLINK) + type = GRUB_FSHELP_SYMLINK; + else + type = GRUB_FSHELP_UNKNOWN; + node->data = data; - node->size = size; node->block = block; - node->parent = grub_be_to_cpu32 (file.parent); + node->di = *fil; + node->parent = dir; if (hook (name, type, node)) { @@ -317,6 +339,24 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, return 0; } + /* Create the directory entries for `.' and `..'. */ + node = grub_malloc (sizeof (*node)); + if (!node) + return 1; + + *node = *dir; + if (hook (".", GRUB_FSHELP_DIR, node)) + return 1; + if (dir->parent) + { + node = grub_malloc (sizeof (*node)); + if (!node) + return 1; + *node = *dir->parent; + if (hook ("..", GRUB_FSHELP_DIR, node)) + return 1; + } + hashtable = grub_malloc (data->htsize * sizeof (*hashtable)); if (!hashtable) return 1; @@ -326,16 +366,8 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, if (grub_errno) goto fail; - /* Create the directory entries for `.' and `..'. */ - if (grub_affs_create_node (".", dir->block, dir->size, GRUB_FSHELP_DIR)) - return 1; - if (grub_affs_create_node ("..", dir->parent ? dir->parent : dir->block, - dir->size, GRUB_FSHELP_DIR)) - return 1; - for (i = 0; i < data->htsize; i++) { - enum grub_fshelp_filetype type; grub_uint64_t next; if (!hashtable[i]) @@ -356,17 +388,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, file.name[file.namelen] = '\0'; - if ((int) grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_DIR) - type = GRUB_FSHELP_REG; - else if (grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_REG) - type = GRUB_FSHELP_DIR; - else if (grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_SYMLINK) - type = GRUB_FSHELP_SYMLINK; - else - type = GRUB_FSHELP_UNKNOWN; - - if (grub_affs_create_node ((char *) (file.name), next, - grub_be_to_cpu32 (file.size), type)) + if (grub_affs_create_node ((char *) (file.name), next, &file)) return 1; next = grub_be_to_cpu32 (file.next); @@ -401,7 +423,7 @@ grub_affs_open (struct grub_file *file, const char *name) if (grub_errno) goto fail; - file->size = fdiro->size; + file->size = grub_be_to_cpu32 (fdiro->di.size); data->diropen = *fdiro; grub_free (fdiro); From 790aaa8c9f63a151c3cf45ea5d907c10174a2940 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 22:02:22 +0100 Subject: [PATCH 092/406] AFFS mtime support --- grub-core/fs/affs.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 343af6681..e4b487a7e 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -54,7 +54,7 @@ struct grub_affs_time { grub_int32_t day; grub_uint32_t min; - grub_uint32_t fractions_of_sec; + grub_uint32_t hz; } __attribute__ ((packed)); /* The second part of a file header block. */ @@ -487,6 +487,11 @@ grub_affs_dir (grub_device_t device, const char *path, struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = grub_be_to_cpu32 (node->di.mtime.day) * 86400 + + grub_be_to_cpu32 (node->di.mtime.min) * 60 + + grub_be_to_cpu32 (node->di.mtime.hz) / 50 + + 8 * 365 * 86400 + 86400 * 2; grub_free (node); return hook (filename, &info); } From bd1de4341b4bc6cc1e616674a3fc1ff1c12120fc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 22:33:34 +0100 Subject: [PATCH 093/406] explicitly declare SFS as not installable --- grub-core/fs/sfs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c index 4a5005908..b49420de1 100644 --- a/grub-core/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -579,6 +579,9 @@ static struct grub_fs grub_sfs_fs = .read = grub_sfs_read, .close = grub_sfs_close, .label = grub_sfs_label, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif .next = 0 }; From 7b32d83d7834b4f36fbbbff7c526a07f1879c5b0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 22:48:29 +0100 Subject: [PATCH 094/406] SFS mtime support --- grub-core/fs/sfs.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c index b49420de1..dc4fbd45c 100644 --- a/grub-core/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -66,7 +66,7 @@ struct grub_sfs_obj grub_uint32_t dir_objc; } dir __attribute__ ((packed)); } file_dir; - grub_uint8_t unused3[4]; + grub_uint32_t mtime; grub_uint8_t type; grub_uint8_t filename[1]; grub_uint8_t comment[1]; @@ -119,6 +119,7 @@ struct grub_fshelp_node struct grub_sfs_data *data; int block; int size; + grub_uint32_t mtime; }; /* Information about a "mounted" sfs filesystem. */ @@ -355,10 +356,12 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, int pos; auto int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block, - int size, int type); + int size, int type, + grub_uint32_t mtime); int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block, - int size, int type) + int size, int type, + grub_uint32_t mtime) { node = grub_malloc (sizeof (*node)); if (!node) @@ -367,6 +370,7 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, node->data = data; node->size = size; node->block = block; + node->mtime = mtime; return hook (name, type, node); } @@ -426,7 +430,7 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, if (grub_sfs_create_node (filename, block, grub_be_to_cpu32 (obj->file_dir.file.size), - type)) + type, grub_be_to_cpu32 (obj->mtime))) { grub_free (objc_data); return 1; @@ -525,6 +529,8 @@ grub_sfs_dir (grub_device_t device, const char *path, struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2; + info.mtimeset = 1; grub_free (node); return hook (filename, &info); } From 0e5507c411c63bdbddd2fcf1c6628a8ec29c87a4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Dec 2010 01:00:33 +0100 Subject: [PATCH 095/406] mtime support for ntfs --- grub-core/fs/ntfs.c | 8 ++++++++ include/grub/ntfs.h | 1 + 2 files changed, 9 insertions(+) diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index 414f6513d..7a5e2b158 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -610,6 +610,10 @@ list_file (struct grub_ntfs_file *diro, char *pos, fdiro->data = diro->data; fdiro->ino = u32at (pos, 0); + if (u64at (pos, 0x20) > u64at (pos, 0x28)) + fdiro->mtime = u64at (pos, 0x20); + else + fdiro->mtime = u64at (pos, 0x28); ustr = grub_malloc (ns * 4 + 1); if (ustr == NULL) @@ -880,6 +884,10 @@ grub_ntfs_dir (grub_device_t device, const char *path, struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = grub_divmod64 (node->mtime, 10000000, 0) + - 86400ULL * 365 * (1970 - 1601) + - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100); grub_free (node); return hook (filename, &info); } diff --git a/include/grub/ntfs.h b/include/grub/ntfs.h index 31b99398b..0a089b3c0 100644 --- a/include/grub/ntfs.h +++ b/include/grub/ntfs.h @@ -135,6 +135,7 @@ struct grub_fshelp_node struct grub_ntfs_data *data; char *buf; grub_uint64_t size; + grub_uint64_t mtime; grub_uint32_t ino; int inode_read; struct grub_ntfs_attr attr; From 198cae0c965abe97370b13d67e777f1136d4a1c2 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 13 Dec 2010 13:58:53 +0000 Subject: [PATCH 096/406] Fix border repainting. * grub-core/term/gfxterm.c (dirty_region_add): When a repaint is already scheduled, merge the virtual screen with the requested region rather than repainting only the virtual screen. --- ChangeLog.parse-color | 6 ++++++ grub-core/term/gfxterm.c | 18 ++++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/ChangeLog.parse-color b/ChangeLog.parse-color index ccba06d3c..941cd5aad 100644 --- a/ChangeLog.parse-color +++ b/ChangeLog.parse-color @@ -39,3 +39,9 @@ function. (GRUB_MOD_INIT): Register background_color command. (GRUB_MOD_FINI): Unregister background_color command. + + Fix border repainting. + + * grub-core/term/gfxterm.c (dirty_region_add): When a repaint is + already scheduled, merge the virtual screen with the requested + region rather than repainting only the virtual screen. diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c index 93367f2bb..c914f8d2c 100644 --- a/grub-core/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -539,10 +539,20 @@ dirty_region_add (int x, int y, unsigned int width, unsigned int height) if (repaint_scheduled) { - x = virtual_screen.offset_x; - y = virtual_screen.offset_y; - width = virtual_screen.width; - height = virtual_screen.height; + if (x > (int)virtual_screen.offset_x) + { + width += virtual_screen.offset_x - x; + x = virtual_screen.offset_x; + } + if (y > (int)virtual_screen.offset_y) + { + height += virtual_screen.offset_y - y; + y = virtual_screen.offset_y; + } + if (width < virtual_screen.width) + width = virtual_screen.width; + if (height < virtual_screen.height) + height = virtual_screen.height; repaint_scheduled = 0; repaint_was_scheduled = 1; } From 159b4a8bb76f98d294fac139b4f3f4e21c03a03e Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 14 Dec 2010 12:28:36 +0000 Subject: [PATCH 097/406] (redraw_screen_rect): Allow blend/replace of text layer to be controlled independently from whether there is a background bitmap. (grub_gfxterm_fullscreen): Change blend_text_bg when changing bitmap. (destroy_window): Likewise. (grub_gfxterm_background_image_cmd): Likewise. --- ChangeLog.parse-color | 6 +++++ grub-core/term/gfxterm.c | 55 ++++++++++++++++------------------------ 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/ChangeLog.parse-color b/ChangeLog.parse-color index 941cd5aad..b241f3b73 100644 --- a/ChangeLog.parse-color +++ b/ChangeLog.parse-color @@ -39,6 +39,12 @@ function. (GRUB_MOD_INIT): Register background_color command. (GRUB_MOD_FINI): Unregister background_color command. + (redraw_screen_rect): Allow blend/replace of text layer to be + controlled independently from whether there is a background bitmap. + (grub_gfxterm_fullscreen): Change blend_text_bg when changing + bitmap. + (destroy_window): Likewise. + (grub_gfxterm_background_image_cmd): Likewise. Fix border repainting. diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c index c914f8d2c..108ce941a 100644 --- a/grub-core/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -128,6 +128,7 @@ static struct grub_video_render_target *text_layer; static unsigned int bitmap_width; static unsigned int bitmap_height; static struct grub_video_bitmap *bitmap; +static int blend_text_bg; static struct grub_dirty_region dirty_region; @@ -344,6 +345,7 @@ grub_gfxterm_fullscreen (void) grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height); } bitmap = 0; + blend_text_bg = 0; /* Select the font to use. */ font_name = grub_env_get ("gfxterm_font"); @@ -396,6 +398,7 @@ destroy_window (void) { grub_video_bitmap_destroy (bitmap); bitmap = 0; + blend_text_bg = 0; } repaint_callback = 0; @@ -481,26 +484,27 @@ redraw_screen_rect (unsigned int x, unsigned int y, /* Render background layer. */ grub_video_fill_rect (color, x, ty, width, h); } - - /* Render text layer as blended. */ - grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, x, y, - x - virtual_screen.offset_x, - y - virtual_screen.offset_y, - width, height); } else { /* Render background layer. */ color = virtual_screen.bg_color_display; grub_video_fill_rect (color, x, y, width, height); - - /* Render text layer as replaced (to get texts background color). */ - grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_REPLACE, x, y, - x - virtual_screen.offset_x, - y - virtual_screen.offset_y, - width, height); } + if (blend_text_bg) + /* Render text layer as blended. */ + grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, x, y, + x - virtual_screen.offset_x, + y - virtual_screen.offset_y, + width, height); + else + /* Render text layer as replaced (to get texts background color). */ + grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_REPLACE, x, y, + x - virtual_screen.offset_x, + y - virtual_screen.offset_y, + width, height); + /* Restore saved viewport. */ grub_video_set_viewport (saved_view.x, saved_view.y, saved_view.width, saved_view.height); @@ -1137,6 +1141,7 @@ grub_gfxterm_background_image_cmd (grub_extcmd_context_t ctxt, { grub_video_bitmap_destroy (bitmap); bitmap = 0; + blend_text_bg = 0; /* Mark whole screen as dirty. */ dirty_region_add (0, 0, window.width, window.height); @@ -1169,6 +1174,7 @@ grub_gfxterm_background_image_cmd (grub_extcmd_context_t ctxt, /* Replace the original bitmap with the scaled one. */ grub_video_bitmap_destroy (bitmap); bitmap = scaled_bitmap; + blend_text_bg = 1; } } } @@ -1195,8 +1201,6 @@ grub_gfxterm_background_color_cmd (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { grub_video_rgba_color_t color; - grub_uint8_t *data; - unsigned int i; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing operand"); @@ -1218,25 +1222,10 @@ grub_gfxterm_background_color_cmd (grub_command_t cmd __attribute__ ((unused)), dirty_region_add (0, 0, window.width, window.height); } - /* Create a filled bitmap so that we get suitable text blending. */ - grub_video_bitmap_create (&bitmap, window.width, window.height, - GRUB_VIDEO_BLIT_FORMAT_RGB_888); - if (grub_errno != GRUB_ERR_NONE) - return grub_errno; - - data = bitmap->data; - for (i = 0; i < window.height * window.width; i++) - { - *data++ = color.red; - *data++ = color.green; - *data++ = color.blue; - } - - bitmap_width = window.width; - bitmap_height = window.height; - - /* Set the border color. */ - virtual_screen.bg_color_display = grub_video_map_rgba_color (color); + /* Set the background and border colors. */ + virtual_screen.bg_color = grub_video_map_rgba_color (color); + virtual_screen.bg_color_display = virtual_screen.bg_color; + blend_text_bg = 1; /* Mark whole screen as dirty. */ dirty_region_add (0, 0, window.width, window.height); From 477343c86e0b1e4279be40a1af488e7755f20339 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 15 Dec 2010 01:31:07 +0000 Subject: [PATCH 098/406] make sure virtual_screen.bg_color is compatible with the text layer --- grub-core/term/gfxterm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c index 108ce941a..09363918a 100644 --- a/grub-core/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -1201,6 +1201,7 @@ grub_gfxterm_background_color_cmd (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { grub_video_rgba_color_t color; + struct grub_video_render_target *old_target; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing operand"); @@ -1222,9 +1223,13 @@ grub_gfxterm_background_color_cmd (grub_command_t cmd __attribute__ ((unused)), dirty_region_add (0, 0, window.width, window.height); } - /* Set the background and border colors. */ + /* Set the background and border colors. The background color needs to be + compatible with the text layer. */ + grub_video_get_active_render_target (&old_target); + grub_video_set_active_render_target (text_layer); virtual_screen.bg_color = grub_video_map_rgba_color (color); - virtual_screen.bg_color_display = virtual_screen.bg_color; + grub_video_set_active_render_target (old_target); + virtual_screen.bg_color_display = grub_video_map_rgba_color (color); blend_text_bg = 1; /* Mark whole screen as dirty. */ From 29184e9312b4302932720e1bcdd478eaa2999b7e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Dec 2010 19:49:35 +0100 Subject: [PATCH 099/406] romfs support --- Makefile.util.def | 1 + grub-core/Makefile.core.def | 5 + grub-core/fs/romfs.c | 345 ++++++++++++++++++++++++++++++++++++ 3 files changed, 351 insertions(+) create mode 100644 grub-core/fs/romfs.c diff --git a/Makefile.util.def b/Makefile.util.def index 74984e2e9..6279f510a 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -64,6 +64,7 @@ library = { common = grub-core/fs/ntfs.c; common = grub-core/fs/ntfscomp.c; common = grub-core/fs/reiserfs.c; + common = grub-core/fs/romfs.c; common = grub-core/fs/sfs.c; common = grub-core/fs/tar.c; common = grub-core/fs/udf.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 37c0ce970..f5bbb888d 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -977,6 +977,11 @@ module = { common = fs/reiserfs.c; }; +module = { + name = romfs; + common = fs/romfs.c; +}; + module = { name = sfs; common = fs/sfs.c; diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c new file mode 100644 index 000000000..ad0b6a4c4 --- /dev/null +++ b/grub-core/fs/romfs.c @@ -0,0 +1,345 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 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 + +struct grub_romfs_superblock +{ + char magic[8]; +#define GRUB_ROMFS_MAGIC "-rom1fs-" + grub_uint32_t total_size; + grub_uint32_t chksum; + char label[0]; +}; + +struct grub_romfs_file_header +{ + grub_uint32_t next_file; + grub_uint32_t spec; + grub_uint32_t size; + grub_uint32_t chksum; + char name[0]; +}; + +struct grub_romfs_data +{ + grub_disk_addr_t first_file; + grub_disk_t disk; +}; + +struct grub_fshelp_node +{ + grub_disk_addr_t addr; + struct grub_romfs_data *data; + /* Used only on regular files. */ + grub_disk_addr_t data_addr; + struct grub_romfs_file_header file; +}; + +#define GRUB_ROMFS_ALIGN 16 +#define GRUB_ROMFS_TYPE_MASK 7 +#define GRUB_ROMFS_TYPE_REGULAR 2 +#define GRUB_ROMFS_TYPE_DIRECTORY 1 + +static grub_err_t +do_checksum (void *in, grub_size_t insize) +{ + grub_uint32_t *a = in; + grub_size_t sz = insize / 4; + grub_uint32_t *b = a + sz; + grub_uint32_t csum = 0; + + while (a < b) + csum += grub_be_to_cpu32 (*a++); + if (csum) + return grub_error (GRUB_ERR_BAD_FS, "invalid checksum"); + return GRUB_ERR_NONE; +} + +static struct grub_romfs_data * +grub_romfs_mount (grub_device_t dev) +{ + union { + struct grub_romfs_superblock sb; + char d[512]; + } sb; + grub_err_t err; + char *ptr; + grub_disk_addr_t sec = 0; + struct grub_romfs_data *data; + if (!dev->disk) + { + grub_error (GRUB_ERR_BAD_FS, "not a disk"); + return NULL; + } + err = grub_disk_read (dev->disk, 0, 0, sizeof (sb), &sb); + if (err == GRUB_ERR_OUT_OF_RANGE) + err = grub_errno = GRUB_ERR_BAD_FS; + if (err) + return NULL; + if (grub_be_to_cpu32 (sb.sb.total_size) < sizeof (sb)) + { + grub_error (GRUB_ERR_BAD_FS, "too short filesystem"); + return NULL; + } + err = do_checksum (&sb, sizeof (sb) < grub_be_to_cpu32 (sb.sb.total_size) ? + sizeof (sb) : grub_be_to_cpu32 (sb.sb.total_size)); + if (err) + return NULL; + for (ptr = sb.sb.label; (void *) ptr < (void *) (&sb + 1) + && ptr < sb.d + grub_be_to_cpu32 (sb.sb.total_size); ptr++) + if (!*ptr) + break; + if ((void *) ptr == &sb + 1) + for (sec++; ; sec++) + { + err = grub_disk_read (dev->disk, sec, 0, sizeof (sb), &sb); + if (err == GRUB_ERR_OUT_OF_RANGE) + err = grub_errno = GRUB_ERR_BAD_FS; + if (err) + return NULL; + for (ptr = sb.d; (void *) ptr < (void *) (&sb + 1) + && ptr < sb.d + grub_be_to_cpu32 (sb.sb.total_size); ptr++) + if (!*ptr) + break; + } + data = grub_malloc (sizeof (*data)); + if (!data) + return NULL; + data->first_file = ALIGN_UP (ptr - sb.d, GRUB_ROMFS_ALIGN) + sec * 512; + data->disk = dev->disk; + return data; +} + +static int +grub_romfs_iterate_dir (grub_fshelp_node_t dir, + int NESTED_FUNC_ATTR + (*hook) (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node)) +{ + grub_disk_addr_t caddr; + struct grub_romfs_file_header hdr; + grub_size_t a = 0; + char *name = NULL; + unsigned nptr; + unsigned i, j; + for (caddr = dir->addr; caddr; + caddr = grub_be_to_cpu32 (hdr.next_file) & ~(GRUB_ROMFS_ALIGN - 1)) + { + grub_disk_addr_t naddr = caddr + sizeof (hdr); + grub_uint32_t csum = 0; + enum grub_fshelp_filetype filetype = GRUB_FSHELP_UNKNOWN; + struct grub_fshelp_node *node; + grub_err_t err; + + err = grub_disk_read (dir->data->disk, caddr >> GRUB_DISK_SECTOR_BITS, + caddr & (GRUB_DISK_SECTOR_SIZE - 1), + sizeof (hdr), &hdr); + if (err) + { + grub_free (name); + return 1; + } + for (nptr = 0; ; nptr++, naddr += 16) + { + if (a >= nptr) + { + char *on; + a = 2 * (nptr + 1); + on = name; + name = grub_realloc (name, a * 16); + if (!name) + { + grub_free (on); + return 1; + } + } + err = grub_disk_read (dir->data->disk, naddr >> GRUB_DISK_SECTOR_BITS, + naddr & (GRUB_DISK_SECTOR_SIZE - 1), + 16, name + 16 * nptr); + if (err) + return err; + for (j = 0; j < 16; j++) + if (!name[16 * nptr + j]) + break; + if (j != 16) + break; + } + for (i = 0; i < sizeof (hdr) / sizeof (grub_uint32_t); i++) + csum += grub_be_to_cpu32 (((grub_uint32_t *) &hdr)[i]); + for (i = 0; i < (nptr + 1) * 4; i++) + csum += grub_be_to_cpu32 (((grub_uint32_t *) name)[i]); + if (csum != 0) + { + grub_error (GRUB_ERR_BAD_FS, "invalid checksum"); + grub_free (name); + return 1; + } + node = grub_malloc (sizeof (*node)); + if (!node) + return 1; + node->addr = caddr; + node->data_addr = caddr + (nptr + 1) * 16 + sizeof (hdr); + node->data = dir->data; + node->file = hdr; + switch (grub_be_to_cpu32 (hdr.next_file) & GRUB_ROMFS_TYPE_MASK) + { + case GRUB_ROMFS_TYPE_REGULAR: + filetype = GRUB_FSHELP_REG; + break; + case GRUB_ROMFS_TYPE_DIRECTORY: + filetype = GRUB_FSHELP_DIR; + break; + } + + if (hook (name, filetype, node)) + { + grub_free (name); + return 1; + } + } + grub_free (name); + return 0; +} + +static grub_err_t +grub_romfs_dir (grub_device_t device, const char *path, + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)) +{ + struct grub_romfs_data *data = 0; + struct grub_fshelp_node *fdiro = 0, start; + + auto int NESTED_FUNC_ATTR iterate (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node); + + int NESTED_FUNC_ATTR iterate (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node) + { + struct grub_dirhook_info info; + grub_memset (&info, 0, sizeof (info)); + + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + grub_free (node); + return hook (filename, &info); + } + + data = grub_romfs_mount (device); + if (! data) + goto fail; + + start.addr = data->first_file; + start.data = data; + grub_fshelp_find_file (path, &start, &fdiro, grub_romfs_iterate_dir, + NULL, GRUB_FSHELP_DIR); + if (grub_errno) + goto fail; + + grub_romfs_iterate_dir (fdiro, iterate); + + fail: + grub_free (data); + + return grub_errno; +} + +static grub_err_t +grub_romfs_open (struct grub_file *file, const char *name) +{ + struct grub_romfs_data *data = 0; + struct grub_fshelp_node *fdiro = 0, start; + + data = grub_romfs_mount (file->device); + if (! data) + goto fail; + + start.addr = data->first_file; + start.data = data; + + grub_fshelp_find_file (name, &start, &fdiro, grub_romfs_iterate_dir, + NULL, GRUB_FSHELP_REG); + if (grub_errno) + goto fail; + + file->size = grub_be_to_cpu32 (fdiro->file.size); + file->data = fdiro; + + fail: + grub_free (data); + + return grub_errno; +} + +static grub_ssize_t +grub_romfs_read (grub_file_t file, char *buf, grub_size_t len) +{ + struct grub_fshelp_node *data = file->data; + + /* XXX: The file is stored in as a single extent. */ + data->data->disk->read_hook = file->read_hook; + grub_disk_read (data->data->disk, + (data->data_addr + file->offset) >> GRUB_DISK_SECTOR_BITS, + (data->data_addr + file->offset) & (GRUB_DISK_SECTOR_SIZE - 1), + len, buf); + data->data->disk->read_hook = NULL; + + if (grub_errno) + return -1; + + return len; +} + +static grub_err_t +grub_romfs_close (grub_file_t file) +{ + grub_free (file->data); + + return GRUB_ERR_NONE; +} + +static struct grub_fs grub_romfs_fs = + { + .name = "romfs", + .dir = grub_romfs_dir, + .open = grub_romfs_open, + .read = grub_romfs_read, + .close = grub_romfs_close, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif + .next = 0 + }; + +GRUB_MOD_INIT(romfs) +{ + grub_fs_register (&grub_romfs_fs); +} + +GRUB_MOD_FINI(romfs) +{ + grub_fs_unregister (&grub_romfs_fs); +} From 921c7932d0ce8ff5bc36570a02fc220f9887139c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Dec 2010 20:24:16 +0100 Subject: [PATCH 100/406] directory and hardlink support on romfs --- grub-core/fs/romfs.c | 54 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c index ad0b6a4c4..a642615c3 100644 --- a/grub-core/fs/romfs.c +++ b/grub-core/fs/romfs.c @@ -52,15 +52,16 @@ struct grub_fshelp_node { grub_disk_addr_t addr; struct grub_romfs_data *data; - /* Used only on regular files. */ grub_disk_addr_t data_addr; + /* Not filled for root. */ struct grub_romfs_file_header file; }; #define GRUB_ROMFS_ALIGN 16 #define GRUB_ROMFS_TYPE_MASK 7 -#define GRUB_ROMFS_TYPE_REGULAR 2 +#define GRUB_ROMFS_TYPE_HARDLINK 0 #define GRUB_ROMFS_TYPE_DIRECTORY 1 +#define GRUB_ROMFS_TYPE_REGULAR 2 static grub_err_t do_checksum (void *in, grub_size_t insize) @@ -145,7 +146,7 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, char *name = NULL; unsigned nptr; unsigned i, j; - for (caddr = dir->addr; caddr; + for (caddr = dir->data_addr; caddr; caddr = grub_be_to_cpu32 (hdr.next_file) & ~(GRUB_ROMFS_ALIGN - 1)) { grub_disk_addr_t naddr = caddr + sizeof (hdr); @@ -180,7 +181,7 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, naddr & (GRUB_DISK_SECTOR_SIZE - 1), 16, name + 16 * nptr); if (err) - return err; + return 1; for (j = 0; j < 16; j++) if (!name[16 * nptr + j]) break; @@ -210,8 +211,51 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, filetype = GRUB_FSHELP_REG; break; case GRUB_ROMFS_TYPE_DIRECTORY: + node->data_addr = grub_be_to_cpu32 (hdr.spec); filetype = GRUB_FSHELP_DIR; break; + case GRUB_ROMFS_TYPE_HARDLINK: + { + grub_disk_addr_t laddr; + node->addr = laddr = grub_be_to_cpu32 (hdr.spec); + err = grub_disk_read (dir->data->disk, + laddr >> GRUB_DISK_SECTOR_BITS, + laddr & (GRUB_DISK_SECTOR_SIZE - 1), + sizeof (node->file), &node->file); + if (err) + return 1; + if ((grub_be_to_cpu32 (node->file.next_file) & GRUB_ROMFS_TYPE_MASK) + == GRUB_ROMFS_TYPE_REGULAR) + { + laddr += sizeof (hdr); + while (1) + { + char buf[16]; + err = grub_disk_read (dir->data->disk, + laddr >> GRUB_DISK_SECTOR_BITS, + laddr & (GRUB_DISK_SECTOR_SIZE - 1), + 16, buf); + if (err) + return 1; + for (i = 0; i < 16; i++) + if (!buf[i]) + break; + if (i != 16) + break; + laddr += 16; + } + node->data_addr = laddr + 16; + filetype = GRUB_FSHELP_REG; + } + if ((grub_be_to_cpu32 (node->file.next_file) & GRUB_ROMFS_TYPE_MASK) + == GRUB_ROMFS_TYPE_DIRECTORY) + { + node->data_addr = grub_be_to_cpu32 (node->file.spec); + filetype = GRUB_FSHELP_DIR; + } + + break; + } } if (hook (name, filetype, node)) @@ -253,6 +297,7 @@ grub_romfs_dir (grub_device_t device, const char *path, goto fail; start.addr = data->first_file; + start.data_addr = data->first_file; start.data = data; grub_fshelp_find_file (path, &start, &fdiro, grub_romfs_iterate_dir, NULL, GRUB_FSHELP_DIR); @@ -278,6 +323,7 @@ grub_romfs_open (struct grub_file *file, const char *name) goto fail; start.addr = data->first_file; + start.data_addr = data->first_file; start.data = data; grub_fshelp_find_file (name, &start, &fdiro, grub_romfs_iterate_dir, From 20af85758134eb05ecdb950ce113a3145530842d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Dec 2010 20:36:54 +0100 Subject: [PATCH 101/406] symlink support on romfs --- grub-core/fs/romfs.c | 56 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c index a642615c3..342bdd733 100644 --- a/grub-core/fs/romfs.c +++ b/grub-core/fs/romfs.c @@ -62,6 +62,7 @@ struct grub_fshelp_node #define GRUB_ROMFS_TYPE_HARDLINK 0 #define GRUB_ROMFS_TYPE_DIRECTORY 1 #define GRUB_ROMFS_TYPE_REGULAR 2 +#define GRUB_ROMFS_TYPE_SYMLINK 3 static grub_err_t do_checksum (void *in, grub_size_t insize) @@ -133,6 +134,27 @@ grub_romfs_mount (grub_device_t dev) return data; } +static char * +grub_romfs_read_symlink (grub_fshelp_node_t node) +{ + char *ret; + grub_err_t err; + ret = grub_malloc (grub_be_to_cpu32 (node->file.size) + 1); + if (!ret) + return NULL; + err = grub_disk_read (node->data->disk, + (node->data_addr) >> GRUB_DISK_SECTOR_BITS, + (node->data_addr) & (GRUB_DISK_SECTOR_SIZE - 1), + grub_be_to_cpu32 (node->file.size), ret); + if (err) + { + grub_free (ret); + return NULL; + } + ret[grub_be_to_cpu32 (node->file.size)] = 0; + return ret; +} + static int grub_romfs_iterate_dir (grub_fshelp_node_t dir, int NESTED_FUNC_ATTR @@ -210,6 +232,9 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, case GRUB_ROMFS_TYPE_REGULAR: filetype = GRUB_FSHELP_REG; break; + case GRUB_ROMFS_TYPE_SYMLINK: + filetype = GRUB_FSHELP_SYMLINK; + break; case GRUB_ROMFS_TYPE_DIRECTORY: node->data_addr = grub_be_to_cpu32 (hdr.spec); filetype = GRUB_FSHELP_DIR; @@ -225,7 +250,9 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, if (err) return 1; if ((grub_be_to_cpu32 (node->file.next_file) & GRUB_ROMFS_TYPE_MASK) - == GRUB_ROMFS_TYPE_REGULAR) + == GRUB_ROMFS_TYPE_REGULAR + || (grub_be_to_cpu32 (node->file.next_file) + & GRUB_ROMFS_TYPE_MASK) == GRUB_ROMFS_TYPE_SYMLINK) { laddr += sizeof (hdr); while (1) @@ -245,16 +272,21 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, laddr += 16; } node->data_addr = laddr + 16; - filetype = GRUB_FSHELP_REG; } - if ((grub_be_to_cpu32 (node->file.next_file) & GRUB_ROMFS_TYPE_MASK) - == GRUB_ROMFS_TYPE_DIRECTORY) - { - node->data_addr = grub_be_to_cpu32 (node->file.spec); - filetype = GRUB_FSHELP_DIR; - } - - break; + if ((grub_be_to_cpu32 (node->file.next_file) + & GRUB_ROMFS_TYPE_MASK) == GRUB_ROMFS_TYPE_REGULAR) + filetype = GRUB_FSHELP_REG; + if ((grub_be_to_cpu32 (node->file.next_file) + & GRUB_ROMFS_TYPE_MASK) == GRUB_ROMFS_TYPE_SYMLINK) + filetype = GRUB_FSHELP_SYMLINK; + if ((grub_be_to_cpu32 (node->file.next_file) & GRUB_ROMFS_TYPE_MASK) + == GRUB_ROMFS_TYPE_DIRECTORY) + { + node->data_addr = grub_be_to_cpu32 (node->file.spec); + filetype = GRUB_FSHELP_DIR; + } + + break; } } @@ -300,7 +332,7 @@ grub_romfs_dir (grub_device_t device, const char *path, start.data_addr = data->first_file; start.data = data; grub_fshelp_find_file (path, &start, &fdiro, grub_romfs_iterate_dir, - NULL, GRUB_FSHELP_DIR); + grub_romfs_read_symlink, GRUB_FSHELP_DIR); if (grub_errno) goto fail; @@ -327,7 +359,7 @@ grub_romfs_open (struct grub_file *file, const char *name) start.data = data; grub_fshelp_find_file (name, &start, &fdiro, grub_romfs_iterate_dir, - NULL, GRUB_FSHELP_REG); + grub_romfs_read_symlink, GRUB_FSHELP_REG); if (grub_errno) goto fail; From 44932541564c681250d819fe4e425bb9693f0c13 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Dec 2010 22:00:18 +0100 Subject: [PATCH 102/406] Support RomFS label --- grub-core/fs/romfs.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c index 342bdd733..07632e635 100644 --- a/grub-core/fs/romfs.c +++ b/grub-core/fs/romfs.c @@ -399,6 +399,40 @@ grub_romfs_close (grub_file_t file) return GRUB_ERR_NONE; } +static grub_err_t +grub_romfs_label (grub_device_t device, char **label) +{ + struct grub_romfs_data *data; + grub_err_t err; + + *label = NULL; + + data = grub_romfs_mount (device); + if (!data) + return grub_errno; + *label = grub_malloc (data->first_file + 1 + - sizeof (struct grub_romfs_superblock)); + if (!*label) + { + grub_free (data); + return grub_errno; + } + err = grub_disk_read (device->disk, 0, sizeof (struct grub_romfs_superblock), + data->first_file + - sizeof (struct grub_romfs_superblock), + *label); + if (err) + { + grub_free (data); + grub_free (*label); + *label = NULL; + return err; + } + (*label)[data->first_file - sizeof (struct grub_romfs_superblock)] = 0; + return GRUB_ERR_NONE; +} + + static struct grub_fs grub_romfs_fs = { .name = "romfs", @@ -406,6 +440,7 @@ static struct grub_fs grub_romfs_fs = .open = grub_romfs_open, .read = grub_romfs_read, .close = grub_romfs_close, + .label = grub_romfs_label, #ifdef GRUB_UTIL .reserved_first_sector = 0, #endif From e872a2dd82c6bfc27a870aff9088dfccaaa4fc02 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 18 Dec 2010 22:47:50 +0100 Subject: [PATCH 103/406] * util/grub-mkfont.c (main): Handle errors from FT_Set_Pixel_Sizes. --- ChangeLog | 4 ++++ util/grub-mkfont.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 3f15bcc7b..de0a5690a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-12-18 Vladimir Serbinenko + + * util/grub-mkfont.c (main): Handle errors from FT_Set_Pixel_Sizes. + 2010-12-18 Colin Watson * grub-core/normal/term.c (print_more): Make \r or \n scroll one diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c index 3e24380d1..fff6a619e 100644 --- a/util/grub-mkfont.c +++ b/util/grub-mkfont.c @@ -1170,7 +1170,8 @@ main (int argc, char *argv[]) font_info.style = ft_face->style_flags; font_info.size = size; - FT_Set_Pixel_Sizes (ft_face, size, size); + if (FT_Set_Pixel_Sizes (ft_face, size, size)) + grub_util_error ("can't set %dx%d font size", size, size); add_font (&font_info, ft_face, file_format != PF2); FT_Done_Face (ft_face); } From e6533ae1547169a4ef4dd2861bd6c56a8efdc5cc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 19 Dec 2010 00:43:41 +0100 Subject: [PATCH 104/406] Fix handling of UTF-16 UDF labels. * grub-core/fs/udf.c (grub_udf_iterate_dir): Move string-parsing part (read_string): .. here. (grub_udf_label): Use read_string. --- ChangeLog | 8 ++++++ grub-core/fs/udf.c | 70 +++++++++++++++++++++++++++++++--------------- 2 files changed, 55 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index de0a5690a..effab30eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-12-19 Vladimir Serbinenko + + Fix handling of UTF-16 UDF labels. + + * grub-core/fs/udf.c (grub_udf_iterate_dir): Move string-parsing part + (read_string): .. here. + (grub_udf_label): Use read_string. + 2010-12-18 Vladimir Serbinenko * util/grub-mkfont.c (main): Handle errors from FT_Set_Pixel_Sizes. diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index 7041e619e..51726edf3 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -788,6 +788,43 @@ fail: return 0; } +static char * +read_string (grub_uint8_t *raw, grub_size_t sz) +{ + grub_uint16_t *utf16; + char *ret; + grub_size_t utf16len = 0; + + if (raw[0] != 8 && raw[0] != 16) + return NULL; + + if (raw[0] == 8) + { + unsigned i; + utf16len = sz - 1; + utf16 = grub_malloc (utf16len * sizeof (utf16[0])); + if (!utf16) + return NULL; + for (i = 0; i < utf16len; i++) + utf16[i] = raw[i + 1]; + } + if (raw[0] == 16) + { + unsigned i; + utf16len = (sz - 1) / 2; + utf16 = grub_malloc (utf16len * sizeof (utf16[0])); + if (!utf16) + return NULL; + for (i = 0; i < utf16len; i++) + utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; + } + ret = grub_malloc (utf16len * 3 + 1); + if (ret) + *grub_utf16_to_utf8 ((grub_uint8_t *) ret, utf16, utf16len) = '\0'; + grub_free (utf16); + return ret; +} + static int grub_udf_iterate_dir (grub_fshelp_node_t dir, int NESTED_FUNC_ATTR @@ -841,10 +878,8 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, else { enum grub_fshelp_filetype type; + char *filename; grub_uint8_t raw[dirent.file_ident_length]; - grub_uint16_t utf16[dirent.file_ident_length - 1]; - grub_uint8_t filename[dirent.file_ident_length * 2]; - grub_size_t utf16len = 0; type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ? (GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG)); @@ -855,27 +890,16 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, != dirent.file_ident_length) return 0; - if (raw[0] == 8) - { - unsigned i; - utf16len = dirent.file_ident_length - 1; - for (i = 0; i < utf16len; i++) - utf16[i] = raw[i + 1]; - } - if (raw[0] == 16) - { - unsigned i; - utf16len = (dirent.file_ident_length - 1) / 2; - for (i = 0; i < utf16len; i++) - utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; - } - if (raw[0] == 8 || raw[0] == 16) - { - *grub_utf16_to_utf8 (filename, utf16, utf16len) = '\0'; + filename = read_string (raw, dirent.file_ident_length); + if (!filename) + grub_print_error (); - if (hook ((char *) filename, type, child)) - return 1; + if (filename && hook (filename, type, child)) + { + grub_free (filename); + return 1; } + grub_free (filename); } } @@ -1004,7 +1028,7 @@ grub_udf_label (grub_device_t device, char **label) if (data) { - *label = grub_strdup ((char *) &data->lvd.ident[1]); + *label = read_string (data->lvd.ident, sizeof (data->lvd.ident)); grub_free (data); } else From b85812b06f6806f988c9c57ca52f01c4eb110114 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 19 Dec 2010 00:49:52 +0100 Subject: [PATCH 105/406] * grub-core/fs/affs.c (grub_affs_fs) [GRUB_UTIL]: Explicitly set reserved_first_sector to 0. * grub-core/fs/cpio.c (grub_cpio_fs) [GRUB_UTIL]: Likewise. * grub-core/fs/sfs.c (grub_sfs_fs) [GRUB_UTIL]: Likewise. * grub-core/fs/xfs.c (grub_xfs_fs) [GRUB_UTIL]: Likewise. --- ChangeLog | 8 ++++++++ grub-core/fs/affs.c | 3 +++ grub-core/fs/cpio.c | 3 +++ grub-core/fs/sfs.c | 3 +++ grub-core/fs/xfs.c | 3 +++ 5 files changed, 20 insertions(+) diff --git a/ChangeLog b/ChangeLog index effab30eb..cc3f65c86 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-12-19 Vladimir Serbinenko + + * grub-core/fs/affs.c (grub_affs_fs) [GRUB_UTIL]: Explicitly set + reserved_first_sector to 0. + * grub-core/fs/cpio.c (grub_cpio_fs) [GRUB_UTIL]: Likewise. + * grub-core/fs/sfs.c (grub_sfs_fs) [GRUB_UTIL]: Likewise. + * grub-core/fs/xfs.c (grub_xfs_fs) [GRUB_UTIL]: Likewise. + 2010-12-19 Vladimir Serbinenko Fix handling of UTF-16 UDF labels. diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 3dc80752d..27e03c0c4 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -535,6 +535,9 @@ static struct grub_fs grub_affs_fs = .read = grub_affs_read, .close = grub_affs_close, .label = grub_affs_label, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif .next = 0 }; diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index c087b4f90..2c92404c3 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -354,6 +354,9 @@ static struct grub_fs grub_cpio_fs = { .open = grub_cpio_open, .read = grub_cpio_read, .close = grub_cpio_close, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif }; #ifdef MODE_USTAR diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c index 4a5005908..b49420de1 100644 --- a/grub-core/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -579,6 +579,9 @@ static struct grub_fs grub_sfs_fs = .read = grub_sfs_read, .close = grub_sfs_close, .label = grub_sfs_label, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif .next = 0 }; diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 9dffe31d1..3d773856e 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -808,6 +808,9 @@ static struct grub_fs grub_xfs_fs = .close = grub_xfs_close, .label = grub_xfs_label, .uuid = grub_xfs_uuid, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif .next = 0 }; From b070525d039783869b96e0223c8142a055fffc0f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 19 Dec 2010 00:52:18 +0100 Subject: [PATCH 106/406] * grub-core/fs/affs.c (grub_affs_mount): Read data->bblock.rootblock rather than assuming than rootblock is exactly in the middle. (grub_affs_label): Likewise. --- ChangeLog | 6 ++++++ grub-core/fs/affs.c | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index cc3f65c86..8f459f198 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-12-19 Vladimir Serbinenko + + * grub-core/fs/affs.c (grub_affs_mount): Read data->bblock.rootblock + rather than assuming than rootblock is exactly in the middle. + (grub_affs_label): Likewise. + 2010-12-19 Vladimir Serbinenko * grub-core/fs/affs.c (grub_affs_fs) [GRUB_UTIL]: Explicitly set diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 27e03c0c4..40be4b2f6 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -208,7 +208,7 @@ grub_affs_mount (grub_disk_t disk) rblock = (struct grub_affs_rblock *) rootblock; /* Read the rootblock. */ - grub_disk_read (disk, (disk->total_sectors >> 1) + blocksize, 0, + grub_disk_read (disk, grub_be_to_cpu32 (data->bblock.rootblock), 0, GRUB_DISK_SECTOR_SIZE * 16, rootblock); if (grub_errno) goto fail; @@ -240,7 +240,7 @@ grub_affs_mount (grub_disk_t disk) data->disk = disk; data->htsize = grub_be_to_cpu32 (rblock->htsize); data->diropen.data = data; - data->diropen.block = (disk->total_sectors >> 1); + data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock); grub_free (rootblock); @@ -507,7 +507,7 @@ grub_affs_label (grub_device_t device, char **label) { /* The rootblock maps quite well on a file header block, it's something we can use here. */ - grub_disk_read (data->disk, disk->total_sectors >> 1, + grub_disk_read (data->disk, grub_be_to_cpu32 (data->bblock.rootblock), data->blocksize * (GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION), sizeof (file), &file); From 1c95b6d2bfb721df4859414a4f31ac8ed9c7bc8d Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 23 Dec 2010 12:11:44 +0000 Subject: [PATCH 107/406] Move video/colors.c into video.mod. --- ChangeLog.parse-color | 5 ++--- grub-core/Makefile.core.def | 7 +------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/ChangeLog.parse-color b/ChangeLog.parse-color index b241f3b73..81628e89f 100644 --- a/ChangeLog.parse-color +++ b/ChangeLog.parse-color @@ -1,4 +1,4 @@ -2010-12-10 Colin Watson +2010-12-23 Colin Watson Move gfxmenu color handling to video, so that gfxterm can use it too. @@ -30,8 +30,7 @@ * grub-core/Makefile.core.def (kernel) [videoinkernel]: Add video/colors.c. (gfxmenu): Remove gfxmenu/named_colors.c. - (video_colors) [videomodules]: New module, containing - video/colors.c. + (video) [videomodules]: Add video/colors.c. Add a background_color command. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index fdf7d0826..8566c79fb 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1442,12 +1442,6 @@ module = { enable = i386_pc; }; -module = { - name = video_colors; - common = video/colors.c; - enable = videomodules; -}; - module = { name = video_fb; common = video/fb/video_fb.c; @@ -1460,6 +1454,7 @@ module = { module = { name = video; common = video/video.c; + common = video/colors.c; enable = videomodules; }; From af4e4a875acc4398a211b8e15ffa8ee40b1efdce Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 23 Dec 2010 12:19:55 +0000 Subject: [PATCH 108/406] return GRUB_ERR_NONE instead of setting grub_errno --- grub-core/term/gfxterm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c index 09363918a..8a75df93c 100644 --- a/grub-core/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -1235,9 +1235,7 @@ grub_gfxterm_background_color_cmd (grub_command_t cmd __attribute__ ((unused)), /* Mark whole screen as dirty. */ dirty_region_add (0, 0, window.width, window.height); - /* All was ok. */ - grub_errno = GRUB_ERR_NONE; - return grub_errno; + return GRUB_ERR_NONE; } static struct grub_term_output grub_video_term = From c7336d912c656c4b7c7162e8dee6f5001e732be5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Dec 2010 16:07:53 +0100 Subject: [PATCH 109/406] splitting generic ata from pata. --- commands/hdparm.c | 95 +++-- disk/ahci.c | 289 ++++++++++----- disk/ata.c | 829 ++++++++++++++------------------------------ disk/ata_pthru.c | 520 ++++++++++++++++++++++++--- disk/scsi.c | 38 +- disk/usbms.c | 12 +- include/grub/ata.h | 122 ++++--- include/grub/disk.h | 13 +- include/grub/scsi.h | 16 +- kern/disk.c | 4 - 10 files changed, 1095 insertions(+), 843 deletions(-) diff --git a/commands/hdparm.c b/commands/hdparm.c index a3f8bbff0..02ae8f36b 100644 --- a/commands/hdparm.c +++ b/commands/hdparm.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -61,60 +62,60 @@ enum grub_ata_smart_commands static int quiet = 0; static grub_err_t -grub_hdparm_do_ata_cmd (grub_disk_t disk, grub_uint8_t cmd, +grub_hdparm_do_ata_cmd (grub_ata_t ata, grub_uint8_t cmd, grub_uint8_t features, grub_uint8_t sectors, void * buffer, int size) { struct grub_disk_ata_pass_through_parms apt; grub_memset (&apt, 0, sizeof (apt)); - apt.taskfile[GRUB_ATA_REG_CMD] = cmd; - apt.taskfile[GRUB_ATA_REG_FEATURES] = features; - apt.taskfile[GRUB_ATA_REG_SECTORS] = sectors; + apt.taskfile.cmd = cmd; + apt.taskfile.features = features; + apt.taskfile.sectors = sectors; apt.buffer = buffer; apt.size = size; - if (grub_disk_ata_pass_through (disk, &apt)) + if (ata->dev->readwrite (ata, &apt)) return grub_errno; return GRUB_ERR_NONE; } static int -grub_hdparm_do_check_powermode_cmd (grub_disk_t disk) +grub_hdparm_do_check_powermode_cmd (grub_ata_t ata) { struct grub_disk_ata_pass_through_parms apt; grub_memset (&apt, 0, sizeof (apt)); - apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_CHECK_POWER_MODE; + apt.taskfile.cmd = GRUB_ATA_CMD_CHECK_POWER_MODE; - if (grub_disk_ata_pass_through (disk, &apt)) + if (ata->dev->readwrite (ata, &apt)) return -1; - return apt.taskfile[GRUB_ATA_REG_SECTORS]; + return apt.taskfile.sectors; } static int -grub_hdparm_do_smart_cmd (grub_disk_t disk, grub_uint8_t features) +grub_hdparm_do_smart_cmd (grub_ata_t ata, grub_uint8_t features) { struct grub_disk_ata_pass_through_parms apt; grub_memset (&apt, 0, sizeof (apt)); - apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_SMART; - apt.taskfile[GRUB_ATA_REG_FEATURES] = features; - apt.taskfile[GRUB_ATA_REG_LBAMID] = 0x4f; - apt.taskfile[GRUB_ATA_REG_LBAHIGH] = 0xc2; + apt.taskfile.cmd = GRUB_ATA_CMD_SMART; + apt.taskfile.features = features; + apt.taskfile.lba_mid = 0x4f; + apt.taskfile.lba_high = 0xc2; - if (grub_disk_ata_pass_through (disk, &apt)) + if (ata->dev->readwrite (ata, &apt)) return -1; if (features == GRUB_ATA_FEAT_SMART_STATUS) { - if ( apt.taskfile[GRUB_ATA_REG_LBAMID] == 0x4f - && apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0xc2) + if ( apt.taskfile.lba_mid == 0x4f + && apt.taskfile.lba_high == 0xc2) return 0; /* Good SMART status. */ - else if ( apt.taskfile[GRUB_ATA_REG_LBAMID] == 0xf4 - && apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0x2c) + else if ( apt.taskfile.lba_mid == 0xf4 + && apt.taskfile.lba_high == 0x2c) return 1; /* Bad SMART status. */ else return -1; @@ -124,12 +125,12 @@ grub_hdparm_do_smart_cmd (grub_disk_t disk, grub_uint8_t features) static grub_err_t grub_hdparm_simple_cmd (const char * msg, - grub_disk_t disk, grub_uint8_t cmd) + grub_ata_t ata, grub_uint8_t cmd) { if (! quiet && msg) grub_printf ("%s", msg); - grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, 0, 0, NULL, 0); + grub_err_t err = grub_hdparm_do_ata_cmd (ata, cmd, 0, 0, NULL, 0); if (! quiet && msg) grub_printf ("%s\n", ! err ? "" : ": not supported"); @@ -138,7 +139,7 @@ grub_hdparm_simple_cmd (const char * msg, static grub_err_t grub_hdparm_set_val_cmd (const char * msg, int val, - grub_disk_t disk, grub_uint8_t cmd, + grub_ata_t ata, grub_uint8_t cmd, grub_uint8_t features, grub_uint8_t sectors) { if (! quiet && msg && *msg) @@ -149,7 +150,7 @@ grub_hdparm_set_val_cmd (const char * msg, int val, grub_printf ("Disable %s", msg); } - grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, features, sectors, + grub_err_t err = grub_hdparm_do_ata_cmd (ata, cmd, features, sectors, NULL, 0); if (! quiet && msg) @@ -273,6 +274,7 @@ static grub_err_t grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? { struct grub_arg_list *state = cmd->state; + struct grub_ata *ata; /* Check command line. */ if (argc != 1) @@ -283,9 +285,6 @@ grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? return grub_error (GRUB_ERR_BAD_ARGUMENT, "argument is not a device name"); args[0][len - 1] = 0; - if (! grub_disk_ata_pass_through) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "ATA pass through not available"); - int i = 0; int apm = get_int_arg (&state[i++]); int power = state[i++].set; @@ -311,15 +310,37 @@ grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? return grub_error (GRUB_ERR_BAD_ARGUMENT, "partition not allowed"); } + switch (disk->dev->id) + { + case GRUB_DISK_DEVICE_ATA_ID: + ata = disk->data; + break; + case GRUB_DISK_DEVICE_SCSI_ID: + if (((disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xFF) + == GRUB_SCSI_SUBSYSTEM_PATA + || (((disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xFF) + == GRUB_SCSI_SUBSYSTEM_AHCI)) + { + ata = ((struct grub_scsi *) disk->data)->data; + break; + } + default: + return grub_error (GRUB_ERR_IO, "not an ATA device"); + } + + /* Change settings. */ if (aam >= 0) grub_hdparm_set_val_cmd ("Automatic Acoustic Management", (aam ? aam : -1), - disk, GRUB_ATA_CMD_SET_FEATURES, (aam ? 0x42 : 0xc2), aam); + ata, GRUB_ATA_CMD_SET_FEATURES, + (aam ? 0x42 : 0xc2), aam); if (apm >= 0) grub_hdparm_set_val_cmd ("Advanced Power Management", - (apm != 255 ? apm : -1), disk, GRUB_ATA_CMD_SET_FEATURES, - (apm != 255 ? 0x05 : 0x85), (apm != 255 ? apm : 0)); + (apm != 255 ? apm : -1), ata, + GRUB_ATA_CMD_SET_FEATURES, + (apm != 255 ? 0x05 : 0x85), + (apm != 255 ? apm : 0)); if (standby_tout >= 0) { @@ -330,28 +351,28 @@ grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? grub_printf (")"); } /* The IDLE cmd sets disk to idle mode and configures standby timer. */ - grub_hdparm_set_val_cmd ("", -1, disk, GRUB_ATA_CMD_IDLE, 0, standby_tout); + grub_hdparm_set_val_cmd ("", -1, ata, GRUB_ATA_CMD_IDLE, 0, standby_tout); } if (enable_smart >= 0) { if (! quiet) grub_printf ("%sable SMART operations", (enable_smart ? "En" : "Dis")); - int err = grub_hdparm_do_smart_cmd (disk, (enable_smart ? + int err = grub_hdparm_do_smart_cmd (ata, (enable_smart ? GRUB_ATA_FEAT_SMART_ENABLE : GRUB_ATA_FEAT_SMART_DISABLE)); if (! quiet) grub_printf ("%s\n", err ? ": not supported" : ""); } if (sec_freeze) - grub_hdparm_simple_cmd ("Freeze security settings", disk, + grub_hdparm_simple_cmd ("Freeze security settings", ata, GRUB_ATA_CMD_SECURITY_FREEZE_LOCK); /* Print/dump IDENTIFY. */ if (ident || dumpid) { char buf[GRUB_DISK_SECTOR_SIZE]; - if (grub_hdparm_do_ata_cmd (disk, GRUB_ATA_CMD_IDENTIFY_DEVICE, + if (grub_hdparm_do_ata_cmd (ata, GRUB_ATA_CMD_IDENTIFY_DEVICE, 0, 0, buf, sizeof (buf))) grub_printf ("Cannot read ATA IDENTIFY data\n"); else @@ -367,7 +388,7 @@ grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? if (power) { grub_printf ("Disk power mode is: "); - int mode = grub_hdparm_do_check_powermode_cmd (disk); + int mode = grub_hdparm_do_check_powermode_cmd (ata); if (mode < 0) grub_printf ("unknown\n"); else @@ -383,7 +404,7 @@ grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? { if (! quiet) grub_printf ("SMART status is: "); - int err = grub_hdparm_do_smart_cmd (disk, GRUB_ATA_FEAT_SMART_STATUS); + int err = grub_hdparm_do_smart_cmd (ata, GRUB_ATA_FEAT_SMART_STATUS); if (! quiet) grub_printf ("%s\n", (err < 0 ? "unknown" : err == 0 ? "OK" : "*BAD*")); @@ -392,11 +413,11 @@ grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? /* Change power mode. */ if (standby_now) - grub_hdparm_simple_cmd ("Set disk to standby mode", disk, + grub_hdparm_simple_cmd ("Set disk to standby mode", ata, GRUB_ATA_CMD_STANDBY_IMMEDIATE); if (sleep_now) - grub_hdparm_simple_cmd ("Set disk to sleep mode", disk, + grub_hdparm_simple_cmd ("Set disk to sleep mode", ata, GRUB_ATA_CMD_SLEEP); grub_disk_close (disk); diff --git a/disk/ahci.c b/disk/ahci.c index 1372fd651..946db82e1 100644 --- a/disk/ahci.c +++ b/disk/ahci.c @@ -21,39 +21,79 @@ #include #include #include +#include #include +#include +#include struct grub_ahci_cmd_head { - grub_uint32_t unused[8]; + grub_uint32_t config; + grub_uint32_t transfered; + grub_uint64_t command_table_base; + grub_uint32_t unused[4]; +}; + +struct grub_ahci_prdt_entry +{ + grub_uint64_t data_base; + grub_uint32_t unused; + grub_uint32_t size; +}; + +struct grub_ahci_cmd_table +{ + grub_uint8_t cfis[0x40]; + grub_uint8_t command[16]; + grub_uint32_t reserved[0xc]; + struct grub_ahci_prdt_entry prdt[1]; }; struct grub_ahci_hba_port { grub_uint64_t command_list_base; - grub_uint32_t unused[12]; + grub_uint64_t fis_base; + grub_uint32_t intstatus; + grub_uint32_t inten; + grub_uint32_t command; + grub_uint32_t unused1[6]; grub_uint32_t sata_active; grub_uint32_t command_issue; - grub_uint32_t unused[16]; + grub_uint32_t unused2[17]; }; struct grub_ahci_hba { grub_uint32_t cap; -#define GRUB_AHCI_HBA_CAP_MASK 0x1f grub_uint32_t global_control; -#define GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN 0x80000000 + grub_uint32_t intr_status; grub_uint32_t ports_implemented; - grub_uint32_t unused1[7]; + grub_uint32_t unused1[6]; grub_uint32_t bios_handoff; -#define GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED 1 -#define GRUB_AHCI_BIOS_HANDOFF_OS_OWNED 2 -#define GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED 8 -#define GRUB_AHCI_BIOS_HANDOFF_RWC 8 grub_uint32_t unused2[53]; struct grub_ahci_hba_port ports[32]; }; +enum + { + GRUB_AHCI_HBA_CAP_NPORTS_MASK = 0x1f + }; + +enum + { + GRUB_AHCI_HBA_GLOBAL_CONTROL_INTR_EN = 0x00000002, + GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN = 0x80000000, + }; + +enum + { + GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED = 1, + GRUB_AHCI_BIOS_HANDOFF_OS_OWNED = 2, + GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED = 8, + GRUB_AHCI_BIOS_HANDOFF_RWC = 8 + }; + + struct grub_ahci_device { struct grub_ahci_device *next; @@ -62,19 +102,41 @@ struct grub_ahci_device int num; struct grub_pci_dma_chunk *command_list_chunk; volatile struct grub_ahci_cmd_head *command_list; + struct grub_pci_dma_chunk *command_table_chunk; + volatile struct grub_ahci_cmd_table *command_table; }; +enum + { + GRUB_AHCI_CONFIG_READ = 0, + GRUB_AHCI_CONFIG_CFIS_LENGTH_MASK = 0x1f, + GRUB_AHCI_CONFIG_ATAPI = 0x20, + GRUB_AHCI_CONFIG_WRITE = 0x40, + GRUB_AHCI_CONFIG_PREFETCH = 0x80, + GRUB_AHCI_CONFIG_RESET = 0x100, + GRUB_AHCI_CONFIG_BIST = 0x200, + GRUB_AHCI_CONFIG_CLEAR_R_OK = 0x400, + GRUB_AHCI_CONFIG_PMP_MASK = 0xf000, + GRUB_AHCI_CONFIG_PRDT_LENGTH_MASK = 0xffff0000, + }; +#define GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT 0 +#define GRUB_AHCI_CONFIG_PMP_SHIFT 12 +#define GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT 16 +#define GRUB_AHCI_INTERRUPT_ON_COMPLETE 0x80000000 + +#define GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH 0x200000 + static struct grub_ahci_device *grub_ahci_devices; static int numdevs; static int NESTED_FUNC_ATTR grub_ahci_pciinit (grub_pci_device_t dev, - grub_pci_id_t pciid __attribute__ ((unused))) + grub_pci_id_t pciid __attribute__ ((unused))) { grub_pci_address_t addr; grub_uint32_t class; grub_uint32_t bar; - int nports; + unsigned i, nports; volatile struct grub_ahci_hba *hba; /* Read class. */ @@ -88,8 +150,8 @@ grub_ahci_pciinit (grub_pci_device_t dev, addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG5); bar = grub_pci_read (addr); - if (bar & (GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_TYPE_MASK - | GRUB_PCI_ADDR_MEM_PREFETCH) + if ((bar & (GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_TYPE_MASK + | GRUB_PCI_ADDR_MEM_PREFETCH)) != (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32)) return 0; @@ -98,7 +160,7 @@ grub_ahci_pciinit (grub_pci_device_t dev, hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; - nports = hba->cap & GRUB_AHCI_HBA_CAP_MASK; + nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1; if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED)) { @@ -122,11 +184,13 @@ grub_ahci_pciinit (grub_pci_device_t dev, } else grub_dprintf ("ahci", "AHCI is already in OS mode\n"); + grub_dprintf ("ahci", "%d AHCI ports\n", nports); for (i = 0; i < nports; i++) { struct grub_ahci_device *adev; struct grub_pci_dma_chunk *command_list; + struct grub_pci_dma_chunk *command_table; if (!(hba->ports_implemented & (1 << i))) continue; @@ -136,18 +200,34 @@ grub_ahci_pciinit (grub_pci_device_t dev, if (!command_list) return 1; - adev = grub_malloc (sizeof (*adev)); - if (!adev) + command_table = grub_memalign_dma32 (1024, + sizeof (struct grub_ahci_cmd_table)); + if (!command_table) { grub_dma_free (command_list); return 1; } + adev = grub_malloc (sizeof (*adev)); + if (!adev) + { + grub_dma_free (command_list); + grub_dma_free (command_table); + return 1; + } + + grub_dprintf ("ahci", "found device ahci%d (port %d)\n", numdevs, i); + adev->hba = hba; adev->port = i; adev->num = numdevs++; adev->command_list_chunk = command_list; adev->command_list = grub_dma_get_virt (command_list); + adev->command_table_chunk = command_table; + adev->command_table = grub_dma_get_virt (command_table); + adev->command_list->command_table_base + = grub_dma_get_phys (command_table); + adev->hba->ports[i].command_list_base = grub_dma_get_phys (command_list); grub_list_push (GRUB_AS_LIST_P (&grub_ahci_devices), GRUB_AS_LIST (adev)); @@ -167,12 +247,12 @@ grub_ahci_initialize (void) static int -grub_ahci_iterate (int (*hook) (int bus, int luns)) +grub_ahci_iterate (int (*hook) (int id, int bus)) { struct grub_ahci_device *dev; FOR_LIST_ELEMENTS(dev, grub_ahci_devices) - if (hook (dev->num, 1)) + if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num)) return 1; return 0; @@ -195,95 +275,130 @@ find_free_cmd_slot (struct grub_ahci_device *dev) } #endif -static grub_err_t -grub_ahci_packet (struct grub_ahci_device *dev, char *packet, - grub_size_t size) +enum + { + GRUB_AHCI_FIS_REG_H2D = 0x27 + }; + +static const int register_map[11] = { 3 /* Features */, + 12 /* Sectors */, + 4 /* LBA low */, + 5 /* LBA mid */, + 6 /* LBA high */, + 7 /* Device */, + 2 /* CMD register */, + 13 /* Sectors 48 */, + 8 /* LBA48 low */, + 9 /* LBA48 mid */, + 10 /* LBA48 high */ }; + +static grub_err_t +grub_ahci_readwrite (grub_ata_t disk, + struct grub_disk_ata_pass_through_parms *parms) { + struct grub_ahci_device *dev = (struct grub_ahci_device *) disk->data; + struct grub_pci_dma_chunk *bufc; + grub_uint64_t endtime; + unsigned i; + + grub_dprintf("ahci", "grub_ahci_read (size=%llu, cmdsize = %llu)\n", + (unsigned long long) parms->size, + (unsigned long long) parms->cmdsize); + + if (parms->cmdsize != 0 && parms->cmdsize != 12 && parms->cmdsize != 16) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "incorrect ATAPI command size"); + + if (parms->size > GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "too big data buffer"); + + bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1)); + + /* FIXME: support port multipliers. */ + dev->command_list[0].config + = (4 << GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT) + | GRUB_AHCI_CONFIG_CLEAR_R_OK + | (0 << GRUB_AHCI_CONFIG_PMP_SHIFT) + | (1 << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT) + | (parms->cmdsize ? GRUB_AHCI_CONFIG_ATAPI : 0) + | (parms->write ? GRUB_AHCI_CONFIG_WRITE : GRUB_AHCI_CONFIG_READ); + dev->command_list[0].transfered = 0; + dev->command_list[0].command_table_base + = grub_dma_get_phys (dev->command_table_chunk); + grub_memset ((char *) dev->command_list[0].unused, 0, + sizeof (dev->command_list[0].unused)); + grub_memset ((char *) &dev->command_table[0], 0, + sizeof (dev->command_table[0])); + if (parms->cmdsize) + grub_memcpy ((char *) dev->command_table[0].command, parms->cmd, + parms->cmdsize); + + dev->command_table[0].cfis[0] = GRUB_AHCI_FIS_REG_H2D; + for (i = 0; i < sizeof (parms->taskfile.raw); i++) + dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i]; + + dev->command_table[0].prdt[0].data_base = grub_dma_get_phys (bufc); + dev->command_table[0].prdt[0].unused = 0; + dev->command_table[0].prdt[0].size = (parms->size + (parms->size & 1) - 1) + | GRUB_AHCI_INTERRUPT_ON_COMPLETE; + + if (parms->write) + grub_memcpy ((char *) grub_dma_get_virt (bufc), parms->buffer, parms->size); + + grub_dprintf ("ahci", "AHCI command schedulded\n"); + dev->hba->ports[dev->port].inten = (1 << 5); + dev->hba->ports[dev->port].intstatus = (1 << 5); + dev->hba->ports[dev->port].command_issue |= 1; + dev->hba->ports[dev->port].command |= 1; + + endtime = grub_get_time_ms () + 1000; + while (!(dev->hba->ports[dev->port].intstatus & (1 << 5))) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "AHCI timeout\n"); + dev->hba->ports[dev->port].command &= ~1; + /* FIXME: free resources. */ + return grub_error (GRUB_ERR_IO, "AHCI transfer timeouted"); + } + + grub_dprintf ("ahci", "AHCI command completed succesfully\n"); + dev->hba->ports[dev->port].command &= ~1; + + if (!parms->write) + grub_memcpy (parms->buffer, (char *) grub_dma_get_virt (bufc), parms->size); + grub_dma_free (bufc); return GRUB_ERR_NONE; } static grub_err_t -grub_ahci_read (struct grub_scsi *scsi, - grub_size_t cmdsize __attribute__((unused)), - char *cmd, grub_size_t size, char *buf) -{ - struct grub_ahci_device *dev = (struct grub_ahci_device *) scsi->data; - - grub_dprintf("ahci", "grub_ahci_read (size=%llu)\n", (unsigned long long) size); - - if (grub_atapi_packet (dev, cmd, size)) - return grub_errno; - - grub_size_t nread = 0; - while (nread < size) - { - /* Wait for !BSY, DRQ, I/O, !C/D. */ - if (grub_atapi_wait_drq (dev, GRUB_ATAPI_IREASON_DATA_IN, GRUB_ATA_TOUT_DATA)) - return grub_errno; - - /* Get byte count for this DRQ assertion. */ - unsigned cnt = grub_ata_regget (dev, GRUB_ATAPI_REG_CNTHIGH) << 8 - | grub_ata_regget (dev, GRUB_ATAPI_REG_CNTLOW); - grub_dprintf("ata", "DRQ count=%u\n", cnt); - - /* Count of last transfer may be uneven. */ - if (! (0 < cnt && cnt <= size - nread && (! (cnt & 1) || cnt == size - nread))) - return grub_error (GRUB_ERR_READ_ERROR, "invalid ATAPI transfer count"); - - /* Read the data. */ - grub_ata_pio_read (dev, buf + nread, cnt); - - if (cnt & 1) - buf[nread + cnt - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress + GRUB_ATA_REG_DATA)); - - nread += cnt; - } - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_ahci_write (struct grub_scsi *scsi __attribute__((unused)), - grub_size_t cmdsize __attribute__((unused)), - char *cmd __attribute__((unused)), - grub_size_t size __attribute__((unused)), - char *buf __attribute__((unused))) -{ - // XXX: scsi.mod does not use write yet. - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "AHCI write not implemented"); -} - -static grub_err_t -grub_ahci_open (int devnum, struct grub_scsi *scsi) +grub_ahci_open (int id, int devnum, struct grub_ata *ata) { struct grub_ahci_device *dev; + if (id != GRUB_SCSI_SUBSYSTEM_AHCI) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an AHCI device"); + FOR_LIST_ELEMENTS(dev, grub_ahci_devices) { if (dev->num == devnum) break; } - grub_dprintf ("ata", "opening AHCI dev `ahci%d'\n", devnum); - if (! dev) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such AHCI device"); - scsi->data = dev; + grub_dprintf ("ahci", "opening AHCI dev `ahci%d'\n", dev->num); + + ata->data = dev; return GRUB_ERR_NONE; } - -static struct grub_scsi_dev grub_ahci_dev = +static struct grub_ata_dev grub_ahci_dev = { - .name = "ahci", - .id = GRUB_SCSI_SUBSYSTEM_AHCI, .iterate = grub_ahci_iterate, .open = grub_ahci_open, - .read = grub_ahci_read, - .write = grub_ahci_write + .readwrite = grub_ahci_readwrite, }; @@ -291,8 +406,8 @@ static struct grub_scsi_dev grub_ahci_dev = GRUB_MOD_INIT(ahci) { /* To prevent two drivers operating on the same disks. */ - grub_disk_firmware_is_tainted = 1; - if (grub_disk_firmware_fini) + // grub_disk_firmware_is_tainted = 1; + if (0 && grub_disk_firmware_fini) { grub_disk_firmware_fini (); grub_disk_firmware_fini = NULL; @@ -302,10 +417,10 @@ GRUB_MOD_INIT(ahci) grub_ahci_initialize (); /* AHCI devices are handled by scsi.mod. */ - grub_scsi_dev_register (&grub_ahci_dev); + grub_ata_dev_register (&grub_ahci_dev); } GRUB_MOD_FINI(ahci) { - grub_scsi_dev_unregister (&grub_ahci_dev); + grub_ata_dev_unregister (&grub_ahci_dev); } diff --git a/disk/ata.c b/disk/ata.c index cfd58a6d5..3d9de23dd 100644 --- a/disk/ata.c +++ b/disk/ata.c @@ -21,76 +21,9 @@ #include #include #include -#include -#include #include -#include -/* At the moment, only two IDE ports are supported. */ -static const grub_port_t grub_ata_ioaddress[] = { GRUB_ATA_CH0_PORT1, - GRUB_ATA_CH1_PORT1 }; -static const grub_port_t grub_ata_ioaddress2[] = { GRUB_ATA_CH0_PORT2, - GRUB_ATA_CH1_PORT2 }; - -static struct grub_ata_device *grub_ata_devices; - -/* Wait for !BSY. */ -grub_err_t -grub_ata_wait_not_busy (struct grub_ata_device *dev, int milliseconds) -{ - /* ATA requires 400ns (after a write to CMD register) or - 1 PIO cycle (after a DRQ block transfer) before - first check of BSY. */ - grub_millisleep (1); - - int i = 1; - grub_uint8_t sts; - while ((sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS)) - & GRUB_ATA_STATUS_BUSY) - { - if (i >= milliseconds) - { - grub_dprintf ("ata", "timeout: %dms, status=0x%x\n", - milliseconds, sts); - return grub_error (GRUB_ERR_TIMEOUT, "ATA timeout"); - } - - grub_millisleep (1); - i++; - } - - return GRUB_ERR_NONE; -} - -static inline void -grub_ata_wait (void) -{ - grub_millisleep (50); -} - -/* Wait for !BSY, DRQ. */ -grub_err_t -grub_ata_wait_drq (struct grub_ata_device *dev, int rw, - int milliseconds) -{ - if (grub_ata_wait_not_busy (dev, milliseconds)) - return grub_errno; - - /* !DRQ implies error condition. */ - grub_uint8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS); - if ((sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) - != GRUB_ATA_STATUS_DRQ) - { - grub_dprintf ("ata", "ata error: status=0x%x, error=0x%x\n", - sts, grub_ata_regget (dev, GRUB_ATA_REG_ERROR)); - if (! rw) - return grub_error (GRUB_ERR_READ_ERROR, "ATA read error"); - else - return grub_error (GRUB_ERR_WRITE_ERROR, "ATA write error"); - } - - return GRUB_ERR_NONE; -} +static grub_ata_dev_t grub_ata_dev_list; /* Byteorder has to be changed before strings can be read. */ static void @@ -105,30 +38,8 @@ grub_ata_strncpy (char *dst, char *src, grub_size_t len) dst[len] = '\0'; } -void -grub_ata_pio_read (struct grub_ata_device *dev, char *buf, grub_size_t size) -{ - grub_uint16_t *buf16 = (grub_uint16_t *) buf; - unsigned int i; - - /* Read in the data, word by word. */ - for (i = 0; i < size / 2; i++) - buf16[i] = grub_le_to_cpu16 (grub_inw(dev->ioaddress + GRUB_ATA_REG_DATA)); -} - static void -grub_ata_pio_write (struct grub_ata_device *dev, char *buf, grub_size_t size) -{ - grub_uint16_t *buf16 = (grub_uint16_t *) buf; - unsigned int i; - - /* Write the data, word by word. */ - for (i = 0; i < size / 2; i++) - grub_outw(grub_cpu_to_le16 (buf16[i]), dev->ioaddress + GRUB_ATA_REG_DATA); -} - -static void -grub_ata_dumpinfo (struct grub_ata_device *dev, char *info) +grub_ata_dumpinfo (struct grub_ata *dev, char *info) { char text[41]; @@ -148,31 +59,27 @@ grub_ata_dumpinfo (struct grub_ata_device *dev, char *info) } static grub_err_t -grub_atapi_identify (struct grub_ata_device *dev) +grub_atapi_identify (struct grub_ata *dev) { + struct grub_disk_ata_pass_through_parms parms; char *info; + grub_err_t err; info = grub_malloc (GRUB_DISK_SECTOR_SIZE); if (! info) return grub_errno; - grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4); - grub_ata_wait (); - if (grub_ata_check_ready (dev)) - { - grub_free (info); - return grub_errno; - } + grub_memset (&parms, 0, sizeof (parms)); + parms.taskfile.disk = 0; + parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE; - grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE); - grub_ata_wait (); + err = dev->dev->readwrite (dev, &parms); + if (err) + return err; - if (grub_ata_wait_drq (dev, 0, GRUB_ATA_TOUT_STD)) - { - grub_free (info); - return grub_errno; - } - grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE); + if (parms.size != GRUB_DISK_SECTOR_SIZE) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + "device cannot be identified"); dev->atapi = 1; @@ -184,96 +91,35 @@ grub_atapi_identify (struct grub_ata_device *dev) } static grub_err_t -grub_atapi_wait_drq (struct grub_ata_device *dev, - grub_uint8_t ireason, - int milliseconds) -{ - /* Wait for !BSY, DRQ, ireason */ - if (grub_ata_wait_not_busy (dev, milliseconds)) - return grub_errno; - - grub_uint8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS); - grub_uint8_t irs = grub_ata_regget (dev, GRUB_ATAPI_REG_IREASON); - - /* OK if DRQ is asserted and interrupt reason is as expected. */ - if ((sts & GRUB_ATA_STATUS_DRQ) - && (irs & GRUB_ATAPI_IREASON_MASK) == ireason) - return GRUB_ERR_NONE; - - /* !DRQ implies error condition. */ - grub_dprintf ("ata", "atapi error: status=0x%x, ireason=0x%x, error=0x%x\n", - sts, irs, grub_ata_regget (dev, GRUB_ATA_REG_ERROR)); - - if (! (sts & GRUB_ATA_STATUS_DRQ) - && (irs & GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_ERROR) - { - if (ireason == GRUB_ATAPI_IREASON_CMD_OUT) - return grub_error (GRUB_ERR_READ_ERROR, "ATA PACKET command error"); - else - return grub_error (GRUB_ERR_READ_ERROR, "ATAPI read error"); - } - - return grub_error (GRUB_ERR_READ_ERROR, "ATAPI protocol error"); -} - -static grub_err_t -grub_atapi_packet (struct grub_ata_device *dev, char *packet, - grub_size_t size) -{ - grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4); - if (grub_ata_check_ready (dev)) - return grub_errno; - - /* Send ATA PACKET command. */ - grub_ata_regset (dev, GRUB_ATA_REG_FEATURES, 0); - grub_ata_regset (dev, GRUB_ATAPI_REG_IREASON, 0); - grub_ata_regset (dev, GRUB_ATAPI_REG_CNTHIGH, size >> 8); - grub_ata_regset (dev, GRUB_ATAPI_REG_CNTLOW, size & 0xFF); - - grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_PACKET); - - /* Wait for !BSY, DRQ, !I/O, C/D. */ - if (grub_atapi_wait_drq (dev, GRUB_ATAPI_IREASON_CMD_OUT, GRUB_ATA_TOUT_STD)) - return grub_errno; - - /* Write the packet. */ - grub_ata_pio_write (dev, packet, 12); - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_ata_identify (struct grub_ata_device *dev) +grub_ata_identify (struct grub_ata *dev) { + struct grub_disk_ata_pass_through_parms parms; char *info; grub_uint16_t *info16; + grub_err_t err; info = grub_malloc (GRUB_DISK_SECTOR_SIZE); if (! info) return grub_errno; info16 = (grub_uint16_t *) info; + grub_memset (&parms, 0, sizeof (parms)); + parms.buffer = info; + parms.taskfile.disk = 0; - grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4); - grub_ata_wait (); - if (grub_ata_check_ready (dev)) + parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_DEVICE; + + err = dev->dev->readwrite (dev, &parms); + if (err) + return err; + + if (parms.size != GRUB_DISK_SECTOR_SIZE) { + grub_uint8_t sts = parms.taskfile.status; grub_free (info); - return grub_errno; - } - - grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_IDENTIFY_DEVICE); - grub_ata_wait (); - - if (grub_ata_wait_drq (dev, 0, GRUB_ATA_TOUT_STD)) - { - grub_free (info); - grub_errno = GRUB_ERR_NONE; - grub_uint8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS); - if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR - && (grub_ata_regget (dev, GRUB_ATA_REG_ERROR) & 0x04 /* ABRT */)) + && (parms.taskfile.error & 0x04 /* ABRT */)) /* Device without ATA IDENTIFY, try ATAPI. */ return grub_atapi_identify (dev); @@ -287,19 +133,6 @@ grub_ata_identify (struct grub_ata_device *dev) "device cannot be identified"); } - grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE); - - /* Re-check status to avoid bogus identify data due to stuck DRQ. */ - grub_uint8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS); - if (sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) - { - grub_dprintf ("ata", "bad status=0x%x\n", sts); - grub_free (info); - /* No device, return error but don't print message. */ - grub_errno = GRUB_ERR_NONE; - return GRUB_ERR_UNKNOWN_DEVICE; - } - /* Now it is certain that this is not an ATAPI device. */ dev->atapi = 0; @@ -335,196 +168,12 @@ grub_ata_identify (struct grub_ata_device *dev) } static grub_err_t -check_device (struct grub_ata_device *dev) -{ - grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4); - grub_ata_wait (); - - /* Try to detect if the port is in use by writing to it, - waiting for a while and reading it again. If the value - was preserved, there is a device connected. */ - grub_ata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A); - grub_ata_wait (); - grub_uint8_t sec = grub_ata_regget (dev, GRUB_ATA_REG_SECTORS); - grub_dprintf ("ata", "sectors=0x%x\n", sec); - if (sec != 0x5A) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no device connected"); - - /* The above test may detect a second (slave) device - connected to a SATA controller which supports only one - (master) device. It is not safe to use the status register - READY bit to check for controller channel existence. Some - ATAPI commands (RESET, DIAGNOSTIC) may clear this bit. */ - - /* Use the IDENTIFY DEVICE command to query the device. */ - return grub_ata_identify (dev); -} - -static grub_err_t -grub_ata_device_initialize (int port, int device, int addr, int addr2) -{ - struct grub_ata_device *dev; - struct grub_ata_device **devp; - grub_err_t err; - - grub_dprintf ("ata", "detecting device %d,%d (0x%x, 0x%x)\n", - port, device, addr, addr2); - - dev = grub_malloc (sizeof(*dev)); - if (! dev) - return grub_errno; - - /* Setup the device information. */ - dev->port = port; - dev->device = device; - dev->ioaddress = addr + GRUB_MACHINE_PCI_IO_BASE; - dev->ioaddress2 = addr2 + GRUB_MACHINE_PCI_IO_BASE; - dev->next = NULL; - - /* Register the device. */ - for (devp = &grub_ata_devices; *devp; devp = &(*devp)->next); - *devp = dev; - - err = check_device (dev); - if (err) - grub_print_error (); - - return 0; -} - -static int NESTED_FUNC_ATTR -grub_ata_pciinit (grub_pci_device_t dev, - grub_pci_id_t pciid) -{ - static int compat_use[2] = { 0 }; - grub_pci_address_t addr; - grub_uint32_t class; - grub_uint32_t bar1; - grub_uint32_t bar2; - int rega; - int regb; - int i; - static int controller = 0; - int cs5536 = 0; - int nports = 2; - - /* Read class. */ - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - class = grub_pci_read (addr); - - /* AMD CS5536 Southbridge. */ - if (pciid == GRUB_CS5536_PCIID) - { - cs5536 = 1; - nports = 1; - } - - /* Check if this class ID matches that of a PCI IDE Controller. */ - if (!cs5536 && (class >> 16 != 0x0101)) - return 0; - - for (i = 0; i < nports; i++) - { - /* Set to 0 when the channel operated in compatibility mode. */ - int compat; - - /* We don't support non-compatibility mode for CS5536. */ - if (cs5536) - compat = 0; - else - compat = (class >> (8 + 2 * i)) & 1; - - rega = 0; - regb = 0; - - /* If the channel is in compatibility mode, just assign the - default registers. */ - if (compat == 0 && !compat_use[i]) - { - rega = grub_ata_ioaddress[i]; - regb = grub_ata_ioaddress2[i]; - compat_use[i] = 1; - } - else if (compat) - { - /* Read the BARs, which either contain a mmapped IO address - or the IO port address. */ - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES - + sizeof (grub_uint64_t) * i); - bar1 = grub_pci_read (addr); - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES - + sizeof (grub_uint64_t) * i - + sizeof (grub_uint32_t)); - bar2 = grub_pci_read (addr); - - /* Check if the BARs describe an IO region. */ - if ((bar1 & 1) && (bar2 & 1)) - { - rega = bar1 & ~3; - regb = bar2 & ~3; - } - } - - grub_dprintf ("ata", - "PCI dev (%d,%d,%d) compat=%d rega=0x%x regb=0x%x\n", - grub_pci_get_bus (dev), grub_pci_get_device (dev), - grub_pci_get_function (dev), compat, rega, regb); - - if (rega && regb) - { - grub_errno = GRUB_ERR_NONE; - grub_ata_device_initialize (controller * 2 + i, 0, rega, regb); - - /* Most errors raised by grub_ata_device_initialize() are harmless. - They just indicate this particular drive is not responding, most - likely because it doesn't exist. We might want to ignore specific - error types here, instead of printing them. */ - if (grub_errno) - { - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - } - - grub_ata_device_initialize (controller * 2 + i, 1, rega, regb); - - /* Likewise. */ - if (grub_errno) - { - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - } - } - } - - controller++; - - return 0; -} - -static grub_err_t -grub_ata_initialize (void) -{ - grub_pci_iterate (grub_ata_pciinit); - return 0; -} - -static void -grub_ata_setlba (struct grub_ata_device *dev, grub_disk_addr_t sector, - grub_size_t size) -{ - grub_ata_regset (dev, GRUB_ATA_REG_SECTORS, size); - grub_ata_regset (dev, GRUB_ATA_REG_LBALOW, sector & 0xFF); - grub_ata_regset (dev, GRUB_ATA_REG_LBAMID, (sector >> 8) & 0xFF); - grub_ata_regset (dev, GRUB_ATA_REG_LBAHIGH, (sector >> 16) & 0xFF); -} - -static grub_err_t -grub_ata_setaddress (struct grub_ata_device *dev, - grub_ata_addressing_t addressing, +grub_ata_setaddress (struct grub_ata *dev, + struct grub_disk_ata_pass_through_parms *parms, grub_disk_addr_t sector, grub_size_t size) { - switch (addressing) + switch (dev->addr) { case GRUB_ATA_CHS: { @@ -544,14 +193,11 @@ grub_ata_setaddress (struct grub_ata_device *dev, return grub_error (GRUB_ERR_OUT_OF_RANGE, "sector %d cannot be addressed " "using CHS addressing", sector); - - grub_ata_regset (dev, GRUB_ATA_REG_DISK, (dev->device << 4) | head); - if (grub_ata_check_ready (dev)) - return grub_errno; - - grub_ata_regset (dev, GRUB_ATA_REG_SECTNUM, sect); - grub_ata_regset (dev, GRUB_ATA_REG_CYLLSB, cylinder & 0xFF); - grub_ata_regset (dev, GRUB_ATA_REG_CYLMSB, cylinder >> 8); + + parms->taskfile.disk = head; + parms->taskfile.sectnum = sect; + parms->taskfile.cyllsb = cylinder & 0xFF; + parms->taskfile.cylmsb = cylinder >> 8; break; } @@ -559,26 +205,31 @@ grub_ata_setaddress (struct grub_ata_device *dev, case GRUB_ATA_LBA: if (size == 256) size = 0; - grub_ata_regset (dev, GRUB_ATA_REG_DISK, - 0xE0 | (dev->device << 4) | ((sector >> 24) & 0x0F)); - if (grub_ata_check_ready (dev)) - return grub_errno; + parms->taskfile.disk = ((sector >> 24) & 0x0F); - grub_ata_setlba (dev, sector, size); + parms->taskfile.sectors = size; + parms->taskfile.lba_low = sector & 0xFF; + parms->taskfile.lba_mid = (sector >> 8) & 0xFF; + parms->taskfile.lba_high = (sector >> 16) & 0xFF; break; case GRUB_ATA_LBA48: if (size == 65536) size = 0; - grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | (dev->device << 4)); - if (grub_ata_check_ready (dev)) - return grub_errno; + parms->taskfile.disk = 0; /* Set "Previous". */ - grub_ata_setlba (dev, sector >> 24, size >> 8); + parms->taskfile.sectors = size & 0xFF; + parms->taskfile.lba_low = sector & 0xFF; + parms->taskfile.lba_mid = (sector >> 8) & 0xFF; + parms->taskfile.lba_high = (sector >> 16) & 0xFF; + /* Set "Current". */ - grub_ata_setlba (dev, sector, size); + parms->taskfile.sectors48 = (size >> 8) & 0xFF; + parms->taskfile.lba48_low = (sector >> 24) & 0xFF; + parms->taskfile.lba48_mid = (sector >> 32) & 0xFF; + parms->taskfile.lba48_high = (sector >> 40) & 0xFF; break; } @@ -590,14 +241,15 @@ static grub_err_t grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t size, char *buf, int rw) { - struct grub_ata_device *dev = (struct grub_ata_device *) disk->data; + struct grub_ata *ata = disk->data; - grub_dprintf("ata", "grub_ata_readwrite (size=%llu, rw=%d)\n", (unsigned long long) size, rw); - - grub_ata_addressing_t addressing = dev->addr; + grub_ata_addressing_t addressing = ata->addr; grub_size_t batch; int cmd, cmd_write; + grub_dprintf("ata", "grub_ata_readwrite (size=%llu, rw=%d)\n", + (unsigned long long) size, rw); + if (addressing == GRUB_ATA_LBA48 && ((sector + size) >> 28) != 0) { batch = 65536; @@ -608,7 +260,10 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, { if (addressing == GRUB_ATA_LBA48) addressing = GRUB_ATA_LBA; - batch = 256; + if (addressing != GRUB_ATA_CHS) + batch = 256; + else + batch = 1; cmd = GRUB_ATA_CMD_READ_SECTORS; cmd_write = GRUB_ATA_CMD_WRITE_SECTORS; } @@ -616,44 +271,25 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t nsectors = 0; while (nsectors < size) { + struct grub_disk_ata_pass_through_parms parms; + grub_err_t err; + if (size - nsectors < batch) batch = size - nsectors; grub_dprintf("ata", "rw=%d, sector=%llu, batch=%llu\n", rw, (unsigned long long) sector, (unsigned long long) batch); - - /* Send read/write command. */ - if (grub_ata_setaddress (dev, addressing, sector, batch)) - return grub_errno; - - grub_ata_regset (dev, GRUB_ATA_REG_CMD, (! rw ? cmd : cmd_write)); - - unsigned sect; - for (sect = 0; sect < batch; sect++) - { - /* Wait for !BSY, DRQ. */ - if (grub_ata_wait_drq (dev, rw, GRUB_ATA_TOUT_DATA)) - return grub_errno; - - /* Transfer data. */ - if (! rw) - grub_ata_pio_read (dev, buf, GRUB_DISK_SECTOR_SIZE); - else - grub_ata_pio_write (dev, buf, GRUB_DISK_SECTOR_SIZE); - - buf += GRUB_DISK_SECTOR_SIZE; - } - - if (rw) - { - /* Check for write error. */ - if (grub_ata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) - return grub_errno; - - if (grub_ata_regget (dev, GRUB_ATA_REG_STATUS) - & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) - return grub_error (GRUB_ERR_WRITE_ERROR, "ATA write error"); - } - + grub_memset (&parms, 0, sizeof (parms)); + grub_ata_setaddress (ata, &parms, sector, batch); + parms.taskfile.cmd = (! rw ? cmd : cmd_write); + parms.buffer = buf; + parms.size = batch * GRUB_DISK_SECTOR_SIZE; + + err = ata->dev->readwrite (ata, &parms); + if (err) + return err; + if (parms.size != batch * GRUB_DISK_SECTOR_SIZE) + return grub_error (GRUB_ERR_READ_ERROR, "incomplete read"); + buf += GRUB_DISK_SECTOR_SIZE * batch; sector += batch; nsectors += batch; } @@ -663,76 +299,118 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, -static int -grub_ata_iterate (int (*hook) (const char *name)) +static inline void +grub_ata_real_close (struct grub_ata *ata) { - struct grub_ata_device *dev; + if (ata->dev->close) + ata->dev->close (ata); +} - for (dev = grub_ata_devices; dev; dev = dev->next) +static struct grub_ata * +grub_ata_real_open (int id, int bus) +{ + struct grub_ata *ata; + grub_ata_dev_t p; + + ata = grub_malloc (sizeof (*ata)); + if (!ata) + return NULL; + for (p = grub_ata_dev_list; p; p = p->next) { - char devname[10]; grub_err_t err; - - err = check_device (dev); - if (err) + if (p->open (id, bus, ata)) { grub_errno = GRUB_ERR_NONE; continue; } - - if (dev->atapi) - continue; - - grub_snprintf (devname, sizeof (devname), - "ata%d", dev->port * 2 + dev->device); - - if (hook (devname)) - return 1; + ata->dev = p; + /* Use the IDENTIFY DEVICE command to query the device. */ + err = grub_ata_identify (ata); + if (err) + { + grub_free (ata); + return NULL; + } + return ata; } + grub_free (ata); + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATA device"); + return NULL; +} +static int +grub_ata_iterate (int (*hook_in) (const char *name)) +{ + auto int hook (int id, int bus); + int hook (int id, int bus) + { + struct grub_ata *ata; + int ret; + char devname[40]; + + ata = grub_ata_real_open (id, bus); + + if (!ata) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (ata->atapi) + { + grub_ata_real_close (ata); + return 0; + } + grub_snprintf (devname, sizeof (devname), + "%s%d", grub_scsi_names[id], bus); + ret = hook_in (devname); + grub_ata_real_close (ata); + return ret; + } + + grub_ata_dev_t p; + + for (p = grub_ata_dev_list; p; p = p->next) + if (p->iterate && p->iterate (hook)) + return 1; return 0; } static grub_err_t grub_ata_open (const char *name, grub_disk_t disk) { - struct grub_ata_device *dev; - grub_err_t err; + unsigned id, bus; + struct grub_ata *ata; - for (dev = grub_ata_devices; dev; dev = dev->next) - { - char devname[10]; - grub_snprintf (devname, sizeof (devname), - "ata%d", dev->port * 2 + dev->device); - if (grub_strcmp (name, devname) == 0) - break; - } + for (id = 0; id < GRUB_SCSI_NUM_SUBSYSTEMS; id++) + if (grub_strncmp (grub_scsi_names[id], name, + grub_strlen (grub_scsi_names[id])) == 0 + && grub_isdigit (name[grub_strlen (grub_scsi_names[id])])) + break; + if (id == GRUB_SCSI_NUM_SUBSYSTEMS) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk"); + bus = grub_strtoul (name + grub_strlen (grub_scsi_names[id]), 0, 0); + ata = grub_ata_real_open (id, bus); + if (!ata) + return grub_errno; - if (! dev) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); - - if (dev->atapi) + if (ata->atapi) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk"); - err = check_device (dev); + disk->total_sectors = ata->size; - if (err) - return err; - - disk->total_sectors = dev->size; - - disk->id = (unsigned long) dev; + disk->id = grub_make_scsi_id (id, bus, 0); disk->has_partitions = 1; - disk->data = dev; + disk->data = ata; return 0; } static void -grub_ata_close (grub_disk_t disk __attribute__((unused))) +grub_ata_close (grub_disk_t disk) { - + struct grub_ata *ata = disk->data; + grub_ata_real_close (ata); } static grub_err_t @@ -767,70 +445,35 @@ static struct grub_disk_dev grub_atadisk_dev = /* ATAPI code. */ -static int -grub_atapi_iterate (int (*hook) (int bus, int luns)) -{ - struct grub_ata_device *dev; - - for (dev = grub_ata_devices; dev; dev = dev->next) - { - grub_err_t err; - - err = check_device (dev); - if (err) - { - grub_errno = GRUB_ERR_NONE; - continue; - } - - if (! dev->atapi) - continue; - - if (hook (dev->port * 2 + dev->device, 1)) - return 1; - } - - return 0; - -} - static grub_err_t -grub_atapi_read (struct grub_scsi *scsi, - grub_size_t cmdsize __attribute__((unused)), - char *cmd, grub_size_t size, char *buf) +grub_atapi_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, + grub_size_t size, char *buf) { - struct grub_ata_device *dev = (struct grub_ata_device *) scsi->data; + struct grub_ata *dev = scsi->data; + struct grub_disk_ata_pass_through_parms parms; + grub_err_t err; grub_dprintf("ata", "grub_atapi_read (size=%llu)\n", (unsigned long long) size); + grub_memset (&parms, 0, sizeof (parms)); - if (grub_atapi_packet (dev, cmd, size)) - return grub_errno; + parms.taskfile.disk = 0; + parms.taskfile.features = 0; + parms.taskfile.atapi_ireason = 0; + parms.taskfile.atapi_cnthigh = size >> 8; + parms.taskfile.atapi_cntlow = size & 0xff; + parms.taskfile.cmd = GRUB_ATA_CMD_PACKET; + parms.cmd = cmd; + parms.cmdsize = cmdsize; - grub_size_t nread = 0; - while (nread < size) - { - /* Wait for !BSY, DRQ, I/O, !C/D. */ - if (grub_atapi_wait_drq (dev, GRUB_ATAPI_IREASON_DATA_IN, GRUB_ATA_TOUT_DATA)) - return grub_errno; - - /* Get byte count for this DRQ assertion. */ - unsigned cnt = grub_ata_regget (dev, GRUB_ATAPI_REG_CNTHIGH) << 8 - | grub_ata_regget (dev, GRUB_ATAPI_REG_CNTLOW); - grub_dprintf("ata", "DRQ count=%u\n", cnt); - - /* Count of last transfer may be uneven. */ - if (! (0 < cnt && cnt <= size - nread && (! (cnt & 1) || cnt == size - nread))) - return grub_error (GRUB_ERR_READ_ERROR, "invalid ATAPI transfer count"); - - /* Read the data. */ - grub_ata_pio_read (dev, buf + nread, cnt); - - if (cnt & 1) - buf[nread + cnt - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress + GRUB_ATA_REG_DATA)); - - nread += cnt; - } + parms.size = size; + parms.buffer = buf; + + err = dev->dev->readwrite (dev, &parms); + if (err) + return err; + if (parms.size != size) + return grub_error (GRUB_ERR_READ_ERROR, "incomplete ATAPI read"); return GRUB_ERR_NONE; } @@ -846,64 +489,98 @@ grub_atapi_write (struct grub_scsi *scsi __attribute__((unused)), } static grub_err_t -grub_atapi_open (int devnum, struct grub_scsi *scsi) +grub_atapi_open (int id, int bus, struct grub_scsi *scsi) { - struct grub_ata_device *dev; - struct grub_ata_device *devfnd = 0; - grub_err_t err; + struct grub_ata *ata; - for (dev = grub_ata_devices; dev; dev = dev->next) - { - if (dev->port * 2 + dev->device == devnum) - { - devfnd = dev; - break; - } - } - - grub_dprintf ("ata", "opening ATAPI dev `ata%d'\n", devnum); - - if (! devfnd) + ata = grub_ata_real_open (id, bus); + if (!ata) + return grub_errno; + + if (! ata->atapi) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device"); - err = check_device (devfnd); - if (err) - return err; - - if (! devfnd->atapi) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device"); - - scsi->data = devfnd; + scsi->data = ata; return GRUB_ERR_NONE; } +static int +grub_atapi_iterate (int (*hook_in) (int id, int bus, int luns)) +{ + auto int hook (int id, int bus); + int hook (int id, int bus) + { + struct grub_ata *ata; + int ret; + + ata = grub_ata_real_open (id, bus); + + if (!ata) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (!ata->atapi) + { + grub_ata_real_close (ata); + return 0; + } + ret = hook_in (id, bus, 1); + grub_ata_real_close (ata); + return ret; + } + + grub_ata_dev_t p; + + for (p = grub_ata_dev_list; p; p = p->next) + if (p->iterate && p->iterate (hook)) + return 1; + return 0; +} + +static void +grub_atapi_close (grub_scsi_t disk) +{ + struct grub_ata *ata = disk->data; + grub_ata_real_close (ata); +} + + +void +grub_ata_dev_register (grub_ata_dev_t dev) +{ + dev->next = grub_ata_dev_list; + grub_ata_dev_list = dev; +} + +void +grub_ata_dev_unregister (grub_ata_dev_t dev) +{ + grub_ata_dev_t *p, q; + + for (p = &grub_ata_dev_list, q = *p; q; p = &(q->next), q = q->next) + if (q == dev) + { + *p = q->next; + break; + } +} static struct grub_scsi_dev grub_atapi_dev = { - .name = "ata", - .id = GRUB_SCSI_SUBSYSTEM_ATAPI, .iterate = grub_atapi_iterate, .open = grub_atapi_open, + .close = grub_atapi_close, .read = grub_atapi_read, - .write = grub_atapi_write + .write = grub_atapi_write, + .next = 0 }; GRUB_MOD_INIT(ata) { - /* To prevent two drivers operating on the same disks. */ - grub_disk_firmware_is_tainted = 1; - if (grub_disk_firmware_fini) - { - grub_disk_firmware_fini (); - grub_disk_firmware_fini = NULL; - } - - /* ATA initialization. */ - grub_ata_initialize (); - grub_disk_dev_register (&grub_atadisk_dev); /* ATAPI devices are handled by scsi.mod. */ diff --git a/disk/ata_pthru.c b/disk/ata_pthru.c index f52725a49..b6edf78d6 100644 --- a/disk/ata_pthru.c +++ b/disk/ata_pthru.c @@ -18,90 +18,496 @@ */ #include +#include #include #include #include +#include +#include +#include +/* At the moment, only two IDE ports are supported. */ +static const grub_port_t grub_pata_ioaddress[] = { GRUB_ATA_CH0_PORT1, + GRUB_ATA_CH1_PORT1 }; +static const grub_port_t grub_pata_ioaddress2[] = { GRUB_ATA_CH0_PORT2, + GRUB_ATA_CH1_PORT2 }; -/* ATA pass through support, used by hdparm.mod. */ -static grub_err_t -grub_ata_pass_through (grub_disk_t disk, - struct grub_disk_ata_pass_through_parms *parms) +struct grub_pata_device { - if (disk->dev->id != GRUB_DISK_DEVICE_ATA_ID) - return grub_error (GRUB_ERR_BAD_DEVICE, - "device not accessed via ata.mod"); + /* IDE port to use. */ + int port; - struct grub_ata_device *dev = (struct grub_ata_device *) disk->data; + /* IO addresses on which the registers for this device can be + found. */ + grub_port_t ioaddress; + grub_port_t ioaddress2; - if (! (parms->size == 0 || parms->size == GRUB_DISK_SECTOR_SIZE)) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "ATA multi-sector read and DATA OUT not implemented"); + /* Two devices can be connected to a single cable. Use this field + to select device 0 (commonly known as "master") or device 1 + (commonly known as "slave"). */ + int device; - grub_dprintf ("ata", "ata_pass_through: cmd=0x%x, features=0x%x, sectors=0x%x\n", - parms->taskfile[GRUB_ATA_REG_CMD], - parms->taskfile[GRUB_ATA_REG_FEATURES], - parms->taskfile[GRUB_ATA_REG_SECTORS]); - grub_dprintf ("ata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%d\n", - parms->taskfile[GRUB_ATA_REG_LBAHIGH], - parms->taskfile[GRUB_ATA_REG_LBAMID], - parms->taskfile[GRUB_ATA_REG_LBALOW], parms->size); + struct grub_pata_device *next; +}; - /* Set registers. */ - grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4 - | (parms->taskfile[GRUB_ATA_REG_DISK] & 0xf)); - if (grub_ata_check_ready (dev)) - return grub_errno; +static struct grub_pata_device *grub_pata_devices; - int i; - for (i = GRUB_ATA_REG_FEATURES; i <= GRUB_ATA_REG_LBAHIGH; i++) - grub_ata_regset (dev, i, parms->taskfile[i]); +static inline void +grub_pata_regset (struct grub_pata_device *dev, int reg, int val) +{ + grub_outb (val, dev->ioaddress + reg); +} - /* Start command. */ - grub_ata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile[GRUB_ATA_REG_CMD]); +static inline grub_uint8_t +grub_pata_regget (struct grub_pata_device *dev, int reg) +{ + return grub_inb (dev->ioaddress + reg); +} - /* Wait for !BSY. */ - if (grub_ata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) - return grub_errno; +static inline void +grub_pata_regset2 (struct grub_pata_device *dev, int reg, int val) +{ + grub_outb (val, dev->ioaddress2 + reg); +} - /* Check status. */ - grub_int8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS); - grub_dprintf ("ata", "status=0x%x\n", sts); +static inline grub_uint8_t +grub_pata_regget2 (struct grub_pata_device *dev, int reg) +{ + return grub_inb (dev->ioaddress2 + reg); +} - /* Transfer data. */ - if ((sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_DRQ) +/* Wait for !BSY. */ +static grub_err_t +grub_pata_wait_not_busy (struct grub_pata_device *dev, int milliseconds) +{ + /* ATA requires 400ns (after a write to CMD register) or + 1 PIO cycle (after a DRQ block transfer) before + first check of BSY. */ + grub_millisleep (1); + + int i = 1; + grub_uint8_t sts; + while ((sts = grub_pata_regget (dev, GRUB_ATA_REG_STATUS)) + & GRUB_ATA_STATUS_BUSY) { - if (parms->size != GRUB_DISK_SECTOR_SIZE) - return grub_error (GRUB_ERR_READ_ERROR, "DRQ unexpected"); - grub_ata_pio_read (dev, parms->buffer, GRUB_DISK_SECTOR_SIZE); + if (i >= milliseconds) + { + grub_dprintf ("pata", "timeout: %dms, status=0x%x\n", + milliseconds, sts); + return grub_error (GRUB_ERR_TIMEOUT, "PATA timeout"); + } + + grub_millisleep (1); + i++; } - /* Return registers. */ - for (i = GRUB_ATA_REG_ERROR; i <= GRUB_ATA_REG_STATUS; i++) - parms->taskfile[i] = grub_ata_regget (dev, i); - - grub_dprintf ("ata", "status=0x%x, error=0x%x, sectors=0x%x\n", - parms->taskfile[GRUB_ATA_REG_STATUS], - parms->taskfile[GRUB_ATA_REG_ERROR], - parms->taskfile[GRUB_ATA_REG_SECTORS]); - - if (parms->taskfile[GRUB_ATA_REG_STATUS] - & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) - return grub_error (GRUB_ERR_READ_ERROR, "ATA passthrough failed"); - return GRUB_ERR_NONE; } +static inline grub_err_t +grub_pata_check_ready (struct grub_pata_device *dev) +{ + if (grub_pata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY) + return grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_STD); + + return GRUB_ERR_NONE; +} + +static inline void +grub_pata_wait (void) +{ + grub_millisleep (50); +} + +static void +grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size) +{ + grub_uint16_t *buf16 = (grub_uint16_t *) buf; + unsigned int i; + + /* Read in the data, word by word. */ + for (i = 0; i < size / 2; i++) + buf16[i] = grub_le_to_cpu16 (grub_inw(dev->ioaddress + GRUB_ATA_REG_DATA)); + if (size & 1) + buf[size - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress + + GRUB_ATA_REG_DATA)); +} + +static void +grub_pata_pio_write (struct grub_pata_device *dev, char *buf, grub_size_t size) +{ + grub_uint16_t *buf16 = (grub_uint16_t *) buf; + unsigned int i; + + /* Write the data, word by word. */ + for (i = 0; i < size / 2; i++) + grub_outw(grub_cpu_to_le16 (buf16[i]), dev->ioaddress + GRUB_ATA_REG_DATA); +} + +/* ATA pass through support, used by hdparm.mod. */ +static grub_err_t +grub_pata_readwrite (struct grub_ata *disk, + struct grub_disk_ata_pass_through_parms *parms) +{ + struct grub_pata_device *dev = (struct grub_pata_device *) disk->data; + grub_size_t nread = 0; + + if (! (parms->cmdsize == 0 || parms->cmdsize == 12)) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "ATAPI non-12 byte commands not supported"); + + grub_dprintf ("pata", "pata_pass_through: cmd=0x%x, features=0x%x, sectors=0x%x\n", + parms->taskfile.cmd, + parms->taskfile.features, + parms->taskfile.sectors); + grub_dprintf ("pata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%d\n", + parms->taskfile.lba_high, + parms->taskfile.lba_mid, + parms->taskfile.lba_low, parms->size); + + /* Set registers. */ + grub_pata_regset (dev, GRUB_ATA_REG_DISK, (parms->cmdsize ? 0 : 0xE0) + | dev->device << 4 + | (parms->taskfile.disk & 0xf)); + if (grub_pata_check_ready (dev)) + return grub_errno; + + int i; + for (i = GRUB_ATA_REG_SECTORS; i <= GRUB_ATA_REG_LBAHIGH; i++) + grub_pata_regset (dev, i, + parms->taskfile.raw[7 + (i - GRUB_ATA_REG_SECTORS)]); + for (i = GRUB_ATA_REG_FEATURES; i <= GRUB_ATA_REG_LBAHIGH; i++) + grub_pata_regset (dev, i, parms->taskfile.raw[i - GRUB_ATA_REG_FEATURES]); + + /* Start command. */ + grub_pata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile.cmd); + + /* Wait for !BSY. */ + if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) + return grub_errno; + + /* Check status. */ + grub_int8_t sts = grub_pata_regget (dev, GRUB_ATA_REG_STATUS); + grub_dprintf ("pata", "status=0x%x\n", sts); + + if (parms->cmdsize) + { + grub_uint8_t irs = grub_pata_regget (dev, GRUB_ATAPI_REG_IREASON); + /* OK if DRQ is asserted and interrupt reason is as expected. */ + if (!((sts & GRUB_ATA_STATUS_DRQ) + && (irs & GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_CMD_OUT)) + return grub_error (GRUB_ERR_READ_ERROR, "ATAPI protocol error"); + /* Write the packet. */ + grub_pata_pio_write (dev, parms->cmd, parms->cmdsize); + } + + /* Transfer data. */ + while (nread < parms->size + && ((sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) + == GRUB_ATA_STATUS_DRQ) + && (!parms->cmdsize + || ((grub_pata_regget (dev, GRUB_ATAPI_REG_IREASON) + & GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_DATA_IN))) + { + unsigned cnt; + if (parms->cmdsize) + { + cnt = grub_pata_regget (dev, GRUB_ATAPI_REG_CNTHIGH) << 8 + | grub_pata_regget (dev, GRUB_ATAPI_REG_CNTLOW); + grub_dprintf("pata", "DRQ count=%u\n", cnt); + + /* Count of last transfer may be uneven. */ + if (! (0 < cnt && cnt <= parms->size - nread + && (! (cnt & 1) || cnt == parms->size - nread))) + return grub_error (GRUB_ERR_READ_ERROR, + "invalid ATAPI transfer count"); + } + else + cnt = GRUB_DISK_SECTOR_SIZE; + if (cnt > parms->size - nread) + cnt = parms->size - nread; + + if (parms->write) + grub_pata_pio_write (dev, (char *) parms->buffer + nread, cnt); + else + grub_pata_pio_read (dev, (char *) parms->buffer + nread, cnt); + + nread += cnt; + } + if (parms->write) + { + /* Check for write error. */ + if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) + return grub_errno; + + if (grub_pata_regget (dev, GRUB_ATA_REG_STATUS) + & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) + return grub_error (GRUB_ERR_WRITE_ERROR, "ATA write error"); + } + parms->size = nread; + + /* Return registers. */ + for (i = GRUB_ATA_REG_ERROR; i <= GRUB_ATA_REG_STATUS; i++) + parms->taskfile.raw[i - GRUB_ATA_REG_FEATURES] = grub_pata_regget (dev, i); + + grub_dprintf ("pata", "status=0x%x, error=0x%x, sectors=0x%x\n", + parms->taskfile.status, + parms->taskfile.error, + parms->taskfile.sectors); + + if (parms->taskfile.status + & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) + return grub_error (GRUB_ERR_READ_ERROR, "PATA passthrough failed"); + + return GRUB_ERR_NONE; +} + +static grub_err_t +check_device (struct grub_pata_device *dev) +{ + grub_pata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4); + grub_pata_wait (); + + /* Try to detect if the port is in use by writing to it, + waiting for a while and reading it again. If the value + was preserved, there is a device connected. */ + grub_pata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A); + grub_pata_wait (); + grub_uint8_t sec = grub_pata_regget (dev, GRUB_ATA_REG_SECTORS); + grub_dprintf ("ata", "sectors=0x%x\n", sec); + if (sec != 0x5A) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no device connected"); + + /* The above test may detect a second (slave) device + connected to a SATA controller which supports only one + (master) device. It is not safe to use the status register + READY bit to check for controller channel existence. Some + ATAPI commands (RESET, DIAGNOSTIC) may clear this bit. */ + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_pata_device_initialize (int port, int device, int addr, int addr2) +{ + struct grub_pata_device *dev; + struct grub_pata_device **devp; + grub_err_t err; + + grub_dprintf ("pata", "detecting device %d,%d (0x%x, 0x%x)\n", + port, device, addr, addr2); + + dev = grub_malloc (sizeof(*dev)); + if (! dev) + return grub_errno; + + /* Setup the device information. */ + dev->port = port; + dev->device = device; + dev->ioaddress = addr + GRUB_MACHINE_PCI_IO_BASE; + dev->ioaddress2 = addr2 + GRUB_MACHINE_PCI_IO_BASE; + dev->next = NULL; + + /* Register the device. */ + for (devp = &grub_pata_devices; *devp; devp = &(*devp)->next); + *devp = dev; + + err = check_device (dev); + if (err) + grub_print_error (); + + return 0; +} + +static int NESTED_FUNC_ATTR +grub_pata_pciinit (grub_pci_device_t dev, + grub_pci_id_t pciid) +{ + static int compat_use[2] = { 0 }; + grub_pci_address_t addr; + grub_uint32_t class; + grub_uint32_t bar1; + grub_uint32_t bar2; + int rega; + int regb; + int i; + static int controller = 0; + int cs5536 = 0; + int nports = 2; + + /* Read class. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + /* AMD CS5536 Southbridge. */ + if (pciid == GRUB_CS5536_PCIID) + { + cs5536 = 1; + nports = 1; + } + + /* Check if this class ID matches that of a PCI IDE Controller. */ + if (!cs5536 && (class >> 16 != 0x0101)) + return 0; + + for (i = 0; i < nports; i++) + { + /* Set to 0 when the channel operated in compatibility mode. */ + int compat; + + /* We don't support non-compatibility mode for CS5536. */ + if (cs5536) + compat = 0; + else + compat = (class >> (8 + 2 * i)) & 1; + + rega = 0; + regb = 0; + + /* If the channel is in compatibility mode, just assign the + default registers. */ + if (compat == 0 && !compat_use[i]) + { + rega = grub_pata_ioaddress[i]; + regb = grub_pata_ioaddress2[i]; + compat_use[i] = 1; + } + else if (compat) + { + /* Read the BARs, which either contain a mmapped IO address + or the IO port address. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES + + sizeof (grub_uint64_t) * i); + bar1 = grub_pci_read (addr); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES + + sizeof (grub_uint64_t) * i + + sizeof (grub_uint32_t)); + bar2 = grub_pci_read (addr); + + /* Check if the BARs describe an IO region. */ + if ((bar1 & 1) && (bar2 & 1)) + { + rega = bar1 & ~3; + regb = bar2 & ~3; + } + } + + grub_dprintf ("pata", + "PCI dev (%d,%d,%d) compat=%d rega=0x%x regb=0x%x\n", + grub_pci_get_bus (dev), grub_pci_get_device (dev), + grub_pci_get_function (dev), compat, rega, regb); + + if (rega && regb) + { + grub_errno = GRUB_ERR_NONE; + grub_pata_device_initialize (controller * 2 + i, 0, rega, regb); + + /* Most errors raised by grub_ata_device_initialize() are harmless. + They just indicate this particular drive is not responding, most + likely because it doesn't exist. We might want to ignore specific + error types here, instead of printing them. */ + if (grub_errno) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + + grub_pata_device_initialize (controller * 2 + i, 1, rega, regb); + + /* Likewise. */ + if (grub_errno) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + } + } + + controller++; + + return 0; +} + +static grub_err_t +grub_pata_initialize (void) +{ + grub_pci_iterate (grub_pata_pciinit); + return 0; +} + +static grub_err_t +grub_pata_open (int id, int devnum, struct grub_ata *ata) +{ + struct grub_pata_device *dev; + struct grub_pata_device *devfnd = 0; + grub_err_t err; + + if (id != GRUB_SCSI_SUBSYSTEM_PATA) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a PATA device"); + + for (dev = grub_pata_devices; dev; dev = dev->next) + { + if (dev->port * 2 + dev->device == devnum) + { + devfnd = dev; + break; + } + } + + grub_dprintf ("pata", "opening PATA dev `ata%d'\n", devnum); + + if (! devfnd) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such PATA device"); + + err = check_device (devfnd); + if (err) + return err; + + ata->data = devfnd; + + return GRUB_ERR_NONE; +} + +static int +grub_pata_iterate (int (*hook) (int id, int bus)) +{ + struct grub_pata_device *dev; + + for (dev = grub_pata_devices; dev; dev = dev->next) + if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device)) + return 1; + + return 0; +} + + +static struct grub_ata_dev grub_pata_dev = + { + .iterate = grub_pata_iterate, + .open = grub_pata_open, + .readwrite = grub_pata_readwrite, + }; + + GRUB_MOD_INIT(ata_pthru) { - /* Register ATA pass through function. */ - grub_disk_ata_pass_through = grub_ata_pass_through; + /* To prevent two drivers operating on the same disks. */ + grub_disk_firmware_is_tainted = 1; + if (grub_disk_firmware_fini) + { + grub_disk_firmware_fini (); + grub_disk_firmware_fini = NULL; + } + + /* ATA initialization. */ + grub_pata_initialize (); + + grub_ata_dev_register (&grub_pata_dev); } GRUB_MOD_FINI(ata_pthru) { - if (grub_disk_ata_pass_through == grub_ata_pass_through) - grub_disk_ata_pass_through = NULL; + grub_ata_dev_unregister (&grub_pata_dev); } diff --git a/disk/scsi.c b/disk/scsi.c index 60192bef5..f0594e7c7 100644 --- a/disk/scsi.c +++ b/disk/scsi.c @@ -30,6 +30,12 @@ static grub_scsi_dev_t grub_scsi_dev_list; +char grub_scsi_names[GRUB_SCSI_NUM_SUBSYSTEMS][5] = { + [GRUB_SCSI_SUBSYSTEM_USBMS] = "usb", + [GRUB_SCSI_SUBSYSTEM_PATA] = "ata", + [GRUB_SCSI_SUBSYSTEM_AHCI] = "ahci" +}; + void grub_scsi_dev_register (grub_scsi_dev_t dev) { @@ -318,9 +324,9 @@ grub_scsi_iterate (int (*hook) (const char *name)) { grub_scsi_dev_t p; - auto int scsi_iterate (int bus, int luns); + auto int scsi_iterate (int id, int bus, int luns); - int scsi_iterate (int bus, int luns) + int scsi_iterate (int id, int bus, int luns) { int i; @@ -329,7 +335,7 @@ grub_scsi_iterate (int (*hook) (const char *name)) { char *sname; int ret; - sname = grub_xasprintf ("%s%d", p->name, bus); + sname = grub_xasprintf ("%s%d", grub_scsi_names[id], bus); if (!sname) return 1; ret = hook (sname); @@ -343,7 +349,7 @@ grub_scsi_iterate (int (*hook) (const char *name)) { char *sname; int ret; - sname = grub_xasprintf ("%s%d%c", p->name, bus, 'a' + i); + sname = grub_xasprintf ("%s%d%c", grub_scsi_names[id], bus, 'a' + i); if (!sname) return 1; ret = hook (sname); @@ -370,6 +376,7 @@ grub_scsi_open (const char *name, grub_disk_t disk) int lun, bus; grub_uint64_t maxtime; const char *nameend; + unsigned id; nameend = name + grub_strlen (name) - 1; /* Try to detect a LUN ('a'-'z'), otherwise just use the first @@ -394,15 +401,25 @@ grub_scsi_open (const char *name, grub_disk_t disk) if (! scsi) return grub_errno; + for (id = 0; id < ARRAY_SIZE (grub_scsi_names); id++) + if (grub_strncmp (grub_scsi_names[id], name, nameend - name) == 0) + break; + + if (id == ARRAY_SIZE (grub_scsi_names)) + { + grub_free (scsi); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a SCSI disk"); + } + for (p = grub_scsi_dev_list; p; p = p->next) { - if (grub_strncmp (p->name, name, nameend - name) != 0) - continue; + if (p->open (id, bus, scsi)) + { + grub_errno = GRUB_ERR_NONE; + continue; + } - if (p->open (bus, scsi)) - continue; - - disk->id = grub_make_scsi_id (p->id, bus, lun); + disk->id = grub_make_scsi_id (id, bus, lun); disk->data = scsi; scsi->dev = p; scsi->lun = lun; @@ -484,7 +501,6 @@ grub_scsi_open (const char *name, grub_disk_t disk) } grub_free (scsi); - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a SCSI disk"); } diff --git a/disk/usbms.c b/disk/usbms.c index 225761e0f..0ff2e6235 100644 --- a/disk/usbms.c +++ b/disk/usbms.c @@ -205,7 +205,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) static int -grub_usbms_iterate (int (*hook) (int bus, int luns)) +grub_usbms_iterate (int (*hook) (int id, int bus, int luns)) { unsigned i; @@ -214,7 +214,7 @@ grub_usbms_iterate (int (*hook) (int bus, int luns)) for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++) if (grub_usbms_devices[i]) { - if (hook (i, grub_usbms_devices[i]->luns)) + if (hook (GRUB_SCSI_SUBSYSTEM_USBMS, i, grub_usbms_devices[i]->luns)) return 1; } @@ -384,8 +384,12 @@ grub_usbms_write (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, } static grub_err_t -grub_usbms_open (int devnum, struct grub_scsi *scsi) +grub_usbms_open (int id, int devnum, struct grub_scsi *scsi) { + if (id != GRUB_SCSI_SUBSYSTEM_USBMS) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + "not USB Mass Storage device"); + grub_usb_poll_devices (); if (!grub_usbms_devices[devnum]) @@ -400,8 +404,6 @@ grub_usbms_open (int devnum, struct grub_scsi *scsi) static struct grub_scsi_dev grub_usbms_dev = { - .name = "usb", - .id = GRUB_SCSI_SUBSYSTEM_USBMS, .iterate = grub_usbms_iterate, .open = grub_usbms_open, .read = grub_usbms_read, diff --git a/include/grub/ata.h b/include/grub/ata.h index 9e3aaf0e6..b1c6ead26 100644 --- a/include/grub/ata.h +++ b/include/grub/ata.h @@ -97,21 +97,64 @@ enum grub_ata_timeout_milliseconds GRUB_ATA_TOUT_DATA = 10000 /* 10s DATA I/O timeout. */ }; -struct grub_ata_device +typedef union { - /* IDE port to use. */ - int port; + grub_uint8_t raw[11]; + struct + { + union + { + grub_uint8_t features; + grub_uint8_t error; + }; + union + { + grub_uint8_t sectors; + grub_uint8_t atapi_ireason; + }; + union + { + grub_uint8_t lba_low; + grub_uint8_t sectnum; + }; + union + { + grub_uint8_t lba_mid; + grub_uint8_t cyllsb; + grub_uint8_t atapi_cntlow; + }; + union + { + grub_uint8_t lba_high; + grub_uint8_t cylmsb; + grub_uint8_t atapi_cnthigh; + }; + grub_uint8_t disk; + union + { + grub_uint8_t cmd; + grub_uint8_t status; + }; + grub_uint8_t sectors48; + grub_uint8_t lba48_low; + grub_uint8_t lba48_mid; + grub_uint8_t lba48_high; + }; +} grub_ata_regs_t; - /* IO addresses on which the registers for this device can be - found. */ - grub_port_t ioaddress; - grub_port_t ioaddress2; - - /* Two devices can be connected to a single cable. Use this field - to select device 0 (commonly known as "master") or device 1 - (commonly known as "slave"). */ - int device; +/* ATA pass through parameters and function. */ +struct grub_disk_ata_pass_through_parms +{ + grub_ata_regs_t taskfile; + void * buffer; + grub_size_t size; + int write; + void *cmd; + int cmdsize; +}; +struct grub_ata +{ /* Addressing methods available for accessing this device. If CHS is only available, use that. Otherwise use LBA, except for the high sectors. In that case use LBA48. */ @@ -128,47 +171,36 @@ struct grub_ata_device /* Set to 0 for ATA, set to 1 for ATAPI. */ int atapi; - struct grub_ata_device *next; + void *data; + + struct grub_ata_dev *dev; }; -grub_err_t EXPORT_FUNC(grub_ata_wait_not_busy) (struct grub_ata_device *dev, - int milliseconds); -grub_err_t EXPORT_FUNC(grub_ata_wait_drq) (struct grub_ata_device *dev, - int rw, int milliseconds); -void EXPORT_FUNC(grub_ata_pio_read) (struct grub_ata_device *dev, - char *buf, grub_size_t size); +typedef struct grub_ata *grub_ata_t; -static inline void -grub_ata_regset (struct grub_ata_device *dev, int reg, int val) +struct grub_ata_dev { - grub_outb (val, dev->ioaddress + reg); -} + /* Call HOOK with each device name, until HOOK returns non-zero. */ + int (*iterate) (int (*hook) (int id, int bus)); -static inline grub_uint8_t -grub_ata_regget (struct grub_ata_device *dev, int reg) -{ - return grub_inb (dev->ioaddress + reg); -} + /* Open the device named NAME, and set up SCSI. */ + grub_err_t (*open) (int id, int bus, struct grub_ata *scsi); -static inline void -grub_ata_regset2 (struct grub_ata_device *dev, int reg, int val) -{ - grub_outb (val, dev->ioaddress2 + reg); -} + /* Close the scsi device SCSI. */ + void (*close) (struct grub_ata *ata); -static inline grub_uint8_t -grub_ata_regget2 (struct grub_ata_device *dev, int reg) -{ - return grub_inb (dev->ioaddress2 + reg); -} + /* Read SIZE bytes from the device SCSI into BUF after sending the + command CMD of size CMDSIZE. */ + grub_err_t (*readwrite) (struct grub_ata *ata, + struct grub_disk_ata_pass_through_parms *parms); -static inline grub_err_t -grub_ata_check_ready (struct grub_ata_device *dev) -{ - if (grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY) - return grub_ata_wait_not_busy (dev, GRUB_ATA_TOUT_STD); + /* The next scsi device. */ + struct grub_ata_dev *next; +}; - return GRUB_ERR_NONE; -} +typedef struct grub_ata_dev *grub_ata_dev_t; + +void grub_ata_dev_register (grub_ata_dev_t dev); +void grub_ata_dev_unregister (grub_ata_dev_t dev); #endif /* ! GRUB_ATA_HEADER */ diff --git a/include/grub/disk.h b/include/grub/disk.h index e7f807e0e..ac3fb6497 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -165,16 +165,5 @@ grub_uint64_t EXPORT_FUNC(grub_disk_get_size) (grub_disk_t disk); extern void (* EXPORT_VAR(grub_disk_firmware_fini)) (void); extern int EXPORT_VAR(grub_disk_firmware_is_tainted); - -/* ATA pass through parameters and function. */ -struct grub_disk_ata_pass_through_parms -{ - grub_uint8_t taskfile[8]; - void * buffer; - int size; -}; - -extern grub_err_t (* EXPORT_VAR(grub_disk_ata_pass_through)) (grub_disk_t, - struct grub_disk_ata_pass_through_parms *); - + #endif /* ! GRUB_DISK_HEADER */ diff --git a/include/grub/scsi.h b/include/grub/scsi.h index 289cd8e4a..081189fb0 100644 --- a/include/grub/scsi.h +++ b/include/grub/scsi.h @@ -29,10 +29,13 @@ struct grub_scsi; enum { GRUB_SCSI_SUBSYSTEM_USBMS, - GRUB_SCSI_SUBSYSTEM_ATAPI, - GRUB_SCSI_SUBSYSTEM_AHCI + GRUB_SCSI_SUBSYSTEM_PATA, + GRUB_SCSI_SUBSYSTEM_AHCI, + GRUB_SCSI_NUM_SUBSYSTEMS }; +extern char grub_scsi_names[GRUB_SCSI_NUM_SUBSYSTEMS][5]; + #define GRUB_SCSI_ID_SUBSYSTEM_SHIFT 24 #define GRUB_SCSI_ID_BUS_SHIFT 8 #define GRUB_SCSI_ID_LUN_SHIFT 0 @@ -46,16 +49,11 @@ grub_make_scsi_id (int subsystem, int bus, int lun) struct grub_scsi_dev { - /* The device name. */ - const char *name; - - grub_uint8_t id; - /* Call HOOK with each device name, until HOOK returns non-zero. */ - int (*iterate) (int (*hook) (int bus, int luns)); + int (*iterate) (int (*hook) (int id, int bus, int luns)); /* Open the device named NAME, and set up SCSI. */ - grub_err_t (*open) (int bus, struct grub_scsi *scsi); + grub_err_t (*open) (int id, int bus, struct grub_scsi *scsi); /* Close the scsi device SCSI. */ void (*close) (struct grub_scsi *scsi); diff --git a/kern/disk.c b/kern/disk.c index ccd5f200f..84c48e65c 100644 --- a/kern/disk.c +++ b/kern/disk.c @@ -46,10 +46,6 @@ static struct grub_disk_cache grub_disk_cache_table[GRUB_DISK_CACHE_NUM]; void (*grub_disk_firmware_fini) (void); int grub_disk_firmware_is_tainted; -grub_err_t (* grub_disk_ata_pass_through) (grub_disk_t, - struct grub_disk_ata_pass_through_parms *); - - #if 0 static unsigned long grub_disk_cache_hits; static unsigned long grub_disk_cache_misses; From faec81d97dd6b3cb58b631f4fcf426786f1db54f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Dec 2010 16:54:33 +0100 Subject: [PATCH 110/406] Add missing buffer specifications --- grub-core/disk/ata.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 04b81cd27..9f62546e1 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -72,6 +72,8 @@ grub_atapi_identify (struct grub_ata *dev) grub_memset (&parms, 0, sizeof (parms)); parms.taskfile.disk = 0; parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE; + parms.size = GRUB_DISK_SECTOR_SIZE; + parms.buffer = info; err = dev->dev->readwrite (dev, &parms); if (err) @@ -105,6 +107,7 @@ grub_ata_identify (struct grub_ata *dev) info16 = (grub_uint16_t *) info; grub_memset (&parms, 0, sizeof (parms)); parms.buffer = info; + parms.size = GRUB_DISK_SECTOR_SIZE; parms.taskfile.disk = 0; parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_DEVICE; From 22a7cc9a6f5e61de79b34f09c97a71a12dd370a2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Dec 2010 17:09:56 +0100 Subject: [PATCH 111/406] fix 3rd argument to scsi_iterate --- grub-core/disk/ata.c | 2 +- grub-core/disk/scsi.c | 4 ++-- grub-core/disk/usbms.c | 2 +- include/grub/scsi.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 9f62546e1..6f7f44227 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -508,7 +508,7 @@ grub_atapi_open (int id, int bus, struct grub_scsi *scsi) } static int -grub_atapi_iterate (int (*hook_in) (int id, int bus, int luns)) +grub_atapi_iterate (int NESTED_FUNC_ATTR (*hook_in) (int id, int bus, int luns)) { auto int hook (int id, int bus); int hook (int id, int bus) diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index b989a98ad..015e5dce6 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -324,9 +324,9 @@ grub_scsi_iterate (int (*hook) (const char *name)) { grub_scsi_dev_t p; - auto int scsi_iterate (int id, int bus, int luns); + auto int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns); - int scsi_iterate (int id, int bus, int luns) + int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns) { int i; diff --git a/grub-core/disk/usbms.c b/grub-core/disk/usbms.c index 4e1af7be3..8041c6c95 100644 --- a/grub-core/disk/usbms.c +++ b/grub-core/disk/usbms.c @@ -205,7 +205,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) static int -grub_usbms_iterate (int (*hook) (int id, int bus, int luns)) +grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns)) { unsigned i; diff --git a/include/grub/scsi.h b/include/grub/scsi.h index 3deb18f1b..5b6ccc9f4 100644 --- a/include/grub/scsi.h +++ b/include/grub/scsi.h @@ -50,7 +50,7 @@ grub_make_scsi_id (int subsystem, int bus, int lun) struct grub_scsi_dev { /* Call HOOK with each device name, until HOOK returns non-zero. */ - int (*iterate) (int (*hook) (int id, int bus, int luns)); + int (*iterate) (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns)); /* Open the device named NAME, and set up SCSI. */ grub_err_t (*open) (int id, int bus, struct grub_scsi *scsi); From 8f5ac9e57050652378a9d54d9082ab331a775946 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Dec 2010 17:10:41 +0100 Subject: [PATCH 112/406] fix ATAPI support --- grub-core/disk/ata.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 6f7f44227..5015f8507 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -113,13 +113,12 @@ grub_ata_identify (struct grub_ata *dev) parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_DEVICE; err = dev->dev->readwrite (dev, &parms); - if (err) - return err; - if (parms.size != GRUB_DISK_SECTOR_SIZE) + if (err || parms.size != GRUB_DISK_SECTOR_SIZE) { grub_uint8_t sts = parms.taskfile.status; grub_free (info); + grub_errno = GRUB_ERR_NONE; if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR && (parms.taskfile.error & 0x04 /* ABRT */)) @@ -503,6 +502,7 @@ grub_atapi_open (int id, int bus, struct grub_scsi *scsi) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device"); scsi->data = ata; + scsi->luns = 1; return GRUB_ERR_NONE; } From ee2b985ef68f5522796057ef6d3055ad7d6dc5a1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Dec 2010 17:11:21 +0100 Subject: [PATCH 113/406] rearrange wait_not_busy --- grub-core/disk/pata.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index b6edf78d6..a24237a83 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -182,17 +182,18 @@ grub_pata_readwrite (struct grub_ata *disk, /* Start command. */ grub_pata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile.cmd); - /* Wait for !BSY. */ - if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) - return grub_errno; - /* Check status. */ grub_int8_t sts = grub_pata_regget (dev, GRUB_ATA_REG_STATUS); grub_dprintf ("pata", "status=0x%x\n", sts); if (parms->cmdsize) { - grub_uint8_t irs = grub_pata_regget (dev, GRUB_ATAPI_REG_IREASON); + grub_uint8_t irs; + /* Wait for !BSY. */ + if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) + return grub_errno; + + irs = grub_pata_regget (dev, GRUB_ATAPI_REG_IREASON); /* OK if DRQ is asserted and interrupt reason is as expected. */ if (!((sts & GRUB_ATA_STATUS_DRQ) && (irs & GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_CMD_OUT)) @@ -210,6 +211,11 @@ grub_pata_readwrite (struct grub_ata *disk, & GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_DATA_IN))) { unsigned cnt; + + /* Wait for !BSY. */ + if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) + return grub_errno; + if (parms->cmdsize) { cnt = grub_pata_regget (dev, GRUB_ATAPI_REG_CNTHIGH) << 8 @@ -246,6 +252,10 @@ grub_pata_readwrite (struct grub_ata *disk, } parms->size = nread; + /* Wait for !BSY. */ + if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) + return grub_errno; + /* Return registers. */ for (i = GRUB_ATA_REG_ERROR; i <= GRUB_ATA_REG_STATUS; i++) parms->taskfile.raw[i - GRUB_ATA_REG_FEATURES] = grub_pata_regget (dev, i); From 908a8fc37a51aea0dd22d53494772456a210b900 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Dec 2010 19:48:55 +0100 Subject: [PATCH 114/406] Fix several AHCI problems --- grub-core/disk/ahci.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 946db82e1..1e28b3dc5 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -56,10 +56,12 @@ struct grub_ahci_hba_port grub_uint32_t intstatus; grub_uint32_t inten; grub_uint32_t command; - grub_uint32_t unused1[6]; + grub_uint32_t unused1[3]; + grub_uint32_t status; + grub_uint32_t unused2[2]; grub_uint32_t sata_active; grub_uint32_t command_issue; - grub_uint32_t unused2[17]; + grub_uint32_t unused3[17]; }; struct grub_ahci_hba @@ -195,6 +197,10 @@ grub_ahci_pciinit (grub_pci_device_t dev, if (!(hba->ports_implemented & (1 << i))) continue; + /* FIXME: support hotplugging. */ + if (!hba->ports[i].status) + continue; + command_list = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head)); if (!command_list) @@ -333,8 +339,11 @@ grub_ahci_readwrite (grub_ata_t disk, parms->cmdsize); dev->command_table[0].cfis[0] = GRUB_AHCI_FIS_REG_H2D; + dev->command_table[0].cfis[1] = 0x80; for (i = 0; i < sizeof (parms->taskfile.raw); i++) - dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i]; + dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i]; + + dev->command_table[0].cfis[7] |= (parms->cmdsize ? 0 : 0xE0); dev->command_table[0].prdt[0].data_base = grub_dma_get_phys (bufc); dev->command_table[0].prdt[0].unused = 0; @@ -345,12 +354,12 @@ grub_ahci_readwrite (grub_ata_t disk, grub_memcpy ((char *) grub_dma_get_virt (bufc), parms->buffer, parms->size); grub_dprintf ("ahci", "AHCI command schedulded\n"); - dev->hba->ports[dev->port].inten = (1 << 5); - dev->hba->ports[dev->port].intstatus = (1 << 5); + dev->hba->ports[dev->port].inten = (1 << 2) | (1 << 5); + dev->hba->ports[dev->port].intstatus = (1 << 2) | (1 << 5); dev->hba->ports[dev->port].command_issue |= 1; dev->hba->ports[dev->port].command |= 1; - endtime = grub_get_time_ms () + 1000; + endtime = grub_get_time_ms () + 1000; while (!(dev->hba->ports[dev->port].intstatus & (1 << 5))) if (grub_get_time_ms () > endtime) { @@ -362,6 +371,7 @@ grub_ahci_readwrite (grub_ata_t disk, grub_dprintf ("ahci", "AHCI command completed succesfully\n"); dev->hba->ports[dev->port].command &= ~1; + dev->hba->ports[dev->port].command_issue &= ~1; if (!parms->write) grub_memcpy (parms->buffer, (char *) grub_dma_get_virt (bufc), parms->size); @@ -379,10 +389,8 @@ grub_ahci_open (int id, int devnum, struct grub_ata *ata) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an AHCI device"); FOR_LIST_ELEMENTS(dev, grub_ahci_devices) - { - if (dev->num == devnum) - break; - } + if (dev->num == devnum) + break; if (! dev) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such AHCI device"); From 51f7e1acb7355d15d83ff3f916cc80cc1827b96b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 02:53:20 +0100 Subject: [PATCH 115/406] DMA ATA commands support --- grub-core/disk/ahci.c | 1 + grub-core/disk/ata.c | 28 +++++++++++++++++++++++----- grub-core/disk/pata.c | 1 + include/grub/ata.h | 8 ++++++++ 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 1e28b3dc5..4b5d195f2 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -398,6 +398,7 @@ grub_ahci_open (int id, int devnum, struct grub_ata *ata) grub_dprintf ("ahci", "opening AHCI dev `ahci%d'\n", dev->num); ata->data = dev; + ata->dma = 0; return GRUB_ERR_NONE; } diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 5015f8507..b33abf90d 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -255,8 +255,16 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, if (addressing == GRUB_ATA_LBA48 && ((sector + size) >> 28) != 0) { batch = 65536; - cmd = GRUB_ATA_CMD_READ_SECTORS_EXT; - cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_EXT; + if (ata->dma) + { + cmd = GRUB_ATA_CMD_READ_SECTORS_DMA_EXT; + cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_DMA_EXT; + } + else + { + cmd = GRUB_ATA_CMD_READ_SECTORS_EXT; + cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_EXT; + } } else { @@ -266,9 +274,17 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, batch = 256; else batch = 1; - cmd = GRUB_ATA_CMD_READ_SECTORS; - cmd_write = GRUB_ATA_CMD_WRITE_SECTORS; - } + if (ata->dma) + { + cmd = GRUB_ATA_CMD_READ_SECTORS_DMA; + cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_DMA; + } + else + { + cmd = GRUB_ATA_CMD_READ_SECTORS; + cmd_write = GRUB_ATA_CMD_WRITE_SECTORS; + } + } grub_size_t nsectors = 0; while (nsectors < size) @@ -285,6 +301,8 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, parms.taskfile.cmd = (! rw ? cmd : cmd_write); parms.buffer = buf; parms.size = batch * GRUB_DISK_SECTOR_SIZE; + if (ata->dma) + parms.dma = 1; err = ata->dev->readwrite (ata, &parms); if (err) diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index a24237a83..186caf6a2 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -474,6 +474,7 @@ grub_pata_open (int id, int devnum, struct grub_ata *ata) return err; ata->data = devfnd; + ata->dma = 0; return GRUB_ERR_NONE; } diff --git a/include/grub/ata.h b/include/grub/ata.h index b1c6ead26..bea74c180 100644 --- a/include/grub/ata.h +++ b/include/grub/ata.h @@ -82,6 +82,9 @@ enum grub_ata_commands GRUB_ATA_CMD_PACKET = 0xa0, GRUB_ATA_CMD_READ_SECTORS = 0x20, GRUB_ATA_CMD_READ_SECTORS_EXT = 0x24, + GRUB_ATA_CMD_READ_SECTORS_DMA = 0xc8, + GRUB_ATA_CMD_READ_SECTORS_DMA_EXT = 0x25, + GRUB_ATA_CMD_SECURITY_FREEZE_LOCK = 0xf5, GRUB_ATA_CMD_SET_FEATURES = 0xef, GRUB_ATA_CMD_SLEEP = 0xe6, @@ -89,6 +92,8 @@ enum grub_ata_commands GRUB_ATA_CMD_STANDBY_IMMEDIATE = 0xe0, GRUB_ATA_CMD_WRITE_SECTORS = 0x30, GRUB_ATA_CMD_WRITE_SECTORS_EXT = 0x34, + GRUB_ATA_CMD_WRITE_SECTORS_DMA_EXT = 0x35, + GRUB_ATA_CMD_WRITE_SECTORS_DMA = 0xca, }; enum grub_ata_timeout_milliseconds @@ -151,6 +156,7 @@ struct grub_disk_ata_pass_through_parms int write; void *cmd; int cmdsize; + int dma; }; struct grub_ata @@ -171,6 +177,8 @@ struct grub_ata /* Set to 0 for ATA, set to 1 for ATAPI. */ int atapi; + int dma; + void *data; struct grub_ata_dev *dev; From 060d0c7ac2fbf763cc07efcb498c04c03b4cf197 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 03:06:07 +0100 Subject: [PATCH 116/406] working AHCI (at last) --- grub-core/disk/ahci.c | 182 +++++++++++++++++++++++++++++++++++------- 1 file changed, 152 insertions(+), 30 deletions(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 4b5d195f2..4d5ee692c 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -44,8 +44,8 @@ struct grub_ahci_prdt_entry struct grub_ahci_cmd_table { grub_uint8_t cfis[0x40]; - grub_uint8_t command[16]; - grub_uint32_t reserved[0xc]; + grub_uint8_t command[0x10]; + grub_uint8_t reserved[0x30]; struct grub_ahci_prdt_entry prdt[1]; }; @@ -56,14 +56,27 @@ struct grub_ahci_hba_port grub_uint32_t intstatus; grub_uint32_t inten; grub_uint32_t command; - grub_uint32_t unused1[3]; + grub_uint32_t unused1; + grub_uint32_t task_file_data; + grub_uint32_t sig; grub_uint32_t status; - grub_uint32_t unused2[2]; + grub_uint32_t unused2; + grub_uint32_t sata_error; grub_uint32_t sata_active; grub_uint32_t command_issue; - grub_uint32_t unused3[17]; + grub_uint32_t unused3; + grub_uint32_t fbs; + grub_uint32_t unused4[15]; }; +enum grub_ahci_hba_port_command + { + GRUB_AHCI_HBA_PORT_CMD_ST = 0x01, + GRUB_AHCI_HBA_PORT_CMD_FRE = 0x10, + GRUB_AHCI_HBA_PORT_CMD_CR = 0x8000, + GRUB_AHCI_HBA_PORT_CMD_FR = 0x4000, + }; + struct grub_ahci_hba { grub_uint32_t cap; @@ -76,6 +89,11 @@ struct grub_ahci_hba struct grub_ahci_hba_port ports[32]; }; +struct grub_ahci_received_fis +{ + char raw[4096]; +}; + enum { GRUB_AHCI_HBA_CAP_NPORTS_MASK = 0x1f @@ -83,6 +101,7 @@ enum enum { + GRUB_AHCI_HBA_GLOBAL_CONTROL_RESET = 0x00000001, GRUB_AHCI_HBA_GLOBAL_CONTROL_INTR_EN = 0x00000002, GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN = 0x80000000, }; @@ -106,8 +125,14 @@ struct grub_ahci_device volatile struct grub_ahci_cmd_head *command_list; struct grub_pci_dma_chunk *command_table_chunk; volatile struct grub_ahci_cmd_table *command_table; + struct grub_pci_dma_chunk *rfis; }; +static grub_err_t +grub_ahci_readwrite_real (struct grub_ahci_device *dev, + struct grub_disk_ata_pass_through_parms *parms); + + enum { GRUB_AHCI_CONFIG_READ = 0, @@ -160,10 +185,6 @@ grub_ahci_pciinit (grub_pci_device_t dev, hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK, sizeof (hba)); - hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; - - nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1; - if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED)) { grub_uint64_t endtime; @@ -186,6 +207,11 @@ grub_ahci_pciinit (grub_pci_device_t dev, } else grub_dprintf ("ahci", "AHCI is already in OS mode\n"); + + hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; + + nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1; + grub_dprintf ("ahci", "%d AHCI ports\n", nports); for (i = 0; i < nports; i++) @@ -197,8 +223,9 @@ grub_ahci_pciinit (grub_pci_device_t dev, if (!(hba->ports_implemented & (1 << i))) continue; + grub_dprintf ("ahci", "status %d:%x\n", i, hba->ports[i].status); /* FIXME: support hotplugging. */ - if (!hba->ports[i].status) + if ((hba->ports[i].status & 0xf) != 0x3) continue; command_list = grub_memalign_dma32 (1024, @@ -224,6 +251,26 @@ grub_ahci_pciinit (grub_pci_device_t dev, grub_dprintf ("ahci", "found device ahci%d (port %d)\n", numdevs, i); + hba->ports[i].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + while ((hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_FR)); + hba->ports[i].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + while ((hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + + hba->ports[i].fbs = 2; + + adev->rfis = grub_memalign_dma32 (4096, + sizeof (struct grub_ahci_received_fis)); + grub_memset ((char *) grub_dma_get_virt (adev->rfis), 0, + sizeof (struct grub_ahci_received_fis)); + hba->ports[i].fis_base = grub_dma_get_phys (adev->rfis); + hba->ports[i].command |= GRUB_AHCI_HBA_PORT_CMD_FRE; + while (!(hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_FR)); + hba->ports[i].command |= GRUB_AHCI_HBA_PORT_CMD_ST; + while (!(hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + + hba->ports[i].command = (hba->ports[i].command & 0x0fffffff) + | (1 << 28) | 2 | 4; + adev->hba = hba; adev->port = i; adev->num = numdevs++; @@ -299,13 +346,26 @@ static const int register_map[11] = { 3 /* Features */, 10 /* LBA48 high */ }; static grub_err_t -grub_ahci_readwrite (grub_ata_t disk, - struct grub_disk_ata_pass_through_parms *parms) +grub_ahci_readwrite_real (struct grub_ahci_device *dev, + struct grub_disk_ata_pass_through_parms *parms) { - struct grub_ahci_device *dev = (struct grub_ahci_device *) disk->data; struct grub_pci_dma_chunk *bufc; grub_uint64_t endtime; unsigned i; + grub_err_t err = GRUB_ERR_NONE; + + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); + + if ((dev->hba->ports[dev->port].task_file_data & 0x80)) + { + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST; + while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + } + + dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error; grub_dprintf("ahci", "grub_ahci_read (size=%llu, cmdsize = %llu)\n", (unsigned long long) parms->size, @@ -319,14 +379,19 @@ grub_ahci_readwrite (grub_ata_t disk, bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1)); + dev->hba->ports[dev->port].command |= 8; + + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); /* FIXME: support port multipliers. */ dev->command_list[0].config - = (4 << GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT) - | GRUB_AHCI_CONFIG_CLEAR_R_OK + = (5 << GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT) + // | GRUB_AHCI_CONFIG_CLEAR_R_OK | (0 << GRUB_AHCI_CONFIG_PMP_SHIFT) | (1 << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT) | (parms->cmdsize ? GRUB_AHCI_CONFIG_ATAPI : 0) - | (parms->write ? GRUB_AHCI_CONFIG_WRITE : GRUB_AHCI_CONFIG_READ); + | (parms->write ? GRUB_AHCI_CONFIG_WRITE : GRUB_AHCI_CONFIG_READ) + | (parms->taskfile.cmd == 8 ? (1 << 8) : 0); dev->command_list[0].transfered = 0; dev->command_list[0].command_table_base = grub_dma_get_phys (dev->command_table_chunk); @@ -344,40 +409,97 @@ grub_ahci_readwrite (grub_ata_t disk, dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i]; dev->command_table[0].cfis[7] |= (parms->cmdsize ? 0 : 0xE0); + grub_dprintf ("ahci", "cfis: %02x %02x %02x %02x %02x %02x %02x %02x\n", + dev->command_table[0].cfis[0], dev->command_table[0].cfis[1], + dev->command_table[0].cfis[2], dev->command_table[0].cfis[3], + dev->command_table[0].cfis[4], dev->command_table[0].cfis[5], + dev->command_table[0].cfis[6], dev->command_table[0].cfis[7]); + grub_dprintf ("ahci", "cfis: %02x %02x %02x %02x %02x %02x %02x %02x\n", + dev->command_table[0].cfis[8], dev->command_table[0].cfis[9], + dev->command_table[0].cfis[10], dev->command_table[0].cfis[11], + dev->command_table[0].cfis[12], dev->command_table[0].cfis[13], + dev->command_table[0].cfis[14], dev->command_table[0].cfis[15]); dev->command_table[0].prdt[0].data_base = grub_dma_get_phys (bufc); dev->command_table[0].prdt[0].unused = 0; dev->command_table[0].prdt[0].size = (parms->size + (parms->size & 1) - 1) | GRUB_AHCI_INTERRUPT_ON_COMPLETE; + grub_dprintf ("ahci", "PRDT = %" PRIxGRUB_UINT64_T ", %x, %x (%x)\n", + dev->command_table[0].prdt[0].data_base, + dev->command_table[0].prdt[0].unused, + dev->command_table[0].prdt[0].size, + (char *) &dev->command_table[0].prdt[0] + - (char *) &dev->command_table[0]); + if (parms->write) grub_memcpy ((char *) grub_dma_get_virt (bufc), parms->buffer, parms->size); grub_dprintf ("ahci", "AHCI command schedulded\n"); - dev->hba->ports[dev->port].inten = (1 << 2) | (1 << 5); - dev->hba->ports[dev->port].intstatus = (1 << 2) | (1 << 5); + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); + dev->hba->ports[dev->port].inten = 0xffffffff;//(1 << 2) | (1 << 5); + dev->hba->ports[dev->port].intstatus = 0xffffffff;//(1 << 2) | (1 << 5); + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); dev->hba->ports[dev->port].command_issue |= 1; - dev->hba->ports[dev->port].command |= 1; + grub_dprintf ("ahci", "AHCI sig = %x\n", dev->hba->ports[dev->port].sig); + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); endtime = grub_get_time_ms () + 1000; - while (!(dev->hba->ports[dev->port].intstatus & (1 << 5))) + while ((dev->hba->ports[dev->port].command_issue & 1)) if (grub_get_time_ms () > endtime) { - grub_dprintf ("ahci", "AHCI timeout\n"); - dev->hba->ports[dev->port].command &= ~1; - /* FIXME: free resources. */ - return grub_error (GRUB_ERR_IO, "AHCI transfer timeouted"); + grub_dprintf ("ahci", "AHCI status <%x %x %x>\n", + dev->hba->ports[dev->port].command_issue, + dev->hba->ports[dev->port].intstatus, + dev->hba->ports[dev->port].task_file_data); + err = grub_error (GRUB_ERR_IO, "AHCI transfer timeouted"); + break; } - grub_dprintf ("ahci", "AHCI command completed succesfully\n"); - dev->hba->ports[dev->port].command &= ~1; - dev->hba->ports[dev->port].command_issue &= ~1; + grub_dprintf ("ahci", "AHCI command completed <%x %x %x %x %x, %x %x>\n", + dev->hba->ports[dev->port].command_issue, + dev->hba->ports[dev->port].intstatus, + dev->hba->ports[dev->port].task_file_data, + dev->command_list[0].transfered, + dev->hba->ports[dev->port].sata_error, + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x00], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x18]); + grub_dprintf ("ahci", + "last PIO FIS %08x %08x %08x %08x %08x %08x %08x %08x\n", + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x08], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x09], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0a], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0b], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0c], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0d], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0e], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0f]); + grub_dprintf ("ahci", + "last REG FIS %08x %08x %08x %08x %08x %08x %08x %08x\n", + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x10], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x11], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x12], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x13], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x14], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x15], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x16], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x17]); if (!parms->write) grub_memcpy (parms->buffer, (char *) grub_dma_get_virt (bufc), parms->size); grub_dma_free (bufc); - return GRUB_ERR_NONE; + return err; +} + +static grub_err_t +grub_ahci_readwrite (grub_ata_t disk, + struct grub_disk_ata_pass_through_parms *parms) +{ + return grub_ahci_readwrite_real (disk->data, parms); } static grub_err_t @@ -415,8 +537,8 @@ static struct grub_ata_dev grub_ahci_dev = GRUB_MOD_INIT(ahci) { /* To prevent two drivers operating on the same disks. */ - // grub_disk_firmware_is_tainted = 1; - if (0 && grub_disk_firmware_fini) + grub_disk_firmware_is_tainted = 1; + if (grub_disk_firmware_fini) { grub_disk_firmware_fini (); grub_disk_firmware_fini = NULL; From 188ac234bd37cd6c0fbf649d1f09cb1a0f114f5e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 03:12:49 +0100 Subject: [PATCH 117/406] use DMA for AHCI commands --- grub-core/disk/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 4d5ee692c..d9b95df37 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -520,7 +520,7 @@ grub_ahci_open (int id, int devnum, struct grub_ata *ata) grub_dprintf ("ahci", "opening AHCI dev `ahci%d'\n", dev->num); ata->data = dev; - ata->dma = 0; + ata->dma = 1; return GRUB_ERR_NONE; } From a934071d76d66b4b1a36ec73240249363392351f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 03:22:12 +0100 Subject: [PATCH 118/406] Remove unused pata ioaddress2 --- grub-core/disk/pata.c | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index 186caf6a2..940a9a5f0 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -29,8 +29,6 @@ /* At the moment, only two IDE ports are supported. */ static const grub_port_t grub_pata_ioaddress[] = { GRUB_ATA_CH0_PORT1, GRUB_ATA_CH1_PORT1 }; -static const grub_port_t grub_pata_ioaddress2[] = { GRUB_ATA_CH0_PORT2, - GRUB_ATA_CH1_PORT2 }; struct grub_pata_device { @@ -40,7 +38,6 @@ struct grub_pata_device /* IO addresses on which the registers for this device can be found. */ grub_port_t ioaddress; - grub_port_t ioaddress2; /* Two devices can be connected to a single cable. Use this field to select device 0 (commonly known as "master") or device 1 @@ -64,18 +61,6 @@ grub_pata_regget (struct grub_pata_device *dev, int reg) return grub_inb (dev->ioaddress + reg); } -static inline void -grub_pata_regset2 (struct grub_pata_device *dev, int reg, int val) -{ - grub_outb (val, dev->ioaddress2 + reg); -} - -static inline grub_uint8_t -grub_pata_regget2 (struct grub_pata_device *dev, int reg) -{ - return grub_inb (dev->ioaddress2 + reg); -} - /* Wait for !BSY. */ static grub_err_t grub_pata_wait_not_busy (struct grub_pata_device *dev, int milliseconds) @@ -298,14 +283,14 @@ check_device (struct grub_pata_device *dev) } static grub_err_t -grub_pata_device_initialize (int port, int device, int addr, int addr2) +grub_pata_device_initialize (int port, int device, int addr) { struct grub_pata_device *dev; struct grub_pata_device **devp; grub_err_t err; - grub_dprintf ("pata", "detecting device %d,%d (0x%x, 0x%x)\n", - port, device, addr, addr2); + grub_dprintf ("pata", "detecting device %d,%d (0x%x)\n", + port, device, addr); dev = grub_malloc (sizeof(*dev)); if (! dev) @@ -315,7 +300,6 @@ grub_pata_device_initialize (int port, int device, int addr, int addr2) dev->port = port; dev->device = device; dev->ioaddress = addr + GRUB_MACHINE_PCI_IO_BASE; - dev->ioaddress2 = addr2 + GRUB_MACHINE_PCI_IO_BASE; dev->next = NULL; /* Register the device. */ @@ -339,7 +323,6 @@ grub_pata_pciinit (grub_pci_device_t dev, grub_uint32_t bar1; grub_uint32_t bar2; int rega; - int regb; int i; static int controller = 0; int cs5536 = 0; @@ -372,14 +355,12 @@ grub_pata_pciinit (grub_pci_device_t dev, compat = (class >> (8 + 2 * i)) & 1; rega = 0; - regb = 0; /* If the channel is in compatibility mode, just assign the default registers. */ if (compat == 0 && !compat_use[i]) { rega = grub_pata_ioaddress[i]; - regb = grub_pata_ioaddress2[i]; compat_use[i] = 1; } else if (compat) @@ -398,19 +379,18 @@ grub_pata_pciinit (grub_pci_device_t dev, if ((bar1 & 1) && (bar2 & 1)) { rega = bar1 & ~3; - regb = bar2 & ~3; } } grub_dprintf ("pata", - "PCI dev (%d,%d,%d) compat=%d rega=0x%x regb=0x%x\n", + "PCI dev (%d,%d,%d) compat=%d rega=0x%x\n", grub_pci_get_bus (dev), grub_pci_get_device (dev), - grub_pci_get_function (dev), compat, rega, regb); + grub_pci_get_function (dev), compat, rega); - if (rega && regb) + if (rega) { grub_errno = GRUB_ERR_NONE; - grub_pata_device_initialize (controller * 2 + i, 0, rega, regb); + grub_pata_device_initialize (controller * 2 + i, 0, rega); /* Most errors raised by grub_ata_device_initialize() are harmless. They just indicate this particular drive is not responding, most @@ -422,7 +402,7 @@ grub_pata_pciinit (grub_pci_device_t dev, grub_errno = GRUB_ERR_NONE; } - grub_pata_device_initialize (controller * 2 + i, 1, rega, regb); + grub_pata_device_initialize (controller * 2 + i, 1, rega); /* Likewise. */ if (grub_errno) From d9675dbee3525def248571a7937e69fdec7afab0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 03:47:51 +0100 Subject: [PATCH 119/406] Move 0xE0 to callers rather than to have it in drivers --- grub-core/commands/hdparm.c | 4 ++++ grub-core/disk/ahci.c | 1 - grub-core/disk/ata.c | 10 +++++----- grub-core/disk/pata.c | 5 ++--- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/grub-core/commands/hdparm.c b/grub-core/commands/hdparm.c index 0154ece57..800bfa06d 100644 --- a/grub-core/commands/hdparm.c +++ b/grub-core/commands/hdparm.c @@ -72,6 +72,8 @@ grub_hdparm_do_ata_cmd (grub_ata_t ata, grub_uint8_t cmd, apt.taskfile.cmd = cmd; apt.taskfile.features = features; apt.taskfile.sectors = sectors; + apt.taskfile.disk = 0xE0; + apt.buffer = buffer; apt.size = size; @@ -88,6 +90,7 @@ grub_hdparm_do_check_powermode_cmd (grub_ata_t ata) grub_memset (&apt, 0, sizeof (apt)); apt.taskfile.cmd = GRUB_ATA_CMD_CHECK_POWER_MODE; + apt.taskfile.disk = 0xE0; if (ata->dev->readwrite (ata, &apt)) return -1; @@ -105,6 +108,7 @@ grub_hdparm_do_smart_cmd (grub_ata_t ata, grub_uint8_t features) apt.taskfile.features = features; apt.taskfile.lba_mid = 0x4f; apt.taskfile.lba_high = 0xc2; + apt.taskfile.disk = 0xE0; if (ata->dev->readwrite (ata, &apt)) return -1; diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index d9b95df37..3160523ce 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -408,7 +408,6 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, for (i = 0; i < sizeof (parms->taskfile.raw); i++) dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i]; - dev->command_table[0].cfis[7] |= (parms->cmdsize ? 0 : 0xE0); grub_dprintf ("ahci", "cfis: %02x %02x %02x %02x %02x %02x %02x %02x\n", dev->command_table[0].cfis[0], dev->command_table[0].cfis[1], dev->command_table[0].cfis[2], dev->command_table[0].cfis[3], diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index b33abf90d..494325aa5 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -70,7 +70,7 @@ grub_atapi_identify (struct grub_ata *dev) return grub_errno; grub_memset (&parms, 0, sizeof (parms)); - parms.taskfile.disk = 0; + parms.taskfile.disk = 0xE0; parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE; parms.size = GRUB_DISK_SECTOR_SIZE; parms.buffer = info; @@ -108,7 +108,7 @@ grub_ata_identify (struct grub_ata *dev) grub_memset (&parms, 0, sizeof (parms)); parms.buffer = info; parms.size = GRUB_DISK_SECTOR_SIZE; - parms.taskfile.disk = 0; + parms.taskfile.disk = 0xE0; parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_DEVICE; @@ -196,7 +196,7 @@ grub_ata_setaddress (struct grub_ata *dev, "sector %d cannot be addressed " "using CHS addressing", sector); - parms->taskfile.disk = head; + parms->taskfile.disk = 0xE0 | head; parms->taskfile.sectnum = sect; parms->taskfile.cyllsb = cylinder & 0xFF; parms->taskfile.cylmsb = cylinder >> 8; @@ -207,7 +207,7 @@ grub_ata_setaddress (struct grub_ata *dev, case GRUB_ATA_LBA: if (size == 256) size = 0; - parms->taskfile.disk = ((sector >> 24) & 0x0F); + parms->taskfile.disk = 0xE0 | ((sector >> 24) & 0x0F); parms->taskfile.sectors = size; parms->taskfile.lba_low = sector & 0xFF; @@ -219,7 +219,7 @@ grub_ata_setaddress (struct grub_ata *dev, if (size == 65536) size = 0; - parms->taskfile.disk = 0; + parms->taskfile.disk = 0xE0; /* Set "Previous". */ parms->taskfile.sectors = size & 0xFF; diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index 940a9a5f0..f9111bc5f 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -151,9 +151,8 @@ grub_pata_readwrite (struct grub_ata *disk, parms->taskfile.lba_low, parms->size); /* Set registers. */ - grub_pata_regset (dev, GRUB_ATA_REG_DISK, (parms->cmdsize ? 0 : 0xE0) - | dev->device << 4 - | (parms->taskfile.disk & 0xf)); + grub_pata_regset (dev, GRUB_ATA_REG_DISK, (dev->device << 4) + | (parms->taskfile.disk & 0xef)); if (grub_pata_check_ready (dev)) return grub_errno; From d1e517eb20c2e5e14bdd8eea7168538f9f15a67c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 12:11:54 +0100 Subject: [PATCH 120/406] extend --disk-module to AHCI and USB --- grub-core/bus/usb/ohci.c | 8 ++++++-- grub-core/disk/ahci.c | 38 ++++++++++++++++++++++++++++++++++++++ util/grub-install.in | 14 +++++++++++--- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c index 8adaee6e0..577f35259 100644 --- a/grub-core/bus/usb/ohci.c +++ b/grub-core/bus/usb/ohci.c @@ -1422,18 +1422,22 @@ static struct grub_usb_controller_dev usb_controller = .detect_dev = grub_ohci_detect_dev }; +static void *fini_hnd; + GRUB_MOD_INIT(ohci) { COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_td) == 32); COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_ed) == 16); grub_ohci_inithw (); grub_usb_controller_dev_register (&usb_controller); - grub_loader_register_preboot_hook (grub_ohci_fini_hw, grub_ohci_restore_hw, - GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); + fini_hnd = grub_loader_register_preboot_hook (grub_ohci_fini_hw, + grub_ohci_restore_hw, + GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); } GRUB_MOD_FINI(ohci) { grub_ohci_fini_hw (0); + grub_loader_unregister_preboot_hook (fini_hnd); grub_usb_controller_dev_unregister (&usb_controller); } diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 3160523ce..61ca7e4d6 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -25,6 +25,7 @@ #include #include #include +#include struct grub_ahci_cmd_head { @@ -296,6 +297,34 @@ grub_ahci_initialize (void) return grub_errno; } +static grub_err_t +grub_ahci_fini_hw (int noreturn __attribute__ ((unused))) +{ + struct grub_ahci_device *dev, *next; + + for (dev = grub_ahci_devices; dev; dev = next) + { + next = dev->next; + dev->hba->ports[dev->num].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + while ((dev->hba->ports[dev->num].command & GRUB_AHCI_HBA_PORT_CMD_FR)); + dev->hba->ports[dev->num].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + while ((dev->hba->ports[dev->num].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + grub_dma_free (dev->command_list_chunk); + grub_dma_free (dev->command_table_chunk); + grub_dma_free (dev->rfis); + + grub_free (dev); + } + grub_ahci_devices = NULL; + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_ahci_restore_hw (void) +{ + return grub_ahci_initialize (); +} + @@ -533,6 +562,8 @@ static struct grub_ata_dev grub_ahci_dev = +static void *fini_hnd; + GRUB_MOD_INIT(ahci) { /* To prevent two drivers operating on the same disks. */ @@ -548,9 +579,16 @@ GRUB_MOD_INIT(ahci) /* AHCI devices are handled by scsi.mod. */ grub_ata_dev_register (&grub_ahci_dev); + + fini_hnd = grub_loader_register_preboot_hook (grub_ahci_fini_hw, + grub_ahci_restore_hw, + GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); } GRUB_MOD_FINI(ahci) { + grub_ahci_fini_hw (0); + grub_loader_unregister_preboot_hook (fini_hnd); + grub_ata_dev_unregister (&grub_ahci_dev); } diff --git a/util/grub-install.in b/util/grub-install.in index b9e833360..6259b1c4a 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -77,7 +77,7 @@ if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then elif [ "${platform}" = "ieee1275" ] || [ "${platform}" = "efi" ] ; then disk_module= else - disk_module=ata + disk_module=native fi # Usage: usage @@ -114,7 +114,7 @@ Install GRUB on your drive. EOF if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then cat < Date: Sat, 25 Dec 2010 13:44:31 +0100 Subject: [PATCH 121/406] avoid throwing data away on pxefs_open. Reported by : Seth Goldberg --- grub-core/net/i386/pc/pxe.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/grub-core/net/i386/pc/pxe.c b/grub-core/net/i386/pc/pxe.c index fd1447b40..c07aa78f9 100644 --- a/grub-core/net/i386/pc/pxe.c +++ b/grub-core/net/i386/pc/pxe.c @@ -117,7 +117,7 @@ grub_pxefs_open (struct grub_file *file, const char *name) struct grub_pxe_data *data; grub_file_t file_int, bufio; - data = grub_malloc (sizeof (*data)); + data = grub_zalloc (sizeof (*data) + grub_strlen (name) + 1); if (!data) return grub_errno; @@ -135,7 +135,10 @@ grub_pxefs_open (struct grub_file *file, const char *name) err = grub_net_resolve_address (file->device->net->name + sizeof ("pxe,") - 1, &addr); if (err) - return err; + { + grub_free (data); + return err; + } } else { @@ -144,7 +147,10 @@ grub_pxefs_open (struct grub_file *file, const char *name) } err = grub_net_route_address (addr, &gateway, &interf); if (err) - return err; + { + grub_free (data); + return err; + } data->server_ip = addr.ipv4; data->gateway_ip = gateway.ipv4; } @@ -160,7 +166,10 @@ grub_pxefs_open (struct grub_file *file, const char *name) grub_strcpy ((char *)&c.c1.filename[0], name); grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1, pxe_rm_entry); if (c.c1.status) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + { + grub_free (data); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + } file->size = c.c1.file_size; @@ -168,11 +177,10 @@ grub_pxefs_open (struct grub_file *file, const char *name) c.c2.packet_size = grub_pxe_blksize; grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &c.c2, pxe_rm_entry); if (c.c2.status) - return grub_error (GRUB_ERR_BAD_FS, "open fails"); - - data = grub_zalloc (sizeof (struct grub_pxe_data) + grub_strlen (name) + 1); - if (! data) - return grub_errno; + { + grub_free (data); + return grub_error (GRUB_ERR_BAD_FS, "open fails"); + } data->block_size = c.c2.packet_size; grub_strcpy (data->filename, name); From 3c51ecb82b7ab1a94a296c530bd5f4ffdb7a2eab Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 15:47:23 +0100 Subject: [PATCH 122/406] Fix adressing mode mismatch --- grub-core/disk/ata.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 494325aa5..3fecb98dd 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -173,9 +173,10 @@ static grub_err_t grub_ata_setaddress (struct grub_ata *dev, struct grub_disk_ata_pass_through_parms *parms, grub_disk_addr_t sector, - grub_size_t size) + grub_size_t size, + grub_ata_addressing_t addressing) { - switch (dev->addr) + switch (addressing) { case GRUB_ATA_CHS: { @@ -297,7 +298,7 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, grub_dprintf("ata", "rw=%d, sector=%llu, batch=%llu\n", rw, (unsigned long long) sector, (unsigned long long) batch); grub_memset (&parms, 0, sizeof (parms)); - grub_ata_setaddress (ata, &parms, sector, batch); + grub_ata_setaddress (ata, &parms, sector, batch, addressing); parms.taskfile.cmd = (! rw ? cmd : cmd_write); parms.buffer = buf; parms.size = batch * GRUB_DISK_SECTOR_SIZE; From c76ae9b4da785c43dba8478768dd346f5c0b4d59 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 17:40:00 +0100 Subject: [PATCH 123/406] set parms.write on disk write --- grub-core/disk/ata.c | 1 + 1 file changed, 1 insertion(+) diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 3fecb98dd..c7cde3166 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -302,6 +302,7 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, parms.taskfile.cmd = (! rw ? cmd : cmd_write); parms.buffer = buf; parms.size = batch * GRUB_DISK_SECTOR_SIZE; + parms.write = rw; if (ata->dma) parms.dma = 1; From 9797178671d1044cf9fc13648152ea2ea5e76e41 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 18:02:43 +0100 Subject: [PATCH 124/406] Accept ports in state 1 --- grub-core/disk/ahci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 61ca7e4d6..b348ce3d0 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -220,13 +220,15 @@ grub_ahci_pciinit (grub_pci_device_t dev, struct grub_ahci_device *adev; struct grub_pci_dma_chunk *command_list; struct grub_pci_dma_chunk *command_table; + grub_uint32_t st; if (!(hba->ports_implemented & (1 << i))) continue; grub_dprintf ("ahci", "status %d:%x\n", i, hba->ports[i].status); /* FIXME: support hotplugging. */ - if ((hba->ports[i].status & 0xf) != 0x3) + st = hba->ports[i].status; + if ((st & 0xf) != 0x3 && (st & 0xf) != 0x1) continue; command_list = grub_memalign_dma32 (1024, From b28fd807eb6e6ec74964715e0bfd3c32b0dbb449 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Dec 2010 00:38:20 +0100 Subject: [PATCH 125/406] freedos support --- docs/grub.texi | 4 + grub-core/Makefile.core.def | 6 ++ grub-core/lib/i386/relocator.c | 2 + grub-core/lib/i386/relocator16.S | 7 +- grub-core/loader/i386/pc/freedos.c | 136 +++++++++++++++++++++++++++++ include/grub/i386/relocator.h | 1 + 6 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 grub-core/loader/i386/pc/freedos.c diff --git a/docs/grub.texi b/docs/grub.texi index 54a2d8791..d9500fb52 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -3305,6 +3305,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item @tab BIOS @tab Coreboot @item BIOS chainloading @tab yes @tab no (1) @item NTLDR @tab yes @tab no (1) +@item Freedos @tab yes @tab no (1) @item FreeBSD bootloader @tab yes @tab crashes (1) @item 32-bit kFreeBSD @tab yes @tab crashes (2,6) @item 64-bit kFreeBSD @tab yes @tab crashes (2,6) @@ -3329,6 +3330,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item @tab Multiboot @tab Qemu @item BIOS chainloading @tab no (1) @tab no (1) @item NTLDR @tab no (1) @tab no (1) +@item FreeDOS @tab no (1) @tab no (1) @item FreeBSD bootloader @tab crashes (1) @tab crashes (1) @item 32-bit kFreeBSD @tab crashes (6) @tab crashes (6) @item 64-bit kFreeBSD @tab crashes (6) @tab crashes (6) @@ -3353,6 +3355,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item @tab 32-bit EFI @tab 64-bit EFI @item BIOS chainloading @tab no (1) @tab no (1) @item NTLDR @tab no (1) @tab no (1) +@item FreeDOS @tab no (1) @tab no (1) @item FreeBSD bootloader @tab crashes (1) @tab crashes (1) @item 32-bit kFreeBSD @tab headless @tab headless @item 64-bit kFreeBSD @tab headless @tab headless @@ -3377,6 +3380,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item @tab IEEE1275 @item BIOS chainloading @tab no (1) @item NTLDR @tab no (1) +@item FreeDOS @tab no (1) @item FreeBSD bootloader @tab crashes (1) @item 32-bit kFreeBSD @tab crashes (6) @item 64-bit kFreeBSD @tab crashes (6) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 37c0ce970..da309d6d9 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1158,6 +1158,12 @@ module = { enable = i386_pc; }; +module = { + name = freedos; + i386_pc = loader/i386/pc/freedos.c; + enable = i386_pc; +}; + module = { name = multiboot2; cppflags = "-DGRUB_USE_MULTIBOOT2"; diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c index 1bc4240c3..2f10feb5e 100644 --- a/grub-core/lib/i386/relocator.c +++ b/grub-core/lib/i386/relocator.c @@ -50,6 +50,7 @@ extern grub_uint16_t grub_relocator16_gs; extern grub_uint16_t grub_relocator16_ss; extern grub_uint16_t grub_relocator16_sp; extern grub_uint32_t grub_relocator16_edx; +extern grub_uint32_t grub_relocator16_ebx; extern grub_uint8_t grub_relocator32_start; extern grub_uint8_t grub_relocator32_end; @@ -212,6 +213,7 @@ grub_relocator16_boot (struct grub_relocator *rel, grub_relocator16_ss = state.ss; grub_relocator16_sp = state.sp; + grub_relocator16_ebx = state.ebx; grub_relocator16_edx = state.edx; grub_memmove (get_virtual_current_address (ch), &grub_relocator16_start, diff --git a/grub-core/lib/i386/relocator16.S b/grub-core/lib/i386/relocator16.S index c3768f4eb..c6d38eba4 100644 --- a/grub-core/lib/i386/relocator16.S +++ b/grub-core/lib/i386/relocator16.S @@ -136,7 +136,12 @@ VARIABLE(grub_relocator16_sp) .byte 0x66, 0xba VARIABLE(grub_relocator16_edx) .long 0 - + + /* movw imm32, %ebx. */ + .byte 0x66, 0xbb +VARIABLE(grub_relocator16_ebx) + .long 0 + /* Cleared direction flag is of no problem with any current payload and makes this implementation easier. */ cld diff --git a/grub-core/loader/i386/pc/freedos.c b/grub-core/loader/i386/pc/freedos.c new file mode 100644 index 000000000..67d97e246 --- /dev/null +++ b/grub-core/loader/i386/pc/freedos.c @@ -0,0 +1,136 @@ +/* chainloader.c - boot another boot loader */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2004,2007,2009,2010 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 + +static grub_dl_t my_mod; +static struct grub_relocator *rel; +static grub_uint32_t ebx = 0xffffffff; + +#define GRUB_FREEDOS_SEGMENT 0x60 +#define GRUB_FREEDOS_STACK_SEGMENT 0x1fe0 +#define GRUB_FREEDOS_STACK_POINTER 0x8000 + +static grub_err_t +grub_freedos_boot (void) +{ + struct grub_relocator16_state state = { + .cs = GRUB_FREEDOS_SEGMENT, + .ip = 0, + .ds = 0, + .es = 0, + .fs = 0, + .gs = 0, + .ss = GRUB_FREEDOS_STACK_SEGMENT, + .sp = GRUB_FREEDOS_STACK_POINTER, + .ebx = ebx, + .edx = 0 + }; + grub_video_set_mode ("text", 0, 0); + + return grub_relocator16_boot (rel, state); +} + +static grub_err_t +grub_freedos_unload (void) +{ + grub_relocator_unload (rel); + rel = NULL; + grub_dl_unref (my_mod); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_freedos (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + grub_file_t file = 0; + grub_err_t err; + void *kernelsys; + grub_size_t kernelsyssize; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); + + grub_dl_ref (my_mod); + + rel = grub_relocator_new (); + if (!rel) + goto fail; + + file = grub_file_open (argv[0]); + if (! file) + goto fail; + + ebx = grub_get_root_biosnumber (); + + kernelsyssize = grub_file_size (file); + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_NTLDR_SEGMENT << 4, + kernelsyssize); + if (err) + goto fail; + kernelsys = get_virtual_current_address (ch); + } + + if (grub_file_read (file, kernelsys, kernelsyssize) + != (grub_ssize_t) ntldrsize) + goto fail; + + grub_loader_set (grub_freedos_boot, grub_freedos_unload, 1); + return GRUB_ERR_NONE; + + fail: + + if (file) + grub_file_close (file); + + grub_ntldr_unload (); + + return grub_errno; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(freedos) +{ + cmd = grub_register_command ("freedos", grub_cmd_freedos, + 0, N_("Load FreeDOS kernel.sys.")); + my_mod = mod; +} + +GRUB_MOD_FINI(freedos) +{ + grub_unregister_command (cmd); +} diff --git a/include/grub/i386/relocator.h b/include/grub/i386/relocator.h index 6ff5c6631..778049eef 100644 --- a/include/grub/i386/relocator.h +++ b/include/grub/i386/relocator.h @@ -46,6 +46,7 @@ struct grub_relocator16_state grub_uint16_t ss; grub_uint16_t sp; grub_uint16_t ip; + grub_uint32_t ebx; grub_uint32_t edx; }; From af36812f5cf8d15cdb00a80681a2918bd07a9765 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Dec 2010 00:57:03 +0100 Subject: [PATCH 126/406] fix a compilation error --- grub-core/loader/i386/pc/freedos.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grub-core/loader/i386/pc/freedos.c b/grub-core/loader/i386/pc/freedos.c index 67d97e246..0ae815490 100644 --- a/grub-core/loader/i386/pc/freedos.c +++ b/grub-core/loader/i386/pc/freedos.c @@ -97,7 +97,7 @@ grub_cmd_freedos (grub_command_t cmd __attribute__ ((unused)), kernelsyssize = grub_file_size (file); { grub_relocator_chunk_t ch; - err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_NTLDR_SEGMENT << 4, + err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_FREEDOS_SEGMENT << 4, kernelsyssize); if (err) goto fail; @@ -105,7 +105,7 @@ grub_cmd_freedos (grub_command_t cmd __attribute__ ((unused)), } if (grub_file_read (file, kernelsys, kernelsyssize) - != (grub_ssize_t) ntldrsize) + != (grub_ssize_t) kernelsyssize) goto fail; grub_loader_set (grub_freedos_boot, grub_freedos_unload, 1); @@ -116,7 +116,7 @@ grub_cmd_freedos (grub_command_t cmd __attribute__ ((unused)), if (file) grub_file_close (file); - grub_ntldr_unload (); + grub_freedos_unload (); return grub_errno; } From b9cd13659cce5dd2414e962c02042c9ece90b918 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 31 Dec 2010 15:22:36 +0100 Subject: [PATCH 127/406] Simplify the AFFS checksum computation. --- grub-core/fs/affs.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index e4b487a7e..e05c166a9 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -174,7 +174,6 @@ grub_affs_mount (grub_disk_t disk) struct grub_affs_rblock *rblock; int checksum = 0; - int checksumr = 0; int blocksize = 0; data = grub_malloc (sizeof (struct grub_affs_data)); @@ -224,8 +223,6 @@ grub_affs_mount (grub_disk_t disk) /* The filesystem blocksize is not stored anywhere in the filesystem itself. One way to determine it is reading blocks for the rootblock until the checksum is correct. */ - checksumr = grub_be_to_cpu32 (rblock->checksum); - rblock->checksum = 0; for (blocksize = 0; blocksize < 8; blocksize++) { grub_uint32_t *currblock = rootblock + GRUB_DISK_SECTOR_SIZE * blocksize; @@ -234,10 +231,10 @@ grub_affs_mount (grub_disk_t disk) for (i = 0; i < GRUB_DISK_SECTOR_SIZE / sizeof (*currblock); i++) checksum += grub_be_to_cpu32 (currblock[i]); - if (checksumr == -checksum) + if (checksum == 0) break; } - if (-checksum != checksumr) + if (checksum != 0) { grub_error (GRUB_ERR_BAD_FS, "AFFS blocksize couldn't be determined"); goto fail; From fb17547ca89991f33d269cc01af711e198ab1eb0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 31 Dec 2010 15:23:06 +0100 Subject: [PATCH 128/406] Check amiga partmap checksum --- grub-core/partmap/amiga.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/grub-core/partmap/amiga.c b/grub-core/partmap/amiga.c index 1e0f23402..803e2e14f 100644 --- a/grub-core/partmap/amiga.c +++ b/grub-core/partmap/amiga.c @@ -37,7 +37,7 @@ struct grub_amiga_rdsk grub_uint32_t partitionlst; grub_uint32_t fslst; - /* The other information is not important for us. */ + grub_uint32_t unused[128 - 9]; } __attribute__ ((packed)); struct grub_amiga_partition @@ -65,12 +65,24 @@ struct grub_amiga_partition grub_uint32_t highcyl; grub_uint32_t firstcyl; + grub_uint32_t unused[128 - 44]; } __attribute__ ((packed)); static struct grub_partition_map grub_amiga_partition_map; +static grub_uint32_t +amiga_partition_map_checksum (void *buf, grub_size_t sz) +{ + grub_uint32_t *ptr = buf; + grub_uint32_t r = 0; + sz /= sizeof (grub_uint32_t); + for (; sz; sz--, ptr++) + r += grub_be_to_cpu32 (*ptr); + return r; +} + static grub_err_t amiga_partition_map_iterate (grub_disk_t disk, int (*hook) (grub_disk_t disk, @@ -90,7 +102,8 @@ amiga_partition_map_iterate (grub_disk_t disk, return grub_errno; if (grub_memcmp (rdsk.magic, GRUB_AMIGA_RDSK_MAGIC, - sizeof (rdsk.magic)) == 0) + sizeof (rdsk.magic)) == 0 + && amiga_partition_map_checksum (&rdsk, sizeof (rdsk)) == 0) { /* Found the first PART block. */ next = grub_be_to_cpu32 (rdsk.partitionlst); @@ -112,7 +125,8 @@ amiga_partition_map_iterate (grub_disk_t disk, return grub_errno; if (grub_memcmp (apart.magic, GRUB_AMIGA_PART_MAGIC, - sizeof (apart.magic)) == 0) + sizeof (apart.magic)) == 0 + && amiga_partition_map_checksum (&apart, sizeof (apart)) == 0) /* Calculate the first block and the size of the partition. */ part.start = (grub_be_to_cpu32 (apart.lowcyl) From 3a04c65d008246c29d8a0b86fb66770ac6d6634f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 1 Jan 2011 15:13:03 +0100 Subject: [PATCH 129/406] Always add libgcc.h --- grub-core/Makefile.am | 4 +--- include/grub/libgcc.h | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 5d13d0313..7fa00b744 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -74,6 +74,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h if COND_i386_pc KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h @@ -132,7 +133,6 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap_scale.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cs5536.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pci.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/serial.h @@ -140,11 +140,9 @@ endif if COND_powerpc_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h endif if COND_sparc64_ieee1275 -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h endif diff --git a/include/grub/libgcc.h b/include/grub/libgcc.h index 703182577..100c8667b 100644 --- a/include/grub/libgcc.h +++ b/include/grub/libgcc.h @@ -53,7 +53,7 @@ void EXPORT_FUNC (__udivdi3) (void); # ifdef HAVE___DIVSI3 void EXPORT_FUNC (__divsi3) (void); # endif -# ifdef HAVE___UMODSI3 +# ifdef HAVE___MODSI3 void EXPORT_FUNC (__modsi3) (void); # endif #endif From 52f65ea0bc9c3d36a0691a330eb2131df7cacc6d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 1 Jan 2011 15:28:39 +0100 Subject: [PATCH 130/406] add moddi3 and divdi3 --- configure.ac | 2 +- include/grub/libgcc.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index ca886b5dc..4c710748c 100644 --- a/configure.ac +++ b/configure.ac @@ -542,7 +542,7 @@ CFLAGS="$CFLAGS -Wl,--defsym,abort=main" fi # Check for libgcc symbols -AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2 _restgpr_14_x __ia64_trampoline __udivsi3 __umoddi3 __udivdi3 __divsi3 __modsi3 __umodsi3) +AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2 _restgpr_14_x __ia64_trampoline __udivsi3 __umoddi3 __udivdi3 __divsi3 __modsi3 __umodsi3 __moddi3 __divdi3) if test "x$TARGET_APPLE_CC" = x1 ; then CFLAGS="$TARGET_CFLAGS -nostdlib" diff --git a/include/grub/libgcc.h b/include/grub/libgcc.h index 100c8667b..be600220e 100644 --- a/include/grub/libgcc.h +++ b/include/grub/libgcc.h @@ -50,6 +50,12 @@ void EXPORT_FUNC (__umoddi3) (void); # ifdef HAVE___UDIVDI3 void EXPORT_FUNC (__udivdi3) (void); # endif +# ifdef HAVE___MODDI3 +void EXPORT_FUNC (__moddi3) (void); +# endif +# ifdef HAVE___DIVDI3 +void EXPORT_FUNC (__divdi3) (void); +# endif # ifdef HAVE___DIVSI3 void EXPORT_FUNC (__divsi3) (void); # endif From 6f49d0aacb1a26d756faa849ea5b18d1322091d5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 1 Jan 2011 15:53:31 +0100 Subject: [PATCH 131/406] Add missing cache.c --- grub-core/Makefile.core.def | 1 + grub-core/kern/emu/cache.c | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 grub-core/kern/emu/cache.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index b953adfb9..801ad6d7c 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -158,6 +158,7 @@ kernel = { emu = kern/emu/misc.c; emu = kern/emu/mm.c; emu = kern/emu/time.c; + emu = kern/emu/cache.c; videoinkernel = lib/arg.c; videoinkernel = term/gfxterm.c; diff --git a/grub-core/kern/emu/cache.c b/grub-core/kern/emu/cache.c new file mode 100644 index 000000000..bdff146ef --- /dev/null +++ b/grub-core/kern/emu/cache.c @@ -0,0 +1,10 @@ + +#include + +void __clear_cache (char *beg, char *end); + +void +grub_arch_sync_caches (void *address, grub_size_t len) +{ + __clear_cache (address, (char *) address + len); +} From f9c30af6d08a6d2b0c3e831d116c37dc1d1d7c78 Mon Sep 17 00:00:00 2001 From: phcoder Date: Sun, 2 Jan 2011 14:09:58 +0100 Subject: [PATCH 132/406] Succesfully loaded return-only module on ia64-emu --- grub-core/kern/dl.c | 49 ++++++- grub-core/kern/emu/cache.S | 1 + grub-core/kern/emu/cache.c | 3 + grub-core/kern/emu/full.c | 9 ++ grub-core/kern/emu/lite.c | 2 + grub-core/kern/ia64/dl.c | 288 +++++++++++++++++++++++++++++++++++++ include/grub/dl.h | 20 ++- include/grub/types.h | 3 + 8 files changed, 368 insertions(+), 7 deletions(-) create mode 100644 grub-core/kern/ia64/dl.c diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 02d785b9b..2f2493fca 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -37,6 +37,10 @@ #define GRUB_MODULES_MACHINE_READONLY #endif +#ifdef GRUB_MACHINE_EMU +#include +#endif + grub_dl_t grub_dl_head = 0; @@ -233,11 +237,24 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) if (s->sh_flags & SHF_ALLOC) { grub_dl_segment_t seg; + grub_size_t tramp_size = 0; seg = (grub_dl_segment_t) grub_malloc (sizeof (*seg)); if (! seg) return grub_errno; + tramp_size = grub_arch_dl_get_tramp_size (e, i); + if (tramp_size && s->sh_addralign < GRUB_ARCH_DL_TRAMP_ALIGN) + { + s->sh_addralign = GRUB_ARCH_DL_TRAMP_ALIGN; + s->sh_size = ALIGN_UP (s->sh_size, GRUB_ARCH_DL_TRAMP_ALIGN) + tramp_size; + } +#ifdef GRUB_MACHINE_EMU + if (s->sh_addralign < 8192) + s->sh_addralign = 8192; + s->sh_size = ALIGN_UP (s->sh_size, 8192); +#endif + if (s->sh_size) { void *addr; @@ -260,6 +277,10 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) } seg->addr = addr; +#ifdef GRUB_MACHINE_EMU + if (s->sh_flags & SHF_EXECINSTR) + mprotect (addr, s->sh_size, PROT_READ | PROT_WRITE | PROT_EXEC); +#endif } else seg->addr = 0; @@ -343,9 +364,9 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) return grub_errno; if (grub_strcmp (name, "grub_mod_init") == 0) - mod->init = (void (*) (grub_dl_t)) sym->st_value; + mod->init = sym->st_value; else if (grub_strcmp (name, "grub_mod_fini") == 0) - mod->fini = (void (*) (void)) sym->st_value; + mod->fini = sym->st_value; break; case STT_SECTION: @@ -370,7 +391,16 @@ static void grub_dl_call_init (grub_dl_t mod) { if (mod->init) - (mod->init) (mod); + { +#ifndef __ia64__ + ((void (*) (grub_dl_t)) mod->init) (mod); +#else + char *jmp[2]; + jmp[0] = (char *) mod->init; + jmp[1] = mod->gp; + ((void (*) (grub_dl_t)) jmp) (mod); +#endif + } } static grub_err_t @@ -533,7 +563,7 @@ grub_dl_load_core (void *addr, grub_size_t size) grub_dl_flush_cache (mod); grub_dprintf ("modules", "module name: %s\n", mod->name); - grub_dprintf ("modules", "init function: %p\n", mod->init); + grub_dprintf ("modules", "init function: %" PRIxGRUB_ADDR "\n", mod->init); grub_dl_call_init (mod); if (grub_dl_add (mod)) @@ -633,7 +663,16 @@ grub_dl_unload (grub_dl_t mod) return 0; if (mod->fini) - (mod->fini) (); + { +#ifndef __ia64__ + ((void (*) (void)) mod->fini) (); +#else + char *jmp[2]; + jmp[0] = (char *) mod->fini; + jmp[1] = mod->gp; + ((void (*) (void)) jmp) (); +#endif + } grub_dl_remove (mod); grub_dl_unregister_symbols (mod); diff --git a/grub-core/kern/emu/cache.S b/grub-core/kern/emu/cache.S index 90a5b5396..99637762a 100644 --- a/grub-core/kern/emu/cache.S +++ b/grub-core/kern/emu/cache.S @@ -10,6 +10,7 @@ #include "../mips/cache.S" #elif defined(__powerpc__) #include "../powerpc/cache.S" +#elif defined(__ia64__) #else #error "No target cpu type is defined" #endif diff --git a/grub-core/kern/emu/cache.c b/grub-core/kern/emu/cache.c index bdff146ef..543e457e5 100644 --- a/grub-core/kern/emu/cache.c +++ b/grub-core/kern/emu/cache.c @@ -1,4 +1,5 @@ +#if defined(__ia64__) #include void __clear_cache (char *beg, char *end); @@ -8,3 +9,5 @@ grub_arch_sync_caches (void *address, grub_size_t len) { __clear_cache (address, (char *) address + len); } +#endif + diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c index 0bd33337f..0396d0ab4 100644 --- a/grub-core/kern/emu/full.c +++ b/grub-core/kern/emu/full.c @@ -48,3 +48,12 @@ grub_emu_init (void) { grub_no_autoload = 1; } + +#ifdef __ia64__ +grub_size_t +grub_arch_dl_get_tramp_size (const void *ehdr __attribute__ ((unused)), + unsigned sec __attribute__ ((unused))) +{ + return ~(grub_size_t)0; +} +#endif diff --git a/grub-core/kern/emu/lite.c b/grub-core/kern/emu/lite.c index 9b3728717..5d3588bd0 100644 --- a/grub-core/kern/emu/lite.c +++ b/grub-core/kern/emu/lite.c @@ -15,6 +15,8 @@ #include "../mips/dl.c" #elif defined(__powerpc__) #include "../powerpc/dl.c" +#elif defined(__ia64__) +#include "../ia64/dl.c" #else #error "No target cpu type is defined" #endif diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c new file mode 100644 index 000000000..2b87577a4 --- /dev/null +++ b/grub-core/kern/ia64/dl.c @@ -0,0 +1,288 @@ +/* dl.c - arch-dependent part of loadable module support */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2004,2005,2007,2009 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 + +/* Check if EHDR is a valid ELF header. */ +grub_err_t +grub_arch_dl_check_header (void *ehdr) +{ + Elf_Ehdr *e = ehdr; + + /* Check the magic numbers. */ + if (e->e_ident[EI_CLASS] != ELFCLASS64 + || e->e_ident[EI_DATA] != ELFDATA2LSB + || e->e_machine != EM_IA_64) + return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic"); + + return GRUB_ERR_NONE; +} + +#define MASK20 ((1 << 20) - 1) +#define MASK19 ((1 << 19) - 1) + +static void +add_value_to_slot13_20 (Elf_Word *addr, grub_uint32_t value, int slot) +{ + grub_uint32_t *p __attribute__ ((aligned (1))); + switch (slot) + { + case 0: + p = (grub_uint32_t *) (addr + 2); + *p = (((((*p >> 2) & MASK20) + value) & MASK20) << 2) | (*p & ~(MASK20 << 2)); + break; + case 1: + p = (grub_uint32_t *) ((grub_uint8_t *) addr + 7); + *p = (((((*p >> 3) & MASK20) + value) & MASK20) << 3) | (*p & ~(MASK20 << 3)); + break; + case 2: + p = (grub_uint32_t *) ((grub_uint8_t *) addr + 12); + *p = (((((*p >> 4) & MASK20) + value) & MASK20) << 4) | (*p & ~(MASK20 << 4)); + break; + } +} + +static grub_uint8_t nopm[5] = + { + /* [MLX] nop.m 0x0 */ + 0x05, 0x00, 0x00, 0x00, 0x01 + }; + +static grub_uint8_t jump[0x20] = + { + /* ld8 r16=[r15],8 */ + 0x02, 0x80, 0x20, 0x1e, 0x18, 0x14, + /* mov r14=r1;; */ + 0xe0, 0x00, 0x04, 0x00, 0x42, 0x00, + /* nop.i 0x0 */ + 0x00, 0x00, 0x04, 0x00, + /* ld8 r1=[r15] */ + 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10, + /* mov b6=r16 */ + 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, + /* br.few b6;; */ + 0x60, 0x00, 0x80, 0x00 + }; + +struct ia64_trampoline +{ + /* nop.m */ + grub_uint8_t nop[5]; + /* movl r15 = addr*/ + grub_uint8_t addr_hi[6]; + grub_uint8_t e0; + grub_uint8_t addr_lo[4]; + grub_uint8_t jump[0x20]; +}; + +static void +make_trampoline (struct ia64_trampoline *tr, grub_uint64_t addr) +{ + grub_memcpy (tr->nop, nopm, sizeof (tr->nop)); + tr->addr_hi[0] = ((addr & 0xc00000) >> 18); + tr->addr_hi[1] = (addr >> 24) & 0xff; + tr->addr_hi[2] = (addr >> 32) & 0xff; + tr->addr_hi[3] = (addr >> 40) & 0xff; + tr->addr_hi[4] = (addr >> 48) & 0xff; + tr->addr_hi[5] = (addr >> 56) & 0xff; + tr->e0 = 0xe0; + tr->addr_lo[0] = ((addr & 0x000f) << 4) | 0x01; + tr->addr_lo[1] = ((addr & 0x0070) >> 4) | ((addr & 0x070000) >> 11) | ((addr & 0x200000) >> 17); + tr->addr_lo[2] = ((addr & 0x1f80) >> 5) | ((addr & 0x180000) >> 19); + tr->addr_lo[3] = ((addr & 0xe000) >> 13) | 0x60; + grub_memcpy (tr->jump, jump, sizeof (tr->jump)); +} + +grub_size_t +grub_arch_dl_get_tramp_size (const void *ehdr, unsigned sec) +{ + const Elf_Ehdr *e = ehdr; + int cnt = 0; + const Elf_Shdr *s; + Elf_Word entsize; + unsigned i; + + /* Find a symbol table. */ + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_SYMTAB) + break; + + if (i == e->e_shnum) + return 0; + + entsize = s->sh_entsize; + + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_RELA) + { + Elf_Rela *rel, *max; + + if (s->sh_info != sec) + continue; + + for (rel = (Elf_Rela *) ((char *) e + s->sh_offset), + max = rel + s->sh_size / s->sh_entsize; + rel < max; rel++) + if (ELF_R_TYPE (rel->r_info) == R_IA64_PCREL21B) + cnt++; + } + + return cnt * sizeof (struct ia64_trampoline); +} + +/* Relocate symbols. */ +grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +{ + Elf_Ehdr *e = ehdr; + Elf_Shdr *s; + Elf_Word entsize; + unsigned i; + grub_uint64_t *gp, *gpptr; + grub_size_t gp_size = 0; + + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_REL) + { + grub_dl_segment_t seg; + + /* Find the target segment. */ + for (seg = mod->segment; seg; seg = seg->next) + if (seg->section == s->sh_info) + break; + + if (seg) + { + Elf_Rel *rel, *max; + + for (rel = (Elf_Rel *) ((char *) e + s->sh_offset), + max = rel + s->sh_size / s->sh_entsize; + rel < max; + rel++) + switch (ELF_R_TYPE (rel->r_info)) + { + default: break; + } + } + } + + if (gp_size > MASK19) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "gp too big"); + + gpptr = gp = grub_malloc (gp_size); + if (!gp) + return grub_errno; + mod->gp = (char *) gp; + + /* Find a symbol table. */ + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_SYMTAB) + break; + + if (i == e->e_shnum) + return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found"); + + entsize = s->sh_entsize; + + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_RELA) + { + grub_dl_segment_t seg; + + /* Find the target segment. */ + for (seg = mod->segment; seg; seg = seg->next) + if (seg->section == s->sh_info) + break; + + if (seg) + { + Elf_Rela *rel, *max; + struct ia64_trampoline *tr; + + for (rel = (Elf_Rela *) ((char *) e + s->sh_offset), + max = rel + s->sh_size / s->sh_entsize; + rel < max; + rel++) + { + Elf_Word *addr; + Elf_Sym *sym; + grub_uint64_t value; + int slot = 0; + + if (seg->size < (rel->r_offset & ~3)) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); + + tr = (void *) ((char *) seg->addr + ALIGN_UP (seg->size, GRUB_ARCH_DL_TRAMP_ALIGN)); + + if (ELF_R_TYPE (rel->r_info) == R_IA64_PCREL21B) + { + addr = (Elf_Word *) ((char *) seg->addr + (rel->r_offset & ~3)); + slot = rel->r_offset & 3; + } + else + addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset); + sym = (Elf_Sym *) ((char *) mod->symtab + + entsize * ELF_R_SYM (rel->r_info)); + + /* On the PPC the value does not have an explicit + addend, add it. */ + value = sym->st_value + rel->r_addend; + switch (ELF_R_TYPE (rel->r_info)) + { + case R_IA64_PCREL21B: + { + grub_uint64_t noff; + make_trampoline (tr, value); + noff = ((char *) tr - (char *) addr) >> 4; + tr++; + if (noff & ~MASK19) + return grub_error (GRUB_ERR_BAD_OS, + "trampoline offset too big"); + add_value_to_slot13_20 (addr, noff, slot); + } + break; + case R_IA64_SEGREL64LSB: + *(grub_uint64_t *) addr += value - rel->r_offset; + break; + default: + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "this relocation (0x%x) is not implemented yet", + ELF_R_TYPE (rel->r_info)); + } + } + } + } + + return GRUB_ERR_NONE; +} diff --git a/include/grub/dl.h b/include/grub/dl.h index afc4af41a..e04285280 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -90,8 +90,11 @@ struct grub_dl grub_dl_dep_t dep; grub_dl_segment_t segment; Elf_Sym *symtab; - void (*init) (struct grub_dl *mod); - void (*fini) (void); + grub_addr_t init; + grub_addr_t fini; +#ifdef __ia64__ + char *gp; +#endif struct grub_dl *next; }; typedef struct grub_dl *grub_dl_t; @@ -119,4 +122,17 @@ grub_err_t grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr); void grub_arch_dl_init_linker (void); #endif +#ifdef __ia64__ +grub_size_t grub_arch_dl_get_tramp_size (const void *ehdr, unsigned sec); +#define GRUB_ARCH_DL_TRAMP_ALIGN 16 +#else +static inline grub_size_t +grub_arch_dl_get_tramp_size (const void *ehdr __attribute__ ((unused)), int sec __attribute__ ((unused))) +{ + return 0; +} +#define GRUB_ARCH_DL_TRAMP_ALIGN 1 +#endif + + #endif /* ! GRUB_DL_H */ diff --git a/include/grub/types.h b/include/grub/types.h index 4499e4538..b3aa69c1c 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -95,8 +95,10 @@ typedef grub_int64_t grub_ssize_t; # if GRUB_CPU_SIZEOF_LONG == 8 # define PRIxGRUB_SIZE "lx" +# define PRIxGRUB_ADDR "lx" # else # define PRIxGRUB_SIZE "llx" +# define PRIxGRUB_ADDR "llx" # endif #else typedef grub_uint32_t grub_addr_t; @@ -104,6 +106,7 @@ typedef grub_uint32_t grub_size_t; typedef grub_int32_t grub_ssize_t; # define PRIxGRUB_SIZE "x" +# define PRIxGRUB_ADDR "x" #endif #if GRUB_CPU_SIZEOF_LONG == 8 From daca6c5f45406137290e008ae0ef363624bc1887 Mon Sep 17 00:00:00 2001 From: phcoder Date: Sun, 2 Jan 2011 14:39:23 +0100 Subject: [PATCH 133/406] ltoff relocation support --- grub-core/kern/ia64/dl.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c index 2b87577a4..24fa01b90 100644 --- a/grub-core/kern/ia64/dl.c +++ b/grub-core/kern/ia64/dl.c @@ -187,6 +187,10 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) rel++) switch (ELF_R_TYPE (rel->r_info)) { + case R_IA64_LTOFF22X: + case R_IA64_LTOFF22: + gp_size += 8; + break; default: break; } } @@ -275,6 +279,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) case R_IA64_SEGREL64LSB: *(grub_uint64_t *) addr += value - rel->r_offset; break; + case R_IA64_LTOFF22X: + case R_IA64_LTOFF22: + *gpptr = value; + add_value_to_slot13_20 (addr, (gpptr - gp) * sizeof (grub_uint64_t), slot); + gpptr++; + break; + + /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */ + case R_IA64_LDXMOV: + break; default: return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "this relocation (0x%x) is not implemented yet", From 73911575dd67eaa09837fe0f691655553c3dea69 Mon Sep 17 00:00:00 2001 From: phcoder Date: Sun, 2 Jan 2011 14:58:57 +0100 Subject: [PATCH 134/406] support for registering functions from modules (not tested yet) --- grub-core/kern/dl.c | 20 +++++++++++++++++--- grub-core/kern/emu/full.c | 8 ++++++++ grub-core/kern/ia64/dl.c | 30 ++++++++++++++++++++---------- include/grub/dl.h | 9 +++++++++ 4 files changed, 54 insertions(+), 13 deletions(-) diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 2f2493fca..9dfff5287 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -360,9 +360,22 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) sym->st_value += (Elf_Addr) grub_dl_get_section_addr (mod, sym->st_shndx); if (bind != STB_LOCAL) - if (grub_dl_register_symbol (name, (void *) sym->st_value, mod)) - return grub_errno; - + { +#ifdef __ia64__ + /* FIXME: free descriptor once it's not used anymore. */ + char **desc; + desc = grub_malloc (2 * sizeof (char *)); + if (!desc) + return grub_errno; + desc[0] = (void *) sym->st_value; + desc[1] = mod->gp; + if (grub_dl_register_symbol (name, (void *) desc, mod)) + return grub_errno; +#else + if (grub_dl_register_symbol (name, (void *) sym->st_value, mod)) + return grub_errno; +#endif + } if (grub_strcmp (name, "grub_mod_init") == 0) mod->init = sym->st_value; else if (grub_strcmp (name, "grub_mod_fini") == 0) @@ -552,6 +565,7 @@ grub_dl_load_core (void *addr, grub_size_t size) if (grub_dl_resolve_name (mod, e) || grub_dl_resolve_dependencies (mod, e) || grub_dl_load_segments (mod, e) + || grub_arch_dl_allocate_gp (mod, e) || grub_dl_resolve_symbols (mod, e) || grub_arch_dl_relocate_symbols (mod, e)) { diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c index 0396d0ab4..67a125301 100644 --- a/grub-core/kern/emu/full.c +++ b/grub-core/kern/emu/full.c @@ -56,4 +56,12 @@ grub_arch_dl_get_tramp_size (const void *ehdr __attribute__ ((unused)), { return ~(grub_size_t)0; } + +grub_err_t +grub_arch_dl_allocate_gp (grub_dl_t mod __attribute__ ((unused)), + const void *ehdr __attribute__ ((unused))) +{ + return GRUB_ERR_BAD_MODULE; +} + #endif diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c index 24fa01b90..1fbe185b4 100644 --- a/grub-core/kern/ia64/dl.c +++ b/grub-core/kern/ia64/dl.c @@ -154,16 +154,13 @@ grub_arch_dl_get_tramp_size (const void *ehdr, unsigned sec) return cnt * sizeof (struct ia64_trampoline); } -/* Relocate symbols. */ grub_err_t -grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +grub_arch_dl_allocate_gp (grub_dl_t mod, const void *ehdr) { - Elf_Ehdr *e = ehdr; - Elf_Shdr *s; - Elf_Word entsize; - unsigned i; - grub_uint64_t *gp, *gpptr; grub_size_t gp_size = 0; + const Elf_Ehdr *e = ehdr; + const Elf_Shdr *s; + unsigned i; for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); i < e->e_shnum; @@ -199,10 +196,23 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) if (gp_size > MASK19) return grub_error (GRUB_ERR_OUT_OF_RANGE, "gp too big"); - gpptr = gp = grub_malloc (gp_size); - if (!gp) + mod->gp = grub_malloc (gp_size); + if (!mod->gp) return grub_errno; - mod->gp = (char *) gp; + return GRUB_ERR_NONE; +} + +/* Relocate symbols. */ +grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +{ + Elf_Ehdr *e = ehdr; + Elf_Shdr *s; + Elf_Word entsize; + unsigned i; + grub_uint64_t *gp, *gpptr; + + gp = gpptr = (grub_uint64_t *) mod->gp; /* Find a symbol table. */ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); diff --git a/include/grub/dl.h b/include/grub/dl.h index e04285280..c43c30ca7 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -124,6 +124,8 @@ void grub_arch_dl_init_linker (void); #ifdef __ia64__ grub_size_t grub_arch_dl_get_tramp_size (const void *ehdr, unsigned sec); +grub_err_t grub_arch_dl_allocate_gp (grub_dl_t mod, const void *ehdr); + #define GRUB_ARCH_DL_TRAMP_ALIGN 16 #else static inline grub_size_t @@ -131,6 +133,13 @@ grub_arch_dl_get_tramp_size (const void *ehdr __attribute__ ((unused)), int sec { return 0; } +static inline grub_err_t +grub_arch_dl_allocate_gp (grub_dl_t mod __attribute__ ((unused)), + const void *ehdr __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} + #define GRUB_ARCH_DL_TRAMP_ALIGN 1 #endif From bbbf84350e06a97de1254fa0866d317ab40c95a7 Mon Sep 17 00:00:00 2001 From: phcoder Date: Sun, 2 Jan 2011 19:20:28 +0100 Subject: [PATCH 135/406] Working hello.mod with extcmd.mod --- grub-core/kern/dl.c | 46 ++++++++----------- grub-core/kern/ia64/dl.c | 99 ++++++++++++++++++++++++++++------------ 2 files changed, 88 insertions(+), 57 deletions(-) diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 9dfff5287..0ccdbe03b 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -238,28 +238,32 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) { grub_dl_segment_t seg; grub_size_t tramp_size = 0; + grub_size_t alsize, align; seg = (grub_dl_segment_t) grub_malloc (sizeof (*seg)); if (! seg) return grub_errno; + alsize = s->sh_size; + align = s->sh_addralign; tramp_size = grub_arch_dl_get_tramp_size (e, i); - if (tramp_size && s->sh_addralign < GRUB_ARCH_DL_TRAMP_ALIGN) + if (tramp_size && align < GRUB_ARCH_DL_TRAMP_ALIGN) { - s->sh_addralign = GRUB_ARCH_DL_TRAMP_ALIGN; - s->sh_size = ALIGN_UP (s->sh_size, GRUB_ARCH_DL_TRAMP_ALIGN) + tramp_size; + align = GRUB_ARCH_DL_TRAMP_ALIGN; + alsize = ALIGN_UP (alsize, GRUB_ARCH_DL_TRAMP_ALIGN); } + alsize += tramp_size; #ifdef GRUB_MACHINE_EMU - if (s->sh_addralign < 8192) - s->sh_addralign = 8192; - s->sh_size = ALIGN_UP (s->sh_size, 8192); + if (align < 8192 * 16) + align = 8192 * 16; + alsize = ALIGN_UP (alsize, 8192 * 16); #endif - if (s->sh_size) + if (alsize) { void *addr; - addr = grub_memalign (s->sh_addralign, s->sh_size); + addr = grub_memalign (align, alsize); if (! addr) { grub_free (seg); @@ -279,7 +283,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) seg->addr = addr; #ifdef GRUB_MACHINE_EMU if (s->sh_flags & SHF_EXECINSTR) - mprotect (addr, s->sh_size, PROT_READ | PROT_WRITE | PROT_EXEC); + mprotect (addr, alsize, PROT_READ | PROT_WRITE | PROT_EXEC); #endif } else @@ -359,9 +363,8 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) case STT_FUNC: sym->st_value += (Elf_Addr) grub_dl_get_section_addr (mod, sym->st_shndx); - if (bind != STB_LOCAL) - { #ifdef __ia64__ + { /* FIXME: free descriptor once it's not used anymore. */ char **desc; desc = grub_malloc (2 * sizeof (char *)); @@ -371,10 +374,13 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) desc[1] = mod->gp; if (grub_dl_register_symbol (name, (void *) desc, mod)) return grub_errno; -#else + sym->st_value = (grub_addr_t) desc; + } +#endif + if (bind != STB_LOCAL) + { if (grub_dl_register_symbol (name, (void *) sym->st_value, mod)) return grub_errno; -#endif } if (grub_strcmp (name, "grub_mod_init") == 0) mod->init = sym->st_value; @@ -405,14 +411,7 @@ grub_dl_call_init (grub_dl_t mod) { if (mod->init) { -#ifndef __ia64__ ((void (*) (grub_dl_t)) mod->init) (mod); -#else - char *jmp[2]; - jmp[0] = (char *) mod->init; - jmp[1] = mod->gp; - ((void (*) (grub_dl_t)) jmp) (mod); -#endif } } @@ -678,14 +677,7 @@ grub_dl_unload (grub_dl_t mod) if (mod->fini) { -#ifndef __ia64__ ((void (*) (void)) mod->fini) (); -#else - char *jmp[2]; - jmp[0] = (char *) mod->fini; - jmp[1] = mod->gp; - ((void (*) (void)) jmp) (); -#endif } grub_dl_remove (mod); diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c index 1fbe185b4..55b50ff69 100644 --- a/grub-core/kern/ia64/dl.c +++ b/grub-core/kern/ia64/dl.c @@ -41,23 +41,62 @@ grub_arch_dl_check_header (void *ehdr) #define MASK20 ((1 << 20) - 1) #define MASK19 ((1 << 19) - 1) -static void -add_value_to_slot13_20 (Elf_Word *addr, grub_uint32_t value, int slot) +struct unaligned_uint32 { - grub_uint32_t *p __attribute__ ((aligned (1))); - switch (slot) + grub_uint32_t val; +} __attribute__ ((packed)); + +static void +add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value) +{ + struct unaligned_uint32 *p; + switch (addr & 3) { case 0: - p = (grub_uint32_t *) (addr + 2); - *p = (((((*p >> 2) & MASK20) + value) & MASK20) << 2) | (*p & ~(MASK20 << 2)); + p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2); + p->val = (((((p->val >> 2) & MASK20) + value) & MASK20) << 2) | (p->val & ~(MASK20 << 2)); break; case 1: - p = (grub_uint32_t *) ((grub_uint8_t *) addr + 7); - *p = (((((*p >> 3) & MASK20) + value) & MASK20) << 3) | (*p & ~(MASK20 << 3)); + p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 7); + p->val = (((((p->val >> 3) & MASK20) + value) & MASK20) << 3) | (p->val & ~(MASK20 << 3)); break; case 2: - p = (grub_uint32_t *) ((grub_uint8_t *) addr + 12); - *p = (((((*p >> 4) & MASK20) + value) & MASK20) << 4) | (*p & ~(MASK20 << 4)); + p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 12); + p->val = (((((p->val >> 4) & MASK20) + value) & MASK20) << 4) | (p->val & ~(MASK20 << 4)); + break; + } +} + +#define MASKF21 ( ((1 << 23) - 1) & ~((1 << 7) | (1 << 8)) ) + +static grub_uint32_t +add_value_to_slot_21_real (grub_uint32_t a, grub_uint32_t value) +{ + grub_uint32_t high, mid, low, c; + low = (a & 0x00007f); + mid = (a & 0x7fc000) >> 7; + high = (a & 0x003e00) << 5; + c = (low | mid | high) + value; + return (c & 0x7f) | ((c << 7) & 0x7fc000) | ((c >> 5) & 0x003e00); +} + +static void +add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value) +{ + struct unaligned_uint32 *p; + switch (addr & 3) + { + case 0: + p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2); + p->val = ((add_value_to_slot_21_real (((p->val >> 2) & MASKF21), value) & MASKF21) << 2) | (p->val & ~(MASKF21 << 2)); + break; + case 1: + p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 7); + p->val = ((add_value_to_slot_21_real (((p->val >> 3) & MASKF21), value) & MASKF21) << 3) | (p->val & ~(MASKF21 << 3)); + break; + case 2: + p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 12); + p->val = ((add_value_to_slot_21_real (((p->val >> 4) & MASKF21), value) & MASKF21) << 4) | (p->val & ~(MASKF21 << 4)); break; } } @@ -147,8 +186,8 @@ grub_arch_dl_get_tramp_size (const void *ehdr, unsigned sec) for (rel = (Elf_Rela *) ((char *) e + s->sh_offset), max = rel + s->sh_size / s->sh_entsize; rel < max; rel++) - if (ELF_R_TYPE (rel->r_info) == R_IA64_PCREL21B) - cnt++; + if (ELF_R_TYPE (rel->r_info) == R_IA64_PCREL21B) + cnt++; } return cnt * sizeof (struct ia64_trampoline); @@ -165,7 +204,7 @@ grub_arch_dl_allocate_gp (grub_dl_t mod, const void *ehdr) for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); i < e->e_shnum; i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_REL) + if (s->sh_type == SHT_RELA) { grub_dl_segment_t seg; @@ -176,16 +215,18 @@ grub_arch_dl_allocate_gp (grub_dl_t mod, const void *ehdr) if (seg) { - Elf_Rel *rel, *max; + Elf_Rela *rel, *max; - for (rel = (Elf_Rel *) ((char *) e + s->sh_offset), + for (rel = (Elf_Rela *) ((char *) e + s->sh_offset), max = rel + s->sh_size / s->sh_entsize; rel < max; rel++) switch (ELF_R_TYPE (rel->r_info)) { + case R_IA64_LTOFF_FPTR22: case R_IA64_LTOFF22X: case R_IA64_LTOFF22: + case R_IA64_GPREL22: gp_size += 8; break; default: break; @@ -243,29 +284,22 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) Elf_Rela *rel, *max; struct ia64_trampoline *tr; + tr = (void *) ((char *) seg->addr + ALIGN_UP (seg->size, GRUB_ARCH_DL_TRAMP_ALIGN)); + for (rel = (Elf_Rela *) ((char *) e + s->sh_offset), max = rel + s->sh_size / s->sh_entsize; rel < max; rel++) { - Elf_Word *addr; + grub_addr_t addr; Elf_Sym *sym; grub_uint64_t value; - int slot = 0; if (seg->size < (rel->r_offset & ~3)) return grub_error (GRUB_ERR_BAD_MODULE, "reloc offset is out of the segment"); - tr = (void *) ((char *) seg->addr + ALIGN_UP (seg->size, GRUB_ARCH_DL_TRAMP_ALIGN)); - - if (ELF_R_TYPE (rel->r_info) == R_IA64_PCREL21B) - { - addr = (Elf_Word *) ((char *) seg->addr + (rel->r_offset & ~3)); - slot = rel->r_offset & 3; - } - else - addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset); + addr = (grub_addr_t) seg->addr + rel->r_offset; sym = (Elf_Sym *) ((char *) mod->symtab + entsize * ELF_R_SYM (rel->r_info)); @@ -278,21 +312,26 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) { grub_uint64_t noff; make_trampoline (tr, value); - noff = ((char *) tr - (char *) addr) >> 4; + noff = ((char *) tr - (char *) (addr & ~3)) >> 4; tr++; if (noff & ~MASK19) return grub_error (GRUB_ERR_BAD_OS, - "trampoline offset too big"); - add_value_to_slot13_20 (addr, noff, slot); + "trampoline offset too big (%lx)", noff); + add_value_to_slot_20b (addr, noff); } break; case R_IA64_SEGREL64LSB: *(grub_uint64_t *) addr += value - rel->r_offset; break; + case R_IA64_DIR64LSB: + *(grub_uint64_t *) addr += value; + break; + case R_IA64_LTOFF_FPTR22: case R_IA64_LTOFF22X: case R_IA64_LTOFF22: + case R_IA64_GPREL22: *gpptr = value; - add_value_to_slot13_20 (addr, (gpptr - gp) * sizeof (grub_uint64_t), slot); + add_value_to_slot_21 (addr, (gpptr - gp) * sizeof (grub_uint64_t)); gpptr++; break; From f49157dfe52bc95640645080f228cccd69ff72a5 Mon Sep 17 00:00:00 2001 From: phcoder Date: Sun, 2 Jan 2011 23:30:25 +0100 Subject: [PATCH 136/406] Restructure module loading and many fixes. Now normal.mod loads successfully --- grub-core/kern/dl.c | 83 +++++++++++++++++++----------- grub-core/kern/emu/full.c | 15 ++---- grub-core/kern/ia64/dl.c | 105 +++++++++++++------------------------- include/grub/dl.h | 22 +++----- 4 files changed, 99 insertions(+), 126 deletions(-) diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 0ccdbe03b..787fcfad0 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -229,6 +229,46 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) { unsigned i; Elf_Shdr *s; + grub_size_t tsize = 0, talign = 1; +#ifdef __ia64__ + grub_size_t tramp; + grub_size_t got; +#endif + char *ptr; + + for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize)) + { + tsize += ALIGN_UP (s->sh_size, s->sh_addralign); + if (talign < s->sh_addralign) + talign = s->sh_addralign; + } + +#ifdef __ia64__ + grub_arch_dl_get_tramp_got_size (e, &tramp, &got); + tsize += ALIGN_UP (tramp, GRUB_ARCH_DL_TRAMP_ALIGN); + if (talign < GRUB_ARCH_DL_TRAMP_ALIGN) + talign = GRUB_ARCH_DL_TRAMP_ALIGN; + tsize += ALIGN_UP (got, GRUB_ARCH_DL_GOT_ALIGN); + if (talign < GRUB_ARCH_DL_GOT_ALIGN) + talign = GRUB_ARCH_DL_GOT_ALIGN; +#endif + +#ifdef GRUB_MACHINE_EMU + if (talign < 8192 * 16) + talign = 8192 * 16; + tsize = ALIGN_UP (tsize, 8192 * 16); +#endif + + mod->base = grub_memalign (talign, tsize); + if (!mod->base) + return grub_errno; + ptr = mod->base; + +#ifdef GRUB_MACHINE_EMU + mprotect (mod->base, tsize, PROT_READ | PROT_WRITE | PROT_EXEC); +#endif for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff); i < e->e_shnum; @@ -237,38 +277,18 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) if (s->sh_flags & SHF_ALLOC) { grub_dl_segment_t seg; - grub_size_t tramp_size = 0; - grub_size_t alsize, align; seg = (grub_dl_segment_t) grub_malloc (sizeof (*seg)); if (! seg) return grub_errno; - alsize = s->sh_size; - align = s->sh_addralign; - tramp_size = grub_arch_dl_get_tramp_size (e, i); - if (tramp_size && align < GRUB_ARCH_DL_TRAMP_ALIGN) - { - align = GRUB_ARCH_DL_TRAMP_ALIGN; - alsize = ALIGN_UP (alsize, GRUB_ARCH_DL_TRAMP_ALIGN); - } - alsize += tramp_size; -#ifdef GRUB_MACHINE_EMU - if (align < 8192 * 16) - align = 8192 * 16; - alsize = ALIGN_UP (alsize, 8192 * 16); -#endif - - if (alsize) + if (s->sh_size) { void *addr; - addr = grub_memalign (align, alsize); - if (! addr) - { - grub_free (seg); - return grub_errno; - } + ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, s->sh_addralign); + addr = ptr; + ptr += s->sh_size; switch (s->sh_type) { @@ -281,10 +301,6 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) } seg->addr = addr; -#ifdef GRUB_MACHINE_EMU - if (s->sh_flags & SHF_EXECINSTR) - mprotect (addr, alsize, PROT_READ | PROT_WRITE | PROT_EXEC); -#endif } else seg->addr = 0; @@ -295,6 +311,14 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) mod->segment = seg; } } +#ifdef __ia64__ + ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_TRAMP_ALIGN); + mod->tramp = ptr; + ptr += tramp; + ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_GOT_ALIGN); + mod->got = ptr; + ptr += got; +#endif return GRUB_ERR_NONE; } @@ -371,7 +395,7 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) if (!desc) return grub_errno; desc[0] = (void *) sym->st_value; - desc[1] = mod->gp; + desc[1] = mod->base; if (grub_dl_register_symbol (name, (void *) desc, mod)) return grub_errno; sym->st_value = (grub_addr_t) desc; @@ -564,7 +588,6 @@ grub_dl_load_core (void *addr, grub_size_t size) if (grub_dl_resolve_name (mod, e) || grub_dl_resolve_dependencies (mod, e) || grub_dl_load_segments (mod, e) - || grub_arch_dl_allocate_gp (mod, e) || grub_dl_resolve_symbols (mod, e) || grub_arch_dl_relocate_symbols (mod, e)) { diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c index 67a125301..80edb991e 100644 --- a/grub-core/kern/emu/full.c +++ b/grub-core/kern/emu/full.c @@ -50,18 +50,11 @@ grub_emu_init (void) } #ifdef __ia64__ -grub_size_t -grub_arch_dl_get_tramp_size (const void *ehdr __attribute__ ((unused)), - unsigned sec __attribute__ ((unused))) +void grub_arch_dl_get_tramp_got_size (const void *ehdr __attribute__ ((unused)), + grub_size_t *tramp, grub_size_t *got) { - return ~(grub_size_t)0; -} - -grub_err_t -grub_arch_dl_allocate_gp (grub_dl_t mod __attribute__ ((unused)), - const void *ehdr __attribute__ ((unused))) -{ - return GRUB_ERR_BAD_MODULE; + *tramp = 0; + *got = 0; } #endif diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c index 55b50ff69..9bbebcd2f 100644 --- a/grub-core/kern/ia64/dl.c +++ b/grub-core/kern/ia64/dl.c @@ -75,9 +75,9 @@ add_value_to_slot_21_real (grub_uint32_t a, grub_uint32_t value) grub_uint32_t high, mid, low, c; low = (a & 0x00007f); mid = (a & 0x7fc000) >> 7; - high = (a & 0x003e00) << 5; + high = (a & 0x003e00) << 7; c = (low | mid | high) + value; - return (c & 0x7f) | ((c << 7) & 0x7fc000) | ((c >> 5) & 0x003e00); + return (c & 0x7f) | ((c << 7) & 0x7fc000) | ((c >> 7) & 0x0003e00); //0x003e00 } static void @@ -138,7 +138,7 @@ static void make_trampoline (struct ia64_trampoline *tr, grub_uint64_t addr) { grub_memcpy (tr->nop, nopm, sizeof (tr->nop)); - tr->addr_hi[0] = ((addr & 0xc00000) >> 18); + tr->addr_hi[0] = ((addr & 0xc00000) >> 16); tr->addr_hi[1] = (addr >> 24) & 0xff; tr->addr_hi[2] = (addr >> 32) & 0xff; tr->addr_hi[3] = (addr >> 40) & 0xff; @@ -152,11 +152,11 @@ make_trampoline (struct ia64_trampoline *tr, grub_uint64_t addr) grub_memcpy (tr->jump, jump, sizeof (tr->jump)); } -grub_size_t -grub_arch_dl_get_tramp_size (const void *ehdr, unsigned sec) +void +grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, grub_size_t *got) { const Elf_Ehdr *e = ehdr; - int cnt = 0; + grub_size_t cntt = 0, cntg = 0;; const Elf_Shdr *s; Elf_Word entsize; unsigned i; @@ -169,7 +169,7 @@ grub_arch_dl_get_tramp_size (const void *ehdr, unsigned sec) break; if (i == e->e_shnum) - return 0; + return; entsize = s->sh_entsize; @@ -180,68 +180,25 @@ grub_arch_dl_get_tramp_size (const void *ehdr, unsigned sec) { Elf_Rela *rel, *max; - if (s->sh_info != sec) - continue; - for (rel = (Elf_Rela *) ((char *) e + s->sh_offset), max = rel + s->sh_size / s->sh_entsize; rel < max; rel++) - if (ELF_R_TYPE (rel->r_info) == R_IA64_PCREL21B) - cnt++; + switch (ELF_R_TYPE (rel->r_info)) + { + case R_IA64_PCREL21B: + cntt++; + break; + case R_IA64_LTOFF_FPTR22: + case R_IA64_LTOFF22X: + case R_IA64_LTOFF22: + cntg++; + break; + } } - - return cnt * sizeof (struct ia64_trampoline); + *tramp = cntt * sizeof (struct ia64_trampoline); + *got = cntg * sizeof (grub_uint64_t); } -grub_err_t -grub_arch_dl_allocate_gp (grub_dl_t mod, const void *ehdr) -{ - grub_size_t gp_size = 0; - const Elf_Ehdr *e = ehdr; - const Elf_Shdr *s; - unsigned i; - - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_RELA) - { - grub_dl_segment_t seg; - - /* Find the target segment. */ - for (seg = mod->segment; seg; seg = seg->next) - if (seg->section == s->sh_info) - break; - - if (seg) - { - Elf_Rela *rel, *max; - - for (rel = (Elf_Rela *) ((char *) e + s->sh_offset), - max = rel + s->sh_size / s->sh_entsize; - rel < max; - rel++) - switch (ELF_R_TYPE (rel->r_info)) - { - case R_IA64_LTOFF_FPTR22: - case R_IA64_LTOFF22X: - case R_IA64_LTOFF22: - case R_IA64_GPREL22: - gp_size += 8; - break; - default: break; - } - } - } - - if (gp_size > MASK19) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "gp too big"); - - mod->gp = grub_malloc (gp_size); - if (!mod->gp) - return grub_errno; - return GRUB_ERR_NONE; -} /* Relocate symbols. */ grub_err_t @@ -252,8 +209,11 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) Elf_Word entsize; unsigned i; grub_uint64_t *gp, *gpptr; + struct ia64_trampoline *tr; - gp = gpptr = (grub_uint64_t *) mod->gp; + gp = (grub_uint64_t *) mod->base; + gpptr = (grub_uint64_t *) mod->got; + tr = mod->tramp; /* Find a symbol table. */ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); @@ -282,9 +242,6 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) if (seg) { Elf_Rela *rel, *max; - struct ia64_trampoline *tr; - - tr = (void *) ((char *) seg->addr + ALIGN_UP (seg->size, GRUB_ARCH_DL_TRAMP_ALIGN)); for (rel = (Elf_Rela *) ((char *) e + s->sh_offset), max = rel + s->sh_size / s->sh_entsize; @@ -306,6 +263,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) /* On the PPC the value does not have an explicit addend, add it. */ value = sym->st_value + rel->r_addend; + switch (ELF_R_TYPE (rel->r_info)) { case R_IA64_PCREL21B: @@ -323,15 +281,24 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) case R_IA64_SEGREL64LSB: *(grub_uint64_t *) addr += value - rel->r_offset; break; + case R_IA64_FPTR64LSB: case R_IA64_DIR64LSB: *(grub_uint64_t *) addr += value; break; + case R_IA64_PCREL64LSB: + *(grub_uint64_t *) addr += value - addr; + break; + case R_IA64_GPREL22: + add_value_to_slot_21 (addr, value - (grub_addr_t) gp); + break; + case R_IA64_LTOFF_FPTR22: case R_IA64_LTOFF22X: case R_IA64_LTOFF22: - case R_IA64_GPREL22: *gpptr = value; - add_value_to_slot_21 (addr, (gpptr - gp) * sizeof (grub_uint64_t)); + if ((addr & 0xffff) == 0x4301) + grub_dprintf ("modules", "off = %lx\n", (grub_addr_t) gpptr - (grub_addr_t) gp); + add_value_to_slot_21 (addr, (grub_addr_t) gpptr - (grub_addr_t) gp); gpptr++; break; diff --git a/include/grub/dl.h b/include/grub/dl.h index c43c30ca7..b57c3ae87 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -93,8 +93,10 @@ struct grub_dl grub_addr_t init; grub_addr_t fini; #ifdef __ia64__ - char *gp; + void *got; + void *tramp; #endif + void *base; struct grub_dl *next; }; typedef struct grub_dl *grub_dl_t; @@ -123,24 +125,12 @@ void grub_arch_dl_init_linker (void); #endif #ifdef __ia64__ -grub_size_t grub_arch_dl_get_tramp_size (const void *ehdr, unsigned sec); -grub_err_t grub_arch_dl_allocate_gp (grub_dl_t mod, const void *ehdr); +void grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, grub_size_t *got); #define GRUB_ARCH_DL_TRAMP_ALIGN 16 -#else -static inline grub_size_t -grub_arch_dl_get_tramp_size (const void *ehdr __attribute__ ((unused)), int sec __attribute__ ((unused))) -{ - return 0; -} -static inline grub_err_t -grub_arch_dl_allocate_gp (grub_dl_t mod __attribute__ ((unused)), - const void *ehdr __attribute__ ((unused))) -{ - return GRUB_ERR_NONE; -} +#define GRUB_ARCH_DL_GOT_ALIGN 16 -#define GRUB_ARCH_DL_TRAMP_ALIGN 1 +#else #endif From 0a2b2cdc95d1a8677fec66df81d48db88a2546f7 Mon Sep 17 00:00:00 2001 From: phcoder Date: Mon, 3 Jan 2011 00:30:26 +0100 Subject: [PATCH 137/406] Fix autogen --- grub-core/Makefile.core.def | 37 +---------------------- grub-core/kern/emu/{cache.S => cache_s.S} | 0 2 files changed, 1 insertion(+), 36 deletions(-) rename grub-core/kern/emu/{cache.S => cache_s.S} (100%) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 8f988b0be..ff5bf7a30 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -173,7 +173,7 @@ kernel = { emu = disk/host.c; emu = gnulib/progname.c; emu = gnulib/error.c; - emu = kern/emu/cache.S; + emu = kern/emu/cache_s.S; emu = kern/emu/console.c; emu = kern/emu/getroot.c; emu = kern/emu/hostdisk.c; @@ -463,41 +463,6 @@ module = { enable = i386_multiboot; }; -module = { - name = lsacpi; - - common = commands/lsacpi.c; - - enable = efi; - enable = i386_pc; - enable = i386_coreboot; - enable = i386_multiboot; -}; - -module = { - name = lsefisystab; - - common = commands/efi/lsefisystab.c; - - enable = efi; -}; - -module = { - name = lssal; - - common = commands/efi/lssal.c; - - enable = efi; -}; - -module = { - name = lsefimmap; - - common = commands/efi/lsefimmap.c; - - enable = efi; -}; - module = { name = lsacpi; diff --git a/grub-core/kern/emu/cache.S b/grub-core/kern/emu/cache_s.S similarity index 100% rename from grub-core/kern/emu/cache.S rename to grub-core/kern/emu/cache_s.S From 5faa440cb00186819dd2af2fca42fe4f9eb4d608 Mon Sep 17 00:00:00 2001 From: phcoder Date: Mon, 3 Jan 2011 00:47:21 +0100 Subject: [PATCH 138/406] Discard several spurious differences from mainline --- grub-core/kern/dl.c | 25 ------------------------- grub-core/kern/main.c | 2 +- include/grub/dl.h | 4 ++-- 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 7727745e8..787fcfad0 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -611,31 +611,6 @@ grub_dl_load_core (void *addr, grub_size_t size) return mod; } -#ifdef __ia64__ -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 = (char *) 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); -} -#endif - /* Load a module from the file FILENAME. */ grub_dl_t grub_dl_load_file (const char *filename) diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index 24593e3c0..3474ed3bb 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -159,7 +159,7 @@ static void grub_load_normal_mode (void) { /* Load the module. */ -// grub_dl_load ("normal"); + grub_dl_load ("normal"); /* Something went wrong. Print errors here to let user know why we're entering rescue mode. */ grub_print_error (); diff --git a/include/grub/dl.h b/include/grub/dl.h index fcf5bb620..a5e5c3332 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -34,9 +34,9 @@ #ifndef GRUB_MOD_INIT #define GRUB_MOD_INIT(name) \ static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \ -void grub_##name##_init (grub_dl_t); \ +void grub_##name##_init (void); \ void \ -grub_##name##_init (grub_dl_t mod) { grub_mod_init (mod); } \ +grub_##name##_init (void) { grub_mod_init (0); } \ static void \ grub_mod_init (grub_dl_t mod __attribute__ ((unused))) #endif From 0718f66d12275a940f8cf882d24aec2a48f17f99 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 3 Jan 2011 00:56:28 +0100 Subject: [PATCH 139/406] Discard a bunch of junk code --- grub-core/kern/dl.c | 20 +- grub-core/kern/main.c | 2 - grub-core/kern/mm.c | 2 +- include/grub/dl.h | 4 +- include/grub/ia64/efi/misc.h | 27 -- util/ia64/efi/elf2pe.c | 812 ---------------------------------- util/ia64/efi/grub-install.in | 233 ---------- util/ia64/efi/pe32.h | 237 ---------- 8 files changed, 10 insertions(+), 1327 deletions(-) delete mode 100644 include/grub/ia64/efi/misc.h delete mode 100644 util/ia64/efi/elf2pe.c delete mode 100644 util/ia64/efi/grub-install.in delete mode 100644 util/ia64/efi/pe32.h diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 787fcfad0..f871b81a1 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -402,14 +402,12 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) } #endif if (bind != STB_LOCAL) - { - if (grub_dl_register_symbol (name, (void *) sym->st_value, mod)) - return grub_errno; - } + if (grub_dl_register_symbol (name, (void *) sym->st_value, mod)) + return grub_errno; if (grub_strcmp (name, "grub_mod_init") == 0) - mod->init = sym->st_value; + mod->init = (void (*) (grub_dl_t)) sym->st_value; else if (grub_strcmp (name, "grub_mod_fini") == 0) - mod->fini = sym->st_value; + mod->fini = (void (*) (void)) sym->st_value; break; case STT_SECTION: @@ -434,9 +432,7 @@ static void grub_dl_call_init (grub_dl_t mod) { if (mod->init) - { - ((void (*) (grub_dl_t)) mod->init) (mod); - } + (mod->init) (mod); } static grub_err_t @@ -599,7 +595,7 @@ grub_dl_load_core (void *addr, grub_size_t size) grub_dl_flush_cache (mod); grub_dprintf ("modules", "module name: %s\n", mod->name); - grub_dprintf ("modules", "init function: %" PRIxGRUB_ADDR "\n", mod->init); + grub_dprintf ("modules", "init function: %p\n", mod->init); grub_dl_call_init (mod); if (grub_dl_add (mod)) @@ -699,9 +695,7 @@ grub_dl_unload (grub_dl_t mod) return 0; if (mod->fini) - { - ((void (*) (void)) mod->fini) (); - } + (mod->fini) (); grub_dl_remove (mod); grub_dl_unregister_symbols (mod); diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index 3474ed3bb..8b6c8a180 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -76,7 +76,6 @@ grub_modules_get_end (void) static void grub_load_modules (void) { -#if 0 auto int hook (struct grub_module_header *); int hook (struct grub_module_header *header) { @@ -95,7 +94,6 @@ grub_load_modules (void) } grub_module_iterate (hook); -#endif } static void diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c index bd489e22c..8d9b5db78 100644 --- a/grub-core/kern/mm.c +++ b/grub-core/kern/mm.c @@ -313,7 +313,7 @@ grub_memalign (grub_size_t align, grub_size_t size) case 1: /* Unload unneeded modules. */ -// grub_dl_unload_unneeded (); + grub_dl_unload_unneeded (); count++; goto again; diff --git a/include/grub/dl.h b/include/grub/dl.h index a5e5c3332..b45928a76 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -92,8 +92,8 @@ struct grub_dl grub_dl_dep_t dep; grub_dl_segment_t segment; Elf_Sym *symtab; - grub_addr_t init; - grub_addr_t fini; + void (*init) (struct grub_dl *mod); + void (*fini) (void); #ifdef __ia64__ void *got; void *tramp; diff --git a/include/grub/ia64/efi/misc.h b/include/grub/ia64/efi/misc.h deleted file mode 100644 index 4f9c69e32..000000000 --- a/include/grub/ia64/efi/misc.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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 (__ia64_trampoline) (void); -void EXPORT_FUNC (grub_init_modules) (void); - -void -grub_init_module (const char *name, - void (*init)(grub_dl_t), void (*fini)(void)); - -extern unsigned long EXPORT_VAR (__gp); - diff --git a/util/ia64/efi/elf2pe.c b/util/ia64/efi/elf2pe.c deleted file mode 100644 index 66d28bde8..000000000 --- a/util/ia64/efi/elf2pe.c +++ /dev/null @@ -1,812 +0,0 @@ -/* 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(ELF2PE_I386) -#define USE_ELF32 -#define USE_PE32 -#define ELF_MACHINE EM_386 -#define EFI_MACHINE PE32_MACHINE_I386 -#elif defined(ELF2PE_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 ELF2PE_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 ELF2PE_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 ELF2PE_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 ELF2PE_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 ELF2PE_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 ELF2PE_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 ELF2PE_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 ELF2PE_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 ELF2PE_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 ELF2PE_IA64 - *(uint64_t*)(coff_file + coff_entry_descr_offset) = coff_entry_descr_func; - *(uint64_t*)(coff_file + coff_entry_descr_offset + 8) = plt_base; -#endif - - if (write_sections (is_data_shdr) != 0) - return -4; - - /* Translate and write relocations. */ - if (write_relocations () != 0) - return -5; - - /* Write debug info. */ - write_debug (); - - nt_hdr = (struct pe32_nt_header *)(coff_file + nt_hdr_offset); - nt_hdr->optional_header.image_size = coff_offset; - - nt_hdr->optional_header.subsystem = PE32_SUBSYSTEM_EFI_APPLICATION; - - /* Replace. */ - free (*file_buffer); - *file_buffer = coff_file; - *file_length = coff_offset; - - return 0; -} - -int -main (int argc, char **argv) -{ - FILE *f; - unsigned int size; - uint8_t *buffer; - const char *outfile; - int status; - - if (argc != 3) - { - fprintf (stderr, "usage: %s elf-file pe-file\n", argv[0]); - exit (1); - } - - filename = argv[1]; - outfile = argv[2]; - f = fopen (filename, "rb"); - fseek (f, 0, SEEK_END); - size = ftell (f); - fseek (f, 0, SEEK_SET); - - buffer = malloc (size); - if (buffer == NULL) - { - fprintf (stderr, "cannot allocate %u bytes of memory\n", size); - exit (2); - } - if (fread (buffer, size, 1, f) != 1) - { - fprintf (stderr, "cannot read %s\n", filename); - exit (2); - } - fclose (f); - - if (!is_elf_header (buffer)) - { - fprintf (stderr, "%s is not an elf file\n", filename); - exit (2); - } - - status = convert_elf (&buffer, &size); - if (status != 0) - { - fprintf (stderr, "cannot convert %s to pe (err=%d)\n", filename, status); - exit (2); - } - - f = fopen (outfile, "wb"); - if (f == NULL) - { - fprintf (stderr, "cannot open %s\n", outfile); - exit (2); - } - if (fwrite (buffer, size, 1, f) != 1) - { - fprintf (stderr, "cannot write to %s\n", outfile); - exit (2); - } - fclose (f); - - return 0; -} diff --git a/util/ia64/efi/grub-install.in b/util/ia64/efi/grub-install.in deleted file mode 100644 index 63b0c9f6c..000000000 --- a/util/ia64/efi/grub-install.in +++ /dev/null @@ -1,233 +0,0 @@ -#! /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. -prefix=@prefix@ -exec_prefix=@exec_prefix@ -sbindir=@sbindir@ -bindir=@bindir@ -libdir=@libdir@ -datadir=@datadir@ -PACKAGE_NAME=@PACKAGE_NAME@ -PACKAGE_TARNAME=@PACKAGE_TARNAME@ -PACKAGE_VERSION=@PACKAGE_VERSION@ -target_cpu=@target_cpu@ -platform=@platform@ -pkglibdir=${libdir}/${PACKAGE_TARNAME}/${target_cpu}-${platform} -pkgdatadir=${datadir}/${PACKAGE_TARNAME} - - -TARGET_CC=@TARGET_CC@ -TARGET_CFLAGS="@TARGET_CFLAGS@" -TARGET_CPPFLAGS="@TARGET_CPPFLAGS@" -TARGET_LDFLAGS="@TARGET_LDFLAGS@" -OBJCOPY=@OBJCOPY@ - -grub_setup=${sbindir}/grub-setup -grub_mkimage=${bindir}/grub-mkimage -grub_mkdevicemap=${sbindir}/grub-mkdevicemap -grub_probefs=${sbindir}/grub-probefs -rootdir= -grub_prefix=/boot/grub -modules= - -install_device= -recheck=no -debug=no - -# Usage: usage -# Print the usage. -usage () { - cat <. -EOF -} - -# Check the arguments. -for option in "$@"; do - case "$option" in - -h | --help) - usage - exit 0 ;; - -v | --version) - echo "grub-install (GNU GRUB ${PACKAGE_VERSION})" - exit 0 ;; - --modules=*) - modules=`echo "$option" | sed 's/--modules=//'` ;; - --root-directory=*) - rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; - --grub-setup=*) - grub_setup=`echo "$option" | sed 's/--grub-setup=//'` ;; - --grub-mkimage=*) - grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; - --grub-mkdevicemap=*) - grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;; - --grub-probefs=*) - grub_probefs=`echo "$option" | sed 's/--grub-probefs=//'` ;; - --pkglibdir=*) - pkglibdir=`echo "$option" | sed 's/--pkglibdir=//'` ;; - --pkgdatadir=*) - pkgdatadir=`echo "$option" | sed 's/--pkgdatadir=//'` ;; - --recheck) - recheck=yes ;; - # This is an undocumented feature... - --debug) - debug=yes ;; - -*) - echo "Unrecognized option \`$option'" 1>&2 - usage - exit 1 - ;; - *) - if test "x$install_device" != x; then - echo "More than one install_devices?" 1>&2 - usage - exit 1 - fi - install_device="${option}" ;; - esac -done - -#if test "x$install_device" = x; then -# echo "install_device not specified." 1>&2 -# usage -# exit 1 -#fi - -# If the debugging feature is enabled, print commands. -if test $debug = yes; then - set -x -fi - -# Initialize these directories here, since ROOTDIR was initialized. -bootdir=${rootdir}/boot/efi - -grubdir=${bootdir}/grub -device_map=${grubdir}/device.map - -# Create the GRUB directory if it is not present. -test -d "$bootdir" || mkdir "$bootdir" || exit 1 -test -d "$grubdir" || mkdir "$grubdir" || exit 1 - -# Copy the GRUB images to the GRUB directory. -if false; then - for file in ${grubdir}/*.mod ${grubdir}/*.lst; do - if test -f $file; then - rm -f $file || exit 1 - fi - done - for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst; do - cp -f $file ${grubdir} || exit 1 - done -fi - -# Create the core image. First, auto-detect the filesystme module. -#fs_module=`$grub_probefs --device-map=${device_map} ${grubdir}` -#if test "x$fs_module" = x -a "x$modules" = x; then -# echo "Auto-detection of a filesystem module failed." 1>&2 -# echo "Please specify the module with the option \`--modules' explicitly." 1>&2 -# exit 1 -#fi - -# Typically, _chain and pc are required. -modules="$modules $fs_module _chain" - -modules="kernel gzio gpt fat normal ls cat fshelp help _linux linux $modules" -modules="$modules memmap systab boot" - -if [ $debug = yes ]; then - tmpdir=. -else - tmpdir=`mktemp -d /tmp/grub.XXXXXXXXXX` || exit 1 - trap "rm -rf $tmpdir" 1 2 13 15 -fi - -# Generate init/fini for modules. -modfile=$tmpdir/mod.c -echo "/* Dummy modules. */" > $modfile -list="" -init_list="" -fini_list="" -for m in $modules; do - file="$pkglibdir/${m}.mod" - name=`nm $file | sed -n "/ r grub_module_name/ s/.* r grub_module_name_\(.*\)/\1/p"` - init=`nm $file | sed -n "/ T grub_module_.*_init/ s/.* T //p"` - fini=`nm $file | sed -n "/ T grub_module_.*_fini/ s/.* T //p"` - init_list="$init_list $init" - fini_list="$fini_list $fini" - arg="\"$name\",${init:-0},${fini:-0}" - list="$list $arg" -done -echo "extern void grub_init_module (const char *, void (*init)(void *), void (*fini)(void));" >> $modfile -echo "extern void grub_init_modules (void);" >> $modfile -for m in $init_list; do - echo "extern void $m(void *);" >> $modfile -done -for m in $fini_list; do - echo "extern void $m(void);" >> $modfile -done -echo "void grub_init_modules (void)" >> $modfile -echo "{" >> $modfile -for m in $list; do - echo " grub_init_module($m);" >> $modfile -done -echo "}" >> $modfile - -$TARGET_CC -c $TARGET_CFLAGS -o $tmpdir/mod.o $modfile - -mod_objs= -for m in $modules; do mod_objs="$mod_objs $pkglibdir/${m}.mod"; done - -ld -pie -nostdlib -T $pkgdatadir/elf_ia64_efi.lds \ - $mod_objs $tmpdir/mod.o -o $tmpdir/grub.elf - - -if ! $bindir/grub-elf2pe $tmpdir/grub.elf $grubdir/grub.efi; then - echo "Failed to build efi binary" - [ $debug = no ] && rm -rf $tmpdir - exit 1 -fi - -echo "grub.efi generated" - -[ $debug = no ] && rm -rf $tmpdir - -# Bye. -exit 0 diff --git a/util/ia64/efi/pe32.h b/util/ia64/efi/pe32.h deleted file mode 100644 index 391e70c26..000000000 --- a/util/ia64/efi/pe32.h +++ /dev/null @@ -1,237 +0,0 @@ -/* 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 - From c18271ed0042a870b84476b6b20241e884ed5792 Mon Sep 17 00:00:00 2001 From: phcoder Date: Mon, 3 Jan 2011 02:28:14 +0100 Subject: [PATCH 140/406] Fix compilation errors --- grub-core/Makefile.am | 1 - grub-core/Makefile.core.def | 9 ++++++--- grub-core/kern/ia64/efi/init.c | 2 -- grub-core/kern/ia64/efi/startup.S | 13 +++++++++++++ grub-core/lib/efi/halt.c | 2 ++ grub-core/loader/ia64/efi/linux.c | 7 +++---- include/grub/efi/api.h | 2 +- include/grub/offsets.h | 6 ++++++ 8 files changed, 31 insertions(+), 11 deletions(-) diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 5481d9ebb..df691a586 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -130,7 +130,6 @@ if COND_ia64_efi KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/time.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ia64/efi/misc.h endif if COND_mips_yeeloong diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index ff5bf7a30..4581b79cf 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -126,8 +126,8 @@ kernel = { x86_64_efi = kern/i386/efi/init.c; ia64_efi = kern/ia64/efi/startup.S; - ia64_efi = kern/ia64/trampoline.S; ia64_efi = kern/ia64/efi/init.c; + ia64_efi = kern/ia64/dl.c; i386_pc = kern/i386/pc/init.c; i386_pc = kern/i386/pc/mmap.c; @@ -575,7 +575,8 @@ module = { i386_pc = commands/acpihalt.c; i386_coreboot = commands/acpihalt.c; i386_multiboot = commands/acpihalt.c; - x86_efi = commands/acpihalt.c; + i386_efi = commands/acpihalt.c; + x86_64_efi = commands/acpihalt.c; i386_multiboot = lib/i386/halt.c; i386_coreboot = lib/i386/halt.c; i386_qemu = lib/i386/halt.c; @@ -1244,6 +1245,7 @@ module = { mips_yeeloong = mmap/mips/yeeloong/uppermem.c; enable = x86; + enable = ia64_efi; enable = mips_yeeloong; }; @@ -1435,7 +1437,8 @@ module = { module = { name = efi_uga; efi = video/efi_uga.c; - enable = efi; + enable = i386_efi; + enable = x86_64_efi; }; module = { diff --git a/grub-core/kern/ia64/efi/init.c b/grub-core/kern/ia64/efi/init.c index 06d5f5095..13a81a66e 100644 --- a/grub-core/kern/ia64/efi/init.c +++ b/grub-core/kern/ia64/efi/init.c @@ -25,13 +25,11 @@ #include #include #include -#include void grub_machine_init (void) { grub_efi_init (); - grub_init_modules (); } void diff --git a/grub-core/kern/ia64/efi/startup.S b/grub-core/kern/ia64/efi/startup.S index 9ba6858d9..fcaf4e189 100644 --- a/grub-core/kern/ia64/efi/startup.S +++ b/grub-core/kern/ia64/efi/startup.S @@ -15,6 +15,10 @@ * You should have received a copy of the GNU General Public License * along with GRUB. If not, see . */ +#include +#include +#include + .text .psr abi64 .psr lsb @@ -38,3 +42,12 @@ _start: br.ret.sptk.few rp .endp _start + + . = _start + GRUB_KERNEL_MACHINE_PREFIX +VARIABLE(grub_prefix) + /* to be filled by grub-mkimage */ + + /* + * Leave some breathing room for the prefix. + */ + . = _start + GRUB_KERNEL_MACHINE_PREFIX_END diff --git a/grub-core/lib/efi/halt.c b/grub-core/lib/efi/halt.c index c19536897..5ebf2cd1d 100644 --- a/grub-core/lib/efi/halt.c +++ b/grub-core/lib/efi/halt.c @@ -28,7 +28,9 @@ void grub_halt (void) { grub_machine_fini (); +#ifndef __ia64__ grub_acpi_halt (); +#endif efi_call_4 (grub_efi_system_table->runtime_services->reset_system, GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL); diff --git a/grub-core/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c index d9b4c338b..b018e4549 100644 --- a/grub-core/loader/ia64/efi/linux.c +++ b/grub-core/loader/ia64/efi/linux.c @@ -30,7 +30,6 @@ #include #include #include -#include #define ALIGN_MIN (256*1024*1024) @@ -512,7 +511,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), goto fail; } - file = grub_gzfile_open (argv[0], 1); + file = grub_file_open (argv[0]); if (! file) { grub_error (GRUB_ERR_BAD_ARGUMENT, "Couldn't open file"); @@ -594,7 +593,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } - file = grub_gzfile_open (argv[0], 1); + file = grub_file_open (argv[0]); if (! file) goto fail; @@ -644,7 +643,7 @@ grub_cmd_payload (grub_command_t cmd __attribute__ ((unused)), goto fail; } - file = grub_gzfile_open (argv[0], 1); + file = grub_file_open (argv[0]); if (! file) goto fail; diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index cb6b1113b..ded03a1b3 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -1234,7 +1234,7 @@ struct grub_efi_block_io }; typedef struct grub_efi_block_io grub_efi_block_io_t; -#if GRUB_TARGET_SIZEOF_VOID_P == 4 +#if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) #define efi_call_0(func) func() #define efi_call_1(func, a) func(a) diff --git a/include/grub/offsets.h b/include/grub/offsets.h index 817372b69..55b0f8fb8 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -117,6 +117,12 @@ /* End of the data section. */ #define GRUB_KERNEL_I386_EFI_PREFIX_END 0x50 +/* The offset of GRUB_PREFIX. */ +#define GRUB_KERNEL_IA64_EFI_PREFIX 0x50 + +/* End of the data section. */ +#define GRUB_KERNEL_IA64_EFI_PREFIX_END 0xa0 + /* The offset of GRUB_PREFIX. */ #define GRUB_KERNEL_X86_64_EFI_PREFIX 0x8 From bea33583891ad31f7673a377244defa4e393c8b7 Mon Sep 17 00:00:00 2001 From: phcoder Date: Mon, 3 Jan 2011 13:46:36 +0100 Subject: [PATCH 141/406] First handling of ia64-efi in grub-mkimage --- grub-core/Makefile.core.def | 4 ++-- include/grub/efi/pe32.h | 1 + util/grub-mkimage.c | 34 +++++++++++++++++++++++++++++---- util/grub-mkimagexx.c | 38 ++++++++++++++++++++++++++++--------- 4 files changed, 62 insertions(+), 15 deletions(-) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 4581b79cf..c21c38763 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -24,8 +24,8 @@ kernel = { x86_64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment'; ia64_efi_cflags = '-fno-builtin -fpic -minline-int-divide-max-throughput'; - ia64_efi_ldflags = '-melf_64'; - ia64_efi_stripflags = '-R .note -R .comment -X'; + ia64_efi_ldflags = '-Wl,-r,-d'; + ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment'; i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200'; diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h index 81a1a5797..c3efa9b3d 100644 --- a/include/grub/efi/pe32.h +++ b/include/grub/efi/pe32.h @@ -64,6 +64,7 @@ struct grub_pe32_coff_header }; #define GRUB_PE32_MACHINE_I386 0x14c +#define GRUB_PE32_MACHINE_IA64 0x200 #define GRUB_PE32_MACHINE_X86_64 0x8664 #define GRUB_PE32_RELOCS_STRIPPED 0x0001 diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 53e867602..507a7a80d 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -86,6 +86,7 @@ struct image_target_desc grub_uint64_t link_addr; unsigned mod_gap, mod_align; grub_compression_t default_compression; + grub_uint16_t pe_target; }; struct image_target_desc image_targets[] = @@ -191,6 +192,8 @@ struct image_target_desc image_targets[] = GRUB_PE32_SECTION_ALIGNMENT), .install_dos_part = TARGET_NO_FIELD, .install_bsd_part = TARGET_NO_FIELD, + .pe_target = GRUB_PE32_MACHINE_I386, + .elf_target = EM_386, }, { .name = "i386-ieee1275", @@ -253,6 +256,8 @@ struct image_target_desc image_targets[] = GRUB_PE32_SECTION_ALIGNMENT), .install_dos_part = TARGET_NO_FIELD, .install_bsd_part = TARGET_NO_FIELD, + .pe_target = GRUB_PE32_MACHINE_X86_64, + .elf_target = EM_X86_64, }, { .name = "mipsel-yeeloong-flash", @@ -354,6 +359,30 @@ struct image_target_desc image_targets[] = .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR }, + { + .name = "ia64-efi", + .voidp_sizeof = 8, + .bigendian = 0, + .id = IMAGE_EFI, + .flags = PLATFORM_FLAGS_NONE, + .prefix = GRUB_KERNEL_IA64_EFI_PREFIX, + .prefix_end = GRUB_KERNEL_IA64_EFI_PREFIX_END, + .raw_size = 0, + .total_module_size = TARGET_NO_FIELD, + .kernel_image_size = TARGET_NO_FIELD, + .compressed_size = TARGET_NO_FIELD, + .section_align = GRUB_PE32_SECTION_ALIGNMENT, + .vaddr_offset = ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE + + GRUB_PE32_SIGNATURE_SIZE + + sizeof (struct grub_pe32_coff_header) + + sizeof (struct grub_pe64_optional_header) + + 4 * sizeof (struct grub_pe32_section_table), + GRUB_PE32_SECTION_ALIGNMENT), + .install_dos_part = TARGET_NO_FIELD, + .install_bsd_part = TARGET_NO_FIELD, + .pe_target = GRUB_PE32_MACHINE_IA64, + .elf_target = EM_IA_64, + }, }; #define grub_target_to_host32(x) (grub_target_to_host32_real (image_target, (x))) @@ -927,10 +956,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], /* The COFF file header. */ c = (struct grub_pe32_coff_header *) (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE); - if (image_target->voidp_sizeof == 4) - c->machine = grub_host_to_target16 (GRUB_PE32_MACHINE_I386); - else - c->machine = grub_host_to_target16 (GRUB_PE32_MACHINE_X86_64); + c->machine = grub_host_to_target16 (image_target->pe_target); c->num_sections = grub_host_to_target16 (4); c->time = grub_host_to_target32 (time (0)); diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index ce51f2fbc..20cbacf15 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -101,9 +101,9 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections, else if (index >= num_sections) grub_util_error ("section %d does not exist", index); - sym->st_value = (grub_target_to_host32 (sym->st_value) + sym->st_value = (grub_target_to_host (sym->st_value) + section_addresses[index]); - grub_util_info ("locating %s at 0x%x", name, sym->st_value); + grub_util_info ("locating %s at 0x%x", name, sym->st_value, section_addresses[index]); if (! start_address) if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0) @@ -200,7 +200,9 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ? r->r_addend : 0; - if (image_target->voidp_sizeof == 4) + switch (image_target->elf_target) + { + case EM_386: switch (ELF_R_TYPE (info)) { case R_386_NONE: @@ -224,11 +226,12 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, *target, offset); break; default: - grub_util_error ("unknown relocation type %d", + grub_util_error ("unknown relocation type 0x%x", ELF_R_TYPE (info)); break; } - else + break; + case EM_X86_64: switch (ELF_R_TYPE (info)) { @@ -270,6 +273,20 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, ELF_R_TYPE (info)); break; } + break; + case EM_IA_64: + switch (ELF_R_TYPE (info)) + { + default: + grub_util_error ("unknown relocation type 0x%x", + ELF_R_TYPE (info)); + break; + } + break; + default: + grub_util_error ("unknown architecture type %d", + image_target->elf_target); + } } } } @@ -417,8 +434,9 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out, info = grub_le_to_cpu32 (r->r_info); /* Necessary to relocate only absolute addresses. */ - if (image_target->voidp_sizeof == 4) + switch (image_target->elf_target) { + case EM_386: if (ELF_R_TYPE (info) == R_386_32) { Elf_Addr addr; @@ -431,9 +449,8 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out, addr, 0, current_address, image_target); } - } - else - { + break; + case EM_X86_64: if ((ELF_R_TYPE (info) == R_X86_64_32) || (ELF_R_TYPE (info) == R_X86_64_32S)) { @@ -452,6 +469,9 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out, 0, current_address, image_target); } + break; + default: + grub_util_error ("unknown machine type 0x%x", image_target->elf_target); } } } From 7021cb3e16f4c5c32289ede7d0c53f4d4cc850c9 Mon Sep 17 00:00:00 2001 From: phcoder Date: Mon, 3 Jan 2011 13:48:33 +0100 Subject: [PATCH 142/406] Fix incorrect usage of variables in grub-install --- util/grub-install.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/grub-install.in b/util/grub-install.in index b9e833360..716582dfd 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -648,7 +648,7 @@ elif [ x"$platform" = xefi ]; then efidir_disk="$(echo "$clean_devmap" | grep "^$(echo "$efidir_drive" | sed 's/,[^)]*//')" | cut -f2)" efidir_part="$(echo "$efidir_drive" | sed 's/^([^,]*,[^0-9]*//; s/[^0-9].*//')" efibootmgr $efi_quiet -c -d "$efidir_disk" -p "$efidir_part" -w \ - -L "$GRUB_DISTRIBUTOR" -l "\\EFI\\$efi_distributor\\$efi_file" + -L "$bootloader_id" -l "\\EFI\\$efi_distributor\\$efi_file" fi fi fi From fb7ab4a99ba343167d3d0c5a8affa38c8dc057bf Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 3 Jan 2011 15:54:59 +0100 Subject: [PATCH 143/406] add missing == 0 --- grub-core/net/net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 54663f4b0..d3b4c74db 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -199,7 +199,7 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); FOR_NET_NETWORK_LEVEL_INTERFACES (inter) - if (grub_strcmp (inter->name, args[1])) + if (grub_strcmp (inter->name, args[1]) == 0) break; if (inter == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found")); @@ -730,7 +730,7 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_BAD_ARGUMENT, "4 arguments expected"); FOR_NET_NETWORK_LEVEL_INTERFACES (inter) - if (grub_strcmp (inter->name, args[1])) + if (grub_strcmp (inter->name, args[1]) == 0) break; if (!inter) From 7a1d4deec9267fc56ed50507b5a7fa9d96e3b610 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 3 Jan 2011 15:59:20 +0100 Subject: [PATCH 144/406] Fix finalisation/restore --- grub-core/disk/ahci.c | 255 +++++++++++++++++++++++++++++++----------- 1 file changed, 192 insertions(+), 63 deletions(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index b348ce3d0..c67dbbe7e 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -157,6 +157,98 @@ enum static struct grub_ahci_device *grub_ahci_devices; static int numdevs; +static int +init_port (struct grub_ahci_device *dev) +{ + struct grub_pci_dma_chunk *command_list; + struct grub_pci_dma_chunk *command_table; + grub_uint64_t endtime; + + command_list = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head)); + if (!command_list) + return 1; + + command_table = grub_memalign_dma32 (1024, + sizeof (struct grub_ahci_cmd_table)); + if (!command_table) + { + grub_dma_free (command_list); + return 1; + } + + grub_dprintf ("ahci", "found device ahci%d (port %d)\n", dev->num, dev->port); + + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop FR\n"); + goto out; + } + + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop CR\n"); + goto out; + } + + dev->hba->ports[dev->port].fbs = 2; + + dev->rfis = grub_memalign_dma32 (4096, + sizeof (struct grub_ahci_received_fis)); + grub_memset ((char *) grub_dma_get_virt (dev->rfis), 0, + sizeof (struct grub_ahci_received_fis)); + dev->hba->ports[dev->port].fis_base = grub_dma_get_phys (dev->rfis); + dev->hba->ports[dev->port].command_list_base + = grub_dma_get_phys (command_list); + dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_FRE; + while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't start FR\n"); + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + goto out; + } + dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST; + while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't start CR\n"); + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_CR; + goto out_stop_fr; + } + + dev->hba->ports[dev->port].command + = (dev->hba->ports[dev->port].command & 0x0fffffff) | (1 << 28) | 2 | 4; + + dev->command_list_chunk = command_list; + dev->command_list = grub_dma_get_virt (command_list); + dev->command_table_chunk = command_table; + dev->command_table = grub_dma_get_virt (command_table); + dev->command_list->command_table_base + = grub_dma_get_phys (command_table); + + return 0; + out_stop_fr: + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop FR\n"); + break; + } + out: + grub_dma_free (command_list); + grub_dma_free (command_table); + grub_dma_free (dev->rfis); + return 1; +} + static int NESTED_FUNC_ATTR grub_ahci_pciinit (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))) @@ -209,7 +301,50 @@ grub_ahci_pciinit (grub_pci_device_t dev, else grub_dprintf ("ahci", "AHCI is already in OS mode\n"); - hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; + if (~(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)) + grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n"); + else + grub_dprintf ("ahci", "AHCI is in AHCI mode.\n"); + + for (i = 0; i < 5; i++) + { + hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; + grub_millisleep (1); + if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN) + break; + } + if (i == 5) + { + grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n"); + return 0; + } + + /* + { + grub_uint64_t endtime; + hba->global_control |= 1; + endtime = grub_get_time_ms () + 1000; + while (hba->global_control & 1) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't reset AHCI\n"); + return 0; + } + } + + for (i = 0; i < 5; i++) + { + hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; + grub_millisleep (1); + if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN) + break; + } + if (i == 5) + { + grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n"); + return 0; + } + */ nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1; @@ -218,8 +353,6 @@ grub_ahci_pciinit (grub_pci_device_t dev, for (i = 0; i < nports; i++) { struct grub_ahci_device *adev; - struct grub_pci_dma_chunk *command_list; - struct grub_pci_dma_chunk *command_table; grub_uint32_t st; if (!(hba->ports_implemented & (1 << i))) @@ -231,60 +364,20 @@ grub_ahci_pciinit (grub_pci_device_t dev, if ((st & 0xf) != 0x3 && (st & 0xf) != 0x1) continue; - command_list = grub_memalign_dma32 (1024, - sizeof (struct grub_ahci_cmd_head)); - if (!command_list) - return 1; - - command_table = grub_memalign_dma32 (1024, - sizeof (struct grub_ahci_cmd_table)); - if (!command_table) - { - grub_dma_free (command_list); - return 1; - } - adev = grub_malloc (sizeof (*adev)); if (!adev) - { - grub_dma_free (command_list); - grub_dma_free (command_table); - return 1; - } - - grub_dprintf ("ahci", "found device ahci%d (port %d)\n", numdevs, i); - - hba->ports[i].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; - while ((hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_FR)); - hba->ports[i].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; - while ((hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_CR)); - - hba->ports[i].fbs = 2; - - adev->rfis = grub_memalign_dma32 (4096, - sizeof (struct grub_ahci_received_fis)); - grub_memset ((char *) grub_dma_get_virt (adev->rfis), 0, - sizeof (struct grub_ahci_received_fis)); - hba->ports[i].fis_base = grub_dma_get_phys (adev->rfis); - hba->ports[i].command |= GRUB_AHCI_HBA_PORT_CMD_FRE; - while (!(hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_FR)); - hba->ports[i].command |= GRUB_AHCI_HBA_PORT_CMD_ST; - while (!(hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_CR)); - - hba->ports[i].command = (hba->ports[i].command & 0x0fffffff) - | (1 << 28) | 2 | 4; + return 1; adev->hba = hba; adev->port = i; adev->num = numdevs++; - adev->command_list_chunk = command_list; - adev->command_list = grub_dma_get_virt (command_list); - adev->command_table_chunk = command_table; - adev->command_table = grub_dma_get_virt (command_table); - adev->command_list->command_table_base - = grub_dma_get_phys (command_table); - adev->hba->ports[i].command_list_base = grub_dma_get_phys (command_list); + if (init_port (adev)) + { + grub_free (adev); + return 1; + } + grub_list_push (GRUB_AS_LIST_P (&grub_ahci_devices), GRUB_AS_LIST (adev)); } @@ -302,29 +395,53 @@ grub_ahci_initialize (void) static grub_err_t grub_ahci_fini_hw (int noreturn __attribute__ ((unused))) { - struct grub_ahci_device *dev, *next; + struct grub_ahci_device *dev; - for (dev = grub_ahci_devices; dev; dev = next) + for (dev = grub_ahci_devices; dev; dev = dev->next) { - next = dev->next; - dev->hba->ports[dev->num].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; - while ((dev->hba->ports[dev->num].command & GRUB_AHCI_HBA_PORT_CMD_FR)); - dev->hba->ports[dev->num].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; - while ((dev->hba->ports[dev->num].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + grub_uint64_t endtime; + + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop FR\n"); + break; + } + + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop CR\n"); + break; + } grub_dma_free (dev->command_list_chunk); grub_dma_free (dev->command_table_chunk); grub_dma_free (dev->rfis); - - grub_free (dev); + dev->command_list_chunk = NULL; + dev->command_table_chunk = NULL; + dev->rfis = NULL; } - grub_ahci_devices = NULL; return GRUB_ERR_NONE; } static grub_err_t grub_ahci_restore_hw (void) { - return grub_ahci_initialize (); + struct grub_ahci_device **pdev; + + for (pdev = &grub_ahci_devices; *pdev; pdev = &((*pdev)->next)) + if (init_port (*pdev)) + { + struct grub_ahci_device *odev; + odev = *pdev; + *pdev = (*pdev)->next; + grub_free (odev); + } + return GRUB_ERR_NONE; } @@ -391,9 +508,21 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, if ((dev->hba->ports[dev->port].task_file_data & 0x80)) { dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; - while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop CR\n"); + break; + } dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST; - while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + endtime = grub_get_time_ms () + 1000; + while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't start CR\n"); + break; + } } dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error; From f440c33fd2669b06a0c84cbbe1912054d5d39314 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 14 Jan 2011 17:37:11 +0100 Subject: [PATCH 145/406] Make qemu-mips compile again. Still no grub-mkimage support --- configure.ac | 4 +-- gentpl.py | 8 ++--- grub-core/Makefile.am | 5 +++ grub-core/Makefile.core.def | 12 ++++--- grub-core/kern/mips/cache_flush.S | 4 +++ grub-core/kern/mips/qemu-mips/init.c | 3 +- grub-core/loader/mips/linux.c | 7 ++++- grub-core/loader/multiboot_mbi2.c | 2 ++ include/grub/mips/qemu_mips/cmos.h | 28 +++++++++++++++++ .../mips/{qemu-mips => qemu_mips}/kernel.h | 1 - .../mips/{qemu-mips => qemu_mips}/loader.h | 0 .../mips/{qemu-mips => qemu_mips}/memory.h | 31 +++++++++++++++++-- .../mips/{qemu-mips => qemu_mips}/serial.h | 0 .../grub/mips/{qemu-mips => qemu_mips}/time.h | 0 include/grub/offsets.h | 28 +++++++++++++---- 15 files changed, 110 insertions(+), 23 deletions(-) create mode 100644 include/grub/mips/qemu_mips/cmos.h rename include/grub/mips/{qemu-mips => qemu_mips}/kernel.h (97%) rename include/grub/mips/{qemu-mips => qemu_mips}/loader.h (100%) rename include/grub/mips/{qemu-mips => qemu_mips}/memory.h (69%) rename include/grub/mips/{qemu-mips => qemu_mips}/serial.h (100%) rename include/grub/mips/{qemu-mips => qemu_mips}/time.h (100%) diff --git a/configure.ac b/configure.ac index 0b9207ea2..aac93fba2 100644 --- a/configure.ac +++ b/configure.ac @@ -122,7 +122,7 @@ case "$target_cpu"-"$platform" in i386-qemu) ;; powerpc-ieee1275) ;; sparc64-ieee1275) ;; - mips-qemu-mips) ;; + mips-qemu_mips) ;; mips-yeeloong) ;; *-emu) ;; *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;; @@ -157,7 +157,7 @@ case "$platform" in pc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_PCBIOS=1" ;; emu) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_EMU=1" ;; yeeloong) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_YEELOONG=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;; - qemu-mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_QEMU_MIPS=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;; + qemu_mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_QEMU_MIPS=1" ;; esac case "$target_cpu" in mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS=1" ;; diff --git a/gentpl.py b/gentpl.py index a42a60667..97eff9f57 100644 --- a/gentpl.py +++ b/gentpl.py @@ -6,7 +6,7 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_multiboot", "i386_ieee1275", "x86_64_efi", - "mips_yeeloong", "sparc64_ieee1275", + "mips_yeeloong", "mips_qemu_mips", "sparc64_ieee1275", "powerpc_ieee1275" ] GROUPS = {} @@ -17,7 +17,7 @@ GROUPS["common"] = GRUB_PLATFORMS[:] GROUPS["i386"] = [ "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_multiboot", "i386_ieee1275" ] GROUPS["x86_64"] = [ "x86_64_efi" ] GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"] -GROUPS["mips"] = [ "mips_yeeloong" ] +GROUPS["mips"] = [ "mips_yeeloong", "mips_qemu_mips" ] GROUPS["sparc64"] = [ "sparc64_ieee1275" ] GROUPS["powerpc"] = [ "powerpc_ieee1275" ] @@ -29,8 +29,8 @@ GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu") # Groups based on hardware features -GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_yeeloong"]; GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi") -GROUPS["pci"] = GROUPS["x86"] + GROUPS["mips"] +GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_yeeloong", "mips_qemu_mips" ]; GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi") +GROUPS["pci"] = GROUPS["x86"] + ["mips_yeeloong"] GROUPS["usb"] = GROUPS["pci"] # If gfxterm is main output console integrate it into kernel diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 94f7f3ffe..65f638745 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -145,6 +145,11 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h endif +if COND_mips_qemu_mips +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +endif + if COND_powerpc_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 2cca4fa95..1cc832892 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -48,7 +48,7 @@ kernel = { i386_ieee1275_startup = kern/i386/ieee1275/startup.S; i386_coreboot_startup = kern/i386/coreboot/startup.S; i386_multiboot_startup = kern/i386/coreboot/startup.S; - mips_yeeloong_startup = kern/mips/startup.S; + mips_startup = kern/mips/startup.S; sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S; powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S; @@ -82,6 +82,7 @@ kernel = { i386_coreboot = kern/generic/rtc_get_time_ms.c; i386_multiboot = kern/generic/rtc_get_time_ms.c; mips_yeeloong = kern/generic/rtc_get_time_ms.c; + mips_qemu_mips = kern/generic/rtc_get_time_ms.c; ieee1275 = disk/ieee1275/ofdisk.c; ieee1275 = kern/ieee1275/cmain.c; @@ -140,10 +141,11 @@ kernel = { mips_yeeloong = bus/bonito.c; mips_yeeloong = bus/cs5536.c; mips_yeeloong = bus/pci.c; - mips_yeeloong = kern/mips/cache.S; - mips_yeeloong = kern/mips/dl.c; - mips_yeeloong = kern/mips/init.c; + mips = kern/mips/cache.S; + mips = kern/mips/dl.c; + mips = kern/mips/init.c; mips_yeeloong = kern/mips/yeeloong/init.c; + mips_qemu_mips = kern/mips/qemu-mips/init.c; mips_yeeloong = term/at_keyboard.c; mips_yeeloong = term/serial.c; mips_yeeloong = video/sm712.c; @@ -1229,7 +1231,7 @@ module = { mips_yeeloong = mmap/mips/yeeloong/uppermem.c; enable = x86; - enable = mips_yeeloong; + enable = mips; }; module = { diff --git a/grub-core/kern/mips/cache_flush.S b/grub-core/kern/mips/cache_flush.S index 11096c035..87a738caa 100644 --- a/grub-core/kern/mips/cache_flush.S +++ b/grub-core/kern/mips/cache_flush.S @@ -1,3 +1,6 @@ + + /* Qemu doesn't emulate caches. Oh boy. */ +#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS move $t2, $a0 addu $t3, $a0, $a1 srl $t2, $t2, 5 @@ -21,3 +24,4 @@ bne $t1, $zero, 2b addiu $t0, $t0, 0x1 sync +#endif \ No newline at end of file diff --git a/grub-core/kern/mips/qemu-mips/init.c b/grub-core/kern/mips/qemu-mips/init.c index f2bb652a8..1690b5451 100644 --- a/grub-core/kern/mips/qemu-mips/init.c +++ b/grub-core/kern/mips/qemu-mips/init.c @@ -6,9 +6,8 @@ #include #include #include -#include #include -#include +#include #define RAMSIZE (*(grub_uint32_t *) ((16 << 20) - 264)) diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c index 6ae2a9321..8520609ed 100644 --- a/grub-core/loader/mips/linux.c +++ b/grub-core/loader/mips/linux.c @@ -29,8 +29,10 @@ #include /* For frequencies. */ +#ifdef GRUB_MACHINE_MIPS_YEELOONG #include #include +#endif #ifdef GRUB_MACHINE_MIPS_YEELOONG /* This can be detected on runtime from PMON, but: @@ -314,6 +316,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), linux_envp = extra; envp_off = (grub_uint8_t *) linux_envp - (grub_uint8_t *) playground; linux_envs = (char *) (linux_envp + 5); +#ifdef GRUB_MACHINE_MIPS_YEELOONG grub_snprintf (linux_envs, sizeof ("memsize=XXXXXXXXXXXXXXXXXXXX"), "memsize=%lld", (unsigned long long) grub_mmap_get_lower () >> 20); @@ -338,8 +341,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + target_addr; linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4); - linux_envp[4] = 0; +#else + linux_envp[0] = 0; +#endif grub_loader_set (grub_linux_boot, grub_linux_unload, 1); initrd_loaded = 0; diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index 3141f0028..e4a630d03 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -671,6 +671,7 @@ grub_multiboot_make_mbi (grub_uint32_t *target) ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); } +#if defined (__i386) || defined (__x86_64__) || defined (GRUB_MACHINE_MIPS_YEELOONG) { struct multiboot_tag_basic_meminfo *tag = (struct multiboot_tag_basic_meminfo *) ptrorig; @@ -682,6 +683,7 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->mem_upper = grub_mmap_get_upper () / 1024; ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); } +#endif if (bootdev_set) { diff --git a/include/grub/mips/qemu_mips/cmos.h b/include/grub/mips/qemu_mips/cmos.h new file mode 100644 index 000000000..4aef40e81 --- /dev/null +++ b/include/grub/mips/qemu_mips/cmos.h @@ -0,0 +1,28 @@ +/* + * 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_CPU_CMOS_H +#define GRUB_CPU_CMOS_H 1 + +#include +#include + +#define GRUB_CMOS_ADDR_REG 0xb4000070 +#define GRUB_CMOS_DATA_REG 0xb4000071 + +#endif /* GRUB_CPU_CMOS_H */ diff --git a/include/grub/mips/qemu-mips/kernel.h b/include/grub/mips/qemu_mips/kernel.h similarity index 97% rename from include/grub/mips/qemu-mips/kernel.h rename to include/grub/mips/qemu_mips/kernel.h index 230455dbf..c08405e83 100644 --- a/include/grub/mips/qemu-mips/kernel.h +++ b/include/grub/mips/qemu_mips/kernel.h @@ -20,7 +20,6 @@ #define GRUB_KERNEL_MACHINE_HEADER 1 #include -#include #ifndef ASM_FILE diff --git a/include/grub/mips/qemu-mips/loader.h b/include/grub/mips/qemu_mips/loader.h similarity index 100% rename from include/grub/mips/qemu-mips/loader.h rename to include/grub/mips/qemu_mips/loader.h diff --git a/include/grub/mips/qemu-mips/memory.h b/include/grub/mips/qemu_mips/memory.h similarity index 69% rename from include/grub/mips/qemu-mips/memory.h rename to include/grub/mips/qemu_mips/memory.h index 99d9ef2be..57220a1e2 100644 --- a/include/grub/mips/qemu-mips/memory.h +++ b/include/grub/mips/qemu_mips/memory.h @@ -28,11 +28,37 @@ #define GRUB_MACHINE_MEMORY_STACK_HIGH 0x80f00000 #define GRUB_MACHINE_MEMORY_USABLE 0x81000000 +#define GRUB_MACHINE_MEMORY_AVAILABLE 1 +#define GRUB_MACHINE_MEMORY_MAX_TYPE 1 + /* This one is special: it's used internally but is never reported + by firmware. */ +#define GRUB_MACHINE_MEMORY_HOLE 2 +#define GRUB_MACHINE_MEMORY_RESERVED GRUB_MACHINE_MEMORY_HOLE + #ifndef ASM_FILE + +typedef grub_addr_t grub_phys_addr_t; + +static inline grub_phys_addr_t +grub_vtop (void *a) +{ + return ((grub_phys_addr_t) a) & 0x1fffffff; +} + +static inline void * +grub_map_memory (grub_phys_addr_t a, grub_size_t size __attribute__ ((unused))) +{ + return (void *) (a | 0x80000000); +} + +static inline void +grub_unmap_memory (void *a __attribute__ ((unused)), + grub_size_t size __attribute__ ((unused))) +{ +} + grub_err_t EXPORT_FUNC (grub_machine_mmap_iterate) (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); -grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) - (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); static inline grub_err_t grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), @@ -47,6 +73,7 @@ grub_machine_mmap_unregister (int handle __attribute__ ((unused))) { return GRUB_ERR_NONE; } + #endif #endif diff --git a/include/grub/mips/qemu-mips/serial.h b/include/grub/mips/qemu_mips/serial.h similarity index 100% rename from include/grub/mips/qemu-mips/serial.h rename to include/grub/mips/qemu_mips/serial.h diff --git a/include/grub/mips/qemu-mips/time.h b/include/grub/mips/qemu_mips/time.h similarity index 100% rename from include/grub/mips/qemu-mips/time.h rename to include/grub/mips/qemu_mips/time.h diff --git a/include/grub/offsets.h b/include/grub/offsets.h index 817372b69..fa609b16f 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -104,12 +104,26 @@ #define GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN 32 -#define GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE 0x8 -#define GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE 0xc +#define GRUB_KERNEL_MIPS_COMPRESSED_SIZE 0x8 +#define GRUB_KERNEL_MIPS_UNCOMPRESSED_SIZE 0xc -#define GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE 0x08 -#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX 0x0c -#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END 0x54 +#define GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE GRUB_KERNEL_MIPS_COMPRESSED_SIZE +#define GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE GRUB_KERNEL_MIPS_UNCOMPRESSED_SIZE + +#define GRUB_KERNEL_MIPS_QEMU_MIPS_COMPRESSED_SIZE GRUB_KERNEL_MIPS_COMPRESSED_SIZE +#define GRUB_KERNEL_MIPS_QEMU_MIPS_UNCOMPRESSED_SIZE GRUB_KERNEL_MIPS_UNCOMPRESSED_SIZE + +#define GRUB_KERNEL_MIPS_TOTAL_MODULE_SIZE 0x08 +#define GRUB_KERNEL_MIPS_PREFIX 0x0c +#define GRUB_KERNEL_MIPS_PREFIX_END 0x54 + +#define GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE GRUB_KERNEL_MIPS_TOTAL_MODULE_SIZE +#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX GRUB_KERNEL_MIPS_PREFIX +#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END GRUB_KERNEL_MIPS_PREFIX_END + +#define GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE GRUB_KERNEL_MIPS_TOTAL_MODULE_SIZE +#define GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX GRUB_KERNEL_MIPS_PREFIX +#define GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END GRUB_KERNEL_MIPS_PREFIX_END /* The offset of GRUB_PREFIX. */ #define GRUB_KERNEL_I386_EFI_PREFIX 0x8 @@ -144,7 +158,9 @@ #define GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN 0x1000 -#define GRUB_KERNEL_MIPS_YEELOONG_MOD_ALIGN 0x1 +#define GRUB_KERNEL_MIPS_MOD_ALIGN 0x1 +#define GRUB_KERNEL_MIPS_YEELOONG_MOD_ALIGN GRUB_KERNEL_MIPS_MOD_ALIGN +#define GRUB_KERNEL_MIPS_QEMU_MIPS_MOD_ALIGN GRUB_KERNEL_MIPS_MOD_ALIGN /* Minimal gap between _end and the start of the modules. It's a hack for PowerMac to prevent "CLAIM failed" error. The real fix is to From 01b08a0f15e12a1bcbea49b092a960645c9880fb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 18 Jan 2011 13:44:16 +0100 Subject: [PATCH 146/406] initial SIS315PRO support --- grub-core/Makefile.core.def | 1 + grub-core/kern/mips/yeeloong/init.c | 2 + grub-core/video/sis315pro.c | 246 ++++++++++++++++++++++++++++ include/grub/video.h | 3 +- 4 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 grub-core/video/sis315pro.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index ce7d0b0c2..a67c805c9 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -147,6 +147,7 @@ kernel = { mips_yeeloong = term/at_keyboard.c; mips_yeeloong = term/serial.c; mips_yeeloong = video/sm712.c; + mips_yeeloong = video/sis315pro.c; extra_dist = video/sm712_init.c; mips_yeeloong = commands/keylayouts.c; diff --git a/grub-core/kern/mips/yeeloong/init.c b/grub-core/kern/mips/yeeloong/init.c index 7a48d69f5..f42c9696d 100644 --- a/grub-core/kern/mips/yeeloong/init.c +++ b/grub-core/kern/mips/yeeloong/init.c @@ -33,6 +33,7 @@ #include extern void grub_video_sm712_init (void); +extern void grub_video_sis315pro_init (void); extern void grub_video_init (void); extern void grub_bitmap_init (void); extern void grub_font_init (void); @@ -202,6 +203,7 @@ grub_machine_init (void) relies on a working heap. */ grub_video_init (); grub_video_sm712_init (); + grub_video_sis315pro_init (); grub_bitmap_init (); grub_font_init (); grub_gfxterm_init (); diff --git a/grub-core/video/sis315pro.c b/grub-core/video/sis315pro.c new file mode 100644 index 000000000..59ff6432d --- /dev/null +++ b/grub-core/video/sis315pro.c @@ -0,0 +1,246 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009,2010 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 . + */ + +#define grub_video_render_target grub_video_fbrender_target + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GRUB_SIS315PRO_PCIID 0x03251039 +#define GRUB_SIS315PRO_TOTAL_MEMORY_SPACE 0x800000 + +static struct +{ + struct grub_video_mode_info mode_info; + struct grub_video_render_target *render_target; + + grub_uint8_t *ptr; + int mapped; + grub_uint32_t base; + grub_pci_device_t dev; +} framebuffer; + +#ifndef TEST +static grub_err_t +grub_video_sis315pro_video_init (void) +{ + /* Reset frame buffer. */ + grub_memset (&framebuffer, 0, sizeof(framebuffer)); + + return grub_video_fb_init (); +} + +static grub_err_t +grub_video_sis315pro_video_fini (void) +{ + if (framebuffer.mapped) + grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr, + GRUB_SIS315PRO_TOTAL_MEMORY_SPACE); + + return grub_video_fb_fini (); +} +#endif + +static grub_err_t +grub_video_sis315pro_setup (unsigned int width, unsigned int height, + unsigned int mode_type, + unsigned int mode_mask __attribute__ ((unused))) +{ + int depth; + grub_err_t err; + int found = 0; + +#ifndef TEST + auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))); + int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))) + { + grub_pci_address_t addr; + grub_uint32_t class; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA + || pciid != GRUB_SIS315PRO_PCIID) + return 0; + + found = 1; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + framebuffer.base = grub_pci_read (addr); + framebuffer.dev = dev; + + return 1; + } + + /* Decode depth from mode_type. If it is zero, then autodetect. */ + depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) + >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; + + if ((width != 640 && width != 0) || (height != 400 && height != 0) + || (depth != 8 && depth != 0)) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "Only 640x400x8 is supported"); + + grub_pci_iterate (find_card); + if (!found) + return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); +#endif + /* Fill mode info details. */ + framebuffer.mode_info.width = 640; + framebuffer.mode_info.height = 400; + framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + framebuffer.mode_info.bpp = 8; + framebuffer.mode_info.bytes_per_pixel = 1; + framebuffer.mode_info.pitch = 640 * 1; + framebuffer.mode_info.number_of_colors = 256; + framebuffer.mode_info.red_mask_size = 0; + framebuffer.mode_info.red_field_pos = 0; + framebuffer.mode_info.green_mask_size = 0; + framebuffer.mode_info.green_field_pos = 0; + framebuffer.mode_info.blue_mask_size = 0; + framebuffer.mode_info.blue_field_pos = 0; + framebuffer.mode_info.reserved_mask_size = 0; + framebuffer.mode_info.reserved_field_pos = 0; +#ifndef TEST + framebuffer.mode_info.blit_format + = grub_video_get_blit_format (&framebuffer.mode_info); +#endif + + /* We can safely discard volatile attribute. */ +#ifndef TEST + framebuffer.ptr + = (void *) grub_pci_device_map_range (framebuffer.dev, + framebuffer.base, + GRUB_SIS315PRO_TOTAL_MEMORY_SPACE); +#endif + framebuffer.mapped = 1; + +#ifndef TEST + /* Prevent garbage from appearing on the screen. */ + grub_memset (framebuffer.ptr, 0, + framebuffer.mode_info.height * framebuffer.mode_info.pitch); +#endif + +#ifndef TEST + err = grub_video_fb_create_render_target_from_pointer (&framebuffer + .render_target, + &framebuffer.mode_info, + framebuffer.ptr); + + if (err) + return err; + + err = grub_video_fb_set_active_render_target (framebuffer.render_target); + + if (err) + return err; + + /* Copy default palette to initialize emulated palette. */ + err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, + grub_video_fbstd_colors); +#endif + return err; +} + +#ifndef TEST + +static grub_err_t +grub_video_sis315pro_swap_buffers (void) +{ + /* TODO: Implement buffer swapping. */ + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_video_sis315pro_set_active_render_target (struct grub_video_render_target *target) +{ + if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY) + target = framebuffer.render_target; + + return grub_video_fb_set_active_render_target (target); +} + +static grub_err_t +grub_video_sis315pro_get_info_and_fini (struct grub_video_mode_info *mode_info, + void **framebuf) +{ + grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info)); + *framebuf = (char *) framebuffer.ptr; + + grub_video_fb_fini (); + + return GRUB_ERR_NONE; +} + +static struct grub_video_adapter grub_video_sis315pro_adapter = + { + .name = "SIS315PRO Video Driver", + .id = GRUB_VIDEO_DRIVER_SIS315PRO, + + .prio = GRUB_VIDEO_ADAPTER_PRIO_NATIVE, + + .init = grub_video_sis315pro_video_init, + .fini = grub_video_sis315pro_video_fini, + .setup = grub_video_sis315pro_setup, + .get_info = grub_video_fb_get_info, + .get_info_and_fini = grub_video_sis315pro_get_info_and_fini, + .set_palette = grub_video_fb_set_palette, + .get_palette = grub_video_fb_get_palette, + .set_viewport = grub_video_fb_set_viewport, + .get_viewport = grub_video_fb_get_viewport, + .map_color = grub_video_fb_map_color, + .map_rgb = grub_video_fb_map_rgb, + .map_rgba = grub_video_fb_map_rgba, + .unmap_color = grub_video_fb_unmap_color, + .fill_rect = grub_video_fb_fill_rect, + .blit_bitmap = grub_video_fb_blit_bitmap, + .blit_render_target = grub_video_fb_blit_render_target, + .scroll = grub_video_fb_scroll, + .swap_buffers = grub_video_sis315pro_swap_buffers, + .create_render_target = grub_video_fb_create_render_target, + .delete_render_target = grub_video_fb_delete_render_target, + .set_active_render_target = grub_video_sis315pro_set_active_render_target, + .get_active_render_target = grub_video_fb_get_active_render_target, + + .next = 0 + }; + +GRUB_MOD_INIT(video_sis315pro) +{ + grub_video_register (&grub_video_sis315pro_adapter); +} + +GRUB_MOD_FINI(video_sis315pro) +{ + grub_video_unregister (&grub_video_sis315pro_adapter); +} +#else +int +main () +{ + grub_video_sis315pro_setup (640, 400, 0, 0); +} +#endif diff --git a/include/grub/video.h b/include/grub/video.h index 5350d87eb..8773199c2 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -211,7 +211,8 @@ typedef enum grub_video_driver_id GRUB_VIDEO_DRIVER_VGA, GRUB_VIDEO_DRIVER_CIRRUS, GRUB_VIDEO_DRIVER_BOCHS, - GRUB_VIDEO_DRIVER_SDL + GRUB_VIDEO_DRIVER_SDL, + GRUB_VIDEO_DRIVER_SIS315PRO, } grub_video_driver_id_t; typedef enum grub_video_adapter_prio From edf9d1f7ebb6c37e2de52c50268331384a6e66b5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 18 Jan 2011 14:00:55 +0100 Subject: [PATCH 147/406] Don't double the divisor on Geode UART, it runs at normal speed --- grub-core/term/ns8250.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c index 4be528df8..5d403c845 100644 --- a/grub-core/term/ns8250.c +++ b/grub-core/term/ns8250.c @@ -37,7 +37,8 @@ static const grub_port_t serial_hw_io_addr[] = GRUB_MACHINE_SERIAL_PORTS; /* Convert speed to divisor. */ static unsigned short -serial_get_divisor (unsigned int speed) +serial_get_divisor (const struct grub_serial_port *port, + const struct grub_serial_config *config) { unsigned int i; @@ -63,13 +64,16 @@ serial_get_divisor (unsigned int speed) /* Set the baud rate. */ for (i = 0; i < ARRAY_SIZE (divisor_tab); i++) - if (divisor_tab[i].speed == speed) - /* UART in Yeeloong runs twice the usual rate. */ + if (divisor_tab[i].speed == config->speed) + { + /* internal UART in Yeeloong runs twice the usual rate. */ #ifdef GRUB_MACHINE_MIPS_YEELOONG - return 2 * divisor_tab[i].div; -#else - return divisor_tab[i].div; + if (port->port == 0xbff003f8) + return 2 * divisor_tab[i].div; + else #endif + return divisor_tab[i].div; + } return 0; } @@ -93,7 +97,7 @@ do_real_config (struct grub_serial_port *port) port->broken = 0; - divisor = serial_get_divisor (port->config.speed); + divisor = serial_get_divisor (port, &port->config); /* Turn off the interrupt. */ grub_outb (0, port->port + UART_IER); @@ -188,7 +192,7 @@ serial_hw_configure (struct grub_serial_port *port, { unsigned short divisor; - divisor = serial_get_divisor (config->speed); + divisor = serial_get_divisor (port, config); if (divisor == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed"); From 74eea126f472abc82268d937a26d7367e75e9369 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 18 Jan 2011 15:28:44 +0100 Subject: [PATCH 148/406] fuloong support --- grub-core/boot/mips/yeeloong/fwstart.S | 3 ++ grub-core/kern/mips/startup.S | 3 ++ grub-core/kern/mips/yeeloong/init.c | 7 +++-- grub-core/loader/mips/linux.c | 40 +++++++++++++++----------- grub-core/term/serial.c | 16 ++++++++--- include/grub/mips/yeeloong/kernel.h | 5 ++++ include/grub/mips/yeeloong/serial.h | 9 ++++-- include/grub/term.h | 16 +++++++++++ 8 files changed, 74 insertions(+), 25 deletions(-) diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S index 425458401..4c2fe5543 100644 --- a/grub-core/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/yeeloong/fwstart.S @@ -25,6 +25,9 @@ #include #include +#define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT0 +#define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT0_DIVISOR_115200 + .set noreorder .set noat .set nomacro diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index ae0e0b187..4bf4c1762 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -20,6 +20,7 @@ #include #include #include +#include #include #define BASE_ADDR 8 @@ -59,6 +60,8 @@ VARIABLE (grub_arch_memsize) .long 0 VARIABLE (grub_arch_highmemsize) .long 0 +VARIABLE (grub_arch_machine) + .long GRUB_ARCH_MACHINE_FULOONG #endif cont: /* Save our base. */ diff --git a/grub-core/kern/mips/yeeloong/init.c b/grub-core/kern/mips/yeeloong/init.c index f42c9696d..6787a205d 100644 --- a/grub-core/kern/mips/yeeloong/init.c +++ b/grub-core/kern/mips/yeeloong/init.c @@ -208,8 +208,11 @@ grub_machine_init (void) grub_font_init (); grub_gfxterm_init (); - grub_keylayouts_init (); - grub_at_keyboard_init (); + if (grub_arch_machine == GRUB_ARCH_MACHINE_YEELOONG) + { + grub_keylayouts_init (); + grub_at_keyboard_init (); + } grub_terminfo_init (); grub_serial_init (); diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c index 6ae2a9321..244d2b8a3 100644 --- a/grub-core/loader/mips/linux.c +++ b/grub-core/loader/mips/linux.c @@ -33,11 +33,13 @@ #include #ifdef GRUB_MACHINE_MIPS_YEELOONG -/* This can be detected on runtime from PMON, but: - a) it wouldn't work when GRUB is the firmware - and - b) for now we only support Yeeloong anyway. */ -#define LOONGSON_MACHTYPE "machtype=lemote-yeeloong-2f-8.9inches" +#include + +const char loongson_machtypes[][60] = + { + [GRUB_ARCH_MACHINE_YEELOONG] = "machtype=lemote-yeeloong-2f-8.9inches", + [GRUB_ARCH_MACHINE_FULOONG] = "machtype=lemote-fuloong-2f-unknown" + }; #endif static grub_dl_t my_mod; @@ -222,7 +224,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* For arguments. */ linux_argc = argc; -#ifdef LOONGSON_MACHTYPE +#ifdef GRUB_MACHINE_MIPS_YEELOONG linux_argc++; #endif /* Main arguments. */ @@ -237,8 +239,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* Normal arguments. */ for (i = 1; i < argc; i++) size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); -#ifdef LOONGSON_MACHTYPE - size += ALIGN_UP (sizeof (LOONGSON_MACHTYPE), 4); +#ifdef GRUB_MACHINE_MIPS_YEELOONG + size += ALIGN_UP (sizeof (loongson_machtypes[0]), 4); #endif /* rd arguments. */ @@ -277,14 +279,20 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), linux_argv++; linux_args += ALIGN_UP (sizeof ("a0"), 4); -#ifdef LOONGSON_MACHTYPE - /* In Loongson platform, it is the responsibility of the bootloader/firmware - to supply the OS kernel with machine type information. */ - grub_memcpy (linux_args, LOONGSON_MACHTYPE, sizeof (LOONGSON_MACHTYPE)); - *linux_argv = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground - + target_addr; - linux_argv++; - linux_args += ALIGN_UP (sizeof (LOONGSON_MACHTYPE), 4); +#ifdef GRUB_MACHINE_MIPS_YEELOONG + { + unsigned mtype = grub_arch_machine; + if (mtype >= ARRAY_SIZE (loongson_machtypes)) + mtype = 0; + /* In Loongson platform, it is the responsibility of the bootloader/firmware + to supply the OS kernel with machine type information. */ + grub_memcpy (linux_args, loongson_machtypes[mtype], + sizeof (loongson_machtypes[mtype])); + *linux_argv = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground + + target_addr; + linux_argv++; + linux_args += ALIGN_UP (sizeof (loongson_machtypes[mtype]), 4); + } #endif for (i = 1; i < argc; i++) diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c index e672a89d6..aca5769fd 100644 --- a/grub-core/term/serial.c +++ b/grub-core/term/serial.c @@ -26,6 +26,9 @@ #include #include #include +#ifdef GRUB_MACHINE_MIPS_YEELOONG +#include +#endif #define FOR_SERIAL_PORTS(var) FOR_LIST_ELEMENTS((var), (grub_serial_ports)) @@ -296,17 +299,22 @@ grub_serial_register (struct grub_serial_port *port) port->term_out = out; grub_terminfo_output_register (out, "vt100"); #ifdef GRUB_MACHINE_MIPS_YEELOONG - if (grub_strcmp (port->name, "com0") == 0) + if (grub_strcmp (port->name, + (grub_arch_machine == GRUB_ARCH_MACHINE_YEELOONG) + ? "com0" : "com2") == 0) { grub_term_register_input_active ("serial_*", in); grub_term_register_output_active ("serial_*", out); } else -#endif { - grub_term_register_input ("serial_*", in); - grub_term_register_output ("serial_*", out); + grub_term_register_input_inactive ("serial_*", in); + grub_term_register_output_inactive ("serial_*", out); } +#else + grub_term_register_input ("serial_*", in); + grub_term_register_output ("serial_*", out); +#endif return GRUB_ERR_NONE; } diff --git a/include/grub/mips/yeeloong/kernel.h b/include/grub/mips/yeeloong/kernel.h index 15cf9f9fd..857b37a15 100644 --- a/include/grub/mips/yeeloong/kernel.h +++ b/include/grub/mips/yeeloong/kernel.h @@ -21,11 +21,16 @@ #include +#define GRUB_ARCH_MACHINE_YEELOONG 0 +#define GRUB_ARCH_MACHINE_FULOONG 1 + #ifndef ASM_FILE void EXPORT_FUNC (grub_reboot) (void) __attribute__ ((noreturn)); void EXPORT_FUNC (grub_halt) (void) __attribute__ ((noreturn)); +extern grub_uint32_t EXPORT_VAR (grub_arch_machine); + #endif #endif /* ! GRUB_KERNEL_MACHINE_HEADER */ diff --git a/include/grub/mips/yeeloong/serial.h b/include/grub/mips/yeeloong/serial.h index ebe3638a1..45e6d8457 100644 --- a/include/grub/mips/yeeloong/serial.h +++ b/include/grub/mips/yeeloong/serial.h @@ -19,11 +19,14 @@ #ifndef GRUB_MACHINE_SERIAL_HEADER #define GRUB_MACHINE_SERIAL_HEADER 1 -#define GRUB_MACHINE_SERIAL_DIVISOR_115200 2 -#define GRUB_MACHINE_SERIAL_PORT 0xbff003f8 +#define GRUB_MACHINE_SERIAL_PORT0_DIVISOR_115200 2 +#define GRUB_MACHINE_SERIAL_PORT2_DIVISOR_115200 1 +#define GRUB_MACHINE_SERIAL_PORT0 0xbff003f8 +#define GRUB_MACHINE_SERIAL_PORT1 0xbfd003f8 +#define GRUB_MACHINE_SERIAL_PORT2 0xbfd002f8 #ifndef ASM_FILE -#define GRUB_MACHINE_SERIAL_PORTS { GRUB_MACHINE_SERIAL_PORT } +#define GRUB_MACHINE_SERIAL_PORTS { GRUB_MACHINE_SERIAL_PORT0, GRUB_MACHINE_SERIAL_PORT1, GRUB_MACHINE_SERIAL_PORT2 } #else #endif diff --git a/include/grub/term.h b/include/grub/term.h index dbcb2f52c..e9efc3f84 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -251,6 +251,14 @@ grub_term_register_input (const char *name __attribute__ ((unused)), } } +static inline void +grub_term_register_input_inactive (const char *name __attribute__ ((unused)), + grub_term_input_t term) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled), + GRUB_AS_LIST (term)); +} + static inline void grub_term_register_input_active (const char *name __attribute__ ((unused)), grub_term_input_t term) @@ -275,6 +283,14 @@ grub_term_register_output (const char *name __attribute__ ((unused)), } } +static inline void +grub_term_register_output_inactive (const char *name __attribute__ ((unused)), + grub_term_output_t term) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled), + GRUB_AS_LIST (term)); +} + static inline void grub_term_register_output_active (const char *name __attribute__ ((unused)), grub_term_output_t term) From 8f49d04c98338c29bddeb1f407500f954a78494e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 18 Jan 2011 19:04:27 +0100 Subject: [PATCH 149/406] machtype autodetection --- grub-core/boot/mips/startup_raw.S | 56 ++++++++++++++++++++++++-- grub-core/boot/mips/yeeloong/fwstart.S | 3 +- grub-core/kern/mips/startup.S | 1 + 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index c41ce8257..d8789982f 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -20,6 +20,7 @@ #include #include #include +#include #include #define BASE_ADDR 8 @@ -54,10 +55,12 @@ codestart: move $s3, $zero move $s4, $zero move $s5, $zero + move $s7, $zero /* $a2 has the environment. */ - addiu $t0, $a2, 1 - beq $t0, $zero, argdone + addiu $t0, $zero, -0x10 + and $t1, $a2, $t0 + beq $t0, $t1, argfw nop move $t0, $a2 argcont: @@ -72,11 +75,19 @@ argcont: nop ;\ b 2f;\ move reg, $v0; \ -1: +1: +#define DO_CHECKT1(str, val) \ + move $t6, $t1 ;\ + addiu $t7, $s0, (str - base);\ + bal do_check ;\ + li $t2, val + DO_PARSE (busclockstr, $s2) DO_PARSE (cpuclockstr, $s3) DO_PARSE (memsizestr, $s4) DO_PARSE (highmemsizestr, $s5) + DO_CHECKT1 (pmon_yeeloong_verstr, GRUB_ARCH_MACHINE_YEELOONG) + DO_CHECKT1 (pmon_fuloong_verstr, GRUB_ARCH_MACHINE_FULOONG) 2: b argcont addiu $t0, $t0, 4 @@ -120,8 +131,47 @@ busclockstr: .asciiz "busclock=" cpuclockstr: .asciiz "cpuclock=" memsizestr: .asciiz "memsize=" highmemsizestr: .asciiz "highmemsize=" +machtype_yeeloong_str1: .asciiz "machtype=8.9" +machtype_yeeloong_str2: .asciiz "machtype=lemote-yeeloong-" +machtype_fuloong_str: .asciiz "machtype=lemote-fuloong-" +pmon_yeeloong_str: .asciiz "PMON_VER=LM8" +pmon_fuloong_str: .asciiz "PMON_VER=LM6" +pmon_yeeloong_verstr: .asciiz "Version=LM8" +pmon_fuloong_verstr: .asciiz "Version=LM6" .p2align 2 + argdone: + beq $a0, $zero, cmdlinedone + nop +#define DO_CHECKA1(str, val) \ + lw $t6, 0($a1) ;\ + addiu $t7, $s0, (str - base);\ + bal do_check ;\ + li $t2, val + DO_CHECKA1 (machtype_yeeloong_str1, GRUB_ARCH_MACHINE_YEELOONG) + DO_CHECKA1 (machtype_yeeloong_str2, GRUB_ARCH_MACHINE_YEELOONG) + DO_CHECKA1 (pmon_yeeloong_str, GRUB_ARCH_MACHINE_YEELOONG) + DO_CHECKA1 (machtype_fuloong_str, GRUB_ARCH_MACHINE_FULOONG) + DO_CHECKA1 (pmon_fuloong_str, GRUB_ARCH_MACHINE_FULOONG) + addiu $a0, $a0, -1 + b argdone + addiu $a1, $a1, 4 +do_check: + lb $t4, 0($t7) + beq $t4, $zero, 1f + lb $t3, 0($t6) + bne $t3, $t4, 2f + addiu $t6, $t6, 1 + b do_check + addiu $t7, $t7, 1 +1: + move $s7, $t2 +2: + jr $ra + nop +argfw: + not $s7, $a2 +cmdlinedone: #endif /* Copy the decompressor. */ lui $t1, %hi(base) diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S index 4c2fe5543..bc59c1174 100644 --- a/grub-core/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/yeeloong/fwstart.S @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -629,6 +630,6 @@ continue: lui $t0, %hi(cached_continue - 0x20000000) addiu $t0, $t0, %lo(cached_continue - 0x20000000) jr $t0 - addiu $a2, $zero, -1 + addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_YEELOONG) cached_continue: \ No newline at end of file diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index 4bf4c1762..999beee79 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -74,6 +74,7 @@ cont: sw $s3, 4($t1) sw $s4, 8($t1) sw $s5, 12($t1) + sw $s7, 16($t1) #endif /* Move the modules out of BSS. */ From cfe6539cfe8146ea27ec30fa1ecf55f95b331601 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 18 Jan 2011 19:05:12 +0100 Subject: [PATCH 150/406] initialise keylayout on fuloong too --- grub-core/kern/mips/yeeloong/init.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/grub-core/kern/mips/yeeloong/init.c b/grub-core/kern/mips/yeeloong/init.c index 6787a205d..b444caf06 100644 --- a/grub-core/kern/mips/yeeloong/init.c +++ b/grub-core/kern/mips/yeeloong/init.c @@ -208,11 +208,9 @@ grub_machine_init (void) grub_font_init (); grub_gfxterm_init (); + grub_keylayouts_init (); if (grub_arch_machine == GRUB_ARCH_MACHINE_YEELOONG) - { - grub_keylayouts_init (); - grub_at_keyboard_init (); - } + grub_at_keyboard_init (); grub_terminfo_init (); grub_serial_init (); From 99388e0cf8e7c3e8f3bdf3d828caddade7b68613 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 18 Jan 2011 19:39:12 +0100 Subject: [PATCH 151/406] Fuloong shutdown support --- grub-core/kern/mips/yeeloong/init.c | 26 ++++++++++++++++++++++---- include/grub/mips/loongson.h | 2 +- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/grub-core/kern/mips/yeeloong/init.c b/grub-core/kern/mips/yeeloong/init.c index b444caf06..7526111cc 100644 --- a/grub-core/kern/mips/yeeloong/init.c +++ b/grub-core/kern/mips/yeeloong/init.c @@ -226,10 +226,28 @@ grub_machine_fini (void) void grub_halt (void) { - grub_outb (grub_inb (GRUB_CPU_LOONGSON_GPIOCFG) - & ~GRUB_CPU_LOONGSON_SHUTDOWN_GPIO, GRUB_CPU_LOONGSON_GPIOCFG); - - grub_millisleep (1500); + switch (grub_arch_machine) + { + case GRUB_ARCH_MACHINE_FULOONG: + { + grub_pci_device_t dev; + grub_port_t p; + if (grub_cs5536_find (&dev)) + { + p = (grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_GPIO_BAR) + & GRUB_CS5536_LBAR_ADDR_MASK) + GRUB_MACHINE_PCI_IO_BASE; + grub_outl ((1 << 13), p + 4); + grub_outl ((1 << 29), p); + grub_millisleep (5000); + } + } + break; + case GRUB_ARCH_MACHINE_YEELOONG: + grub_outb (grub_inb (GRUB_CPU_LOONGSON_GPIOCFG) + & ~GRUB_CPU_YEELOONG_SHUTDOWN_GPIO, GRUB_CPU_LOONGSON_GPIOCFG); + grub_millisleep (1500); + break; + } grub_printf ("Shutdown failed\n"); grub_refresh (); diff --git a/include/grub/mips/loongson.h b/include/grub/mips/loongson.h index 6cb1178d5..e9f1583ab 100644 --- a/include/grub/mips/loongson.h +++ b/include/grub/mips/loongson.h @@ -85,6 +85,6 @@ #define GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI 0xbfe00154 #define GRUB_CPU_LOONGSON_GPIOCFG 0xbfe00120 -#define GRUB_CPU_LOONGSON_SHUTDOWN_GPIO 1 +#define GRUB_CPU_YEELOONG_SHUTDOWN_GPIO 1 #endif From ea9e017dc5064da8a8f8d336785bd1937d1b6737 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Jan 2011 21:50:09 +0100 Subject: [PATCH 152/406] Correct address to unsupported memory type string --- grub-core/boot/mips/yeeloong/fwstart.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S index bc59c1174..560e0ed8c 100644 --- a/grub-core/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/yeeloong/fwstart.S @@ -124,7 +124,7 @@ __start: ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2 lui $a0, %hi(unimplemented_memory_type) bne $t0, $v0, fatal - addiu $a0, $a0, %hi(unimplemented_memory_type) + addiu $a0, $a0, %lo(unimplemented_memory_type) /* And here is our goal: DDR2 controller initialisation. */ lui $t0, %hi(GRUB_CPU_LOONGSON_CORECFG) From 9b4ad415e649d02565d429d539c7800df967b2b6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Jan 2011 21:52:43 +0100 Subject: [PATCH 153/406] Retry the scan for CS5536 in case of failure --- grub-core/boot/mips/yeeloong/fwstart.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S index 560e0ed8c..144c76ac6 100644 --- a/grub-core/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/yeeloong/fwstart.S @@ -43,17 +43,18 @@ __start: /* $t4 chooses device in priority encoding. */ /* Resulting value is kept in GRUB_MACHINE_PCI_CONF_CTRL_REG. This way we don't need to sacrifice a register for it. */ +retry_cs5536: /* We have only one bus (0). Function is 0. */ lui $t0, %hi(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE) lui $t3, %hi(GRUB_CS5536_PCIID) addiu $t3, $t3, %lo(GRUB_CS5536_PCIID) ori $t4, $zero, 1 - lui $a0, %hi(no_cs5536) 1: andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES) - 1) - beql $t4, $zero, fatal - addiu $a0, $a0, %lo(no_cs5536) + /* In case of failure try again. CS5536 may be slow to come up. */ + beql $t4, $zero, retry_cs5536 + nop sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0) lw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_PCI_ID) ($t1) bnel $t2, $t3, 1b @@ -383,7 +384,6 @@ read_spd_fail: ori $v0, $v0, 0x100 notification_string: .asciz "GRUB " -no_cs5536: .asciz "No CS5536 found.\n\r" cs5536_found: .asciz "CS5536 at " sm_failed: .asciz "SM transaction failed.\n\r" unhandled_tlb_refill: .asciz "Unhandled TLB refill.\n\r" From 0889c3401c4b2c2c9359fdfe06a7169f8b9b4bc4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Jan 2011 21:56:00 +0100 Subject: [PATCH 154/406] Explicitly enable MSR mailbox --- grub-core/boot/mips/yeeloong/fwstart.S | 4 ++++ include/grub/cs5536.h | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S index 144c76ac6..184aff5d2 100644 --- a/grub-core/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/yeeloong/fwstart.S @@ -66,6 +66,10 @@ retry_cs5536: move $a0, $t4 /* Initialise SMBus controller. */ + lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE) + li $t1, GRUB_CS5536_MSR_MAILBOX_CONFIG_ENABLED + sw $t1, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_CONFIG) ($t0) + /* Set GPIO LBAR. */ lui $a0, %hi(GRUB_CS5536_MSR_GPIO_BAR) addiu $a0, $a0, %lo(GRUB_CS5536_MSR_GPIO_BAR) diff --git a/include/grub/cs5536.h b/include/grub/cs5536.h index cd17e11fc..de0d6df7e 100644 --- a/include/grub/cs5536.h +++ b/include/grub/cs5536.h @@ -26,9 +26,11 @@ #endif #define GRUB_CS5536_PCIID 0x208f1022 -#define GRUB_CS5536_MSR_MAILBOX_ADDR 0xf4 -#define GRUB_CS5536_MSR_MAILBOX_DATA0 0xf8 -#define GRUB_CS5536_MSR_MAILBOX_DATA1 0xfc +#define GRUB_CS5536_MSR_MAILBOX_CONFIG_ENABLED 0x1 +#define GRUB_CS5536_MSR_MAILBOX_CONFIG 0xf0 +#define GRUB_CS5536_MSR_MAILBOX_ADDR 0xf4 +#define GRUB_CS5536_MSR_MAILBOX_DATA0 0xf8 +#define GRUB_CS5536_MSR_MAILBOX_DATA1 0xfc #define GRUB_CS5536_MSR_IRQ_MAP_BAR 0x80000008 #define GRUB_CS5536_MSR_SMB_BAR 0x8000000b From 1ccfc5d20139637a65ab81bb3c606e122eb341f4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 24 Jan 2011 00:38:30 +0100 Subject: [PATCH 155/406] Move GPIO init to fwstart.S for convenience --- grub-core/boot/mips/yeeloong/fwstart.S | 70 ++++++++++++++++++++++---- grub-core/bus/cs5536.c | 31 ------------ 2 files changed, 61 insertions(+), 40 deletions(-) diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S index 184aff5d2..41559ffa4 100644 --- a/grub-core/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/yeeloong/fwstart.S @@ -65,7 +65,6 @@ retry_cs5536: bal printhex move $a0, $t4 - /* Initialise SMBus controller. */ lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE) li $t1, GRUB_CS5536_MSR_MAILBOX_CONFIG_ENABLED sw $t1, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_CONFIG) ($t0) @@ -79,6 +78,10 @@ retry_cs5536: ori $a2, $zero, ((GRUB_CS5536_LBAR_MASK_MASK \ | GRUB_CS5536_LBAR_ENABLE) >> 32) + bal gpio_init + nop + + /* Initialise SMBus controller. */ /* Set SMBUS LBAR. */ lui $a0, %hi(GRUB_CS5536_MSR_SMB_BAR) addiu $a0, $a0, %lo(GRUB_CS5536_MSR_SMB_BAR) @@ -92,14 +95,6 @@ retry_cs5536: bal message addiu $a0, $a0, %lo(smbus_enabled) - /* Enable SMBus controller pins. */ - lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO) - ori $t1, $zero, GRUB_GPIO_SMBUS_PINS - sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_OUT_EN) ($t0) - sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_OUT_AUX1) ($t0) - sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_IN_EN) ($t0) - sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_IN_AUX1) ($t0) - lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS) /* Disable SMB. */ @@ -215,6 +210,24 @@ other_exception: b fatal addiu $a0, $a0, %lo(unhandled_exception) +gpio_init: + lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO) + addiu $t0, $t0, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO) + lui $t1, %hi (gpio_dump) + addiu $t1, $t1, %lo (gpio_dump) + +1: + lw $t2, 0($t1) + sw $t2, 0($t0) + addiu $t0, $t0, 4 + addiu $t1, $t1, 4 + lui $t2, %hi (gpio_dump_end) + addiu $t2, $t2, %lo (gpio_dump_end) + bne $t1, $t2, 1b + nop + jr $ra + nop + /* Same as similarly named C function but in asm since we need it early. */ /* In: none. Out: none. Clobbered: $t0, $t1, $a0. */ @@ -434,6 +447,45 @@ regdump: .quad 0 /* 1b */ .quad 0 /* 1c */ +/* Dump of GPIO connections. FIXME: Remove useless and macroify. */ +gpio_dump: +#ifdef FULOONG + .long 0xffff0000, 0x2eefd110, 0xffff0000, 0xffff0000 + .long 0x2eefd110, 0xffff0000, 0x1000efff, 0xefff1000 + .long 0x3df3c20c, 0xffff0000, 0xffff0000, 0xffff0000 + .long 0x7df3820c, 0x3df3c20c, 0xffff0000, 0x00000000 + .long 0xffff0000, 0xffff0000, 0x3de3c21c, 0x3d83c27c + .long 0x00000000, 0x00000000, 0x00000000, 0x00000000 + .long 0x00000000, 0x00000000, 0x00000000, 0x00000000 + .long 0x00000000, 0x00000000, 0x00000000, 0x00000000 + .long 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000 + .long 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000 + .long 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000 + .long 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000 + .long 0xffff0000, 0xffff0000, 0xefff1000, 0xefff1000 + .long 0x00000000, 0x00000000, 0x00000000, 0x00000000 + .long 0x00000000, 0x00000000, 0x00000000, 0x00000000 + .long 0x00000000, 0x00000000, 0x00000000, 0x00000000 +#else + .long 0xffff0000, 0x2ffdd002, 0xffff0000, 0xffff0000 + .long 0x2fffd000, 0xffff0000, 0x1000efff, 0xefff1000 + .long 0x3ffbc004, 0xffff0000, 0xffff0000, 0xffff0000 + .long 0x3ffbc004, 0x3ffbc004, 0xffff0000, 0x00000000 + .long 0xffff0000, 0xffff0000, 0x3ffbc004, 0x3f9bc064 + .long 0x00000000, 0x00000000, 0x00000000, 0x00000000 + .long 0x00000000, 0x00000000, 0x00000000, 0x00000000 + .long 0x00000000, 0x00000000, 0x00000000, 0x00000000 + .long 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000 + .long 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000 + .long 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000 + .long 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000 + .long 0xffff0000, 0xffff0000, 0xefff1000, 0xffff0000 + .long 0x00000000, 0x00000000, 0x00000000, 0x00000000 + .long 0x00000000, 0x00000000, 0x00000000, 0x00000000 + .long 0x00000000, 0x50000000, 0x00000000, 0x00000000 +#endif +gpio_dump_end: + .p2align write_dumpreg: diff --git a/grub-core/bus/cs5536.c b/grub-core/bus/cs5536.c index 088f4dfc1..690b8f29a 100644 --- a/grub-core/bus/cs5536.c +++ b/grub-core/bus/cs5536.c @@ -213,26 +213,6 @@ grub_cs5536_read_spd (grub_port_t smbbase, grub_uint8_t dev, return GRUB_ERR_NONE; } -/* Dump of GPIO connections. FIXME: Remove useless and macroify. */ -static grub_uint32_t gpiodump[] = { - 0xffff0000, 0x2ffdd002, 0xffff0000, 0xffff0000, - 0x2fffd000, 0xffff0000, 0x1000efff, 0xefff1000, - 0x3ffbc004, 0xffff0000, 0xffff0000, 0xffff0000, - 0x3ffbc004, 0x3ffbc004, 0xffff0000, 0x00000000, - 0xffff0000, 0xffff0000, 0x3ffbc004, 0x3f9bc064, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, - 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000, - 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000, - 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000, - 0xffff0000, 0xffff0000, 0xefff1000, 0xffff0000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x50000000, 0x00000000, 0x00000000, -}; - static inline void set_io_space (grub_pci_device_t dev, int num, grub_uint16_t start, grub_uint16_t len) @@ -273,17 +253,6 @@ set_p2d (grub_pci_device_t dev, int num, int dest, grub_uint32_t start) void grub_cs5536_init_geode (grub_pci_device_t dev) { - int i; - - /* Make sure GPIO is where we expect it to be. */ - grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_GPIO_BAR, - GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_GPIO); - - /* Setup GPIO. */ - for (i = 0; i < (int) ARRAY_SIZE (gpiodump); i++) - ((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_IO_BASE - + GRUB_CS5536_LBAR_GPIO)) [i] = gpiodump[i]; - /* Enable more BARs. */ grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_IRQ_MAP_BAR, GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_IRQ_MAP); From 5ea788ada075c32a171390c26d06e596eefd2412 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 24 Jan 2011 00:40:03 +0100 Subject: [PATCH 156/406] Geode UART2 (for Fuloong) fwstart.img support --- grub-core/boot/mips/yeeloong/fwstart.S | 42 +++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S index 41559ffa4..1a1a44c85 100644 --- a/grub-core/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/yeeloong/fwstart.S @@ -26,8 +26,13 @@ #include #include +#ifdef FULOONG +#define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT2 +#define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT2_DIVISOR_115200 +#else #define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT0 #define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT0_DIVISOR_115200 +#endif .set noreorder .set noat @@ -37,8 +42,14 @@ start: _start: __start: + /* Put serial init as soon as possible. But on Fuloong serial is past + Geode, so on Fuloong we need Geode first. + */ +#ifndef FULOONG bal serial_hw_init nop +#endif + /* Find CS5536 controller. */ /* $t4 chooses device in priority encoding. */ /* Resulting value is kept in GRUB_MACHINE_PCI_CONF_CTRL_REG. @@ -60,10 +71,12 @@ retry_cs5536: bnel $t2, $t3, 1b sll $t4, $t4, 1 +#ifndef FULOONG bal message addiu $a0, $a0, %lo(cs5536_found) bal printhex move $a0, $t4 +#endif lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE) li $t1, GRUB_CS5536_MSR_MAILBOX_CONFIG_ENABLED @@ -81,6 +94,11 @@ retry_cs5536: bal gpio_init nop +#ifdef FULOONG + bal serial_hw_init + nop +#endif + /* Initialise SMBus controller. */ /* Set SMBUS LBAR. */ lui $a0, %hi(GRUB_CS5536_MSR_SMB_BAR) @@ -230,8 +248,29 @@ gpio_init: /* Same as similarly named C function but in asm since we need it early. */ - /* In: none. Out: none. Clobbered: $t0, $t1, $a0. */ + /* In: none. Out: none. Clobbered: $t0, $t1, $t2, $a0, $a1, $a2. */ serial_hw_init: + move $t2, $ra +#ifdef FULOONG + lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_LEG_IO) + addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_LEG_IO) + li $a1, 0x04570003 + bal wrmsr + move $a2, $zero + + lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_UART1_CONF) + addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_UART1_CONF) + li $a1, 2 + bal wrmsr + move $a2, $zero + + lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_UART2_CONF) + addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_UART2_CONF) + li $a1, 2 + bal wrmsr + move $a2, $zero +#endif + lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT) /* Turn off the interrupt. */ @@ -261,6 +300,7 @@ serial_hw_init: /* Let message return to original caller. */ lui $a0, %hi(notification_string) addiu $a0, $a0, %lo(notification_string) + move $ra, $t2 /* Print message on serial console. */ /* In: $a0 = asciiz message. Out: none. Clobbered: $t0, $t1, $a0. */ From c69ef8a0ab622769bc7ede5c45b36a38e2203035 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 24 Jan 2011 00:40:59 +0100 Subject: [PATCH 157/406] pass machine type from fwstart.S. Minor cleanup --- grub-core/boot/mips/yeeloong/fwstart.S | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S index 1a1a44c85..8c0963ba3 100644 --- a/grub-core/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/yeeloong/fwstart.S @@ -726,6 +726,10 @@ continue: lui $t0, %hi(cached_continue - 0x20000000) addiu $t0, $t0, %lo(cached_continue - 0x20000000) jr $t0 +#ifdef FULOONG + addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_FULOONG) +#else addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_YEELOONG) +#endif -cached_continue: \ No newline at end of file +cached_continue: From 9f7322f50e80df1cd67ffda5bbd148b6bcefcd80 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 24 Jan 2011 00:47:36 +0100 Subject: [PATCH 158/406] Add missing UART2 definitions --- include/grub/cs5536.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/grub/cs5536.h b/include/grub/cs5536.h index de0d6df7e..90a39df44 100644 --- a/include/grub/cs5536.h +++ b/include/grub/cs5536.h @@ -80,6 +80,8 @@ #define GRUB_CS5536_DIVIL_LPC_INTERRUPTS 0x1002 #define GRUB_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL 0x8000004e #define GRUB_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL_ENABLE 0x80 +#define GRUB_CS5536_MSR_DIVIL_UART1_CONF 0x8000003a +#define GRUB_CS5536_MSR_DIVIL_UART2_CONF 0x8000003e #define GRUB_CS5536_MSR_USB_OHCI_BASE 0x40000008 #define GRUB_CS5536_MSR_USB_EHCI_BASE 0x40000009 From 44626c910ec2a8a4ebea96b590a549610301735b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 24 Jan 2011 01:45:11 +0100 Subject: [PATCH 159/406] Add fuloong registers for RAM controller --- grub-core/boot/mips/yeeloong/fwstart.S | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S index 8c0963ba3..995aa5071 100644 --- a/grub-core/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/yeeloong/fwstart.S @@ -465,14 +465,22 @@ regdump: .quad 0x0100020200010101 /* 4 */ .quad 0x0a04030603050203 /* 6 */ .quad 0x0f0e040000010a0b /* 7 */ +#ifdef FULOONG + .quad 0x0000000100000001 /* 8 */ +#else .quad 0x0000010200000102 /* 8 */ +#endif .quad 0x0000060c00000000 /* 9 */ .quad 0x2323233f3f1f0200 /* a */ .quad 0x5f7f232323232323 /* b */ .quad 0x002a3c0615000000 /* c */ .quad 0x002a002a002a002a /* d */ .quad 0x002a002a002a002a /* e */ +#ifdef FULOONG + .quad 0x00b40020005b0004 /* f */ +#else .quad 0x00b40020006d0004 /* f */ +#endif .quad 0x070007ff00000087 /* 10 */ .quad 0x000000000016101f /* 11 */ .quad 0x001c000000000000 /* 12 */ From 88906eaa69c3f117ef7416b225c33f6bdaf7a2c4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 24 Jan 2011 01:46:00 +0100 Subject: [PATCH 160/406] Fix accidental disable of Geode UARTs --- grub-core/boot/mips/yeeloong/fwstart.S | 7 ++++++- grub-core/bus/cs5536.c | 25 ++++++++++++++++++++----- include/grub/cs5536.h | 2 ++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S index 995aa5071..d25ff1a5b 100644 --- a/grub-core/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/yeeloong/fwstart.S @@ -254,7 +254,12 @@ serial_hw_init: #ifdef FULOONG lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_LEG_IO) addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_LEG_IO) - li $a1, 0x04570003 + li $a1, (GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3 \ + | GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP \ + | GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86 \ + | GRUB_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1 \ + | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0 \ + | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1) bal wrmsr move $a2, $zero diff --git a/grub-core/bus/cs5536.c b/grub-core/bus/cs5536.c index 690b8f29a..f5b2089e3 100644 --- a/grub-core/bus/cs5536.c +++ b/grub-core/bus/cs5536.c @@ -21,6 +21,7 @@ #include #include #include +#include int grub_cs5536_find (grub_pci_device_t *devp) @@ -264,11 +265,25 @@ grub_cs5536_init_geode (grub_pci_device_t dev) GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_PM); /* Setup DIVIL. */ - grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_LEG_IO, - GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86 - | GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP - | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0 - | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1); + switch (grub_arch_machine) + { + case GRUB_ARCH_MACHINE_YEELOONG: + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_LEG_IO, + GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86 + | GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP + | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0 + | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1); + break; + case GRUB_ARCH_MACHINE_FULOONG: + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_LEG_IO, + GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3 + | GRUB_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1 + | GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86 + | GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP + | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0 + | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1); + break; + } grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_PRIMARY_MASK, (~GRUB_CS5536_DIVIL_LPC_INTERRUPTS) & 0xffff); grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_LPC_MASK, diff --git a/include/grub/cs5536.h b/include/grub/cs5536.h index 90a39df44..103b30633 100644 --- a/include/grub/cs5536.h +++ b/include/grub/cs5536.h @@ -75,6 +75,8 @@ #define GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1 0x00000002 #define GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86 0x10000000 #define GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP 0x04000000 +#define GRUB_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1 0x00070000 +#define GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3 0x00500000 #define GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_PRIMARY_MASK 0x80000024 #define GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_LPC_MASK 0x80000025 #define GRUB_CS5536_DIVIL_LPC_INTERRUPTS 0x1002 From dc1c21edb7be8bd892204981c31cd496f65e9a35 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 24 Jan 2011 01:49:25 +0100 Subject: [PATCH 161/406] Add informative #define --- grub-core/boot/mips/yeeloong/fwstart.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S index d25ff1a5b..41ed0063b 100644 --- a/grub-core/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/yeeloong/fwstart.S @@ -26,6 +26,8 @@ #include #include +/* #define FULOONG 1 */ + #ifdef FULOONG #define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT2 #define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT2_DIVISOR_115200 From a9fa2a22d7f7e8f696c6cbca6103f3a62528c3a8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 24 Jan 2011 02:20:04 +0100 Subject: [PATCH 162/406] Integrate Fuloong firmware port into build system and grub-mkimage --- grub-core/Makefile.core.def | 8 ++ grub-core/boot/mips/yeeloong/fuloong.S | 2 + grub-core/boot/mips/yeeloong/fwstart.S | 2 - util/grub-mkimage.c | 144 +++++++++++++++++-------- 4 files changed, 108 insertions(+), 48 deletions(-) create mode 100644 grub-core/boot/mips/yeeloong/fuloong.S diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index a67c805c9..e651e1596 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -329,6 +329,14 @@ image = { enable = mips_yeeloong; }; +image = { + name = fwstart_fuloong; + mips_yeeloong = boot/mips/yeeloong/fuloong.S; + objcopyflags = '-O binary'; + ldflags = '-static-libgcc -lgcc -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; + enable = mips_yeeloong; +}; + module = { name = trig; common_nodist = trigtables.c; diff --git a/grub-core/boot/mips/yeeloong/fuloong.S b/grub-core/boot/mips/yeeloong/fuloong.S new file mode 100644 index 000000000..5df0d54c1 --- /dev/null +++ b/grub-core/boot/mips/yeeloong/fuloong.S @@ -0,0 +1,2 @@ +#define FULOONG 1 +#include "fwstart.S" diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S index 41ed0063b..d25ff1a5b 100644 --- a/grub-core/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/yeeloong/fwstart.S @@ -26,8 +26,6 @@ #include #include -/* #define FULOONG 1 */ - #ifdef FULOONG #define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT2 #define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT2_DIVISOR_115200 diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 0375d3ed5..663e60f08 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -58,14 +58,15 @@ typedef enum { struct image_target_desc { - const char *name; + const char *dirname; + const char *names[6]; grub_size_t voidp_sizeof; int bigendian; enum { IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT, IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_I386_IEEE1275, IMAGE_YEELOONG_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH, - IMAGE_I386_PC_PXE + IMAGE_FULOONG_FLASH, IMAGE_I386_PC_PXE } id; enum { @@ -92,7 +93,8 @@ struct image_target_desc struct image_target_desc image_targets[] = { { - .name = "i386-coreboot", + .dirname = "i386-coreboot", + .names = { "i386-coreboot", NULL }, .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_COREBOOT, @@ -114,7 +116,8 @@ struct image_target_desc image_targets[] = .mod_align = GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN }, { - .name = "i386-multiboot", + .dirname = "i386-multiboot", + .names = { "i386-multiboot", NULL}, .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_COREBOOT, @@ -136,7 +139,8 @@ struct image_target_desc image_targets[] = .mod_align = GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN }, { - .name = "i386-pc", + .dirname = "i386-pc", + .names = { "i386-pc", NULL }, .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_I386_PC, @@ -154,7 +158,8 @@ struct image_target_desc image_targets[] = .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR }, { - .name = "i386-pc-pxe", + .dirname = "i386-pc", + .names = { "i386-pc-pxe", NULL }, .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_I386_PC_PXE, @@ -172,7 +177,8 @@ struct image_target_desc image_targets[] = .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR }, { - .name = "i386-efi", + .dirname = "i386-efi", + .names = { "i386-efi", NULL }, .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_EFI, @@ -194,7 +200,8 @@ struct image_target_desc image_targets[] = .install_bsd_part = TARGET_NO_FIELD, }, { - .name = "i386-ieee1275", + .dirname = "i386-ieee1275", + .names = { "i386-ieee1275", NULL }, .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_I386_IEEE1275, @@ -216,7 +223,8 @@ struct image_target_desc image_targets[] = .link_align = 4, }, { - .name = "i386-qemu", + .dirname = "i386-qemu", + .names = { "i386-qemu", NULL }, .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_QEMU, @@ -234,7 +242,8 @@ struct image_target_desc image_targets[] = .link_addr = GRUB_KERNEL_I386_QEMU_LINK_ADDR }, { - .name = "x86_64-efi", + .dirname = "x86_64-efi", + .names = { "x86_64-efi", NULL }, .voidp_sizeof = 8, .bigendian = 0, .id = IMAGE_EFI, @@ -256,7 +265,8 @@ struct image_target_desc image_targets[] = .install_bsd_part = TARGET_NO_FIELD, }, { - .name = "mipsel-yeeloong-flash", + .dirname = "mipsel-yeeloong", + .names = { "mipsel-yeeloong-flash", NULL }, .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_YEELOONG_FLASH, @@ -277,7 +287,31 @@ struct image_target_desc image_targets[] = .default_compression = COMPRESSION_NONE }, { - .name = "mipsel-yeeloong-elf", + .dirname = "mipsel-yeeloong", + .names = { "mipsel-fuloong-flash", NULL }, + .voidp_sizeof = 4, + .bigendian = 0, + .id = IMAGE_FULOONG_FLASH, + .flags = PLATFORM_FLAGS_DECOMPRESSORS, + .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX, + .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END, + .raw_size = 0, + .total_module_size = GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE, + .compressed_size = TARGET_NO_FIELD, + .kernel_image_size = TARGET_NO_FIELD, + .section_align = 1, + .vaddr_offset = 0, + .install_dos_part = TARGET_NO_FIELD, + .install_bsd_part = TARGET_NO_FIELD, + .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR, + .elf_target = EM_MIPS, + .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN, + .default_compression = COMPRESSION_NONE + }, + { + .dirname = "mipsel-yeeloong", + .names = { "mipsel-loongson-elf", "mipsel-yeeloong-elf", + "mipsel-fuloong-elf", NULL }, .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_YEELOONG_ELF, @@ -298,7 +332,8 @@ struct image_target_desc image_targets[] = .default_compression = COMPRESSION_NONE }, { - .name = "powerpc-ieee1275", + .dirname = "powerpc-ieee1275", + .names = { "powerpc-ieee1275", NULL }, .voidp_sizeof = 4, .bigendian = 1, .id = IMAGE_PPC, @@ -320,7 +355,8 @@ struct image_target_desc image_targets[] = .link_align = 4 }, { - .name = "sparc64-ieee1275-raw", + .dirname = "sparc64-ieee1275", + .names = { "sparc64-ieee1275-raw", NULL }, .voidp_sizeof = 8, .bigendian = 1, .id = IMAGE_SPARC64_RAW, @@ -338,7 +374,8 @@ struct image_target_desc image_targets[] = .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR }, { - .name = "sparc64-ieee1275-aout", + .dirname = "sparc64-ieee1275", + .names = { "sparc64-ieee1275-aout", NULL }, .voidp_sizeof = 8, .bigendian = 1, .id = IMAGE_SPARC64_AOUT, @@ -1163,6 +1200,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], } break; case IMAGE_YEELOONG_FLASH: + case IMAGE_FULOONG_FLASH: { char *rom_img; size_t rom_size; @@ -1170,20 +1208,40 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], size_t boot_size; grub_uint8_t context[GRUB_MD_SHA512->contextsize]; /* fwstart.img is the only part which can't be testes by using *-elf - target. Check it against the checksum. This checksum is obtained with - sha512sum utility after compiling on Gnewsense. - */ - const grub_uint8_t fwstart_good_hash[] = - { 0x75, 0xbf, 0xa3, 0x0e, 0x7c, 0xd1, 0x03, 0x82, - 0xe1, 0x34, 0x55, 0xd7, 0x09, 0x1e, 0x6c, 0xcc, - 0xef, 0x08, 0x61, 0xc1, 0x3c, 0xd8, 0xc7, 0x9f, - 0xe8, 0x2d, 0x3d, 0xb2, 0xda, 0x41, 0xd3, 0x83, - 0xd7, 0xb8, 0xe3, 0xd7, 0x13, 0xec, 0x9b, 0xf6, - 0xf6, 0xae, 0x6b, 0x32, 0x29, 0xc1, 0x69, 0x82, - 0xfa, 0x65, 0x2d, 0x97, 0x3e, 0x83, 0x6e, 0x6c, - 0xce, 0x34, 0x10, 0x59, 0x74, 0x0e, 0x96, 0x26 }; - - boot_path = grub_util_get_path (dir, "fwstart.img"); + target. Check it against the checksum. */ + /* Wasn't retested after important changes. */ + const grub_uint8_t yeeloong_fwstart_good_hash[512 / 8] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + /* None yet. */ + const grub_uint8_t fuloong_fwstart_good_hash[512 / 8] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + const grub_uint8_t *fwstart_good_hash; + + if (image_target->id == IMAGE_FULOONG_FLASH) + { + fwstart_good_hash = fuloong_fwstart_good_hash; + boot_path = grub_util_get_path (dir, "fwstart_fuloong.img"); + } + else + { + fwstart_good_hash = yeeloong_fwstart_good_hash; + boot_path = grub_util_get_path (dir, "fwstart.img"); + } boot_size = grub_util_get_image_size (boot_path); boot_img = grub_util_read_image (boot_path); @@ -1403,12 +1461,12 @@ usage (int status) char *ptr; unsigned i; for (i = 0; i < ARRAY_SIZE (image_targets); i++) - format_len += strlen (image_targets[i].name) + 2; + format_len += strlen (image_targets[i].names[0]) + 2; ptr = formats = xmalloc (format_len); for (i = 0; i < ARRAY_SIZE (image_targets); i++) { - strcpy (ptr, image_targets[i].name); - ptr += strlen (image_targets[i].name); + strcpy (ptr, image_targets[i].names[0]); + ptr += strlen (image_targets[i].names[0]); *ptr++ = ','; *ptr++ = ' '; } @@ -1478,10 +1536,12 @@ main (int argc, char *argv[]) case 'O': { - unsigned i; + unsigned i, j; for (i = 0; i < ARRAY_SIZE (image_targets); i++) - if (strcmp (optarg, image_targets[i].name) == 0) - image_target = &image_targets[i]; + for (j = 0; image_targets[i].names[j] + && j < ARRAY_SIZE (image_targets[i].names); j++) + if (strcmp (optarg, image_targets[i].names[j]) == 0) + image_target = &image_targets[i]; if (!image_target) { printf ("unknown target format %s\n", optarg); @@ -1576,19 +1636,11 @@ main (int argc, char *argv[]) if (!dir) { - const char *last; - last = strchr (image_target->name, '-'); - if (last) - last = strchr (last + 1, '-'); - if (!last) - last = image_target->name + strlen (image_target->name); - dir = xmalloc (sizeof (GRUB_PKGLIBROOTDIR) + (last - image_target->name) - + 1); + dir = xmalloc (sizeof (GRUB_PKGLIBROOTDIR) + + grub_strlen (image_target->dirname) + 1); memcpy (dir, GRUB_PKGLIBROOTDIR, sizeof (GRUB_PKGLIBROOTDIR) - 1); *(dir + sizeof (GRUB_PKGLIBROOTDIR) - 1) = '/'; - memcpy (dir + sizeof (GRUB_PKGLIBROOTDIR), image_target->name, - last - image_target->name); - *(dir + sizeof (GRUB_PKGLIBROOTDIR) + (last - image_target->name)) = 0; + strcpy (dir + sizeof (GRUB_PKGLIBROOTDIR), image_target->dirname); } generate_image (dir, prefix ? : DEFAULT_DIRECTORY, fp, From 54da1febceee8e07edf6b58f31952648897ba689 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 19 Feb 2011 13:18:05 +0100 Subject: [PATCH 163/406] Rename mipsel-yeeloong to mipsel-loongson --- conf/Makefile.common | 2 +- configure.ac | 16 +++--- gentpl.py | 12 ++-- grub-core/Makefile.am | 2 +- grub-core/Makefile.core.def | 50 ++++++++--------- .../mips/{yeeloong => loongson}/fuloong.S | 0 .../mips/{yeeloong => loongson}/fwstart.S | 6 +- grub-core/boot/mips/startup_raw.S | 2 +- grub-core/bus/pci.c | 12 ++-- .../mips/{yeeloong => loongson}/lsspd.c | 0 grub-core/kern/main.c | 4 +- .../kern/mips/{yeeloong => loongson}/init.c | 6 +- grub-core/kern/mips/startup.S | 6 +- grub-core/loader/mips/linux.c | 8 +-- .../mips/{yeeloong => loongson}/uppermem.c | 0 grub-core/term/at_keyboard.c | 4 +- grub-core/term/ns8250.c | 8 +-- grub-core/term/serial.c | 4 +- .../mips/{yeeloong => loongson}/at_keyboard.h | 0 .../grub/mips/{yeeloong => loongson}/cmos.h | 0 include/grub/mips/{yeeloong => loongson}/ec.h | 0 .../grub/mips/{yeeloong => loongson}/kernel.h | 0 .../grub/mips/{yeeloong => loongson}/memory.h | 0 .../grub/mips/{yeeloong => loongson}/pci.h | 8 +-- .../grub/mips/{yeeloong => loongson}/serial.h | 0 .../grub/mips/{yeeloong => loongson}/time.h | 0 include/grub/offsets.h | 16 +++--- include/grub/serial.h | 2 +- util/grub-install.in | 6 +- util/grub-mkimage.c | 56 +++++++++---------- 30 files changed, 116 insertions(+), 114 deletions(-) rename grub-core/boot/mips/{yeeloong => loongson}/fuloong.S (100%) rename grub-core/boot/mips/{yeeloong => loongson}/fwstart.S (99%) rename grub-core/commands/mips/{yeeloong => loongson}/lsspd.c (100%) rename grub-core/kern/mips/{yeeloong => loongson}/init.c (98%) rename grub-core/mmap/mips/{yeeloong => loongson}/uppermem.c (100%) rename include/grub/mips/{yeeloong => loongson}/at_keyboard.h (100%) rename include/grub/mips/{yeeloong => loongson}/cmos.h (100%) rename include/grub/mips/{yeeloong => loongson}/ec.h (100%) rename include/grub/mips/{yeeloong => loongson}/kernel.h (100%) rename include/grub/mips/{yeeloong => loongson}/memory.h (100%) rename include/grub/mips/{yeeloong => loongson}/pci.h (95%) rename include/grub/mips/{yeeloong => loongson}/serial.h (100%) rename include/grub/mips/{yeeloong => loongson}/time.h (100%) diff --git a/conf/Makefile.common b/conf/Makefile.common index 32ca76d08..2c08d4df9 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -21,7 +21,7 @@ endif if COND_i386_ieee1275 CFLAGS_PLATFORM += -mrtd -mregparm=3 endif -if COND_mips_yeeloong +if COND_mips_loongson CFLAGS_PLATFORM += -mexplicit-relocs CPPFLAGS_PLATFORM = -DUSE_ASCII_FAILBACK CCASFLAGS_PLATFORM = -march=mips3 diff --git a/configure.ac b/configure.ac index c660ac41e..64d6daf2b 100644 --- a/configure.ac +++ b/configure.ac @@ -96,7 +96,7 @@ if test "x$with_platform" = x; then powerpc-*) platform=ieee1275 ;; powerpc64-*) platform=ieee1275 ;; sparc64-*) platform=ieee1275 ;; - mips-*) platform=yeeloong ;; + mips-*) platform=loongson ;; *) AC_MSG_ERROR([unsupported CPU: "$target_cpu"]) ;; esac else @@ -123,7 +123,9 @@ case "$target_cpu"-"$platform" in powerpc-ieee1275) ;; sparc64-ieee1275) ;; mips-qemu-mips) ;; - mips-yeeloong) ;; + mips-yeeloong) platform=loongson ;; + mips-fuloong) platform=loongson ;; + mips-loongson) ;; *-emu) ;; *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;; esac @@ -156,7 +158,7 @@ case "$platform" in qemu) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_QEMU=1" ;; pc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_PCBIOS=1" ;; emu) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_EMU=1" ;; - yeeloong) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_YEELOONG=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;; + loongson) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_LOONGSON=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;; qemu-mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_QEMU_MIPS=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;; esac case "$target_cpu" in @@ -219,8 +221,8 @@ for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do done done -if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" = xyeeloong ); then - AC_MSG_ERROR([qemu and yeeloong ports need unifont]) +if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" = xloongson ); then + AC_MSG_ERROR([qemu and loongson ports need unifont]) fi AC_SUBST([FONT_SOURCE]) @@ -398,7 +400,7 @@ if test "x$grub_cv_cc_fno_dwarf2_cfi_asm" = xyes; then TARGET_CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm" fi -if test "${target_cpu}-${platform}" = mips-yeeloong; then +if test "${target_cpu}-${platform}" = mips-loongson; then AC_CACHE_CHECK([whether -march=loongson2f works], [grub_cv_cc_march_loongson2f], [ SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -march=loongson2f" @@ -941,7 +943,7 @@ AM_CONDITIONAL([COND_i386_ieee1275], [test x$target_cpu = xi386 -a x$platform = AM_CONDITIONAL([COND_i386_coreboot], [test x$target_cpu = xi386 -a x$platform = xcoreboot]) AM_CONDITIONAL([COND_i386_multiboot], [test x$target_cpu = xi386 -a x$platform = xmultiboot]) AM_CONDITIONAL([COND_x86_64_efi], [test x$target_cpu = xx86_64 -a x$platform = xefi]) -AM_CONDITIONAL([COND_mips_yeeloong], [test x$target_cpu = xmips -a x$platform = xyeeloong]) +AM_CONDITIONAL([COND_mips_loongson], [test x$target_cpu = xmips -a x$platform = xloongson]) AM_CONDITIONAL([COND_mips_qemu_mips], [test x$target_cpu = xmips -a x$platform = xqemu_mips]) AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275]) AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275]) diff --git a/gentpl.py b/gentpl.py index a42a60667..17c6abfd8 100644 --- a/gentpl.py +++ b/gentpl.py @@ -6,7 +6,7 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_multiboot", "i386_ieee1275", "x86_64_efi", - "mips_yeeloong", "sparc64_ieee1275", + "mips_loongson", "sparc64_ieee1275", "powerpc_ieee1275" ] GROUPS = {} @@ -17,7 +17,7 @@ GROUPS["common"] = GRUB_PLATFORMS[:] GROUPS["i386"] = [ "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_multiboot", "i386_ieee1275" ] GROUPS["x86_64"] = [ "x86_64_efi" ] GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"] -GROUPS["mips"] = [ "mips_yeeloong" ] +GROUPS["mips"] = [ "mips_loongson" ] GROUPS["sparc64"] = [ "sparc64_ieee1275" ] GROUPS["powerpc"] = [ "powerpc_ieee1275" ] @@ -29,17 +29,17 @@ GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu") # Groups based on hardware features -GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_yeeloong"]; GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi") +GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson"]; GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi") GROUPS["pci"] = GROUPS["x86"] + GROUPS["mips"] GROUPS["usb"] = GROUPS["pci"] # If gfxterm is main output console integrate it into kernel -GROUPS["videoinkernel"] = ["mips_yeeloong"] +GROUPS["videoinkernel"] = ["mips_loongson"] GROUPS["videomodules"] = GRUB_PLATFORMS[:]; for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i) # Similar for terminfo -GROUPS["terminfoinkernel"] = ["mips_yeeloong"] + GROUPS["ieee1275"]; +GROUPS["terminfoinkernel"] = ["mips_loongson"] + GROUPS["ieee1275"]; GROUPS["terminfomodule"] = GRUB_PLATFORMS[:]; for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i) @@ -238,7 +238,7 @@ def foreach_enabled_platform(closure): # noemu = bus/usb/usbhub.c; # enable = emu; # enable = i386; -# enable = mips_yeeloong; +# enable = mips_loongson; # emu_condition = COND_GRUB_EMU_USB; # }; # diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 94f7f3ffe..3b1611db2 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -125,7 +125,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h endif -if COND_mips_yeeloong +if COND_mips_loongson KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/cache.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index e651e1596..a87eb1598 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -32,11 +32,11 @@ kernel = { i386_coreboot_ldflags = '-Wl,-Ttext=0x8200'; i386_multiboot_ldflags = '-Wl,-Ttext=0x8200'; i386_ieee1275_ldflags = '-Wl,-Ttext=0x10000'; - mips_yeeloong_ldflags = '-Wl,-Ttext,0x80200000'; + mips_loongson_ldflags = '-Wl,-Ttext,0x80200000'; powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000'; sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; - mips_yeeloong_cppflags = '-DUSE_ASCII_FAILBACK'; + mips_loongson_cppflags = '-DUSE_ASCII_FAILBACK'; i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; emu_cflags = '$(CFLAGS_GNULIB)'; emu_cppflags = '$(CPPFLAGS_GNULIB)'; @@ -48,7 +48,7 @@ kernel = { i386_ieee1275_startup = kern/i386/ieee1275/startup.S; i386_coreboot_startup = kern/i386/coreboot/startup.S; i386_multiboot_startup = kern/i386/coreboot/startup.S; - mips_yeeloong_startup = kern/mips/startup.S; + mips_loongson_startup = kern/mips/startup.S; sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S; powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S; @@ -81,7 +81,7 @@ kernel = { i386_qemu = kern/generic/rtc_get_time_ms.c; i386_coreboot = kern/generic/rtc_get_time_ms.c; i386_multiboot = kern/generic/rtc_get_time_ms.c; - mips_yeeloong = kern/generic/rtc_get_time_ms.c; + mips_loongson = kern/generic/rtc_get_time_ms.c; ieee1275 = disk/ieee1275/ofdisk.c; ieee1275 = kern/ieee1275/cmain.c; @@ -136,20 +136,20 @@ kernel = { i386_ieee1275 = kern/ieee1275/init.c; - mips_yeeloong = term/ns8250.c; - mips_yeeloong = bus/bonito.c; - mips_yeeloong = bus/cs5536.c; - mips_yeeloong = bus/pci.c; - mips_yeeloong = kern/mips/cache.S; - mips_yeeloong = kern/mips/dl.c; - mips_yeeloong = kern/mips/init.c; - mips_yeeloong = kern/mips/yeeloong/init.c; - mips_yeeloong = term/at_keyboard.c; - mips_yeeloong = term/serial.c; - mips_yeeloong = video/sm712.c; - mips_yeeloong = video/sis315pro.c; + mips_loongson = term/ns8250.c; + mips_loongson = bus/bonito.c; + mips_loongson = bus/cs5536.c; + mips_loongson = bus/pci.c; + mips_loongson = kern/mips/cache.S; + mips_loongson = kern/mips/dl.c; + mips_loongson = kern/mips/init.c; + mips_loongson = kern/mips/loongson/init.c; + mips_loongson = term/at_keyboard.c; + mips_loongson = term/serial.c; + mips_loongson = video/sm712.c; + mips_loongson = video/sis315pro.c; extra_dist = video/sm712_init.c; - mips_yeeloong = commands/keylayouts.c; + mips_loongson = commands/keylayouts.c; powerpc_ieee1275 = kern/ieee1275/init.c; powerpc_ieee1275 = kern/powerpc/cache.S; @@ -323,18 +323,18 @@ image = { image = { name = fwstart; - mips_yeeloong = boot/mips/yeeloong/fwstart.S; + mips_loongson = boot/mips/loongson/fwstart.S; objcopyflags = '-O binary'; ldflags = '-static-libgcc -lgcc -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; - enable = mips_yeeloong; + enable = mips_loongson; }; image = { name = fwstart_fuloong; - mips_yeeloong = boot/mips/yeeloong/fuloong.S; + mips_loongson = boot/mips/loongson/fuloong.S; objcopyflags = '-O binary'; ldflags = '-static-libgcc -lgcc -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; - enable = mips_yeeloong; + enable = mips_loongson; }; module = { @@ -358,8 +358,8 @@ module = { module = { name = lsspd; - mips_yeeloong = commands/mips/yeeloong/lsspd.c; - enable = mips_yeeloong; + mips_loongson = commands/mips/loongson/lsspd.c; + enable = mips_loongson; }; module = { @@ -1236,10 +1236,10 @@ module = { x86_efi = mmap/efi/mmap.c; - mips_yeeloong = mmap/mips/yeeloong/uppermem.c; + mips_loongson = mmap/mips/loongson/uppermem.c; enable = x86; - enable = mips_yeeloong; + enable = mips_loongson; }; module = { diff --git a/grub-core/boot/mips/yeeloong/fuloong.S b/grub-core/boot/mips/loongson/fuloong.S similarity index 100% rename from grub-core/boot/mips/yeeloong/fuloong.S rename to grub-core/boot/mips/loongson/fuloong.S diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/loongson/fwstart.S similarity index 99% rename from grub-core/boot/mips/yeeloong/fwstart.S rename to grub-core/boot/mips/loongson/fwstart.S index d25ff1a5b..6deb17f2b 100644 --- a/grub-core/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/loongson/fwstart.S @@ -16,8 +16,8 @@ * along with GRUB. If not, see . */ -#include -#include +#include +#include #include #include #include @@ -129,7 +129,7 @@ retry_cs5536: sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL3) ($t0) sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0) - /* Yeeloong has only one memory slot. */ + /* Yeeloong and Fuloong have only one memory slot. */ /* Output first byte on serial for debugging. */ ori $a1, $zero, GRUB_SMB_RAM_START_ADDR bal read_spd diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index d8789982f..0bb3ea11f 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -50,7 +50,7 @@ codestart: /* Parse arguments. Has to be done before relocation. So need to do it in asm. */ -#ifdef GRUB_MACHINE_MIPS_YEELOONG +#ifdef GRUB_MACHINE_MIPS_LOONGSON move $s2, $zero move $s3, $zero move $s4, $zero diff --git a/grub-core/bus/pci.c b/grub-core/bus/pci.c index 11101d42b..bf9e605ae 100644 --- a/grub-core/bus/pci.c +++ b/grub-core/bus/pci.c @@ -36,7 +36,7 @@ grub_dma_free (struct grub_pci_dma_chunk *ch) } /* #endif */ -#ifdef GRUB_MACHINE_MIPS_YEELOONG +#ifdef GRUB_MACHINE_MIPS_LOONGSON volatile void * grub_dma_get_virt (struct grub_pci_dma_chunk *ch) { @@ -99,13 +99,13 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook) continue; } -#ifdef GRUB_MACHINE_MIPS_YEELOONG +#ifdef GRUB_MACHINE_MIPS_LOONGSON /* Skip ghosts. */ - if (id == GRUB_YEELOONG_OHCI_PCIID - && dev.function == GRUB_YEELOONG_OHCI_GHOST_FUNCTION) + if (id == GRUB_LOONGSON_OHCI_PCIID + && dev.function == GRUB_LOONGSON_OHCI_GHOST_FUNCTION) continue; - if (id == GRUB_YEELOONG_EHCI_PCIID - && dev.function == GRUB_YEELOONG_EHCI_GHOST_FUNCTION) + if (id == GRUB_LOONGSON_EHCI_PCIID + && dev.function == GRUB_LOONGSON_EHCI_GHOST_FUNCTION) continue; #endif diff --git a/grub-core/commands/mips/yeeloong/lsspd.c b/grub-core/commands/mips/loongson/lsspd.c similarity index 100% rename from grub-core/commands/mips/yeeloong/lsspd.c rename to grub-core/commands/mips/loongson/lsspd.c diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index da7123234..6376c2516 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -53,8 +53,8 @@ grub_module_iterate (int (*hook) (struct grub_module_header *header)) } } -/* This is actualy platform-independant but used only on yeeloong and sparc. */ -#if defined (GRUB_MACHINE_MIPS_YEELOONG) || defined (GRUB_MACHINE_SPARC64) +/* This is actualy platform-independant but used only on loongson and sparc. */ +#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_SPARC64) grub_addr_t grub_modules_get_end (void) { diff --git a/grub-core/kern/mips/yeeloong/init.c b/grub-core/kern/mips/loongson/init.c similarity index 98% rename from grub-core/kern/mips/yeeloong/init.c rename to grub-core/kern/mips/loongson/init.c index 7526111cc..acc3a17c7 100644 --- a/grub-core/kern/mips/yeeloong/init.c +++ b/grub-core/kern/mips/loongson/init.c @@ -80,7 +80,7 @@ init_pci (void) /* FIXME: autoscan for BARs and devices. */ switch (pciid) { - case GRUB_YEELOONG_OHCI_PCIID: + case GRUB_LOONGSON_OHCI_PCIID: addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); grub_pci_write (addr, 0x5025000); addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); @@ -92,7 +92,7 @@ init_pci (void) addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS); grub_pci_write_word (addr, 0x0200 | GRUB_PCI_STATUS_CAPABILITIES); break; - case GRUB_YEELOONG_EHCI_PCIID: + case GRUB_LOONGSON_EHCI_PCIID: addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); grub_pci_write (addr, 0x5026000); addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); @@ -164,7 +164,7 @@ grub_machine_init (void) if (err) grub_fatal ("Couldn't init SMBus: %s\n", grub_errmsg); - /* Yeeloong has only one memory slot. */ + /* Yeeloong and Fuloong have only one memory slot. */ err = grub_cs5536_read_spd (smbbase, GRUB_SMB_RAM_START_ADDR, &spd); if (err) grub_fatal ("Couldn't read SPD: %s\n", grub_errmsg); diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index 999beee79..624ceb6d0 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -36,7 +36,7 @@ start: bal cont nop - . = _start + GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE + . = _start + GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE total_module_size: .long 0 @@ -51,7 +51,7 @@ VARIABLE(grub_prefix) */ . = _start + GRUB_KERNEL_MACHINE_PREFIX_END -#ifdef GRUB_MACHINE_MIPS_YEELOONG +#ifdef GRUB_MACHINE_MIPS_LOONGSON VARIABLE (grub_arch_busclock) .long 0 VARIABLE (grub_arch_cpuclock) @@ -67,7 +67,7 @@ cont: /* Save our base. */ move $s0, $ra -#ifdef GRUB_MACHINE_MIPS_YEELOONG +#ifdef GRUB_MACHINE_MIPS_LOONGSON lui $t1, %hi(grub_arch_busclock) addiu $t1, %lo(grub_arch_busclock) sw $s2, 0($t1) diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c index 244d2b8a3..9cc1bd778 100644 --- a/grub-core/loader/mips/linux.c +++ b/grub-core/loader/mips/linux.c @@ -32,7 +32,7 @@ #include #include -#ifdef GRUB_MACHINE_MIPS_YEELOONG +#ifdef GRUB_MACHINE_MIPS_LOONGSON #include const char loongson_machtypes[][60] = @@ -224,7 +224,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* For arguments. */ linux_argc = argc; -#ifdef GRUB_MACHINE_MIPS_YEELOONG +#ifdef GRUB_MACHINE_MIPS_LOONGSON linux_argc++; #endif /* Main arguments. */ @@ -239,7 +239,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* Normal arguments. */ for (i = 1; i < argc; i++) size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); -#ifdef GRUB_MACHINE_MIPS_YEELOONG +#ifdef GRUB_MACHINE_MIPS_LOONGSON size += ALIGN_UP (sizeof (loongson_machtypes[0]), 4); #endif @@ -279,7 +279,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), linux_argv++; linux_args += ALIGN_UP (sizeof ("a0"), 4); -#ifdef GRUB_MACHINE_MIPS_YEELOONG +#ifdef GRUB_MACHINE_MIPS_LOONGSON { unsigned mtype = grub_arch_machine; if (mtype >= ARRAY_SIZE (loongson_machtypes)) diff --git a/grub-core/mmap/mips/yeeloong/uppermem.c b/grub-core/mmap/mips/loongson/uppermem.c similarity index 100% rename from grub-core/mmap/mips/yeeloong/uppermem.c rename to grub-core/mmap/mips/loongson/uppermem.c diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c index 55cb76483..828217497 100644 --- a/grub-core/term/at_keyboard.c +++ b/grub-core/term/at_keyboard.c @@ -257,7 +257,7 @@ grub_keyboard_controller_write (grub_uint8_t c) grub_outb (c, KEYBOARD_REG_DATA); } -#if !defined (GRUB_MACHINE_MIPS_YEELOONG) && !defined (GRUB_MACHINE_QEMU) +#if !defined (GRUB_MACHINE_MIPS_LOONGSON) && !defined (GRUB_MACHINE_QEMU) static grub_uint8_t grub_keyboard_controller_read (void) @@ -562,7 +562,7 @@ grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unus keyboard_controller_wait_until_ready (); grub_inb (KEYBOARD_REG_DATA); } -#if defined (GRUB_MACHINE_MIPS_YEELOONG) || defined (GRUB_MACHINE_QEMU) +#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_QEMU) grub_keyboard_controller_orig = 0; grub_keyboard_orig_set = 2; #else diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c index 5d403c845..b63ee14d9 100644 --- a/grub-core/term/ns8250.c +++ b/grub-core/term/ns8250.c @@ -66,8 +66,8 @@ serial_get_divisor (const struct grub_serial_port *port, for (i = 0; i < ARRAY_SIZE (divisor_tab); i++) if (divisor_tab[i].speed == config->speed) { - /* internal UART in Yeeloong runs twice the usual rate. */ -#ifdef GRUB_MACHINE_MIPS_YEELOONG + /* internal Loongson UART runs twice the usual rate. */ +#ifdef GRUB_MACHINE_MIPS_LOONGSON if (port->port == 0xbff003f8) return 2 * divisor_tab[i].div; else @@ -115,8 +115,8 @@ do_real_config (struct grub_serial_port *port) | stop_bits[port->config.stop_bits]); grub_outb (status, port->port + UART_LCR); - /* In Yeeloong serial port has only 3 wires. */ -#ifndef GRUB_MACHINE_MIPS_YEELOONG + /* On Loongson machines serial port has only 3 wires. */ +#ifndef GRUB_MACHINE_MIPS_LOONGSON /* Enable the FIFO. */ grub_outb (UART_ENABLE_FIFO_TRIGGER1, port->port + UART_FCR); diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c index aca5769fd..74c493da1 100644 --- a/grub-core/term/serial.c +++ b/grub-core/term/serial.c @@ -26,7 +26,7 @@ #include #include #include -#ifdef GRUB_MACHINE_MIPS_YEELOONG +#ifdef GRUB_MACHINE_MIPS_LOONGSON #include #endif @@ -298,7 +298,7 @@ grub_serial_register (struct grub_serial_port *port) port->term_in = in; port->term_out = out; grub_terminfo_output_register (out, "vt100"); -#ifdef GRUB_MACHINE_MIPS_YEELOONG +#ifdef GRUB_MACHINE_MIPS_LOONGSON if (grub_strcmp (port->name, (grub_arch_machine == GRUB_ARCH_MACHINE_YEELOONG) ? "com0" : "com2") == 0) diff --git a/include/grub/mips/yeeloong/at_keyboard.h b/include/grub/mips/loongson/at_keyboard.h similarity index 100% rename from include/grub/mips/yeeloong/at_keyboard.h rename to include/grub/mips/loongson/at_keyboard.h diff --git a/include/grub/mips/yeeloong/cmos.h b/include/grub/mips/loongson/cmos.h similarity index 100% rename from include/grub/mips/yeeloong/cmos.h rename to include/grub/mips/loongson/cmos.h diff --git a/include/grub/mips/yeeloong/ec.h b/include/grub/mips/loongson/ec.h similarity index 100% rename from include/grub/mips/yeeloong/ec.h rename to include/grub/mips/loongson/ec.h diff --git a/include/grub/mips/yeeloong/kernel.h b/include/grub/mips/loongson/kernel.h similarity index 100% rename from include/grub/mips/yeeloong/kernel.h rename to include/grub/mips/loongson/kernel.h diff --git a/include/grub/mips/yeeloong/memory.h b/include/grub/mips/loongson/memory.h similarity index 100% rename from include/grub/mips/yeeloong/memory.h rename to include/grub/mips/loongson/memory.h diff --git a/include/grub/mips/yeeloong/pci.h b/include/grub/mips/loongson/pci.h similarity index 95% rename from include/grub/mips/yeeloong/pci.h rename to include/grub/mips/loongson/pci.h index 199bac048..3f828c2f8 100644 --- a/include/grub/mips/yeeloong/pci.h +++ b/include/grub/mips/loongson/pci.h @@ -24,10 +24,10 @@ #include #endif -#define GRUB_YEELOONG_OHCI_PCIID 0x00351033 -#define GRUB_YEELOONG_EHCI_PCIID 0x00e01033 -#define GRUB_YEELOONG_OHCI_GHOST_FUNCTION 4 -#define GRUB_YEELOONG_EHCI_GHOST_FUNCTION 5 +#define GRUB_LOONGSON_OHCI_PCIID 0x00351033 +#define GRUB_LOONGSON_EHCI_PCIID 0x00e01033 +#define GRUB_LOONGSON_OHCI_GHOST_FUNCTION 4 +#define GRUB_LOONGSON_EHCI_GHOST_FUNCTION 5 #define GRUB_PCI_NUM_BUS 1 #define GRUB_PCI_NUM_DEVICES 16 diff --git a/include/grub/mips/yeeloong/serial.h b/include/grub/mips/loongson/serial.h similarity index 100% rename from include/grub/mips/yeeloong/serial.h rename to include/grub/mips/loongson/serial.h diff --git a/include/grub/mips/yeeloong/time.h b/include/grub/mips/loongson/time.h similarity index 100% rename from include/grub/mips/yeeloong/time.h rename to include/grub/mips/loongson/time.h diff --git a/include/grub/offsets.h b/include/grub/offsets.h index 817372b69..7d88f344d 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -100,16 +100,16 @@ #define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ALIGN 4 #define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR 0x200000 -#define GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR 0x80200000 +#define GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR 0x80200000 -#define GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN 32 +#define GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN 32 -#define GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE 0x8 -#define GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE 0xc +#define GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE 0x8 +#define GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE 0xc -#define GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE 0x08 -#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX 0x0c -#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END 0x54 +#define GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE 0x08 +#define GRUB_KERNEL_MIPS_LOONGSON_PREFIX 0x0c +#define GRUB_KERNEL_MIPS_LOONGSON_PREFIX_END 0x54 /* The offset of GRUB_PREFIX. */ #define GRUB_KERNEL_I386_EFI_PREFIX 0x8 @@ -144,7 +144,7 @@ #define GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN 0x1000 -#define GRUB_KERNEL_MIPS_YEELOONG_MOD_ALIGN 0x1 +#define GRUB_KERNEL_MIPS_LOONGSON_MOD_ALIGN 0x1 /* Minimal gap between _end and the start of the modules. It's a hack for PowerMac to prevent "CLAIM failed" error. The real fix is to diff --git a/include/grub/serial.h b/include/grub/serial.h index 9540bee64..41b720891 100644 --- a/include/grub/serial.h +++ b/include/grub/serial.h @@ -102,7 +102,7 @@ grub_serial_config_defaults (struct grub_serial_port *port) { struct grub_serial_config config = { -#ifdef GRUB_MACHINE_MIPS_YEELOONG +#ifdef GRUB_MACHINE_MIPS_LOONGSON .speed = 115200, #else .speed = 9600, diff --git a/util/grub-install.in b/util/grub-install.in index 90360c279..b20cadaf6 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -551,13 +551,13 @@ fi case "${target_cpu}-${platform}" in sparc64-ieee1275) mkimage_target=sparc64-ieee1275-raw ;; - mips-yeeloong) mkimage_target=mipsel-yeeloong-elf ;; + mips-loongson) mkimage_target=mipsel-loongson-elf ;; *) mkimage_target="${target_cpu}-${platform}" ;; esac case "${target_cpu}-${platform}" in i386-efi | x86_64-efi) imgext=efi ;; - mips-yeeloong | i386-coreboot | i386-multiboot | i386-ieee1275 \ + mips-loongson | i386-coreboot | i386-multiboot | i386-ieee1275 \ | powerpc-ieee1275) imgext=elf ;; *) imgext=img ;; esac @@ -566,7 +566,7 @@ esac "$grub_mkimage" ${config_opt} -d "${pkglibdir}" -O ${mkimage_target} --output="${grubdir}/core.${imgext}" --prefix="${prefix_drive}${relative_grubdir}" $modules || exit 1 # Backward-compatibility kludges -if [ "${target_cpu}-${platform}" = "mips-yeeloong" ]; then +if [ "${target_cpu}-${platform}" = "mips-loongson" ]; then cp "${grubdir}/core.${imgext}" "${bootdir}"/grub.elf elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then cp "${grubdir}/core.${imgext}" "${grubdir}/grub" diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 663e60f08..739b8c16e 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -65,7 +65,7 @@ struct image_target_desc enum { IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT, IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_I386_IEEE1275, - IMAGE_YEELOONG_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH, + IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH, IMAGE_FULOONG_FLASH, IMAGE_I386_PC_PXE } id; enum @@ -265,70 +265,70 @@ struct image_target_desc image_targets[] = .install_bsd_part = TARGET_NO_FIELD, }, { - .dirname = "mipsel-yeeloong", + .dirname = "mipsel-loongson", .names = { "mipsel-yeeloong-flash", NULL }, .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_YEELOONG_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX, - .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END, + .prefix = GRUB_KERNEL_MIPS_LOONGSON_PREFIX, + .prefix_end = GRUB_KERNEL_MIPS_LOONGSON_PREFIX_END, .raw_size = 0, - .total_module_size = GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE, + .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, .install_bsd_part = TARGET_NO_FIELD, - .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR, + .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR, .elf_target = EM_MIPS, - .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN, + .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN, .default_compression = COMPRESSION_NONE }, { - .dirname = "mipsel-yeeloong", + .dirname = "mipsel-loongson", .names = { "mipsel-fuloong-flash", NULL }, .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_FULOONG_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX, - .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END, + .prefix = GRUB_KERNEL_MIPS_LOONGSON_PREFIX, + .prefix_end = GRUB_KERNEL_MIPS_LOONGSON_PREFIX_END, .raw_size = 0, - .total_module_size = GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE, + .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, .install_bsd_part = TARGET_NO_FIELD, - .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR, + .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR, .elf_target = EM_MIPS, - .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN, + .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN, .default_compression = COMPRESSION_NONE }, { - .dirname = "mipsel-yeeloong", + .dirname = "mipsel-loongson", .names = { "mipsel-loongson-elf", "mipsel-yeeloong-elf", "mipsel-fuloong-elf", NULL }, .voidp_sizeof = 4, .bigendian = 0, - .id = IMAGE_YEELOONG_ELF, + .id = IMAGE_LOONGSON_ELF, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX, - .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END, + .prefix = GRUB_KERNEL_MIPS_LOONGSON_PREFIX, + .prefix_end = GRUB_KERNEL_MIPS_LOONGSON_PREFIX_END, .raw_size = 0, - .total_module_size = GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE, + .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, .install_bsd_part = TARGET_NO_FIELD, - .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR, + .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR, .elf_target = EM_MIPS, - .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN, + .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN, .default_compression = COMPRESSION_NONE }, { @@ -837,10 +837,10 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], decompress_size = grub_util_get_image_size (decompress_path); decompress_img = grub_util_read_image (decompress_path); - *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE)) + *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE)) = grub_host_to_target32 (core_size); - *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE)) + *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE)) = grub_host_to_target32 (kernel_size + total_module_size); full_size = core_size + decompress_size; @@ -1271,7 +1271,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], core_size = rom_size; } break; - case IMAGE_YEELOONG_ELF: + case IMAGE_LOONGSON_ELF: case IMAGE_PPC: case IMAGE_COREBOOT: case IMAGE_I386_IEEE1275: @@ -1284,7 +1284,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], int header_size, footer_size = 0; int phnum = 1; - if (image_target->id != IMAGE_YEELOONG_ELF) + if (image_target->id != IMAGE_LOONGSON_ELF) phnum += 2; if (note) @@ -1319,7 +1319,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], /* No section headers. */ ehdr->e_shoff = grub_host_to_target32 (0); - if (image_target->id == IMAGE_YEELOONG_ELF) + if (image_target->id == IMAGE_LOONGSON_ELF) ehdr->e_shentsize = grub_host_to_target16 (0); else ehdr->e_shentsize = grub_host_to_target16 (sizeof (Elf32_Shdr)); @@ -1332,7 +1332,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], phdr->p_offset = grub_host_to_target32 (header_size); phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X); - if (image_target->id == IMAGE_YEELOONG_ELF) + if (image_target->id == IMAGE_LOONGSON_ELF) target_addr = ALIGN_UP (image_target->link_addr + kernel_size + total_module_size, 32); else @@ -1341,12 +1341,12 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], phdr->p_vaddr = grub_host_to_target32 (target_addr); phdr->p_paddr = grub_host_to_target32 (target_addr); phdr->p_align = grub_host_to_target32 (align > image_target->link_align ? align : image_target->link_align); - if (image_target->id == IMAGE_YEELOONG_ELF) + if (image_target->id == IMAGE_LOONGSON_ELF) ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER | EF_MIPS_PIC | EF_MIPS_CPIC); else ehdr->e_flags = 0; - if (image_target->id == IMAGE_YEELOONG_ELF) + if (image_target->id == IMAGE_LOONGSON_ELF) { phdr->p_filesz = grub_host_to_target32 (core_size); phdr->p_memsz = grub_host_to_target32 (core_size); From 09573499ff62ebbeabfedc45dd8106ba715cbdf3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 29 Mar 2011 02:02:55 +0200 Subject: [PATCH 164/406] Initial variable sector size support --- grub-core/disk/efi/efidisk.c | 17 ++++--- grub-core/disk/i386/pc/biosdisk.c | 52 +++++++++++---------- grub-core/disk/scsi.c | 36 +++++---------- grub-core/kern/disk.c | 77 +++++++++++++++++++++++-------- grub-core/kern/emu/hostdisk.c | 37 ++++++++++----- grub-core/partmap/msdos.c | 22 ++++++--- include/grub/disk.h | 10 ++-- 7 files changed, 155 insertions(+), 96 deletions(-) diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 08094fa5c..20fea956f 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -536,8 +536,13 @@ grub_efidisk_open (const char *name, struct grub_disk *disk) and total sectors should be replaced with total blocks. */ grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n", m, (unsigned long long) m->last_block, m->block_size); - disk->total_sectors = (m->last_block - * (m->block_size >> GRUB_DISK_SECTOR_BITS)); + disk->total_sectors = m->last_block; + if (m->blocksize & (m->blocksize - 1) || !m->blocksize) + return grub_error (GRUB_ERR_IO, "invalid sector size %d", + m->blocksize); + for (disk->log_sector_size = 0; + (1 << disk->log_sector_size) < m->blocksize; + disk->log_sector_size++); disk->data = d; grub_dprintf ("efidisk", "opening %s succeeded\n", name); @@ -571,8 +576,8 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector, (unsigned long) size, (unsigned long long) sector, disk->name); status = efi_call_5 (dio->read, dio, bio->media->media_id, - (grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS, - (grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS, + (grub_efi_uint64_t) sector << disk->log_sector_size, + (grub_efi_uintn_t) size << disk->log_sector_size, buf); if (status != GRUB_EFI_SUCCESS) return grub_error (GRUB_ERR_READ_ERROR, "efidisk read error"); @@ -599,8 +604,8 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector, (unsigned long) size, (unsigned long long) sector, disk->name); status = efi_call_5 (dio->write, dio, bio->media->media_id, - (grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS, - (grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS, + (grub_efi_uint64_t) sector << disk->log_sector_size, + (grub_efi_uintn_t) size << disk->log_sector_size, (void *) buf); if (status != GRUB_EFI_SUCCESS) return grub_error (GRUB_ERR_WRITE_ERROR, "efidisk write error"); diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index 069bb0b59..6e48fff43 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -338,7 +338,8 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) if ((cd_drive) && (drive == cd_drive)) { data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM; - data->sectors = 32; + data->sectors = 8; + disk->log_sector_size = 11; /* TODO: get the correct size. */ total_sectors = GRUB_DISK_SIZE_UNKNOWN; } @@ -347,6 +348,8 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) /* HDD */ int version; + disk->log_sector_size = 9; + version = grub_biosdisk_check_int13_extensions (drive); if (version) { @@ -367,6 +370,15 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) correctly but returns zero. So if it is zero, compute it by C/H/S returned by the LBA BIOS call. */ total_sectors = drp->cylinders * drp->heads * drp->sectors; + if (drp->bytes_per_sector + && !(drp->bytes_per_sector & (drp->bytes_per_sector - 1)) + && drp->bytes_per_sector >= 512 + && drp->bytes_per_sector <= 16384) + { + for (disk->log_sector_size = 0; + (1 << disk->log_sector_size) < drp->bytes_per_sector; + disk->log_sector_size++); + } } } } @@ -429,7 +441,7 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk, dap = (struct grub_biosdisk_dap *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + (data->sectors - << GRUB_DISK_SECTOR_BITS)); + << disk->log_sector_size)); dap->length = sizeof (*dap); dap->reserved = 0; dap->blocks = size; @@ -443,9 +455,6 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk, if (cmd) return grub_error (GRUB_ERR_WRITE_ERROR, "can\'t write to cdrom"); - dap->blocks = ALIGN_UP (dap->blocks, 4) >> 2; - dap->block >>= 2; - for (i = 0; i < GRUB_BIOSDISK_CDROM_RETRY_COUNT; i++) if (! grub_biosdisk_rw_int13_extensions (0x42, data->drive, dap)) break; @@ -501,10 +510,12 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk, /* Return the number of sectors which can be read safely at a time. */ static grub_size_t -get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors) +get_safe_sectors (grub_disk_t disk, grub_disk_addr_t sector) { grub_size_t size; grub_uint32_t offset; + struct grub_biosdisk_data *data = disk->data; + grub_uint32_t sectors = data->sectors; /* OFFSET = SECTOR % SECTORS */ grub_divmod64 (sector, sectors, &offset); @@ -512,8 +523,8 @@ get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors) size = sectors - offset; /* Limit the max to 0x7f because of Phoenix EDD. */ - if (size > 0x7f) - size = 0x7f; + if (size > ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size)) + size = ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size); return size; } @@ -522,21 +533,11 @@ static grub_err_t grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t size, char *buf) { - struct grub_biosdisk_data *data = disk->data; - while (size) { grub_size_t len; - grub_size_t cdoff = 0; - len = get_safe_sectors (sector, data->sectors); - - if (data->flags & GRUB_BIOSDISK_FLAG_CDROM) - { - cdoff = (sector & 3) << GRUB_DISK_SECTOR_BITS; - len = ALIGN_UP (sector + len, 4) - (sector & ~3); - sector &= ~3; - } + len = get_safe_sectors (disk, sector); if (len > size) len = size; @@ -545,9 +546,10 @@ grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, GRUB_MEMORY_MACHINE_SCRATCH_SEG)) return grub_errno; - grub_memcpy (buf, (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + cdoff), - len << GRUB_DISK_SECTOR_BITS); - buf += len << GRUB_DISK_SECTOR_BITS; + grub_memcpy (buf, (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, + len << disk->log_sector_size); + + buf += len << disk->log_sector_size; sector += len; size -= len; } @@ -568,18 +570,18 @@ grub_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, { grub_size_t len; - len = get_safe_sectors (sector, data->sectors); + len = get_safe_sectors (disk, sector); if (len > size) len = size; grub_memcpy ((void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, buf, - len << GRUB_DISK_SECTOR_BITS); + len << disk->log_sector_size); if (grub_biosdisk_rw (GRUB_BIOSDISK_WRITE, disk, sector, len, GRUB_MEMORY_MACHINE_SCRATCH_SEG)) return grub_errno; - buf += len << GRUB_DISK_SECTOR_BITS; + buf += len << disk->log_sector_size; sector += len; size -= len; } diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index a40de278f..0d4734dc0 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -463,15 +463,20 @@ grub_scsi_open (const char *name, grub_disk_t disk) return err; } - /* SCSI blocks can be something else than 512, although GRUB - wants 512 byte blocks. */ - disk->total_sectors = ((grub_uint64_t)scsi->size - * (grub_uint64_t)scsi->blocksize) - >> GRUB_DISK_SECTOR_BITS; + disk->total_sectors = scsi->size; + if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize) + { + grub_free (scsi); + return grub_error (GRUB_ERR_IO, "invalid sector size %d", + scsi->blocksize); + } + for (disk->log_sector_size = 0; + (1 << disk->log_sector_size) < scsi->blocksize; + disk->log_sector_size++); grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n", scsi->size, scsi->blocksize); - grub_dprintf ("scsi", "Disk total 512 sectors = %llu\n", + grub_dprintf ("scsi", "Disk total sectors = %llu\n", (unsigned long long) disk->total_sectors); return GRUB_ERR_NONE; @@ -501,25 +506,6 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector, scsi = disk->data; - /* SCSI sectors are variable in size. GRUB uses 512 byte - sectors. */ - if (scsi->blocksize != GRUB_DISK_SECTOR_SIZE) - { - unsigned spb = scsi->blocksize >> GRUB_DISK_SECTOR_BITS; - if (spb == 0 || (scsi->blocksize & (GRUB_DISK_SECTOR_SIZE - 1)) != 0) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unsupported SCSI block size"); - - grub_uint32_t sector_mod = 0; - sector = grub_divmod64 (sector, spb, §or_mod); - - if (! (sector_mod == 0 && size % spb == 0)) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unaligned SCSI read not supported"); - - size /= spb; - } - /* Depending on the type, select a read function. */ switch (scsi->devtype) { diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index 807ee4277..af56527ad 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -247,6 +247,7 @@ grub_disk_open (const char *name) disk = (grub_disk_t) grub_zalloc (sizeof (*disk)); if (! disk) return 0; + disk->log_sector_size = GRUB_DISK_SECTOR_BITS; p = find_part_sep (name); if (p) @@ -266,7 +267,6 @@ grub_disk_open (const char *name) if (! disk->name) goto fail; - for (dev = grub_disk_dev_list; dev; dev = dev->next) { if ((dev->open) (raw, disk) == GRUB_ERR_NONE) @@ -282,6 +282,14 @@ grub_disk_open (const char *name) grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such disk"); goto fail; } + if (disk->log_sector_size > GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS + || disk->log_sector_size < GRUB_DISK_SECTOR_BITS) + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "sector sizes of %d bytes aren't supported yet", + (1 << disk->log_sector_size)); + goto fail; + } disk->dev = dev; @@ -373,14 +381,23 @@ grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector, *sector += start; } - if (disk->total_sectors <= *sector - || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS) > disk->total_sectors - *sector) + if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN + && ((disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) <= *sector + || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1) + >> GRUB_DISK_SECTOR_BITS) > (disk->total_sectors + << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) - *sector)) return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of disk"); return GRUB_ERR_NONE; } +static inline grub_disk_addr_t +transform_sector (grub_disk_t disk, grub_disk_addr_t sector) +{ + return sector >> (disk->log_sector_size - GRUB_DISK_SECTOR_BITS); +} + /* Read data from the disk. */ grub_err_t grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, @@ -433,27 +450,39 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, else { /* Otherwise read data from the disk actually. */ - if (start_sector + GRUB_DISK_CACHE_SIZE > disk->total_sectors - || (disk->dev->read) (disk, start_sector, - GRUB_DISK_CACHE_SIZE, tmp_buf) + if ((disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN + && start_sector + GRUB_DISK_CACHE_SIZE + > (disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS))) + || (disk->dev->read) (disk, transform_sector (disk, start_sector), + 1 << (GRUB_DISK_CACHE_BITS + + GRUB_DISK_SECTOR_BITS + - disk->log_sector_size), tmp_buf) != GRUB_ERR_NONE) { /* Uggh... Failed. Instead, just read necessary data. */ unsigned num; char *p; + grub_disk_addr_t aligned_sector; grub_errno = GRUB_ERR_NONE; - num = ((size + real_offset + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS); + aligned_sector = (sector & ~((1 << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) + - 1)); + real_offset += ((sector - aligned_sector) + << GRUB_DISK_SECTOR_BITS); + num = ((size + real_offset + (1 << (disk->log_sector_size)) + - 1) >> (disk->log_sector_size)); - p = grub_realloc (tmp_buf, num << GRUB_DISK_SECTOR_BITS); + p = grub_realloc (tmp_buf, num << disk->log_sector_size); if (!p) goto finish; tmp_buf = p; - if ((disk->dev->read) (disk, sector, num, tmp_buf)) + if ((disk->dev->read) (disk, transform_sector (disk, + aligned_sector), + num, tmp_buf)) { grub_error_push (); grub_dprintf ("disk", "%s read failed\n", disk->name); @@ -528,25 +557,31 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, grub_off_t offset, grub_size_t size, const void *buf) { unsigned real_offset; + grub_disk_addr_t aligned_sector; grub_dprintf ("disk", "Writing `%s'...\n", disk->name); if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE) return -1; - real_offset = offset; + aligned_sector = (sector & ~((1 << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) - 1)); + real_offset = offset + ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS); + sector = aligned_sector; while (size) { - if (real_offset != 0 || (size < GRUB_DISK_SECTOR_SIZE && size != 0)) + if (real_offset != 0 || (size < (1U << disk->log_sector_size) + && size != 0)) { - char tmp_buf[GRUB_DISK_SECTOR_SIZE]; + char tmp_buf[1 << disk->log_sector_size]; grub_size_t len; grub_partition_t part; part = disk->partition; disk->partition = 0; - if (grub_disk_read (disk, sector, 0, GRUB_DISK_SECTOR_SIZE, tmp_buf) + if (grub_disk_read (disk, sector, + 0, (1 << disk->log_sector_size), tmp_buf) != GRUB_ERR_NONE) { disk->partition = part; @@ -554,7 +589,7 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, } disk->partition = part; - len = GRUB_DISK_SECTOR_SIZE - real_offset; + len = (1 << disk->log_sector_size) - real_offset; if (len > size) len = size; @@ -565,7 +600,7 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, if ((disk->dev->write) (disk, sector, 1, tmp_buf) != GRUB_ERR_NONE) goto finish; - sector++; + sector += (1 << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); buf = (char *) buf + len; size -= len; real_offset = 0; @@ -575,8 +610,8 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t len; grub_size_t n; - len = size & ~(GRUB_DISK_SECTOR_SIZE - 1); - n = size >> GRUB_DISK_SECTOR_BITS; + len = size & ~((1 << disk->log_sector_size) - 1); + n = size >> disk->log_sector_size; if ((disk->dev->write) (disk, sector, n, buf) != GRUB_ERR_NONE) goto finish; @@ -599,6 +634,8 @@ grub_disk_get_size (grub_disk_t disk) { if (disk->partition) return grub_partition_get_len (disk->partition); + else if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN) + return disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS); else - return disk->total_sectors; + return GRUB_DISK_SIZE_UNKNOWN; } diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 73d023ce9..f082ada89 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -42,6 +42,7 @@ #ifdef __linux__ # include /* ioctl */ +# include # if !defined(__GLIBC__) || \ ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))) /* Maybe libc doesn't have large file support. */ @@ -264,6 +265,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk) # else unsigned long long nr; # endif + int sector_size; int fd; fd = open (map[drive].device, O_RDONLY); @@ -295,16 +297,28 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk) goto fail; } + if (ioctl (fd, BLKSSZGET, §or_size)) + { + close (fd); + goto fail; + } + close (fd); + if (sector_size & (sector_size - 1) || !sector_size) + goto fail; + for (disk->log_sector_size = 0; + (1 << disk->log_sector_size) < sector_size; + disk->log_sector_size++); + # if defined (__APPLE__) disk->total_sectors = nr; # elif defined(__NetBSD__) disk->total_sectors = label.d_secperunit; # else - disk->total_sectors = nr / 512; + disk->total_sectors = nr >> disk->log_sector_size; - if (nr % 512) + if (nr & ((1 << disk->log_sector_size) - 1)) grub_util_error ("unaligned device size"); # endif @@ -321,7 +335,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk) if (stat (map[drive].device, &st) < 0) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot stat `%s'", map[drive].device); - disk->total_sectors = st.st_size >> GRUB_DISK_SECTOR_BITS; + disk->total_sectors = st.st_size >> disk->log_sector_size; grub_util_info ("the size of %s is %lu", name, disk->total_sectors); @@ -760,7 +774,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo, loff_t *, res, uint, wh); - offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS; + offset = (loff_t) sector << disk->log_sector_size; if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET)) { grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device); @@ -770,7 +784,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) } #else { - off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS; + off_t offset = (off_t) sector << disk->log_sector_size; if (lseek (fd, offset, SEEK_SET) != offset) { @@ -870,20 +884,21 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, sectors that are read together with the MBR in one read. It should only remap the MBR, so we split the read in two parts. -jochen */ - if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE) + if (nread (fd, buf, (1 << disk->log_sector_size)) + != (1 << disk->log_sector_size)) { grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device); close (fd); return grub_errno; } - buf += GRUB_DISK_SECTOR_SIZE; + buf += (1 << disk->log_sector_size); size--; } #endif /* __linux__ */ - if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS) - != (ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + if (nread (fd, buf, size << disk->log_sector_size) + != (ssize_t) (size << disk->log_sector_size)) grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device); return grub_errno; @@ -916,8 +931,8 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, if (fd < 0) return grub_errno; - if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS) - != (ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + if (nwrite (fd, buf, size << disk->log_sector_size) + != (ssize_t) (size << disk->log_sector_size)) grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device); return grub_errno; diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c index 31a0a0707..c2e726bd7 100644 --- a/grub-core/partmap/msdos.c +++ b/grub-core/partmap/msdos.c @@ -90,8 +90,11 @@ grub_partition_msdos_iterate (grub_disk_t disk, { e = mbr.entries + p.index; - p.start = p.offset + grub_le_to_cpu32 (e->start) - delta; - p.len = grub_le_to_cpu32 (e->length); + p.start = p.offset + + (grub_le_to_cpu32 (e->start) + << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) - delta; + p.len = grub_le_to_cpu32 (e->length) + << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS); p.msdostype = e->type; grub_dprintf ("partition", @@ -126,7 +129,9 @@ grub_partition_msdos_iterate (grub_disk_t disk, if (grub_msdos_partition_is_extended (e->type)) { - p.offset = ext_offset + grub_le_to_cpu32 (e->start); + p.offset = ext_offset + + (grub_le_to_cpu32 (e->start) + << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); if (! ext_offset) ext_offset = p.offset; @@ -204,8 +209,11 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, e = mbr.entries + i; if (!grub_msdos_partition_is_empty (e->type) - && end > offset + grub_le_to_cpu32 (e->start)) - end = offset + grub_le_to_cpu32 (e->start); + && end > offset + + (grub_le_to_cpu32 (e->start) + << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS))) + end = offset + (grub_le_to_cpu32 (e->start) + << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); /* If this is a GPT partition, this MBR is just a dummy. */ if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && i == 0) @@ -219,7 +227,9 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, if (grub_msdos_partition_is_extended (e->type)) { - offset = ext_offset + grub_le_to_cpu32 (e->start); + offset = ext_offset + + (grub_le_to_cpu32 (e->start) + << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); if (! ext_offset) ext_offset = offset; diff --git a/include/grub/disk.h b/include/grub/disk.h index 66db1149a..b46d6670a 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -100,6 +100,9 @@ struct grub_disk /* The total number of sectors. */ grub_uint64_t total_sectors; + /* Logarithm of sector size. */ + unsigned int log_sector_size; + /* The id used by the disk cache manager. */ unsigned long id; @@ -132,9 +135,10 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t; /* The maximum number of disk caches. */ #define GRUB_DISK_CACHE_NUM 1021 -/* The size of a disk cache in sector units. */ -#define GRUB_DISK_CACHE_SIZE 8 -#define GRUB_DISK_CACHE_BITS 3 +/* The size of a disk cache in 512B units. Must be at least as big as the + largest supported sector size, currently 16K. */ +#define GRUB_DISK_CACHE_BITS 6 +#define GRUB_DISK_CACHE_SIZE (1 << GRUB_DISK_CACHE_BITS) /* Return value of grub_disk_get_size() in case disk size is unknown. */ #define GRUB_DISK_SIZE_UNKNOWN 0xffffffffffffffffULL From cf4d3fa6407417a6ecdc82ed886484400789cde5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 29 Mar 2011 18:34:05 +0200 Subject: [PATCH 165/406] Send blend_text_bg when any backgorund is set as opposed to only when streteched background is set --- grub-core/term/gfxterm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c index 8a75df93c..1d850abd4 100644 --- a/grub-core/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -1174,7 +1174,6 @@ grub_gfxterm_background_image_cmd (grub_extcmd_context_t ctxt, /* Replace the original bitmap with the scaled one. */ grub_video_bitmap_destroy (bitmap); bitmap = scaled_bitmap; - blend_text_bg = 1; } } } @@ -1182,6 +1181,8 @@ grub_gfxterm_background_image_cmd (grub_extcmd_context_t ctxt, /* If bitmap was loaded correctly, display it. */ if (bitmap) { + blend_text_bg = 1; + /* Determine bitmap dimensions. */ bitmap_width = grub_video_bitmap_get_width (bitmap); bitmap_height = grub_video_bitmap_get_height (bitmap); From 6dc14451f4769d68d96c40f66644fe52e5a29d39 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:12:44 -0300 Subject: [PATCH 166/406] Iterate sockets to see if we expect this packet. Let the App layer to remove its own header. Add packet to socket list if it contains data. Undesired packets are freed. --- grub-core/net/udp.c | 62 ++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index a73431f83..16b2011ff 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -5,63 +5,51 @@ #include grub_err_t -grub_net_send_udp_packet (const grub_net_network_level_address_t *target, - struct grub_net_buff *nb, grub_uint16_t srcport, - grub_uint16_t destport) +grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff *nb) { struct udphdr *udph; - struct grub_net_network_level_interface *inf; - grub_err_t err; - grub_net_network_level_address_t gateway; - - err = grub_net_route_address (*target, &gateway, &inf); - if (err) - return err; grub_netbuff_push (nb,sizeof(*udph)); udph = (struct udphdr *) nb->data; - udph->src = grub_cpu_to_be16 (srcport); - udph->dst = grub_cpu_to_be16 (destport); + udph->src = grub_cpu_to_be16 (socket->in_port); + udph->dst = grub_cpu_to_be16 (socket->out_port); /* No chechksum. */ udph->chksum = 0; udph->len = grub_cpu_to_be16 (nb->tail - nb->data); - return grub_net_send_ip_packet (inf, target, nb); + return grub_net_send_ip_packet (socket->inf, &(socket->out_nla), nb); } grub_err_t -grub_net_recv_udp_packet (const grub_net_network_level_address_t *target, - struct grub_net_buff *buf, - grub_uint16_t srcport, grub_uint16_t destport) +grub_net_recv_udp_packet (struct grub_net_buff *nb) { - grub_err_t err; - struct grub_net_packet *pkt; - struct grub_net_network_level_interface *inf; - grub_net_network_level_address_t gateway; + //grub_err_t err; + struct udphdr *udph; + grub_net_socket_t sock; + udph = (struct udphdr *) nb->data; + grub_netbuff_pull (nb, sizeof (*udph)); - err = grub_net_route_address (*target, &gateway, &inf); - if (err) - return err; - - (void) srcport; - - err = grub_net_recv_ip_packets (inf); - - FOR_NET_NL_PACKETS(inf, pkt) + FOR_NET_SOCKETS(sock) { - struct udphdr *udph; - struct grub_net_buff *nb = pkt->nb; - udph = (struct udphdr *) nb->data; - if (grub_be_to_cpu16 (udph->dst) == destport) + if (grub_be_to_cpu16 (udph->dst) == sock->in_port) { - grub_net_remove_packet (pkt); - grub_netbuff_pull (nb, sizeof(*udph)); - grub_memcpy (buf, nb, sizeof (buf)); - + if (sock->status == 0) + sock->out_port = udph->src; + + + /* App protocol remove its own reader. */ + sock->app->read (sock,nb); + + /* If there is data, puts packet in socket list */ + if ((nb->tail - nb->data) > 0) + grub_net_put_packet (sock->packs, nb); + else + grub_netbuff_free (nb); return GRUB_ERR_NONE; } } + grub_netbuff_free (nb); return GRUB_ERR_NONE; } From d5e0a358f1252bb4af4002a9589e89ec70f0944c Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:14:16 -0300 Subject: [PATCH 167/406] Correctly match network. --- grub-core/net/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 54663f4b0..ab6b39261 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -105,7 +105,7 @@ match_net (const grub_net_network_level_netaddress_t *net, { case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { - grub_int32_t mask = (1 << net->ipv4.masksize) - 1; + grub_int32_t mask = ((1 << net->ipv4.masksize) - 1) << (32 - net->ipv4.masksize); return ((grub_be_to_cpu32 (net->ipv4.base) & mask) == (grub_be_to_cpu32 (addr->ipv4) & mask)); } From fbdee79b1729f432e4673a5088b20509be5e032b Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:22:41 -0300 Subject: [PATCH 168/406] Add generic functions to read and seek in network file. Allocate socket with network and adress information. --- grub-core/net/net.c | 164 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index ab6b39261..8c9229915 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -17,8 +17,12 @@ */ #include +#include +#include +#include #include #include +#include #include #include #include @@ -40,6 +44,7 @@ struct grub_net_route struct grub_net_route *grub_net_routes = NULL; struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL; struct grub_net_card *grub_net_cards = NULL; +struct grub_net_card_driver *grub_net_card_drivers = NULL; struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; static inline void @@ -538,6 +543,7 @@ grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)), } grub_net_app_level_t grub_net_app_level_list; +struct grub_net_socket *grub_net_sockets; static grub_net_t grub_net_open_real (const char *name) @@ -570,6 +576,159 @@ grub_net_open_real (const char *name) return NULL; } +static grub_err_t +grub_net_file_open_real (struct grub_file *file, const char *name) +{ + grub_err_t err; + grub_net_network_level_address_t addr; + struct grub_net_network_level_interface *inf; + grub_net_network_level_address_t gateway; + grub_net_socket_t socket; + static int port = 25300; + + err = grub_net_resolve_address (file->device->net->name + + sizeof (file->device->net->protocol->name) + 1, &addr); + if (err) + return err; + + err = grub_net_route_address (addr, &gateway, &inf); + if (err) + return err; + + if ((socket = (grub_net_socket_t) grub_malloc (sizeof (*socket))) == NULL) + return GRUB_ERR_OUT_OF_MEMORY; + + socket->inf = inf; + socket->out_nla = addr; + socket->in_port = port++; + socket->status = 0; + socket->app = file->device->net->protocol; + socket->packs = NULL; + file->device->net->socket = socket; + grub_net_socket_register (socket); + + if ((err = file->device->net->protocol->open (file,name))) + goto fail; + + return GRUB_ERR_NONE; +fail: + grub_net_socket_unregister (socket); + grub_free (socket); + return err; + +} + +static grub_err_t +receive_packets (struct grub_net_card *card) +{ + /* Maybe should be better have a fixed number of packets for each card + and just mark them as used and not used. */ + struct grub_net_buff *nb; + nb = grub_netbuff_alloc (1500); + if (!nb) + return grub_errno; + + card->driver->recv (card, nb); + return GRUB_ERR_NONE; +} + +void +grub_net_pool_cards (unsigned time) +{ + struct grub_net_card *card; + grub_uint64_t start_time; + FOR_NET_CARDS (card) + { + start_time = grub_get_time_ms (); + while( (grub_get_time_ms () - start_time) < time) + receive_packets (card); + } +} + +static grub_ssize_t +process_packets (grub_file_t file, void *buf, grub_size_t len, + void *NESTED_FUNC_ATTR (hook) (void *dest, const void *src, grub_size_t n)) +{ + grub_net_socket_t sock = file->device->net->socket; + struct grub_net_buff *nb; + char *ptr = (char *) buf; + grub_size_t amount, total = 0; + int try = 0; + while (try <= 3) + { + while (sock->packs->first) + { + try = 0; + nb = sock->packs->first->nb; + amount = (grub_size_t)(len <= (grub_size_t) (nb->tail - nb->data))? len :(grub_size_t)(nb->tail - nb->data); + len -= amount; + total += amount; + hook (ptr, nb->data, amount); + ptr += amount; + if (amount == (grub_size_t) (nb->tail - nb->data)) + { + grub_netbuff_free (nb); + grub_net_remove_packet (sock->packs->first); + } + else + nb->data += amount; + + if (!len) + return total; + } + if (sock->status == 1) + { + try++; + grub_net_pool_cards (200); + } + else + return total; + } + return total; +} + + +/* Read from the packets list*/ +static grub_ssize_t +grub_net_read_real (grub_file_t file, void *buf, grub_size_t len ) +{ + auto void *NESTED_FUNC_ATTR memcpy_hook (void *dest, const void *src, grub_size_t n); + void *NESTED_FUNC_ATTR memcpy_hook (void *dest __attribute__ ((unused)), const void *src __attribute__ ((unused)), + grub_size_t n __attribute__ ((unused))) + { + return grub_memcpy (dest, src, n); + } + return process_packets (file, buf, len, memcpy_hook); +} + +/* Read from the packets list*/ +static grub_err_t +grub_net_seek_real (struct grub_file *file, grub_off_t offset) +{ + grub_net_socket_t sock = file->device->net->socket; + struct grub_net_buff *nb; + grub_size_t len = offset - file->offset; + + if (!len) + return GRUB_ERR_NONE; + + /* We cant seek backwards past the current packet. */ + if (file->offset > offset) + { + nb = sock->packs->first->nb; + return grub_netbuff_push (nb, file->offset - offset); + } + + auto void *NESTED_FUNC_ATTR dummy (void *dest, const void *src, grub_size_t n); + void *NESTED_FUNC_ATTR dummy (void *dest __attribute__ ((unused)), const void *src __attribute__ ((unused)), + grub_size_t n __attribute__ ((unused))) + { + return NULL; + } + process_packets (file, NULL, len, dummy); + return GRUB_ERR_NONE; +} + static char * grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), const char *val __attribute__ ((unused))) @@ -857,6 +1016,9 @@ GRUB_MOD_INIT(net) N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); grub_net_open = grub_net_open_real; + grub_file_net_open = grub_net_file_open_real; + grub_file_net_read = grub_net_read_real; + grub_file_net_seek = grub_net_seek_real; } GRUB_MOD_FINI(net) @@ -869,4 +1031,6 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_lscards); grub_unregister_command (cmd_getdhcp); grub_net_open = NULL; + grub_file_net_read = NULL; + grub_file_net_open = NULL; } From 6ccb7a35e61a2853549dc90fe00981aebc09571b Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:26:27 -0300 Subject: [PATCH 169/406] Remove unused file. --- grub-core/net/device.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 grub-core/net/device.c diff --git a/grub-core/net/device.c b/grub-core/net/device.c deleted file mode 100644 index e69de29bb..000000000 From 6d5c2ed68a8b5f126c2eec349e39496af86d63ab Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:27:06 -0300 Subject: [PATCH 170/406] Use nb in all function declarations for consistency. --- grub-core/net/netbuff.c | 45 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c index cc366ae09..be9fc9de2 100644 --- a/grub-core/net/netbuff.c +++ b/grub-core/net/netbuff.c @@ -22,43 +22,43 @@ #include -grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len) +grub_err_t grub_netbuff_put (struct grub_net_buff *nb ,grub_size_t len) { - net_buff->tail += len; - if (net_buff->tail > net_buff->end) + nb->tail += len; + if (nb->tail > nb->end) return grub_error (GRUB_ERR_OUT_OF_RANGE, "put out of the packet range."); return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len) +grub_err_t grub_netbuff_unput (struct grub_net_buff *nb ,grub_size_t len) { - net_buff->tail -= len; - if (net_buff->tail < net_buff->head) + nb->tail -= len; + if (nb->tail < nb->head) return grub_error (GRUB_ERR_OUT_OF_RANGE, "unput out of the packet range."); return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len) +grub_err_t grub_netbuff_push (struct grub_net_buff *nb ,grub_size_t len) { - net_buff->data -= len; - if (net_buff->data < net_buff->head) + nb->data -= len; + if (nb->data < nb->head) return grub_error (GRUB_ERR_OUT_OF_RANGE, "push out of the packet range."); return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len) +grub_err_t grub_netbuff_pull (struct grub_net_buff *nb ,grub_size_t len) { - net_buff->data += len; - if (net_buff->data > net_buff->end) + nb->data += len; + if (nb->data > nb->end) return grub_error (GRUB_ERR_OUT_OF_RANGE, "pull out of the packet range."); return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len) +grub_err_t grub_netbuff_reserve (struct grub_net_buff *nb ,grub_size_t len) { - net_buff->data += len; - net_buff->tail += len; - if ((net_buff->tail > net_buff->end) || (net_buff->data > net_buff->end)) + nb->data += len; + nb->tail += len; + if ((nb->tail > nb->end) || (nb->data > nb->end)) return grub_error (GRUB_ERR_OUT_OF_RANGE, "reserve out of the packet range."); return GRUB_ERR_NONE; } @@ -73,22 +73,23 @@ struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len ) len = ALIGN_UP (len,NETBUFF_ALIGN); data = grub_memalign (NETBUFF_ALIGN, len + sizeof (*nb)); + if (!data) + return NULL; nb = (struct grub_net_buff *) ((grub_uint8_t *) data + len); nb->head = nb->data = nb->tail = data; - nb->end = (char *) nb; - + nb->end = (char *) nb; return nb; } -grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff) +grub_err_t grub_netbuff_free (struct grub_net_buff *nb) { - grub_free (net_buff->head); + grub_free (nb->head); return 0; } -grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff) +grub_err_t grub_netbuff_clear (struct grub_net_buff *nb) { - net_buff->data = net_buff->tail = net_buff->head; + nb->data = nb->tail = nb->head; return 0; } From 59b361a2df22426b6d34870bdbcc312641414369 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:39:06 -0300 Subject: [PATCH 171/406] Use bootp packet to set prefix and card address. --- grub-core/kern/ieee1275/init.c | 19 +++++- grub-core/kern/ieee1275/openfw.c | 1 + grub-core/net/drivers/ieee1275/ofnet.c | 89 +++++++++++++++++--------- include/grub/ieee1275/ofnet.h | 6 +- 4 files changed, 77 insertions(+), 38 deletions(-) diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index 682a8b5a4..ad34ea188 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include @@ -74,7 +76,22 @@ grub_machine_set_prefix (void) char bootpath[64]; /* XXX check length */ char *filename; char *prefix; - + grub_bootp_t bootp_pckt; + char addr[GRUB_NET_MAX_STR_ADDR_LEN]; + + /* Set the net prefix when possible. */ + if (grub_getbootp && (bootp_pckt = grub_getbootp())) + { + grub_uint32_t n = bootp_pckt->siaddr; + grub_snprintf (addr, GRUB_NET_MAX_STR_ADDR_LEN, "%d.%d.%d.%d", + ((n >> 24) & 0xff), ((n >> 16) & 0xff), + ((n >> 8) & 0xff), ((n >> 0) & 0xff)); + prefix = grub_xasprintf ("(tftp,%s)%s", addr,grub_prefix); + grub_env_set ("prefix", prefix); + grub_free (prefix); + return; + } + if (grub_prefix[0]) { grub_env_set ("prefix", grub_prefix); diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 3c228f574..fed4f7e76 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -28,6 +28,7 @@ #include #include +grub_bootp_t (*grub_getbootp) (void); enum grub_ieee1275_parse_type { GRUB_PARSE_FILENAME, diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index ce5276efe..10de81bc7 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -78,12 +78,11 @@ bootp_response_properties[] = { .name = "bootpreply-packet", .offset = 0x2a }, }; - -grub_bootp_t -grub_getbootp( void ) +static grub_bootp_t +grub_getbootp_real ( void ) { - grub_bootp_t packet = grub_malloc(sizeof *packet); - void *bootp_response = NULL; + grub_bootp_t packet = grub_malloc (sizeof *packet); + char *bootp_response; grub_ssize_t size; unsigned int i; @@ -94,30 +93,27 @@ grub_getbootp( void ) break; if (size < 0) - { - grub_printf("Error to get bootp\n"); return NULL; - } + bootp_response = grub_malloc (size); if (grub_ieee1275_get_property (grub_ieee1275_chosen, bootp_response_properties[i].name, bootp_response , size, 0) < 0) - { - grub_printf("Error to get bootp\n"); return NULL; - } - packet = (void *) ((int)bootp_response - + bootp_response_properties[i].offset); + grub_memcpy (packet, bootp_response + bootp_response_properties[i].offset, sizeof (*packet)); + grub_free (bootp_response); return packet; } +static void grub_ofnet_findcards (void) { struct grub_net_card *card; + grub_ieee1275_phandle_t devhandle; + grub_net_link_level_address_t lla; int i = 0; - auto int search_net_devices (struct grub_ieee1275_devalias *alias); int search_net_devices (struct grub_ieee1275_devalias *alias) @@ -128,53 +124,82 @@ void grub_ofnet_findcards (void) card = grub_malloc (sizeof (struct grub_net_card)); struct grub_ofnetcard_data *ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data)); ofdata->path = grub_strdup (alias->path); - card->data = ofdata; + + grub_ieee1275_finddevice (ofdata->path, &devhandle); + + if (grub_ieee1275_get_integer_property + (devhandle, "max-frame-size", &(ofdata->mtu), sizeof (ofdata->mtu), 0)) + return grub_error (GRUB_ERR_IO, "Couldn't retrieve mtu size."); + + if (grub_ieee1275_get_property (devhandle, "mac-address", &(lla.mac), 6, 0)) + return grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address."); + + lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + card->default_address = lla; + + card->data = ofdata; + card->flags = 0; card->name = grub_xasprintf("eth%d",i++); // grub_strdup (alias->name); grub_net_card_register (card); } return 0; } - /*Look at all nodes for devices of the type network*/ + /* Look at all nodes for devices of the type network. */ grub_ieee1275_devices_iterate (search_net_devices); - } +static void grub_ofnet_probecards (void) { struct grub_net_card *card; struct grub_net_card_driver *driver; + struct grub_net_network_level_interface *inter; + grub_bootp_t bootp_pckt; + grub_net_network_level_address_t addr; + grub_net_network_level_netaddress_t net; - /*Assign correspondent driver for each device. */ + /* Assign correspondent driver for each device. */ FOR_NET_CARDS (card) { FOR_NET_CARD_DRIVERS (driver) { if (driver->init(card) == GRUB_ERR_NONE) - { - card->driver = driver; - continue; - } + { + card->driver = driver; + bootp_pckt = grub_getbootp (); + if (bootp_pckt) + { + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + addr.ipv4 = bootp_pckt->yiaddr; + grub_net_add_addr ("bootp_cli_addr", card, addr, card->default_address, 0); + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + if (grub_strcmp (inter->name, "bootp_cli_addr") == 0) + break; + net.type = addr.type; + net.ipv4.base = addr.ipv4; + net.ipv4.masksize = 24; + grub_net_add_route ("bootp-router", net, inter); + } + grub_free (bootp_pckt); + break; + } } } } -GRUB_MOD_INIT(ofnet) +GRUB_MOD_INIT (ofnet) { + grub_getbootp = grub_getbootp_real; grub_net_card_driver_register (&ofdriver); - grub_ofnet_findcards(); - grub_ofnet_probecards(); - - /*init tftp stack - will be handled by module subsystem in the future*/ - tftp_ini (); - /*get bootp packet - won't be needed in the future*/ - bootp_pckt = grub_getbootp (); - grub_disknet_init(); + grub_ofnet_findcards (); + grub_ofnet_probecards (); } -GRUB_MODE_FINI(ofnet) +GRUB_MOD_FINI (ofnet) { grub_net_card_driver_unregister (&ofdriver); + grub_getbootp = NULL; } diff --git a/include/grub/ieee1275/ofnet.h b/include/grub/ieee1275/ofnet.h index ba4c62630..9a0ae29e3 100644 --- a/include/grub/ieee1275/ofnet.h +++ b/include/grub/ieee1275/ofnet.h @@ -60,14 +60,10 @@ struct grub_bootp { unsigned char chaddr [16]; /* Client hardware address */ char sname [64]; /* Server name */ char file [128]; /* Boot filename */ -// grub_uint32_t filesize ; /*File size (testing)*/ unsigned char vend [64]; }; typedef struct grub_bootp* grub_bootp_t; -char * grub_get_filestr(const char * ); -char * grub_ip2str (grub_uint32_t ip); -void grub_get_netinfo (grub_ofnet_t netinfo,grub_bootp_t packet); -grub_bootp_t grub_getbootp (void); +extern grub_bootp_t (*EXPORT_VAR (grub_getbootp)) (void); #endif /* ! GRUB_NET_HEADER */ From 457d1104f6137887a04c479ee43b5168b7733987 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:40:44 -0300 Subject: [PATCH 172/406] Add ofnet.h to Makefile.am --- grub-core/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 050075ef8..0fdb4b1db 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -113,6 +113,7 @@ endif if COND_i386_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h @@ -148,6 +149,7 @@ endif if COND_powerpc_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h @@ -155,6 +157,7 @@ endif if COND_sparc64_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h From 09375846b9ea73269302e97affc85dbb3a43f1b8 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:41:37 -0300 Subject: [PATCH 173/406] Add mtu to ieee1275 driver data. --- include/grub/ieee1275/ieee1275.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index 94a69d73d..87294610d 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -68,6 +68,7 @@ struct grub_ofnetcard_data { char *path; grub_ieee1275_ihandle_t handle; + grub_uint32_t mtu; }; /* Maps a device alias to a pathname. */ @@ -201,8 +202,6 @@ int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook) (struct grub_ieee1275_devalias * alias)); char *EXPORT_FUNC(grub_ieee1275_get_aliasdevname) (const char *path); -void EXPORT_FUNC(grub_ofnet_findcards) (void); -void EXPORT_FUNC(grub_ofnet_probecards) (void); char *EXPORT_FUNC(grub_ieee1275_canonicalise_devname) (const char *path); #endif /* ! GRUB_IEEE1275_HEADER */ From 25f1579b4348935084a7f349b1ee6c345fe83d39 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:42:34 -0300 Subject: [PATCH 174/406] Adapt protocols to new network struct. --- Makefile.util.def | 1 + grub-core/kern/file.c | 29 ++++++- grub-core/kern/fs.c | 2 +- grub-core/net/arp.c | 100 ++++++++++++------------ grub-core/net/ethernet.c | 18 ++--- grub-core/net/i386/pc/pxe.c | 2 +- grub-core/net/ip.c | 36 +++++---- grub-core/net/tftp.c | 151 ++++++++++++++++++------------------ include/grub/net.h | 125 ++++++++++++++++++++++------- include/grub/net/arp.h | 3 +- include/grub/net/device.h | 7 -- include/grub/net/ethernet.h | 4 +- include/grub/net/ip.h | 2 +- include/grub/net/tftp.h | 12 ++- include/grub/net/udp.h | 12 +-- 15 files changed, 296 insertions(+), 208 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index 579fd0714..0f7643b58 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -37,6 +37,7 @@ library = { common = grub-core/commands/extcmd.c; common = grub-core/commands/ls.c; common = grub-core/net/net.c; + common = grub-core/net/netbuff.c; common = grub-core/disk/dmraid_nvidia.c; common = grub-core/disk/loopback.c; common = grub-core/disk/lvm.c; diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c index c93fbf737..85ba8536c 100644 --- a/grub-core/kern/file.c +++ b/grub-core/kern/file.c @@ -20,10 +20,15 @@ #include #include #include +#include #include #include #include +grub_ssize_t (*grub_file_net_read) (grub_file_t file, void *buf, grub_size_t len) = NULL; +grub_err_t (*grub_file_net_open) (struct grub_file *file, const char *name) = NULL; +grub_err_t (*grub_file_net_seek) (struct grub_file *file, grub_off_t offset) = NULL; + grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX]; grub_file_filter_t grub_file_filters_enabled[GRUB_FILE_FILTER_MAX]; @@ -85,6 +90,13 @@ grub_file_open (const char *name) file->device = device; + if (device->net && grub_file_net_open) + { + if (grub_file_net_open (file, file_name)) + goto fail; + return file; + } + if (device->disk && file_name[0] != '/') /* This is a block list. */ file->fs = &grub_fs_blocklist; @@ -130,7 +142,7 @@ grub_file_open (const char *name) grub_ssize_t grub_file_read (grub_file_t file, void *buf, grub_size_t len) { - grub_ssize_t res; + grub_ssize_t res = 0; if (file->offset > file->size) { @@ -148,8 +160,12 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) if (len == 0) return 0; - - res = (file->fs->read) (file, buf, len); + if (file->device->disk) + res = (file->fs->read) (file, buf, len); + else + if (grub_file_net_read && file->device->net) + res = grub_file_net_read (file, buf, len); + if (res > 0) file->offset += res; @@ -159,6 +175,9 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) grub_err_t grub_file_close (grub_file_t file) { + if (file->device->net) + return grub_errno; + if (file->fs->close) (file->fs->close) (file); @@ -179,8 +198,12 @@ grub_file_seek (grub_file_t file, grub_off_t offset) "attempt to seek outside of the file"); return -1; } + + if (file->device->net && grub_file_net_seek) + grub_file_net_seek (file, offset); old = file->offset; file->offset = offset; + return old; } diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c index c4d6efa96..7166648be 100644 --- a/grub-core/kern/fs.c +++ b/grub-core/kern/fs.c @@ -95,7 +95,7 @@ grub_fs_probe (grub_device_t device) } } else if (device->net) - return device->net->protocol; + return NULL; grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem"); return 0; diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index c7b5d0573..8778a6e51 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -35,36 +35,40 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, grub_net_link_level_address_t *hw_addr) { struct arp_entry *entry; - struct grub_net_buff *nb; + struct grub_net_buff nb; struct arphdr *arp_header; grub_net_link_level_address_t target_hw_addr; - grub_uint8_t *aux, i; + char *aux, arp_data[128]; + int i; - /* Check cache table */ + /* Check cache table. */ entry = arp_find_entry (proto_addr); if (entry) { *hw_addr = entry->ll_address; return GRUB_ERR_NONE; } - /* Build a request packet */ - nb = grub_netbuff_alloc (2048); - if (!nb) - return grub_errno; - grub_netbuff_reserve(nb, 2048); - grub_netbuff_push(nb, sizeof(*arp_header) + 2 * (6 + 6)); - arp_header = (struct arphdr *)nb->data; + /* Build a request packet. */ + nb.head = arp_data; + nb.end = arp_data + sizeof (arp_data); + grub_netbuff_clear (&nb); + + grub_netbuff_reserve (&nb,128); + grub_netbuff_push (&nb, sizeof(*arp_header) + 2 * (6 + 4)); + arp_header = (struct arphdr *) nb.data; arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET); arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP); + /* FIXME Add support to ipv6 address. */ arp_header->hln = 6; arp_header->pln = 4; arp_header->op = grub_cpu_to_be16 (ARP_REQUEST); - aux = (grub_uint8_t *)arp_header + sizeof(*arp_header); - /* Sender hardware address */ - grub_memcpy(aux, &inf->hwaddress.mac, 6); + aux = (char *) arp_header + sizeof (*arp_header); + /* Sender hardware address. */ + grub_memcpy (aux, &inf->hwaddress.mac, 6); + aux += 6; /* Sender protocol address */ - grub_memcpy(aux, &inf->address.ipv4, 4); + grub_memcpy (aux, &inf->address.ipv4, 4); aux += 4; /* Target hardware address */ for(i = 0; i < 6; i++) @@ -72,49 +76,40 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, aux += 6; /* Target protocol address */ grub_memcpy(aux, &proto_addr->ipv4, 4); - grub_memset (&target_hw_addr.mac, 0xff, 6); - send_ethernet_packet (inf, nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); - grub_netbuff_clear(nb); - grub_netbuff_reserve(nb, 2048); - - grub_uint64_t start_time, current_time; - start_time = grub_get_time_ms(); - do + send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); + for (i = 0; i < 3; i++) { - grub_net_recv_ethernet_packet (inf, nb, GRUB_NET_ETHERTYPE_ARP); - /* Now check cache table again */ - entry = arp_find_entry(proto_addr); + entry = arp_find_entry (proto_addr); if (entry) - { - grub_memcpy(hw_addr, &entry->ll_address, sizeof (*hw_addr)); - grub_netbuff_clear(nb); - return GRUB_ERR_NONE; - } - current_time = grub_get_time_ms(); - if (current_time - start_time > 3000) - break; - } while (! entry); - grub_netbuff_clear(nb); + { + grub_memcpy (hw_addr, &entry->ll_address, sizeof (*hw_addr)); + return GRUB_ERR_NONE; + } + grub_net_pool_cards (200); + + } + return grub_error (GRUB_ERR_TIMEOUT, "Timeout: could not resolve hardware address."); } grub_err_t -grub_net_arp_receive (struct grub_net_network_level_interface *inf, - struct grub_net_buff *nb) +grub_net_arp_receive (struct grub_net_buff *nb) { struct arphdr *arp_header = (struct arphdr *)nb->data; struct arp_entry *entry; grub_uint8_t *sender_hardware_address, *sender_protocol_address; grub_uint8_t *target_hardware_address, *target_protocol_address; grub_net_network_level_address_t hwaddress; + struct grub_net_network_level_interface *inf; sender_hardware_address = (grub_uint8_t *) arp_header + sizeof(*arp_header); sender_protocol_address = sender_hardware_address + arp_header->hln; target_hardware_address = sender_protocol_address + arp_header->pln; target_protocol_address = target_hardware_address + arp_header->hln; grub_memcpy (&hwaddress.ipv4, sender_protocol_address, 4); + /* Check if the sender is in the cache table */ entry = arp_find_entry(&hwaddress); /* Update sender hardware address */ @@ -134,21 +129,24 @@ grub_net_arp_receive (struct grub_net_network_level_interface *inf, new_table_entry = 0; } - /* Am I the protocol address target? */ - if (grub_memcmp(target_protocol_address, inf->hwaddress.mac, 6) == 0 - && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) + FOR_NET_NETWORK_LEVEL_INTERFACES(inf) { - grub_net_link_level_address_t aux; - /* Swap hardware fields */ - grub_memcpy(target_hardware_address, sender_hardware_address, arp_header->hln); - grub_memcpy(sender_hardware_address, inf->hwaddress.mac, 6); - grub_memcpy(aux.mac, sender_protocol_address, 6); - grub_memcpy(sender_protocol_address, target_protocol_address, arp_header->pln); - grub_memcpy(target_protocol_address, aux.mac, arp_header->pln); - /* Change operation to REPLY and send packet */ - arp_header->op = grub_be_to_cpu16 (ARP_REPLY); - grub_memcpy (aux.mac, target_hardware_address, 6); - send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP); + /* Am I the protocol address target? */ + if (grub_memcmp (target_protocol_address, &inf->address.ipv4, 6) == 0 + && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) + { + grub_net_link_level_address_t aux; + /* Swap hardware fields */ + grub_memcpy (target_hardware_address, sender_hardware_address, arp_header->hln); + grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6); + grub_memcpy (aux.mac, sender_protocol_address, 6); + grub_memcpy (sender_protocol_address, target_protocol_address, arp_header->pln); + grub_memcpy (target_protocol_address, aux.mac, arp_header->pln); + /* Change operation to REPLY and send packet */ + arp_header->op = grub_be_to_cpu16 (ARP_REPLY); + grub_memcpy (aux.mac, target_hardware_address, 6); + send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP); + } } return GRUB_ERR_NONE; } diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index cbda4c875..c96a65602 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -23,23 +23,20 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, eth->type = grub_cpu_to_be16 (ethertype); - return inf->card->driver->send (inf->card,nb); + return inf->card->driver->send (inf->card, nb); } grub_err_t -grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf, - struct grub_net_buff *nb, - grub_uint16_t ethertype) +grub_net_recv_ethernet_packet (struct grub_net_buff *nb) { struct etherhdr *eth; struct llchdr *llch; struct snaphdr *snaph; grub_uint16_t type; - inf->card->driver->recv (inf->card, nb); eth = (struct etherhdr *) nb->data; type = grub_be_to_cpu16 (eth->type); - grub_netbuff_pull(nb,sizeof (*eth)); + grub_netbuff_pull (nb, sizeof (*eth)); if (type <= 1500) { @@ -56,10 +53,13 @@ grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf, /* ARP packet */ if (type == GRUB_NET_ETHERTYPE_ARP) - grub_net_arp_receive(inf, nb); + { + grub_net_arp_receive (nb); + grub_netbuff_free (nb); + } /* IP packet */ - if(type == GRUB_NET_ETHERTYPE_IP && ethertype == GRUB_NET_ETHERTYPE_IP) - return GRUB_ERR_NONE; + if (type == GRUB_NET_ETHERTYPE_IP) + grub_net_recv_ip_packets (nb); return GRUB_ERR_NONE; } diff --git a/grub-core/net/i386/pc/pxe.c b/grub-core/net/i386/pc/pxe.c index c07aa78f9..8e7f75ed8 100644 --- a/grub-core/net/i386/pc/pxe.c +++ b/grub-core/net/i386/pc/pxe.c @@ -292,7 +292,7 @@ grub_pxefs_label (grub_device_t device __attribute ((unused)), return GRUB_ERR_NONE; } -static struct grub_fs grub_pxefs_fs = +static struct grub_net_app_protocol grub_pxefs_fs = { .name = "pxe", .dir = grub_pxefs_dir, diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 9a96ef532..d6684c29e 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -33,7 +34,7 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, grub_net_link_level_address_t ll_target_addr; grub_err_t err; - grub_netbuff_push(nb,sizeof(*iph)); + grub_netbuff_push (nb, sizeof(*iph)); iph = (struct iphdr *) nb->data; iph->verhdrlen = ((4 << 4) | 5); @@ -49,17 +50,15 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, iph->chksum = 0 ; iph->chksum = ipchksum((void *)nb->data, sizeof(*iph)); - /* Determine link layer target address via ARP */ - err = grub_net_arp_resolve(inf, target, &ll_target_addr); + /* Determine link layer target address via ARP. */ + err = grub_net_arp_resolve (inf, target, &ll_target_addr); if (err) return err; - return send_ethernet_packet (inf, nb, ll_target_addr, GRUB_NET_ETHERTYPE_IP); } - +/* static int -ip_filter (struct grub_net_buff *nb, - struct grub_net_network_level_interface *inf) +ip_filter (struct grub_net_buff *nb) { struct iphdr *iph = (struct iphdr *) nb->data; grub_err_t err; @@ -80,15 +79,22 @@ ip_filter (struct grub_net_buff *nb, } return 1; } - +*/ grub_err_t -grub_net_recv_ip_packets (struct grub_net_network_level_interface *inf) +grub_net_recv_ip_packets (struct grub_net_buff *nb) { - struct grub_net_buff *nb; - nb = grub_netbuff_alloc (2048); - if (!nb) - return grub_errno; - grub_net_recv_ethernet_packet (inf, nb, GRUB_NET_ETHERTYPE_IP); - ip_filter (nb, inf); + struct iphdr *iph = (struct iphdr *) nb->data; + grub_netbuff_pull (nb, sizeof (*iph)); + + switch (iph->protocol) + { + case IP_UDP: + return grub_net_recv_udp_packet (nb); + break; + default: + grub_netbuff_free (nb); + break; + } + return GRUB_ERR_NONE; } diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 16b60eeb6..cafb30585 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -14,26 +14,23 @@ tftp_open (struct grub_file *file, const char *filename) { struct tftphdr *tftph; char *rrq; - char *ptr; + int i; int rrqlen; - int hdrlen; - struct grub_net_buff *nb; - grub_net_network_level_address_t addr; + int hdrlen; + char open_data[1500]; + struct grub_net_buff nb; + tftp_data_t data = grub_malloc (sizeof *data); grub_err_t err; + + file->device->net->socket->data = (void *) data; + nb.head = open_data; + nb.end = open_data + sizeof (open_data); + grub_netbuff_clear (&nb); - err = grub_net_resolve_address (file->device->net->name - + sizeof ("tftp,") - 1, &addr); - if (err) - return err; + grub_netbuff_reserve (&nb,1500); + grub_netbuff_push (&nb,sizeof (*tftph)); - nb = grub_netbuff_alloc (2048); - if (!nb) - return grub_errno; - - grub_netbuff_reserve (nb,2048); - grub_netbuff_push (nb,sizeof (*tftph)); - - tftph = (struct tftphdr *) nb->data; + tftph = (struct tftphdr *) nb.data; rrq = (char *) tftph->u.rrq; rrqlen = 0; @@ -64,89 +61,93 @@ tftp_open (struct grub_file *file, const char *filename) rrq += grub_strlen ("0") + 1; hdrlen = sizeof (tftph->opcode) + rrqlen; - grub_netbuff_unput (nb,nb->tail - (nb->data+hdrlen)); + grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen)); - err = grub_net_send_udp_packet (&addr, - nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT); + file->device->net->socket->out_port = TFTP_SERVER_PORT; + + err = grub_net_send_udp_packet (file->device->net->socket, &nb); if (err) return err; - /* Receive OACK. */ - grub_netbuff_clear (nb); - grub_netbuff_reserve (nb,2048); - - do + /* Receive OACK packet. */ + for ( i = 0; i < 3; i++) { - err = grub_net_recv_udp_packet (&addr, nb, - TFTP_CLIENT_PORT, TFTP_SERVER_PORT); - if (err) - return err; + grub_net_pool_cards (100); + if (grub_errno) + return grub_errno; + if (file->device->net->socket->status != 0) + break; + /* Retry. */ + //err = grub_net_send_udp_packet (file->device->net->socket, &nb); + // if (err) + // return err; } - while (nb->tail == nb->data); - file->size = 0; + if (file->device->net->socket->status == 0) + return grub_error (GRUB_ERR_TIMEOUT,"Time out opening tftp."); + file->size = data->file_size; - for (ptr = nb->data; ptr < nb->tail; ) - grub_printf ("%02x ", *ptr); - - for (ptr = nb->data; ptr < nb->tail; ) - { - if (grub_memcmp (ptr, "tsize\0=", sizeof ("tsize\0=") - 1) == 0) - { - file->size = grub_strtoul (ptr + sizeof ("tsize\0=") - 1, 0, 0); - grub_errno = GRUB_ERR_NONE; - } - while (ptr < nb->tail && *ptr) - ptr++; - ptr++; - } return GRUB_ERR_NONE; } -static grub_ssize_t -tftp_receive (struct grub_file *file, char *buf, grub_size_t len) +static grub_err_t +tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) { struct tftphdr *tftph; - // char *token,*value,*temp; + char nbdata[128]; + tftp_data_t data = sock->data; grub_err_t err; - grub_net_network_level_address_t addr; - struct grub_net_buff nb; + char *ptr; + struct grub_net_buff nb_ack; - err = grub_net_resolve_address (file->device->net->name - + sizeof ("tftp,") - 1, &addr); - if (err) - return err; + nb_ack.head = nbdata; + nb_ack.end = nbdata + sizeof (nbdata); - grub_net_recv_udp_packet (&addr, &nb, - TFTP_CLIENT_PORT, TFTP_SERVER_PORT); - - tftph = (struct tftphdr *) nb.data; + + tftph = (struct tftphdr *) nb->data; switch (grub_be_to_cpu16 (tftph->opcode)) { + case TFTP_OACK: + for (ptr = nb->data; ptr < nb->tail; ) + { + if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) + data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1, 0, 0); + while (ptr < nb->tail && *ptr) + ptr++; + ptr++; + } + sock->status = 1; + data->block = 0; + grub_netbuff_clear(nb); + break; case TFTP_DATA: - grub_netbuff_pull (&nb,sizeof (tftph->opcode) + sizeof (tftph->u.data.block)); - // if (tftph->u.data.block == block + 1) - //{ - // block = tftph->u.data.block; - grub_memcpy (buf, nb.data, len); - //} - //else - //grub_netbuff_clear(&nb); - break; + grub_netbuff_pull (nb,sizeof (tftph->opcode) + sizeof (tftph->u.data.block)); + + if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) + { + data->block++; + if (nb->tail - nb->data < 1024) + sock->status = 2; + } + else + grub_netbuff_clear(nb); + + break; case TFTP_ERROR: - grub_netbuff_clear (&nb); + grub_netbuff_clear (nb); return grub_error (GRUB_ERR_IO, (char *)tftph->u.err.errmsg); + break; } + grub_netbuff_clear (&nb_ack); + grub_netbuff_reserve (&nb_ack,128); + grub_netbuff_push (&nb_ack,sizeof (tftph->opcode) + sizeof (tftph->u.ack.block)); - nb.data = nb.tail = nb.end; - - grub_netbuff_push (&nb,sizeof (tftph->opcode) + sizeof (tftph->u.ack.block)); - - tftph = (struct tftphdr *) nb.data; + tftph = (struct tftphdr *) nb_ack.data; tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); - // tftph->u.ack.block = block; + tftph->u.ack.block = data->block; - return grub_net_send_udp_packet (&addr, &nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT); + err = grub_net_send_udp_packet (sock, &nb_ack); + return err; } static grub_err_t @@ -155,7 +156,7 @@ tftp_close (struct grub_file *file __attribute__ ((unused))) return 0; } -static struct grub_fs grub_tftp_protocol = +static struct grub_net_app_protocol grub_tftp_protocol = { .name = "tftp", .open = tftp_open, diff --git a/include/grub/net.h b/include/grub/net.h index 20bf3c0e6..37b258f36 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -23,19 +23,10 @@ #include #include #include +#include #include #include -typedef struct grub_fs *grub_net_app_level_t; - -typedef struct grub_net -{ - char *name; - grub_net_app_level_t protocol; -} *grub_net_t; - -extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); - typedef enum grub_link_level_protocol_id { GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET @@ -75,6 +66,37 @@ struct grub_net_card_driver grub_size_t (*recv) (struct grub_net_card *dev, struct grub_net_buff *buf); }; +extern struct grub_net_card_driver *grub_net_card_drivers; + +static inline void +grub_net_card_driver_register (struct grub_net_card_driver *driver) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_card_drivers), + GRUB_AS_LIST (driver)); +} + +static inline void +grub_net_card_driver_unregister (struct grub_net_card_driver *driver) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_card_drivers), + GRUB_AS_LIST (driver)); +} + +#define FOR_NET_CARD_DRIVERS(var) for (var = grub_net_card_drivers; var; var = var->next) + +typedef struct grub_net_packet +{ + struct grub_net_packet *next; + struct grub_net_packet *prev; + struct grub_net_packets *up; + struct grub_net_buff *nb; +} grub_net_packet_t; + +typedef struct grub_net_packets +{ + grub_net_packet_t *first; + grub_net_packet_t *last; +} grub_net_packets_t; struct grub_net_card { @@ -118,20 +140,6 @@ typedef struct grub_net_network_level_netaddress }; } grub_net_network_level_netaddress_t; -typedef struct grub_net_packet -{ - struct grub_net_packet *next; - struct grub_net_packet *prev; - struct grub_net_packets *up; - struct grub_net_buff *nb; -} grub_net_packet_t; - -typedef struct grub_net_packets -{ - struct grub_net_packet *first; - struct grub_net_packet *last; -} grub_net_packets_t; - #define FOR_PACKETS(cont,var) for (var = (cont).first; var; var = var->next) static inline grub_err_t @@ -172,6 +180,66 @@ grub_net_remove_packet (grub_net_packet_t *pkt) pkt->up->last = pkt->prev; } +typedef struct grub_net_app_protocol *grub_net_app_level_t; + +typedef struct grub_net_socket *grub_net_socket_t; + +struct grub_net_app_protocol +{ + struct grub_net_app_protocol *next; + char *name; + grub_err_t (*dir) (grub_device_t device, const char *path, + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)); + grub_err_t (*open) (struct grub_file *file, const char *filename); + grub_err_t (*read) (grub_net_socket_t sock, struct grub_net_buff *nb); + grub_err_t (*close) (struct grub_file *file); + grub_err_t (*label) (grub_device_t device, char **label); +}; + +struct grub_net_socket +{ + struct grub_net_socket *next; + int status; + int in_port; + int out_port; + grub_net_app_level_t app; + grub_net_network_level_address_t out_nla; + struct grub_net_network_level_interface *inf; + grub_net_packets_t *packs; + void *data; +}; + +extern struct grub_net_socket *grub_net_sockets; + +static inline void +grub_net_socket_register (grub_net_socket_t socket) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_sockets), + GRUB_AS_LIST (socket)); +} + +static inline void +grub_net_socket_unregister (grub_net_socket_t socket) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_sockets), + GRUB_AS_LIST (socket)); +} + +#define FOR_NET_SOCKETS(var) for (var = grub_net_sockets; var; var = var->next) + +typedef struct grub_net +{ + char *name; + grub_net_app_level_t protocol; + grub_net_socket_t socket; +} *grub_net_t; + +extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); +extern grub_ssize_t (*EXPORT_VAR (grub_file_net_read)) (grub_file_t file, void *buf, grub_size_t len); +extern grub_err_t (*EXPORT_VAR (grub_file_net_open)) (struct grub_file *file, const char *name); +extern grub_err_t (*EXPORT_VAR (grub_file_net_seek)) (struct grub_file *file, grub_off_t offset); + struct grub_net_network_level_interface { struct grub_net_network_level_interface *next; @@ -182,7 +250,6 @@ struct grub_net_network_level_interface grub_net_interface_flags_t flags; struct grub_net_bootp_ack *dhcp_ack; grub_size_t dhcp_acklen; - grub_net_packets_t nl_pending; void *data; }; @@ -354,7 +421,7 @@ grub_err_t grub_net_recv_link_layer (struct grub_net_network_level_interface *in grub_net_packet_handler_t handler); grub_err_t -grub_net_recv_ip_packets (struct grub_net_network_level_interface *inf); +grub_net_recv_ip_packets (struct grub_net_buff *nb); grub_err_t grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, @@ -363,4 +430,10 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, #define FOR_NET_NL_PACKETS(inf, var) FOR_PACKETS(inf->nl_pending, var) +void +grub_net_pool_cards (unsigned time); + +void +hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str); + #endif /* ! GRUB_NET_HEADER */ diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h index 691fda307..c60ea333f 100644 --- a/include/grub/net/arp.h +++ b/include/grub/net/arp.h @@ -27,8 +27,7 @@ struct arphdr { grub_uint16_t op; } __attribute__ ((packed)); -extern grub_err_t grub_net_arp_receive(struct grub_net_network_level_interface *inf, - struct grub_net_buff *nb); +extern grub_err_t grub_net_arp_receive(struct grub_net_buff *nb); extern grub_err_t grub_net_arp_resolve(struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *addr, diff --git a/include/grub/net/device.h b/include/grub/net/device.h index 9f1b9bf1d..e69de29bb 100644 --- a/include/grub/net/device.h +++ b/include/grub/net/device.h @@ -1,7 +0,0 @@ -struct grub_net_card -{ - struct grub_net_card *next; - char *name; - struct grub_net_card_driver *driver; - void *data; -}; diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h index 7a0235be6..7ff7a4562 100644 --- a/include/grub/net/ethernet.h +++ b/include/grub/net/ethernet.h @@ -52,8 +52,6 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, grub_net_link_level_address_t target_addr, grub_uint16_t ethertype); grub_err_t -grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf, - struct grub_net_buff *nb, - grub_uint16_t ethertype); +grub_net_recv_ethernet_packet (struct grub_net_buff *nb); #endif diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index 6f748bbf3..cb8481a7d 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -26,7 +26,7 @@ struct ip6hdr grub_uint8_t daddr[16]; } __attribute__ ((packed)); -#define IP_UDP 17 /* UDP protocol */ +#define IP_UDP 0x11 /* UDP protocol */ #define IP_BROADCAST 0xFFFFFFFF grub_uint16_t ipchksum(void *ipv, int len); diff --git a/include/grub/net/tftp.h b/include/grub/net/tftp.h index 1f1c48616..c67380817 100644 --- a/include/grub/net/tftp.h +++ b/include/grub/net/tftp.h @@ -14,7 +14,6 @@ /* IP port for the TFTP server */ #define TFTP_SERVER_PORT 69 -#define TFTP_CLIENT_PORT 26300 /* We define these based on what's in arpa/tftp.h. We just like our @@ -40,10 +39,17 @@ #define TFTP_EBADID 5 /* unknown transfer ID */ #define TFTP_EEXISTS 6 /* file already exists */ #define TFTP_ENOUSER 7 /* no such user */ -#define TFTP_DEFAULT_FILENAME "kernel" /* * own here because this is cleaner, and maps to the same data layout. * */ + +typedef struct tftp_data + { + int file_size; + int block; + } *tftp_data_t; + + struct tftphdr { grub_uint16_t opcode; union { @@ -65,6 +71,4 @@ struct tftphdr { } u; } __attribute__ ((packed)) ; -void tftp_ini(void); -void tftp_fini(void); #endif diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h index f1992467d..86311ccf1 100644 --- a/include/grub/net/udp.h +++ b/include/grub/net/udp.h @@ -12,20 +12,12 @@ struct udphdr } __attribute__ ((packed)); grub_err_t -grub_net_send_udp_packet (const grub_net_network_level_address_t *target, - struct grub_net_buff *nb, grub_uint16_t srcport, - grub_uint16_t destport); - +grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff *nb); grub_err_t -grub_net_recv_udp_packets (struct grub_net_network_level_interface *inf); +grub_net_recv_udp_packet (struct grub_net_buff *nb); -grub_err_t -grub_net_recv_udp_packet (const grub_net_network_level_address_t *target, - struct grub_net_buff *buf, - grub_uint16_t srcport, grub_uint16_t destport); #define FOR_NET_UDP_PACKETS(inf, var) FOR_PACKETS(inf->udp_pending, var) - #endif From 6ac14e6cef8b3dc675fc09239b2101dcc4393a18 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Apr 2011 09:34:58 +0200 Subject: [PATCH 175/406] Fix EFI compilation --- grub-core/disk/efi/efidisk.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 20fea956f..1bf764f10 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -537,11 +537,11 @@ grub_efidisk_open (const char *name, struct grub_disk *disk) grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n", m, (unsigned long long) m->last_block, m->block_size); disk->total_sectors = m->last_block; - if (m->blocksize & (m->blocksize - 1) || !m->blocksize) + if (m->block_size & (m->block_size - 1) || !m->block_size) return grub_error (GRUB_ERR_IO, "invalid sector size %d", - m->blocksize); + m->block_size); for (disk->log_sector_size = 0; - (1 << disk->log_sector_size) < m->blocksize; + (1U << disk->log_sector_size) < m->block_size; disk->log_sector_size++); disk->data = d; From b38a4983949bbf66a7ecdae3423b2401ce2e635f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Apr 2011 14:40:15 +0200 Subject: [PATCH 176/406] BPB patching support (untested) --- grub-core/fs/fat.c | 47 +------------ grub-core/loader/i386/pc/chainloader.c | 91 ++++++++++++++++++++++++-- grub-core/loader/i386/pc/ntldr.c | 2 + grub-core/normal/main.c | 3 + include/grub/i386/pc/chainloader.h | 7 +- include/grub/ntfs.h | 8 ++- 6 files changed, 99 insertions(+), 59 deletions(-) diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index 89050943c..7906cf1b2 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -26,6 +26,7 @@ #include #include #include +#include #define GRUB_FAT_DIR_ENTRY_SIZE 32 @@ -49,52 +50,6 @@ | GRUB_FAT_ATTR_ARCHIVE \ | GRUB_FAT_ATTR_VOLUME_ID) -struct grub_fat_bpb -{ - grub_uint8_t jmp_boot[3]; - grub_uint8_t oem_name[8]; - grub_uint16_t bytes_per_sector; - grub_uint8_t sectors_per_cluster; - grub_uint16_t num_reserved_sectors; - grub_uint8_t num_fats; - grub_uint16_t num_root_entries; - grub_uint16_t num_total_sectors_16; - grub_uint8_t media; - grub_uint16_t sectors_per_fat_16; - grub_uint16_t sectors_per_track; - grub_uint16_t num_heads; - grub_uint32_t num_hidden_sectors; - grub_uint32_t num_total_sectors_32; - union - { - struct - { - grub_uint8_t num_ph_drive; - grub_uint8_t reserved; - grub_uint8_t boot_sig; - grub_uint32_t num_serial; - grub_uint8_t label[11]; - grub_uint8_t fstype[8]; - } __attribute__ ((packed)) fat12_or_fat16; - struct - { - grub_uint32_t sectors_per_fat_32; - grub_uint16_t extended_flags; - grub_uint16_t fs_version; - grub_uint32_t root_cluster; - grub_uint16_t fs_info; - grub_uint16_t backup_boot_sector; - grub_uint8_t reserved[12]; - grub_uint8_t num_ph_drive; - grub_uint8_t reserved1; - grub_uint8_t boot_sig; - grub_uint32_t num_serial; - grub_uint8_t label[11]; - grub_uint8_t fstype[8]; - } __attribute__ ((packed)) fat32; - } __attribute__ ((packed)) version_specific; -} __attribute__ ((packed)); - struct grub_fat_dir_entry { grub_uint8_t name[11]; diff --git a/grub-core/loader/i386/pc/chainloader.c b/grub-core/loader/i386/pc/chainloader.c index fd99c81d5..174e5b7a5 100644 --- a/grub-core/loader/i386/pc/chainloader.c +++ b/grub-core/loader/i386/pc/chainloader.c @@ -37,11 +37,19 @@ #include #include #include +#include +#include static grub_dl_t my_mod; static int boot_drive; static void *boot_part_addr; +typedef enum + { + GRUB_CHAINLOADER_FORCE = 0x1, + GRUB_CHAINLOADER_BPB = 0x2, + } grub_chainloader_flags_t; + static grub_err_t grub_chainloader_boot (void) { @@ -59,6 +67,63 @@ grub_chainloader_unload (void) return GRUB_ERR_NONE; } +void +grub_chainloader_patch_bpb (void *bs, grub_device_t dev, grub_uint8_t dl) +{ + grub_uint32_t part_start = 0; + if (dev && dev->disk) + part_start = grub_partition_get_start (dev->disk->partition); + if (grub_memcmp ((char *) &((struct grub_ntfs_bpb *) bs)->oem_name, + "NTFS", 4) == 0) + { + struct grub_ntfs_bpb *bpb = (struct grub_ntfs_bpb *) bs; + bpb->num_hidden_sectors = grub_cpu_to_le32 (part_start); + bpb->bios_drive = dl; + return; + } + + do + { + struct grub_fat_bpb *bpb = (struct grub_fat_bpb *) bs; + if (grub_strncmp((const char *) bpb->version_specific.fat12_or_fat16.fstype, "FAT12", 5) + && grub_strncmp((const char *) bpb->version_specific.fat12_or_fat16.fstype, "FAT16", 5) + && grub_strncmp((const char *) bpb->version_specific.fat32.fstype, "FAT32", 5)) + break; + + if (grub_le_to_cpu16 (bpb->bytes_per_sector) < 512 + || (grub_le_to_cpu16 (bpb->bytes_per_sector) + & (grub_le_to_cpu16 (bpb->bytes_per_sector) - 1))) + break; + + if (bpb->sectors_per_cluster == 0 + || (bpb->sectors_per_cluster & (bpb->sectors_per_cluster - 1))) + break; + + if (bpb->num_reserved_sectors == 0) + break; + if (bpb->num_total_sectors_16 == 0 || bpb->num_total_sectors_32 == 0) + break; + + if (bpb->num_fats == 0) + break; + + if (bpb->sectors_per_fat_16) + { + bpb->num_hidden_sectors = grub_cpu_to_le32 (part_start); + bpb->version_specific.fat12_or_fat16.num_ph_drive = dl; + return; + } + if (bpb->version_specific.fat32.sectors_per_fat_32) + { + bpb->num_hidden_sectors = grub_cpu_to_le32 (part_start); + bpb->version_specific.fat32.num_ph_drive = dl; + return; + } + break; + } + while (0); +} + static void grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags) { @@ -119,6 +184,9 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags) } } + if (flags & GRUB_CHAINLOADER_BPB) + grub_chainloader_patch_bpb ((void *) 0x7C00, dev, drive); + if (dev) grub_device_close (dev); @@ -145,11 +213,23 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), { grub_chainloader_flags_t flags = 0; - if (argc > 0 && grub_strcmp (argv[0], "--force") == 0) + while (argc > 0) { - flags |= GRUB_CHAINLOADER_FORCE; - argc--; - argv++; + if (grub_strcmp (argv[0], "--force") == 0) + { + flags |= GRUB_CHAINLOADER_FORCE; + argc--; + argv++; + continue; + } + if (grub_strcmp (argv[0], "--bpb") == 0) + { + flags |= GRUB_CHAINLOADER_BPB; + argc--; + argv++; + continue; + } + break; } if (argc == 0) @@ -165,7 +245,8 @@ static grub_command_t cmd; GRUB_MOD_INIT(chainloader) { cmd = grub_register_command ("chainloader", grub_cmd_chainloader, - 0, N_("Load another boot loader.")); + "[--force|--bpb] FILE", + N_("Load another boot loader.")); my_mod = mod; } diff --git a/grub-core/loader/i386/pc/ntldr.c b/grub-core/loader/i386/pc/ntldr.c index 0c33a0680..9649cdfbe 100644 --- a/grub-core/loader/i386/pc/ntldr.c +++ b/grub-core/loader/i386/pc/ntldr.c @@ -32,6 +32,7 @@ #include #include #include +#include static grub_dl_t my_mod; static struct grub_relocator *rel; @@ -110,6 +111,7 @@ grub_cmd_ntldr (grub_command_t cmd __attribute__ ((unused)), grub_device_close (dev); goto fail; } + grub_chainloader_patch_bpb (bs, dev, edx); } if (dev) diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c index cefb1cb9b..c04accb6d 100644 --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -515,6 +515,9 @@ GRUB_MOD_INIT(normal) /* Set default color names. */ grub_env_set ("color_normal", "white/black"); grub_env_set ("color_highlight", "black/white"); + + grub_env_set ("grub_feature_chainloader_bpb", "--bpb"); + grub_env_export ("grub_feature_chainloader_bpb"); } GRUB_MOD_FINI(normal) diff --git a/include/grub/i386/pc/chainloader.h b/include/grub/i386/pc/chainloader.h index ca1da23a7..4776b181b 100644 --- a/include/grub/i386/pc/chainloader.h +++ b/include/grub/i386/pc/chainloader.h @@ -21,10 +21,7 @@ #include -/* Common function for normal and rescue mode commands. */ -typedef enum - { - GRUB_CHAINLOADER_FORCE = 0x1 - } grub_chainloader_flags_t; +void +grub_chainloader_patch_bpb (void *bs, grub_device_t dev, grub_uint8_t dl); #endif /* GRUB_CHAINLOADER_MACHINE_HEADER */ diff --git a/include/grub/ntfs.h b/include/grub/ntfs.h index 31b99398b..9e2e34707 100644 --- a/include/grub/ntfs.h +++ b/include/grub/ntfs.h @@ -106,14 +106,16 @@ struct grub_ntfs_bpb grub_uint16_t sectors_per_track; grub_uint16_t num_heads; grub_uint32_t num_hidden_sectors; - grub_uint32_t reserved_3[2]; + grub_uint32_t reserved_3; + grub_uint8_t bios_drive; + grub_uint8_t reserved_4[3]; grub_uint64_t num_total_sectors; grub_uint64_t mft_lcn; grub_uint64_t mft_mirr_lcn; grub_int8_t clusters_per_mft; - grub_int8_t reserved_4[3]; - grub_int8_t clusters_per_index; grub_int8_t reserved_5[3]; + grub_int8_t clusters_per_index; + grub_int8_t reserved_6[3]; grub_uint64_t num_serial; grub_uint32_t checksum; } __attribute__ ((packed)); From 5bfb6e71e8c3d189cc55542239a01794096344bb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Apr 2011 15:05:53 +0200 Subject: [PATCH 177/406] features support --- grub-core/normal/main.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c index c04accb6d..fa20d0d78 100644 --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -471,9 +471,14 @@ grub_mini_cmd_clear (struct grub_command *cmd __attribute__ ((unused)), static grub_command_t cmd_clear; static void (*grub_xputs_saved) (const char *str); +static const char *features[] = { + "feature_chainloader_bpb", "feature_ntldr" +}; GRUB_MOD_INIT(normal) { + unsigned i; + /* Previously many modules depended on gzio. Be nice to user and load it. */ grub_dl_load ("gzio"); @@ -516,8 +521,11 @@ GRUB_MOD_INIT(normal) grub_env_set ("color_normal", "white/black"); grub_env_set ("color_highlight", "black/white"); - grub_env_set ("grub_feature_chainloader_bpb", "--bpb"); - grub_env_export ("grub_feature_chainloader_bpb"); + for (i = 0; i < ARRAY_SIZE (features); i++) + { + grub_env_set (features[i], "y"); + grub_env_export (features[i]); + } } GRUB_MOD_FINI(normal) From 3dd3dd335fe8efb23d54bfbc322701d54c28a65d Mon Sep 17 00:00:00 2001 From: Feiran Zheng Date: Mon, 11 Apr 2011 08:16:13 +0200 Subject: [PATCH 178/406] minix3fs support --- grub-core/Makefile.core.def | 5 ++ grub-core/fs/minix.c | 164 +++++++++++++++++++++++++++--------- grub-core/fs/minix3.c | 2 + 3 files changed, 132 insertions(+), 39 deletions(-) create mode 100644 grub-core/fs/minix3.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 7c26b37e9..9f418a0b7 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -958,6 +958,11 @@ module = { common = fs/minix2.c; }; +module = { + name = minix3; + common = fs/minix3.c; +}; + module = { name = nilfs2; common = fs/nilfs2.c; diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 679e1ec51..c93dfe085 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -25,14 +25,17 @@ #include #include -#ifdef MODE_MINIX2 +#ifdef MODE_MINIX3 +#define GRUB_MINIX_MAGIC 0x4D5A +#elif defined(MODE_MINIX2) #define GRUB_MINIX_MAGIC 0x2468 #define GRUB_MINIX_MAGIC_30 0x2478 #else #define GRUB_MINIX_MAGIC 0x137F #define GRUB_MINIX_MAGIC_30 0x138F #endif -#define GRUB_MINIX_BSIZE 1024U + +#define GRUB_MINIX_INODE_DIR_BLOCKS 7 #define GRUB_MINIX_LOG2_BSIZE 1 #define GRUB_MINIX_ROOT_INODE 1 #define GRUB_MINIX_MAX_SYMLNK_CNT 8 @@ -41,7 +44,7 @@ #define GRUB_MINIX_IFDIR 0040000U #define GRUB_MINIX_IFLNK 0120000U -#ifdef MODE_MINIX2 +#if defined(MODE_MINIX2) || defined(MODE_MINIX3) typedef grub_uint32_t grub_minix_uintn_t; #define grub_minix_le_to_cpu_n grub_le_to_cpu32 #else @@ -50,6 +53,13 @@ typedef grub_uint16_t grub_minix_uintn_t; #endif #define GRUB_MINIX_INODE_BLKSZ(data) sizeof (grub_minix_uintn_t) +#ifdef MODE_MINIX3 +typedef grub_uint32_t grub_minix_ino_t; +#define grub_minix_le_to_cpu_ino grub_le_to_cpu32 +#else +typedef grub_uint16_t grub_minix_ino_t; +#define grub_minix_le_to_cpu_ino grub_le_to_cpu16 +#endif #define GRUB_MINIX_INODE_SIZE(data) (grub_minix_le_to_cpu_n (data->inode.size)) #define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode)) @@ -62,9 +72,28 @@ typedef grub_uint16_t grub_minix_uintn_t; #define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \ + grub_le_to_cpu16 (sblock->log2_zone_size)) -#define GRUB_MINIX_ZONESZ (GRUB_MINIX_BSIZE \ +#define GRUB_MINIX_ZONESZ (data->block_size \ << grub_le_to_cpu16 (sblock->log2_zone_size)) +#ifdef MODE_MINIX3 +struct grub_minix_sblock +{ + grub_uint32_t inode_cnt; + grub_uint16_t zone_cnt; + grub_uint16_t inode_bmap_size; + grub_uint16_t zone_bmap_size; + grub_uint16_t first_data_zone; + grub_uint16_t log2_zone_size; + grub_uint16_t pad; + grub_uint32_t max_file_size; + grub_uint32_t zones; + grub_uint16_t magic; + + grub_uint16_t pad2; + grub_uint16_t block_size; + grub_uint8_t disk_version; +}; +#else struct grub_minix_sblock { grub_uint16_t inode_cnt; @@ -76,8 +105,28 @@ struct grub_minix_sblock grub_uint32_t max_file_size; grub_uint16_t magic; }; +#endif -#ifndef MODE_MINIX2 +#if defined(MODE_MINIX3) + +struct grub_minix_inode +{ + grub_uint16_t mode; + grub_uint16_t nlinks; + grub_uint16_t uid; + grub_uint8_t gid; + grub_uint8_t pad; + grub_uint32_t size; + grub_uint32_t atime; + grub_uint32_t mtime; + grub_uint32_t ctime; + grub_uint32_t dir_zones[7]; + grub_uint32_t indir_zone; + grub_uint32_t double_indir_zone; + grub_uint32_t unused; +}; + +#elif defined(MODE_MINIX2) struct grub_minix_inode { grub_uint16_t mode; @@ -121,6 +170,7 @@ struct grub_minix_data int linknest; grub_disk_t disk; int filename_size; + grub_size_t block_size; }; static grub_dl_t my_mod; @@ -141,18 +191,22 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) { grub_minix_uintn_t indirn; grub_disk_read (data->disk, +#ifdef MODE_MINIX3 + zone * (data->block_size / GRUB_DISK_SECTOR_SIZE), +#else zone << GRUB_MINIX_LOG2_ZONESZ, +#endif sizeof (grub_minix_uintn_t) * num, sizeof (grub_minix_uintn_t), (char *) &indirn); return grub_minix_le_to_cpu_n (indirn); } /* Direct block. */ - if (blk < 7) + if (blk < GRUB_MINIX_INODE_DIR_BLOCKS) return GRUB_MINIX_INODE_DIR_ZONES (data, blk); /* Indirect block. */ - blk -= 7; + blk -= GRUB_MINIX_INODE_DIR_BLOCKS; if (blk < GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data)) { indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk); @@ -185,25 +239,27 @@ static grub_ssize_t grub_minix_read_file (struct grub_minix_data *data, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, grub_disk_addr_t len, char *buf) + grub_off_t pos, grub_disk_addr_t len, char *buf) { struct grub_minix_sblock *sblock = &data->sblock; - int i; - int blockcnt; + grub_disk_addr_t i; + grub_disk_addr_t blockcnt; + grub_uint64_t posblock; + grub_uint32_t blockoff; /* Adjust len so it we can't read past the end of the file. */ if (len + pos > GRUB_MINIX_INODE_SIZE (data)) len = GRUB_MINIX_INODE_SIZE (data) - pos; - blockcnt = (len + pos + GRUB_MINIX_BSIZE - 1) / GRUB_MINIX_BSIZE; + blockcnt = grub_divmod64 ((len + pos + data->block_size - 1), + data->block_size, 0); + posblock = grub_divmod64 (pos, data->block_size, &blockoff); - for (i = pos / GRUB_MINIX_BSIZE; i < blockcnt; i++) + for (i = posblock; i < blockcnt; i++) { - int blknr; - int blockoff = pos % GRUB_MINIX_BSIZE; - int blockend = GRUB_MINIX_BSIZE; - - int skipfirst = 0; + grub_disk_addr_t blknr; + grub_uint32_t blockend = data->block_size; + grub_off_t skipfirst = 0; blknr = grub_minix_get_file_block (data, i); if (grub_errno) @@ -212,28 +268,32 @@ grub_minix_read_file (struct grub_minix_data *data, /* Last block. */ if (i == blockcnt - 1) { - blockend = (len + pos) % GRUB_MINIX_BSIZE; + grub_divmod64 (len + pos, data->block_size, &blockend); if (!blockend) - blockend = GRUB_MINIX_BSIZE; + blockend = data->block_size; } /* First block. */ - if (i == (pos / (int) GRUB_MINIX_BSIZE)) + if (i == posblock) { skipfirst = blockoff; blockend -= skipfirst; } data->disk->read_hook = read_hook; - grub_disk_read (data->disk, blknr << GRUB_MINIX_LOG2_ZONESZ, + grub_disk_read (data->disk, +#ifdef MODE_MINIX3 + blknr * (sblock->block_size / GRUB_DISK_SECTOR_SIZE), +#else + blknr << GRUB_MINIX_LOG2_ZONESZ, +#endif skipfirst, blockend, buf); - data->disk->read_hook = 0; if (grub_errno) return -1; - buf += GRUB_MINIX_BSIZE - skipfirst; + buf += data->block_size - skipfirst; } return len; @@ -248,16 +308,18 @@ grub_minix_read_inode (struct grub_minix_data *data, int ino) struct grub_minix_sblock *sblock = &data->sblock; /* Block in which the inode is stored. */ - int block; + grub_disk_addr_t block; data->ino = ino; /* The first inode in minix is inode 1. */ ino--; - - block = ((2 + grub_le_to_cpu16 (sblock->inode_bmap_size) - + grub_le_to_cpu16 (sblock->zone_bmap_size)) - << GRUB_MINIX_LOG2_BSIZE); - + block = (2 + grub_le_to_cpu16 (sblock->inode_bmap_size) + + grub_le_to_cpu16 (sblock->zone_bmap_size)); +#ifndef MODE_MINIX3 + block <<= GRUB_MINIX_LOG2_BSIZE; +#else + block *= sblock->block_size / GRUB_DISK_SECTOR_SIZE; +#endif block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode)); int offs = (ino % (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode)) @@ -333,7 +395,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path) do { - grub_uint16_t ino; + grub_minix_ino_t ino; char filename[data->filename_size + 1]; if (grub_strlen (name) == 0) @@ -353,7 +415,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path) if (!grub_strcmp (name, filename)) { dirino = data->ino; - grub_minix_read_inode (data, grub_le_to_cpu16 (ino)); + grub_minix_read_inode (data, grub_minix_le_to_cpu_ino (ino)); /* Follow the symlink. */ if ((GRUB_MINIX_INODE_MODE (data) @@ -409,20 +471,35 @@ grub_minix_mount (grub_disk_t disk) goto fail; if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC) + { +#if !defined(MODE_MINIX3) data->filename_size = 14; +#else + data->filename_size = 60; +#endif + } +#if !defined(MODE_MINIX3) else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC_30) data->filename_size = 30; +#endif else goto fail; data->disk = disk; data->linknest = 0; +#ifdef MODE_MINIX3 + data->block_size = grub_le_to_cpu16 (data->sblock.block_size); +#else + data->block_size = 1024U; +#endif return data; fail: grub_free (data); -#ifdef MODE_MINIX2 +#if defined(MODE_MINIX3) + grub_error (GRUB_ERR_BAD_FS, "not a minix3 filesystem"); +#elif defined(MODE_MINIX2) grub_error (GRUB_ERR_BAD_FS, "not a minix2 filesystem"); #else grub_error (GRUB_ERR_BAD_FS, "not a minix filesystem"); @@ -458,7 +535,7 @@ grub_minix_dir (grub_device_t device, const char *path, while (pos < GRUB_MINIX_INODE_SIZE (data)) { - grub_uint16_t ino; + grub_minix_ino_t ino; char filename[data->filename_size + 1]; int dirino = data->ino; struct grub_dirhook_info info; @@ -474,10 +551,13 @@ grub_minix_dir (grub_device_t device, const char *path, (char *) filename) < 0) return grub_errno; filename[data->filename_size] = '\0'; + if (!ino) + { + pos += sizeof (ino) + data->filename_size; + continue; + } - /* The filetype is not stored in the dirent. Read the inode to - find out the filetype. This *REALLY* sucks. */ - grub_minix_read_inode (data, grub_le_to_cpu16 (ino)); + grub_minix_read_inode (data, grub_minix_le_to_cpu_ino (ino)); info.dir = ((GRUB_MINIX_INODE_MODE (data) & GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR); if (hook (filename, &info) ? 1 : 0) @@ -556,7 +636,9 @@ grub_minix_close (grub_file_t file) static struct grub_fs grub_minix_fs = { -#ifdef MODE_MINIX2 +#if defined(MODE_MINIX3) + .name = "minix3", +#elif defined(MODE_MINIX2) .name = "minix2", #else .name = "minix", @@ -568,7 +650,9 @@ static struct grub_fs grub_minix_fs = .next = 0 }; -#ifdef MODE_MINIX2 +#if defined(MODE_MINIX3) +GRUB_MOD_INIT(minix3) +#elif defined(MODE_MINIX2) GRUB_MOD_INIT(minix2) #else GRUB_MOD_INIT(minix) @@ -578,7 +662,9 @@ GRUB_MOD_INIT(minix) my_mod = mod; } -#ifdef MODE_MINIX2 +#if defined(MODE_MINIX3) +GRUB_MOD_FINI(minix3) +#elif defined(MODE_MINIX2) GRUB_MOD_FINI(minix2) #else GRUB_MOD_FINI(minix) diff --git a/grub-core/fs/minix3.c b/grub-core/fs/minix3.c new file mode 100644 index 000000000..58a21d2b5 --- /dev/null +++ b/grub-core/fs/minix3.c @@ -0,0 +1,2 @@ +#define MODE_MINIX3 1 +#include "minix.c" From 58ee1408a8be7d386027882cb07e14f76a2b6cfb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 11 Apr 2011 08:53:28 +0200 Subject: [PATCH 179/406] Fix an error in minix inode declaration --- grub-core/fs/minix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index c93dfe085..877f71921 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -126,7 +126,7 @@ struct grub_minix_inode grub_uint32_t unused; }; -#elif defined(MODE_MINIX2) +#elif !defined(MODE_MINIX2) struct grub_minix_inode { grub_uint16_t mode; From 65f01628e19d04be6cad0242d3056dbb656a54b2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 11 Apr 2011 08:56:42 +0200 Subject: [PATCH 180/406] unify minix3 and minix2 inode declarations --- grub-core/fs/minix.c | 49 +++++++++++++------------------------------- 1 file changed, 14 insertions(+), 35 deletions(-) diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 877f71921..a01ee77ca 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -107,41 +107,7 @@ struct grub_minix_sblock }; #endif -#if defined(MODE_MINIX3) - -struct grub_minix_inode -{ - grub_uint16_t mode; - grub_uint16_t nlinks; - grub_uint16_t uid; - grub_uint8_t gid; - grub_uint8_t pad; - grub_uint32_t size; - grub_uint32_t atime; - grub_uint32_t mtime; - grub_uint32_t ctime; - grub_uint32_t dir_zones[7]; - grub_uint32_t indir_zone; - grub_uint32_t double_indir_zone; - grub_uint32_t unused; -}; - -#elif !defined(MODE_MINIX2) -struct grub_minix_inode -{ - grub_uint16_t mode; - grub_uint16_t uid; - grub_uint16_t size; - grub_uint32_t ctime; - grub_uint8_t gid; - grub_uint8_t nlinks; - grub_uint16_t dir_zones[7]; - grub_uint16_t indir_zone; - grub_uint16_t double_indir_zone; -}; - -#else - +#if defined(MODE_MINIX3) || defined(MODE_MINIX2) struct grub_minix_inode { grub_uint16_t mode; @@ -158,6 +124,19 @@ struct grub_minix_inode grub_uint32_t unused; }; +#else +struct grub_minix_inode +{ + grub_uint16_t mode; + grub_uint16_t uid; + grub_uint16_t size; + grub_uint32_t ctime; + grub_uint8_t gid; + grub_uint8_t nlinks; + grub_uint16_t dir_zones[7]; + grub_uint16_t indir_zone; + grub_uint16_t double_indir_zone; +}; #endif From 8fc88523dd88ed4e7852bbab28faa8225cde7f21 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 11 Apr 2011 14:09:02 +0200 Subject: [PATCH 181/406] Add minix3 to util filesystems --- Makefile.util.def | 1 + grub-core/fs/minix.c | 36 +++++++++++++++--------------------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index 303baea3f..678e581e6 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -60,6 +60,7 @@ library = { common = grub-core/fs/jfs.c; common = grub-core/fs/minix.c; common = grub-core/fs/minix2.c; + common = grub-core/fs/minix3.c; common = grub-core/fs/nilfs2.c; common = grub-core/fs/ntfs.c; common = grub-core/fs/ntfscomp.c; diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index a01ee77ca..298eef394 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -70,10 +70,19 @@ typedef grub_uint16_t grub_minix_ino_t; #define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_le_to_cpu_n \ (data->inode.double_indir_zone)) +#ifndef MODE_MINIX3 #define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \ - + grub_le_to_cpu16 (sblock->log2_zone_size)) + + grub_le_to_cpu16 (data->sblock.log2_zone_size)) +#endif #define GRUB_MINIX_ZONESZ (data->block_size \ - << grub_le_to_cpu16 (sblock->log2_zone_size)) + << grub_le_to_cpu16 (data->sblock.log2_zone_size)) + +#ifdef MODE_MINIX3 +#define GRUB_MINIX_ZONE2SECT(zone) ((zone) * (data->block_size / GRUB_DISK_SECTOR_SIZE)) +#else +#define GRUB_MINIX_ZONE2SECT(zone) ((zone) << GRUB_MINIX_LOG2_ZONESZ) +#endif + #ifdef MODE_MINIX3 struct grub_minix_sblock @@ -160,7 +169,6 @@ static grub_err_t grub_minix_find_file (struct grub_minix_data *data, static int grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) { - struct grub_minix_sblock *sblock = &data->sblock; int indir; auto int grub_get_indir (int, int); @@ -170,11 +178,7 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) { grub_minix_uintn_t indirn; grub_disk_read (data->disk, -#ifdef MODE_MINIX3 - zone * (data->block_size / GRUB_DISK_SECTOR_SIZE), -#else - zone << GRUB_MINIX_LOG2_ZONESZ, -#endif + GRUB_MINIX_ZONE2SECT(zone), sizeof (grub_minix_uintn_t) * num, sizeof (grub_minix_uintn_t), (char *) &indirn); return grub_minix_le_to_cpu_n (indirn); @@ -220,7 +224,6 @@ grub_minix_read_file (struct grub_minix_data *data, unsigned offset, unsigned length), grub_off_t pos, grub_disk_addr_t len, char *buf) { - struct grub_minix_sblock *sblock = &data->sblock; grub_disk_addr_t i; grub_disk_addr_t blockcnt; grub_uint64_t posblock; @@ -262,11 +265,7 @@ grub_minix_read_file (struct grub_minix_data *data, data->disk->read_hook = read_hook; grub_disk_read (data->disk, -#ifdef MODE_MINIX3 - blknr * (sblock->block_size / GRUB_DISK_SECTOR_SIZE), -#else - blknr << GRUB_MINIX_LOG2_ZONESZ, -#endif + GRUB_MINIX_ZONE2SECT(blknr), skipfirst, blockend, buf); data->disk->read_hook = 0; if (grub_errno) @@ -292,13 +291,8 @@ grub_minix_read_inode (struct grub_minix_data *data, int ino) /* The first inode in minix is inode 1. */ ino--; - block = (2 + grub_le_to_cpu16 (sblock->inode_bmap_size) - + grub_le_to_cpu16 (sblock->zone_bmap_size)); -#ifndef MODE_MINIX3 - block <<= GRUB_MINIX_LOG2_BSIZE; -#else - block *= sblock->block_size / GRUB_DISK_SECTOR_SIZE; -#endif + block = GRUB_MINIX_ZONE2SECT (2 + grub_le_to_cpu16 (sblock->inode_bmap_size) + + grub_le_to_cpu16 (sblock->zone_bmap_size)); block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode)); int offs = (ino % (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode)) From bd671cc4fe27784df6bacb57d83f691a84e3f5f0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 15 Apr 2011 18:15:06 +0200 Subject: [PATCH 182/406] Use Block IO on EFI --- grub-core/disk/efi/efidisk.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 1bf764f10..35602513e 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -33,12 +33,10 @@ struct grub_efidisk_data grub_efi_device_path_t *device_path; grub_efi_device_path_t *last_device_path; grub_efi_block_io_t *block_io; - grub_efi_disk_io_t *disk_io; struct grub_efidisk_data *next; }; -/* GUIDs. */ -static grub_efi_guid_t disk_io_guid = GRUB_EFI_DISK_IO_GUID; +/* GUID. */ static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID; static struct grub_efidisk_data *fd_devices; @@ -143,7 +141,7 @@ make_devices (void) struct grub_efidisk_data *devices = 0; /* Find handles which support the disk io interface. */ - handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &disk_io_guid, + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &block_io_guid, 0, &num_handles); if (! handles) return 0; @@ -155,7 +153,6 @@ make_devices (void) grub_efi_device_path_t *ldp; struct grub_efidisk_data *d; grub_efi_block_io_t *bio; - grub_efi_disk_io_t *dio; dp = grub_efi_get_device_path (*handle); if (! dp) @@ -168,9 +165,7 @@ make_devices (void) bio = grub_efi_open_protocol (*handle, &block_io_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); - dio = grub_efi_open_protocol (*handle, &disk_io_guid, - GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); - if (! bio || ! dio) + if (! bio) /* This should not happen... Why? */ continue; @@ -186,7 +181,6 @@ make_devices (void) d->device_path = dp; d->last_device_path = ldp; d->block_io = bio; - d->disk_io = dio; d->next = devices; devices = d; } @@ -563,22 +557,20 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector, { /* For now, use the disk io interface rather than the block io's. */ struct grub_efidisk_data *d; - grub_efi_disk_io_t *dio; grub_efi_block_io_t *bio; grub_efi_status_t status; d = disk->data; - dio = d->disk_io; bio = d->block_io; grub_dprintf ("efidisk", "reading 0x%lx sectors at the sector 0x%llx from %s\n", (unsigned long) size, (unsigned long long) sector, disk->name); - status = efi_call_5 (dio->read, dio, bio->media->media_id, - (grub_efi_uint64_t) sector << disk->log_sector_size, - (grub_efi_uintn_t) size << disk->log_sector_size, - buf); + status = efi_call_5 (bio->read_blocks, bio, bio->media->media_id, + (grub_efi_uint64_t) sector, + (grub_efi_uintn_t) size << disk->log_sector_size, + buf); if (status != GRUB_EFI_SUCCESS) return grub_error (GRUB_ERR_READ_ERROR, "efidisk read error"); @@ -591,20 +583,18 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector, { /* For now, use the disk io interface rather than the block io's. */ struct grub_efidisk_data *d; - grub_efi_disk_io_t *dio; grub_efi_block_io_t *bio; grub_efi_status_t status; d = disk->data; - dio = d->disk_io; bio = d->block_io; grub_dprintf ("efidisk", "writing 0x%lx sectors at the sector 0x%llx to %s\n", (unsigned long) size, (unsigned long long) sector, disk->name); - status = efi_call_5 (dio->write, dio, bio->media->media_id, - (grub_efi_uint64_t) sector << disk->log_sector_size, + status = efi_call_5 (bio->write_blocks, bio, bio->media->media_id, + (grub_efi_uint64_t) sector, (grub_efi_uintn_t) size << disk->log_sector_size, (void *) buf); if (status != GRUB_EFI_SUCCESS) From d8a2bcf564728cc38b138fed18cd89b097493e75 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 15 Apr 2011 21:42:29 +0200 Subject: [PATCH 183/406] contiguous read --- grub-core/kern/disk.c | 296 +++++++++++++++++++++++++----------------- 1 file changed, 178 insertions(+), 118 deletions(-) diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index af56527ad..5439a02f6 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -398,13 +398,93 @@ transform_sector (grub_disk_t disk, grub_disk_addr_t sector) return sector >> (disk->log_sector_size - GRUB_DISK_SECTOR_BITS); } +/* Small read (less than cache size and not pass across cache unit boundaries). + sector is already adjusted and is divisible by cache unit size. + */ +static grub_err_t +grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector, + grub_off_t offset, grub_size_t size, void *buf) +{ + char *data; + char *tmp_buf; + + /* Fetch the cache. */ + data = grub_disk_cache_fetch (disk->dev->id, disk->id, sector); + if (data) + { + /* Just copy it! */ + grub_memcpy (buf, data + offset, size); + grub_disk_cache_unlock (disk->dev->id, disk->id, sector); + return GRUB_ERR_NONE; + } + + /* Allocate a temporary buffer. */ + tmp_buf = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS); + if (! tmp_buf) + return grub_errno; + + /* Otherwise read data from the disk actually. */ + if (disk->total_sectors == GRUB_DISK_SIZE_UNKNOWN + || sector + GRUB_DISK_CACHE_SIZE + < (disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS))) + { + grub_err_t err; + err = (disk->dev->read) (disk, transform_sector (disk, sector), + 1 << (GRUB_DISK_CACHE_BITS + + GRUB_DISK_SECTOR_BITS + - disk->log_sector_size), tmp_buf); + if (!err) + { + /* Copy it and store it in the disk cache. */ + grub_memcpy (buf, tmp_buf + offset, size); + grub_disk_cache_store (disk->dev->id, disk->id, + sector, tmp_buf); + grub_free (tmp_buf); + return GRUB_ERR_NONE; + } + } + + grub_errno = GRUB_ERR_NONE; + + { + /* Uggh... Failed. Instead, just read necessary data. */ + unsigned num; + grub_disk_addr_t aligned_sector; + + sector += (offset >> GRUB_DISK_SECTOR_BITS); + offset &= ((1 << GRUB_DISK_SECTOR_BITS) - 1); + aligned_sector = (sector & ~((1 << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) + - 1)); + offset += ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS); + num = ((size + offset + (1 << (disk->log_sector_size)) + - 1) >> (disk->log_sector_size)); + + tmp_buf = grub_malloc (num << disk->log_sector_size); + if (!tmp_buf) + return grub_errno; + + if ((disk->dev->read) (disk, transform_sector (disk, aligned_sector), + num, tmp_buf)) + { + grub_error_push (); + grub_dprintf ("disk", "%s read failed\n", disk->name); + grub_error_pop (); + return grub_errno; + } + grub_memcpy (buf, tmp_buf + offset, size); + return GRUB_ERR_NONE; + } +} + /* Read data from the disk. */ grub_err_t grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_off_t offset, grub_size_t size, void *buf) { - char *tmp_buf; - unsigned real_offset; + grub_off_t real_offset; + grub_disk_addr_t real_sector; + grub_size_t real_size; /* First of all, check if the region is within the disk. */ if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE) @@ -416,138 +496,118 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, return grub_errno; } + real_sector = sector; real_offset = offset; + real_size = size; - /* Allocate a temporary buffer. */ - tmp_buf = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS); - if (! tmp_buf) - return grub_errno; - - /* Until SIZE is zero... */ - while (size) + /* First read until first cache boundary. */ + if (offset || (sector & (GRUB_DISK_CACHE_SIZE - 1))) { - char *data; grub_disk_addr_t start_sector; - grub_size_t len; grub_size_t pos; + grub_err_t err; + grub_size_t len; - /* For reading bulk data. */ start_sector = sector & ~(GRUB_DISK_CACHE_SIZE - 1); pos = (sector - start_sector) << GRUB_DISK_SECTOR_BITS; len = ((GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS) - - pos - real_offset); + - pos - offset); if (len > size) len = size; - - /* Fetch the cache. */ - data = grub_disk_cache_fetch (disk->dev->id, disk->id, start_sector); - if (data) - { - /* Just copy it! */ - grub_memcpy (buf, data + pos + real_offset, len); - grub_disk_cache_unlock (disk->dev->id, disk->id, start_sector); - } - else - { - /* Otherwise read data from the disk actually. */ - if ((disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN - && start_sector + GRUB_DISK_CACHE_SIZE - > (disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS))) - || (disk->dev->read) (disk, transform_sector (disk, start_sector), - 1 << (GRUB_DISK_CACHE_BITS - + GRUB_DISK_SECTOR_BITS - - disk->log_sector_size), tmp_buf) - != GRUB_ERR_NONE) - { - /* Uggh... Failed. Instead, just read necessary data. */ - unsigned num; - char *p; - grub_disk_addr_t aligned_sector; - - grub_errno = GRUB_ERR_NONE; - - aligned_sector = (sector & ~((1 << (disk->log_sector_size - - GRUB_DISK_SECTOR_BITS)) - - 1)); - real_offset += ((sector - aligned_sector) - << GRUB_DISK_SECTOR_BITS); - num = ((size + real_offset + (1 << (disk->log_sector_size)) - - 1) >> (disk->log_sector_size)); - - p = grub_realloc (tmp_buf, num << disk->log_sector_size); - if (!p) - goto finish; - - tmp_buf = p; - - if ((disk->dev->read) (disk, transform_sector (disk, - aligned_sector), - num, tmp_buf)) - { - grub_error_push (); - grub_dprintf ("disk", "%s read failed\n", disk->name); - grub_error_pop (); - goto finish; - } - - grub_memcpy (buf, tmp_buf + real_offset, size); - - /* Call the read hook, if any. */ - if (disk->read_hook) - while (size) - { - grub_size_t to_read = (size > GRUB_DISK_SECTOR_SIZE) ? GRUB_DISK_SECTOR_SIZE : size; - (disk->read_hook) (sector, real_offset, - to_read); - if (grub_errno != GRUB_ERR_NONE) - goto finish; - - sector++; - size -= to_read - real_offset; - real_offset = 0; - } - - /* This must be the end. */ - goto finish; - } - - /* Copy it and store it in the disk cache. */ - grub_memcpy (buf, tmp_buf + pos + real_offset, len); - grub_disk_cache_store (disk->dev->id, disk->id, - start_sector, tmp_buf); - } - - /* Call the read hook, if any. */ - if (disk->read_hook) - { - grub_disk_addr_t s = sector; - grub_size_t l = len; - - while (l) - { - (disk->read_hook) (s, real_offset, - ((l > GRUB_DISK_SECTOR_SIZE) - ? GRUB_DISK_SECTOR_SIZE - : l)); - - if (l < GRUB_DISK_SECTOR_SIZE - real_offset) - break; - - s++; - l -= GRUB_DISK_SECTOR_SIZE - real_offset; - real_offset = 0; - } - } - - sector = start_sector + GRUB_DISK_CACHE_SIZE; + err = grub_disk_read_small (disk, start_sector, + offset + pos, len, buf); + if (err) + return err; buf = (char *) buf + len; size -= len; - real_offset = 0; + offset += len; + sector += (offset >> GRUB_DISK_SECTOR_BITS); + offset &= ((1 << GRUB_DISK_SECTOR_BITS) - 1); } - finish: + /* Until SIZE is zero... */ + while (size >= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS)) + { + char *data = NULL; + grub_disk_addr_t agglomerate; + grub_err_t err; - grub_free (tmp_buf); + /* agglomerate read until we find a first cached entry. */ + for (agglomerate = 0; agglomerate + < (size >> (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS)); + agglomerate++) + { + data = grub_disk_cache_fetch (disk->dev->id, disk->id, + sector + (agglomerate + << GRUB_DISK_CACHE_BITS)); + if (data) + break; + } + + if (agglomerate) + { + grub_disk_addr_t i; + + err = (disk->dev->read) (disk, transform_sector (disk, sector), + agglomerate << (GRUB_DISK_CACHE_BITS + + GRUB_DISK_SECTOR_BITS + - disk->log_sector_size), + buf); + if (err) + return err; + + for (i = 0; i < agglomerate; i ++) + grub_disk_cache_store (disk->dev->id, disk->id, + sector + (i << GRUB_DISK_CACHE_BITS), + (char *) buf + + (i << (GRUB_DISK_CACHE_BITS + + GRUB_DISK_SECTOR_BITS))); + + sector += agglomerate << GRUB_DISK_CACHE_BITS; + size -= agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS); + buf = (char *) buf + + (agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS)); + } + + if (data) + { + grub_memcpy (buf, data, GRUB_DISK_CACHE_SIZE); + sector += GRUB_DISK_CACHE_SIZE; + buf = (char *) buf + (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); + size -= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); + grub_disk_cache_unlock (disk->dev->id, disk->id, + sector + (agglomerate + << GRUB_DISK_CACHE_BITS)); + } + } + + /* And now read the last part. */ + if (size) + { + grub_err_t err; + err = grub_disk_read_small (disk, sector, 0, size, buf); + if (err) + return err; + } + + /* Call the read hook, if any. */ + if (disk->read_hook) + { + grub_disk_addr_t s = real_sector; + grub_size_t l = real_size; + grub_off_t o = real_offset; + + while (l) + { + (disk->read_hook) (s, o, + ((l > GRUB_DISK_SECTOR_SIZE) + ? GRUB_DISK_SECTOR_SIZE + : l)); + s++; + l -= GRUB_DISK_SECTOR_SIZE - o; + o = 0; + } + } return grub_errno; } From b13f79a427b6ae6c1405c48b8cf57a1e99de16f9 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 21 Apr 2011 00:07:22 +0100 Subject: [PATCH 184/406] Fix stack pointer handling in 16-bit relocator. * grub-core/lib/i386/relocator16.S (grub_relocator16_start): Move grub_relocator16_sp to %esp rather than %ss, and zero-extend it. Fixes Ubuntu bug #683904. --- ChangeLog | 8 ++++++++ grub-core/lib/i386/relocator16.S | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 083d22ec5..98d3b0ea8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-04-21 Colin Watson + + Fix stack pointer handling in 16-bit relocator. + + * grub-core/lib/i386/relocator16.S (grub_relocator16_start): Move + grub_relocator16_sp to %esp rather than %ss, and zero-extend it. + Fixes Ubuntu bug #683904. + 2011-04-20 Vladimir Serbinenko * configure.ac: Bump version to 1.99~rc2. diff --git a/grub-core/lib/i386/relocator16.S b/grub-core/lib/i386/relocator16.S index c3768f4eb..982415de4 100644 --- a/grub-core/lib/i386/relocator16.S +++ b/grub-core/lib/i386/relocator16.S @@ -130,7 +130,7 @@ VARIABLE(grub_relocator16_ss) .byte 0xb8 VARIABLE(grub_relocator16_sp) .word 0 - movw %ax, %ss + movzwl %ax, %esp /* movw imm32, %edx. */ .byte 0x66, 0xba From 92051871b736cde73d8755b3e29781a677ee362c Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 21 Apr 2011 10:26:29 +0100 Subject: [PATCH 185/406] * grub-core/kern/emu/getroot.c (grub_find_root_device_from_mountinfo): Remove non-virtual-device test that was incorrectly reintroduced in r3214. Reported by: Ian Dall. Fixes Savannah bug #33133. --- ChangeLog | 7 +++++++ grub-core/kern/emu/getroot.c | 3 --- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 98d3b0ea8..1142cf81d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-04-21 Colin Watson + + * grub-core/kern/emu/getroot.c + (grub_find_root_device_from_mountinfo): Remove non-virtual-device + test that was incorrectly reintroduced in r3214. + Reported by: Ian Dall. Fixes Savannah bug #33133. + 2011-04-21 Colin Watson Fix stack pointer handling in 16-bit relocator. diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index f836a6625..a274f3c06 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -216,9 +216,6 @@ grub_find_root_device_from_mountinfo (const char *dir, char **relroot) /* Now scan visible mounts for the ones we're interested in. */ for (i = entry_len - 1; i >= 0; i--) { - if (entries[i].major != 0) - continue; /* not a virtual device */ - if (!*entries[i].device) continue; From cff5e5e58d93bdd028aba1a220bb59a7962bba52 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 21 Apr 2011 10:37:45 +0100 Subject: [PATCH 186/406] grub-core/fs/squash4.c: Add missing GRUB_MOD_LICENSE. --- grub-core/fs/squash4.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 8e8388628..4f1265582 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* object format Pointed by superblock RAW Fixed offset (0) From c85140b3b79fb91fb7d174042139adc9b5028a23 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 21 Apr 2011 15:17:48 +0100 Subject: [PATCH 187/406] Add "SEE ALSO" sections to most man pages. Fixes Debian bug #551428. * docs/man/grub-editenv.h2m (SEE ALSO): New section. * docs/man/grub-emu.h2m (SEE ALSO): Likewise. * docs/man/grub-fstest.h2m (SEE ALSO): Likewise. * docs/man/grub-install.h2m (SEE ALSO): Likewise. * docs/man/grub-macho2img.h2m (SEE ALSO): Likewise. * docs/man/grub-menulst2cfg.h2m (SEE ALSO): Likewise. * docs/man/grub-mkconfig.h2m (SEE ALSO): Likewise. * docs/man/grub-mkdevicemap.h2m (SEE ALSO): Likewise. * docs/man/grub-mkfont.h2m (SEE ALSO): Likewise. * docs/man/grub-mkimage.h2m (SEE ALSO): Likewise. * docs/man/grub-mklayout.h2m (SEE ALSO): Likewise. * docs/man/grub-mknetdir.h2m (SEE ALSO): Likewise. * docs/man/grub-mkpasswd-pbkdf2.h2m (SEE ALSO): Likewise. * docs/man/grub-mkrelpath.h2m (SEE ALSO): Likewise. * docs/man/grub-mkrescue.h2m (SEE ALSO): Likewise. * docs/man/grub-ofpathname.h2m (SEE ALSO): Likewise. * docs/man/grub-pe2elf.h2m (SEE ALSO): Likewise. * docs/man/grub-probe.h2m (SEE ALSO): Likewise. * docs/man/grub-reboot.h2m (SEE ALSO): Likewise. * docs/man/grub-script-check.h2m (SEE ALSO): Likewise. * docs/man/grub-set-default.h2m (SEE ALSO): Likewise. * docs/man/grub-setup.h2m (SEE ALSO): Likewise. --- ChangeLog | 28 ++++++++++++++++++++++++++++ docs/man/grub-editenv.h2m | 3 +++ docs/man/grub-emu.h2m | 4 ++++ docs/man/grub-fstest.h2m | 2 ++ docs/man/grub-install.h2m | 5 +++++ docs/man/grub-macho2img.h2m | 2 ++ docs/man/grub-menulst2cfg.h2m | 3 ++- docs/man/grub-mkconfig.h2m | 2 ++ docs/man/grub-mkdevicemap.h2m | 2 ++ docs/man/grub-mkfont.h2m | 2 ++ docs/man/grub-mkimage.h2m | 5 +++++ docs/man/grub-mklayout.h2m | 2 ++ docs/man/grub-mknetdir.h2m | 2 ++ docs/man/grub-mkpasswd-pbkdf2.h2m | 2 ++ docs/man/grub-mkrelpath.h2m | 2 ++ docs/man/grub-mkrescue.h2m | 2 ++ docs/man/grub-ofpathname.h2m | 2 ++ docs/man/grub-pe2elf.h2m | 2 ++ docs/man/grub-probe.h2m | 2 ++ docs/man/grub-reboot.h2m | 3 +++ docs/man/grub-script-check.h2m | 2 ++ docs/man/grub-set-default.h2m | 3 +++ docs/man/grub-setup.h2m | 4 ++++ 23 files changed, 85 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1142cf81d..3b98caba3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2011-04-21 Colin Watson + + Add "SEE ALSO" sections to most man pages. Fixes Debian bug + #551428. + + * docs/man/grub-editenv.h2m (SEE ALSO): New section. + * docs/man/grub-emu.h2m (SEE ALSO): Likewise. + * docs/man/grub-fstest.h2m (SEE ALSO): Likewise. + * docs/man/grub-install.h2m (SEE ALSO): Likewise. + * docs/man/grub-macho2img.h2m (SEE ALSO): Likewise. + * docs/man/grub-menulst2cfg.h2m (SEE ALSO): Likewise. + * docs/man/grub-mkconfig.h2m (SEE ALSO): Likewise. + * docs/man/grub-mkdevicemap.h2m (SEE ALSO): Likewise. + * docs/man/grub-mkfont.h2m (SEE ALSO): Likewise. + * docs/man/grub-mkimage.h2m (SEE ALSO): Likewise. + * docs/man/grub-mklayout.h2m (SEE ALSO): Likewise. + * docs/man/grub-mknetdir.h2m (SEE ALSO): Likewise. + * docs/man/grub-mkpasswd-pbkdf2.h2m (SEE ALSO): Likewise. + * docs/man/grub-mkrelpath.h2m (SEE ALSO): Likewise. + * docs/man/grub-mkrescue.h2m (SEE ALSO): Likewise. + * docs/man/grub-ofpathname.h2m (SEE ALSO): Likewise. + * docs/man/grub-pe2elf.h2m (SEE ALSO): Likewise. + * docs/man/grub-probe.h2m (SEE ALSO): Likewise. + * docs/man/grub-reboot.h2m (SEE ALSO): Likewise. + * docs/man/grub-script-check.h2m (SEE ALSO): Likewise. + * docs/man/grub-set-default.h2m (SEE ALSO): Likewise. + * docs/man/grub-setup.h2m (SEE ALSO): Likewise. + 2011-04-21 Colin Watson * grub-core/kern/emu/getroot.c diff --git a/docs/man/grub-editenv.h2m b/docs/man/grub-editenv.h2m index efbd79070..3859d3d4c 100644 --- a/docs/man/grub-editenv.h2m +++ b/docs/man/grub-editenv.h2m @@ -1,2 +1,5 @@ [NAME] grub-editenv \- edit GRUB environment block +[SEE ALSO] +.BR grub-reboot (8), +.BR grub-set-default (8) diff --git a/docs/man/grub-emu.h2m b/docs/man/grub-emu.h2m index 09a1f88c1..ef1c00065 100644 --- a/docs/man/grub-emu.h2m +++ b/docs/man/grub-emu.h2m @@ -1,2 +1,6 @@ [NAME] grub-emu \- GRUB emulator +[SEE ALSO] +If you are trying to install GRUB, then you should use +.BR grub-install (8) +rather than this program. diff --git a/docs/man/grub-fstest.h2m b/docs/man/grub-fstest.h2m index be39429b5..9676b159a 100644 --- a/docs/man/grub-fstest.h2m +++ b/docs/man/grub-fstest.h2m @@ -1,2 +1,4 @@ [NAME] grub-fstest \- debug tool for GRUB filesystem drivers +[SEE ALSO] +.BR grub-probe (8) diff --git a/docs/man/grub-install.h2m b/docs/man/grub-install.h2m index 65252155c..2de371a3f 100644 --- a/docs/man/grub-install.h2m +++ b/docs/man/grub-install.h2m @@ -1,2 +1,7 @@ [NAME] grub-install \- install GRUB to a device +[SEE ALSO] +.BR grub-mkconfig (8), +.BR grub-mkimage (1), +.BR grub-setup (8), +.BR grub-mkrescue (1) diff --git a/docs/man/grub-macho2img.h2m b/docs/man/grub-macho2img.h2m index 412bf926a..d79aaeed8 100644 --- a/docs/man/grub-macho2img.h2m +++ b/docs/man/grub-macho2img.h2m @@ -1,2 +1,4 @@ [NAME] grub-macho2img \- convert Mach-O to raw image +[SEE ALSO] +.BR grub-mkimage (1) diff --git a/docs/man/grub-menulst2cfg.h2m b/docs/man/grub-menulst2cfg.h2m index 0c0570f27..c2e0055ed 100644 --- a/docs/man/grub-menulst2cfg.h2m +++ b/docs/man/grub-menulst2cfg.h2m @@ -1,3 +1,4 @@ [NAME] grub-menulst2cfg \- transform legacy menu.lst into grub.cfg - +[SEE ALSO] +.BR grub-mkconfig (8) diff --git a/docs/man/grub-mkconfig.h2m b/docs/man/grub-mkconfig.h2m index b0d33ec61..9b42f8130 100644 --- a/docs/man/grub-mkconfig.h2m +++ b/docs/man/grub-mkconfig.h2m @@ -1,2 +1,4 @@ [NAME] grub-mkconfig \- generate a GRUB configuration file +[SEE ALSO] +.BR grub-install (8) diff --git a/docs/man/grub-mkdevicemap.h2m b/docs/man/grub-mkdevicemap.h2m index 8ab34ac86..3ef8e9712 100644 --- a/docs/man/grub-mkdevicemap.h2m +++ b/docs/man/grub-mkdevicemap.h2m @@ -1,2 +1,4 @@ [NAME] grub-mkdevicemap \- generate a GRUB device map file automatically +[SEE ALSO] +.BR grub-install (8) diff --git a/docs/man/grub-mkfont.h2m b/docs/man/grub-mkfont.h2m index d8580186f..d46fe600e 100644 --- a/docs/man/grub-mkfont.h2m +++ b/docs/man/grub-mkfont.h2m @@ -1,2 +1,4 @@ [NAME] grub-mkfont \- make GRUB font files +[SEE ALSO] +.BR grub-mkconfig (8) diff --git a/docs/man/grub-mkimage.h2m b/docs/man/grub-mkimage.h2m index 71f270940..ca08b0c5c 100644 --- a/docs/man/grub-mkimage.h2m +++ b/docs/man/grub-mkimage.h2m @@ -1,2 +1,7 @@ [NAME] grub-mkimage \- make a bootable image of GRUB +[SEE ALSO] +.BR grub-install (8), +.BR grub-setup (8), +.BR grub-mkrescue (1), +.BR grub-mknetdir (8) diff --git a/docs/man/grub-mklayout.h2m b/docs/man/grub-mklayout.h2m index e0ae9dedb..cda6f3676 100644 --- a/docs/man/grub-mklayout.h2m +++ b/docs/man/grub-mklayout.h2m @@ -1,2 +1,4 @@ [NAME] grub-mklayout \- generate a GRUB keyboard layout file +[SEE ALSO] +.BR grub-mkconfig (8) diff --git a/docs/man/grub-mknetdir.h2m b/docs/man/grub-mknetdir.h2m index 26defe876..a2ef13ec1 100644 --- a/docs/man/grub-mknetdir.h2m +++ b/docs/man/grub-mknetdir.h2m @@ -1,2 +1,4 @@ [NAME] grub-mknetdir \- prepare a GRUB netboot directory. +[SEE ALSO] +.BR grub-mkimage (1) diff --git a/docs/man/grub-mkpasswd-pbkdf2.h2m b/docs/man/grub-mkpasswd-pbkdf2.h2m index 5b2b2ef7f..4d202f3da 100644 --- a/docs/man/grub-mkpasswd-pbkdf2.h2m +++ b/docs/man/grub-mkpasswd-pbkdf2.h2m @@ -1,2 +1,4 @@ [NAME] grub-mkpasswd-pbkdf2 \- generate hashed password for GRUB +[SEE ALSO] +.BR grub-mkconfig (8) diff --git a/docs/man/grub-mkrelpath.h2m b/docs/man/grub-mkrelpath.h2m index ccc0880fa..d01f3961e 100644 --- a/docs/man/grub-mkrelpath.h2m +++ b/docs/man/grub-mkrelpath.h2m @@ -1,2 +1,4 @@ [NAME] grub-mkrelpath \- make a system path relative to its root +[SEE ALSO] +.BR grub-probe (8) diff --git a/docs/man/grub-mkrescue.h2m b/docs/man/grub-mkrescue.h2m index 5e92e0d99..a427f02e3 100644 --- a/docs/man/grub-mkrescue.h2m +++ b/docs/man/grub-mkrescue.h2m @@ -1,2 +1,4 @@ [NAME] grub-mkrescue \- make a GRUB rescue image +[SEE ALSO] +.BR grub-mkimage (1) diff --git a/docs/man/grub-ofpathname.h2m b/docs/man/grub-ofpathname.h2m index f07158cb3..74b43eea0 100644 --- a/docs/man/grub-ofpathname.h2m +++ b/docs/man/grub-ofpathname.h2m @@ -1,2 +1,4 @@ [NAME] grub-ofpathname \- find OpenBOOT path for a device +[SEE ALSO] +.BR grub-probe (8) diff --git a/docs/man/grub-pe2elf.h2m b/docs/man/grub-pe2elf.h2m index 3fdb88b43..7ca29bd70 100644 --- a/docs/man/grub-pe2elf.h2m +++ b/docs/man/grub-pe2elf.h2m @@ -1,2 +1,4 @@ [NAME] grub-pe2elf \- convert PE image to ELF +[SEE ALSO] +.BR grub-mkimage (1) diff --git a/docs/man/grub-probe.h2m b/docs/man/grub-probe.h2m index 817ba8ef6..6e1ffdcf9 100644 --- a/docs/man/grub-probe.h2m +++ b/docs/man/grub-probe.h2m @@ -1,2 +1,4 @@ [NAME] grub-probe \- probe device information for GRUB +[SEE ALSO] +.BR grub-fstest (1) diff --git a/docs/man/grub-reboot.h2m b/docs/man/grub-reboot.h2m index 957e4b797..e4acace65 100644 --- a/docs/man/grub-reboot.h2m +++ b/docs/man/grub-reboot.h2m @@ -1,2 +1,5 @@ [NAME] grub-reboot \- set the default boot entry for GRUB, for the next boot only +[SEE ALSO] +.BR grub-set-default (8), +.BR grub-editenv (1) diff --git a/docs/man/grub-script-check.h2m b/docs/man/grub-script-check.h2m index 39c0a3ef6..365368267 100644 --- a/docs/man/grub-script-check.h2m +++ b/docs/man/grub-script-check.h2m @@ -1,2 +1,4 @@ [NAME] grub-script-check \- check grub.cfg for syntax errors +[SEE ALSO] +.BR grub-mkconfig (8) diff --git a/docs/man/grub-set-default.h2m b/docs/man/grub-set-default.h2m index dd0793cfd..7945001c1 100644 --- a/docs/man/grub-set-default.h2m +++ b/docs/man/grub-set-default.h2m @@ -1,2 +1,5 @@ [NAME] grub-set-default \- set the saved default boot entry for GRUB +[SEE ALSO] +.BR grub-reboot (8), +.BR grub-editenv (1) diff --git a/docs/man/grub-setup.h2m b/docs/man/grub-setup.h2m index e70e465a4..eebe3ef38 100644 --- a/docs/man/grub-setup.h2m +++ b/docs/man/grub-setup.h2m @@ -1,2 +1,6 @@ [NAME] grub-setup \- set up a device to boot using GRUB +[SEE ALSO] +.BR grub-install (8), +.BR grub-mkimage (1), +.BR grub-mkrescue (1) From e91dba5b13c564a5fbfc2b9d070ad9e87cb1bae5 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 21 Apr 2011 15:47:58 +0100 Subject: [PATCH 188/406] * po/README: Add instructions for creating po/LINGUAS. --- ChangeLog | 4 ++++ po/README | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 3b98caba3..cd791308c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-04-21 Colin Watson + + * po/README: Add instructions for creating po/LINGUAS. + 2011-04-21 Colin Watson Add "SEE ALSO" sections to most man pages. Fixes Debian bug diff --git a/po/README b/po/README index 801599583..5541f4229 100644 --- a/po/README +++ b/po/README @@ -8,6 +8,10 @@ that will hopefully clarify the situation. rsync -Lrtvz translationproject.org::tp/latest/grub/ po + Then create a po/LINGUAS file listing all the language codes: + + (cd po && ls *.po | cut -d. -f1 | xargs) >po/LINGUAS + GRUB's build system will automatically detect those and include them in your install. From 0c512b092c885733eb31aa1a12c6e7289c5e5ea1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 14:52:00 +0200 Subject: [PATCH 189/406] Fix a cache retrieving bug --- grub-core/kern/disk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index 5439a02f6..30bc604f0 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -571,7 +571,8 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, if (data) { - grub_memcpy (buf, data, GRUB_DISK_CACHE_SIZE); + grub_memcpy (buf, data, + GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); sector += GRUB_DISK_CACHE_SIZE; buf = (char *) buf + (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); size -= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); From 6be8715dfce00f852b8f31ae3d89f34c5b2f60b0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 25 Apr 2011 15:23:37 +0200 Subject: [PATCH 190/406] * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Make mdraid UUID match the one used by mdadm. --- ChangeLog | 5 +++++ grub-core/disk/mdraid_linux.c | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index cd791308c..2de8578ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-04-25 Vladimir Serbinenko + + * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Make mdraid UUID + match the one used by mdadm. + 2011-04-21 Colin Watson * po/README: Add instructions for creating po/LINGUAS. diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c index 691d100b8..0e2d85009 100644 --- a/grub-core/disk/mdraid_linux.c +++ b/grub-core/disk/mdraid_linux.c @@ -221,10 +221,10 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, return grub_errno; uuid = (grub_uint32_t *) array->uuid; - uuid[0] = sb.set_uuid0; - uuid[1] = sb.set_uuid1; - uuid[2] = sb.set_uuid2; - uuid[3] = sb.set_uuid3; + uuid[0] = grub_swap_bytes32 (sb.set_uuid0); + uuid[1] = grub_swap_bytes32 (sb.set_uuid1); + uuid[2] = grub_swap_bytes32 (sb.set_uuid2); + uuid[3] = grub_swap_bytes32 (sb.set_uuid3); *start_sector = 0; From 68797f9230de4768b472f2807d1c947dba96dff0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 25 Apr 2011 15:29:41 +0200 Subject: [PATCH 191/406] * grub-core/gnulib/regex.c: Remove GRUB_MOD_LICENSE since it's already supplied by another part of the module (fixes compilation on FreeBSD). --- ChangeLog | 6 ++++++ grub-core/gnulib/regex.c | 3 --- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2de8578ff..b464d83a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-04-25 Vladimir Serbinenko + + * grub-core/gnulib/regex.c: Remove GRUB_MOD_LICENSE since it's + already supplied by another part of the module (fixes compilation on + FreeBSD). + 2011-04-25 Vladimir Serbinenko * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Make mdraid UUID diff --git a/grub-core/gnulib/regex.c b/grub-core/gnulib/regex.c index 4c2243f64..ba0eebee7 100644 --- a/grub-core/gnulib/regex.c +++ b/grub-core/gnulib/regex.c @@ -19,9 +19,6 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include -#include - -GRUB_MOD_LICENSE ("GPLv3+"); /* Make sure noone compiles this code with a C++ compiler. */ #if defined __cplusplus && defined _LIBC From 723f63f2f88c91407ec0ee8c6b545f76a79e75dc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 25 Apr 2011 15:36:08 +0200 Subject: [PATCH 192/406] * grub-core/partmap/amiga.c (amiga_partition_map_iterate): Fix a wrong action on non-detecting the magic. --- ChangeLog | 5 +++++ grub-core/partmap/amiga.c | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index b464d83a8..3da7693db 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-04-25 Vladimir Serbinenko + + * grub-core/partmap/amiga.c (amiga_partition_map_iterate): Fix a + wrong action on non-detecting the magic. + 2011-04-25 Vladimir Serbinenko * grub-core/gnulib/regex.c: Remove GRUB_MOD_LICENSE since it's diff --git a/grub-core/partmap/amiga.c b/grub-core/partmap/amiga.c index f3ba950aa..36e318beb 100644 --- a/grub-core/partmap/amiga.c +++ b/grub-core/partmap/amiga.c @@ -114,8 +114,9 @@ amiga_partition_map_iterate (grub_disk_t disk, return grub_errno; if (grub_memcmp (apart.magic, GRUB_AMIGA_PART_MAGIC, - sizeof (apart.magic)) == 0) - + sizeof (apart.magic)) != 0) + return grub_error (GRUB_ERR_BAD_PART_TABLE, + "invalid Amiga partition map"); /* Calculate the first block and the size of the partition. */ part.start = (grub_be_to_cpu32 (apart.lowcyl) * grub_be_to_cpu32 (apart.heads) From 3c62402d08da39973b299c1c153c119567bb08f3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 25 Apr 2011 16:58:25 +0200 Subject: [PATCH 193/406] * grub-core/loader/i386/linux.c (grub_linux_boot): Supply target rather than source address for efi mmap buffer. --- ChangeLog | 5 +++++ grub-core/loader/i386/linux.c | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3da7693db..0a7e4d64c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-04-25 Vladimir Serbinenko + + * grub-core/loader/i386/linux.c (grub_linux_boot): Supply target rather + than source address for efi mmap buffer. + 2011-04-25 Vladimir Serbinenko * grub-core/partmap/amiga.c (amiga_partition_map_iterate): Fix a diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index 241eaa5e7..f19f471ab 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -549,6 +549,7 @@ grub_linux_boot (void) #ifdef GRUB_MACHINE_EFI { grub_efi_uintn_t efi_desc_size; + grub_size_t efi_mmap_target; grub_efi_uint32_t efi_desc_version; err = grub_efi_finish_boot_services (&efi_mmap_size, efi_mmap_buf, NULL, &efi_desc_size, &efi_desc_version); @@ -556,23 +557,24 @@ grub_linux_boot (void) return err; /* Note that no boot services are available from here. */ - + efi_mmap_target = real_mode_target + + ((grub_uint8_t *) efi_mmap_buf - (grub_uint8_t *) real_mode_mem); /* Pass EFI parameters. */ if (grub_le_to_cpu16 (params->version) >= 0x0206) { params->v0206.efi_mem_desc_size = efi_desc_size; params->v0206.efi_mem_desc_version = efi_desc_version; - params->v0206.efi_mmap = (grub_uint32_t) (unsigned long) efi_mmap_buf; + params->v0206.efi_mmap = efi_mmap_target; params->v0206.efi_mmap_size = efi_mmap_size; #ifdef __x86_64__ - params->v0206.efi_mmap_hi = (grub_uint32_t) ((grub_uint64_t) efi_mmap_buf >> 32); + params->v0206.efi_mmap_hi = (efi_mmap_target >> 32); #endif } else if (grub_le_to_cpu16 (params->version) >= 0x0204) { params->v0204.efi_mem_desc_size = efi_desc_size; params->v0204.efi_mem_desc_version = efi_desc_version; - params->v0204.efi_mmap = (grub_uint32_t) (unsigned long) efi_mmap_buf; + params->v0204.efi_mmap = efi_mmap_target; params->v0204.efi_mmap_size = efi_mmap_size; } } From 8f9425534015c78ec04976aa04ce28811cf42405 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 1 May 2011 20:04:02 +0100 Subject: [PATCH 194/406] * docs/grub.texi (GRUB only offers a rescue shell): Suggest the use of `ls' to find out which devices are available. --- ChangeLog | 5 +++++ docs/grub.texi | 2 ++ 2 files changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index 0a7e4d64c..58b3cc56c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-01 Colin Watson + + * docs/grub.texi (GRUB only offers a rescue shell): Suggest the use + of `ls' to find out which devices are available. + 2011-04-25 Vladimir Serbinenko * grub-core/loader/i386/linux.c (grub_linux_boot): Supply target rather diff --git a/docs/grub.texi b/docs/grub.texi index 8d2223fb4..95707e4cc 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -4127,6 +4127,8 @@ device), then you can correct this and enter normal mode manually: @group # Inspect the current prefix (and other preset variables): set +# Find out which devices are available: +ls # Set to the correct value, which might be something like this: set prefix=(hd0,1)/grub set root=(hd0,1) From 4ebff75340fa311ed4c76644b6f3b798f0ae9723 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 3 May 2011 17:57:39 +0100 Subject: [PATCH 195/406] * tests/partmap_test.in: Don't hardcode path to parted. Reported by: Peter Hjalmarsson. Fixes Savannah bug #33150. --- ChangeLog | 5 +++++ tests/partmap_test.in | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 58b3cc56c..2aaeb862a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-03 Colin Watson + + * tests/partmap_test.in: Don't hardcode path to parted. + Reported by: Peter Hjalmarsson. Fixes Savannah bug #33150. + 2011-05-01 Colin Watson * docs/grub.texi (GRUB only offers a rescue shell): Suggest the use diff --git a/tests/partmap_test.in b/tests/partmap_test.in index 5a9c1a93d..7e9cef7c6 100644 --- a/tests/partmap_test.in +++ b/tests/partmap_test.in @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with GRUB. If not, see . -parted=/sbin/parted +parted=parted grubshell=@builddir@/grub-shell create_disk_image () { From bd405bbc55f88971a5e669d3c1f6c2570296093f Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 3 May 2011 18:03:05 +0100 Subject: [PATCH 196/406] * grub-core/fs/i386/pc/pxe.c (grub_pxefs_dir): Return GRUB_ERR_BAD_FS rather than GRUB_ERR_IO if the disk is not a pxe disk; otherwise grub_fs_probe will not fall back to the next filesystem. (grub_pxefs_open): Likewise, for consistency. Reported and tested by: Ezekiel Grave. --- ChangeLog | 9 +++++++++ grub-core/fs/i386/pc/pxe.c | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2aaeb862a..29cdc3e01 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-05-03 Colin Watson + + * grub-core/fs/i386/pc/pxe.c (grub_pxefs_dir): Return + GRUB_ERR_BAD_FS rather than GRUB_ERR_IO if the disk is not a pxe + disk; otherwise grub_fs_probe will not fall back to the next + filesystem. + (grub_pxefs_open): Likewise, for consistency. + Reported and tested by: Ezekiel Grave. + 2011-05-03 Colin Watson * tests/partmap_test.in: Don't hardcode path to parted. diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index d6dc2c22d..4304881fa 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -227,7 +227,7 @@ grub_pxefs_dir (grub_device_t device, __attribute__ ((unused))) { if (device->disk->dev->id != GRUB_DISK_DEVICE_PXE_ID) - return grub_error (GRUB_ERR_IO, "not a pxe disk"); + return grub_error (GRUB_ERR_BAD_FS, "not a pxe disk"); return GRUB_ERR_NONE; } @@ -245,7 +245,7 @@ grub_pxefs_open (struct grub_file *file, const char *name) grub_file_t file_int, bufio; if (file->device->disk->dev->id != GRUB_DISK_DEVICE_PXE_ID) - return grub_error (GRUB_ERR_IO, "not a pxe disk"); + return grub_error (GRUB_ERR_BAD_FS, "not a pxe disk"); if (curr_file != 0) { From 664889a69ccae30908c13e2293d8400b570bee44 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 5 May 2011 01:26:16 +0200 Subject: [PATCH 197/406] * grub-core/efiemu/main.c (grub_efiemu_load_file): Return grub_errno and not 0 on failure. --- ChangeLog | 5 +++++ grub-core/efiemu/main.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 29cdc3e01..cdfc82688 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-05 Vladimir Serbinenko + + * grub-core/efiemu/main.c (grub_efiemu_load_file): Return grub_errno + and not 0 on failure. + 2011-05-03 Colin Watson * grub-core/fs/i386/pc/pxe.c (grub_pxefs_dir): Return diff --git a/grub-core/efiemu/main.c b/grub-core/efiemu/main.c index 772db2956..7ad3abb0d 100644 --- a/grub-core/efiemu/main.c +++ b/grub-core/efiemu/main.c @@ -193,7 +193,7 @@ grub_efiemu_load_file (const char *filename) file = grub_file_open (filename); if (! file) - return 0; + return grub_errno; err = grub_efiemu_mm_init (); if (err) From ee5614b7f8ff69ca55541a72bef0755488a4171d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 5 May 2011 01:27:54 +0200 Subject: [PATCH 198/406] * grub-core/lib/legacy_parse.c (grub_legacy_parse): Correctly handle hexadecimal. --- ChangeLog | 5 +++++ grub-core/lib/legacy_parse.c | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index cdfc82688..7785ac9f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-05 Vladimir Serbinenko + + * grub-core/lib/legacy_parse.c (grub_legacy_parse): Correctly handle + hexadecimal. + 2011-05-05 Vladimir Serbinenko * grub-core/efiemu/main.c (grub_efiemu_load_file): Return grub_errno diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 024849055..659fa7061 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -680,7 +680,10 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) int base = 10; brk = curarg; if (brk[0] == '0' && brk[1] == 'x') - base = 16; + { + base = 16; + brk += 2; + } else if (brk[0] == '0') base = 8; for (; *brk && brk < curarg + curarglen; brk++) From ed660bd8ed99a29a5eb4b0bebf77a5c50a7fef44 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 5 May 2011 01:29:21 +0200 Subject: [PATCH 199/406] * util/grub-mkrescue.in (process_input_dir): Include efiemu??.o. --- ChangeLog | 4 ++++ util/grub-mkrescue.in | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7785ac9f7..794fdf719 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-05-05 Vladimir Serbinenko + + * util/grub-mkrescue.in (process_input_dir): Include efiemu??.o. + 2011-05-05 Vladimir Serbinenko * grub-core/lib/legacy_parse.c (grub_legacy_parse): Correctly handle diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in index 455534009..f7f751708 100644 --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in @@ -160,7 +160,7 @@ process_input_dir () input_dir="$1" platform="$2" mkdir -p ${iso9660_dir}/boot/grub/${platform} - for file in ${input_dir}/*.mod; do + for file in "${input_dir}/"*.mod "${input_dir}/"efiemu32.o "${input_dir}/"efiemu64.o; do if test -f "$file"; then cp -f "$file" ${iso9660_dir}/boot/grub/${platform}/ fi From 7c515bee148b85f907bdd41db613064b6e2f445c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 5 May 2011 01:32:04 +0200 Subject: [PATCH 200/406] * util/grub-mkpasswd-pbkdf2.c (main): Use /dev/urandom and not /dev/random. /dev/urandom is good enough for our purposes (salting). --- ChangeLog | 5 +++++ util/grub-mkpasswd-pbkdf2.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 794fdf719..5dd39905e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-05 Vladimir Serbinenko + + * util/grub-mkpasswd-pbkdf2.c (main): Use /dev/urandom and not + /dev/random. /dev/urandom is good enough for our purposes (salting). + 2011-05-05 Vladimir Serbinenko * util/grub-mkrescue.in (process_input_dir): Include efiemu??.o. diff --git a/util/grub-mkpasswd-pbkdf2.c b/util/grub-mkpasswd-pbkdf2.c index fe1887f8f..dc2afdb6e 100644 --- a/util/grub-mkpasswd-pbkdf2.c +++ b/util/grub-mkpasswd-pbkdf2.c @@ -248,7 +248,7 @@ main (int argc, char *argv[]) { FILE *f; size_t rd; - f = fopen ("/dev/random", "rb"); + f = fopen ("/dev/urandom", "rb"); if (!f) { memset (pass1, 0, strlen (pass1)); From 7fae005102ffab0148219a26df8aa80d2110627e Mon Sep 17 00:00:00 2001 From: Zach Date: Thu, 5 May 2011 12:18:00 +0200 Subject: [PATCH 201/406] Support 2010 Macbooks. * grub-core/loader/efi/appleloader.c (devpath_6): New variable. (devs): Add devpath_6. --- ChangeLog | 7 +++++++ grub-core/loader/efi/appleloader.c | 33 ++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/ChangeLog b/ChangeLog index 5dd39905e..81deaf96d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-05-05 Zach + + Support 2010 Macbooks. + + * grub-core/loader/efi/appleloader.c (devpath_6): New variable. + (devs): Add devpath_6. + 2011-05-05 Vladimir Serbinenko * util/grub-mkpasswd-pbkdf2.c (main): Use /dev/urandom and not diff --git a/grub-core/loader/efi/appleloader.c b/grub-core/loader/efi/appleloader.c index 847750dc0..d8ca4a7f3 100644 --- a/grub-core/loader/efi/appleloader.c +++ b/grub-core/loader/efi/appleloader.c @@ -229,6 +229,38 @@ static struct piwg_full_device_path devpath_5 = } }; +/* mid-2010 MB/MBP (NVidia chipset) */ +static struct piwg_full_device_path devpath_6 = +{ + .comp1 = + { + .header = { + .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, + .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, + .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0} + }, + .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, + .start_address = 0xffcc4000, + .end_address = 0xffffbfff + }, + .comp2 = + { + .header = { + .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, + .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, + .length = {sizeof (struct grub_efi_piwg_device_path), 0} + }, + .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B, + 0x01, 0xAE, 0xF2, 0xB7}} + }, + .end = + { + .type = GRUB_EFI_END_DEVICE_PATH_TYPE, + .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, + .length = {sizeof (struct grub_efi_device_path), 0} + } +}; + struct devdata { char *model; @@ -242,6 +274,7 @@ struct devdata devs[] = {"MBP", (grub_efi_device_path_t *) &devpath_3}, {"MBA", (grub_efi_device_path_t *) &devpath_4}, {"MB NV", (grub_efi_device_path_t *) &devpath_5}, + {"MB NV2", (grub_efi_device_path_t *) &devpath_6}, {NULL, NULL}, }; From 072b5d315af49fc0ff4c6e31bc4f3a8f9e8a58ef Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 5 May 2011 13:34:03 +0200 Subject: [PATCH 202/406] * grub-core/loader/efi/appleloader.c (MAKE_PIWG_PATH): New macro. (devpath_1): Use MAKE_PIWG_PATH. (devpath_2): Likewise. (devpath_3): Likewise. (devpath_4): Likewise. (devpath_5): Likewise. (devpath_6): Likewise. The appleldr.mod was checked that to be binary identical to previous version. --- ChangeLog | 13 ++ grub-core/loader/efi/appleloader.c | 223 ++++++----------------------- 2 files changed, 56 insertions(+), 180 deletions(-) diff --git a/ChangeLog b/ChangeLog index 81deaf96d..540e171cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2011-05-05 Vladimir Serbinenko + + * grub-core/loader/efi/appleloader.c (MAKE_PIWG_PATH): New macro. + (devpath_1): Use MAKE_PIWG_PATH. + (devpath_2): Likewise. + (devpath_3): Likewise. + (devpath_4): Likewise. + (devpath_5): Likewise. + (devpath_6): Likewise. + + The appleldr.mod was checked that to be binary identical to previous + version. + 2011-05-05 Zach Support 2010 Macbooks. diff --git a/grub-core/loader/efi/appleloader.c b/grub-core/loader/efi/appleloader.c index d8ca4a7f3..db57a573c 100644 --- a/grub-core/loader/efi/appleloader.c +++ b/grub-core/loader/efi/appleloader.c @@ -69,197 +69,60 @@ struct piwg_full_device_path struct grub_efi_device_path end; }; -/* early 2006 Core Duo / Core Solo models */ -static struct piwg_full_device_path devpath_1 = -{ - .comp1 = - { - .header = { - .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0} - }, - .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, - .start_address = 0xffe00000, - .end_address = 0xfff9ffff - }, - .comp2 = - { - .header = { - .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_piwg_device_path), 0} - }, - .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B, - 0x01, 0xAE, 0xF2, 0xB7}} - }, - .end = - { - .type = GRUB_EFI_END_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_device_path), 0} +#define MAKE_PIWG_PATH(st, en) \ + { \ + .comp1 = \ + { \ + .header = { \ + .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, \ + .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, \ + .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0} \ + }, \ + .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, \ + .start_address = st, \ + .end_address = en \ + }, \ + .comp2 = \ + { \ + .header = { \ + .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, \ + .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, \ + .length = {sizeof (struct grub_efi_piwg_device_path), 0} \ + }, \ + .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B, \ + 0x01, 0xAE, 0xF2, 0xB7}} \ + }, \ + .end = \ + { \ + .type = GRUB_EFI_END_DEVICE_PATH_TYPE, \ + .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, \ + .length = {sizeof (struct grub_efi_device_path), 0} \ + } \ } -}; + +/* early 2006 Core Duo / Core Solo models */ +static struct piwg_full_device_path devpath_1 = MAKE_PIWG_PATH (0xffe00000, + 0xfff9ffff); /* mid-2006 Mac Pro (and probably other Core 2 models) */ -static struct piwg_full_device_path devpath_2 = -{ - .comp1 = - { - .header = { - .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0} - }, - .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, - .start_address = 0xffe00000, - .end_address = 0xfff7ffff - }, - .comp2 = - { - .header = { - .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_piwg_device_path), 0} - }, - .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B, - 0x01, 0xAE, 0xF2, 0xB7}} - }, - .end = - { - .type = GRUB_EFI_END_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_device_path), 0} - } -}; +static struct piwg_full_device_path devpath_2 = MAKE_PIWG_PATH (0xffe00000, + 0xfff7ffff); /* mid-2007 MBP ("Santa Rosa" based models) */ -static struct piwg_full_device_path devpath_3 = -{ - .comp1 = - { - .header = { - .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0} - }, - .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, - .start_address = 0xffe00000, - .end_address = 0xfff8ffff - }, - .comp2 = - { - .header = { - .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_piwg_device_path), 0} - }, - .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B, - 0x01, 0xAE, 0xF2, 0xB7}} - }, - .end = - { - .type = GRUB_EFI_END_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_device_path), 0} - } -}; +static struct piwg_full_device_path devpath_3 = MAKE_PIWG_PATH (0xffe00000, + 0xfff8ffff); /* early-2008 MBA */ -static struct piwg_full_device_path devpath_4 = -{ - .comp1 = - { - .header = { - .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0} - }, - .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, - .start_address = 0xffc00000, - .end_address = 0xfff8ffff - }, - .comp2 = - { - .header = { - .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_piwg_device_path), 0} - }, - .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B, - 0x01, 0xAE, 0xF2, 0xB7}} - }, - .end = - { - .type = GRUB_EFI_END_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_device_path), 0} - } -}; +static struct piwg_full_device_path devpath_4 = MAKE_PIWG_PATH (0xffc00000, + 0xfff8ffff); /* late-2008 MB/MBP (NVidia chipset) */ -static struct piwg_full_device_path devpath_5 = -{ - .comp1 = - { - .header = { - .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0} - }, - .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, - .start_address = 0xffcb4000, - .end_address = 0xffffbfff - }, - .comp2 = - { - .header = { - .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_piwg_device_path), 0} - }, - .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B, - 0x01, 0xAE, 0xF2, 0xB7}} - }, - .end = - { - .type = GRUB_EFI_END_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_device_path), 0} - } -}; +static struct piwg_full_device_path devpath_5 = MAKE_PIWG_PATH (0xffcb4000, + 0xffffbfff); /* mid-2010 MB/MBP (NVidia chipset) */ -static struct piwg_full_device_path devpath_6 = -{ - .comp1 = - { - .header = { - .type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_memory_mapped_device_path), 0} - }, - .memory_type = GRUB_EFI_MEMORY_MAPPED_IO, - .start_address = 0xffcc4000, - .end_address = 0xffffbfff - }, - .comp2 = - { - .header = { - .type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_piwg_device_path), 0} - }, - .guid = {0x2B0585EB, 0xD8B8, 0x49A9, {0x8B, 0x8C, 0xE2, 0x1B, - 0x01, 0xAE, 0xF2, 0xB7}} - }, - .end = - { - .type = GRUB_EFI_END_DEVICE_PATH_TYPE, - .subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, - .length = {sizeof (struct grub_efi_device_path), 0} - } -}; +static struct piwg_full_device_path devpath_6 = MAKE_PIWG_PATH (0xffcc4000, + 0xffffbfff); struct devdata { From c5934345bea4070e56813c4064645240ff902f4a Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 6 May 2011 14:03:51 -0300 Subject: [PATCH 203/406] Free memory when removing packet. --- include/grub/net.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/grub/net.h b/include/grub/net.h index 37b258f36..59974b94f 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -178,6 +178,7 @@ grub_net_remove_packet (grub_net_packet_t *pkt) pkt->next->prev = pkt->prev; else pkt->up->last = pkt->prev; + grub_free (pkt); } typedef struct grub_net_app_protocol *grub_net_app_level_t; From 5452733f3505fcd1135c3705a9565365be60bfd5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 8 May 2011 12:39:08 +0200 Subject: [PATCH 204/406] more or less functional ia64 grub-mkimage --- Makefile.util.def | 1 + grub-core/Makefile.core.def | 1 + grub-core/kern/dl.c | 2 + grub-core/kern/ia64/dl.c | 66 ++----- include/grub/dl.h | 12 +- util/grub-mkimage.c | 29 ++- util/grub-mkimagexx.c | 345 +++++++++++++++++++++++++++++++++--- 7 files changed, 358 insertions(+), 98 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index c37cac965..df3b14138 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -98,6 +98,7 @@ library = { common = grub-core/script/main.c; common = grub-core/script/script.c; common = grub-core/script/argv.c; + common = grub-core/kern/ia64/dl_helper.c; }; program = { diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index c21c38763..7bb51adfe 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -128,6 +128,7 @@ kernel = { ia64_efi = kern/ia64/efi/startup.S; ia64_efi = kern/ia64/efi/init.c; ia64_efi = kern/ia64/dl.c; + ia64_efi = kern/ia64/dl_helper.c; i386_pc = kern/i386/pc/init.c; i386_pc = kern/i386/pc/mmap.c; diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index f871b81a1..aa15cfa24 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -247,6 +247,8 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) #ifdef __ia64__ grub_arch_dl_get_tramp_got_size (e, &tramp, &got); + tramp *= GRUB_IA64_DL_TRAMP_SIZE; + got *= sizeof (grub_uint64_t); tsize += ALIGN_UP (tramp, GRUB_ARCH_DL_TRAMP_ALIGN); if (talign < GRUB_ARCH_DL_TRAMP_ALIGN) talign = GRUB_ARCH_DL_TRAMP_ALIGN; diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c index 9bbebcd2f..0d1e0d2e6 100644 --- a/grub-core/kern/ia64/dl.c +++ b/grub-core/kern/ia64/dl.c @@ -54,15 +54,18 @@ add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value) { case 0: p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2); - p->val = (((((p->val >> 2) & MASK20) + value) & MASK20) << 2) | (p->val & ~(MASK20 << 2)); + p->val = ((((((p->val >> 2) & MASK20) + value) & MASK20) << 2) + | (p->val & ~(MASK20 << 2))); break; case 1: p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 7); - p->val = (((((p->val >> 3) & MASK20) + value) & MASK20) << 3) | (p->val & ~(MASK20 << 3)); + p->val = ((((((p->val >> 3) & MASK20) + value) & MASK20) << 3) + | (p->val & ~(MASK20 << 3))); break; case 2: p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 12); - p->val = (((((p->val >> 4) & MASK20) + value) & MASK20) << 4) | (p->val & ~(MASK20 << 4)); + p->val = ((((((p->val >> 4) & MASK20) + value) & MASK20) << 4) + | (p->val & ~(MASK20 << 4))); break; } } @@ -137,6 +140,8 @@ struct ia64_trampoline static void make_trampoline (struct ia64_trampoline *tr, grub_uint64_t addr) { + COMPILE_TIME_ASSERT (sizeof (struct ia64_trampoline) + == GRUB_IA64_DL_TRAMP_SIZE); grub_memcpy (tr->nop, nopm, sizeof (tr->nop)); tr->addr_hi[0] = ((addr & 0xc00000) >> 16); tr->addr_hi[1] = (addr >> 24) & 0xff; @@ -146,60 +151,13 @@ make_trampoline (struct ia64_trampoline *tr, grub_uint64_t addr) tr->addr_hi[5] = (addr >> 56) & 0xff; tr->e0 = 0xe0; tr->addr_lo[0] = ((addr & 0x000f) << 4) | 0x01; - tr->addr_lo[1] = ((addr & 0x0070) >> 4) | ((addr & 0x070000) >> 11) | ((addr & 0x200000) >> 17); + tr->addr_lo[1] = (((addr & 0x0070) >> 4) | ((addr & 0x070000) >> 11) + | ((addr & 0x200000) >> 17)); tr->addr_lo[2] = ((addr & 0x1f80) >> 5) | ((addr & 0x180000) >> 19); tr->addr_lo[3] = ((addr & 0xe000) >> 13) | 0x60; grub_memcpy (tr->jump, jump, sizeof (tr->jump)); } -void -grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, grub_size_t *got) -{ - const Elf_Ehdr *e = ehdr; - grub_size_t cntt = 0, cntg = 0;; - const Elf_Shdr *s; - Elf_Word entsize; - unsigned i; - - /* Find a symbol table. */ - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_SYMTAB) - break; - - if (i == e->e_shnum) - return; - - entsize = s->sh_entsize; - - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_RELA) - { - Elf_Rela *rel, *max; - - for (rel = (Elf_Rela *) ((char *) e + s->sh_offset), - max = rel + s->sh_size / s->sh_entsize; - rel < max; rel++) - switch (ELF_R_TYPE (rel->r_info)) - { - case R_IA64_PCREL21B: - cntt++; - break; - case R_IA64_LTOFF_FPTR22: - case R_IA64_LTOFF22X: - case R_IA64_LTOFF22: - cntg++; - break; - } - } - *tramp = cntt * sizeof (struct ia64_trampoline); - *got = cntg * sizeof (grub_uint64_t); -} - - /* Relocate symbols. */ grub_err_t grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) @@ -279,7 +237,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) } break; case R_IA64_SEGREL64LSB: - *(grub_uint64_t *) addr += value - rel->r_offset; + *(grub_uint64_t *) addr += value - (grub_addr_t) seg->addr; break; case R_IA64_FPTR64LSB: case R_IA64_DIR64LSB: @@ -296,8 +254,6 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) case R_IA64_LTOFF22X: case R_IA64_LTOFF22: *gpptr = value; - if ((addr & 0xffff) == 0x4301) - grub_dprintf ("modules", "off = %lx\n", (grub_addr_t) gpptr - (grub_addr_t) gp); add_value_to_slot_21 (addr, (grub_addr_t) gpptr - (grub_addr_t) gp); gpptr++; break; diff --git a/include/grub/dl.h b/include/grub/dl.h index b45928a76..6646902d4 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -126,12 +126,18 @@ grub_err_t grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr); void grub_arch_dl_init_linker (void); #endif -#ifdef __ia64__ -void grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, grub_size_t *got); +#define GRUB_IA64_DL_TRAMP_ALIGN 16 +#define GRUB_IA64_DL_TRAMP_SIZE 48 +#define GRUB_IA64_DL_GOT_ALIGN 16 +void +grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + grub_size_t *got); + +#ifdef __ia64__ #define GRUB_ARCH_DL_TRAMP_ALIGN 16 #define GRUB_ARCH_DL_GOT_ALIGN 16 - +#define grub_arch_dl_get_tramp_got_size grub_ia64_dl_get_tramp_got_size #else #endif diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 507a7a80d..9f4e2a61f 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -89,6 +90,13 @@ struct image_target_desc grub_uint16_t pe_target; }; +#define EFI64_HEADER_SIZE ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE \ + + GRUB_PE32_SIGNATURE_SIZE \ + + sizeof (struct grub_pe32_coff_header) \ + + sizeof (struct grub_pe64_optional_header) \ + + 4 * sizeof (struct grub_pe32_section_table), \ + GRUB_PE32_SECTION_ALIGNMENT) + struct image_target_desc image_targets[] = { { @@ -248,12 +256,7 @@ struct image_target_desc image_targets[] = .kernel_image_size = TARGET_NO_FIELD, .compressed_size = TARGET_NO_FIELD, .section_align = GRUB_PE32_SECTION_ALIGNMENT, - .vaddr_offset = ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE - + GRUB_PE32_SIGNATURE_SIZE - + sizeof (struct grub_pe32_coff_header) - + sizeof (struct grub_pe64_optional_header) - + 4 * sizeof (struct grub_pe32_section_table), - GRUB_PE32_SECTION_ALIGNMENT), + .vaddr_offset = EFI64_HEADER_SIZE, .install_dos_part = TARGET_NO_FIELD, .install_bsd_part = TARGET_NO_FIELD, .pe_target = GRUB_PE32_MACHINE_X86_64, @@ -372,12 +375,7 @@ struct image_target_desc image_targets[] = .kernel_image_size = TARGET_NO_FIELD, .compressed_size = TARGET_NO_FIELD, .section_align = GRUB_PE32_SECTION_ALIGNMENT, - .vaddr_offset = ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE - + GRUB_PE32_SIGNATURE_SIZE - + sizeof (struct grub_pe32_coff_header) - + sizeof (struct grub_pe64_optional_header) - + 4 * sizeof (struct grub_pe32_section_table), - GRUB_PE32_SECTION_ALIGNMENT), + .vaddr_offset = EFI64_HEADER_SIZE, .install_dos_part = TARGET_NO_FIELD, .install_bsd_part = TARGET_NO_FIELD, .pe_target = GRUB_PE32_MACHINE_IA64, @@ -930,12 +928,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], + 4 * sizeof (struct grub_pe32_section_table), GRUB_PE32_SECTION_ALIGNMENT); else - header_size = ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE - + GRUB_PE32_SIGNATURE_SIZE - + sizeof (struct grub_pe32_coff_header) - + sizeof (struct grub_pe64_optional_header) - + 4 * sizeof (struct grub_pe32_section_table), - GRUB_PE32_SECTION_ALIGNMENT); + header_size = EFI64_HEADER_SIZE; reloc_addr = ALIGN_UP (header_size + core_size, image_target->section_align); diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index 20cbacf15..6f68bf1af 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -56,6 +56,7 @@ static Elf_Addr SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections, Elf_Shdr *symtab_section, Elf_Addr *section_addresses, Elf_Half section_entsize, Elf_Half num_sections, + void *jumpers, Elf_Addr jumpers_addr, struct image_target_desc *image_target) { Elf_Word symtab_size, sym_size, num_syms; @@ -65,6 +66,7 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections, Elf_Word i; Elf_Shdr *strtab_section; const char *strtab; + grub_uint64_t *jptr = jumpers; strtab_section = (Elf_Shdr *) ((char *) sections @@ -103,6 +105,16 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections, sym->st_value = (grub_target_to_host (sym->st_value) + section_addresses[index]); + + if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info) + == STT_FUNC) + { + *jptr = sym->st_value; + sym->st_value = (char *) jptr - (char *) jumpers + jumpers_addr; + jptr++; + *jptr = 0; + jptr++; + } grub_util_info ("locating %s at 0x%x", name, sym->st_value, section_addresses[index]); if (! start_address) @@ -134,6 +146,152 @@ SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset, return (Elf_Addr *) ((char *) e + grub_target_to_host32 (s->sh_offset) + offset); } +static Elf_Addr +SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section, + struct image_target_desc *image_target) +{ + Elf_Word symtab_size, sym_size, num_syms; + Elf_Off symtab_offset; + Elf_Addr start_address = 0; + Elf_Sym *sym; + Elf_Word i; + int ret = 0; + + symtab_size = grub_target_to_host (symtab_section->sh_size); + sym_size = grub_target_to_host (symtab_section->sh_entsize); + symtab_offset = grub_target_to_host (symtab_section->sh_offset); + num_syms = symtab_size / sym_size; + + for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset); + i < num_syms; + i++, sym = (Elf_Sym *) ((char *) sym + sym_size)) + if (ELF_ST_TYPE (sym->st_info) == STT_FUNC) + ret++; + + return ret; +} + +#ifdef MKIMAGE_ELF64 +struct unaligned_uint32 +{ + grub_uint32_t val; +} __attribute__ ((packed)); + +#define MASK20 ((1 << 20) - 1) +#define MASK19 ((1 << 19) - 1) + +static void +add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value) +{ + struct unaligned_uint32 *p; + switch (addr & 3) + { + case 0: + p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2); + p->val = ((((((p->val >> 2) & MASK20) + value) & MASK20) << 2) + | (p->val & ~(MASK20 << 2))); + break; + case 1: + p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 7); + p->val = ((((((p->val >> 3) & MASK20) + value) & MASK20) << 3) + | (p->val & ~(MASK20 << 3))); + break; + case 2: + p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 12); + p->val = ((((((p->val >> 4) & MASK20) + value) & MASK20) << 4) + | (p->val & ~(MASK20 << 4))); + break; + } +} + +#define MASKF21 ( ((1 << 23) - 1) & ~((1 << 7) | (1 << 8)) ) + +static grub_uint32_t +add_value_to_slot_21_real (grub_uint32_t a, grub_uint32_t value) +{ + grub_uint32_t high, mid, low, c; + low = (a & 0x00007f); + mid = (a & 0x7fc000) >> 7; + high = (a & 0x003e00) << 7; + c = (low | mid | high) + value; + return (c & 0x7f) | ((c << 7) & 0x7fc000) | ((c >> 7) & 0x0003e00); //0x003e00 +} + +static void +add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value) +{ + struct unaligned_uint32 *p; + switch (addr & 3) + { + case 0: + p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2); + p->val = ((add_value_to_slot_21_real (((p->val >> 2) & MASKF21), value) & MASKF21) << 2) | (p->val & ~(MASKF21 << 2)); + break; + case 1: + p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 7); + p->val = ((add_value_to_slot_21_real (((p->val >> 3) & MASKF21), value) & MASKF21) << 3) | (p->val & ~(MASKF21 << 3)); + break; + case 2: + p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 12); + p->val = ((add_value_to_slot_21_real (((p->val >> 4) & MASKF21), value) & MASKF21) << 4) | (p->val & ~(MASKF21 << 4)); + break; + } +} + + +struct ia64_kernel_trampoline +{ + /* nop.m */ + grub_uint8_t nop[5]; + /* movl r15 = addr*/ + grub_uint8_t addr_hi[6]; + grub_uint8_t e0; + grub_uint8_t addr_lo[4]; + grub_uint8_t jump[0x20]; +}; + +static grub_uint8_t nopm[5] = + { + /* [MLX] nop.m 0x0 */ + 0x05, 0x00, 0x00, 0x00, 0x01 + }; + +static grub_uint8_t jump[0x20] = + { + /* [MMI] add r15=r15,r1;; */ + 0x0b, 0x78, 0x3c, 0x02, 0x00, 0x20, + /* ld8 r16=[r15],8 */ + 0x00, 0x41, 0x3c, 0x30, 0x28, 0xc0, + /* mov r14=r1;; */ + 0x01, 0x08, 0x00, 0x84, + /* [MIB] ld8 r1=[r15] */ + 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10, + /* mov b6=r16 */ + 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, + /* br.few b6;; */ + 0x60, 0x00, 0x80, 0x00 + }; + +static void +make_trampoline (struct ia64_kernel_trampoline *tr, grub_uint64_t addr) +{ + grub_memcpy (tr->nop, nopm, sizeof (tr->nop)); + tr->addr_hi[0] = ((addr & 0xc00000) >> 16); + tr->addr_hi[1] = (addr >> 24) & 0xff; + tr->addr_hi[2] = (addr >> 32) & 0xff; + tr->addr_hi[3] = (addr >> 40) & 0xff; + tr->addr_hi[4] = (addr >> 48) & 0xff; + tr->addr_hi[5] = (addr >> 56) & 0xff; + tr->e0 = 0xe0; + tr->addr_lo[0] = ((addr & 0x000f) << 4) | 0x01; + tr->addr_lo[1] = (((addr & 0x0070) >> 4) | ((addr & 0x070000) >> 11) + | ((addr & 0x200000) >> 17)); + tr->addr_lo[2] = ((addr & 0x1f80) >> 5) | ((addr & 0x180000) >> 19); + tr->addr_lo[3] = ((addr & 0xe000) >> 13) | 0x60; + grub_memcpy (tr->jump, jump, sizeof (tr->jump)); +} +#endif + /* Deal with relocation information. This function relocates addresses within the virtual address space starting from 0. So only relative addresses can be fully resolved. Absolute addresses must be relocated @@ -142,10 +300,15 @@ static void SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, Elf_Addr *section_addresses, Elf_Half section_entsize, Elf_Half num_sections, - const char *strtab, struct image_target_desc *image_target) + const char *strtab, + char *pe_target, Elf_Addr tramp_off, + Elf_Addr got_off, + struct image_target_desc *image_target) { Elf_Half i; Elf_Shdr *s; + struct ia64_kernel_trampoline *tr = (void *) (pe_target + tramp_off); + grub_uint64_t *gpptr = (void *) (pe_target + got_off); for (i = 0, s = sections; i < num_sections; @@ -274,15 +437,69 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, break; } break; +#ifdef MKIMAGE_ELF64 case EM_IA_64: switch (ELF_R_TYPE (info)) { + case R_IA64_PCREL21B: + { + grub_uint64_t noff; + make_trampoline (tr, addend + sym_addr); + noff = ((char *) tr - (char *) pe_target + - target_section_addr - (offset & ~3) + - image_target->vaddr_offset) >> 4; + tr++; + if (noff & ~MASK19) + grub_util_error ("trampoline offset too big (%lx)", + noff); + add_value_to_slot_20b ((grub_addr_t) target, noff); + } + break; + + case R_IA64_LTOFF_FPTR22: + case R_IA64_LTOFF22X: + case R_IA64_LTOFF22: + *gpptr = grub_host_to_target64 (addend + sym_addr); + add_value_to_slot_21 ((grub_addr_t) target, + (char *) gpptr - (char *) pe_target); + gpptr++; + break; + + case R_IA64_GPREL22: + add_value_to_slot_21 ((grub_addr_t) target, + addend + sym_addr); + break; + case R_IA64_PCREL64LSB: + *target = grub_host_to_target64 (grub_target_to_host64 (*target) + + addend + sym_addr + - target_section_addr - offset + - image_target->vaddr_offset); + break; + + case R_IA64_SEGREL64LSB: + *target = grub_host_to_target64 (grub_target_to_host64 (*target) + + addend + sym_addr - target_section_addr); + break; + case R_IA64_DIR64LSB: + case R_IA64_FPTR64LSB: + *target = grub_host_to_target64 (grub_target_to_host64 (*target) + + addend + sym_addr); + grub_util_info ("relocating a direct entry to 0x%" + PRIxGRUB_UINT64_T " at the offset 0x%x", + *target, offset); + break; + + /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */ + case R_IA64_LDXMOV: + break; + default: grub_util_error ("unknown relocation type 0x%x", - ELF_R_TYPE (info)); + ELF_R_TYPE (info)); break; } break; +#endif default: grub_util_error ("unknown architecture type %d", image_target->elf_target); @@ -329,7 +546,7 @@ SUFFIX (add_fixup_entry) (struct fixup_block_list **cblock, grub_uint16_t type, b->block_size += 2; } } - else if (b->block_size & (8 - 1)) + else while (b->block_size & (8 - 1)) { /* If not aligned with a 32-bit boundary, add a padding entry. */ @@ -391,9 +608,11 @@ static Elf_Addr SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out, Elf_Addr *section_addresses, Elf_Shdr *sections, Elf_Half section_entsize, Elf_Half num_sections, - const char *strtab, struct image_target_desc *image_target) + const char *strtab, + Elf_Addr jumpers, grub_size_t njumpers, + struct image_target_desc *image_target) { - Elf_Half i; + unsigned i; Elf_Shdr *s; struct fixup_block_list *lst, *lst0; Elf_Addr current_address = 0; @@ -401,8 +620,7 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out, lst = lst0 = xmalloc (sizeof (*lst) + 2 * 0x1000); memset (lst, 0, sizeof (*lst) + 2 * 0x1000); - for (i = 0, s = sections; - i < num_sections; + for (i = 0, s = sections; i < num_sections; i++, s = (Elf_Shdr *) ((char *) s + section_entsize)) if ((s->sh_type == grub_cpu_to_le32 (SHT_REL)) || (s->sh_type == grub_cpu_to_le32 (SHT_RELA))) @@ -470,12 +688,56 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out, image_target); } break; + case EM_IA_64: + switch (ELF_R_TYPE (info)) + { + case R_IA64_PCREL64LSB: + case R_IA64_LDXMOV: + case R_IA64_PCREL21B: + case R_IA64_LTOFF_FPTR22: + case R_IA64_LTOFF22X: + case R_IA64_LTOFF22: + case R_IA64_GPREL22: + case R_IA64_SEGREL64LSB: + break; + + case R_IA64_FPTR64LSB: + case R_IA64_DIR64LSB: +#if 1 + { + Elf_Addr addr; + + addr = section_address + offset; + grub_util_info ("adding a relocation entry for 0x%llx", addr); + current_address + = SUFFIX (add_fixup_entry) (&lst, + GRUB_PE32_REL_BASED_DIR64, + addr, + 0, current_address, + image_target); + } +#endif + break; + default: + grub_util_error ("unknown relocation type 0x%x", + ELF_R_TYPE (info)); + break; + } + break; default: grub_util_error ("unknown machine type 0x%x", image_target->elf_target); } } } + if (image_target->elf_target == EM_IA_64) + for (i = 0; i < njumpers; i++) + current_address = SUFFIX (add_fixup_entry) (&lst, + GRUB_PE32_REL_BASED_DIR64, + jumpers + 8 * i, + 0, current_address, + image_target); + current_address = SUFFIX (add_fixup_entry) (&lst, 0, 0, 1, current_address, image_target); { @@ -637,7 +899,10 @@ SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size, Elf_Off section_offset; Elf_Half section_entsize; grub_size_t kernel_size; + grub_size_t ia64jmp_off = 0, ia64_toff = 0, ia64_got_off = 0; + unsigned ia64jmpnum = 0; Elf_Shdr *symtab_section; + grub_size_t got = 0; *start = 0; @@ -716,23 +981,31 @@ SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size, break; } +#ifdef MKIMAGE_ELF64 + if (image_target->elf_target == EM_IA_64) + { + grub_size_t tramp; + + *kernel_sz = ALIGN_UP (*kernel_sz, 16); + + grub_ia64_dl_get_tramp_got_size (e, &tramp, &got); + tramp *= sizeof (struct ia64_kernel_trampoline); + + ia64_toff = *kernel_sz; + *kernel_sz += ALIGN_UP (tramp, 16); + + ia64jmp_off = *kernel_sz; + ia64jmpnum = SUFFIX (count_funcs) (e, symtab_section, + image_target); + *kernel_sz += 16 * ia64jmpnum; + + ia64_got_off = *kernel_sz; + *kernel_sz += ALIGN_UP (got * sizeof (grub_uint64_t), 16); + } +#endif + if (! symtab_section) grub_util_error ("no symbol table"); - - *start = SUFFIX (relocate_symbols) (e, sections, symtab_section, - section_vaddresses, section_entsize, - num_sections, image_target); - if (*start == 0) - grub_util_error ("start symbol is not defined"); - - /* Resolve addresses in the virtual address space. */ - SUFFIX (relocate_addresses) (e, sections, section_addresses, section_entsize, - num_sections, strtab, image_target); - - *reloc_size = SUFFIX (make_reloc_section) (e, reloc_section, - section_vaddresses, sections, - section_entsize, num_sections, - strtab, image_target); } else { @@ -742,6 +1015,34 @@ SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size, out_img = xmalloc (*kernel_sz + total_module_size); + if (image_target->id == IMAGE_EFI) + { + *start = SUFFIX (relocate_symbols) (e, sections, symtab_section, + section_vaddresses, section_entsize, + num_sections, + (char *) out_img + ia64jmp_off, + ia64jmp_off + + image_target->vaddr_offset, + image_target); + if (*start == 0) + grub_util_error ("start symbol is not defined"); + + /* Resolve addresses in the virtual address space. */ + SUFFIX (relocate_addresses) (e, sections, section_addresses, + section_entsize, + num_sections, strtab, + out_img, ia64_toff, ia64_got_off, + image_target); + + *reloc_size = SUFFIX (make_reloc_section) (e, reloc_section, + section_vaddresses, sections, + section_entsize, num_sections, + strtab, ia64jmp_off + + image_target->vaddr_offset, + 2 * ia64jmpnum + got, + image_target); + } + for (i = 0, s = sections; i < num_sections; i++, s = (Elf_Shdr *) ((char *) s + section_entsize)) From ad6e5cf25fb3cc4a42dcf1eeb2e555ac9300cf91 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 8 May 2011 12:42:08 +0200 Subject: [PATCH 205/406] add missing file --- grub-core/kern/ia64/dl_helper.c | 73 +++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 grub-core/kern/ia64/dl_helper.c diff --git a/grub-core/kern/ia64/dl_helper.c b/grub-core/kern/ia64/dl_helper.c new file mode 100644 index 000000000..9503c49ea --- /dev/null +++ b/grub-core/kern/ia64/dl_helper.c @@ -0,0 +1,73 @@ +/* dl.c - arch-dependent part of loadable module support */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2004,2005,2007,2009 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 + +void +grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + grub_size_t *got) +{ + const Elf_Ehdr *e = ehdr; + grub_size_t cntt = 0, cntg = 0;; + const Elf_Shdr *s; + Elf_Word entsize; + unsigned i; + + /* Find a symbol table. */ + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_SYMTAB) + break; + + if (i == e->e_shnum) + return; + + entsize = s->sh_entsize; + + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_RELA) + { + Elf_Rela *rel, *max; + + for (rel = (Elf_Rela *) ((char *) e + s->sh_offset), + max = rel + s->sh_size / s->sh_entsize; + rel < max; rel++) + switch (ELF_R_TYPE (rel->r_info)) + { + case R_IA64_PCREL21B: + cntt++; + break; + case R_IA64_LTOFF_FPTR22: + case R_IA64_LTOFF22X: + case R_IA64_LTOFF22: + cntg++; + break; + } + } + *tramp = cntt; + *got = cntg; +} + From a988e7aa63948b2e624c1aff8cb63f32d0cee406 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 8 May 2011 14:33:30 +0200 Subject: [PATCH 206/406] Fix 2 incorrect vaddr_offsets --- util/grub-mkimagexx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index 6f68bf1af..9bfb5de75 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -446,8 +446,7 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, grub_uint64_t noff; make_trampoline (tr, addend + sym_addr); noff = ((char *) tr - (char *) pe_target - - target_section_addr - (offset & ~3) - - image_target->vaddr_offset) >> 4; + - target_section_addr - (offset & ~3)) >> 4; tr++; if (noff & ~MASK19) grub_util_error ("trampoline offset too big (%lx)", @@ -461,7 +460,8 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, case R_IA64_LTOFF22: *gpptr = grub_host_to_target64 (addend + sym_addr); add_value_to_slot_21 ((grub_addr_t) target, - (char *) gpptr - (char *) pe_target); + (char *) gpptr - (char *) pe_target + + image_target->vaddr_offset); gpptr++; break; From 7216a1bff3a513549525787b67bd365e8f788569 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 8 May 2011 17:05:47 +0200 Subject: [PATCH 207/406] Set EFI ticks to 1000Hz simplifying much of the code and avoiding cotsly division --- grub-core/Makefile.core.def | 1 - grub-core/kern/efi/efi.c | 16 +++++++++++----- include/grub/efi/time.h | 3 +-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 7bb51adfe..bc7ce5fbe 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -83,7 +83,6 @@ kernel = { noemu_nodist = symlist.c; i386_pc = kern/generic/rtc_get_time_ms.c; - efi = kern/generic/rtc_get_time_ms.c; i386_qemu = kern/generic/rtc_get_time_ms.c; i386_coreboot = kern/generic/rtc_get_time_ms.c; i386_multiboot = kern/generic/rtc_get_time_ms.c; diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index fa1d0c730..c95058733 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -193,8 +194,8 @@ grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size, return grub_error (GRUB_ERR_IO, "set_virtual_address_map failed"); } -grub_uint32_t -grub_get_rtc (void) +grub_uint64_t +grub_rtc_get_time_ms (void) { grub_efi_time_t time; grub_efi_runtime_services_t *r; @@ -204,9 +205,14 @@ grub_get_rtc (void) /* What is possible in this case? */ return 0; - return (((time.minute * 60 + time.second) * 1000 - + time.nanosecond / 1000000) - * GRUB_TICKS_PER_SECOND / 1000); + return ((time.minute * 60 + time.second) * 1000 + + time.nanosecond / 1000000); +} + +grub_uint32_t +grub_get_rtc (void) +{ + return grub_rtc_get_time_ms (); } /* Search the mods section from the PE32/PE32+ image. This code uses diff --git a/include/grub/efi/time.h b/include/grub/efi/time.h index 540f6fc04..51b337309 100644 --- a/include/grub/efi/time.h +++ b/include/grub/efi/time.h @@ -21,8 +21,7 @@ #include -/* This is destined to overflow when one hour passes by. */ -#define GRUB_TICKS_PER_SECOND ((1UL << 31) / 60 / 60 * 2) +#define GRUB_TICKS_PER_SECOND 1000 /* Return the real time in ticks. */ grub_uint32_t EXPORT_FUNC (grub_get_rtc) (void); From fa610088bafb704ae3a0bfdc5d2040542687ae14 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 8 May 2011 17:06:28 +0200 Subject: [PATCH 208/406] Add missing time installation --- grub-core/kern/ia64/efi/init.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/grub-core/kern/ia64/efi/init.c b/grub-core/kern/ia64/efi/init.c index 13a81a66e..6bb4219ac 100644 --- a/grub-core/kern/ia64/efi/init.c +++ b/grub-core/kern/ia64/efi/init.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,7 @@ void grub_machine_init (void) { grub_efi_init (); + grub_install_get_time_ms (grub_rtc_get_time_ms); } void From 44748f71c043e069dbbd7c3d960102df94c8a505 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 8 May 2011 17:06:56 +0200 Subject: [PATCH 209/406] Add explicit byt 0 to workaround a problem with assembler --- grub-core/kern/ia64/efi/startup.S | 1 + 1 file changed, 1 insertion(+) diff --git a/grub-core/kern/ia64/efi/startup.S b/grub-core/kern/ia64/efi/startup.S index fcaf4e189..b5e26a204 100644 --- a/grub-core/kern/ia64/efi/startup.S +++ b/grub-core/kern/ia64/efi/startup.S @@ -45,6 +45,7 @@ _start: . = _start + GRUB_KERNEL_MACHINE_PREFIX VARIABLE(grub_prefix) + .byte 0 /* to be filled by grub-mkimage */ /* From 2679b7249be860ad19d8d9fa4e0c882e2eed207a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 8 May 2011 17:07:40 +0200 Subject: [PATCH 210/406] Fix LTOFF relocation to functions (needed for trampolines) --- grub-core/kern/ia64/dl.c | 4 +++- util/grub-mkimagexx.c | 13 ++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c index 0d1e0d2e6..3904f73b7 100644 --- a/grub-core/kern/ia64/dl.c +++ b/grub-core/kern/ia64/dl.c @@ -250,9 +250,11 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) add_value_to_slot_21 (addr, value - (grub_addr_t) gp); break; - case R_IA64_LTOFF_FPTR22: case R_IA64_LTOFF22X: case R_IA64_LTOFF22: + if (ELF_ST_TYPE (sym->st_info) == STT_FUNC) + value = *(grub_uint64_t *) sym->st_value + rel->r_addend; + case R_IA64_LTOFF_FPTR22: *gpptr = value; add_value_to_slot_21 (addr, (grub_addr_t) gpptr - (grub_addr_t) gp); gpptr++; diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index 9bfb5de75..352291070 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -455,9 +455,20 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, } break; - case R_IA64_LTOFF_FPTR22: case R_IA64_LTOFF22X: case R_IA64_LTOFF22: + { + Elf_Sym *sym; + + sym = (Elf_Sym *) ((char *) e + + grub_target_to_host32 (symtab_section->sh_offset) + + ELF_R_SYM (info) * grub_target_to_host32 (symtab_section->sh_entsize)); + if (ELF_ST_TYPE (sym->st_info) == STT_FUNC) + sym_addr = grub_target_to_host64 (*(grub_uint64_t *) (pe_target + + sym->st_value + - image_target->vaddr_offset)); + } + case R_IA64_LTOFF_FPTR22: *gpptr = grub_host_to_target64 (addend + sym_addr); add_value_to_slot_21 ((grub_addr_t) target, (char *) gpptr - (char *) pe_target From 5a0baa09f29fc1ccd5227e00aea8d409024fddfa Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 8 May 2011 18:28:25 +0200 Subject: [PATCH 211/406] Remove now useless LD script --- grub-core/kern/ia64/efi/elf_ia64_efi.lds | 84 ------------------------ 1 file changed, 84 deletions(-) delete mode 100644 grub-core/kern/ia64/efi/elf_ia64_efi.lds diff --git a/grub-core/kern/ia64/efi/elf_ia64_efi.lds b/grub-core/kern/ia64/efi/elf_ia64_efi.lds deleted file mode 100644 index b6889d4af..000000000 --- a/grub-core/kern/ia64/efi/elf_ia64_efi.lds +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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) - } -} From 7b58e65f2423311b2224cf54d347a0c33eac09bc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 8 May 2011 18:29:37 +0200 Subject: [PATCH 212/406] track function symbols --- grub-core/gensymlist.sh | 10 +++++----- grub-core/kern/dl.c | 22 +++++++++++++--------- include/grub/dl.h | 2 +- include/grub/elf.h | 3 +++ 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/grub-core/gensymlist.sh b/grub-core/gensymlist.sh index 0ab56e9cb..5f402ea87 100644 --- a/grub-core/gensymlist.sh +++ b/grub-core/gensymlist.sh @@ -47,7 +47,7 @@ grub_register_exported_symbols (void) EOF cat < sizeof (tab[0])); for (p = tab; p->name; p++) - grub_dl_register_symbol (p->name, p->addr, 0); + grub_dl_register_symbol (p->name, p->addr, p->isfunc, 0); } EOF diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index aa15cfa24..6353b0d59 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -90,6 +90,7 @@ struct grub_symbol struct grub_symbol *next; const char *name; void *addr; + int isfunc; grub_dl_t mod; /* The module to which this symbol belongs. */ }; typedef struct grub_symbol *grub_symbol_t; @@ -114,21 +115,22 @@ grub_symbol_hash (const char *s) /* Resolve the symbol name NAME and return the address. Return NULL, if not found. */ -static void * +static grub_symbol_t grub_dl_resolve_symbol (const char *name) { grub_symbol_t sym; for (sym = grub_symtab[grub_symbol_hash (name)]; sym; sym = sym->next) if (grub_strcmp (sym->name, name) == 0) - return sym->addr; + return sym; return 0; } /* Register a symbol with the name NAME and the address ADDR. */ grub_err_t -grub_dl_register_symbol (const char *name, void *addr, grub_dl_t mod) +grub_dl_register_symbol (const char *name, void *addr, int isfunc, + grub_dl_t mod) { grub_symbol_t sym; unsigned k; @@ -151,6 +153,7 @@ grub_dl_register_symbol (const char *name, void *addr, grub_dl_t mod) sym->addr = addr; sym->mod = mod; + sym->isfunc = isfunc; k = grub_symbol_hash (name); sym->next = grub_symtab[k]; @@ -371,17 +374,20 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) /* Resolve a global symbol. */ if (sym->st_name != 0 && sym->st_shndx == 0) { - sym->st_value = (Elf_Addr) grub_dl_resolve_symbol (name); - if (! sym->st_value) + grub_symbol_t nsym = grub_dl_resolve_symbol (name); + if (! nsym) return grub_error (GRUB_ERR_BAD_MODULE, "symbol not found: `%s'", name); + sym->st_value = (Elf_Addr) nsym->addr; + if (nsym->isfunc) + sym->st_info = ELF_ST_INFO (bind, STT_FUNC); } else { sym->st_value += (Elf_Addr) grub_dl_get_section_addr (mod, sym->st_shndx); if (bind != STB_LOCAL) - if (grub_dl_register_symbol (name, (void *) sym->st_value, mod)) + if (grub_dl_register_symbol (name, (void *) sym->st_value, 0, mod)) return grub_errno; } break; @@ -398,13 +404,11 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) return grub_errno; desc[0] = (void *) sym->st_value; desc[1] = mod->base; - if (grub_dl_register_symbol (name, (void *) desc, mod)) - return grub_errno; sym->st_value = (grub_addr_t) desc; } #endif if (bind != STB_LOCAL) - if (grub_dl_register_symbol (name, (void *) sym->st_value, mod)) + if (grub_dl_register_symbol (name, (void *) sym->st_value, 1, mod)) return grub_errno; if (grub_strcmp (name, "grub_mod_init") == 0) mod->init = (void (*) (grub_dl_t)) sym->st_value; diff --git a/include/grub/dl.h b/include/grub/dl.h index 6646902d4..319ed5745 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -116,7 +116,7 @@ extern grub_dl_t EXPORT_VAR(grub_dl_head); grub_dl_t EXPORT_FUNC(grub_dl_get) (const char *name); grub_err_t grub_dl_register_symbol (const char *name, void *addr, - grub_dl_t mod); + int isfunc, grub_dl_t mod); grub_err_t grub_arch_dl_check_header (void *ehdr); grub_err_t grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr); diff --git a/include/grub/elf.h b/include/grub/elf.h index b9401f241..a02b90238 100644 --- a/include/grub/elf.h +++ b/include/grub/elf.h @@ -2348,6 +2348,8 @@ typedef Elf32_Xword Elf_Xword; #define ELF_ST_BIND(val) ELF32_ST_BIND(val) #define ELF_ST_TYPE(val) ELF32_ST_TYPE(val) +#define ELF_ST_INFO(a,b) ELF32_ST_INFO(a,b) + #define ELF_R_SYM(val) ELF32_R_SYM(val) #define ELF_R_TYPE(val) ELF32_R_TYPE(val) #define ELF_R_INFO(sym, type) ELF32_R_INFO(sym, type) @@ -2369,6 +2371,7 @@ typedef Elf64_Xword Elf_Xword; #define ELF_ST_BIND(val) ELF64_ST_BIND (val) #define ELF_ST_TYPE(val) ELF64_ST_TYPE (val) +#define ELF_ST_INFO(a,b) ELF64_ST_INFO(a,b) #define ELF_R_SYM(val) ELF64_R_SYM(val) #define ELF_R_TYPE(val) ELF64_R_TYPE(val) #define ELF_R_INFO(sym, type) ELF64_R_INFO(sym, type) From b868b5105219f202cf158e01198d1b7504f050c8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 8 May 2011 20:06:03 +0200 Subject: [PATCH 213/406] remove ia64.moved From 485e1572467c5b0cf29086572e7a40da53292146 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 8 May 2011 20:16:25 +0200 Subject: [PATCH 214/406] Remove 2 useless directories From ea75312f31fb83300d1f00b9630b05fd79bb7650 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 9 May 2011 16:27:09 +0200 Subject: [PATCH 215/406] * util/grub-mkimage.c (main): Explicitely flush and sync the output before closing to ensure that it will be readable by grub-setup. --- ChangeLog | 5 +++++ util/grub-mkimage.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index 540e171cc..bec788b3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-09 Vladimir Serbinenko + + * util/grub-mkimage.c (main): Explicitely flush and sync the output + before closing to ensure that it will be readable by grub-setup. + 2011-05-05 Vladimir Serbinenko * grub-core/loader/efi/appleloader.c (MAKE_PIWG_PATH): New macro. diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 2ba351596..b71fb0420 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -1609,6 +1609,8 @@ main (int argc, char *argv[]) argv + optind, memdisk, config, image_target, note, comp); + fflush (fp); + fsync (fileno (fp)); fclose (fp); if (dir) From 157effb745b4e520327bde2ac3de131f766da095 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 9 May 2011 18:46:51 +0200 Subject: [PATCH 216/406] * grub-core/kern/emu/hostdisk.c (linux_find_partition): Prevent possible overflow. --- ChangeLog | 5 +++++ grub-core/kern/emu/hostdisk.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index bec788b3c..532a3a3b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-09 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (linux_find_partition): Prevent possible + overflow. + 2011-05-09 Vladimir Serbinenko * util/grub-mkimage.c (main): Explicitely flush and sync the output diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 63bca37ee..085048e86 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -550,7 +550,7 @@ struct linux_partition_cache struct linux_partition_cache *linux_partition_cache_list; static int -linux_find_partition (char *dev, unsigned long sector) +linux_find_partition (char *dev, grub_disk_addr_t sector) { size_t len = strlen (dev); const char *format; From fa68d99c4552d02be40c56b787141e340021a4ca Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 9 May 2011 18:48:50 +0200 Subject: [PATCH 217/406] * grub-core/kern/emu/hostdisk.c (open_device): Set data->fd to -1 if openning fails. Reported by: Mark Korenberg. --- ChangeLog | 6 ++++++ grub-core/kern/emu/hostdisk.c | 2 ++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 532a3a3b8..7c924a505 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-05-09 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (open_device): Set data->fd to -1 if + openning fails. + Reported by: Mark Korenberg. + 2011-05-09 Vladimir Serbinenko * grub-core/kern/emu/hostdisk.c (linux_find_partition): Prevent possible diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 085048e86..92882838f 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -678,6 +678,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) } close (data->fd); + data->fd = -1; } /* Open the partition. */ @@ -736,6 +737,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) #endif } close (data->fd); + data->fd = -1; } fd = open (map[disk->id].device, flags); From d8ce9995012629e60c91ed24df01720871558c4f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 9 May 2011 18:50:25 +0200 Subject: [PATCH 218/406] Fix surname spelling in Changelog --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7c924a505..6da178a9f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -348,7 +348,7 @@ (grub_util_biosdisk_open): Don't apply ioctl on non-disk devices. (open_device) Likewise. (grub_util_biosdisk_close): Likewise. - Reported by: Mark Korenberger. + Reported by: Mark Korenberg. 2011-04-10 Alexander Kurtz From dd94a3df9deb3d8fad0950bd3ce180b5a1c262e6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 9 May 2011 18:59:35 +0200 Subject: [PATCH 219/406] * grub-core/kern/emu/hostdisk.c (linux_find_partition): Don't abort on first non-existant partition. --- ChangeLog | 5 +++++ grub-core/kern/emu/hostdisk.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 6da178a9f..5136a915e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-09 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (linux_find_partition): Don't abort + on first non-existant partition. + 2011-05-09 Vladimir Serbinenko * grub-core/kern/emu/hostdisk.c (open_device): Set data->fd to -1 if diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 92882838f..feb2a8ff5 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -596,7 +596,7 @@ linux_find_partition (char *dev, grub_disk_addr_t sector) fd = open (real_dev, O_RDONLY); if (fd == -1) - return 0; + continue; close (fd); start = find_partition_start (real_dev); From 9c9bfc6de9c1c397e857506ed6410e1f1c379b8d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 9 May 2011 19:33:03 +0200 Subject: [PATCH 220/406] * grub-core/term/at_keyboard.c (fetch_key): Make a printf on unknown key into a dprintf. --- ChangeLog | 5 +++++ grub-core/term/at_keyboard.c | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5136a915e..9baad1f9c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-09 Vladimir Serbinenko + + * grub-core/term/at_keyboard.c (fetch_key): Make a printf on + unknown key into a dprintf. + 2011-05-09 Vladimir Serbinenko * grub-core/kern/emu/hostdisk.c (linux_find_partition): Don't abort diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c index 210ac21cc..56aa7275e 100644 --- a/grub-core/term/at_keyboard.c +++ b/grub-core/term/at_keyboard.c @@ -431,11 +431,11 @@ fetch_key (int *is_break) if (!ret) { if (was_ext) - grub_printf ("Unknown key 0xe0+0x%02x from set %d\n", - at_key, current_set); + grub_dprintf ("atkeyb", "Unknown key 0xe0+0x%02x from set %d\n", + at_key, current_set); else - grub_printf ("Unknown key 0x%02x from set %d\n", - at_key, current_set); + grub_dprintf ("atkeyb", "Unknown key 0x%02x from set %d\n", + at_key, current_set); return -1; } return ret; From 52856af26237d211bc413f36b1573d267badad37 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 10 May 2011 09:14:41 +0200 Subject: [PATCH 221/406] * grub-core/loader/efi/chainloader.c (grub_chainloader_unload): Set file_path to 0 for surety. (grub_chainloader_boot): Set exit_data to NULL. Unset the loader once done. (grub_cmd_chainloader): Fix confusing error message if file is empty. --- ChangeLog | 8 ++++++++ grub-core/loader/efi/chainloader.c | 10 ++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9baad1f9c..ed0bc71d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-05-09 Vladimir Serbinenko + + * grub-core/loader/efi/chainloader.c (grub_chainloader_unload): Set + file_path to 0 for surety. + (grub_chainloader_boot): Set exit_data to NULL. + Unset the loader once done. + (grub_cmd_chainloader): Fix confusing error message if file is empty. + 2011-05-09 Vladimir Serbinenko * grub-core/term/at_keyboard.c (fetch_key): Make a printf on diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c index 869b64ced..5dd5adab2 100644 --- a/grub-core/loader/efi/chainloader.c +++ b/grub-core/loader/efi/chainloader.c @@ -57,6 +57,7 @@ grub_chainloader_unload (void) grub_free (file_path); grub_free (cmdline); cmdline = 0; + file_path = 0; grub_dl_unref (my_mod); return GRUB_ERR_NONE; @@ -68,7 +69,7 @@ grub_chainloader_boot (void) grub_efi_boot_services_t *b; grub_efi_status_t status; grub_efi_uintn_t exit_data_size; - grub_efi_char16_t *exit_data; + grub_efi_char16_t *exit_data = NULL; b = grub_efi_system_table->boot_services; status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data); @@ -95,7 +96,7 @@ grub_chainloader_boot (void) if (exit_data) efi_call_1 (b->free_pool, exit_data); - grub_chainloader_unload (); + grub_loader_unset (); return grub_errno; } @@ -238,6 +239,11 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), grub_efi_print_device_path (file_path); size = grub_file_size (file); + if (!size) + { + grub_error (GRUB_ERR_BAD_OS, "file is empty"); + goto fail; + } pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12); status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, From 56dbe7b4855d9aa6dc45d0cf5a8a03c28696f864 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 10 May 2011 10:40:22 +0200 Subject: [PATCH 222/406] * util/grub.d/10_linux.in: Correctly handle the Linux in root. --- ChangeLog | 4 ++++ util/grub.d/10_linux.in | 14 +++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index ed0bc71d6..d36d3441f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-05-10 Vladimir Serbinenko + + * util/grub.d/10_linux.in: Correctly handle the Linux in root. + 2011-05-09 Vladimir Serbinenko * grub-core/loader/efi/chainloader.c (grub_chainloader_unload): Set diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index 1dbcad90c..3c3a2a5d5 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -98,10 +98,17 @@ EOF EOF fi - if [ -z "${prepare_boot_cache}" ]; then - prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" + if [ x$dirname = x/ ]; then + if [ -z "${prepare_root_cache}" ]; then + prepare_root_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/")" + fi + printf '%s\n' "${prepare_root_cache}" + else + if [ -z "${prepare_boot_cache}" ]; then + prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" + fi + printf '%s\n' "${prepare_boot_cache}" fi - printf '%s\n' "${prepare_boot_cache}" message="$(gettext_printf "Loading Linux %s ..." ${version})" cat << EOF echo '$message' @@ -131,6 +138,7 @@ case x`uname -m` in esac prepare_boot_cache= +prepare_root_cache= while [ "x$list" != "x" ] ; do linux=`version_find_latest $list` From 4f7386025b3bc0e5da39e79062aaef02a924a86a Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 09:28:45 -0300 Subject: [PATCH 223/406] Correct expected argument numbers in del addr command. --- grub-core/net/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 636aaefaf..48fb350d2 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -200,7 +200,7 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), { struct grub_net_network_level_interface *inter; - if (argc != 4) + if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); FOR_NET_NETWORK_LEVEL_INTERFACES (inter) From 1893017d440b967cb977888ad1fbc4f4cf2df9a4 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 09:30:26 -0300 Subject: [PATCH 224/406] Mark file as not easily seekable on net open. --- grub-core/net/net.c | 1 + 1 file changed, 1 insertion(+) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 48fb350d2..cdeaa5a32 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -609,6 +609,7 @@ grub_net_file_open_real (struct grub_file *file, const char *name) if ((err = file->device->net->protocol->open (file,name))) goto fail; + file->not_easily_seekable = 1; return GRUB_ERR_NONE; fail: From 4d6374ba7855abc9726d838258ec8093bc1238f1 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 09:32:38 -0300 Subject: [PATCH 225/406] Implement file close in network tranference. Stop receiving packets from card on error. --- grub-core/kern/file.c | 8 ++++++-- grub-core/net/net.c | 26 +++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c index 6e7ed0e57..2b3e9d689 100644 --- a/grub-core/kern/file.c +++ b/grub-core/kern/file.c @@ -27,6 +27,7 @@ grub_ssize_t (*grub_file_net_read) (grub_file_t file, void *buf, grub_size_t len) = NULL; grub_err_t (*grub_file_net_open) (struct grub_file *file, const char *name) = NULL; +grub_err_t (*grub_file_net_close) (grub_file_t file) = NULL; grub_err_t (*grub_file_net_seek) (struct grub_file *file, grub_off_t offset) = NULL; grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX]; @@ -176,8 +177,11 @@ grub_err_t grub_file_close (grub_file_t file) { if (file->device->net) - return grub_errno; - + { + grub_file_net_close (file); + return grub_errno; + } + if (file->fs->close) (file->fs->close) (file); diff --git a/grub-core/net/net.c b/grub-core/net/net.c index cdeaa5a32..6ccf20725 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -619,18 +619,35 @@ fail: } +static grub_err_t +grub_net_file_close_real (grub_file_t file) +{ + grub_net_socket_t sock = file->device->net->socket; + while (sock->packs->first) + { + grub_netbuff_free (sock->packs->first->nb); + grub_net_remove_packet (sock->packs->first); + } + grub_net_socket_unregister (sock); + grub_free (sock); + return GRUB_ERR_NONE; + +} + static grub_err_t receive_packets (struct grub_net_card *card) { /* Maybe should be better have a fixed number of packets for each card and just mark them as used and not used. */ struct grub_net_buff *nb; + grub_err_t err; nb = grub_netbuff_alloc (1500); if (!nb) return grub_errno; - card->driver->recv (card, nb); - return GRUB_ERR_NONE; + if ((err = card->driver->recv (card, nb)) != GRUB_ERR_NONE) + grub_netbuff_free (nb); + return err; } void @@ -642,7 +659,8 @@ grub_net_pool_cards (unsigned time) { start_time = grub_get_time_ms (); while( (grub_get_time_ms () - start_time) < time) - receive_packets (card); + if( receive_packets (card) != GRUB_ERR_NONE) + break; } } @@ -1018,6 +1036,7 @@ GRUB_MOD_INIT(net) grub_net_open = grub_net_open_real; grub_file_net_open = grub_net_file_open_real; + grub_file_net_close = grub_net_file_close_real; grub_file_net_read = grub_net_read_real; grub_file_net_seek = grub_net_seek_real; } @@ -1034,4 +1053,5 @@ GRUB_MOD_FINI(net) grub_net_open = NULL; grub_file_net_read = NULL; grub_file_net_open = NULL; + grub_file_net_close = NULL; } From a5184d629a4411f8c74eeb1b244523ddddf1512e Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 09:45:57 -0300 Subject: [PATCH 226/406] Prevente a bootp packet to be sent on open. --- grub-core/net/drivers/ieee1275/ofnet.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 10de81bc7..ce7ab32a8 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -1,17 +1,23 @@ #include #include #include +#include #include +#include static grub_err_t card_open (struct grub_net_card *dev) { int status; struct grub_ofnetcard_data *data = dev->data; - status = grub_ieee1275_open (data->path,&(data->handle)); + char path[grub_strlen(data->path) + grub_strlen(":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512") + 1]; + /* The full string will prevent a bootp packet to be sent. Just put some valid ip in there. */ + grub_snprintf(path,sizeof(path),"%s%s",data->path,":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512"); + status = grub_ieee1275_open (path,&(data->handle)); if (status) - return grub_error (GRUB_ERR_IO, "couldn't open network card"); + return grub_error (GRUB_ERR_IO, "Couldn't open network card."); + return GRUB_ERR_NONE; } From 0f231af8ae44b6e4efe6b25794db21fbfd270718 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 09:50:18 -0300 Subject: [PATCH 227/406] Implement timeout when receiving packets. --- grub-core/net/drivers/ieee1275/ofnet.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index ce7ab32a8..a7b66261c 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -42,24 +42,29 @@ send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) pack->tail - pack->data, &actual); if (status) - return grub_error (GRUB_ERR_IO, "couldn't send network packet"); + return grub_error (GRUB_ERR_IO, "Couldn't send network packet."); return GRUB_ERR_NONE; } static grub_err_t -get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pack) +get_card_packet (struct grub_net_card *dev, struct grub_net_buff *nb) { int actual, rc; struct grub_ofnetcard_data *data = dev->data; - grub_netbuff_clear(pack); + grub_uint64_t start_time; + grub_netbuff_clear (nb); + start_time = grub_get_time_ms (); do - rc = grub_ieee1275_read (data->handle, pack->data, 1500, &actual); - while (actual <= 0 || rc < 0); - grub_netbuff_put (pack, actual); - - return GRUB_ERR_NONE; + rc = grub_ieee1275_read (data->handle, nb->data, data->mtu, &actual); + while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200)); + if (actual) + { + grub_netbuff_put (nb, actual); + return grub_net_recv_ethernet_packet (nb); + } + return GRUB_ERR_TIMEOUT; } static struct grub_net_card_driver ofdriver = From 70c52f3e248a67ad809c1309095b59cfff9d6628 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 09:54:32 -0300 Subject: [PATCH 228/406] Remove cards with no associated driver. --- grub-core/net/drivers/ieee1275/ofnet.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index a7b66261c..e33622fe2 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -148,10 +148,12 @@ void grub_ofnet_findcards (void) lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; card->default_address = lla; + card->driver = NULL; card->data = ofdata; card->flags = 0; card->name = grub_xasprintf("eth%d",i++); // grub_strdup (alias->name); - grub_net_card_register (card); + grub_net_card_register (card); + return 0; } return 0; } @@ -192,19 +194,24 @@ void grub_ofnet_probecards (void) net.ipv4.masksize = 24; grub_net_add_route ("bootp-router", net, inter); } - grub_free (bootp_pckt); break; - } + } } } + grub_free (bootp_pckt); + } GRUB_MOD_INIT (ofnet) { + struct grub_net_card *card; grub_getbootp = grub_getbootp_real; grub_net_card_driver_register (&ofdriver); grub_ofnet_findcards (); grub_ofnet_probecards (); + FOR_NET_CARDS (card) + if (card->driver == NULL) + grub_net_card_unregister (card); } GRUB_MOD_FINI (ofnet) From 36e2782dba154140c30ba77dabf67cea2df02719 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 09:55:20 -0300 Subject: [PATCH 229/406] Only setup network in the card we booted from. --- grub-core/net/drivers/ieee1275/ofnet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index e33622fe2..4067e36cf 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -171,6 +171,7 @@ void grub_ofnet_probecards (void) grub_bootp_t bootp_pckt; grub_net_network_level_address_t addr; grub_net_network_level_netaddress_t net; + bootp_pckt = grub_getbootp (); /* Assign correspondent driver for each device. */ FOR_NET_CARDS (card) @@ -180,8 +181,7 @@ void grub_ofnet_probecards (void) if (driver->init(card) == GRUB_ERR_NONE) { card->driver = driver; - bootp_pckt = grub_getbootp (); - if (bootp_pckt) + if (bootp_pckt && grub_memcmp(bootp_pckt->chaddr,card->default_address.mac,6) == 0) { addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; addr.ipv4 = bootp_pckt->yiaddr; From 0696f08f9238087edf5c1f1b91779f7515e7aeb5 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 14:07:20 -0300 Subject: [PATCH 230/406] Prevente error in broken cards by limiting data size. --- grub-core/net/tftp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index cafb30585..6cc281085 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -126,8 +126,12 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) { data->block++; - if (nb->tail - nb->data < 1024) + unsigned size = nb->tail - nb->data; + if (size < 1024) sock->status = 2; + /* Prevent garbage in broken cards. */ + if (size > 1024) + grub_netbuff_unput (nb, size - 1024); } else grub_netbuff_clear(nb); From 31b5172bbd3cfa83f0cd9d83fce18a21e2796048 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 14:07:54 -0300 Subject: [PATCH 231/406] Implement close in TFTP --- grub-core/net/tftp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 6cc281085..13bd87d15 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -157,7 +157,8 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) static grub_err_t tftp_close (struct grub_file *file __attribute__ ((unused))) { - return 0; + grub_free (file->device->net->socket->data); + return GRUB_ERR_NONE; } static struct grub_net_app_protocol grub_tftp_protocol = From 8db3b0eca9704c93fde8e1b0d41741f2299cb2b3 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 14:08:18 -0300 Subject: [PATCH 232/406] Remove unused file --- include/grub/net/disknet.h | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 include/grub/net/disknet.h diff --git a/include/grub/net/disknet.h b/include/grub/net/disknet.h deleted file mode 100644 index 59aa2a320..000000000 --- a/include/grub/net/disknet.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef GRUB_DISKNET_HEADER -#define GRUB_DISKNET_HEADER 1 - void grub_disknet_init(void); - void grub_disknet_fini(void); -#endif /* ! GRUB_NET_HEADER */ From d8123bfb54e92aff473edaac87b535cb81e1f778 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 12 May 2011 13:20:43 -0300 Subject: [PATCH 233/406] Correct some compile erros. --- grub-core/Makefile.core.def | 2 +- grub-core/kern/ieee1275/openfw.c | 1 - grub-core/net/drivers/ieee1275/ofnet.c | 1 + include/grub/net.h | 4 +--- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index e242d8ece..e1e1623e6 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1503,7 +1503,7 @@ module = { module = { name = emunet; emu = net/drivers/emu/emunet.c; - enable = ieee1275; + enable = emu; }; module = { diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index fed4f7e76..3473fe362 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -25,7 +25,6 @@ #include #include #include -#include #include grub_bootp_t (*grub_getbootp) (void); diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 4067e36cf..44738c67a 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/include/grub/net.h b/include/grub/net.h index 59974b94f..cb6db06d8 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -434,7 +434,5 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, void grub_net_pool_cards (unsigned time); -void -hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str); - +extern grub_err_t (*EXPORT_VAR (grub_file_net_close)) (grub_file_t file); #endif /* ! GRUB_NET_HEADER */ From 48ac061ab6f4d685a1c93af59a0c366d3721a84d Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 12 May 2011 15:40:54 -0300 Subject: [PATCH 234/406] Prevent "incompatible license" error. --- grub-core/net/drivers/ieee1275/ofnet.c | 2 ++ grub-core/net/net.c | 2 ++ grub-core/net/tftp.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 44738c67a..cb3882ceb 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -6,6 +6,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t card_open (struct grub_net_card *dev) { diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 6ccf20725..be5279c99 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + struct grub_net_route { struct grub_net_route *next; diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 13bd87d15..278f6ed14 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -9,6 +9,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t tftp_open (struct grub_file *file, const char *filename) { From 9b44fecaa65643896bfd95fc76a5a782b802e416 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 15:17:02 +0200 Subject: [PATCH 235/406] * grub-core/kern/mips/dl.c (grub_arch_dl_relocate_symbols): Handle R_MIPS_JALR since it's used by newer compiler. --- ChangeLog | 5 +++++ grub-core/kern/mips/dl.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index d36d3441f..944fcb4ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-13 Vladimir Serbinenko + + * grub-core/kern/mips/dl.c (grub_arch_dl_relocate_symbols): Handle + R_MIPS_JALR since it's used by newer compiler. + 2011-05-10 Vladimir Serbinenko * util/grub.d/10_linux.in: Correctly handle the Linux in root. diff --git a/grub-core/kern/mips/dl.c b/grub-core/kern/mips/dl.c index 485955e7f..e17e9f30b 100644 --- a/grub-core/kern/mips/dl.c +++ b/grub-core/kern/mips/dl.c @@ -213,6 +213,8 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) = sizeof (grub_uint32_t) * (gpptr - gp); gpptr++; break; + case R_MIPS_JALR: + break; default: { grub_free (gp); From a298aa046c528b8c4a5a73fb5dd92d24bdd453f6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 15:20:16 +0200 Subject: [PATCH 236/406] * grub-core/boot/mips/startup_raw.S: Use jalr rather than bal to call grub_decompress_core since later would fail if grub_decompress_core is too far. --- ChangeLog | 6 ++++++ grub-core/boot/mips/startup_raw.S | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 944fcb4ab..d1a1d6f05 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-05-13 Vladimir Serbinenko + + * grub-core/boot/mips/startup_raw.S: Use jalr rather than bal to call + grub_decompress_core since later would fail if grub_decompress_core + is too far. + 2011-05-13 Vladimir Serbinenko * grub-core/kern/mips/dl.c (grub_arch_dl_relocate_symbols): Handle diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index c41ce8257..2e874e251 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -170,9 +170,11 @@ argdone: */ move $s6, $a3 - lui $sp, %hi(_start - 256) + lui $t0, %hi(EXT_C(grub_decompress_core)) + addiu $t0, $t0, %lo(EXT_C(grub_decompress_core)) - bal EXT_C(grub_decompress_core) + lui $sp, %hi(_start - 256) + jalr $t0 addiu $sp, $sp, %lo(_start - 256) move $a0, $s1 From 60ddfad3dab5c5eb479227d287f83ee66f67ebe4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 15:35:06 +0200 Subject: [PATCH 237/406] * grub-core/boot/mips/startup_raw.S: Flush cache after loading decompressor. --- ChangeLog | 5 +++++ grub-core/boot/mips/startup_raw.S | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/ChangeLog b/ChangeLog index d1a1d6f05..ede161faf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-13 Vladimir Serbinenko + + * grub-core/boot/mips/startup_raw.S: Flush cache after loading + decompressor. + 2011-05-13 Vladimir Serbinenko * grub-core/boot/mips/startup_raw.S: Use jalr rather than bal to call diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index 2e874e251..6ba04c12f 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -150,6 +150,13 @@ argdone: b 1b addiu $t1, $t1, 1 2: + lui $a0, %hi(base) + addiu $a0, $a0, %lo(base) + lui $a1, %hi(_end) + addiu $a1, %lo(_end) + subu $a1,$a1,$a0 + +#include "../../kern/mips/cache_flush.S" /* Decompress the payload. */ lui $a0, %hi(__bss_start) From 11d86592b7bec1c7ffa746bb1bf384b3cfa7953b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 15:38:42 +0200 Subject: [PATCH 238/406] Adjust mips/dl.c for bigendian --- grub-core/kern/mips/dl.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/grub-core/kern/mips/dl.c b/grub-core/kern/mips/dl.c index e17e9f30b..e4ce12157 100644 --- a/grub-core/kern/mips/dl.c +++ b/grub-core/kern/mips/dl.c @@ -34,7 +34,7 @@ grub_arch_dl_check_header (void *ehdr) Elf_Ehdr *e = ehdr; /* Check the magic numbers. */ -#ifdef WORDS_BIGENDIAN +#ifdef GRUB_CPU_WORDS_BIGENDIAN if (e->e_ident[EI_CLASS] != ELFCLASS32 || e->e_ident[EI_DATA] != ELFDATA2MSB || e->e_machine != EM_MIPS) @@ -144,14 +144,14 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) rel < max; rel++) { - Elf_Word *addr; + grub_uint8_t *addr; Elf_Sym *sym; if (seg->size < rel->r_offset) return grub_error (GRUB_ERR_BAD_MODULE, "reloc offset is out of the segment"); - addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset); + addr = (grub_uint8_t *) ((char *) seg->addr + rel->r_offset); sym = (Elf_Sym *) ((char *) mod->symtab + entsize * ELF_R_SYM (rel->r_info)); if (sym->st_value == (grub_addr_t) &__gnu_local_gp_dummy) @@ -163,7 +163,11 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) { grub_uint32_t value; Elf_Rel *rel2; - + +#ifdef GRUB_CPU_WORDS_BIGENDIAN + addr += 2; +#endif + /* Handle partner lo16 relocation. Lower part is treated as signed. Hence add 0x8000 to compensate. */ @@ -175,13 +179,20 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) && ELF_R_TYPE (rel2->r_info) == R_MIPS_LO16) { value += *(grub_int16_t *) - ((char *) seg->addr + rel2->r_offset); + ((char *) seg->addr + rel2->r_offset +#ifdef GRUB_CPU_WORDS_BIGENDIAN + + 2 +#endif + ); break; } *(grub_uint16_t *) addr = (value >> 16) & 0xffff; } break; case R_MIPS_LO16: +#ifdef GRUB_CPU_WORDS_BIGENDIAN + addr += 2; +#endif *(grub_uint16_t *) addr += (sym->st_value) & 0xffff; break; case R_MIPS_32: @@ -208,6 +219,9 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) case R_MIPS_GOT16: case R_MIPS_CALL16: /* FIXME: reuse*/ +#ifdef GRUB_CPU_WORDS_BIGENDIAN + addr += 2; +#endif *gpptr = sym->st_value + *(grub_uint16_t *) addr; *(grub_uint16_t *) addr = sizeof (grub_uint32_t) * (gpptr - gp); From 8906c3dd40f9a0fa64bc91f32b42f3078a57323b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 16:36:05 +0200 Subject: [PATCH 239/406] sgi support --- conf/Makefile.common | 2 +- configure.ac | 3 + gentpl.py | 8 +- grub-core/Makefile.am | 10 +- grub-core/Makefile.core.def | 45 +++- grub-core/commands/arc/lsdev.c | 53 ++++ grub-core/disk/arc/arcdisk.c | 232 +++++++++++++++++ grub-core/kern/mips/arc/init.c | 203 +++++++++++++++ grub-core/kern/mips/init.c | 18 ++ grub-core/kern/mips/yeeloong/init.c | 17 +- grub-core/lib/arc/datetime.c | 48 ++++ grub-core/mmap/mips/{yeeloong => }/uppermem.c | 2 +- grub-core/partmap/dvh.c | 124 +++++++++ grub-core/term/arc/console.c | 123 +++++++++ grub-core/term/terminfo.c | 19 +- include/grub/arc/arc.h | 244 ++++++++++++++++++ include/grub/arc/console.h | 31 +++ include/grub/disk.h | 3 +- include/grub/mips/arc/kernel.h | 2 + include/grub/mips/arc/memory.h | 42 +++ include/grub/mips/arc/time.h | 0 include/grub/mips/kernel.h | 30 +++ include/grub/mips/loongson.h | 7 +- include/grub/mips/memory.h | 61 ++++- include/grub/mips/mips.h | 30 +++ include/grub/mips/time.h | 33 ++- include/grub/mips/yeeloong/kernel.h | 32 +-- include/grub/mips/yeeloong/memory.h | 34 +-- include/grub/mips/yeeloong/time.h | 12 +- include/grub/offsets.h | 12 + util/grub-mkimage.c | 93 ++++++- 31 files changed, 1453 insertions(+), 120 deletions(-) create mode 100644 grub-core/commands/arc/lsdev.c create mode 100644 grub-core/disk/arc/arcdisk.c create mode 100644 grub-core/kern/mips/arc/init.c create mode 100644 grub-core/lib/arc/datetime.c rename grub-core/mmap/mips/{yeeloong => }/uppermem.c (98%) create mode 100644 grub-core/partmap/dvh.c create mode 100644 grub-core/term/arc/console.c create mode 100644 include/grub/arc/arc.h create mode 100644 include/grub/arc/console.h create mode 100644 include/grub/mips/arc/kernel.h create mode 100644 include/grub/mips/arc/memory.h create mode 100644 include/grub/mips/arc/time.h create mode 100644 include/grub/mips/kernel.h create mode 100644 include/grub/mips/mips.h diff --git a/conf/Makefile.common b/conf/Makefile.common index 5aa13cdd6..13963d5f3 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -28,10 +28,10 @@ endif if COND_mips_yeeloong CFLAGS_PLATFORM += -mexplicit-relocs CPPFLAGS_PLATFORM = -DUSE_ASCII_FAILBACK - CCASFLAGS_PLATFORM = -march=mips3 endif if COND_mips CFLAGS_PLATFORM += -mflush-func=grub_cpu_flush_cache + CCASFLAGS_PLATFORM = -march=mips3 endif if COND_sparc64_ieee1275 CFLAGS_PLATFORM += -mno-app-regs diff --git a/configure.ac b/configure.ac index 811bd992d..28c13b511 100644 --- a/configure.ac +++ b/configure.ac @@ -124,6 +124,7 @@ case "$target_cpu"-"$platform" in sparc64-ieee1275) ;; mips-qemu-mips) ;; mips-yeeloong) ;; + mips-arc) ;; *-emu) ;; *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;; esac @@ -158,6 +159,7 @@ case "$platform" in emu) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_EMU=1" ;; yeeloong) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_YEELOONG=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;; qemu-mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_QEMU_MIPS=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;; + mips-arc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_ARC=1 -DGRUB_MACHINE_ARC=1" ;; esac case "$target_cpu" in mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS=1" ;; @@ -952,6 +954,7 @@ AM_CONDITIONAL([COND_i386_multiboot], [test x$target_cpu = xi386 -a x$platform = AM_CONDITIONAL([COND_x86_64_efi], [test x$target_cpu = xx86_64 -a x$platform = xefi]) AM_CONDITIONAL([COND_mips_yeeloong], [test x$target_cpu = xmips -a x$platform = xyeeloong]) AM_CONDITIONAL([COND_mips_qemu_mips], [test x$target_cpu = xmips -a x$platform = xqemu_mips]) +AM_CONDITIONAL([COND_mips_arc], [test x$target_cpu = xmips -a x$platform = xarc]) AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275]) AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275]) AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips]) diff --git a/gentpl.py b/gentpl.py index a42a60667..c8d81cfba 100644 --- a/gentpl.py +++ b/gentpl.py @@ -7,7 +7,7 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_multiboot", "i386_ieee1275", "x86_64_efi", "mips_yeeloong", "sparc64_ieee1275", - "powerpc_ieee1275" ] + "powerpc_ieee1275", "mips_arc" ] GROUPS = {} @@ -17,7 +17,7 @@ GROUPS["common"] = GRUB_PLATFORMS[:] GROUPS["i386"] = [ "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_multiboot", "i386_ieee1275" ] GROUPS["x86_64"] = [ "x86_64_efi" ] GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"] -GROUPS["mips"] = [ "mips_yeeloong" ] +GROUPS["mips"] = [ "mips_yeeloong", "mips_arc" ] GROUPS["sparc64"] = [ "sparc64_ieee1275" ] GROUPS["powerpc"] = [ "powerpc_ieee1275" ] @@ -30,7 +30,7 @@ GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu") # Groups based on hardware features GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_yeeloong"]; GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi") -GROUPS["pci"] = GROUPS["x86"] + GROUPS["mips"] +GROUPS["pci"] = GROUPS["x86"] + ["mips_yeeloong"] GROUPS["usb"] = GROUPS["pci"] # If gfxterm is main output console integrate it into kernel @@ -39,7 +39,7 @@ GROUPS["videomodules"] = GRUB_PLATFORMS[:]; for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i) # Similar for terminfo -GROUPS["terminfoinkernel"] = ["mips_yeeloong"] + GROUPS["ieee1275"]; +GROUPS["terminfoinkernel"] = ["mips_yeeloong", "mips_arc"] + GROUPS["ieee1275"]; GROUPS["terminfomodule"] = GRUB_PLATFORMS[:]; for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i) diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 94f7f3ffe..234bd3ee8 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -125,9 +125,17 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h endif +if COND_mips +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/kernel.h +endif + +if COND_mips_arc +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arc/arc.h +endif + if COND_mips_yeeloong KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/cache.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index f4d38149d..e27d375c4 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -35,6 +35,7 @@ kernel = { mips_yeeloong_ldflags = '-Wl,-Ttext,0x80200000'; powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000'; sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; + mips_arc_ldflags = '-Wl,-Ttext,0x8a000000'; mips_yeeloong_cppflags = '-DUSE_ASCII_FAILBACK'; i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; @@ -48,7 +49,7 @@ kernel = { i386_ieee1275_startup = kern/i386/ieee1275/startup.S; i386_coreboot_startup = kern/i386/coreboot/startup.S; i386_multiboot_startup = kern/i386/coreboot/startup.S; - mips_yeeloong_startup = kern/mips/startup.S; + mips_startup = kern/mips/startup.S; sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S; powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S; @@ -81,7 +82,7 @@ kernel = { i386_qemu = kern/generic/rtc_get_time_ms.c; i386_coreboot = kern/generic/rtc_get_time_ms.c; i386_multiboot = kern/generic/rtc_get_time_ms.c; - mips_yeeloong = kern/generic/rtc_get_time_ms.c; + mips = kern/generic/rtc_get_time_ms.c; ieee1275 = disk/ieee1275/ofdisk.c; ieee1275 = kern/ieee1275/cmain.c; @@ -136,13 +137,18 @@ kernel = { i386_ieee1275 = kern/ieee1275/init.c; + mips = kern/mips/cache.S; + mips = kern/mips/dl.c; + mips = kern/mips/init.c; + + mips_arc = kern/mips/arc/init.c; + mips_arc = term/arc/console.c; + mips_arc = disk/arc/arcdisk.c; + mips_yeeloong = term/ns8250.c; mips_yeeloong = bus/bonito.c; mips_yeeloong = bus/cs5536.c; mips_yeeloong = bus/pci.c; - mips_yeeloong = kern/mips/cache.S; - mips_yeeloong = kern/mips/dl.c; - mips_yeeloong = kern/mips/init.c; mips_yeeloong = kern/mips/yeeloong/init.c; mips_yeeloong = term/at_keyboard.c; mips_yeeloong = term/serial.c; @@ -297,10 +303,12 @@ image = { cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed'; - mips_cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x80200000'; + mips_arc_cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x8a000000'; + mips_yeeloong_cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x80200000'; objcopyflags = '-O binary'; - ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; + mips_yeeloong_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; + mips_arc_ldflags = '-static-libgcc -Wl,-Ttext,0x89f00000'; ldadd = '-lgcc'; cflags = '-static-libgcc'; enable = mips; @@ -311,10 +319,12 @@ image = { mips = boot/mips/startup_raw.S; common = boot/decompressor/none.c; - mips_cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x80200000'; + mips_arc_cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x8a000000'; + mips_yeeloong_cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x80200000'; objcopyflags = '-O binary'; - ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; + mips_yeeloong_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; + mips_arc_ldflags = '-static-libgcc -Wl,-Ttext,0x89f00000'; ldadd = '-lgcc'; cflags = '-static-libgcc'; enable = mips; @@ -408,6 +418,13 @@ module = { emu_condition = COND_GRUB_EMU_PCI; }; +module = { + name = lsdev; + common = commands/arc/lsdev.c; + + enable = mips_arc; +}; + library = { name = libgnulib.a; common = gnulib/regex.c; @@ -1117,6 +1134,7 @@ module = { x86_efi = lib/efi/datetime.c; sparc64_ieee1275 = lib/ieee1275/datetime.c; powerpc_ieee1275 = lib/ieee1275/datetime.c; + mips_arc = lib/arc/datetime.c; enable = noemu; }; @@ -1228,10 +1246,10 @@ module = { x86_efi = mmap/efi/mmap.c; - mips_yeeloong = mmap/mips/yeeloong/uppermem.c; + mips = mmap/mips/uppermem.c; enable = x86; - enable = mips_yeeloong; + enable = mips; }; module = { @@ -1305,6 +1323,11 @@ module = { common = partmap/sun.c; }; +module = { + name = part_dvh; + common = partmap/dvh.c; +}; + module = { name = part_bsd; common = partmap/bsdlabel.c; diff --git a/grub-core/commands/arc/lsdev.c b/grub-core/commands/arc/lsdev.c new file mode 100644 index 000000000..5d4b0cd09 --- /dev/null +++ b/grub-core/commands/arc/lsdev.c @@ -0,0 +1,53 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_err_t +grub_cmd_lsdev (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + auto int hook (const char *name, const struct grub_arc_component *comp); + int hook (const char *name, const struct grub_arc_component *comp __attribute__ ((unused))) + { + grub_printf ("%s\n", name); + return 0; + } + grub_arc_iterate_devs (hook, 0); + return 0; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lsdev) +{ + cmd = grub_register_command ("lsdev", grub_cmd_lsdev, "", + N_("List devices.")); +} + +GRUB_MOD_FINI(lsdev) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/disk/arc/arcdisk.c b/grub-core/disk/arc/arcdisk.c new file mode 100644 index 000000000..c3b98a52e --- /dev/null +++ b/grub-core/disk/arc/arcdisk.c @@ -0,0 +1,232 @@ +/* ofdisk.c - Open Firmware disk access. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2004,2006,2007,2008,2009 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 unsigned last_handle = 0; +static char *last_path = NULL; + +static int +grub_arcdisk_iterate (int (*hook_in) (const char *name)) +{ + auto int hook (const char *name, const struct grub_arc_component *comp); + int hook (const char *name, const struct grub_arc_component *comp) + { + if (!(comp->type == GRUB_ARC_COMPONENT_TYPE_DISK + || comp->type == GRUB_ARC_COMPONENT_TYPE_DISK + || comp->type == GRUB_ARC_COMPONENT_TYPE_TAPE)) + return 0; + return hook_in (name); + } + return grub_arc_iterate_devs (hook, 1); +} + +#define RAW_SUFFIX "partition(10)" + +static grub_err_t +reopen (const char *name) +{ + unsigned handle; + + if (last_path && grub_strcmp (last_path, name) == 0) + { + grub_dprintf ("arcdisk", "using already opened %s\n", name); + return GRUB_ERR_NONE; + } + if (GRUB_ARC_FIRMWARE_VECTOR->open (name, 0, &handle)) + { + grub_dprintf ("arcdisk", "couldn't open %s\n", name); + return grub_error (GRUB_ERR_IO, "couldn't open %s", name); + } + if (last_path) + { + GRUB_ARC_FIRMWARE_VECTOR->close (last_handle); + grub_free (last_path); + last_path = NULL; + last_handle = 0; + } + last_path = grub_strdup (name); + if (!last_path) + return grub_errno; + last_handle = handle; + grub_dprintf ("arcdisk", "opened %s\n", name); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_arcdisk_open (const char *name, grub_disk_t disk) +{ + char *fullname, *optr; + const char *iptr; + int state = 0; + grub_err_t err; + int r; + struct grub_arc_fileinfo info; + if (grub_memcmp (name, "arc/", 4) != 0) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not arc device"); + fullname = grub_malloc (2 * grub_strlen (name) + sizeof (RAW_SUFFIX)); + if (!fullname) + return grub_errno; + optr = fullname; + for (iptr = name + 4; *iptr; iptr++) + if (state == 0) + { + if (!grub_isdigit (*iptr)) + *optr++ = *iptr; + else + { + *optr++ = '('; + *optr++ = *iptr; + state = 1; + } + } + else + { + if (grub_isdigit (*iptr)) + *optr++ = *iptr; + else + { + *optr++ = ')'; + state = 0; + } + } + if (state) + *optr++ = ')'; + grub_memcpy (optr, RAW_SUFFIX, sizeof (RAW_SUFFIX)); + disk->data = fullname; + grub_dprintf ("arcdisk", "opening %s\n", fullname); + err = reopen (fullname); + if (err) + return err; + + r = GRUB_ARC_FIRMWARE_VECTOR->getfileinformation (last_handle, &info); + if (r) + { + grub_uint64_t res = 0; + int i; + + grub_dprintf ("arcdisk", "couldn't retrieve size: %d\n", r); + for (i = 40; i >= 9; i--) + { + grub_uint64_t pos = res | (1ULL << i); + char buf[512]; + long unsigned count = 0; + grub_dprintf ("arcdisk", + "seek to 0x%" PRIxGRUB_UINT64_T "\n", pos); + if (GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0)) + continue; + if (GRUB_ARC_FIRMWARE_VECTOR->read (last_handle, buf, + 0x200, &count)) + continue; + if (count == 0) + continue; + res |= (1ULL << i); + } + grub_dprintf ("arcdisk", + "determined disk size 0x%" PRIxGRUB_UINT64_T "\n", res); + disk->total_sectors = (res + 0x200) >> 9; + } + else + disk->total_sectors = (info.end >> 9); + disk->id = 0; /* XXX */ + return GRUB_ERR_NONE; +} + +static void +grub_arcdisk_close (grub_disk_t disk) +{ + grub_free (disk->data); +} + +static grub_err_t +grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + grub_err_t err; + grub_uint64_t pos = sector << 9; + unsigned long count; + grub_uint64_t totl = size << 9; + int r; + + err = reopen (disk->data); + if (err) + return err; + r = GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0); + if (r) + { + grub_dprintf ("arcdisk", "seek to 0x%" PRIxGRUB_UINT64_T " failed: %d\n", + pos, r); + return grub_error (GRUB_ERR_IO, "couldn't seek"); + } + + while (totl) + { + if (GRUB_ARC_FIRMWARE_VECTOR->read (last_handle, buf, + totl, &count)) + return grub_error (GRUB_ERR_READ_ERROR, "read failed"); + totl -= count; + buf += count; + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_arcdisk_write (grub_disk_t disk __attribute ((unused)), + grub_disk_addr_t sector __attribute ((unused)), + grub_size_t size __attribute ((unused)), + const char *buf __attribute ((unused))) +{ + return GRUB_ERR_NOT_IMPLEMENTED_YET; +} + +static struct grub_disk_dev grub_arcdisk_dev = + { + .name = "arcdisk", + .id = GRUB_DISK_DEVICE_ARCDISK_ID, + .iterate = grub_arcdisk_iterate, + .open = grub_arcdisk_open, + .close = grub_arcdisk_close, + .read = grub_arcdisk_read, + .write = grub_arcdisk_write, + .next = 0 + }; + +void +grub_arcdisk_init (void) +{ + grub_disk_dev_register (&grub_arcdisk_dev); +} + +void +grub_arcdisk_fini (void) +{ + if (last_path) + { + GRUB_ARC_FIRMWARE_VECTOR->close (last_handle); + grub_free (last_path); + last_path = NULL; + last_handle = 0; + } + + grub_disk_dev_unregister (&grub_arcdisk_dev); +} diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c new file mode 100644 index 000000000..85d8b26f5 --- /dev/null +++ b/grub-core/kern/mips/arc/init.c @@ -0,0 +1,203 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009,2010 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 +#include + +const char *type_names[] = { +#ifdef GRUB_CPU_WORDS_BIGENDIAN + NULL, +#endif + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "eisa", "tc", "scsi", "dti", "multi", "disk", "tape", "cdrom", "worm", + "serial", "net", "video", "par", "point", "key", "audio", "other", + "rdisk", "fdisk", "tape", "modem", "monitor", "print", "pointer", + "keyboard", "term", "other", "line", "network", NULL +}; + +static int +iterate_rec (const char *prefix, const struct grub_arc_component *parent, + int (*hook) (const char *name, + const struct grub_arc_component *comp), + int alt_names) +{ + const struct grub_arc_component *comp; + FOR_ARC_CHILDREN(comp, parent) + { + char *name; + const char *cname = NULL; + if (comp->type < ARRAY_SIZE (type_names)) + cname = type_names[comp->type]; + if (!cname) + cname = "unknown"; + if (alt_names) + name = grub_xasprintf ("%s/%s%d", prefix, cname, comp->key); + else + name = grub_xasprintf ("%s%s(%d)", prefix, cname, comp->key); + if (!name) + return 1; + if (hook (name, comp)) + { + grub_free (name); + return 1; + } + if (iterate_rec ((parent ? name : prefix), comp, hook, alt_names)) + { + grub_free (name); + return 1; + } + grub_free (name); + } + return 0; +} + +int +grub_arc_iterate_devs (int (*hook) (const char *name, + const struct grub_arc_component *comp), + int alt_names) +{ + return iterate_rec ((alt_names ? "arc" : ""), NULL, hook, alt_names); +} + +grub_err_t +grub_machine_mmap_iterate (grub_memory_hook_t hook) +{ + struct grub_arc_memory_descriptor *cur = NULL; + while (1) + { + grub_memory_type_t type; + cur = GRUB_ARC_FIRMWARE_VECTOR->getmemorydescriptor (cur); + if (!cur) + return GRUB_ERR_NONE; + switch (cur->type) + { + case GRUB_ARC_MEMORY_EXCEPTION_BLOCK: + case GRUB_ARC_MEMORY_SYSTEM_PARAMETER_BLOCK: + case GRUB_ARC_MEMORY_FW_PERMANENT: + default: + type = GRUB_MEMORY_RESERVED; + break; + + case GRUB_ARC_MEMORY_FW_TEMPORARY: + case GRUB_ARC_MEMORY_FREE: + case GRUB_ARC_MEMORY_LOADED: + case GRUB_ARC_MEMORY_FREE_CONTIGUOUS: + type = GRUB_MEMORY_AVAILABLE; + break; + case GRUB_ARC_MEMORY_BADRAM: + type = GRUB_MEMORY_BADRAM; + break; + } + if (hook (((grub_uint64_t) cur->start_page) << 12, + ((grub_uint64_t) cur->num_pages) << 12, type)) + return GRUB_ERR_NONE; + } +} + +void +grub_machine_init (void) +{ + struct grub_arc_memory_descriptor *cur = NULL; + + grub_console_init_early (); + + /* FIXME: measure this. */ + grub_arch_cpuclock = 64000000; + grub_install_get_time_ms (grub_rtc_get_time_ms); + + while (1) + { + grub_uint64_t start, end; + cur = GRUB_ARC_FIRMWARE_VECTOR->getmemorydescriptor (cur); + if (!cur) + break; + if (cur->type != GRUB_ARC_MEMORY_FREE + && cur->type != GRUB_ARC_MEMORY_LOADED + && cur->type != GRUB_ARC_MEMORY_FREE_CONTIGUOUS) + continue; + start = ((grub_uint64_t) cur->start_page) << 12; + end = ((grub_uint64_t) cur->num_pages) << 12; + end += start; + if ((grub_uint64_t) end > (GRUB_KERNEL_MIPS_ARC_LINK_ADDR & 0x1fffffff)) + end = (GRUB_KERNEL_MIPS_ARC_LINK_ADDR & 0x1fffffff); + if (end > start) + grub_mm_init_region ((void *) (grub_addr_t) (start | 0x80000000), + end - start); + } + + grub_console_init_lately (); + + grub_arcdisk_init (); +} + +void +grub_machine_fini (void) +{ +} + +void +grub_halt (void) +{ + GRUB_ARC_FIRMWARE_VECTOR->powerdown (); + + grub_millisleep (1500); + + grub_printf ("Shutdown failed\n"); + grub_refresh (); + while (1); +} + +void +grub_exit (void) +{ + GRUB_ARC_FIRMWARE_VECTOR->exit (); + + grub_millisleep (1500); + + grub_printf ("Exit failed\n"); + grub_refresh (); + while (1); +} + +void +grub_reboot (void) +{ + GRUB_ARC_FIRMWARE_VECTOR->restart (); + + grub_millisleep (1500); + + grub_printf ("Reboot failed\n"); + grub_refresh (); + while (1); +} + diff --git a/grub-core/kern/mips/init.c b/grub-core/kern/mips/init.c index f220108d4..3b08d5606 100644 --- a/grub-core/kern/mips/init.c +++ b/grub-core/kern/mips/init.c @@ -18,6 +18,24 @@ #include #include +#include +#include + +/* FIXME: use interrupt to count high. */ +grub_uint64_t +grub_get_rtc (void) +{ + static grub_uint32_t high = 0; + static grub_uint32_t last = 0; + grub_uint32_t low; + + asm volatile ("mfc0 %0, " GRUB_CPU_MIPS_COP0_TIMER_COUNT : "=r" (low)); + if (low < last) + high++; + last = low; + + return (((grub_uint64_t) high) << 32) | low; +} void grub_machine_set_prefix (void) diff --git a/grub-core/kern/mips/yeeloong/init.c b/grub-core/kern/mips/yeeloong/init.c index 7a48d69f5..426e7eabb 100644 --- a/grub-core/kern/mips/yeeloong/init.c +++ b/grub-core/kern/mips/yeeloong/init.c @@ -31,6 +31,7 @@ #include #include #include +#include extern void grub_video_sm712_init (void); extern void grub_video_init (void); @@ -43,22 +44,6 @@ extern void grub_terminfo_init (void); extern void grub_keylayouts_init (void); extern void grub_boot_init (void); -/* FIXME: use interrupt to count high. */ -grub_uint64_t -grub_get_rtc (void) -{ - static grub_uint32_t high = 0; - static grub_uint32_t last = 0; - grub_uint32_t low; - - asm volatile ("mfc0 %0, " GRUB_CPU_LOONGSON_COP0_TIMER_COUNT : "=r" (low)); - if (low < last) - high++; - last = low; - - return (((grub_uint64_t) high) << 32) | low; -} - grub_err_t grub_machine_mmap_iterate (grub_memory_hook_t hook) { diff --git a/grub-core/lib/arc/datetime.c b/grub-core/lib/arc/datetime.c new file mode 100644 index 000000000..b8d910e5f --- /dev/null +++ b/grub-core/lib/arc/datetime.c @@ -0,0 +1,48 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 + +GRUB_MOD_LICENSE ("GPLv3+"); + +grub_err_t +grub_get_datetime (struct grub_datetime *datetime) +{ + struct grub_arc_timeinfo *dt; + grub_memset (datetime, 0, sizeof (*datetime)); + + dt = GRUB_ARC_FIRMWARE_VECTOR->gettime (); + + datetime->year = dt->y; + datetime->month = dt->m; + datetime->day = dt->d; + datetime->hour = dt->h; + datetime->minute = dt->min; + datetime->second = dt->s; + + return 0; +} + +grub_err_t +grub_set_datetime (struct grub_datetime *datetime __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_IO, "setting time isn't supported"); +} diff --git a/grub-core/mmap/mips/yeeloong/uppermem.c b/grub-core/mmap/mips/uppermem.c similarity index 98% rename from grub-core/mmap/mips/yeeloong/uppermem.c rename to grub-core/mmap/mips/uppermem.c index 723b6a888..832618540 100644 --- a/grub-core/mmap/mips/yeeloong/uppermem.c +++ b/grub-core/mmap/mips/uppermem.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include grub_uint64_t grub_mmap_get_lower (void) diff --git a/grub-core/partmap/dvh.c b/grub-core/partmap/dvh.c new file mode 100644 index 000000000..118401612 --- /dev/null +++ b/grub-core/partmap/dvh.c @@ -0,0 +1,124 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2005,2006,2007,2011 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 + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define DVH_MAGIC 0x0be5a941 + +struct grub_dvh_partition_descriptor +{ + grub_uint32_t length; + grub_uint32_t start; + grub_uint32_t type; +} __attribute__ ((packed)); + +struct grub_dvh_block +{ + grub_uint32_t magic; + grub_uint8_t unused[308]; + struct grub_dvh_partition_descriptor parts[16]; + grub_uint32_t checksum; + grub_uint32_t unused2; +} __attribute__ ((packed)); + +static struct grub_partition_map grub_dvh_partition_map; + +/* Verify checksum (true=ok). */ +static int +grub_dvh_is_valid (struct grub_dvh_block *label) +{ + grub_uint32_t *pos; + grub_uint32_t sum = 0; + + for (pos = (grub_uint32_t *) label; + pos < (grub_uint32_t *) (label + 1); + pos++) + sum += *pos; + + return ! sum; +} + +static grub_err_t +dvh_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + struct grub_partition p; + struct grub_dvh_block block; + unsigned partnum; + grub_err_t err; + + p.partmap = &grub_dvh_partition_map; + err = grub_disk_read (disk, 0, 0, sizeof (struct grub_dvh_block), + &block); + if (err) + return err; + + if (DVH_MAGIC != grub_be_to_cpu32 (block.magic)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a dvh partition table"); + + if (! grub_dvh_is_valid (&block)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); + + /* Maybe another error value would be better, because partition + table _is_ recognized but invalid. */ + for (partnum = 0; partnum < ARRAY_SIZE (block.parts); partnum++) + { + if (block.parts[partnum].length == 0) + continue; + + if (partnum == 10) + continue; + + p.start = grub_be_to_cpu32 (block.parts[partnum].start); + p.len = grub_be_to_cpu32 (block.parts[partnum].length); + p.number = p.index = partnum; + if (hook (disk, &p)) + break; + } + + return grub_errno; +} + + +/* Partition map type. */ +static struct grub_partition_map grub_dvh_partition_map = + { + .name = "dvh", + .iterate = dvh_partition_map_iterate, + }; + +GRUB_MOD_INIT(part_dvh) +{ + grub_partition_map_register (&grub_dvh_partition_map); +} + +GRUB_MOD_FINI(part_dvh) +{ + grub_partition_map_unregister (&grub_dvh_partition_map); +} + diff --git a/grub-core/term/arc/console.c b/grub-core/term/arc/console.c new file mode 100644 index 000000000..b7e428795 --- /dev/null +++ b/grub-core/term/arc/console.c @@ -0,0 +1,123 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 + +/* FIXME: use unicode. */ + +static int +readkey (struct grub_term_input *term __attribute__ ((unused))) +{ + unsigned long count; + char chr; + + if (GRUB_ARC_FIRMWARE_VECTOR->get_read_status (GRUB_ARC_STDIN)) + return -1; + + if (GRUB_ARC_FIRMWARE_VECTOR->read (GRUB_ARC_STDIN, &chr, 1, &count)) + return -1; + if (!count) + return -1; + return chr; +} + +static void +put (struct grub_term_output *term __attribute__ ((unused)), const int c) +{ + unsigned long count; + char chr = c; + + GRUB_ARC_FIRMWARE_VECTOR->write (GRUB_ARC_STDOUT, &chr, 1, &count); +} + +static struct grub_terminfo_output_state grub_console_terminfo_output; + +static grub_err_t +grub_console_init_output (struct grub_term_output *term) +{ + struct grub_arc_display_status *info = NULL; + if (GRUB_ARC_SYSTEM_PARAMETER_BLOCK->firmware_vector_length + >= ((char *) (&GRUB_ARC_FIRMWARE_VECTOR->getdisplaystatus + 1) + - (char *) GRUB_ARC_FIRMWARE_VECTOR) + && GRUB_ARC_FIRMWARE_VECTOR->getdisplaystatus) + info = GRUB_ARC_FIRMWARE_VECTOR->getdisplaystatus (GRUB_ARC_STDOUT); + if (info) + { + grub_console_terminfo_output.width = info->w; + grub_console_terminfo_output.height = info->h; + } + grub_terminfo_output_init (term); + + return 0; +} + +static struct grub_terminfo_input_state grub_console_terminfo_input = + { + .readkey = readkey + }; + +static struct grub_terminfo_output_state grub_console_terminfo_output = + { + .put = put, + .width = 80, + .height = 36 + }; + +static struct grub_term_input grub_console_term_input = + { + .name = "console", + .init = grub_terminfo_input_init, + .getkey = grub_terminfo_getkey, + .data = &grub_console_terminfo_input + }; + +static struct grub_term_output grub_console_term_output = + { + .name = "console", + .init = grub_console_init_output, + .putchar = grub_terminfo_putchar, + .getxy = grub_terminfo_getxy, + .getwh = grub_terminfo_getwh, + .gotoxy = grub_terminfo_gotoxy, + .cls = grub_terminfo_cls, + .setcolorstate = grub_terminfo_setcolorstate, + .setcursor = grub_terminfo_setcursor, + .flags = GRUB_TERM_CODE_TYPE_ASCII, + .data = &grub_console_terminfo_output, + .normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR, + .highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR, + }; + +void +grub_console_init_early (void) +{ + grub_term_register_input ("console", &grub_console_term_input); + grub_term_register_output ("console", &grub_console_term_output); +} + +void grub_terminfo_init (void); + +void +grub_console_init_lately (void) +{ + grub_terminfo_init (); + grub_terminfo_output_register (&grub_console_term_output, "arc"); +} diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c index 16158139d..3ba630b33 100644 --- a/grub-core/term/terminfo.c +++ b/grub-core/term/terminfo.c @@ -36,6 +36,9 @@ GRUB_MOD_LICENSE ("GPLv3+"); +#define ANSI_C0 0x9b +#define ANSI_C0_STR "\x9b" + static struct grub_term_output *terminfo_outputs; /* Get current terminfo name. */ @@ -123,6 +126,20 @@ grub_terminfo_set_current (struct grub_term_output *term, return grub_errno; } + if (grub_strcmp ("arc", str) == 0) + { + data->name = grub_strdup ("arc"); + data->gotoxy = grub_strdup (ANSI_C0_STR "%i%p1%d;%p2%dH"); + data->cls = grub_strdup (ANSI_C0_STR "2J"); + data->reverse_video_on = grub_strdup (ANSI_C0_STR "7m"); + data->reverse_video_off = grub_strdup (ANSI_C0_STR "0m"); + data->cursor_on = 0; + data->cursor_off = 0; + data->setcolor = grub_strdup (ANSI_C0_STR "3%p1%dm" + ANSI_C0_STR "4%p2%dm"); + return grub_errno; + } + if (grub_strcmp ("ieee1275", str) == 0) { data->name = grub_strdup ("ieee1275"); @@ -369,8 +386,6 @@ grub_terminfo_getwh (struct grub_term_output *term) return (data->width << 8) | data->height; } -#define ANSI_C0 0x9b - static void grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len, int (*readkey) (struct grub_term_input *term)) diff --git a/include/grub/arc/arc.h b/include/grub/arc/arc.h new file mode 100644 index 000000000..5ff0a41f1 --- /dev/null +++ b/include/grub/arc/arc.h @@ -0,0 +1,244 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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_ARC_HEADER +#define GRUB_ARC_HEADER 1 + +#include +#include + +struct grub_arc_memory_descriptor +{ + grub_uint32_t type; + grub_uint32_t start_page; + grub_uint32_t num_pages; +}; + +enum grub_arc_memory_type + { + GRUB_ARC_MEMORY_EXCEPTION_BLOCK, + GRUB_ARC_MEMORY_SYSTEM_PARAMETER_BLOCK, +#ifdef GRUB_CPU_WORDS_BIGENDIAN + GRUB_ARC_MEMORY_FREE_CONTIGUOUS, +#endif + GRUB_ARC_MEMORY_FREE, + GRUB_ARC_MEMORY_BADRAM, + GRUB_ARC_MEMORY_LOADED, GRUB_ARC_MEMORY_FW_TEMPORARY, + GRUB_ARC_MEMORY_FW_PERMANENT, +#ifndef GRUB_CPU_WORDS_BIGENDIAN + GRUB_ARC_MEMORY_FREE_CONTIGUOUS, +#endif + } grub_arc_memory_type_t; + +struct grub_arc_timeinfo +{ + grub_uint16_t y; + grub_uint16_t m; + grub_uint16_t d; + grub_uint16_t h; + grub_uint16_t min; + grub_uint16_t s; + grub_uint16_t ms; +}; + +struct grub_arc_display_status +{ + grub_uint16_t x; + grub_uint16_t y; + grub_uint16_t w; + grub_uint16_t h; + grub_uint8_t fgcolor; + grub_uint8_t bgcolor; + grub_uint8_t high_intensity; + grub_uint8_t underscored; + grub_uint8_t reverse_video; +}; + +struct grub_arc_component +{ + unsigned class; + unsigned type; + unsigned flags; + grub_uint16_t version; + grub_uint16_t rev; + grub_uint32_t key; + grub_uint32_t affinity; + grub_uint32_t configdatasize; + grub_uint32_t idlen; + const char *idstr; +}; + +enum + { +#ifdef GRUB_CPU_WORDS_BIGENDIAN + GRUB_ARC_COMPONENT_TYPE_ARC = 1, +#else + GRUB_ARC_COMPONENT_TYPE_ARC, +#endif + GRUB_ARC_COMPONENT_TYPE_CPU, + GRUB_ARC_COMPONENT_TYPE_FPU, + GRUB_ARC_COMPONENT_TYPE_PRI_I_CACHE, + GRUB_ARC_COMPONENT_TYPE_PRI_D_CACHE, + GRUB_ARC_COMPONENT_TYPE_SEC_I_CACHE, + GRUB_ARC_COMPONENT_TYPE_SEC_D_CACHE, + GRUB_ARC_COMPONENT_TYPE_SEC_CACHE, + GRUB_ARC_COMPONENT_TYPE_EISA, + GRUB_ARC_COMPONENT_TYPE_TCA, + GRUB_ARC_COMPONENT_TYPE_SCSI, + GRUB_ARC_COMPONENT_TYPE_DTIA, + GRUB_ARC_COMPONENT_TYPE_MULTIFUNC, + GRUB_ARC_COMPONENT_TYPE_DISK_CONTROLLER, + GRUB_ARC_COMPONENT_TYPE_TAPE_CONTROLLER, + GRUB_ARC_COMPONENT_TYPE_CDROM_CONTROLLER, + GRUB_ARC_COMPONENT_TYPE_WORM_CONTROLLER, + GRUB_ARC_COMPONENT_TYPE_SERIAL_CONTROLLER, + GRUB_ARC_COMPONENT_TYPE_NET_CONTROLLER, + GRUB_ARC_COMPONENT_TYPE_DISPLAY_CONTROLLER, + GRUB_ARC_COMPONENT_TYPE_PARALLEL_CONTROLLER, + GRUB_ARC_COMPONENT_TYPE_POINTER_CONTROLLER, + GRUB_ARC_COMPONENT_TYPE_KBD_CONTROLLER, + GRUB_ARC_COMPONENT_TYPE_AUDIO_CONTROLLER, + GRUB_ARC_COMPONENT_TYPE_OTHER_CONTROLLER, + GRUB_ARC_COMPONENT_TYPE_DISK, + GRUB_ARC_COMPONENT_TYPE_FLOPPY, + GRUB_ARC_COMPONENT_TYPE_TAPE, + GRUB_ARC_COMPONENT_TYPE_MODEM, + GRUB_ARC_COMPONENT_TYPE_MONITOR, + GRUB_ARC_COMPONENT_TYPE_PRINTER, + GRUB_ARC_COMPONENT_TYPE_POINTER, + GRUB_ARC_COMPONENT_TYPE_KBD, + GRUB_ARC_COMPONENT_TYPE_TERMINAL, + GRUB_ARC_COMPONENT_TYPE_OTHER_PERIPHERAL, + GRUB_ARC_COMPONENT_TYPE_LINE, + GRUB_ARC_COMPONENT_TYPE_NET, + GRUB_ARC_COMPONENT_TYPE_MEMORY_UNIT, + }; + +struct grub_arc_fileinfo +{ + grub_uint64_t start; + grub_uint64_t end; + grub_uint64_t current; + grub_uint32_t type; + grub_uint32_t fnamelength; + grub_uint8_t attr; + char filename[32]; +}; + +struct grub_arc_firmware_vector +{ + /* 0x00. */ + void *load; + void *invoke; + void *execute; + void *halt; + + /* 0x10. */ + void (*powerdown) (void); + void (*restart) (void); + void (*reboot) (void); + void (*exit) (void); + + /* 0x20. */ + void *reserved1; + const struct grub_arc_component * (*getpeer) (const struct grub_arc_component *comp); + const struct grub_arc_component * (*getchild) (const struct grub_arc_component *comp); + void *getparent; + + /* 0x30. */ + void *getconfigurationdata; + void *addchild; + void *deletecomponent; + void *getcomponent; + + /* 0x40. */ + void *saveconfiguration; + void *getsystemid; + struct grub_arc_memory_descriptor *(*getmemorydescriptor) (struct grub_arc_memory_descriptor *current); + void *reserved2; + + /* 0x50. */ + struct grub_arc_timeinfo *(*gettime) (void); + void *getrelativetime; + void *getdirectoryentry; + int (*open) (const char *path, int mode, unsigned *fileno); + + /* 0x60. */ + int (*close) (unsigned fileno); + int (*read) (unsigned fileno, void *buf, unsigned long n, + unsigned long *count); + int (*get_read_status) (unsigned fileno); + int (*write) (unsigned fileno, void *buf, unsigned long n, + unsigned long *count); + + /* 0x70. */ + int (*seek) (unsigned fileno, grub_uint64_t *pos, int mode); + void *mount; + void *getenvironmentvariable; + void *setenvironmentvariable; + + /* 0x80. */ + int (*getfileinformation) (unsigned fileno, struct grub_arc_fileinfo *info); + void *setfileinformation; + void *flushallcaches; + void *testunicodecharacter; + + /* 0x90. */ + struct grub_arc_display_status * (*getdisplaystatus) (unsigned fileno); +}; + +struct grub_arc_adapter +{ + grub_uint32_t adapter_type; + grub_uint32_t adapter_vector_length; + void *adapter_vector; +}; + +struct grub_arc_system_parameter_block +{ + grub_uint32_t signature; + grub_uint32_t length; + grub_uint16_t version; + grub_uint16_t revision; + void *restartblock; + void *debugblock; + void *gevector; + void *utlbmissvector; + grub_uint32_t firmware_vector_length; + struct grub_arc_firmware_vector *firmwarevector; + grub_uint32_t private_vector_length; + void *private_vector; + grub_uint32_t adapter_count; + struct grub_arc_adapter adapters[0]; +}; + + +#define GRUB_ARC_SYSTEM_PARAMETER_BLOCK ((struct grub_arc_system_parameter_block *) 0xa0001000) +#define GRUB_ARC_FIRMWARE_VECTOR (GRUB_ARC_SYSTEM_PARAMETER_BLOCK->firmwarevector) +#define GRUB_ARC_STDIN 0 +#define GRUB_ARC_STDOUT 1 + +int EXPORT_FUNC (grub_arc_iterate_devs) (int (*hook) (const char *name, const struct grub_arc_component *comp), int alt_names); + +#define FOR_ARC_CHILDREN(comp, parent) for (comp = GRUB_ARC_FIRMWARE_VECTOR->getchild (parent); comp; comp = GRUB_ARC_FIRMWARE_VECTOR->getpeer (comp)) + +extern void grub_arcdisk_init (void); +extern void grub_arcdisk_fini (void); + + +#endif diff --git a/include/grub/arc/console.h b/include/grub/arc/console.h new file mode 100644 index 000000000..e054f54f5 --- /dev/null +++ b/include/grub/arc/console.h @@ -0,0 +1,31 @@ +/* + * 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_CONSOLE_MACHINE_HEADER +#define GRUB_CONSOLE_MACHINE_HEADER 1 + +#include + +/* Initialize the console system. */ +void grub_console_init_early (void); +void grub_console_init_lately (void); + +/* Finish the console system. */ +void grub_console_fini (void); + +#endif /* ! GRUB_CONSOLE_MACHINE_HEADER */ diff --git a/include/grub/disk.h b/include/grub/disk.h index 66db1149a..867283494 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -42,7 +42,8 @@ enum grub_disk_dev_id GRUB_DISK_DEVICE_PXE_ID, GRUB_DISK_DEVICE_SCSI_ID, GRUB_DISK_DEVICE_FILE_ID, - GRUB_DISK_DEVICE_LUKS_ID + GRUB_DISK_DEVICE_LUKS_ID, + GRUB_DISK_DEVICE_ARCDISK_ID, }; struct grub_disk; diff --git a/include/grub/mips/arc/kernel.h b/include/grub/mips/arc/kernel.h new file mode 100644 index 000000000..50694866b --- /dev/null +++ b/include/grub/mips/arc/kernel.h @@ -0,0 +1,2 @@ +#include + diff --git a/include/grub/mips/arc/memory.h b/include/grub/mips/arc/memory.h new file mode 100644 index 000000000..b960d2a37 --- /dev/null +++ b/include/grub/mips/arc/memory.h @@ -0,0 +1,42 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 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_MEMORY_MACHINE_HEADER +#define GRUB_MEMORY_MACHINE_HEADER 1 + +#define GRUB_MACHINE_MEMORY_STACK_HIGH 0x8bfffff0 + +#ifndef ASM_FILE + +static inline grub_err_t +grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), + grub_uint64_t size __attribute__ ((unused)), + int type __attribute__ ((unused)), + int handle __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} +static inline grub_err_t +grub_machine_mmap_unregister (int handle __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} + +#endif + +#endif diff --git a/include/grub/mips/arc/time.h b/include/grub/mips/arc/time.h new file mode 100644 index 000000000..e69de29bb diff --git a/include/grub/mips/kernel.h b/include/grub/mips/kernel.h new file mode 100644 index 000000000..d82d0a97d --- /dev/null +++ b/include/grub/mips/kernel.h @@ -0,0 +1,30 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009 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_KERNEL_MACHINE_HEADER +#define GRUB_KERNEL_MACHINE_HEADER 1 + +#include + +#ifndef ASM_FILE + +void EXPORT_FUNC (grub_halt) (void) __attribute__ ((noreturn)); + +#endif + +#endif /* ! GRUB_KERNEL_MACHINE_HEADER */ diff --git a/include/grub/mips/loongson.h b/include/grub/mips/loongson.h index 6cb1178d5..810b73ef2 100644 --- a/include/grub/mips/loongson.h +++ b/include/grub/mips/loongson.h @@ -19,11 +19,7 @@ #ifndef GRUB_LOONGSON_CPU_HEADER #define GRUB_LOONGSON_CPU_HEADER 1 -#ifdef ASM_FILE -#define GRUB_CPU_REGISTER_WRAP(x) x -#else -#define GRUB_CPU_REGISTER_WRAP(x) #x -#endif +#include #define GRUB_CPU_LOONGSON_FLASH_START 0xbfc00000 #define GRUB_CPU_LOONGSON_FLASH_TLB_REFILL 0xbfc00200 @@ -68,7 +64,6 @@ #define GRUB_CPU_LOONGSON_SECONDARY_CACHE_LOG_SIZE 19 #define GRUB_CPU_LOONGSON_COP0_BADVADDR GRUB_CPU_REGISTER_WRAP($8) -#define GRUB_CPU_LOONGSON_COP0_TIMER_COUNT GRUB_CPU_REGISTER_WRAP($9) #define GRUB_CPU_LOONGSON_COP0_CAUSE GRUB_CPU_REGISTER_WRAP($13) #define GRUB_CPU_LOONGSON_COP0_EPC GRUB_CPU_REGISTER_WRAP($14) #define GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO GRUB_CPU_REGISTER_WRAP($28) diff --git a/include/grub/mips/memory.h b/include/grub/mips/memory.h index e51bcc1f2..2ef2ed31c 100644 --- a/include/grub/mips/memory.h +++ b/include/grub/mips/memory.h @@ -1 +1,60 @@ -#include +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 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_MEMORY_MACHINE_HEADER +#define GRUB_MEMORY_MACHINE_HEADER 1 + +#ifndef ASM_FILE +#include +#include +#include +#endif + +#define GRUB_ARCH_LOWMEMVSTART 0x80000000 +#define GRUB_ARCH_LOWMEMPSTART 0x00000000 +#define GRUB_ARCH_LOWMEMMAXSIZE 0x10000000 +#define GRUB_ARCH_HIGHMEMPSTART 0x10000000 + +#ifndef ASM_FILE + +typedef grub_addr_t grub_phys_addr_t; + +static inline grub_phys_addr_t +grub_vtop (void *a) +{ + return ((grub_phys_addr_t) a) & 0x1fffffff; +} + +static inline void * +grub_map_memory (grub_phys_addr_t a, grub_size_t size __attribute__ ((unused))) +{ + return (void *) (a | 0x80000000); +} + +static inline void +grub_unmap_memory (void *a __attribute__ ((unused)), + grub_size_t size __attribute__ ((unused))) +{ +} + +grub_uint64_t grub_mmap_get_lower (void); +grub_uint64_t grub_mmap_get_upper (void); + +#endif + +#endif diff --git a/include/grub/mips/mips.h b/include/grub/mips/mips.h new file mode 100644 index 000000000..8c161aa15 --- /dev/null +++ b/include/grub/mips/mips.h @@ -0,0 +1,30 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 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_REGISTORS_CPU_HEADER +#define GRUB_REGISTORS_CPU_HEADER 1 + +#ifdef ASM_FILE +#define GRUB_CPU_REGISTER_WRAP(x) x +#else +#define GRUB_CPU_REGISTER_WRAP(x) #x +#endif + +#define GRUB_CPU_MIPS_COP0_TIMER_COUNT GRUB_CPU_REGISTER_WRAP($9) + +#endif diff --git a/include/grub/mips/time.h b/include/grub/mips/time.h index b143a48e0..1139b24bb 100644 --- a/include/grub/mips/time.h +++ b/include/grub/mips/time.h @@ -1,6 +1,37 @@ -#ifdef GRUB_MACHINE_EMU +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2004,2005,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 + +#ifndef GRUB_UTIL + +#define GRUB_TICKS_PER_SECOND (grub_arch_cpuclock / 2) + +/* Return the real time in ticks. */ +grub_uint64_t EXPORT_FUNC (grub_get_rtc) (void); + +extern grub_uint32_t EXPORT_VAR (grub_arch_cpuclock); +#endif + static inline void grub_cpu_idle(void) { } + #endif diff --git a/include/grub/mips/yeeloong/kernel.h b/include/grub/mips/yeeloong/kernel.h index 15cf9f9fd..7752a3ef5 100644 --- a/include/grub/mips/yeeloong/kernel.h +++ b/include/grub/mips/yeeloong/kernel.h @@ -1,31 +1 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,2006,2007,2008,2009 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_KERNEL_MACHINE_HEADER -#define GRUB_KERNEL_MACHINE_HEADER 1 - -#include - -#ifndef ASM_FILE - -void EXPORT_FUNC (grub_reboot) (void) __attribute__ ((noreturn)); -void EXPORT_FUNC (grub_halt) (void) __attribute__ ((noreturn)); - -#endif - -#endif /* ! GRUB_KERNEL_MACHINE_HEADER */ +#include diff --git a/include/grub/mips/yeeloong/memory.h b/include/grub/mips/yeeloong/memory.h index 9d53b5e0e..4a1065ea5 100644 --- a/include/grub/mips/yeeloong/memory.h +++ b/include/grub/mips/yeeloong/memory.h @@ -19,43 +19,16 @@ #ifndef GRUB_MEMORY_MACHINE_HEADER #define GRUB_MEMORY_MACHINE_HEADER 1 +#define GRUB_MACHINE_MEMORY_STACK_HIGH 0x801ffff0 + #ifndef ASM_FILE #include #include #include #endif -#define GRUB_MACHINE_MEMORY_STACK_HIGH 0x801ffff0 -#define GRUB_ARCH_LOWMEMVSTART 0x80000000 -#define GRUB_ARCH_LOWMEMPSTART 0x00000000 -#define GRUB_ARCH_LOWMEMMAXSIZE 0x10000000 -#define GRUB_ARCH_HIGHMEMPSTART 0x10000000 - #ifndef ASM_FILE -typedef grub_addr_t grub_phys_addr_t; - -static inline grub_phys_addr_t -grub_vtop (void *a) -{ - return ((grub_phys_addr_t) a) & 0x1fffffff; -} - -static inline void * -grub_map_memory (grub_phys_addr_t a, grub_size_t size __attribute__ ((unused))) -{ - return (void *) (a | 0x80000000); -} - -static inline void -grub_unmap_memory (void *a __attribute__ ((unused)), - grub_size_t size __attribute__ ((unused))) -{ -} - -grub_err_t EXPORT_FUNC (grub_machine_mmap_iterate) -(int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); - static inline grub_err_t grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), @@ -70,9 +43,6 @@ grub_machine_mmap_unregister (int handle __attribute__ ((unused))) return GRUB_ERR_NONE; } -grub_uint64_t grub_mmap_get_lower (void); -grub_uint64_t grub_mmap_get_upper (void); - extern grub_uint32_t EXPORT_VAR (grub_arch_memsize); extern grub_uint32_t EXPORT_VAR (grub_arch_highmemsize); diff --git a/include/grub/mips/yeeloong/time.h b/include/grub/mips/yeeloong/time.h index 7f468bf12..8b8ee42c4 100644 --- a/include/grub/mips/yeeloong/time.h +++ b/include/grub/mips/yeeloong/time.h @@ -20,18 +20,8 @@ #define KERNEL_MACHINE_TIME_HEADER 1 #include - -#define GRUB_TICKS_PER_SECOND (grub_arch_cpuclock / 2) - -/* Return the real time in ticks. */ -grub_uint64_t EXPORT_FUNC (grub_get_rtc) (void); +#include extern grub_uint32_t EXPORT_VAR (grub_arch_busclock); -extern grub_uint32_t EXPORT_VAR (grub_arch_cpuclock); - -static inline void -grub_cpu_idle(void) -{ -} #endif /* ! KERNEL_MACHINE_TIME_HEADER */ diff --git a/include/grub/offsets.h b/include/grub/offsets.h index 31deb5031..d71e7deae 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -111,6 +111,17 @@ #define GRUB_KERNEL_MIPS_YEELOONG_PREFIX 0x0c #define GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END 0x54 +#define GRUB_KERNEL_MIPS_ARC_LINK_ADDR 0x8a000000 + +#define GRUB_KERNEL_MIPS_ARC_LINK_ALIGN 32 + +#define GRUB_KERNEL_MIPS_ARC_COMPRESSED_SIZE 0x8 +#define GRUB_KERNEL_MIPS_ARC_UNCOMPRESSED_SIZE 0xc + +#define GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE 0x08 +#define GRUB_KERNEL_MIPS_ARC_PREFIX 0x0c +#define GRUB_KERNEL_MIPS_ARC_PREFIX_END 0x54 + /* The offset of GRUB_PREFIX. */ #define GRUB_KERNEL_I386_EFI_PREFIX 0x8 @@ -145,6 +156,7 @@ #define GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN 0x1000 #define GRUB_KERNEL_MIPS_YEELOONG_MOD_ALIGN 0x1 +#define GRUB_KERNEL_MIPS_ARC_MOD_ALIGN 0x1 /* Minimal gap between _end and the start of the modules. It's a hack for PowerMac to prevent "CLAIM failed" error. The real fix is to diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index b71fb0420..259d78beb 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -65,7 +65,7 @@ struct image_target_desc IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT, IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_I386_IEEE1275, IMAGE_YEELOONG_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH, - IMAGE_I386_PC_PXE + IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC } id; enum { @@ -355,6 +355,27 @@ struct image_target_desc image_targets[] = .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR }, + { + .name = "mips-arc", + .voidp_sizeof = 4, + .bigendian = 1, + .id = IMAGE_MIPS_ARC, + .flags = PLATFORM_FLAGS_DECOMPRESSORS, + .prefix = GRUB_KERNEL_MIPS_ARC_PREFIX, + .prefix_end = GRUB_KERNEL_MIPS_ARC_PREFIX_END, + .raw_size = 0, + .total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE, + .compressed_size = TARGET_NO_FIELD, + .kernel_image_size = TARGET_NO_FIELD, + .section_align = 1, + .vaddr_offset = 0, + .install_dos_part = TARGET_NO_FIELD, + .install_bsd_part = TARGET_NO_FIELD, + .link_addr = GRUB_KERNEL_MIPS_ARC_LINK_ADDR, + .elf_target = EM_MIPS, + .link_align = GRUB_KERNEL_MIPS_ARC_LINK_ALIGN, + .default_compression = COMPRESSION_NONE + }, }; #define grub_target_to_host32(x) (grub_target_to_host32_real (image_target, (x))) @@ -1217,6 +1238,76 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], core_size = rom_size; } break; + case IMAGE_MIPS_ARC: + { + char *ecoff_img; + struct ecoff_header { + grub_uint16_t magic; + grub_uint16_t nsec; + grub_uint32_t time; + grub_uint32_t syms; + grub_uint32_t nsyms; + grub_uint16_t opt; + grub_uint16_t flags; + grub_uint16_t magic2; + grub_uint16_t version; + grub_uint32_t textsize; + grub_uint32_t datasize; + grub_uint32_t bsssize; + grub_uint32_t entry; + grub_uint32_t text_start; + grub_uint32_t data_start; + grub_uint32_t bss_start; + grub_uint32_t gprmask; + grub_uint32_t cprmask[4]; + grub_uint32_t gp_value; + }; + struct ecoff_section + { + char name[8]; + grub_uint32_t paddr; + grub_uint32_t vaddr; + grub_uint32_t size; + grub_uint32_t file_offset; + grub_uint32_t reloc; + grub_uint32_t gp; + grub_uint16_t nreloc; + grub_uint16_t ngp; + grub_uint32_t flags; + }; + struct ecoff_header *head; + struct ecoff_section *section; + grub_uint32_t target_addr; + size_t program_size; + + program_size = ALIGN_ADDR (core_size); + target_addr = image_target->link_addr - ALIGN_UP(program_size, 1048576) + - (1 << 20); + + ecoff_img = xmalloc (program_size + sizeof (*head) + sizeof (*section)); + grub_memset (ecoff_img, 0, program_size + sizeof (*head) + sizeof (*section)); + head = (void *) ecoff_img; + section = (void *) (head + 1); + head->magic = grub_host_to_target16 (0x160); + head->nsec = grub_host_to_target16 (1); + head->time = grub_host_to_target32 (0); + head->opt = grub_host_to_target16 (0x38); + head->flags = grub_host_to_target16 (0x207); + head->magic2 = grub_host_to_target16 (0x107); + head->textsize = grub_host_to_target32 (program_size); + head->entry = grub_host_to_target32 (target_addr); + head->text_start = grub_host_to_target32 (target_addr); + head->data_start = grub_host_to_target32 (target_addr + program_size); + grub_memcpy (section->name, ".text", sizeof (".text") - 1); + section->vaddr = grub_host_to_target32 (target_addr); + section->size = grub_host_to_target32 (program_size); + section->file_offset = grub_host_to_target32 (sizeof (*head) + sizeof (*section)); + memcpy (section + 1, core_img, core_size); + free (core_img); + core_img = ecoff_img; + core_size = program_size + sizeof (*head) + sizeof (*section); + } + break; case IMAGE_YEELOONG_ELF: case IMAGE_PPC: case IMAGE_COREBOOT: From 12ce749d86fe53bfaee6bce2b552bedcda72bf50 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 16:36:41 +0200 Subject: [PATCH 240/406] sgimips linux loader --- grub-core/loader/mips/linux.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c index 0bf7b1f8e..0b95bd3c2 100644 --- a/grub-core/loader/mips/linux.c +++ b/grub-core/loader/mips/linux.c @@ -31,10 +31,12 @@ GRUB_MOD_LICENSE ("GPLv3+"); /* For frequencies. */ -#include #include #ifdef GRUB_MACHINE_MIPS_YEELOONG + +#include + /* This can be detected on runtime from PMON, but: a) it wouldn't work when GRUB is the firmware and @@ -52,7 +54,10 @@ static struct grub_relocator *relocator; static grub_uint8_t *playground; static grub_addr_t target_addr, entry_addr; static int linux_argc; -static grub_off_t argv_off, envp_off; +static grub_off_t argv_off; +#ifdef GRUB_MACHINE_MIPS_YEELOONG +static grub_off_t envp_off; +#endif static grub_off_t rd_addr_arg_off, rd_size_arg_off; static int initrd_loaded = 0; @@ -65,7 +70,12 @@ grub_linux_boot (void) state.gpr[1] = entry_addr; state.gpr[4] = linux_argc; state.gpr[5] = target_addr + argv_off; +#ifdef GRUB_MACHINE_MIPS_YEELOONG state.gpr[6] = target_addr + envp_off; +#else + state.gpr[6] = 0; +#endif + state.gpr[7] = 0; state.jumpreg = 1; grub_relocator32_boot (relocator, state); @@ -200,9 +210,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), int i; int size; void *extra = NULL; - grub_uint32_t *linux_argv, *linux_envp; - char *linux_args, *linux_envs; + grub_uint32_t *linux_argv; + char *linux_args; grub_err_t err; +#ifdef GRUB_MACHINE_MIPS_YEELOONG + char *linux_envs; + grub_uint32_t *linux_envp; +#endif if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); @@ -313,6 +327,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), extra = linux_args; +#ifdef GRUB_MACHINE_MIPS_YEELOONG linux_envp = extra; envp_off = (grub_uint8_t *) linux_envp - (grub_uint8_t *) playground; linux_envs = (char *) (linux_envp + 5); @@ -340,8 +355,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + target_addr; linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4); - linux_envp[4] = 0; +#endif grub_loader_set (grub_linux_boot, grub_linux_unload, 1); initrd_loaded = 0; From ae6a81f0bb996aa107810246d4b3148953c95919 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 16:38:23 +0200 Subject: [PATCH 241/406] some additional key sequences for arc --- grub-core/term/terminfo.c | 59 ++++++++++++++++++++++++++++++++++----- include/grub/terminfo.h | 2 +- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c index 3ba630b33..3419a5117 100644 --- a/grub-core/term/terminfo.c +++ b/grub-core/term/terminfo.c @@ -445,7 +445,8 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len, {'K', GRUB_TERM_KEY_END}, {'P', GRUB_TERM_KEY_DC}, {'?', GRUB_TERM_KEY_PPAGE}, - {'/', GRUB_TERM_KEY_NPAGE} + {'/', GRUB_TERM_KEY_NPAGE}, + {'@', GRUB_TERM_KEY_INSERT}, }; static struct @@ -460,6 +461,14 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len, {'5', GRUB_TERM_KEY_PPAGE}, {'6', GRUB_TERM_KEY_NPAGE} }; + char fx_key[] = + { 'P', 'Q', 'w', 'x', 't', 'u', + 'q', 'r', 'p', 'M', 'A', 'B' }; + unsigned fx_code[] = + { GRUB_TERM_KEY_F1, GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, + GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, GRUB_TERM_KEY_F6, + GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, + GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12 }; unsigned i; if (c == '\e') @@ -480,17 +489,53 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len, return; } - for (i = 0; i < ARRAY_SIZE (four_code_table); i++) - if (four_code_table[i].key == c) + switch (c) + { + case 'O': + CONTINUE_READ; + for (i = 0; i < ARRAY_SIZE (fx_key); i++) + if (fx_key[i] == c) + { + keys[0] = fx_code[i]; + *len = 1; + return; + } + return; + + case '0': { + int num = 0; CONTINUE_READ; - if (c != '~') + if (c != '0' && c != '1') return; - keys[0] = three_code_table[i].ascii; + num = (c - '0') * 10; + CONTINUE_READ; + if (c < '0' || c > '9') + return; + num += (c - '0'); + if (num == 0 || num > 12) + return; + CONTINUE_READ; + if (c != 'q') + return; + keys[0] = fx_code[num - 1]; *len = 1; return; - } - return; + } + + default: + for (i = 0; i < ARRAY_SIZE (four_code_table); i++) + if (four_code_table[i].key == c) + { + CONTINUE_READ; + if (c != '~') + return; + keys[0] = three_code_table[i].ascii; + *len = 1; + return; + } + return; + } } #undef CONTINUE_READ } diff --git a/include/grub/terminfo.h b/include/grub/terminfo.h index 5a552b327..e3b28ce88 100644 --- a/include/grub/terminfo.h +++ b/include/grub/terminfo.h @@ -27,7 +27,7 @@ char *EXPORT_FUNC(grub_terminfo_get_current) (struct grub_term_output *term); grub_err_t EXPORT_FUNC(grub_terminfo_set_current) (struct grub_term_output *term, const char *); -#define GRUB_TERMINFO_READKEY_MAX_LEN 4 +#define GRUB_TERMINFO_READKEY_MAX_LEN 6 struct grub_terminfo_input_state { int input_buf[GRUB_TERMINFO_READKEY_MAX_LEN]; From fb25a861086e57e3ab8dbff1f16a5387e5a93d9d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 16:39:02 +0200 Subject: [PATCH 242/406] add dvh to userspace tools --- Makefile.util.def | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.util.def b/Makefile.util.def index 058572f06..50e60f476 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -92,6 +92,7 @@ library = { common = grub-core/partmap/gpt.c; common = grub-core/partmap/msdos.c; common = grub-core/partmap/sun.c; + common = grub-core/partmap/dvh.c; common = grub-core/partmap/sunpc.c; common = grub-core/partmap/bsdlabel.c; common = grub-core/script/function.c; From 214af04cf585007d3b36488b289033c55d4e4719 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 16:41:26 +0200 Subject: [PATCH 243/406] avoid executing cache opcode on non-4 byte aligned boundaries --- grub-core/kern/mips/cache_flush.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/grub-core/kern/mips/cache_flush.S b/grub-core/kern/mips/cache_flush.S index 11096c035..a352fd8ba 100644 --- a/grub-core/kern/mips/cache_flush.S +++ b/grub-core/kern/mips/cache_flush.S @@ -9,15 +9,15 @@ subu $t1, $t3, $t2 1: cache 1, 0($t0) - addiu $t1, $t1, 0xffff + addiu $t1, $t1, -0x4 bne $t1, $zero, 1b - addiu $t0, $t0, 0x1 + addiu $t0, $t0, 0x4 sync move $t0, $t2 subu $t1, $t3, $t2 2: cache 0, 0($t0) - addiu $t1, $t1, 0xffff + addiu $t1, $t1, -0x4 bne $t1, $zero, 2b - addiu $t0, $t0, 0x1 + addiu $t0, $t0, 0x4 sync From dd10ec9e60a5e9bc3829e79dc4c7f9b7d8c16593 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 18:02:36 +0200 Subject: [PATCH 244/406] sgimips grub-install partial support (untested) --- util/grub-install.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/util/grub-install.in b/util/grub-install.in index ff8bea87c..537830ecb 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -619,6 +619,10 @@ elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${pla exit 1 } fi +elif [ x"${target_cpu}-${platform}" = xmips-arc ]; then + dvhtool -d "${install_device}" --unix-to-vh "{grubdir}/core.${imgext}" grub + echo "You will have to set boot-device manually. At the Open Firmware prompt, type:" + elif [ x"$platform" = xefi ]; then cp "${grubdir}/core.${imgext}" "${efidir}/${efi_file}" # For old macs. Suggested by Peter Jones. From cdcfe2a95fb3a7e4828febab37be2f6ec744e436 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 18:02:58 +0200 Subject: [PATCH 245/406] missing part of previous commits --- grub-core/kern/mips/startup.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index ae0e0b187..48bf253de 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -50,11 +50,11 @@ VARIABLE(grub_prefix) */ . = _start + GRUB_KERNEL_MACHINE_PREFIX_END +VARIABLE (grub_arch_cpuclock) + .long 0 #ifdef GRUB_MACHINE_MIPS_YEELOONG VARIABLE (grub_arch_busclock) .long 0 -VARIABLE (grub_arch_cpuclock) - .long 0 VARIABLE (grub_arch_memsize) .long 0 VARIABLE (grub_arch_highmemsize) From 96a29d188b261ada3cf3085f0edda3a9a5622bfa Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 18:03:20 +0200 Subject: [PATCH 246/406] Arc type cleanup --- grub-core/disk/arc/arcdisk.c | 12 ++-- grub-core/kern/mips/arc/init.c | 4 +- include/grub/arc/arc.h | 121 ++++++++++++++++++--------------- 3 files changed, 76 insertions(+), 61 deletions(-) diff --git a/grub-core/disk/arc/arcdisk.c b/grub-core/disk/arc/arcdisk.c index c3b98a52e..62732c7ad 100644 --- a/grub-core/disk/arc/arcdisk.c +++ b/grub-core/disk/arc/arcdisk.c @@ -22,7 +22,7 @@ #include #include -static unsigned last_handle = 0; +static grub_arc_fileno_t last_handle = 0; static char *last_path = NULL; static int @@ -45,7 +45,7 @@ grub_arcdisk_iterate (int (*hook_in) (const char *name)) static grub_err_t reopen (const char *name) { - unsigned handle; + grub_arc_fileno_t handle; if (last_path && grub_strcmp (last_path, name) == 0) { @@ -79,7 +79,7 @@ grub_arcdisk_open (const char *name, grub_disk_t disk) const char *iptr; int state = 0; grub_err_t err; - int r; + grub_arc_err_t r; struct grub_arc_fileinfo info; if (grub_memcmp (name, "arc/", 4) != 0) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not arc device"); @@ -124,7 +124,7 @@ grub_arcdisk_open (const char *name, grub_disk_t disk) grub_uint64_t res = 0; int i; - grub_dprintf ("arcdisk", "couldn't retrieve size: %d\n", r); + grub_dprintf ("arcdisk", "couldn't retrieve size: %ld\n", r); for (i = 40; i >= 9; i--) { grub_uint64_t pos = res | (1ULL << i); @@ -165,7 +165,7 @@ grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_uint64_t pos = sector << 9; unsigned long count; grub_uint64_t totl = size << 9; - int r; + grub_arc_err_t r; err = reopen (disk->data); if (err) @@ -173,7 +173,7 @@ grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector, r = GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0); if (r) { - grub_dprintf ("arcdisk", "seek to 0x%" PRIxGRUB_UINT64_T " failed: %d\n", + grub_dprintf ("arcdisk", "seek to 0x%" PRIxGRUB_UINT64_T " failed: %ld\n", pos, r); return grub_error (GRUB_ERR_IO, "couldn't seek"); } diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c index 85d8b26f5..8ee965d74 100644 --- a/grub-core/kern/mips/arc/init.c +++ b/grub-core/kern/mips/arc/init.c @@ -61,9 +61,9 @@ iterate_rec (const char *prefix, const struct grub_arc_component *parent, if (!cname) cname = "unknown"; if (alt_names) - name = grub_xasprintf ("%s/%s%d", prefix, cname, comp->key); + name = grub_xasprintf ("%s/%s%lu", prefix, cname, comp->key); else - name = grub_xasprintf ("%s%s(%d)", prefix, cname, comp->key); + name = grub_xasprintf ("%s%s(%lu)", prefix, cname, comp->key); if (!name) return 1; if (hook (name, comp)) diff --git a/include/grub/arc/arc.h b/include/grub/arc/arc.h index 5ff0a41f1..aae73052b 100644 --- a/include/grub/arc/arc.h +++ b/include/grub/arc/arc.h @@ -22,11 +22,21 @@ #include #include +typedef unsigned grub_arc_enum_t; +typedef grub_uint64_t grub_arc_ularge_t; +typedef unsigned long grub_arc_ulong_t; +typedef long grub_arc_long_t; +typedef unsigned short grub_arc_ushort_t; +typedef unsigned char grub_arc_uchar_t; + +typedef grub_arc_long_t grub_arc_err_t; +typedef grub_arc_ulong_t grub_arc_fileno_t; + struct grub_arc_memory_descriptor { - grub_uint32_t type; - grub_uint32_t start_page; - grub_uint32_t num_pages; + grub_arc_enum_t type; + grub_arc_ulong_t start_page; + grub_arc_ulong_t num_pages; }; enum grub_arc_memory_type @@ -47,39 +57,39 @@ enum grub_arc_memory_type struct grub_arc_timeinfo { - grub_uint16_t y; - grub_uint16_t m; - grub_uint16_t d; - grub_uint16_t h; - grub_uint16_t min; - grub_uint16_t s; - grub_uint16_t ms; + grub_arc_ushort_t y; + grub_arc_ushort_t m; + grub_arc_ushort_t d; + grub_arc_ushort_t h; + grub_arc_ushort_t min; + grub_arc_ushort_t s; + grub_arc_ushort_t ms; }; struct grub_arc_display_status { - grub_uint16_t x; - grub_uint16_t y; - grub_uint16_t w; - grub_uint16_t h; - grub_uint8_t fgcolor; - grub_uint8_t bgcolor; - grub_uint8_t high_intensity; - grub_uint8_t underscored; - grub_uint8_t reverse_video; + grub_arc_ushort_t x; + grub_arc_ushort_t y; + grub_arc_ushort_t w; + grub_arc_ushort_t h; + grub_arc_uchar_t fgcolor; + grub_arc_uchar_t bgcolor; + grub_arc_uchar_t high_intensity; + grub_arc_uchar_t underscored; + grub_arc_uchar_t reverse_video; }; struct grub_arc_component { - unsigned class; - unsigned type; - unsigned flags; - grub_uint16_t version; - grub_uint16_t rev; - grub_uint32_t key; - grub_uint32_t affinity; - grub_uint32_t configdatasize; - grub_uint32_t idlen; + grub_arc_enum_t class; + grub_arc_enum_t type; + grub_arc_enum_t flags; + grub_arc_ushort_t version; + grub_arc_ushort_t rev; + grub_arc_ulong_t key; + grub_arc_ulong_t affinity; + grub_arc_ulong_t configdatasize; + grub_arc_ulong_t idlen; const char *idstr; }; @@ -131,12 +141,12 @@ enum struct grub_arc_fileinfo { - grub_uint64_t start; - grub_uint64_t end; - grub_uint64_t current; - grub_uint32_t type; - grub_uint32_t fnamelength; - grub_uint8_t attr; + grub_arc_ularge_t start; + grub_arc_ularge_t end; + grub_arc_ularge_t current; + grub_arc_enum_t type; + grub_arc_ulong_t fnamelength; + grub_arc_uchar_t attr; char filename[32]; }; @@ -176,54 +186,59 @@ struct grub_arc_firmware_vector struct grub_arc_timeinfo *(*gettime) (void); void *getrelativetime; void *getdirectoryentry; - int (*open) (const char *path, int mode, unsigned *fileno); + grub_arc_err_t (*open) (const char *path, grub_arc_enum_t mode, + grub_arc_fileno_t *fileno); /* 0x60. */ - int (*close) (unsigned fileno); - int (*read) (unsigned fileno, void *buf, unsigned long n, - unsigned long *count); - int (*get_read_status) (unsigned fileno); - int (*write) (unsigned fileno, void *buf, unsigned long n, - unsigned long *count); + grub_arc_err_t (*close) (grub_arc_fileno_t fileno); + grub_arc_err_t (*read) (grub_arc_fileno_t fileno, void *buf, + grub_arc_ulong_t n, + grub_arc_ulong_t *count); + grub_arc_err_t (*get_read_status) (grub_arc_fileno_t fileno); + grub_arc_err_t (*write) (grub_arc_fileno_t fileno, void *buf, + grub_arc_ulong_t n, + grub_arc_ulong_t *count); /* 0x70. */ - int (*seek) (unsigned fileno, grub_uint64_t *pos, int mode); + grub_arc_err_t (*seek) (grub_arc_fileno_t fileno, + grub_arc_ularge_t *pos, grub_arc_enum_t mode); void *mount; void *getenvironmentvariable; void *setenvironmentvariable; /* 0x80. */ - int (*getfileinformation) (unsigned fileno, struct grub_arc_fileinfo *info); + grub_arc_err_t (*getfileinformation) (grub_arc_fileno_t fileno, + struct grub_arc_fileinfo *info); void *setfileinformation; void *flushallcaches; void *testunicodecharacter; /* 0x90. */ - struct grub_arc_display_status * (*getdisplaystatus) (unsigned fileno); + struct grub_arc_display_status * (*getdisplaystatus) (grub_arc_fileno_t fileno); }; struct grub_arc_adapter { - grub_uint32_t adapter_type; - grub_uint32_t adapter_vector_length; + grub_arc_ulong_t adapter_type; + grub_arc_ulong_t adapter_vector_length; void *adapter_vector; }; struct grub_arc_system_parameter_block { - grub_uint32_t signature; - grub_uint32_t length; - grub_uint16_t version; - grub_uint16_t revision; + grub_arc_ulong_t signature; + grub_arc_ulong_t length; + grub_arc_ushort_t version; + grub_arc_ushort_t revision; void *restartblock; void *debugblock; void *gevector; void *utlbmissvector; - grub_uint32_t firmware_vector_length; + grub_arc_ulong_t firmware_vector_length; struct grub_arc_firmware_vector *firmwarevector; - grub_uint32_t private_vector_length; + grub_arc_ulong_t private_vector_length; void *private_vector; - grub_uint32_t adapter_count; + grub_arc_ulong_t adapter_count; struct grub_arc_adapter adapters[0]; }; From 91bbcc0cb666d9f1cc9965e1c692fd0730ab77fd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 20:23:29 +0200 Subject: [PATCH 247/406] * grub-core/boot/mips/yeeloong/fwstart.S: Add explicit set mips3 to avoid asm treating ld and sd as macros. --- ChangeLog | 5 +++++ grub-core/boot/mips/yeeloong/fwstart.S | 1 + 2 files changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index ede161faf..5b73d8884 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-13 Vladimir Serbinenko + + * grub-core/boot/mips/yeeloong/fwstart.S: Add explicit set mips3 + to avoid asm treating ld and sd as macros. + 2011-05-13 Vladimir Serbinenko * grub-core/boot/mips/startup_raw.S: Flush cache after loading diff --git a/grub-core/boot/mips/yeeloong/fwstart.S b/grub-core/boot/mips/yeeloong/fwstart.S index 9e81df192..2eec876c2 100644 --- a/grub-core/boot/mips/yeeloong/fwstart.S +++ b/grub-core/boot/mips/yeeloong/fwstart.S @@ -28,6 +28,7 @@ .set noreorder .set noat .set nomacro + .set mips3 .global start,_start,__start start: From 19e1c41bbf0638f0504f8cb6faf25c852c49db21 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 20:56:50 +0200 Subject: [PATCH 248/406] Flush caches on DMA memory. * grub-core/kern/mips/cache.S (grub_arch_sync_dma_caches): New function. * grub-core/bus/pci.c (grub_memalign_dma32): Flush caches. (grub_dma_free): Likewise. * include/grub/cache.h (grub_arch_sync_dma_caches): New declaration. --- ChangeLog | 9 +++++++++ grub-core/bus/pci.c | 11 ++++++++++- grub-core/kern/mips/cache.S | 35 +++++++++++++++++++++++++++++++++++ include/grub/cache.h | 10 ++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 5b73d8884..49873303c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-05-13 Vladimir Serbinenko + + Flush caches on DMA memory. + + * grub-core/kern/mips/cache.S (grub_arch_sync_dma_caches): New function. + * grub-core/bus/pci.c (grub_memalign_dma32): Flush caches. + (grub_dma_free): Likewise. + * include/grub/cache.h (grub_arch_sync_dma_caches): New declaration. + 2011-05-13 Vladimir Serbinenko * grub-core/boot/mips/yeeloong/fwstart.S: Add explicit set mips3 diff --git a/grub-core/bus/pci.c b/grub-core/bus/pci.c index 07d20e3f5..766b6d7f1 100644 --- a/grub-core/bus/pci.c +++ b/grub-core/bus/pci.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -28,12 +30,19 @@ GRUB_MOD_LICENSE ("GPLv3+"); struct grub_pci_dma_chunk * grub_memalign_dma32 (grub_size_t align, grub_size_t size) { - return grub_memalign (align, size); + void *ret = grub_memalign (align, size); + if (!ret) + return 0; + grub_arch_sync_dma_caches (ret, size); + return ret; } +/* FIXME: evil. */ void grub_dma_free (struct grub_pci_dma_chunk *ch) { + grub_size_t size = (((struct grub_mm_header *) ch) - 1)->size * GRUB_MM_ALIGN; + grub_arch_sync_dma_caches (ch, size); grub_free (ch); } /* #endif */ diff --git a/grub-core/kern/mips/cache.S b/grub-core/kern/mips/cache.S index 999872f6b..a4aa06fb0 100644 --- a/grub-core/kern/mips/cache.S +++ b/grub-core/kern/mips/cache.S @@ -8,3 +8,38 @@ FUNCTION (grub_cpu_flush_cache) FUNCTION (grub_arch_sync_caches) #include "cache_flush.S" j $ra + +FUNCTION (grub_arch_sync_dma_caches) + move $t2, $a0 + addu $t3, $a0, $a1 + srl $t2, $t2, 5 + sll $t2, $t2, 5 + addu $t3, $t3, 0x1f + srl $t3, $t3, 5 + sll $t3, $t3, 5 + move $t0, $t2 + subu $t1, $t3, $t2 +1: + cache 1, 0($t0) + addiu $t1, $t1, 0xffff + bne $t1, $zero, 1b + addiu $t0, $t0, 0x1 + sync + move $t0, $t2 + subu $t1, $t3, $t2 +2: + cache 0, 0($t0) + addiu $t1, $t1, 0xffff + bne $t1, $zero, 2b + addiu $t0, $t0, 0x1 + sync + move $t0, $t2 + subu $t1, $t3, $t2 +2: + cache 23, 0($t0) + addiu $t1, $t1, 0xffff + bne $t1, $zero, 2b + addiu $t0, $t0, 0x1 + sync + + jr $ra \ No newline at end of file diff --git a/include/grub/cache.h b/include/grub/cache.h index 4f913f5c8..292830566 100644 --- a/include/grub/cache.h +++ b/include/grub/cache.h @@ -37,4 +37,14 @@ grub_arch_sync_caches (void *address __attribute__ ((unused)), void EXPORT_FUNC(grub_arch_sync_caches) (void *address, grub_size_t len); #endif +#ifdef _mips +void EXPORT_FUNC(grub_arch_sync_dma_caches) (void *address, grub_size_t len); +#else +static inline void +grub_arch_sync_dma_caches (void *address __attribute__ ((unused)), + grub_size_t len __attribute__ ((unused))) +{ +} +#endif + #endif /* ! GRUB_CACHE_HEADER */ From bda0e21993092a324ecee96e5d61c53ef5ebf6a1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 21:31:00 +0200 Subject: [PATCH 249/406] * util/grub-mkimage.c (generate_image): Update hash. --- ChangeLog | 4 ++++ util/grub-mkimage.c | 18 +++++++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 49873303c..905b0e919 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-05-13 Vladimir Serbinenko + + * util/grub-mkimage.c (generate_image): Update hash. + 2011-05-13 Vladimir Serbinenko Flush caches on DMA memory. diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index b71fb0420..5e964a3e7 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -1169,20 +1169,20 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], char *boot_path, *boot_img; size_t boot_size; grub_uint8_t context[GRUB_MD_SHA512->contextsize]; - /* fwstart.img is the only part which can't be testes by using *-elf + /* fwstart.img is the only part which can't be tested by using *-elf target. Check it against the checksum. This checksum is obtained with sha512sum utility after compiling on Gnewsense. */ const grub_uint8_t fwstart_good_hash[] = { - 0x9f, 0x7f, 0x79, 0x47, 0x68, 0x91, 0x61, 0xb3, - 0x16, 0x7b, 0xf0, 0x27, 0x1c, 0xf7, 0xaf, 0x05, - 0x6c, 0xc1, 0x6f, 0xd2, 0xe7, 0xd1, 0xe9, 0xec, - 0x08, 0x87, 0xe5, 0xc8, 0x29, 0xa2, 0x5b, 0x84, - 0xf8, 0xa6, 0xec, 0x08, 0xf7, 0xcb, 0x7b, 0x6c, - 0xfe, 0x01, 0xfd, 0x5d, 0xba, 0xbf, 0x0d, 0x0f, - 0x2e, 0xef, 0xed, 0x7b, 0xfe, 0xc9, 0x4a, 0x85, - 0xcf, 0xac, 0x20, 0xd7, 0x01, 0xc5, 0xc5, 0x9c + 0x44, 0xce, 0xbc, 0xe7, 0xc2, 0x5e, 0xff, 0x65, + 0xc5, 0xda, 0x29, 0x5a, 0xb9, 0x08, 0x89, 0x42, + 0x83, 0x3f, 0x2b, 0x2e, 0x06, 0xe1, 0x6f, 0x79, + 0x9b, 0x78, 0x6d, 0xe5, 0xd3, 0x64, 0x98, 0x35, + 0xc8, 0x58, 0xac, 0xb8, 0x08, 0x6d, 0x21, 0x51, + 0xcf, 0xe0, 0x76, 0x48, 0x81, 0x6c, 0xed, 0x65, + 0x4a, 0x50, 0xb4, 0x06, 0x38, 0x0b, 0x26, 0x74, + 0x43, 0xbf, 0xc5, 0x2e, 0x07, 0xa6, 0xb8, 0x0e, }; boot_path = grub_util_get_path (dir, "fwstart.img"); From 36084912c0310c7cb42e80b42d0b187bc3775809 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 21:41:18 +0200 Subject: [PATCH 250/406] Give ATA device a bit more time on first try in order to allow disks to spin up. * grub-core/disk/ata.c (grub_atapi_identify): Use GRUB_ATA_TOUT_DEV_INIT if dev->present is 1. Reset dev->present on failure. (grub_ata_device_initialize): Set dev->present to 1. * include/grub/ata.h (GRUB_ATA_TOUT_DEV_INIT): New value. (grub_ata_device): New member 'present'. --- ChangeLog | 11 +++++++++++ grub-core/disk/ata.c | 35 +++++++++++++++++++++++++---------- include/grub/ata.h | 5 ++++- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 905b0e919..e20f2d3cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-05-13 Vladimir Serbinenko + + Give ATA device a bit more time on first try in order to allow disks + to spin up. + + * grub-core/disk/ata.c (grub_atapi_identify): Use GRUB_ATA_TOUT_DEV_INIT + if dev->present is 1. Reset dev->present on failure. + (grub_ata_device_initialize): Set dev->present to 1. + * include/grub/ata.h (GRUB_ATA_TOUT_DEV_INIT): New value. + (grub_ata_device): New member 'present'. + 2011-05-13 Vladimir Serbinenko * util/grub-mkimage.c (generate_image): Update hash. diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 7f261560d..391ccb9a2 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -160,18 +160,23 @@ grub_atapi_identify (struct grub_ata_device *dev) grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4); grub_ata_wait (); - if (grub_ata_check_ready (dev)) + if ((grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY) + && grub_ata_wait_not_busy (dev, dev->present ? GRUB_ATA_TOUT_DEV_INIT + : GRUB_ATA_TOUT_STD)) { grub_free (info); + dev->present = 0; return grub_errno; } grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE); grub_ata_wait (); - if (grub_ata_wait_drq (dev, 0, GRUB_ATA_TOUT_STD)) + if (grub_ata_wait_drq (dev, 0, dev->present ? GRUB_ATA_TOUT_DEV_INIT + : GRUB_ATA_TOUT_STD)) { grub_free (info); + dev->present = 0; return grub_errno; } grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE); @@ -258,8 +263,11 @@ grub_ata_identify (struct grub_ata_device *dev) grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4); grub_ata_wait (); - if (grub_ata_check_ready (dev)) + if ((grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY) + && grub_ata_wait_not_busy (dev, dev->present ? GRUB_ATA_TOUT_DEV_INIT + : GRUB_ATA_TOUT_STD)) { + dev->present = 0; grub_free (info); return grub_errno; } @@ -267,7 +275,8 @@ grub_ata_identify (struct grub_ata_device *dev) grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_IDENTIFY_DEVICE); grub_ata_wait (); - if (grub_ata_wait_drq (dev, 0, GRUB_ATA_TOUT_STD)) + if (grub_ata_wait_drq (dev, 0, dev->present ? GRUB_ATA_TOUT_DEV_INIT + : GRUB_ATA_TOUT_STD)) { grub_free (info); grub_errno = GRUB_ERR_NONE; @@ -280,13 +289,18 @@ grub_ata_identify (struct grub_ata_device *dev) return grub_atapi_identify (dev); else if (sts == 0x00) - /* No device, return error but don't print message. */ - return GRUB_ERR_UNKNOWN_DEVICE; - + { + dev->present = 0; + /* No device, return error but don't print message. */ + return GRUB_ERR_UNKNOWN_DEVICE; + } else - /* Other Error. */ - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, - "device cannot be identified"); + { + dev->present = 0; + /* Other Error. */ + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + "device cannot be identified"); + } } grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE); @@ -381,6 +395,7 @@ grub_ata_device_initialize (int port, int device, int addr, int addr2) dev->device = device; dev->ioaddress = addr + GRUB_MACHINE_PCI_IO_BASE; dev->ioaddress2 = addr2 + GRUB_MACHINE_PCI_IO_BASE; + dev->present = 1; dev->next = NULL; /* Register the device. */ diff --git a/include/grub/ata.h b/include/grub/ata.h index 9e3aaf0e6..c8f4e5e1b 100644 --- a/include/grub/ata.h +++ b/include/grub/ata.h @@ -94,7 +94,8 @@ enum grub_ata_commands enum grub_ata_timeout_milliseconds { GRUB_ATA_TOUT_STD = 1000, /* 1s standard timeout. */ - GRUB_ATA_TOUT_DATA = 10000 /* 10s DATA I/O timeout. */ + GRUB_ATA_TOUT_DATA = 10000, /* 10s DATA I/O timeout. */ + GRUB_ATA_TOUT_DEV_INIT = 10000, /* Give the device 10s on first try to spinon. */ }; struct grub_ata_device @@ -128,6 +129,8 @@ struct grub_ata_device /* Set to 0 for ATA, set to 1 for ATAPI. */ int atapi; + int present; + struct grub_ata_device *next; }; From 85c6210f6abbb3146d547c33b7e3bd97cdc5751c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 13 May 2011 21:50:18 +0200 Subject: [PATCH 251/406] * configure.ac: Bump version to 1.99. --- ChangeLog | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e20f2d3cf..143fc60f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-05-13 Vladimir Serbinenko + + * configure.ac: Bump version to 1.99. + 2011-05-13 Vladimir Serbinenko Give ATA device a bit more time on first try in order to allow disks diff --git a/configure.ac b/configure.ac index 811bd992d..4a05007fd 100644 --- a/configure.ac +++ b/configure.ac @@ -32,7 +32,7 @@ dnl type, so there is no conflict. Variables with the prefix "TARGET_" dnl (such as TARGET_CC, TARGET_CFLAGS, etc.) are used for the target dnl type. -AC_INIT([GRUB],[1.99~rc2],[bug-grub@gnu.org]) +AC_INIT([GRUB],[1.99],[bug-grub@gnu.org]) AC_CONFIG_AUX_DIR([build-aux]) From 4c2a3b438eadb277a23f9aba650a683cb11d0fb8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 14 May 2011 12:09:16 +0200 Subject: [PATCH 252/406] * grub-core/term/at_keyboard.c (set1_e0_mapping): Fix swap between PgUp and PgDown. --- ChangeLog | 5 +++++ grub-core/term/at_keyboard.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 143fc60f5..398495dea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-14 Vladimir Serbinenko + + * grub-core/term/at_keyboard.c (set1_e0_mapping): Fix swap between + PgUp and PgDown. + 2011-05-13 Vladimir Serbinenko * configure.ac: Bump version to 1.99. diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c index 56aa7275e..f0f346b1b 100644 --- a/grub-core/term/at_keyboard.c +++ b/grub-core/term/at_keyboard.c @@ -111,12 +111,12 @@ static const struct {0x38, GRUB_KEYBOARD_KEY_RIGHT_ALT}, {0x47, GRUB_KEYBOARD_KEY_HOME}, {0x48, GRUB_KEYBOARD_KEY_UP}, - {0x49, GRUB_KEYBOARD_KEY_NPAGE}, + {0x49, GRUB_KEYBOARD_KEY_PPAGE}, {0x4b, GRUB_KEYBOARD_KEY_LEFT}, {0x4d, GRUB_KEYBOARD_KEY_RIGHT}, {0x4f, GRUB_KEYBOARD_KEY_END}, {0x50, GRUB_KEYBOARD_KEY_DOWN}, - {0x51, GRUB_KEYBOARD_KEY_PPAGE}, + {0x51, GRUB_KEYBOARD_KEY_NPAGE}, {0x52, GRUB_KEYBOARD_KEY_INSERT}, {0x53, GRUB_KEYBOARD_KEY_DELETE}, }; From d4de6b01e8953039b84205d5ac181cb3615d726e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 14 May 2011 12:14:00 +0200 Subject: [PATCH 253/406] * grub-core/commands/menuentry.c (grub_cmd_menuentry): Correctly handle class-free menuentries. (grub_normal_add_menu_entry): Add a check to be sure. --- ChangeLog | 6 ++++++ grub-core/commands/menuentry.c | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 398495dea..466713bfe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-05-14 Vladimir Serbinenko + + * grub-core/commands/menuentry.c (grub_cmd_menuentry): Correctly + handle class-free menuentries. + (grub_normal_add_menu_entry): Add a check to be sure. + 2011-05-14 Vladimir Serbinenko * grub-core/term/at_keyboard.c (set1_e0_mapping): Fix swap between diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c index 4dab1783a..4849f8bb8 100644 --- a/grub-core/commands/menuentry.c +++ b/grub-core/commands/menuentry.c @@ -91,7 +91,7 @@ grub_normal_add_menu_entry (int argc, const char **args, char **classes, if (! menu_sourcecode) return grub_errno; - if (classes) + if (classes && classes[0]) { int i; for (i = 0; classes[i]; i++); /* count # of menuentry classes */ @@ -255,7 +255,8 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args) if (! ctxt->script) return grub_normal_add_menu_entry (argc, (const char **) args, - ctxt->state[0].args, ctxt->state[1].arg, + (ctxt->state[0].set ? ctxt->state[0].args + : NULL), ctxt->state[1].arg, ctxt->state[2].arg, 0, ctxt->state[3].arg, ctxt->extcmd->cmd->name[0] == 's'); From 2217a1430e285bc78cf595319c128acc8026369d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 14 May 2011 17:47:59 +0200 Subject: [PATCH 254/406] Handle module_license on windows. * util/grub-pe2elf.c (MODLICENSE_SECTION): New definition. All following sections shifted. (insert_string): Make argument const char * instead of char *. (write_section_data): Handle long section names. Handle module_license. --- ChangeLog | 10 ++++++++++ util/grub-pe2elf.c | 44 +++++++++++++++++++++++++++++--------------- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 466713bfe..80f21841f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-05-14 Vladimir Serbinenko + + Handle module_license on windows. + + * util/grub-pe2elf.c (MODLICENSE_SECTION): New definition. All following + sections shifted. + (insert_string): Make argument const char * instead of char *. + (write_section_data): Handle long section names. + Handle module_license. + 2011-05-14 Vladimir Serbinenko * grub-core/commands/menuentry.c (grub_cmd_menuentry): Correctly diff --git a/util/grub-pe2elf.c b/util/grub-pe2elf.c index cf690841f..4b93faa05 100644 --- a/util/grub-pe2elf.c +++ b/util/grub-pe2elf.c @@ -79,11 +79,12 @@ Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); #define BSS_SECTION 4 #define MODNAME_SECTION 5 #define MODDEPS_SECTION 6 -#define SYMTAB_SECTION 7 -#define STRTAB_SECTION 8 +#define MODLICENSE_SECTION 7 +#define SYMTAB_SECTION 8 +#define STRTAB_SECTION 9 -#define REL_SECTION 9 -#define MAX_SECTIONS 12 +#define REL_SECTION 10 +#define MAX_SECTIONS 16 #define STRTAB_BLOCK 256 @@ -96,7 +97,7 @@ int num_sections; grub_uint32_t offset; static int -insert_string (char *name) +insert_string (const char *name) { int len, result; @@ -124,6 +125,8 @@ write_section_data (FILE* fp, char *image, { int *section_map; int i; + char *pe_strtab = (image + pe_chdr->symtab_offset + + pe_chdr->num_symbols * sizeof (struct grub_pe32_symbol)); section_map = xmalloc ((pe_chdr->num_sections + 1) * sizeof (int)); section_map[0] = 0; @@ -131,31 +134,42 @@ write_section_data (FILE* fp, char *image, for (i = 0; i < pe_chdr->num_sections; i++, pe_shdr++) { grub_uint32_t idx; + const char *name = pe_shdr->name; - if (! strcmp (pe_shdr->name, ".text")) + if (name[0] == '/' && isdigit (name[1])) + { + char t[sizeof (pe_shdr->name) + 1]; + memcpy (t, name, sizeof (pe_shdr->name)); + t[sizeof (pe_shdr->name)] = 0; + name = pe_strtab + atoi (t + 1); + } + + if (! strcmp (name, ".text")) { idx = TEXT_SECTION; shdr[idx].sh_flags = SHF_ALLOC | SHF_EXECINSTR; } - else if (! strcmp (pe_shdr->name, ".rdata")) + else if (! strcmp (name, ".rdata")) { idx = RDATA_SECTION; shdr[idx].sh_flags = SHF_ALLOC; } - else if (! strcmp (pe_shdr->name, ".data")) + else if (! strcmp (name, ".data")) { idx = DATA_SECTION; shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE; } - else if (! strcmp (pe_shdr->name, ".bss")) + else if (! strcmp (name, ".bss")) { idx = BSS_SECTION; shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE; } - else if (! strcmp (pe_shdr->name, ".modname")) + else if (! strcmp (name, ".modname")) idx = MODNAME_SECTION; - else if (! strcmp (pe_shdr->name, ".moddeps")) + else if (! strcmp (name, ".moddeps")) idx = MODDEPS_SECTION; + else if (strcmp (name, ".module_license") == 0) + idx = MODLICENSE_SECTION; else { section_map[i + 1] = -1; @@ -181,14 +195,14 @@ write_section_data (FILE* fp, char *image, if (pe_shdr->relocations_offset) { - char name[5 + strlen (pe_shdr->name)]; + char relname[5 + strlen (name)]; if (num_sections >= MAX_SECTIONS) grub_util_error ("too many sections"); - sprintf (name, ".rel%s", pe_shdr->name); + sprintf (relname, ".rel%s", name); - shdr[num_sections].sh_name = insert_string (name); + shdr[num_sections].sh_name = insert_string (relname); shdr[num_sections].sh_link = i; shdr[num_sections].sh_info = idx; @@ -197,7 +211,7 @@ write_section_data (FILE* fp, char *image, num_sections++; } else - shdr[idx].sh_name = insert_string (pe_shdr->name); + shdr[idx].sh_name = insert_string (name); } return section_map; From 0cac83df852a8a58d36c0197fb2d3a67fef3488f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 14 May 2011 17:50:48 +0200 Subject: [PATCH 255/406] * docs/grub.texi (Installation): Fix several outdated claims. --- ChangeLog | 4 ++++ docs/grub.texi | 62 +++++++++++++------------------------------------- 2 files changed, 20 insertions(+), 46 deletions(-) diff --git a/ChangeLog b/ChangeLog index 80f21841f..01f216bfb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-05-14 Vladimir Serbinenko + + * docs/grub.texi (Installation): Fix several outdated claims. + 2011-05-14 Vladimir Serbinenko Handle module_license on windows. diff --git a/docs/grub.texi b/docs/grub.texi index 95707e4cc..0b7e1098c 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -528,21 +528,15 @@ system (@pxref{Obtaining and Building GRUB}). You can do this either from the source tarball, or as a package for your OS. After you have done that, you need to install the boot loader on a -drive (floppy or hard disk). There are two ways of doing that - either -using the utility @command{grub-install} (@pxref{Invoking -grub-install}) on a UNIX-like OS, or by running GRUB itself from a -floppy. These are quite similar, however the utility might probe a -wrong BIOS drive, so you should be careful. - -Also, if you install GRUB on a UNIX-like OS, please make sure that you -have an emergency boot disk ready, so that you can rescue your computer -if, by any chance, your hard drive becomes unusable (unbootable). +drive (floppy or hard disk) by using the utility +@command{grub-install} (@pxref{Invoking grub-install}) on a UNIX-like OS. GRUB comes with boot images, which are normally put in the directory -@file{/usr/lib/grub/i386-pc}. Hereafter, the directory where GRUB images are -initially placed (normally @file{/usr/lib/grub/i386-pc}) will be +@file{/usr/lib/grub/-} (for BIOS-based machines +@file{/usr/lib/grub/i386-pc}). Hereafter, the directory where GRUB images are +initially placed (normally @file{/usr/lib/grub/-}) will be called the @dfn{image directory}, and the directory where the boot -loader needs to find them (usually @file{/boot/grub}) will be called +loader needs to find them (usually @file{/boot}) will be called the @dfn{boot directory}. @menu @@ -556,27 +550,18 @@ the @dfn{boot directory}. @node Installing GRUB using grub-install @section Installing GRUB using grub-install -@strong{Caution:} This procedure is definitely less safe, because -there are several ways in which your computer can become -unbootable. For example, most operating systems don't tell GRUB how to -map BIOS drives to OS devices correctly---GRUB merely @dfn{guesses} -the mapping. This will succeed in most cases, but not -always. Therefore, GRUB provides you with a map file called the -@dfn{device map}, which you must fix if it is wrong. @xref{Device -map}, for more details. - For information on where GRUB should be installed on PC BIOS platforms, @pxref{BIOS installation}. -If you still do want to install GRUB under a UNIX-like OS (such +In order to install GRUB under a UNIX-like OS (such as @sc{gnu}), invoke the program @command{grub-install} (@pxref{Invoking grub-install}) as the superuser (@dfn{root}). The usage is basically very simple. You only need to specify one argument to the program, namely, where to install the boot loader. The -argument can be either a device file (like @samp{/dev/hda}) or a -partition specified in GRUB's notation. For example, under Linux the -following will install GRUB into the MBR of the first IDE disk: +argument has to be either a device file (like @samp{/dev/hda}). +For example, under Linux the following will install GRUB into the MBR +of the first IDE disk: @example # @kbd{grub-install /dev/hda} @@ -588,37 +573,22 @@ Likewise, under GNU/Hurd, this has the same effect: # @kbd{grub-install /dev/hd0} @end example -But all the above examples assume that GRUB should use images under -the root directory. If you want GRUB to use images under a directory -other than the root directory, you need to specify the option -@option{--root-directory}. The typical usage is that you create a GRUB +But all the above examples assume that GRUB should put images under +the @file{/boot} directory. If you want GRUB to put images under a directory +other than @file{/boot}, you need to specify the option +@option{--boot-directory}. The typical usage is that you create a GRUB boot floppy with a filesystem. Here is an example: @example @group # @kbd{mke2fs /dev/fd0} # @kbd{mount -t ext2 /dev/fd0 /mnt} -# @kbd{grub-install --root-directory=/mnt fd0} +# @kbd{mkdir /mnt/boot} +# @kbd{grub-install --boot-directory=/mnt/boot /dev/fd0} # @kbd{umount /mnt} @end group @end example -Another example is when you have a separate boot partition -which is mounted at @file{/boot}. Since GRUB is a boot loader, it -doesn't know anything about mountpoints at all. Thus, you need to run -@command{grub-install} like this: - -@example -# @kbd{grub-install --root-directory=/boot /dev/hda} -@end example - -By the way, as noted above, it is quite difficult to guess BIOS drives -correctly under a UNIX-like OS. Thus, @command{grub-install} will prompt -you to check if it could really guess the correct mappings, after the -installation. The format is defined in @ref{Device map}. Please be -quite careful. If the output is wrong, it is unlikely that your -computer will be able to boot with no problem. - Some BIOSes have a bug of exposing the first partition of a USB drive as a floppy instead of exposing the USB drive as a hard disk (they call it ``USB-FDD'' boot). In such cases, you need to install like this: From 25a45338751d8ed2f8bed7231380a4e8183e585c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 14 May 2011 22:26:52 +0200 Subject: [PATCH 256/406] Fix few potential memory misusage. * grub-core/font/font.c (load_font_index): Don't free char_index to avoid double free. --- ChangeLog | 7 +++++++ grub-core/font/font.c | 13 ++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 01f216bfb..f316af0b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-05-14 Vladimir Serbinenko + + Fix few potential memory misusage. + + * grub-core/font/font.c (load_font_index): Don't free char_index to + avoid double free. + 2011-05-14 Vladimir Serbinenko * docs/grub.texi (Installation): Fix several outdated claims. diff --git a/grub-core/font/font.c b/grub-core/font/font.c index ef6caf77b..26eac4c05 100644 --- a/grub-core/font/font.c +++ b/grub-core/font/font.c @@ -316,10 +316,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct return 1; font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t)); if (!font->bmp_idx) - { - grub_free (font->char_index); - return 1; - } + return 1; grub_memset (font->bmp_idx, 0xff, 0x10000 * sizeof (grub_uint16_t)); @@ -494,7 +491,7 @@ grub_font_load (const char *filename) #endif /* Allocate the font object. */ - font = (grub_font_t) grub_malloc (sizeof (struct grub_font)); + font = (grub_font_t) grub_zalloc (sizeof (struct grub_font)); if (!font) goto fail; @@ -640,6 +637,11 @@ grub_font_load (const char *filename) return 0; fail: + if (file) + grub_file_close (file); + if (font) + font->file = 0; + free_font (font); return 1; } @@ -799,6 +801,7 @@ free_font (grub_font_t font) grub_free (font->name); grub_free (font->family); grub_free (font->char_index); + grub_free (font->bmp_idx); grub_free (font); } } From b25db2188538c628f79ded0a3e17f77ccb8ebfa3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 14 May 2011 22:29:27 +0200 Subject: [PATCH 257/406] * grub-core/font/font_cmd.c (loadfont_command): Set grub_errno on error if not already done. --- ChangeLog | 8 ++++++++ grub-core/font/font_cmd.c | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f316af0b1..bb4d0aade 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,17 @@ +2011-05-14 Vladimir Serbinenko + + * grub-core/font/font_cmd.c (loadfont_command): Set grub_errno + on error if not already done. + 2011-05-14 Vladimir Serbinenko Fix few potential memory misusage. * grub-core/font/font.c (load_font_index): Don't free char_index to avoid double free. + (grub_font_load): Zero-fill font at alloc for safety. + Close file on error. + (free_font): Free bmp_idx. 2011-05-14 Vladimir Serbinenko diff --git a/grub-core/font/font_cmd.c b/grub-core/font/font_cmd.c index 8b00dd8b9..98f0b88d6 100644 --- a/grub-core/font/font_cmd.c +++ b/grub-core/font/font_cmd.c @@ -33,7 +33,11 @@ loadfont_command (grub_command_t cmd __attribute__ ((unused)), while (argc--) if (grub_font_load (*args++) != 0) - return GRUB_ERR_BAD_FONT; + { + if (!grub_errno) + return grub_error (GRUB_ERR_BAD_FONT, "invalid font"); + return grub_errno; + } return GRUB_ERR_NONE; } From 3d2c7e3591e3f0d4949e5822bfafb67f2b0dc476 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 14 May 2011 22:35:56 +0200 Subject: [PATCH 258/406] * grub-core/kern/dl.c (grub_dl_unload): Don't decrease reference counter on dependencies since grub_dl_unref already handles this. --- ChangeLog | 5 +++++ grub-core/kern/dl.c | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index bb4d0aade..6777eb0f4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-14 Vladimir Serbinenko + + * grub-core/kern/dl.c (grub_dl_unload): Don't decrease reference + counter on dependencies since grub_dl_unref already handles this. + 2011-05-14 Vladimir Serbinenko * grub-core/font/font_cmd.c (loadfont_command): Set grub_errno diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index c5e2888cd..6104f229e 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -683,8 +683,7 @@ grub_dl_unload (grub_dl_t mod) { depn = dep->next; - if (! grub_dl_unref (dep->mod)) - grub_dl_unload (dep->mod); + grub_dl_unload (dep->mod); grub_free (dep); } From 576881217f04b6938f3dd8e15ce93ad6fa3170cd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 14 May 2011 22:42:28 +0200 Subject: [PATCH 259/406] * grub-core/kern/dl.c (grub_dl_load_file): Decrease ref counter rather than resetting it to allow modules to reference themselves in init. --- ChangeLog | 6 ++++++ grub-core/kern/dl.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 6777eb0f4..429467d02 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-05-14 Vladimir Serbinenko + + * grub-core/kern/dl.c (grub_dl_load_file): Decrease ref counter + rather than resetting it to allow modules to reference themselves + in init. + 2011-05-14 Vladimir Serbinenko * grub-core/kern/dl.c (grub_dl_unload): Don't decrease reference diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 6104f229e..623e0cbcb 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -626,7 +626,7 @@ grub_dl_load_file (const char *filename) return 0; } - mod->ref_count = 0; + mod->ref_count--; return mod; } From de04eecfa9df533f69f59a4be23e1ebbe8fe898a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 14 May 2011 22:44:53 +0200 Subject: [PATCH 260/406] * grub-core/kern/mm.c (grub_memalign): Disable auto-unloadding of unused modules since currently referrence counter isn't reliable and there isn't much memory to recover there anyway. --- ChangeLog | 6 ++++++ grub-core/kern/mm.c | 2 ++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 429467d02..a0efb24e8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-05-14 Vladimir Serbinenko + + * grub-core/kern/mm.c (grub_memalign): Disable auto-unloadding of + unused modules since currently referrence counter isn't reliable and + there isn't much memory to recover there anyway. + 2011-05-14 Vladimir Serbinenko * grub-core/kern/dl.c (grub_dl_load_file): Decrease ref counter diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c index 8d9b5db78..d54f3f240 100644 --- a/grub-core/kern/mm.c +++ b/grub-core/kern/mm.c @@ -311,11 +311,13 @@ grub_memalign (grub_size_t align, grub_size_t size) count++; goto again; +#if 0 case 1: /* Unload unneeded modules. */ grub_dl_unload_unneeded (); count++; goto again; +#endif default: break; From 90c571a47fb9a100938707fdeba81e6d6fea4c33 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 14 May 2011 22:47:28 +0200 Subject: [PATCH 261/406] * util/grub.d/10_linux.in: Autoload gzio since it's needed on some platforms if kernel is compressed. --- ChangeLog | 5 +++++ util/grub.d/10_linux.in | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/ChangeLog b/ChangeLog index a0efb24e8..68a13a72e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-14 Vladimir Serbinenko + + * util/grub.d/10_linux.in: Autoload gzio since it's needed on some + platforms if kernel is compressed. + 2011-05-14 Vladimir Serbinenko * grub-core/kern/mm.c (grub_memalign): Disable auto-unloadding of diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index 3c3a2a5d5..1d1eb403f 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -98,6 +98,10 @@ EOF EOF fi + cat << EOF + insmod gzio +EOF + if [ x$dirname = x/ ]; then if [ -z "${prepare_root_cache}" ]; then prepare_root_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/")" From 6ada82d14df6c66cbb433d383e5f2d86e865d7c2 Mon Sep 17 00:00:00 2001 From: Jordan Uggla Date: Sat, 14 May 2011 22:49:53 +0200 Subject: [PATCH 262/406] * docs/grub.texi (Invoking grub-install): Fix additional outdated claims and add some clarification. --- ChangeLog | 5 +++++ docs/grub.texi | 27 ++++++++++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 68a13a72e..9575204c2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-14 Jordan Uggla + + * docs/grub.texi (Invoking grub-install): Fix additional outdated claims + and add some clarification. + 2011-05-14 Vladimir Serbinenko * util/grub.d/10_linux.in: Autoload gzio since it's needed on some diff --git a/docs/grub.texi b/docs/grub.texi index 0b7e1098c..b11e3836f 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -4165,15 +4165,28 @@ Print a summary of the command-line options and exit. @item --version Print the version number of GRUB and exit. -@item --root-directory=@var{dir} -Install GRUB images under the directory @var{dir} instead of the root -directory. This option is useful when you want to install GRUB into a -separate partition or a removable disk. Here is an example in which -you have a separate @dfn{boot} partition which is mounted on -@file{/boot}: +@item --boot-directory=@var{dir} +Install GRUB images under the directory @file{@var{dir}/grub/} +This option is useful when you want to install GRUB into a +separate partition or a removable disk. +If this option is not specified then it defaults to @file{/boot}, so @example -@kbd{grub-install --root-directory=/boot hd0} +@kbd{grub-install /dev/sda} +@end example + +is equivalent to + +@example +@kbd{grub-install --boot-directory=/boot/ /dev/sda} +@end example + +Here is an example in which you have a separate @dfn{boot} partition which is +mounted on +@file{/mnt/boot}: + +@example +@kbd{grub-install --boot-directory=/mnt/boot /dev/sdb} @end example @item --recheck From 983b414d776f638e9cb80988fcce7255cf162dd2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 15 May 2011 10:23:02 +0200 Subject: [PATCH 263/406] * grub-core/fs/btrfs.c (grub_btrfs_read_logical): Silence spurious warning. Move variables before code while on it. --- ChangeLog | 5 +++++ grub-core/fs/btrfs.c | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 505be20c2..ab247969e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-15 Vladimir Serbinenko + + * grub-core/fs/btrfs.c (grub_btrfs_read_logical): Silence spurious + warning. Move variables before code while on it. + 2011-05-15 Vladimir Serbinenko Fuloong support. diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 42aa257d9..59e91b552 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -589,10 +589,14 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, struct grub_btrfs_key *key; struct grub_btrfs_chunk_item *chunk; grub_uint64_t csize; - grub_err_t err; + grub_err_t err = 0; struct grub_btrfs_key key_out; int challoc = 0; grub_device_t dev; + struct grub_btrfs_key key_in; + grub_size_t chsize; + grub_disk_addr_t chaddr; + grub_dprintf ("btrfs", "searching for laddr %" PRIxGRUB_UINT64_T "\n", addr); for (ptr = data->sblock.bootstrap_mapping; @@ -616,9 +620,7 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, + sizeof (struct grub_btrfs_chunk_stripe) * grub_le_to_cpu16 (chunk->nstripes); } - struct grub_btrfs_key key_in; - grub_size_t chsize; - grub_disk_addr_t chaddr; + key_in.object_id = GRUB_BTRFS_OBJECT_ID_CHUNK; key_in.type = GRUB_BTRFS_ITEM_TYPE_CHUNK; key_in.offset = addr; From 67b1e5c9079ae6fb734e69aa07a78e6a52d5eb56 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 15 May 2011 12:32:37 +0200 Subject: [PATCH 264/406] Fix compilation errors. * grub-core/term/ns8250.c (serial_get_divisor): Declare 'port' as potentially unused. * grub-core/loader/i386/linux.c (grub_linux_setup_video): Handle GRUB_VIDEO_DRIVER_SIS315PRO. * grub-core/bus/cs5536.c (grub_cs5536_init_geode): Restrict DIVIL init to loongson machines. --- ChangeLog | 11 +++++++++++ grub-core/bus/cs5536.c | 2 ++ grub-core/loader/i386/linux.c | 1 + grub-core/term/ns8250.c | 2 +- 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a2927df11..98418f4a0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-05-15 Vladimir Serbinenko + + Fix compilation errors. + + * grub-core/term/ns8250.c (serial_get_divisor): Declare 'port' as + potentially unused. + * grub-core/loader/i386/linux.c (grub_linux_setup_video): + Handle GRUB_VIDEO_DRIVER_SIS315PRO. + * grub-core/bus/cs5536.c (grub_cs5536_init_geode): Restrict DIVIL init + to loongson machines. + 2011-05-15 Vladimir Serbinenko Several FS mtime support. diff --git a/grub-core/bus/cs5536.c b/grub-core/bus/cs5536.c index f1a564251..ae3c5c878 100644 --- a/grub-core/bus/cs5536.c +++ b/grub-core/bus/cs5536.c @@ -269,6 +269,7 @@ grub_cs5536_init_geode (grub_pci_device_t dev) GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_PM); /* Setup DIVIL. */ +#ifdef GRUB_MACHINE_MIPS_LOONGSON switch (grub_arch_machine) { case GRUB_ARCH_MACHINE_YEELOONG: @@ -288,6 +289,7 @@ grub_cs5536_init_geode (grub_pci_device_t dev) | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1); break; } +#endif grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_PRIMARY_MASK, (~GRUB_CS5536_DIVIL_LPC_INTERRUPTS) & 0xffff); grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_LPC_MASK, diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index f19f471ab..dc2af4093 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -367,6 +367,7 @@ grub_linux_setup_video (struct linux_kernel_params *params) /* FIXME: check if better id is available. */ case GRUB_VIDEO_DRIVER_SM712: + case GRUB_VIDEO_DRIVER_SIS315PRO: case GRUB_VIDEO_DRIVER_VGA: case GRUB_VIDEO_DRIVER_CIRRUS: case GRUB_VIDEO_DRIVER_BOCHS: diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c index b63ee14d9..996fc81f3 100644 --- a/grub-core/term/ns8250.c +++ b/grub-core/term/ns8250.c @@ -37,7 +37,7 @@ static const grub_port_t serial_hw_io_addr[] = GRUB_MACHINE_SERIAL_PORTS; /* Convert speed to divisor. */ static unsigned short -serial_get_divisor (const struct grub_serial_port *port, +serial_get_divisor (const struct grub_serial_port *port __attribute__ ((unused)), const struct grub_serial_config *config) { unsigned int i; From c3fc520c0d5b05cc3f75b20a42f51f8fd5ca8519 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 15 May 2011 15:41:23 +0200 Subject: [PATCH 265/406] * grub-core/bus/cs5536.c: Don't include grub/machine/kernel.h on non-loongson. * grub-core/kern/mips/dl.c (grub_arch_dl_init_linker): Fix argument to grub_dl_register_symbol. --- ChangeLog | 7 +++++++ grub-core/bus/cs5536.c | 2 ++ grub-core/kern/mips/dl.c | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 98418f4a0..cdf602203 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-05-15 Vladimir Serbinenko + + * grub-core/bus/cs5536.c: Don't include grub/machine/kernel.h on + non-loongson. + * grub-core/kern/mips/dl.c (grub_arch_dl_init_linker): Fix argument + to grub_dl_register_symbol. + 2011-05-15 Vladimir Serbinenko Fix compilation errors. diff --git a/grub-core/bus/cs5536.c b/grub-core/bus/cs5536.c index ae3c5c878..58ffeb60a 100644 --- a/grub-core/bus/cs5536.c +++ b/grub-core/bus/cs5536.c @@ -21,7 +21,9 @@ #include #include #include +#ifdef GRUB_MACHINE_MIPS_LOONGSON #include +#endif #include diff --git a/grub-core/kern/mips/dl.c b/grub-core/kern/mips/dl.c index e17e9f30b..2ddbed3e6 100644 --- a/grub-core/kern/mips/dl.c +++ b/grub-core/kern/mips/dl.c @@ -234,6 +234,6 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) void grub_arch_dl_init_linker (void) { - grub_dl_register_symbol ("__gnu_local_gp", &__gnu_local_gp_dummy, 0); + grub_dl_register_symbol ("__gnu_local_gp", &__gnu_local_gp_dummy, 0, 0); } From 736e0ade54b07ab10e8d98b54ecb6c43e779b04d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 16 May 2011 02:34:58 +0200 Subject: [PATCH 266/406] Fuloong video init support. * include/grub/vga.h (grub_vga_write_arx): inb monochrome address as well. (grub_vga_read_arx): New function. * grub-core/video/sis315pro.c (GRUB_SIS315PRO_MMIO_SPACE): New definition. (framebuffer): New members io, mmioptr and mmiobase. (read_sis_cmd): New function. (write_sis_cmd): Likewise. (grub_video_sis315pro_setup): Do the initialisation. Use 640x480 rather than 640x400. * grub-core/video/sis315_init.c: New file. --- grub-core/video/sis315_init.c | 158 ++++++++++++++++++++++++++ grub-core/video/sis315pro.c | 208 +++++++++++++++++++++++++++++++++- include/grub/vga.h | 15 ++- 3 files changed, 377 insertions(+), 4 deletions(-) create mode 100644 grub-core/video/sis315_init.c diff --git a/grub-core/video/sis315_init.c b/grub-core/video/sis315_init.c new file mode 100644 index 000000000..ae5c1419c --- /dev/null +++ b/grub-core/video/sis315_init.c @@ -0,0 +1,158 @@ +static const struct { grub_uint8_t reg; grub_uint8_t val; } sr_dump [] = +{ + { 0x28, 0x81 }, + { 0x2a, 0x00 }, + { 0x29, 0xe1 }, + { 0x2b, 0x81 }, + { 0x2d, 0x00 }, + { 0x2c, 0xe1 }, + { 0x2e, 0x81 }, + { 0x30, 0x00 }, + { 0x2f, 0xe1 }, + { 0x28, 0x01 }, + { 0x29, 0x22 }, + { 0x28, 0x3b }, + { 0x29, 0x22 }, + { 0x2a, 0x01 }, + { 0x2e, 0x01 }, + { 0x2f, 0x22 }, + { 0x2e, 0x3b }, + { 0x2f, 0x22 }, + { 0x30, 0x01 }, + { 0x15, 0x00 }, + { 0x1b, 0x30 }, + + { 0x16, 0x0f }, + { 0x16, 0x8f }, + { 0x17, 0xba }, + { 0x16, 0x0f }, + { 0x16, 0x8f }, + { 0x1f, 0x00 }, + { 0x20, 0x20 }, + { 0x23, 0xf6 }, + { 0x24, 0x0d }, + { 0x25, 0x33 }, + { 0x21, 0x84 }, + { 0x22, 0x00 }, + { 0x27, 0x1f }, + { 0x31, 0x00 }, + { 0x33, 0x00 }, + { 0x32, 0x11 }, + + { 0x25, 0x33 }, + + { 0x05, 0x86 }, + { 0x01, 0x20 }, + { 0x32, 0x11 }, + { 0x1e, 0x00 }, + { 0x1d, 0x00 }, + { 0x00, 0x03 }, + { 0x01, 0x21 }, + { 0x02, 0x0f }, + { 0x03, 0x00 }, + { 0x04, 0x0e }, + + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0e, 0x00 }, + { 0x37, 0x00 }, + + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, + { 0x0c, 0x05 }, + { 0x0e, 0x00 }, + + { 0x0e, 0x00 }, + + { 0x10, 0x0b }, + { 0x31, 0x00 }, + { 0x2b, 0x01 }, + { 0x2c, 0xe1 }, + { 0x2b, 0x1b }, + { 0x2c, 0xe1 }, + { 0x2d, 0x01 }, + { 0x3d, 0x00 }, + { 0x08, 0x84 }, + { 0x09, 0x00 }, + { 0x3d, 0x01 }, + { 0x1f, 0x00 }, + { 0x06, 0x02 }, + + { 0x0f, 0x00 }, + { 0x17, 0xba }, + { 0x21, 0xa4 }, + { 0x32, 0x11 }, + { 0x07, 0x18 }, + + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + + { 0x01, 0x01 }, + { 0x21, 0x84 }, + { 0x01, 0x21 }, + { 0x16, 0x8f }, + { 0x18, 0xa9 }, + { 0x19, 0xa0 }, + { 0x1b, 0x30 }, + { 0x17, 0xb8 }, + { 0x19, 0xa3 }, + { 0x13, 0x00 }, + { 0x14, 0x00 }, + { 0x14, 0x02 }, + { 0x15, 0x00 }, + { 0x16, 0x0f }, + { 0x16, 0x8f }, + { 0x1d, 0x00 }, + { 0x14, 0x00 }, + { 0x14, 0x01 }, + { 0x15, 0x00 }, + { 0x16, 0x0f }, + { 0x16, 0x8f }, + { 0x1d, 0x00 }, + { 0x14, 0x01 }, + { 0x14, 0x01 }, + { 0x15, 0x10 }, + { 0x13, 0x35 }, + { 0x14, 0x51 }, + { 0x16, 0x0f }, + { 0x16, 0x8f }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x11 }, + { 0x1d, 0x11 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x1d, 0x00 }, + { 0x17, 0xba }, + { 0x19, 0xa0 }, + { 0x19, 0xa0 }, + { 0x01, 0x01 }, + { 0x16, 0x0f }, + { 0x18, 0xa9 }, + { 0x19, 0xa0 }, + { 0x1b, 0x30 }, + { 0x21, 0xa4 }, + { 0x05, 0x86 }, +}; + +static const grub_uint8_t gr[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; diff --git a/grub-core/video/sis315pro.c b/grub-core/video/sis315pro.c index 59ff6432d..22064c91e 100644 --- a/grub-core/video/sis315pro.c +++ b/grub-core/video/sis315pro.c @@ -30,6 +30,7 @@ #define GRUB_SIS315PRO_PCIID 0x03251039 #define GRUB_SIS315PRO_TOTAL_MEMORY_SPACE 0x800000 +#define GRUB_SIS315PRO_MMIO_SPACE 0x1000 static struct { @@ -39,9 +40,26 @@ static struct grub_uint8_t *ptr; int mapped; grub_uint32_t base; + grub_uint32_t mmiobase; + volatile grub_uint32_t *mmioptr; grub_pci_device_t dev; + grub_port_t io; } framebuffer; +static grub_uint8_t +read_sis_cmd (grub_uint8_t addr) +{ + grub_outb (addr, framebuffer.io + 0x44); + return grub_inb (framebuffer.io + 0x45); +} + +static void +write_sis_cmd (grub_uint8_t val, grub_uint8_t addr) +{ + grub_outb (addr, framebuffer.io + 0x44); + grub_outb (val, framebuffer.io + 0x45); +} + #ifndef TEST static grub_err_t grub_video_sis315pro_video_init (void) @@ -63,6 +81,8 @@ grub_video_sis315pro_video_fini (void) } #endif +#include "sis315_init.c" + static grub_err_t grub_video_sis315pro_setup (unsigned int width, unsigned int height, unsigned int mode_type, @@ -71,6 +91,7 @@ grub_video_sis315pro_setup (unsigned int width, unsigned int height, int depth; grub_err_t err; int found = 0; + unsigned i; #ifndef TEST auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))); @@ -89,7 +110,12 @@ grub_video_sis315pro_setup (unsigned int width, unsigned int height, found = 1; addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - framebuffer.base = grub_pci_read (addr); + framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK; + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1); + framebuffer.mmiobase = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK; + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG2); + framebuffer.io = (grub_pci_read (addr) & GRUB_PCI_ADDR_IO_MASK) + + GRUB_MACHINE_PCI_IO_BASE; framebuffer.dev = dev; return 1; @@ -99,7 +125,7 @@ grub_video_sis315pro_setup (unsigned int width, unsigned int height, depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; - if ((width != 640 && width != 0) || (height != 400 && height != 0) + if ((width != 640 && width != 0) || (height != 480 && height != 0) || (depth != 8 && depth != 0)) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "Only 640x400x8 is supported"); @@ -110,7 +136,7 @@ grub_video_sis315pro_setup (unsigned int width, unsigned int height, #endif /* Fill mode info details. */ framebuffer.mode_info.width = 640; - framebuffer.mode_info.height = 400; + framebuffer.mode_info.height = 480; framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; framebuffer.mode_info.bpp = 8; framebuffer.mode_info.bytes_per_pixel = 1; @@ -129,12 +155,49 @@ grub_video_sis315pro_setup (unsigned int width, unsigned int height, = grub_video_get_blit_format (&framebuffer.mode_info); #endif +#ifndef TEST + if (found && (framebuffer.base == 0 || framebuffer.mmiobase == 0)) + { + grub_pci_address_t addr; + /* FIXME: choose address dynamically if needed. */ + framebuffer.base = 0x40000000; + framebuffer.mmiobase = 0x04000000; + framebuffer.io = 0xb300; + + addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_ADDRESS_REG0); + grub_pci_write (addr, framebuffer.base | GRUB_PCI_ADDR_MEM_PREFETCH); + + addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_ADDRESS_REG1); + grub_pci_write (addr, framebuffer.mmiobase); + + addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_ADDRESS_REG2); + grub_pci_write (addr, framebuffer.io | GRUB_PCI_ADDR_SPACE_IO); + + /* Set latency. */ + addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_CACHELINE); + grub_pci_write (addr, 0x80004700); + + /* Enable address spaces. */ + addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_COMMAND); + grub_pci_write (addr, 0x7); + + addr = grub_pci_make_address (framebuffer.dev, 0x30); + grub_pci_write (addr, 0x04060001); + + framebuffer.io += GRUB_MACHINE_PCI_IO_BASE; + } +#endif + + /* We can safely discard volatile attribute. */ #ifndef TEST framebuffer.ptr = (void *) grub_pci_device_map_range (framebuffer.dev, framebuffer.base, GRUB_SIS315PRO_TOTAL_MEMORY_SPACE); + framebuffer.mmioptr = grub_pci_device_map_range (framebuffer.dev, + framebuffer.mmiobase, + GRUB_SIS315PRO_MMIO_SPACE); #endif framebuffer.mapped = 1; @@ -144,6 +207,145 @@ grub_video_sis315pro_setup (unsigned int width, unsigned int height, framebuffer.mode_info.height * framebuffer.mode_info.pitch); #endif + grub_outb (GRUB_VGA_IO_MISC_NEGATIVE_VERT_POLARITY + | GRUB_VGA_IO_MISC_NEGATIVE_HORIZ_POLARITY + | GRUB_VGA_IO_MISC_UPPER_64K + | GRUB_VGA_IO_MISC_EXTERNAL_CLOCK_0 + | GRUB_VGA_IO_MISC_28MHZ + | GRUB_VGA_IO_MISC_ENABLE_VRAM_ACCESS + | GRUB_VGA_IO_MISC_COLOR, + GRUB_VGA_IO_MISC_WRITE + GRUB_MACHINE_PCI_IO_BASE); + + grub_vga_sr_write (0x86, 5); + for (i = 6; i <= 0x27; i++) + grub_vga_sr_write (0, i); + + for (i = 0x31; i <= 0x3d; i++) + grub_vga_sr_write (0, i); + + for (i = 0; i < ARRAY_SIZE (sr_dump); i++) + grub_vga_sr_write (sr_dump[i].val, sr_dump[i].reg); + + for (i = 0x30; i < 0x40; i++) + grub_vga_cr_write (0, i); + + grub_vga_cr_write (0x77, 0x40); + grub_vga_cr_write (0x77, 0x41); + grub_vga_cr_write (0x00, 0x42); + grub_vga_cr_write (0x5b, 0x43); + grub_vga_cr_write (0x00, 0x44); + grub_vga_cr_write (0x23, 0x48); + grub_vga_cr_write (0xaa, 0x49); + grub_vga_cr_write (0x02, 0x37); + grub_vga_cr_write (0x20, 0x5b); + grub_vga_cr_write (0x00, 0x83); + grub_vga_cr_write (0x80, 0x63); + + grub_vga_cr_write (0x0c, GRUB_VGA_CR_VSYNC_END); + grub_vga_cr_write (0x5f, GRUB_VGA_CR_HTOTAL); + grub_vga_cr_write (0x4f, GRUB_VGA_CR_HORIZ_END); + grub_vga_cr_write (0x50, GRUB_VGA_CR_HBLANK_START); + grub_vga_cr_write (0x82, GRUB_VGA_CR_HBLANK_END); + grub_vga_cr_write (0x54, GRUB_VGA_CR_HORIZ_SYNC_PULSE_START); + grub_vga_cr_write (0x80, GRUB_VGA_CR_HORIZ_SYNC_PULSE_END); + grub_vga_cr_write (0x0b, GRUB_VGA_CR_VERT_TOTAL); + grub_vga_cr_write (0x3e, GRUB_VGA_CR_OVERFLOW); + grub_vga_cr_write (0x00, GRUB_VGA_CR_BYTE_PANNING); + grub_vga_cr_write (0x40, GRUB_VGA_CR_CELL_HEIGHT); + grub_vga_cr_write (0x00, GRUB_VGA_CR_CURSOR_START); + grub_vga_cr_write (0x00, GRUB_VGA_CR_CURSOR_END); + grub_vga_cr_write (0x00, GRUB_VGA_CR_START_ADDR_HIGH_REGISTER); + grub_vga_cr_write (0x00, GRUB_VGA_CR_START_ADDR_LOW_REGISTER); + grub_vga_cr_write (0x00, GRUB_VGA_CR_CURSOR_ADDR_HIGH); + grub_vga_cr_write (0x00, GRUB_VGA_CR_CURSOR_ADDR_LOW); + grub_vga_cr_write (0xea, GRUB_VGA_CR_VSYNC_START); + grub_vga_cr_write (0x8c, GRUB_VGA_CR_VSYNC_END); + grub_vga_cr_write (0xdf, GRUB_VGA_CR_VDISPLAY_END); + grub_vga_cr_write (0x28, GRUB_VGA_CR_PITCH); + grub_vga_cr_write (0x40, GRUB_VGA_CR_UNDERLINE_LOCATION); + grub_vga_cr_write (0xe7, GRUB_VGA_CR_VERTICAL_BLANK_START); + grub_vga_cr_write (0x04, GRUB_VGA_CR_VERTICAL_BLANK_END); + grub_vga_cr_write (0xa3, GRUB_VGA_CR_MODE); + grub_vga_cr_write (0xff, GRUB_VGA_CR_LINE_COMPARE); + + grub_vga_cr_write (0x0c, GRUB_VGA_CR_VSYNC_END); + grub_vga_cr_write (0x5f, GRUB_VGA_CR_HTOTAL); + grub_vga_cr_write (0x4f, GRUB_VGA_CR_HORIZ_END); + grub_vga_cr_write (0x50, GRUB_VGA_CR_HBLANK_START); + grub_vga_cr_write (0x82, GRUB_VGA_CR_HBLANK_END); + grub_vga_cr_write (0x55, GRUB_VGA_CR_HORIZ_SYNC_PULSE_START); + grub_vga_cr_write (0x81, GRUB_VGA_CR_HORIZ_SYNC_PULSE_END); + grub_vga_cr_write (0x0b, GRUB_VGA_CR_VERT_TOTAL); + grub_vga_cr_write (0x3e, GRUB_VGA_CR_OVERFLOW); + grub_vga_cr_write (0xe9, GRUB_VGA_CR_VSYNC_START); + grub_vga_cr_write (0x8b, GRUB_VGA_CR_VSYNC_END); + grub_vga_cr_write (0xdf, GRUB_VGA_CR_VDISPLAY_END); + grub_vga_cr_write (0xe7, GRUB_VGA_CR_VERTICAL_BLANK_START); + grub_vga_cr_write (0x04, GRUB_VGA_CR_VERTICAL_BLANK_END); + grub_vga_cr_write (0x40, GRUB_VGA_CR_CELL_HEIGHT); + grub_vga_cr_write (0x50, GRUB_VGA_CR_PITCH); + + grub_vga_cr_write (0x00, 0x19); + grub_vga_cr_write (0x00, 0x1a); + grub_vga_cr_write (0x6c, 0x52); + grub_vga_cr_write (0x2e, 0x34); + grub_vga_cr_write (0x00, 0x31); + + + grub_vga_cr_write (0, GRUB_VGA_CR_START_ADDR_HIGH_REGISTER); + grub_vga_cr_write (0, GRUB_VGA_CR_START_ADDR_LOW_REGISTER); + + for (i = 0; i < 16; i++) + grub_vga_write_arx (i, i); + grub_vga_write_arx (1, GRUB_VGA_ARX_MODE); + grub_vga_write_arx (0, GRUB_VGA_ARX_OVERSCAN); + grub_vga_write_arx (0, GRUB_VGA_ARX_COLOR_PLANE_ENABLE); + grub_vga_write_arx (0, GRUB_VGA_ARX_HORIZONTAL_PANNING); + grub_vga_write_arx (0, GRUB_VGA_ARX_COLOR_SELECT); + + grub_outb (0xff, GRUB_VGA_IO_PIXEL_MASK + GRUB_MACHINE_PCI_IO_BASE); + + for (i = 0; i < ARRAY_SIZE (gr); i++) + grub_vga_gr_write (gr[i], i); + + for (i = 0; i < GRUB_VIDEO_FBSTD_NUMCOLORS; i++) + grub_vga_palette_write (i, grub_video_fbstd_colors[i].r, + grub_video_fbstd_colors[i].g, + grub_video_fbstd_colors[i].b); + +#if 1 + { + if (read_sis_cmd (0x5) != 0xa1) + write_sis_cmd (0x86, 0x5); + + write_sis_cmd (read_sis_cmd (0x20) | 0xa1, 0x20); + write_sis_cmd (read_sis_cmd (0x1e) | 0xda, 0x1e); + +#define IND_SIS_CMDQUEUE_SET 0x26 +#define IND_SIS_CMDQUEUE_THRESHOLD 0x27 + +#define COMMAND_QUEUE_THRESHOLD 0x1F +#define SIS_CMD_QUEUE_RESET 0x01 + +#define SIS_AGP_CMDQUEUE_ENABLE 0x80 /* 315/330/340 series SR26 */ +#define SIS_VRAM_CMDQUEUE_ENABLE 0x40 +#define SIS_MMIO_CMD_ENABLE 0x20 +#define SIS_CMD_QUEUE_SIZE_512k 0x00 +#define SIS_CMD_QUEUE_SIZE_1M 0x04 +#define SIS_CMD_QUEUE_SIZE_2M 0x08 +#define SIS_CMD_QUEUE_SIZE_4M 0x0C +#define SIS_CMD_QUEUE_RESET 0x01 +#define SIS_CMD_AUTO_CORR 0x02 + + + write_sis_cmd (COMMAND_QUEUE_THRESHOLD, IND_SIS_CMDQUEUE_THRESHOLD); + write_sis_cmd (SIS_CMD_QUEUE_RESET, IND_SIS_CMDQUEUE_SET); + framebuffer.mmioptr[0x85C4 / 4] = framebuffer.mmioptr[0x85C8 / 4]; + write_sis_cmd (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR, IND_SIS_CMDQUEUE_SET); + framebuffer.mmioptr[0x85C0 / 4] = (0x1000000 - (512 * 1024)); + } +#endif + #ifndef TEST err = grub_video_fb_create_render_target_from_pointer (&framebuffer .render_target, diff --git a/include/grub/vga.h b/include/grub/vga.h index 7f112d83a..bf4439599 100644 --- a/include/grub/vga.h +++ b/include/grub/vga.h @@ -84,8 +84,8 @@ enum { GRUB_VGA_IO_MISC_COLOR = 0x01, GRUB_VGA_IO_MISC_ENABLE_VRAM_ACCESS = 0x02, - GRUB_VGA_IO_MISC_EXTERNAL_CLOCK_0 = 0x08, GRUB_VGA_IO_MISC_28MHZ = 0x04, + GRUB_VGA_IO_MISC_EXTERNAL_CLOCK_0 = 0x08, GRUB_VGA_IO_MISC_UPPER_64K = 0x20, GRUB_VGA_IO_MISC_NEGATIVE_HORIZ_POLARITY = 0x40, GRUB_VGA_IO_MISC_NEGATIVE_VERT_POLARITY = 0x80, @@ -290,11 +290,24 @@ static inline void grub_vga_write_arx (grub_uint8_t val, grub_uint8_t addr) { grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_INPUT_STATUS1_REGISTER); + grub_inb (GRUB_MACHINE_PCI_IO_BASE + 0x3ba); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX); grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX_READ); grub_outb (val, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX); } +static inline grub_uint8_t +grub_vga_read_arx (grub_uint8_t addr) +{ + grub_uint8_t val; + grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_INPUT_STATUS1_REGISTER); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX); + val = grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX_READ); + grub_outb (val, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX); + return val; +} + struct grub_video_hw_config { unsigned vertical_total; From 638dbe4f27f481d57de39f2847e4c2b8992dbfcf Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 16 May 2011 02:35:47 +0200 Subject: [PATCH 267/406] add changelog entry --- ChangeLog | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/ChangeLog b/ChangeLog index cdf602203..d0b3b1a11 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2011-05-16 Vladimir Serbinenko + + Fuloong video init support. + + * include/grub/vga.h (grub_vga_write_arx): inb monochrome address as + well. + (grub_vga_read_arx): New function. + * grub-core/video/sis315pro.c (GRUB_SIS315PRO_MMIO_SPACE): New + definition. + (framebuffer): New members io, mmioptr and mmiobase. + (read_sis_cmd): New function. + (write_sis_cmd): Likewise. + (grub_video_sis315pro_setup): Do the initialisation. Use 640x480 + rather than 640x400. + * grub-core/video/sis315_init.c: New file. + 2011-05-15 Vladimir Serbinenko * grub-core/bus/cs5536.c: Don't include grub/machine/kernel.h on From ff44d107adc5e85155b212211d4e0893d15da30c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 16 May 2011 02:39:25 +0200 Subject: [PATCH 268/406] Skip incorrect USB devices. * grub-core/bus/usb/usb.c (grub_usb_device_initialize): Fail if configcnt == 0. * include/grub/usb.h (grub_usb_err_t): New enum value GRUB_USB_ERR_BADDEVICE. --- ChangeLog | 9 +++++++++ grub-core/bus/usb/usb.c | 6 ++++++ include/grub/usb.h | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index d0b3b1a11..18a95a58e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-05-16 Vladimir Serbinenko + + Skip incorrect USB devices. + + * grub-core/bus/usb/usb.c (grub_usb_device_initialize): Fail if + configcnt == 0. + * include/grub/usb.h (grub_usb_err_t): New enum value + GRUB_USB_ERR_BADDEVICE. + 2011-05-16 Vladimir Serbinenko Fuloong video init support. diff --git a/grub-core/bus/usb/usb.c b/grub-core/bus/usb/usb.c index 005d3bcf0..cde57ced8 100644 --- a/grub-core/bus/usb/usb.c +++ b/grub-core/bus/usb/usb.c @@ -185,6 +185,12 @@ grub_usb_device_initialize (grub_usb_device_t dev) for (i = 0; i < 8; i++) dev->config[i].descconf = NULL; + if (descdev->configcnt == 0) + { + err = GRUB_USB_ERR_BADDEVICE; + goto fail; + } + for (i = 0; i < descdev->configcnt; i++) { int pos; diff --git a/include/grub/usb.h b/include/grub/usb.h index 6f838e4f9..ee133dbf5 100644 --- a/include/grub/usb.h +++ b/include/grub/usb.h @@ -38,7 +38,8 @@ typedef enum GRUB_USB_ERR_BABBLE, GRUB_USB_ERR_TIMEOUT, GRUB_USB_ERR_BITSTUFF, - GRUB_USB_ERR_UNRECOVERABLE + GRUB_USB_ERR_UNRECOVERABLE, + GRUB_USB_ERR_BADDEVICE } grub_usb_err_t; typedef enum From 153a4b552de2dce36071cb3edd532330e67cd477 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 16 May 2011 08:50:21 +0200 Subject: [PATCH 269/406] * grub-core/bus/usb/usbhub.c (attach_root_port): Wait 10ms after enabling port. --- ChangeLog | 5 +++++ grub-core/bus/usb/usbhub.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index 18a95a58e..fc4d68013 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-16 Vladimir Serbinenko + + * grub-core/bus/usb/usbhub.c (attach_root_port): Wait 10ms + after enabling port. + 2011-05-16 Vladimir Serbinenko Skip incorrect USB devices. diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c index 82bb2da1c..fff94a3fc 100644 --- a/grub-core/bus/usb/usbhub.c +++ b/grub-core/bus/usb/usbhub.c @@ -215,6 +215,8 @@ attach_root_port (struct grub_usb_hub *hub, int portno, return; hub->controller->dev->pending_reset = grub_get_time_ms () + 5000; + grub_millisleep (10); + /* Enable the port and create a device. */ dev = grub_usb_hub_add_dev (hub->controller, speed); hub->controller->dev->pending_reset = 0; From c8ecc840d7fa7111577ec3882623bb4b4f496e55 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 16 May 2011 08:51:55 +0200 Subject: [PATCH 270/406] * grub-core/bus/pci.c (grub_memalign_dma32): Always allocate in 64-byte blocks. --- ChangeLog | 5 +++++ grub-core/bus/pci.c | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index fc4d68013..868391294 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-16 Vladimir Serbinenko + + * grub-core/bus/pci.c (grub_memalign_dma32): Always allocate in 64-byte + blocks. + 2011-05-16 Vladimir Serbinenko * grub-core/bus/usb/usbhub.c (attach_root_port): Wait 10ms diff --git a/grub-core/bus/pci.c b/grub-core/bus/pci.c index 4212905f0..51006a20e 100644 --- a/grub-core/bus/pci.c +++ b/grub-core/bus/pci.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,11 @@ GRUB_MOD_LICENSE ("GPLv3+"); struct grub_pci_dma_chunk * grub_memalign_dma32 (grub_size_t align, grub_size_t size) { - void *ret = grub_memalign (align, size); + void *ret; + if (align < 64) + align = 64; + size = ALIGN_UP (size, align); + ret = grub_memalign (align, size); if (!ret) return 0; grub_arch_sync_dma_caches (ret, size); From 8e29b2ffe3c328d3b73fd7fc14ac4d6521154a08 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 16 May 2011 21:50:14 +0200 Subject: [PATCH 271/406] set id on arc disks --- grub-core/disk/arc/arcdisk.c | 65 +++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/grub-core/disk/arc/arcdisk.c b/grub-core/disk/arc/arcdisk.c index 62732c7ad..e8416634a 100644 --- a/grub-core/disk/arc/arcdisk.c +++ b/grub-core/disk/arc/arcdisk.c @@ -25,6 +25,59 @@ static grub_arc_fileno_t last_handle = 0; static char *last_path = NULL; +static int lnum = 0; + +struct arcdisk_hash_ent +{ + char *devpath; + int num; + struct arcdisk_hash_ent *next; +}; + +#define ARCDISK_HASH_SZ 8 +static struct arcdisk_hash_ent *arcdisk_hash[ARCDISK_HASH_SZ]; + +static int +arcdisk_hash_fn (const char *devpath) +{ + int hash = 0; + while (*devpath) + hash ^= *devpath++; + return (hash & (ARCDISK_HASH_SZ - 1)); +} + +static struct arcdisk_hash_ent * +arcdisk_hash_find (const char *devpath) +{ + struct arcdisk_hash_ent *p = arcdisk_hash[arcdisk_hash_fn (devpath)]; + + while (p) + { + if (!grub_strcmp (p->devpath, devpath)) + break; + p = p->next; + } + return p; +} + +static struct arcdisk_hash_ent * +arcdisk_hash_add (char *devpath) +{ + struct arcdisk_hash_ent *p; + struct arcdisk_hash_ent **head = &arcdisk_hash[arcdisk_hash_fn(devpath)]; + + p = grub_malloc (sizeof (*p)); + if (!p) + return NULL; + + p->devpath = devpath; + p->next = *head; + p->num = lnum++; + *head = p; + return p; +} + + static int grub_arcdisk_iterate (int (*hook_in) (const char *name)) { @@ -81,6 +134,8 @@ grub_arcdisk_open (const char *name, grub_disk_t disk) grub_err_t err; grub_arc_err_t r; struct grub_arc_fileinfo info; + struct arcdisk_hash_ent *hash; + if (grub_memcmp (name, "arc/", 4) != 0) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not arc device"); fullname = grub_malloc (2 * grub_strlen (name) + sizeof (RAW_SUFFIX)); @@ -114,6 +169,13 @@ grub_arcdisk_open (const char *name, grub_disk_t disk) grub_memcpy (optr, RAW_SUFFIX, sizeof (RAW_SUFFIX)); disk->data = fullname; grub_dprintf ("arcdisk", "opening %s\n", fullname); + + hash = arcdisk_hash_find (fullname); + if (!hash) + hash = arcdisk_hash_add (fullname); + if (!hash) + return grub_errno; + err = reopen (fullname); if (err) return err; @@ -147,7 +209,8 @@ grub_arcdisk_open (const char *name, grub_disk_t disk) } else disk->total_sectors = (info.end >> 9); - disk->id = 0; /* XXX */ + + disk->id = hash->num; return GRUB_ERR_NONE; } From 276ef9be21c60e2f0ff18daf7278de4a9f2ced9c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 16 May 2011 21:50:24 +0200 Subject: [PATCH 272/406] Fix install message --- util/grub-install.in | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/util/grub-install.in b/util/grub-install.in index 0e0dfe920..ad6ea1037 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -621,8 +621,7 @@ elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${pla fi elif [ x"${target_cpu}-${platform}" = xmips-arc ]; then dvhtool -d "${install_device}" --unix-to-vh "{grubdir}/core.${imgext}" grub - echo "You will have to set boot-device manually. At the Open Firmware prompt, type:" - + echo "You will have to set SystemPartition and OSLoader manually." elif [ x"$platform" = xefi ]; then cp "${grubdir}/core.${imgext}" "${efidir}/${efi_file}" # For old macs. Suggested by Peter Jones. From b6296b3f9e4dcf24dddc6e1dc3a4f1a06b50d850 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 17 May 2011 09:18:53 +0200 Subject: [PATCH 273/406] Add missing ChngeLog line --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 088de8937..815df4dd8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -104,6 +104,7 @@ to 6. * util/grub-install.in: Run dvhtool on ARC. * util/grub-mkimage.c (image_targets): Add mips-arc. + (generate_image): Handle ECOFF output for mips-arc. 2011-05-16 Vladimir Serbinenko From 1b6656d360d0bb6814b68ade969e04e82ad121d6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 17 May 2011 14:04:49 +0200 Subject: [PATCH 274/406] Revert changes to cache_flush.S --- grub-core/kern/mips/cache_flush.S | 4 ---- 1 file changed, 4 deletions(-) diff --git a/grub-core/kern/mips/cache_flush.S b/grub-core/kern/mips/cache_flush.S index 305a8b401..a352fd8ba 100644 --- a/grub-core/kern/mips/cache_flush.S +++ b/grub-core/kern/mips/cache_flush.S @@ -1,6 +1,3 @@ - - /* Qemu doesn't emulate caches. Oh boy. */ -#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS move $t2, $a0 addu $t3, $a0, $a1 srl $t2, $t2, 5 @@ -24,4 +21,3 @@ bne $t1, $zero, 2b addiu $t0, $t0, 0x4 sync -#endif \ No newline at end of file From b38c1d1442aec530c9faf80579ebf0cb8122adb4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 17 May 2011 14:05:52 +0200 Subject: [PATCH 275/406] Fix -O for qemu --- util/grub-mkimage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 480521cd6..5f35c1da0 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -444,7 +444,7 @@ struct image_target_desc image_targets[] = }, { .dirname = "mips-qemu_mips", - .names = { "mips-qemu_mips-elf", NULL }, + .names = { "mipsel-qemu_mips-elf", NULL }, .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_LOONGSON_ELF, From a228ec103a07815c4e08021f946d10b6fb15ac5b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 17 May 2011 14:35:55 +0200 Subject: [PATCH 276/406] enable ATA on qemu-mips --- grub-core/Makefile.core.def | 2 ++ grub-core/disk/ata.c | 22 +++++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 48809a65d..1c0b530a1 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -856,12 +856,14 @@ module = { name = ata; common = disk/ata.c; enable = pci; + enable = mips_qemu_mips; }; module = { name = ata_pthru; common = disk/ata_pthru.c; enable = pci; + enable = mips_qemu_mips; }; module = { diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 391ccb9a2..12e70d91b 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -22,9 +22,13 @@ #include #include #include +#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS #include -#include #include +#else +#define GRUB_MACHINE_PCI_IO_BASE 0xb4000000 +#endif +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -409,6 +413,7 @@ grub_ata_device_initialize (int port, int device, int addr, int addr2) return 0; } +#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS static int NESTED_FUNC_ATTR grub_ata_pciinit (grub_pci_device_t dev, grub_pci_id_t pciid) @@ -524,6 +529,21 @@ grub_ata_initialize (void) grub_pci_iterate (grub_ata_pciinit); return 0; } +#else +static grub_err_t +grub_ata_initialize (void) +{ + int i; + for (i = 0; i < 2; i++) + { + grub_ata_device_initialize (i, 0, grub_ata_ioaddress[i], + grub_ata_ioaddress2[i]); + grub_ata_device_initialize (i, 1, grub_ata_ioaddress[i], + grub_ata_ioaddress2[i]); + } + return 0; +} +#endif static void grub_ata_setlba (struct grub_ata_device *dev, grub_disk_addr_t sector, From dc16af0369c45d8987c7a65fecea962a0b2e6786 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 17 May 2011 15:34:40 +0200 Subject: [PATCH 277/406] make linux loader work on qemu-mips --- grub-core/loader/mips/linux.c | 68 ++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c index e0a0e7c98..722be36a9 100644 --- a/grub-core/loader/mips/linux.c +++ b/grub-core/loader/mips/linux.c @@ -27,6 +27,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -53,12 +54,16 @@ static grub_size_t linux_size; static struct grub_relocator *relocator; static grub_uint8_t *playground; static grub_addr_t target_addr, entry_addr; +#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS +static char *params; +#else static int linux_argc; static grub_off_t argv_off; #ifdef GRUB_MACHINE_MIPS_LOONGSON static grub_off_t envp_off; #endif static grub_off_t rd_addr_arg_off, rd_size_arg_off; +#endif static int initrd_loaded = 0; static grub_err_t @@ -66,8 +71,26 @@ grub_linux_boot (void) { struct grub_relocator32_state state; + grub_memset (&state, 0, sizeof (state)); + /* Boot the kernel. */ state.gpr[1] = entry_addr; + +#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS + { + grub_err_t err; + grub_relocator_chunk_t ch; + + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + ((16 << 20) - 256), + grub_strlen (params) + 1); + if (err) + return err; + grub_strcpy (get_virtual_current_address (ch), params); + } +#endif + +#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS state.gpr[4] = linux_argc; state.gpr[5] = target_addr + argv_off; #ifdef GRUB_MACHINE_MIPS_LOONGSON @@ -76,6 +99,7 @@ grub_linux_boot (void) state.gpr[6] = 0; #endif state.gpr[7] = 0; +#endif state.jumpreg = 1; grub_relocator32_boot (relocator, state); @@ -88,6 +112,11 @@ grub_linux_unload (void) grub_relocator_unload (relocator); grub_dl_unref (my_mod); +#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS + grub_free (params); + params = 0; +#endif + loaded = 0; return GRUB_ERR_NONE; @@ -207,11 +236,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { grub_elf_t elf = 0; - int i; int size; void *extra = NULL; +#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS + int i; grub_uint32_t *linux_argv; char *linux_args; +#endif grub_err_t err; #ifdef GRUB_MACHINE_MIPS_LOONGSON char *linux_envs; @@ -236,6 +267,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), grub_loader_unset (); loaded = 0; +#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS + size = 0; +#else /* For arguments. */ linux_argc = argc; #ifdef GRUB_MACHINE_MIPS_LOONGSON @@ -268,6 +302,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + ALIGN_UP (sizeof ("highmemsize=XXXXXXXXXXXXXXXXXXXX"), 4) + ALIGN_UP (sizeof ("busclock=XXXXXXXXXX"), 4) + ALIGN_UP (sizeof ("cpuclock=XXXXXXXXXX"), 4); +#endif if (grub_elf_is_elf32 (elf)) err = grub_linux_load32 (elf, &extra, size); @@ -282,6 +317,20 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (err) return err; +#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS + /* Create kernel command line. */ + size = grub_loader_cmdline_size(argc, argv); + params = grub_malloc (size + sizeof (LINUX_IMAGE)); + if (! params) + { + grub_linux_unload (); + return grub_errno; + } + + grub_memcpy (params, LINUX_IMAGE, sizeof (LINUX_IMAGE)); + grub_create_loader_cmdline (argc, argv, params + sizeof (LINUX_IMAGE) - 1, + size); +#else linux_argv = extra; argv_off = (grub_uint8_t *) linux_argv - (grub_uint8_t *) playground; extra = linux_argv + (linux_argc + 1 + 2); @@ -362,6 +411,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4); linux_envp[4] = 0; +#endif #endif grub_loader_set (grub_linux_boot, grub_linux_unload, 1); @@ -425,6 +475,21 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), return grub_errno; } +#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS + { + char *tmp; + tmp = grub_xasprintf ("%s rd_start=0x%" PRIxGRUB_ADDR + " rd_size=0x%" PRIxGRUB_ADDR, params, + initrd_dest, size); + if (!tmp) + { + grub_file_close (file); + return grub_errno; + } + grub_free (params); + params = tmp; + } +#else grub_snprintf ((char *) playground + rd_addr_arg_off, sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), "rd_start=0x%llx", (unsigned long long) initrd_dest); @@ -438,6 +503,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), ((grub_uint32_t *) (playground + argv_off))[linux_argc] = target_addr + rd_size_arg_off; linux_argc++; +#endif initrd_loaded = 1; From 90f7ac192fad8a204c1456dd90c239043ce70d91 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 17 May 2011 18:39:32 +0200 Subject: [PATCH 278/406] * grub-core/kern/mips/startup.S (grub_arch_cpuclock): Move to the right place. --- ChangeLog | 5 +++++ grub-core/kern/mips/startup.S | 6 ++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index c0b2e0ce3..5cd5d0b8e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-17 Vladimir Serbinenko + + * grub-core/kern/mips/startup.S (grub_arch_cpuclock): Move to the right + place. + 2011-05-17 Vladimir Serbinenko Reenable qemu-mips port. diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index 58acb00f3..1472aaf8c 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -51,18 +51,16 @@ VARIABLE(grub_prefix) */ . = _start + GRUB_KERNEL_MACHINE_PREFIX_END -VARIABLE (grub_arch_cpuclock) - .long 0 -#ifdef GRUB_MACHINE_MIPS_LOONGSON VARIABLE (grub_arch_busclock) .long 0 +VARIABLE (grub_arch_cpuclock) + .long 0 VARIABLE (grub_arch_memsize) .long 0 VARIABLE (grub_arch_highmemsize) .long 0 VARIABLE (grub_arch_machine) .long GRUB_ARCH_MACHINE_FULOONG -#endif cont: /* Save our base. */ move $s0, $ra From 24c9143ae3b22a54b9d26e5ef823b394f135dd72 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 17 May 2011 18:00:31 +0100 Subject: [PATCH 279/406] * Makefile.util.def (grub-bin2h): Don't install. * docs/man/grub-bin2h.h2m: Remove. --- ChangeLog | 5 +++++ Makefile.util.def | 2 +- docs/man/grub-bin2h.h2m | 2 -- 3 files changed, 6 insertions(+), 3 deletions(-) delete mode 100644 docs/man/grub-bin2h.h2m diff --git a/ChangeLog b/ChangeLog index 5cd5d0b8e..47d23d811 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-17 Colin Watson + + * Makefile.util.def (grub-bin2h): Don't install. + * docs/man/grub-bin2h.h2m: Remove. + 2011-05-17 Vladimir Serbinenko * grub-core/kern/mips/startup.S (grub_arch_cpuclock): Move to the right diff --git a/Makefile.util.def b/Makefile.util.def index 60ad78217..380c939b9 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -114,7 +114,7 @@ program = { ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER)'; - mansection = 1; + installdir = noinst; }; program = { diff --git a/docs/man/grub-bin2h.h2m b/docs/man/grub-bin2h.h2m deleted file mode 100644 index ef463f3d1..000000000 --- a/docs/man/grub-bin2h.h2m +++ /dev/null @@ -1,2 +0,0 @@ -[NAME] -grub-bin2h \- convert a binary file to a C header From 3ca2b466459ffe724e8f8e1c450a619710de44a4 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 17 May 2011 18:03:59 +0100 Subject: [PATCH 280/406] * util/grub-fstest.c (cmd_cat): New function. (fstest): Handle CMD_CAT. (options): Add cat. (argp_parser): Handle cat. --- ChangeLog | 7 +++++++ util/grub-fstest.c | 44 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 47d23d811..4f17525b6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-05-17 Colin Watson + + * util/grub-fstest.c (cmd_cat): New function. + (fstest): Handle CMD_CAT. + (options): Add cat. + (argp_parser): Handle cat. + 2011-05-17 Colin Watson * Makefile.util.def (grub-bin2h): Don't install. diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 293bdf74a..f253a96f6 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -54,12 +54,15 @@ execute_command (char *name, int n, char **args) return (cmd->func) (cmd, n, args); } -#define CMD_LS 1 -#define CMD_CP 2 -#define CMD_CMP 3 -#define CMD_HEX 4 -#define CMD_CRC 6 -#define CMD_BLOCKLIST 7 +enum { + CMD_LS = 1, + CMD_CP, + CMD_CAT, + CMD_CMP, + CMD_HEX, + CMD_CRC, + CMD_BLOCKLIST +}; #define BUF_SIZE 32256 @@ -182,6 +185,26 @@ cmd_cp (char *src, char *dest) fclose (ff); } +static void +cmd_cat (char *src) +{ + auto int cat_hook (grub_off_t ofs, char *buf, int len); + int cat_hook (grub_off_t ofs, char *buf, int len) + { + (void) ofs; + + if ((int) fwrite (buf, 1, len, stdout) != len) + { + grub_util_error (_("write error")); + return 1; + } + + return 0; + } + + read_file (src, cat_hook); +} + static void cmd_cmp (char *src, char *dest) { @@ -321,6 +344,9 @@ fstest (int n, char **args) case CMD_CP: cmd_cp (args[0], args[1]); break; + case CMD_CAT: + cmd_cat (args[0]); + break; case CMD_CMP: cmd_cmp (args[0], args[1]); break; @@ -356,6 +382,7 @@ static struct argp_option options[] = { {0, 0, 0 , OPTION_DOC, N_("Commands:"), 1}, {N_("ls PATH"), 0, 0 , OPTION_DOC, N_("List files in PATH."), 1}, {N_("cp FILE LOCAL"), 0, 0, OPTION_DOC, N_("Copy FILE to local file LOCAL."), 1}, + {N_("cat FILE"), 0, 0 , OPTION_DOC, N_("Copy FILE to standard output."), 1}, {N_("cmp FILE LOCAL"), 0, 0, OPTION_DOC, N_("Compare FILE with local file LOCAL."), 1}, {N_("hex FILE"), 0, 0 , OPTION_DOC, N_("Hex dump FILE."), 1}, {N_("crc FILE"), 0, 0 , OPTION_DOC, N_("Get crc32 checksum of FILE."), 1}, @@ -468,6 +495,11 @@ argp_parser (int key, char *arg, struct argp_state *state) cmd = CMD_CP; nparm = 2; } + else if (!grub_strcmp (arg, "cat")) + { + cmd = CMD_CAT; + nparm = 1; + } else if (!grub_strcmp (arg, "cmp")) { cmd = CMD_CMP; From d064b83056698964cd6b59c6334d107a55379f46 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 17 May 2011 18:10:29 +0100 Subject: [PATCH 281/406] * util/grub.d/20_linux_xen.in: Honour GRUB_CMDLINE_LINUX_XEN_REPLACE and GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT, which replace GRUB_CMDLINE_LINUX and GRUB_CMDLINE_LINUX_DEFAULT (complementing the existing options which append). * docs/grub.texi (Simple configuration): Document new options. Reported by: Ian Jackson. Fixes Debian bug #617538. --- ChangeLog | 9 +++++++++ docs/grub.texi | 10 ++++++++-- util/grub.d/20_linux_xen.in | 8 ++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4f17525b6..ab710f5fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-05-17 Colin Watson + + * util/grub.d/20_linux_xen.in: Honour GRUB_CMDLINE_LINUX_XEN_REPLACE + and GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT, which replace + GRUB_CMDLINE_LINUX and GRUB_CMDLINE_LINUX_DEFAULT (complementing the + existing options which append). + * docs/grub.texi (Simple configuration): Document new options. + Reported by: Ian Jackson. Fixes Debian bug #617538. + 2011-05-17 Colin Watson * util/grub-fstest.c (cmd_cat): New function. diff --git a/docs/grub.texi b/docs/grub.texi index b11e3836f..7e28d457a 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -1169,8 +1169,14 @@ NetBSD. @item GRUB_CMDLINE_XEN @itemx GRUB_CMDLINE_XEN_DEFAULT -As @samp{GRUB_CMDLINE_LINUX} and @samp{GRUB_CMDLINE_LINUX_DEFAULT}, but for -Linux and Xen. +The values of these options are appended to the values of +@samp{GRUB_CMDLINE_LINUX} and @samp{GRUB_CMDLINE_LINUX_DEFAULT} for Linux +and Xen menu entries. + +@item GRUB_CMDLINE_LINUX_XEN_REPLACE +@item GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT +The values of these options replace the values of @samp{GRUB_CMDLINE_LINUX} +and @samp{GRUB_CMDLINE_LINUX_DEFAULT} for Linux and Xen menu entries. @item GRUB_DISABLE_LINUX_UUID Normally, @command{grub-mkconfig} will generate menu entries that use diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in index a9007603d..083391c40 100644 --- a/util/grub.d/20_linux_xen.in +++ b/util/grub.d/20_linux_xen.in @@ -51,6 +51,14 @@ else LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID} fi +# Allow overriding GRUB_CMDLINE_LINUX and GRUB_CMDLINE_LINUX_DEFAULT. +if [ "${GRUB_CMDLINE_LINUX_XEN_REPLACE}" ]; then + GRUB_CMDLINE_LINUX="${GRUB_CMDLINE_LINUX_XEN_REPLACE}" +fi +if [ "${GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT}" ]; then + GRUB_CMDLINE_LINUX_DEFAULT="${GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT}" +fi + if [ "x`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2>/dev/null || true`" = xbtrfs ]; then rootsubvol="`make_system_path_relative_to_its_root /`" rootsubvol="${rootsubvol#/}" From 5d420cd9833ce99500222ceefa1addbffb6a45b7 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 17 May 2011 18:13:12 +0100 Subject: [PATCH 282/406] * .bzrignore: Remove grub-dumpbios. --- .bzrignore | 1 - ChangeLog | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.bzrignore b/.bzrignore index 55cbdaeeb..668d060ca 100644 --- a/.bzrignore +++ b/.bzrignore @@ -31,7 +31,6 @@ genkernsyms.sh gensymlist.sh gentrigtables grub-bin2h -grub-dumpbios grub-editenv grub-emu grub_emu_init.c diff --git a/ChangeLog b/ChangeLog index ab710f5fb..ded0469a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-05-17 Colin Watson + + * .bzrignore: Remove grub-dumpbios. + 2011-05-17 Colin Watson * util/grub.d/20_linux_xen.in: Honour GRUB_CMDLINE_LINUX_XEN_REPLACE From 566a191715b3a91a7f5efd7e44e203620c513310 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 17 May 2011 19:32:51 +0200 Subject: [PATCH 283/406] Prevent potential loss of memory map by overwrite on qemu-mips. * grub-core/boot/mips/startup_raw.S [GRUB_MACHINE_MIPS_QEMU_MIPS]: Save ram size in $s4. * grub-core/kern/mips/qemu_mips/init.c (RAMSIZE): Removed. All users changed to grub_arch_memsize. * grub-core/kern/mips/startup.S (grub_arch_machine): Restrict to Loongson. [GRUB_MACHINE_MIPS_QEMU_MIPS]: Save grub_arch_memsize. * grub-core/loader/mips/linux.c (grub_linux_boot): Pass memory size. * include/grub/mips/qemu_mips/memory.h (grub_arch_memsize): New external variable. --- ChangeLog | 15 +++++++++++++++ grub-core/boot/mips/startup_raw.S | 5 +++++ grub-core/kern/mips/qemu_mips/init.c | 6 ++---- grub-core/kern/mips/startup.S | 8 ++++++++ grub-core/loader/mips/linux.c | 14 +++++++++++--- include/grub/mips/qemu_mips/memory.h | 3 +++ 6 files changed, 44 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index ded0469a3..d1f01e727 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2011-05-17 Vladimir Serbinenko + + Prevent potential loss of memory map by overwrite on qemu-mips. + + * grub-core/boot/mips/startup_raw.S [GRUB_MACHINE_MIPS_QEMU_MIPS]: + Save ram size in $s4. + * grub-core/kern/mips/qemu_mips/init.c (RAMSIZE): Removed. + All users changed to grub_arch_memsize. + * grub-core/kern/mips/startup.S (grub_arch_machine): Restrict to + Loongson. + [GRUB_MACHINE_MIPS_QEMU_MIPS]: Save grub_arch_memsize. + * grub-core/loader/mips/linux.c (grub_linux_boot): Pass memory size. + * include/grub/mips/qemu_mips/memory.h (grub_arch_memsize): New + external variable. + 2011-05-17 Colin Watson * .bzrignore: Remove grub-dumpbios. diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index e69de26c2..65a2dd59e 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -50,6 +50,11 @@ codestart: /* Parse arguments. Has to be done before relocation. So need to do it in asm. */ +#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS + lui $t0, %hi (((16 << 20) - 264) | 0x80000000) + lw $s4, %lo (((16 << 20) - 264) | 0x80000000) ($t0) +#endif + #ifdef GRUB_MACHINE_MIPS_LOONGSON move $s2, $zero move $s3, $zero diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c index b3155eab5..e426b833d 100644 --- a/grub-core/kern/mips/qemu_mips/init.c +++ b/grub-core/kern/mips/qemu_mips/init.c @@ -10,8 +10,6 @@ #include #include -#define RAMSIZE (*(grub_uint32_t *) ((16 << 20) - 264)) - extern void grub_serial_init (void); extern void grub_terminfo_init (void); @@ -24,7 +22,7 @@ grub_machine_init (void) grub_arch_cpuclock = 64000000; modend = grub_modules_get_end (); - grub_mm_init_region ((void *) modend, RAMSIZE + grub_mm_init_region ((void *) modend, grub_arch_memsize - (modend - GRUB_ARCH_LOWMEMVSTART)); grub_install_get_time_ms (grub_rtc_get_time_ms); @@ -59,6 +57,6 @@ grub_reboot (void) grub_err_t grub_machine_mmap_iterate (grub_memory_hook_t hook) { - hook (0, RAMSIZE, GRUB_MEMORY_AVAILABLE); + hook (0, grub_arch_memsize, GRUB_MEMORY_AVAILABLE); return GRUB_ERR_NONE; } diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index 1472aaf8c..2654d744e 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -59,12 +59,20 @@ VARIABLE (grub_arch_memsize) .long 0 VARIABLE (grub_arch_highmemsize) .long 0 +#ifdef GRUB_MACHINE_MIPS_LOONGSON VARIABLE (grub_arch_machine) .long GRUB_ARCH_MACHINE_FULOONG +#endif cont: /* Save our base. */ move $s0, $ra +#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS + lui $t1, %hi(grub_arch_busclock) + addiu $t1, %lo(grub_arch_busclock) + sw $s4, 8($t1) +#endif + #ifdef GRUB_MACHINE_MIPS_LOONGSON lui $t1, %hi(grub_arch_busclock) addiu $t1, %lo(grub_arch_busclock) diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c index 722be36a9..64c4a0531 100644 --- a/grub-core/loader/mips/linux.c +++ b/grub-core/loader/mips/linux.c @@ -80,13 +80,21 @@ grub_linux_boot (void) { grub_err_t err; grub_relocator_chunk_t ch; + grub_uint32_t *memsize; + grub_uint32_t *magic; + char *str; err = grub_relocator_alloc_chunk_addr (relocator, &ch, - ((16 << 20) - 256), - grub_strlen (params) + 1); + ((16 << 20) - 264), + grub_strlen (params) + 1 + 8); if (err) return err; - grub_strcpy (get_virtual_current_address (ch), params); + memsize = get_virtual_current_address (ch); + magic = memsize + 1; + *memsize = grub_mmap_get_lower (); + *magic = 0x12345678; + str = (char *) (magic + 1); + grub_strcpy (str, params); } #endif diff --git a/include/grub/mips/qemu_mips/memory.h b/include/grub/mips/qemu_mips/memory.h index 7a7ff143e..48a9b69f0 100644 --- a/include/grub/mips/qemu_mips/memory.h +++ b/include/grub/mips/qemu_mips/memory.h @@ -29,6 +29,9 @@ #define GRUB_MACHINE_MEMORY_USABLE 0x81000000 #ifndef ASM_FILE + +extern grub_uint32_t grub_arch_memsize; + static inline grub_err_t grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), From b772baedcd8ef2a995f4bb0fc8ebc9157c21e9b7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 17 May 2011 21:15:54 +0200 Subject: [PATCH 284/406] Reduce memory footprint on SGI by putting modules before the kernel as opposed to after. * grub-core/Makefile.core.def (kernel): Increase linking address. (none_decompress): Likewise. (xz_decompress): Likewise. * grub-core/boot/mips/startup_raw.S: Use prewritten uncompression address. * grub-core/kern/mips/arc/init.c (grub_machine_init): Handle memory layout change. (grub_arch_modules_addr): New function. * grub-core/kern/mips/init.c (grub_arch_modules_addr): Moved from here... * grub-core/kern/mips/loongson/init.c (grub_arch_modules_addr): .. here * grub-core/kern/mips/qemu_mips/init.c (grub_arch_modules_addr): ... and here. * grub-core/kern/mips/startup.S (total_size): Rename to ... (grub_total_modules_size): ... this. Make global. [GRUB_MACHINE_ARC]: Don't attempt to move modules out of the bss. * include/grub/offsets.h (GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR): New definition. (GRUB_KERNEL_MIPS_QEMU_MIPS_UNCOMPRESSED_ADDR): Likewise. (GRUB_KERNEL_MIPS_ARC_UNCOMPRESSED_ADDR): Likewise. (GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR): Likewise. (GRUB_KERNEL_MIPS_ARC_LINK_ADDR): Increased. * util/grub-mkimage.c (image_target_desc): New flag PLATFORM_FLAGS_MODULES_BEFORE_KERNEL. (image_targets): Set PLATFORM_FLAGS_MODULES_BEFORE_KERNEL on mips-arc. (generate_image): Handle images with modules before kernel. --- ChangeLog | 31 ++++++++++++ grub-core/Makefile.core.def | 6 +-- grub-core/boot/mips/startup_raw.S | 6 ++- grub-core/kern/mips/arc/init.c | 14 +++++- grub-core/kern/mips/init.c | 8 ---- grub-core/kern/mips/loongson/init.c | 7 +++ grub-core/kern/mips/qemu_mips/init.c | 8 ++++ grub-core/kern/mips/startup.S | 4 +- include/grub/offsets.h | 6 ++- util/grub-mkimage.c | 70 ++++++++++++++++++++-------- 10 files changed, 123 insertions(+), 37 deletions(-) diff --git a/ChangeLog b/ChangeLog index d1f01e727..bf7d7d110 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2011-05-17 Vladimir Serbinenko + + Reduce memory footprint on SGI by putting modules before the kernel + as opposed to after. + + * grub-core/Makefile.core.def (kernel): Increase linking address. + (none_decompress): Likewise. + (xz_decompress): Likewise. + * grub-core/boot/mips/startup_raw.S: Use prewritten uncompression + address. + * grub-core/kern/mips/arc/init.c (grub_machine_init): Handle memory + layout change. + (grub_arch_modules_addr): New function. + * grub-core/kern/mips/init.c (grub_arch_modules_addr): Moved from here... + * grub-core/kern/mips/loongson/init.c (grub_arch_modules_addr): .. here + * grub-core/kern/mips/qemu_mips/init.c (grub_arch_modules_addr): ... and + here. + * grub-core/kern/mips/startup.S (total_size): Rename to ... + (grub_total_modules_size): ... this. Make global. + [GRUB_MACHINE_ARC]: Don't attempt to move modules out of the bss. + * include/grub/offsets.h (GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR): + New definition. + (GRUB_KERNEL_MIPS_QEMU_MIPS_UNCOMPRESSED_ADDR): Likewise. + (GRUB_KERNEL_MIPS_ARC_UNCOMPRESSED_ADDR): Likewise. + (GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR): Likewise. + (GRUB_KERNEL_MIPS_ARC_LINK_ADDR): Increased. + * util/grub-mkimage.c (image_target_desc): New flag + PLATFORM_FLAGS_MODULES_BEFORE_KERNEL. + (image_targets): Set PLATFORM_FLAGS_MODULES_BEFORE_KERNEL on mips-arc. + (generate_image): Handle images with modules before kernel. + 2011-05-17 Vladimir Serbinenko Prevent potential loss of memory map by overwrite on qemu-mips. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 1c0b530a1..c717167cb 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -41,7 +41,7 @@ kernel = { mips_loongson_ldflags = '-Wl,-Ttext,0x80200000'; powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000'; sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; - mips_arc_ldflags = '-Wl,-Ttext,0x8a000000'; + mips_arc_ldflags = '-Wl,-Ttext,0x8bd00000'; mips_qemu_mips_ldflags = '-Wl,-Ttext,0x80200000'; mips_loongson_cppflags = '-DUSE_ASCII_FAILBACK'; @@ -324,7 +324,7 @@ image = { objcopyflags = '-O binary'; mips_loongson_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; mips_qemu_mips_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; - mips_arc_ldflags = '-static-libgcc -Wl,-Ttext,0x89f00000'; + mips_arc_ldflags = '-static-libgcc -Wl,-Ttext,0x8bc00000'; ldadd = '-lgcc'; cflags = '-static-libgcc'; enable = mips; @@ -340,7 +340,7 @@ image = { objcopyflags = '-O binary'; mips_loongson_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; mips_qemu_mips_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; - mips_arc_ldflags = '-static-libgcc -Wl,-Ttext,0x89f00000'; + mips_arc_ldflags = '-static-libgcc -Wl,-Ttext,0x8bc00000'; ldadd = '-lgcc'; cflags = '-static-libgcc'; enable = mips; diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index 65a2dd59e..e6dfadaf9 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -44,6 +44,9 @@ compressed_size: . = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE uncompressed_size: .long 0 + . = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR +uncompressed_addr: + .long 0 codestart: /* Save our base. */ move $s0, $ra @@ -221,8 +224,7 @@ cmdlinedone: subu $a0, $a0, $t0 addu $a0, $a0, $s0 - lui $a1, %hi(GRUB_MACHINE_LINK_ADDR) - addiu $a1, %lo(GRUB_MACHINE_LINK_ADDR) + lw $a1, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR - BASE_ADDR)($s0) lw $a2, (GRUB_KERNEL_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0) lw $a3, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0) move $s1, $a1 diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c index 8ee965d74..514b481f6 100644 --- a/grub-core/kern/mips/arc/init.c +++ b/grub-core/kern/mips/arc/init.c @@ -124,6 +124,8 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook) } } +extern grub_uint32_t grub_total_modules_size; + void grub_machine_init (void) { @@ -148,8 +150,10 @@ grub_machine_init (void) start = ((grub_uint64_t) cur->start_page) << 12; end = ((grub_uint64_t) cur->num_pages) << 12; end += start; - if ((grub_uint64_t) end > (GRUB_KERNEL_MIPS_ARC_LINK_ADDR & 0x1fffffff)) - end = (GRUB_KERNEL_MIPS_ARC_LINK_ADDR & 0x1fffffff); + if ((grub_uint64_t) end > ((GRUB_KERNEL_MIPS_ARC_LINK_ADDR + - grub_total_modules_size) & 0x1fffffff)) + end = ((GRUB_KERNEL_MIPS_ARC_LINK_ADDR - grub_total_modules_size) + & 0x1fffffff); if (end > start) grub_mm_init_region ((void *) (grub_addr_t) (start | 0x80000000), end - start); @@ -160,6 +164,12 @@ grub_machine_init (void) grub_arcdisk_init (); } +grub_addr_t +grub_arch_modules_addr (void) +{ + return GRUB_KERNEL_MIPS_ARC_LINK_ADDR - grub_total_modules_size; +} + void grub_machine_fini (void) { diff --git a/grub-core/kern/mips/init.c b/grub-core/kern/mips/init.c index 3b08d5606..bfa08f56a 100644 --- a/grub-core/kern/mips/init.c +++ b/grub-core/kern/mips/init.c @@ -42,11 +42,3 @@ grub_machine_set_prefix (void) { grub_env_set ("prefix", grub_prefix); } - -extern char _end[]; - -grub_addr_t -grub_arch_modules_addr (void) -{ - return (grub_addr_t) _end; -} diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c index f0f5c5874..bcef391b9 100644 --- a/grub-core/kern/mips/loongson/init.c +++ b/grub-core/kern/mips/loongson/init.c @@ -257,3 +257,10 @@ grub_reboot (void) while (1); } +extern char _end[]; + +grub_addr_t +grub_arch_modules_addr (void) +{ + return (grub_addr_t) _end; +} diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c index e426b833d..2180b347a 100644 --- a/grub-core/kern/mips/qemu_mips/init.c +++ b/grub-core/kern/mips/qemu_mips/init.c @@ -60,3 +60,11 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook) hook (0, grub_arch_memsize, GRUB_MEMORY_AVAILABLE); return GRUB_ERR_NONE; } + +extern char _end[]; + +grub_addr_t +grub_arch_modules_addr (void) +{ + return (grub_addr_t) _end; +} diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index 2654d744e..6220a8c33 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -37,7 +37,7 @@ start: nop . = _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE -total_module_size: +VARIABLE(grub_total_modules_size) .long 0 . = _start + GRUB_KERNEL_MACHINE_PREFIX @@ -84,6 +84,7 @@ cont: #endif /* Move the modules out of BSS. */ +#ifndef GRUB_MACHINE_ARC lui $t2, %hi(__bss_start) addiu $t2, %lo(__bss_start) @@ -113,6 +114,7 @@ modulesmovcont: b modulesmovcont addiu $t3, $t3, -1 modulesmovdone: +#endif /* Clean BSS. */ diff --git a/include/grub/offsets.h b/include/grub/offsets.h index 40c8a016b..af724096d 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -106,6 +106,7 @@ #define GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE 0x8 #define GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE 0xc +#define GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR 0x10 #define GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE 0x08 #define GRUB_KERNEL_MIPS_LOONGSON_PREFIX 0x0c @@ -115,16 +116,18 @@ #define GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN 32 #define GRUB_KERNEL_MIPS_QEMU_MIPS_COMPRESSED_SIZE 0x8 #define GRUB_KERNEL_MIPS_QEMU_MIPS_UNCOMPRESSED_SIZE 0xc +#define GRUB_KERNEL_MIPS_QEMU_MIPS_UNCOMPRESSED_ADDR 0x10 #define GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE 0x08 #define GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX 0x0c #define GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END 0x54 -#define GRUB_KERNEL_MIPS_ARC_LINK_ADDR 0x8a000000 +#define GRUB_KERNEL_MIPS_ARC_LINK_ADDR 0x8bd00000 #define GRUB_KERNEL_MIPS_ARC_LINK_ALIGN 32 #define GRUB_KERNEL_MIPS_ARC_COMPRESSED_SIZE 0x8 #define GRUB_KERNEL_MIPS_ARC_UNCOMPRESSED_SIZE 0xc +#define GRUB_KERNEL_MIPS_ARC_UNCOMPRESSED_ADDR 0x10 #define GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE 0x08 #define GRUB_KERNEL_MIPS_ARC_PREFIX 0x0c @@ -187,6 +190,7 @@ #define GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _KERNEL_IMAGE_SIZE) #define GRUB_KERNEL_MACHINE_COMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _COMPRESSED_SIZE) #define GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _UNCOMPRESSED_SIZE) +#define GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _UNCOMPRESSED_ADDR) #define GRUB_KERNEL_MACHINE_PREFIX GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _PREFIX) #define GRUB_KERNEL_MACHINE_PREFIX_END GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _PREFIX_END) diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 5f35c1da0..5ae744a8e 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -73,7 +73,8 @@ struct image_target_desc { PLATFORM_FLAGS_NONE = 0, PLATFORM_FLAGS_LZMA = 1, - PLATFORM_FLAGS_DECOMPRESSORS = 2 + PLATFORM_FLAGS_DECOMPRESSORS = 2, + PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4, } flags; unsigned prefix; unsigned prefix_end; @@ -426,7 +427,8 @@ struct image_target_desc image_targets[] = .voidp_sizeof = 4, .bigendian = 1, .id = IMAGE_MIPS_ARC, - .flags = PLATFORM_FLAGS_DECOMPRESSORS, + .flags = (PLATFORM_FLAGS_DECOMPRESSORS + | PLATFORM_FLAGS_MODULES_BEFORE_KERNEL), .prefix = GRUB_KERNEL_MIPS_ARC_PREFIX, .prefix_end = GRUB_KERNEL_MIPS_ARC_PREFIX_END, .raw_size = 0, @@ -781,27 +783,47 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], grub_util_error (_("prefix is too long")); strcpy (kernel_img + image_target->prefix, prefix); + if ((image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) + && (image_target->total_module_size != TARGET_NO_FIELD)) + *((grub_uint32_t *) (kernel_img + image_target->total_module_size)) + = grub_host_to_target32 (total_module_size); + + if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) + memmove (kernel_img + total_module_size, kernel_img, kernel_size); + if (image_target->voidp_sizeof == 8) { /* Fill in the grub_module_info structure. */ struct grub_module_info64 *modinfo; - modinfo = (struct grub_module_info64 *) (kernel_img + kernel_size); + if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) + modinfo = (struct grub_module_info64 *) kernel_img; + else + modinfo = (struct grub_module_info64 *) (kernel_img + kernel_size); memset (modinfo, 0, sizeof (struct grub_module_info64)); modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC); modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info64)); modinfo->size = grub_host_to_target_addr (total_module_size); - offset = kernel_size + sizeof (struct grub_module_info64); + if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) + offset = sizeof (struct grub_module_info64); + else + offset = kernel_size + sizeof (struct grub_module_info64); } else { /* Fill in the grub_module_info structure. */ struct grub_module_info32 *modinfo; - modinfo = (struct grub_module_info32 *) (kernel_img + kernel_size); + if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) + modinfo = (struct grub_module_info32 *) kernel_img; + else + modinfo = (struct grub_module_info32 *) (kernel_img + kernel_size); memset (modinfo, 0, sizeof (struct grub_module_info32)); modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC); modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info32)); modinfo->size = grub_host_to_target_addr (total_module_size); - offset = kernel_size + sizeof (struct grub_module_info32); + if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) + offset = sizeof (struct grub_module_info32); + else + offset = kernel_size + sizeof (struct grub_module_info32); } for (p = path_list; p; p = p->next) @@ -852,26 +874,27 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], offset += config_size; } - if ((image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) - && (image_target->total_module_size != TARGET_NO_FIELD)) - *((grub_uint32_t *) (kernel_img + image_target->total_module_size)) - = grub_host_to_target32 (total_module_size); - grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size); compress_kernel (image_target, kernel_img, kernel_size + total_module_size, &core_img, &core_size, comp); + free (kernel_img); + + if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) + kernel_img = core_img + total_module_size; + else + kernel_img = core_img; grub_util_info ("the core size is 0x%x", core_size); if (!(image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) && image_target->total_module_size != TARGET_NO_FIELD) - *((grub_uint32_t *) (core_img + image_target->total_module_size)) + *((grub_uint32_t *) (kernel_img + image_target->total_module_size)) = grub_host_to_target32 (total_module_size); if (image_target->kernel_image_size != TARGET_NO_FIELD) - *((grub_uint32_t *) (core_img + image_target->kernel_image_size)) + *((grub_uint32_t *) (kernel_img + image_target->kernel_image_size)) = grub_host_to_target32 (kernel_size); if (image_target->compressed_size != TARGET_NO_FIELD) - *((grub_uint32_t *) (core_img + image_target->compressed_size)) + *((grub_uint32_t *) (kernel_img + image_target->compressed_size)) = grub_host_to_target32 (core_size - image_target->raw_size); /* If we included a drive in our prefix, let GRUB know it doesn't have to @@ -879,9 +902,9 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], if (image_target->install_dos_part != TARGET_NO_FIELD && image_target->install_bsd_part != TARGET_NO_FIELD && prefix[0] == '(') { - *((grub_int32_t *) (core_img + image_target->install_dos_part)) + *((grub_int32_t *) (kernel_img + image_target->install_dos_part)) = grub_host_to_target32 (-2); - *((grub_int32_t *) (core_img + image_target->install_bsd_part)) + *((grub_int32_t *) (kernel_img + image_target->install_bsd_part)) = grub_host_to_target32 (-2); } @@ -915,6 +938,13 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE)) = grub_host_to_target32 (kernel_size + total_module_size); + if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) + *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR)) + = grub_host_to_target_addr (image_target->link_addr - total_module_size); + else + *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR)) + = grub_host_to_target_addr (image_target->link_addr); + full_size = core_size + decompress_size; full_img = xmalloc (full_size); @@ -1199,7 +1229,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], rom_img = xmalloc (rom_size); memset (rom_img, 0, rom_size); - *((grub_int32_t *) (core_img + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR)) + *((grub_int32_t *) (kernel_img + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR)) = grub_host_to_target32 ((grub_uint32_t) -rom_size); memcpy (rom_img, core_img, core_size); @@ -1380,8 +1410,9 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], size_t program_size; program_size = ALIGN_ADDR (core_size); - target_addr = image_target->link_addr - ALIGN_UP(program_size, 1048576) - - (1 << 20); + target_addr = (image_target->link_addr + - ALIGN_UP(total_module_size + core_size, 1048576) + - (1 << 20)); ecoff_img = xmalloc (program_size + sizeof (*head) + sizeof (*section)); grub_memset (ecoff_img, 0, program_size + sizeof (*head) + sizeof (*section)); @@ -1553,7 +1584,6 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], } grub_util_write_image (core_img, core_size, out); - free (kernel_img); free (core_img); free (kernel_path); From 35341bbc9644eb17ae08e5ccbc52c691cc8357fb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 17 May 2011 21:40:35 +0200 Subject: [PATCH 285/406] Avoid unnecessary copying on MIPS. * grub-core/boot/decompressor/none.c (grub_decompress_core): Exit early if src == dest. * util/grub-mkimage.c (generate_image): Arange for src == dest if compression is none. --- ChangeLog | 9 +++++++++ grub-core/boot/decompressor/none.c | 3 +++ util/grub-mkimage.c | 21 +++++++++++++++------ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index bf7d7d110..2d6a02d08 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-05-17 Vladimir Serbinenko + + Avoid unnecessary copying on MIPS. + + * grub-core/boot/decompressor/none.c (grub_decompress_core): Exit + early if src == dest. + * util/grub-mkimage.c (generate_image): Arange for src == dest if + compression is none. + 2011-05-17 Vladimir Serbinenko Reduce memory footprint on SGI by putting modules before the kernel diff --git a/grub-core/boot/decompressor/none.c b/grub-core/boot/decompressor/none.c index 44f56ce90..911e861e3 100644 --- a/grub-core/boot/decompressor/none.c +++ b/grub-core/boot/decompressor/none.c @@ -25,6 +25,9 @@ grub_decompress_core (void *src, void *dest, unsigned long n, char *d = (char *) dest; const char *s = (const char *) src; + if (d == s) + return; + if (d < s) while (n--) *d++ = *s++; diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 5ae744a8e..2003a86d2 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -736,6 +736,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], grub_uint64_t start_address; void *rel_section; grub_size_t reloc_size, align; + size_t decompress_size; if (comp == COMPRESSION_AUTO) comp = image_target->default_compression; @@ -913,7 +914,6 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], char *full_img; size_t full_size; char *decompress_path, *decompress_img; - size_t decompress_size; const char *name; switch (comp) @@ -1410,9 +1410,13 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], size_t program_size; program_size = ALIGN_ADDR (core_size); - target_addr = (image_target->link_addr - - ALIGN_UP(total_module_size + core_size, 1048576) - - (1 << 20)); + if (comp == COMPRESSION_NONE) + target_addr = (image_target->link_addr + - total_module_size - decompress_size); + else + target_addr = (image_target->link_addr + - ALIGN_UP(total_module_size + core_size, 1048576) + - (1 << 20)); ecoff_img = xmalloc (program_size + sizeof (*head) + sizeof (*section)); grub_memset (ecoff_img, 0, program_size + sizeof (*head) + sizeof (*section)); @@ -1500,8 +1504,13 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X); if (image_target->id == IMAGE_LOONGSON_ELF) - target_addr = ALIGN_UP (image_target->link_addr - + kernel_size + total_module_size, 32); + { + if (comp == COMPRESSION_NONE) + target_addr = (image_target->link_addr - decompress_size); + else + target_addr = ALIGN_UP (image_target->link_addr + + kernel_size + total_module_size, 32); + } else target_addr = image_target->link_addr; ehdr->e_entry = grub_host_to_target32 (target_addr); From 4959e11109d8305a7a1aefa37cfd6bea60679038 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 17 May 2011 22:48:20 +0200 Subject: [PATCH 286/406] Use mipsel- rather than mips- in directories involving mipsel ports to allow both endiannesses coexist. * configure.ac: proparate target_cpu=mipsel rather than resetting to mips. All conditions adjusted. * tests/util/grub-shell-tester.in: Remove gratuitious target_cpu variable. * util/grub-install.in: Adjust conditions to take renaming into account. * util/grub-mkimage.c (image_targets): Likewise. New target mips-qemu_mips-elf for bigendian mips. --- ChangeLog | 13 +++++++++++ configure.ac | 41 +++++++++++++++++++++------------ tests/util/grub-shell-tester.in | 1 - util/grub-install.in | 6 ++--- util/grub-mkimage.c | 30 ++++++++++++++++++++---- 5 files changed, 68 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2d6a02d08..1d4076a5b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2011-05-17 Vladimir Serbinenko + + Use mipsel- rather than mips- in directories involving mipsel ports to + allow both endiannesses coexist. + + * configure.ac: proparate target_cpu=mipsel rather than resetting to + mips. All conditions adjusted. + * tests/util/grub-shell-tester.in: Remove gratuitious target_cpu + variable. + * util/grub-install.in: Adjust conditions to take renaming into account. + * util/grub-mkimage.c (image_targets): Likewise. New target + mips-qemu_mips-elf for bigendian mips. + 2011-05-17 Vladimir Serbinenko Avoid unnecessary copying on MIPS. diff --git a/configure.ac b/configure.ac index 8f854155e..f674a90aa 100644 --- a/configure.ac +++ b/configure.ac @@ -72,7 +72,7 @@ case "$target_cpu" in amd64) target_cpu=x86_64 ;; sparc) target_cpu=sparc64 ;; mipsel|mips64el) - target_cpu=mips; + target_cpu=mipsel; machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPSEL=1"; ;; mips|mips64) @@ -96,7 +96,8 @@ if test "x$with_platform" = x; then powerpc-*) platform=ieee1275 ;; powerpc64-*) platform=ieee1275 ;; sparc64-*) platform=ieee1275 ;; - mips-*) platform=loongson ;; + mipsel-*) platform=loongson ;; + mips-*) platform=arc ;; ia64-*) platform=efi ;; *) AC_MSG_ERROR([unsupported CPU: "$target_cpu"]) ;; esac @@ -126,10 +127,12 @@ case "$target_cpu"-"$platform" in ia64-efi) ;; mips-qemu_mips) ;; mips-qemu-mips) platform=qemu_mips;; - mips-yeeloong) platform=loongson ;; - mips-fuloong) platform=loongson ;; - mips-loongson) ;; mips-arc) ;; + mipsel-qemu_mips) ;; + mipsel-qemu-mips) platform=qemu_mips;; + mipsel-yeeloong) platform=loongson ;; + mipsel-fuloong) platform=loongson ;; + mipsel-loongson) ;; *-emu) ;; *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;; esac @@ -167,10 +170,14 @@ case "$platform" in arc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_ARC=1" ;; esac case "$target_cpu" in - mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS=1" ;; + mips |mipsel) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS=1" ;; sparc64) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_SPARC64=1" ;; esac -machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo ${target_cpu}_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`" +if test x${target_cpu} = xmipsel ; then + machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo mips_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`" +else + machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo ${target_cpu}_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`" +fi HOST_CPPFLAGS="$HOST_CPPFLAGS $machine_CPPFLAGS" TARGET_CPPFLAGS="$TARGET_CPPFLAGS $machine_CPPFLAGS" @@ -405,7 +412,7 @@ if test "x$grub_cv_cc_fno_dwarf2_cfi_asm" = xyes; then TARGET_CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm" fi -if test "${target_cpu}-${platform}" = mips-loongson; then +if test "${target_cpu}-${platform}" = mipsel-loongson; then AC_CACHE_CHECK([whether -march=loongson2f works], [grub_cv_cc_march_loongson2f], [ SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -march=loongson2f" @@ -958,12 +965,12 @@ AM_CONDITIONAL([COND_i386_ieee1275], [test x$target_cpu = xi386 -a x$platform = AM_CONDITIONAL([COND_i386_coreboot], [test x$target_cpu = xi386 -a x$platform = xcoreboot]) AM_CONDITIONAL([COND_i386_multiboot], [test x$target_cpu = xi386 -a x$platform = xmultiboot]) AM_CONDITIONAL([COND_x86_64_efi], [test x$target_cpu = xx86_64 -a x$platform = xefi]) -AM_CONDITIONAL([COND_mips_loongson], [test x$target_cpu = xmips -a x$platform = xloongson]) -AM_CONDITIONAL([COND_mips_qemu_mips], [test x$target_cpu = xmips -a x$platform = xqemu_mips]) +AM_CONDITIONAL([COND_mips_loongson], [test x$target_cpu = xmipsel -a x$platform = xloongson]) +AM_CONDITIONAL([COND_mips_qemu_mips], [test "(" x$target_cpu = xmips -o x$target_cpu = xmipsel ")" -a x$platform = xqemu_mips]) AM_CONDITIONAL([COND_mips_arc], [test x$target_cpu = xmips -a x$platform = xarc]) AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275]) AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275]) -AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips]) +AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips -o x$target_cpu = xmipsel]) AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd]) AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux]) @@ -985,19 +992,23 @@ AM_CONDITIONAL([COND_HAVE_ASM_USCORE], [test x$HAVE_ASM_USCORE = x1]) AM_CONDITIONAL([COND_CYGWIN], [test x$host_os = xcygwin]) # Output files. +cpudir="${target_cpu}" +if test x${cpudir} = xmipsel; then + cpudir=mips; +fi grub_CHECK_LINK_DIR if test x"$link_dir" = xyes ; then - AC_CONFIG_LINKS([include/grub/cpu:include/grub/$target_cpu]) + AC_CONFIG_LINKS([include/grub/cpu:include/grub/$cpudir]) if test "$platform" != emu ; then - AC_CONFIG_LINKS([include/grub/machine:include/grub/$target_cpu/$platform]) + AC_CONFIG_LINKS([include/grub/machine:include/grub/$cpudir/$platform]) fi else mkdir -p include/grub 2>/dev/null rm -rf include/grub/cpu - cp -rp $srcdir/include/grub/$target_cpu include/grub/cpu 2>/dev/null + cp -rp $srcdir/include/grub/$cpudir include/grub/cpu 2>/dev/null if test "$platform" != emu ; then rm -rf include/grub/machine - cp -rp $srcdir/include/grub/$target_cpu/$platform include/grub/machine 2>/dev/null + cp -rp $srcdir/include/grub/$cpudir/$platform include/grub/machine 2>/dev/null fi fi diff --git a/tests/util/grub-shell-tester.in b/tests/util/grub-shell-tester.in index 02e49d3a4..b839825f1 100644 --- a/tests/util/grub-shell-tester.in +++ b/tests/util/grub-shell-tester.in @@ -27,7 +27,6 @@ builddir=@builddir@ PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ -target_cpu=@target_cpu@ # Force build directory components PATH=${builddir}:$PATH diff --git a/util/grub-install.in b/util/grub-install.in index ad6ea1037..db3a4db98 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -554,13 +554,13 @@ fi case "${target_cpu}-${platform}" in sparc64-ieee1275) mkimage_target=sparc64-ieee1275-raw ;; - mips-loongson) mkimage_target=mipsel-loongson-elf ;; + mipsel-loongson) mkimage_target=mipsel-loongson-elf ;; *) mkimage_target="${target_cpu}-${platform}" ;; esac case "${target_cpu}-${platform}" in i386-efi | x86_64-efi) imgext=efi ;; - mips-loongson | i386-coreboot | i386-multiboot | i386-ieee1275 \ + mipsel-loongson | i386-coreboot | i386-multiboot | i386-ieee1275 \ | powerpc-ieee1275) imgext=elf ;; *) imgext=img ;; esac @@ -569,7 +569,7 @@ esac "$grub_mkimage" ${config_opt} -d "${pkglibdir}" -O ${mkimage_target} --output="${grubdir}/core.${imgext}" --prefix="${prefix_drive}${relative_grubdir}" $modules || exit 1 # Backward-compatibility kludges -if [ "${target_cpu}-${platform}" = "mips-loongson" ]; then +if [ "${target_cpu}-${platform}" = "mipsel-loongson" ]; then cp "${grubdir}/core.${imgext}" "${bootdir}"/grub.elf elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then cp "${grubdir}/core.${imgext}" "${grubdir}/grub" diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 2003a86d2..9fc37df2b 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -274,7 +274,7 @@ struct image_target_desc image_targets[] = .elf_target = EM_X86_64, }, { - .dirname = "mips-loongson", + .dirname = "mipsel-loongson", .names = { "mipsel-yeeloong-flash", NULL }, .voidp_sizeof = 4, .bigendian = 0, @@ -296,7 +296,7 @@ struct image_target_desc image_targets[] = .default_compression = COMPRESSION_NONE }, { - .dirname = "mips-loongson", + .dirname = "mipsel-loongson", .names = { "mipsel-fuloong-flash", NULL }, .voidp_sizeof = 4, .bigendian = 0, @@ -318,7 +318,7 @@ struct image_target_desc image_targets[] = .default_compression = COMPRESSION_NONE }, { - .dirname = "mips-loongson", + .dirname = "mipsel-loongson", .names = { "mipsel-loongson-elf", "mipsel-yeeloong-elf", "mipsel-fuloong-elf", NULL }, .voidp_sizeof = 4, @@ -445,7 +445,7 @@ struct image_target_desc image_targets[] = .default_compression = COMPRESSION_NONE }, { - .dirname = "mips-qemu_mips", + .dirname = "mipsel-qemu_mips", .names = { "mipsel-qemu_mips-elf", NULL }, .voidp_sizeof = 4, .bigendian = 0, @@ -466,6 +466,28 @@ struct image_target_desc image_targets[] = .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN, .default_compression = COMPRESSION_NONE }, + { + .dirname = "mips-qemu_mips", + .names = { "mips-qemu_mips-elf", NULL }, + .voidp_sizeof = 4, + .bigendian = 1, + .id = IMAGE_LOONGSON_ELF, + .flags = PLATFORM_FLAGS_DECOMPRESSORS, + .prefix = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX, + .prefix_end = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END, + .raw_size = 0, + .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, + .compressed_size = TARGET_NO_FIELD, + .kernel_image_size = TARGET_NO_FIELD, + .section_align = 1, + .vaddr_offset = 0, + .install_dos_part = TARGET_NO_FIELD, + .install_bsd_part = TARGET_NO_FIELD, + .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR, + .elf_target = EM_MIPS, + .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN, + .default_compression = COMPRESSION_NONE + }, }; #define grub_target_to_host32(x) (grub_target_to_host32_real (image_target, (x))) From 543a8f6ef929e94a45e293c4aeb3c6fbb9c6963e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 18 May 2011 00:21:49 +0200 Subject: [PATCH 287/406] * grub-core/kern/ia64/dl_helper.c (grub_ia64_dl_get_tramp_got_size): Fix potential usage of Elf32 instead of Elf64 when compiling on 32-bit architecture. Add endianness macros while on it. --- ChangeLog | 6 ++++++ grub-core/kern/ia64/dl_helper.c | 32 ++++++++++++++++---------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1d4076a5b..59574202a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-05-17 Vladimir Serbinenko + + * grub-core/kern/ia64/dl_helper.c (grub_ia64_dl_get_tramp_got_size): + Fix potential usage of Elf32 instead of Elf64 when compiling on + 32-bit architecture. Add endianness macros while on it. + 2011-05-17 Vladimir Serbinenko Use mipsel- rather than mips- in directories involving mipsel ports to diff --git a/grub-core/kern/ia64/dl_helper.c b/grub-core/kern/ia64/dl_helper.c index 9503c49ea..91f28026e 100644 --- a/grub-core/kern/ia64/dl_helper.c +++ b/grub-core/kern/ia64/dl_helper.c @@ -27,35 +27,35 @@ void grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, grub_size_t *got) { - const Elf_Ehdr *e = ehdr; + const Elf64_Ehdr *e = ehdr; grub_size_t cntt = 0, cntg = 0;; - const Elf_Shdr *s; - Elf_Word entsize; + const Elf64_Shdr *s; + Elf64_Word entsize; unsigned i; /* Find a symbol table. */ - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_SYMTAB) + for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff)); + i < grub_le_to_cpu16 (e->e_shnum); + i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) + if (grub_le_to_cpu32 (s->sh_type) == SHT_SYMTAB) break; - if (i == e->e_shnum) + if (i == grub_le_to_cpu16 (e->e_shnum)) return; entsize = s->sh_entsize; - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_RELA) + for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff)); + i < grub_le_to_cpu16 (e->e_shnum); + i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) + if (grub_le_to_cpu32 (s->sh_type) == SHT_RELA) { - Elf_Rela *rel, *max; + Elf64_Rela *rel, *max; - for (rel = (Elf_Rela *) ((char *) e + s->sh_offset), - max = rel + s->sh_size / s->sh_entsize; + for (rel = (Elf64_Rela *) ((char *) e + grub_le_to_cpu32 (s->sh_offset)), + max = rel + grub_le_to_cpu32 (s->sh_size) / grub_le_to_cpu16 (s->sh_entsize); rel < max; rel++) - switch (ELF_R_TYPE (rel->r_info)) + switch (ELF64_R_TYPE (grub_le_to_cpu32 (rel->r_info))) { case R_IA64_PCREL21B: cntt++; From 6ad6223e925efc5e0fa1d0d46c8620c09a06ea0b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 18 May 2011 01:38:01 +0200 Subject: [PATCH 288/406] Unify grub-mkrescue (except powerpc) and grrub-mknetdir across platforms * grub-core/Makefile.am (platform_DATA): Add modinfo.sh. * grub-core/modinfo.sh.in: New file. * grub-core/Makefile.core.def (modinfo.sh): New script. * util/grub-mknetdir.in: Use modinfo.sh. * util/grub-mkrescue.in: Likewise. --- ChangeLog | 10 ++++++++++ grub-core/Makefile.am | 1 + grub-core/Makefile.core.def | 6 ++++++ grub-core/modinfo.sh.in | 4 ++++ util/grub-mknetdir.in | 9 +++------ util/grub-mkrescue.in | 7 +++---- 6 files changed, 27 insertions(+), 10 deletions(-) create mode 100644 grub-core/modinfo.sh.in diff --git a/ChangeLog b/ChangeLog index 59574202a..0c3503288 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-05-18 Vladimir Serbinenko + + Unify grub-mkrescue (except powerpc) and grrub-mknetdir across platforms + + * grub-core/Makefile.am (platform_DATA): Add modinfo.sh. + * grub-core/modinfo.sh.in: New file. + * grub-core/Makefile.core.def (modinfo.sh): New script. + * util/grub-mknetdir.in: Use modinfo.sh. + * util/grub-mkrescue.in: Likewise. + 2011-05-17 Vladimir Serbinenko * grub-core/kern/ia64/dl_helper.c (grub_ia64_dl_get_tramp_got_size): diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 88858c8ab..98e275f7e 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -329,6 +329,7 @@ CLEANFILES += config.log syminfo.lst moddep.lst $(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@ platform_DATA += $(MOD_FILES) +platform_DATA += modinfo.sh CLEANFILES += $(MOD_FILES) if COND_ENABLE_EFIEMU diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index c717167cb..8afb98b73 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -12,6 +12,12 @@ script = { common = genmod.sh.in; }; +script = { + installdir = noinst; + name = modinfo.sh; + common = modinfo.sh.in; +}; + kernel = { name = kernel; diff --git a/grub-core/modinfo.sh.in b/grub-core/modinfo.sh.in new file mode 100644 index 000000000..ff31ca816 --- /dev/null +++ b/grub-core/modinfo.sh.in @@ -0,0 +1,4 @@ +#!/bin/sh + +grub_modinfo_target_cpu=@target_cpu@ +grub_modinfo_platform=@platform@ diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in index b353e98b9..61a7ec3ad 100644 --- a/util/grub-mknetdir.in +++ b/util/grub-mknetdir.in @@ -27,12 +27,8 @@ libdir=@libdir@ PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ -target_cpu=@target_cpu@ -platform=@platform@ host_os=@host_os@ -pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` localedir=@datadir@/locale -native_platform=@platform@ pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst" self=`basename $0` @@ -64,7 +60,7 @@ Install GRUB on your drive. --subdir=DIR relative subdirectory on network server --grub-mkimage=FILE use FILE as grub-mkimage -$self copies GRUB images into net_directory/subdir/${target_cpu}-${platform} +$self copies GRUB images into net_directory/subdir/target_cpu-platform Report bugs to . EOF @@ -222,7 +218,8 @@ if [ "${override_dir}" = "" ] ; then process_input_dir ${pc_dir} i386-pc fi else - process_input_dir ${override_dir} ${target_cpu}-${native_platform} + source "${override_dir}"/modinfo.sh + process_input_dir "${override_dir}" ${grub_modinfo_target_cpu}-${grub_modinfo_platform} fi diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in index f7f751708..2b6c9d391 100644 --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in @@ -27,8 +27,6 @@ libdir=@libdir@ PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ -target_cpu=@target_cpu@ -native_platform=@platform@ pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst" self=`basename $0` @@ -231,14 +229,15 @@ if [ "${override_dir}" = "" ] ; then process_input_dir ${efi64_dir} x86_64-efi fi else - process_input_dir ${override_dir} ${target_cpu}-${native_platform} + source "${override_dir}"/modinfo.sh + process_input_dir "${override_dir}" ${grub_modinfo_target_cpu}-${grub_modinfo_platform} multiboot_dir= pc_dir= efi32_dir= efi64_dir= coreboot_dir= qemu_dir= - case "${target_cpu}-${native_platform}" in + case "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" in i386-multiboot) multiboot_dir=${override_dir} ;; i386-coreboot) coreboot_dir=${override_dir} ;; i386-qemu) qemu_dir=${override_dir} ;; From cf02731e4837930b21bcb30346ae696d4c9a90d2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 18 May 2011 12:39:22 +0200 Subject: [PATCH 289/406] * grub-core/Makefile.core.def (ieee1275_fb): Use enable=powerpc_ieee1275 for cleanness. --- ChangeLog | 5 +++++ grub-core/Makefile.core.def | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 48b7bc171..eb86c47ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-18 Vladimir Serbinenko + + * grub-core/Makefile.core.def (ieee1275_fb): Use enable=powerpc_ieee1275 + for cleanness. + 2011-05-18 Vladimir Serbinenko FreeDOS direct loading support. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 76539e8d2..f10b63238 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1548,7 +1548,7 @@ module = { module = { name = ieee1275_fb; ieee1275 = video/ieee1275.c; - enable = powerpc; + enable = powerpc_ieee1275; }; module = { From 69b11a560c9b3f9f8f42cb3e6290a0db82b3df30 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 18 May 2011 12:41:22 +0200 Subject: [PATCH 290/406] add missing file --- include/grub/fat.h | 70 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 include/grub/fat.h diff --git a/include/grub/fat.h b/include/grub/fat.h new file mode 100644 index 000000000..7d8e51ad5 --- /dev/null +++ b/include/grub/fat.h @@ -0,0 +1,70 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009 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_FAT_H +#define GRUB_FAT_H 1 + +#include + +struct grub_fat_bpb +{ + grub_uint8_t jmp_boot[3]; + grub_uint8_t oem_name[8]; + grub_uint16_t bytes_per_sector; + grub_uint8_t sectors_per_cluster; + grub_uint16_t num_reserved_sectors; + grub_uint8_t num_fats; + grub_uint16_t num_root_entries; + grub_uint16_t num_total_sectors_16; + grub_uint8_t media; + grub_uint16_t sectors_per_fat_16; + grub_uint16_t sectors_per_track; + grub_uint16_t num_heads; + grub_uint32_t num_hidden_sectors; + grub_uint32_t num_total_sectors_32; + union + { + struct + { + grub_uint8_t num_ph_drive; + grub_uint8_t reserved; + grub_uint8_t boot_sig; + grub_uint32_t num_serial; + grub_uint8_t label[11]; + grub_uint8_t fstype[8]; + } __attribute__ ((packed)) fat12_or_fat16; + struct + { + grub_uint32_t sectors_per_fat_32; + grub_uint16_t extended_flags; + grub_uint16_t fs_version; + grub_uint32_t root_cluster; + grub_uint16_t fs_info; + grub_uint16_t backup_boot_sector; + grub_uint8_t reserved[12]; + grub_uint8_t num_ph_drive; + grub_uint8_t reserved1; + grub_uint8_t boot_sig; + grub_uint32_t num_serial; + grub_uint8_t label[11]; + grub_uint8_t fstype[8]; + } __attribute__ ((packed)) fat32; + } __attribute__ ((packed)) version_specific; +} __attribute__ ((packed)); + +#endif From 26618ff0db4b9454685ebd93414aef4eae868fa4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 18 May 2011 12:51:05 +0200 Subject: [PATCH 291/406] Patch BPB in ntldr and chainloader --bpb. * grub-core/fs/fat.c: Include grub/fat.h. (grub_fat_bpb): Moved to ... * include/grub/fat.h (grub_fat_bpb): ... here. New file. * grub-core/loader/i386/pc/chainloader.c: Include grub/fat.h and grub/ntfs.h. * include/grub/i386/pc/chainloader.h (grub_chainloader_flags_t): Moved from here... * grub-core/loader/i386/pc/chainloader.c (grub_chainloader_flags_t): ... here. * grub-core/loader/i386/pc/chainloader.c (grub_chainloader_patch_bpb): New function. (grub_chainloader_cmd): Patch BPB if --bpb is given. (GRUB_MOD_INIT): Show --bpb. * grub-core/loader/i386/pc/ntldr.c (grub_cmd_ntldr): Patch BPB. * grub-core/normal/main.c (features): New variable. (GRUB_MOD_INIT): Set feature_* variables. * include/grub/i386/pc/chainloader.h (grub_chainloader_patch_bpb): New proto. * include/grub/ntfs.h (grub_ntfs_bpb): New field bios_drive. --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 9ea22d970..e80ff7870 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2011-05-18 Vladimir Serbinenko + Patch BPB in ntldr and chainloader --bpb. + * grub-core/fs/fat.c: Include grub/fat.h. (grub_fat_bpb): Moved to ... * include/grub/fat.h (grub_fat_bpb): ... here. New file. From 5626056ffb35ed0320fed4bceac9768ebc8c31d2 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 18 May 2011 12:53:07 +0100 Subject: [PATCH 292/406] * grub-core/genmod.sh.in: Use 'set -e' rather than '#! /bin/sh -e', to avoid accidents when debugging with 'sh -x'. * grub-core/gensyminfo.sh.in: Likewise. * tests/example_scripted_test.in: Likewise. * tests/grub_cmd_regexp.in: Likewise. * tests/grub_script_blanklines.in: Likewise. * tests/grub_script_dollar.in: Likewise. * tests/grub_script_expansion.in: Likewise. * tests/grub_script_final_semicolon.in: Likewise. * tests/partmap_test.in: Likewise. * tests/util/grub-shell-tester.in: Likewise. * tests/util/grub-shell.in: Likewise. --- ChangeLog | 15 +++++++++++++++ grub-core/genmod.sh.in | 5 +++-- grub-core/gensyminfo.sh.in | 5 +++-- tests/example_scripted_test.in | 3 ++- tests/grub_cmd_regexp.in | 3 ++- tests/grub_script_blanklines.in | 3 ++- tests/grub_script_dollar.in | 3 ++- tests/grub_script_expansion.in | 3 ++- tests/grub_script_final_semicolon.in | 3 ++- tests/partmap_test.in | 5 +++-- tests/util/grub-shell-tester.in | 3 ++- tests/util/grub-shell.in | 3 ++- 12 files changed, 40 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9ed12abbe..bac09e101 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2011-05-18 Colin Watson + + * grub-core/genmod.sh.in: Use 'set -e' rather than '#! /bin/sh -e', + to avoid accidents when debugging with 'sh -x'. + * grub-core/gensyminfo.sh.in: Likewise. + * tests/example_scripted_test.in: Likewise. + * tests/grub_cmd_regexp.in: Likewise. + * tests/grub_script_blanklines.in: Likewise. + * tests/grub_script_dollar.in: Likewise. + * tests/grub_script_expansion.in: Likewise. + * tests/grub_script_final_semicolon.in: Likewise. + * tests/partmap_test.in: Likewise. + * tests/util/grub-shell-tester.in: Likewise. + * tests/util/grub-shell.in: Likewise. + 2011-05-18 Colin Watson Move gfxmenu color handling to video, so that gfxterm can use it diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in index 023cd1062..4cab8e50e 100644 --- a/grub-core/genmod.sh.in +++ b/grub-core/genmod.sh.in @@ -1,5 +1,6 @@ -#! /bin/sh -e -# +#! /bin/sh +set -e + # Copyright (C) 2010 Free Software Foundation, Inc. # # This gensymlist.sh is free software; the author diff --git a/grub-core/gensyminfo.sh.in b/grub-core/gensyminfo.sh.in index 4f5184913..d383f2640 100644 --- a/grub-core/gensyminfo.sh.in +++ b/grub-core/gensyminfo.sh.in @@ -1,5 +1,6 @@ -#! /bin/sh -e -# +#! /bin/sh +set -e + # Copyright (C) 2010 Free Software Foundation, Inc. # # This gensymlist.sh is free software; the author diff --git a/tests/example_scripted_test.in b/tests/example_scripted_test.in index 9ac0424c0..09633e893 100644 --- a/tests/example_scripted_test.in +++ b/tests/example_scripted_test.in @@ -1,3 +1,4 @@ -#!/bin/sh -e +#!/bin/sh +set -e true diff --git a/tests/grub_cmd_regexp.in b/tests/grub_cmd_regexp.in index 43b479fec..e7e625701 100644 --- a/tests/grub_cmd_regexp.in +++ b/tests/grub_cmd_regexp.in @@ -1,4 +1,5 @@ -#! /bin/bash -e +#! /bin/bash +set -e # Run GRUB script in a Qemu instance # Copyright (C) 2010 Free Software Foundation, Inc. diff --git a/tests/grub_script_blanklines.in b/tests/grub_script_blanklines.in index 71b869bd3..89ed763d3 100644 --- a/tests/grub_script_blanklines.in +++ b/tests/grub_script_blanklines.in @@ -1,4 +1,5 @@ -#! /bin/sh -e +#! /bin/sh +set -e @builddir@/grub-script-check < Date: Wed, 18 May 2011 12:57:59 +0100 Subject: [PATCH 293/406] * util/grub-mkrescue.in: Use portable `.' rather than non-portable `source'. --- ChangeLog | 5 +++++ util/grub-mkrescue.in | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index bac09e101..7b44c32fc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-18 Colin Watson + + * util/grub-mkrescue.in: Use portable `.' rather than non-portable + `source'. + 2011-05-18 Colin Watson * grub-core/genmod.sh.in: Use 'set -e' rather than '#! /bin/sh -e', diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in index 2b6c9d391..8367c4dd4 100644 --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in @@ -229,7 +229,7 @@ if [ "${override_dir}" = "" ] ; then process_input_dir ${efi64_dir} x86_64-efi fi else - source "${override_dir}"/modinfo.sh + . "${override_dir}"/modinfo.sh process_input_dir "${override_dir}" ${grub_modinfo_target_cpu}-${grub_modinfo_platform} multiboot_dir= pc_dir= From bf947d36e3408fd4f5c74b7751663924500a53ff Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 18 May 2011 15:35:19 +0200 Subject: [PATCH 294/406] Use full 64-bit division. * grub-core/kern/misc.c (grub_divmod64_full): Renamed to ... (grub_divmod64): ... this. * include/grub/misc.h (grub_divmod64): Removed. All users switch to full version. --- ChangeLog | 9 +++++++++ grub-core/commands/ls.c | 5 +++-- grub-core/disk/i386/pc/biosdisk.c | 2 +- grub-core/disk/lvm.c | 4 ++-- grub-core/disk/raid.c | 4 ++-- grub-core/disk/scsi.c | 2 +- grub-core/fs/affs.c | 2 +- grub-core/fs/btrfs.c | 16 ++++++++-------- grub-core/fs/i386/pc/pxe.c | 3 ++- grub-core/fs/minix.c | 4 ++-- grub-core/fs/nilfs2.c | 14 ++++++++------ grub-core/fs/ntfs.c | 2 +- grub-core/io/bufio.c | 2 +- grub-core/kern/misc.c | 4 ++-- include/grub/misc.h | 17 +++-------------- 15 files changed, 46 insertions(+), 44 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7b44c32fc..cd49e296e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-05-18 Vladimir Serbinenko + + Use full 64-bit division. + + * grub-core/kern/misc.c (grub_divmod64_full): Renamed to ... + (grub_divmod64): ... this. + * include/grub/misc.h (grub_divmod64): Removed. All users switch to full + version. + 2011-05-18 Colin Watson * util/grub-mkrescue.in: Use portable `.' rather than non-portable diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index 5fc648a9b..4c4051a22 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -134,11 +134,12 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) if (units) { - grub_uint32_t whole, fraction; + grub_uint64_t whole, fraction; whole = grub_divmod64 (fsize, 100, &fraction); grub_snprintf (buf, sizeof (buf), - "%u.%02u%c", whole, fraction, + "%" PRIuGRUB_UINT64_T + ".%02" PRIuGRUB_UINT64_T "%c", whole, fraction, grub_human_sizes[units]); grub_printf ("%-12s", buf); } diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index 1d47dc727..3baf20717 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -506,7 +506,7 @@ static grub_size_t get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors) { grub_size_t size; - grub_uint32_t offset; + grub_uint64_t offset; /* OFFSET = SECTOR % SECTORS */ grub_divmod64 (sector, sectors, &offset); diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 206e3e220..563b49b49 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -247,9 +247,9 @@ read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector, /* This is a striped segment. We have to find the right PV similar to RAID0. */ struct grub_lvm_node *stripe = seg->nodes; - grub_uint32_t a, b; + grub_uint64_t a, b; grub_uint64_t seg_offset; /* Offset of the segment in PV device. */ - unsigned int stripenr; + grub_uint64_t stripenr; offset = sector - ((grub_uint64_t) seg->start_extent * (grub_uint64_t) vg->extent_size); diff --git a/grub-core/disk/raid.c b/grub-core/disk/raid.c index 946e6d2c2..c6be3efde 100644 --- a/grub-core/disk/raid.c +++ b/grub-core/disk/raid.c @@ -245,7 +245,7 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector, case 10: { grub_disk_addr_t read_sector, far_ofs; - grub_uint32_t disknr, b, near, far, ofs; + grub_uint64_t disknr, b, near, far, ofs; read_sector = grub_divmod64 (sector, array->chunk_size, &b); far = ofs = near = 1; @@ -351,7 +351,7 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector, case 6: { grub_disk_addr_t read_sector; - grub_uint32_t b, p, n, disknr, e; + grub_uint64_t b, p, n, disknr, e; /* n = 1 for level 4 and 5, 2 for level 6. */ n = array->level / 3; diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index 25f0e3aea..d683cbfe7 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -512,7 +512,7 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector, return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "unsupported SCSI block size"); - grub_uint32_t sector_mod = 0; + grub_uint64_t sector_mod = 0; sector = grub_divmod64 (sector, spb, §or_mod); if (! (sector_mod == 0 && size % spb == 0)) diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 7c2099410..e17540e2f 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -125,7 +125,7 @@ grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) int block = node->block; struct grub_affs_file file; struct grub_affs_data *data = node->data; - grub_uint32_t mod; + grub_uint64_t mod; /* Find the block that points to the fileblock we are looking up by following the chain until the right table is reached. */ diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 59e91b552..533529e3f 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -649,7 +649,7 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, chunk_found: { - grub_uint32_t stripen; + grub_uint64_t stripen; grub_uint64_t stripe_offset; grub_uint64_t off = addr - grub_le_to_cpu64 (key->offset); unsigned redundancy = 1; @@ -679,10 +679,10 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, { grub_uint64_t stripe_length; grub_dprintf ("btrfs", "single\n"); - stripe_length = grub_divmod64_full (grub_le_to_cpu64 (chunk->size), - grub_le_to_cpu16 (chunk->nstripes), - NULL); - stripen = grub_divmod64_full (off, stripe_length, &stripe_offset); + stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size), + grub_le_to_cpu16 (chunk->nstripes), + NULL); + stripen = grub_divmod64 (off, stripe_length, &stripe_offset); csize = (stripen + 1) * stripe_length - off; break; } @@ -699,7 +699,7 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, case GRUB_BTRFS_CHUNK_TYPE_RAID0: { grub_uint64_t middle, high; - grub_uint32_t low; + grub_uint64_t low; grub_dprintf ("btrfs", "RAID0\n"); middle = grub_divmod64 (off, grub_le_to_cpu64 (chunk->stripe_length), @@ -715,7 +715,7 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, case GRUB_BTRFS_CHUNK_TYPE_RAID10: { grub_uint64_t middle, high; - grub_uint32_t low; + grub_uint64_t low; middle = grub_divmod64 (off, grub_le_to_cpu64 (chunk->stripe_length), &low); @@ -760,7 +760,7 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T "+0x%" PRIxGRUB_UINT64_T " (%d stripes (%d substripes) of %" - PRIxGRUB_UINT64_T ") stripe %" PRIxGRUB_UINT32_T + PRIxGRUB_UINT64_T ") stripe %" PRIxGRUB_UINT64_T " maps to 0x%" PRIxGRUB_UINT64_T "\n", grub_le_to_cpu64 (key->offset), grub_le_to_cpu64 (chunk->size), diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index 4304881fa..7d86b78bf 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -306,7 +306,8 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_pxenv_tftp_read c; struct grub_pxe_data *data; struct grub_pxe_disk_data *disk_data = file->device->disk->data; - grub_uint32_t pn, r; + grub_uint32_t pn; + grub_uint64_t r; data = file->data; diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 91659b0f6..64a64cca0 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -229,7 +229,7 @@ grub_minix_read_file (struct grub_minix_data *data, grub_disk_addr_t i; grub_disk_addr_t blockcnt; grub_uint64_t posblock; - grub_uint32_t blockoff; + grub_uint64_t blockoff; /* Adjust len so it we can't read past the end of the file. */ if (len + pos > GRUB_MINIX_INODE_SIZE (data)) @@ -242,7 +242,7 @@ grub_minix_read_file (struct grub_minix_data *data, for (i = posblock; i < blockcnt; i++) { grub_disk_addr_t blknr; - grub_uint32_t blockend = data->block_size; + grub_uint64_t blockend = data->block_size; grub_off_t skipfirst = 0; blknr = grub_minix_get_file_block (data, i); diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c index 4c8d7633c..44fb213bd 100644 --- a/grub-core/fs/nilfs2.c +++ b/grub-core/fs/nilfs2.c @@ -303,7 +303,7 @@ grub_nilfs2_palloc_entries_per_group (struct grub_nilfs2_data *data) static inline grub_uint64_t grub_nilfs2_palloc_group (struct grub_nilfs2_data *data, - grub_uint64_t nr, grub_uint32_t * offset) + grub_uint64_t nr, grub_uint64_t * offset) { return grub_divmod64 (nr, grub_nilfs2_palloc_entries_per_group (data), offset); @@ -368,13 +368,15 @@ grub_nilfs2_palloc_entry_offset (struct grub_nilfs2_data *data, grub_uint64_t nr, unsigned long entry_size) { unsigned long group; - grub_uint32_t group_offset; + grub_uint64_t group_offset; group = grub_nilfs2_palloc_group (data, nr, &group_offset); return grub_nilfs2_palloc_bitmap_block_offset (data, group, entry_size) + 1 + - group_offset / grub_nilfs2_entries_per_block (data, entry_size); + grub_divmod64 (group_offset, grub_nilfs2_entries_per_block (data, + entry_size), + NULL); } @@ -577,7 +579,7 @@ grub_nilfs2_dat_translate (struct grub_nilfs2_data *data, grub_uint64_t key) struct grub_nilfs2_dat_entry entry; grub_disk_t disk = data->disk; grub_uint64_t pptr; - grub_uint32_t blockno, offset; + grub_uint64_t blockno, offset; unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data)); blockno = grub_nilfs2_palloc_entry_offset (data, key, @@ -641,7 +643,7 @@ grub_nilfs2_read_checkpoint (struct grub_nilfs2_data *data, struct grub_nilfs2_checkpoint *cpp) { grub_uint64_t blockno; - grub_uint32_t offset; + grub_uint64_t offset; grub_uint64_t pptr; grub_disk_t disk = data->disk; unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data)); @@ -679,7 +681,7 @@ grub_nilfs2_read_inode (struct grub_nilfs2_data *data, grub_uint64_t ino, struct grub_nilfs2_inode *inodep) { grub_uint64_t blockno; - unsigned int offset; + grub_uint64_t offset; grub_uint64_t pptr; grub_disk_t disk = data->disk; unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data)); diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index 1a8d3f17f..5d128bcc0 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -431,7 +431,7 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest, if (at->flags & AF_GPOS) { grub_disk_addr_t st0, st1; - grub_uint32_t m; + grub_uint64_t m; grub_divmod64 (ofs >> BLK_SHR, ctx->comp.spc, &m); diff --git a/grub-core/io/bufio.c b/grub-core/io/bufio.c index 3b456c1d2..adb38af56 100644 --- a/grub-core/io/bufio.c +++ b/grub-core/io/bufio.c @@ -106,7 +106,7 @@ grub_bufio_read (grub_file_t file, char *buf, grub_size_t len) { grub_size_t res = len; grub_bufio_t bufio = file->data; - grub_uint32_t pos; + grub_uint64_t pos; if ((file->offset >= bufio->file->offset) && (file->offset < bufio->file->offset + bufio->buffer_len)) diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index 1b4cdec66..a3dfabf82 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -597,7 +597,7 @@ grub_reverse (char *str) /* Divide N by D, return the quotient, and store the remainder in *R. */ grub_uint64_t -grub_divmod64_full (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r) +grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r) { /* This algorithm is typically implemented by hardware. The idea is to get the highest bit in N, 64 times, by keeping @@ -666,7 +666,7 @@ grub_lltoa (char *str, int c, unsigned long long n) /* BASE == 10 */ do { - unsigned m; + grub_uint64_t m; n = grub_divmod64 (n, 10, &m); *p++ = m + '0'; diff --git a/include/grub/misc.h b/include/grub/misc.h index 80588be33..da4bd4a7e 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -287,20 +287,9 @@ char *EXPORT_FUNC(grub_xasprintf) (const char *fmt, ...) char *EXPORT_FUNC(grub_xvasprintf) (const char *fmt, va_list args) __attribute__ ((warn_unused_result)); void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn)); void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn)); -grub_uint64_t EXPORT_FUNC(grub_divmod64_full) (grub_uint64_t n, - grub_uint64_t d, - grub_uint64_t *r); -static inline grub_uint64_t grub_divmod64 (grub_uint64_t n, - grub_uint32_t d, - grub_uint32_t *r) -{ - grub_uint64_t ret, rr; - - ret = grub_divmod64_full (n, d, &rr); - if (r) - *r = rr; - return ret; -} +grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n, + grub_uint64_t d, + grub_uint64_t *r); #if NEED_ENABLE_EXECUTE_STACK && !defined(GRUB_UTIL) void EXPORT_FUNC(__enable_execute_stack) (void *addr); From e775d8edfe32cadb0294241a89cabbb00e338e39 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 18 May 2011 15:37:18 +0200 Subject: [PATCH 295/406] * grub-core/bus/usb/usbhub.c (poll_nonroot_hub): Downgrade a printf into dprintf. --- ChangeLog | 5 +++++ grub-core/bus/usb/usbhub.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index cd49e296e..1a3731242 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-18 Vladimir Serbinenko + + * grub-core/bus/usb/usbhub.c (poll_nonroot_hub): Downgrade a printf + into dprintf. + 2011-05-18 Vladimir Serbinenko Use full 64-bit division. diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c index fff94a3fc..b59f2f51d 100644 --- a/grub-core/bus/usb/usbhub.c +++ b/grub-core/bus/usb/usbhub.c @@ -352,8 +352,8 @@ poll_nonroot_hub (grub_usb_device_t dev) GRUB_USB_REQ_GET_STATUS, 0, i, sizeof (status), (char *) &status); - grub_printf ("dev = %p, i = %d, status = %08x\n", - dev, i, status); + grub_dprintf ("usb", "dev = %p, i = %d, status = %08x\n", + dev, i, status); if (err) continue; From 8b63a142977cf48d33fd5486a8afeac9de78aca4 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 18 May 2011 16:10:52 +0100 Subject: [PATCH 296/406] * .bzrignore: Add grub-core/modinfo.sh and a number of test files. --- .bzrignore | 26 ++++++++++++++++++++++++++ ChangeLog | 4 ++++ 2 files changed, 30 insertions(+) diff --git a/.bzrignore b/.bzrignore index 668d060ca..69aedc290 100644 --- a/.bzrignore +++ b/.bzrignore @@ -26,11 +26,16 @@ docs/*.info docs/stamp-vti docs/version.texi *.elf +example_grub_script_test +example_scripted_test +example_unit_test *.exec genkernsyms.sh gensymlist.sh gentrigtables grub-bin2h +grub_cmd_echo +grub_cmd_regexp grub-editenv grub-emu grub_emu_init.c @@ -48,9 +53,28 @@ grub-probe grub_probe_init.c grub_probe_init.h grub-reboot +grub_script_blanklines +grub_script_blockarg +grub_script_break grub-script-check grub_script_check_init.c grub_script_check_init.h +grub_script_comments +grub_script_continue +grub_script_dollar +grub_script_echo1 +grub_script_echo_keywords +grub_script_expansion +grub_script_final_semicolon +grub_script_for1 +grub_script_functions +grub_script_if +grub_script_not +grub_script_return +grub_script_setparams +grub_script_shift +grub_script_vars1 +grub_script_while1 grub_script.tab.c grub_script.tab.h grub_script.yy.c @@ -74,6 +98,7 @@ Makefile *.mod mod-*.c missing +partmap_test *.pf2 *.pp po/*.mo @@ -108,6 +133,7 @@ grub-core/Makefile.gcry.def grub-core/contrib grub-core/genmod.sh grub-core/gensyminfo.sh +grub-core/modinfo.sh grub-core/*.module grub-core/*.pp util/bash-completion.d/grub diff --git a/ChangeLog b/ChangeLog index 1a3731242..3980ef7b4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-05-18 Colin Watson + + * .bzrignore: Add grub-core/modinfo.sh and a number of test files. + 2011-05-18 Vladimir Serbinenko * grub-core/bus/usb/usbhub.c (poll_nonroot_hub): Downgrade a printf From 63e3eea967a3b7148adbf97195023fb6460a9989 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 18 May 2011 17:31:50 +0100 Subject: [PATCH 297/406] * Makefile.util.def (grub-ofpathname): Install manual page. --- ChangeLog | 4 ++++ Makefile.util.def | 1 + 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2708949d1..c8e754685 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-05-18 Colin Watson + + * Makefile.util.def (grub-ofpathname): Install manual page. + 2011-05-18 Colin Watson * grub-core/fs/squash4.c: Add missing GRUB_MOD_LICENSE. diff --git a/Makefile.util.def b/Makefile.util.def index 380c939b9..829b16fac 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -288,6 +288,7 @@ program = { program = { name = grub-ofpathname; installdir = sbin; + mansection = 8; ieee1275 = util/ieee1275/grub-ofpathname.c; ieee1275 = util/ieee1275/ofpath.c; From 9a79fcf2c9b56bc85f9d104f947125aa73099c31 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 May 2011 12:13:18 +0200 Subject: [PATCH 298/406] * grub-core/Makefile.core.def (lsacpi): Fix ia64 mismerge. (lsefisystab): Likewise. (lssal): Likewise. (lsefimmap): Likewise. (hdparm): Enable on qemu-mips. (setjmp): Add ia64 nodist. (serial): Simplify tags. --- ChangeLog | 10 ++++++++++ grub-core/Makefile.core.def | 13 +++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index c8e754685..1a68f911c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-05-19 Vladimir Serbinenko + + * grub-core/Makefile.core.def (lsacpi): Fix ia64 mismerge. + (lsefisystab): Likewise. + (lssal): Likewise. + (lsefimmap): Likewise. + (hdparm): Enable on qemu-mips. + (setjmp): Add ia64 nodist. + (serial): Simplify tags. + 2011-05-18 Colin Watson * Makefile.util.def (grub-ofpathname): Install manual page. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 6f0dce6ff..3fdf395b4 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -505,7 +505,7 @@ module = { common = commands/lsacpi.c; - enable = x86_efi; + enable = efi; enable = i386_pc; enable = i386_coreboot; enable = i386_multiboot; @@ -516,7 +516,7 @@ module = { common = commands/efi/lsefisystab.c; - enable = x86_efi; + enable = efi; }; module = { @@ -524,7 +524,7 @@ module = { common = commands/efi/lssal.c; - enable = x86_efi; + enable = efi; }; module = { @@ -532,7 +532,7 @@ module = { common = commands/efi/lsefimmap.c; - enable = x86_efi; + enable = efi; }; module = { @@ -632,6 +632,7 @@ module = { common = commands/hdparm.c; common = lib/hexdump.c; enable = pci; + enable = mips_qemu_mips; }; module = { @@ -1197,6 +1198,7 @@ module = { extra_dist = lib/x86_64/setjmp.S; extra_dist = lib/sparc64/setjmp.S; extra_dist = lib/powerpc/setjmp.S; + extra_dist = lib/ia64/setjmp.S; }; module = { @@ -1421,8 +1423,7 @@ module = { x86 = term/ns8250.c; enable = emu; - enable = i386; - enable = x86_64_efi; + enable = x86; emu_condition = COND_GRUB_EMU_USB; }; From eea841440d27babefa8dbc1e1e7810875a06eef7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 May 2011 15:39:34 +0200 Subject: [PATCH 299/406] fix several bugs --- Makefile.util.def | 2 - grub-core/Makefile.am | 1 + grub-core/commands/ls.c | 22 +++--- grub-core/net/arp.c | 7 +- grub-core/net/drivers/emu/emunet.c | 8 +-- grub-core/net/drivers/ieee1275/ofnet.c | 7 +- grub-core/net/net.c | 96 +++++++++++++------------- grub-core/net/tftp.c | 17 +++-- grub-core/net/udp.c | 5 +- include/grub/net.h | 14 ++-- 10 files changed, 89 insertions(+), 90 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index 79ab040dd..058572f06 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -36,8 +36,6 @@ library = { common = grub-core/commands/blocklist.c; common = grub-core/commands/extcmd.c; common = grub-core/commands/ls.c; - common = grub-core/net/net.c; - common = grub-core/net/netbuff.c; common = grub-core/disk/dmraid_nvidia.c; common = grub-core/disk/loopback.c; common = grub-core/disk/lvm.c; diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 0fdb4b1db..d5cd25a70 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -167,6 +167,7 @@ endif if COND_emu KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/export.h if COND_GRUB_EMU_SDL KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h endif diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index 20a75733c..9df830612 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -48,9 +48,6 @@ static const char grub_human_sizes[] = {' ', 'K', 'M', 'G', 'T'}; static grub_err_t grub_ls_list_devices (int longlist) { - grub_net_app_level_t proto; - int first = 1; - auto int grub_ls_print_devices (const char *name); int grub_ls_print_devices (const char *name) { @@ -65,15 +62,20 @@ grub_ls_list_devices (int longlist) grub_device_iterate (grub_ls_print_devices); grub_xputs ("\n"); - FOR_NET_APP_LEVEL (proto) +#ifndef GRUB_UTIL { - if (first) - grub_puts_ (N_ ("Network protocols:")); - first = 0; - grub_printf ("%s ", proto->name); + grub_net_app_level_t proto; + int first = 1; + FOR_NET_APP_LEVEL (proto) + { + if (first) + grub_puts_ (N_ ("Network protocols:")); + first = 0; + grub_printf ("%s ", proto->name); + } + grub_xputs ("\n"); } - - grub_xputs ("\n"); +#endif grub_refresh (); diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index 8778a6e51..1300def25 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -87,11 +87,10 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, grub_memcpy (hw_addr, &entry->ll_address, sizeof (*hw_addr)); return GRUB_ERR_NONE; } - grub_net_pool_cards (200); + grub_net_poll_cards (200); + } - } - - return grub_error (GRUB_ERR_TIMEOUT, "Timeout: could not resolve hardware address."); + return grub_error (GRUB_ERR_TIMEOUT, "timeout: could not resolve hardware address"); } grub_err_t diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c index 9e4e66dce..d707d8015 100644 --- a/grub-core/net/drivers/emu/emunet.c +++ b/grub-core/net/drivers/emu/emunet.c @@ -26,7 +26,7 @@ send_card_buffer (struct grub_net_card *dev __attribute__ ((unused)), return GRUB_ERR_NONE; } -static grub_size_t +static grub_ssize_t get_card_packet (struct grub_net_card *dev __attribute__ ((unused)), struct grub_net_buff *pack) { @@ -35,10 +35,7 @@ get_card_packet (struct grub_net_card *dev __attribute__ ((unused)), grub_netbuff_clear(pack); actual = read (fd, pack->data, 1500); if (actual < 0) - { - grub_error (GRUB_ERR_IO, "couldn't receive packets"); - return -1; - } + return -1; grub_netbuff_put (pack, actual); return actual; @@ -65,7 +62,6 @@ static struct grub_net_card emucard = GRUB_MOD_INIT(emunet) { struct ifreq ifr; - // char fullname[64]; fd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK); if (fd < 0) return; diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index cb3882ceb..10d0b979e 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -49,7 +48,7 @@ send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) return GRUB_ERR_NONE; } -static grub_err_t +static grub_ssize_t get_card_packet (struct grub_net_card *dev, struct grub_net_buff *nb) { @@ -65,9 +64,9 @@ get_card_packet (struct grub_net_card *dev, struct grub_net_buff *nb) if (actual) { grub_netbuff_put (nb, actual); - return grub_net_recv_ethernet_packet (nb); + return actual; } - return GRUB_ERR_TIMEOUT; + return -1; } static struct grub_net_card_driver ofdriver = diff --git a/grub-core/net/net.c b/grub-core/net/net.c index be5279c99..a82e73ab0 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -26,6 +26,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -587,9 +588,13 @@ grub_net_file_open_real (struct grub_file *file, const char *name) grub_net_network_level_address_t gateway; grub_net_socket_t socket; static int port = 25300; + const char *comma; - err = grub_net_resolve_address (file->device->net->name - + sizeof (file->device->net->protocol->name) + 1, &addr); + comma = grub_strchr (file->device->net->name, ','); + if (!comma) + return grub_error (GRUB_ERR_NET_BAD_ADDRESS, "no separator"); + + err = grub_net_resolve_address (comma + 1, &addr); if (err) return err; @@ -597,19 +602,22 @@ grub_net_file_open_real (struct grub_file *file, const char *name) if (err) return err; - if ((socket = (grub_net_socket_t) grub_malloc (sizeof (*socket))) == NULL) - return GRUB_ERR_OUT_OF_MEMORY; + socket = (grub_net_socket_t) grub_malloc (sizeof (*socket)); + if (socket == NULL) + return grub_errno; socket->inf = inf; socket->out_nla = addr; socket->in_port = port++; socket->status = 0; socket->app = file->device->net->protocol; - socket->packs = NULL; + socket->packs.first = NULL; + socket->packs.last = NULL; file->device->net->socket = socket; grub_net_socket_register (socket); - if ((err = file->device->net->protocol->open (file,name))) + err = file->device->net->protocol->open (file,name); + if (err) goto fail; file->not_easily_seekable = 1; @@ -625,10 +633,10 @@ static grub_err_t grub_net_file_close_real (grub_file_t file) { grub_net_socket_t sock = file->device->net->socket; - while (sock->packs->first) + while (sock->packs.first) { - grub_netbuff_free (sock->packs->first->nb); - grub_net_remove_packet (sock->packs->first); + grub_netbuff_free (sock->packs.first->nb); + grub_net_remove_packet (sock->packs.first); } grub_net_socket_unregister (sock); grub_free (sock); @@ -636,39 +644,44 @@ grub_net_file_close_real (grub_file_t file) } -static grub_err_t +static void receive_packets (struct grub_net_card *card) { /* Maybe should be better have a fixed number of packets for each card and just mark them as used and not used. */ struct grub_net_buff *nb; - grub_err_t err; + grub_ssize_t actual; nb = grub_netbuff_alloc (1500); if (!nb) - return grub_errno; + { + grub_print_error (); + return; + } - if ((err = card->driver->recv (card, nb)) != GRUB_ERR_NONE) + actual = card->driver->recv (card, nb); + if (actual < 0) grub_netbuff_free (nb); - return err; + else + grub_net_recv_ethernet_packet (nb); + grub_print_error (); } void -grub_net_pool_cards (unsigned time) +grub_net_poll_cards (unsigned time) { struct grub_net_card *card; grub_uint64_t start_time; FOR_NET_CARDS (card) { start_time = grub_get_time_ms (); - while( (grub_get_time_ms () - start_time) < time) - if( receive_packets (card) != GRUB_ERR_NONE) - break; + while ((grub_get_time_ms () - start_time) < time) + receive_packets (card); } } +/* Read from the packets list*/ static grub_ssize_t -process_packets (grub_file_t file, void *buf, grub_size_t len, - void *NESTED_FUNC_ATTR (hook) (void *dest, const void *src, grub_size_t n)) +grub_net_read_real (grub_file_t file, void *buf, grub_size_t len) { grub_net_socket_t sock = file->device->net->socket; struct grub_net_buff *nb; @@ -677,19 +690,24 @@ process_packets (grub_file_t file, void *buf, grub_size_t len, int try = 0; while (try <= 3) { - while (sock->packs->first) + while (sock->packs.first) { try = 0; - nb = sock->packs->first->nb; - amount = (grub_size_t)(len <= (grub_size_t) (nb->tail - nb->data))? len :(grub_size_t)(nb->tail - nb->data); + nb = sock->packs.first->nb; + amount = nb->tail - nb->data; + if (amount > len) + amount = len; len -= amount; total += amount; - hook (ptr, nb->data, amount); - ptr += amount; + if (buf) + { + grub_memcpy (ptr, nb->data, amount); + ptr += amount; + } if (amount == (grub_size_t) (nb->tail - nb->data)) { grub_netbuff_free (nb); - grub_net_remove_packet (sock->packs->first); + grub_net_remove_packet (sock->packs.first); } else nb->data += amount; @@ -700,7 +718,7 @@ process_packets (grub_file_t file, void *buf, grub_size_t len, if (sock->status == 1) { try++; - grub_net_pool_cards (200); + grub_net_poll_cards (200); } else return total; @@ -708,20 +726,6 @@ process_packets (grub_file_t file, void *buf, grub_size_t len, return total; } - -/* Read from the packets list*/ -static grub_ssize_t -grub_net_read_real (grub_file_t file, void *buf, grub_size_t len ) -{ - auto void *NESTED_FUNC_ATTR memcpy_hook (void *dest, const void *src, grub_size_t n); - void *NESTED_FUNC_ATTR memcpy_hook (void *dest __attribute__ ((unused)), const void *src __attribute__ ((unused)), - grub_size_t n __attribute__ ((unused))) - { - return grub_memcpy (dest, src, n); - } - return process_packets (file, buf, len, memcpy_hook); -} - /* Read from the packets list*/ static grub_err_t grub_net_seek_real (struct grub_file *file, grub_off_t offset) @@ -736,17 +740,11 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset) /* We cant seek backwards past the current packet. */ if (file->offset > offset) { - nb = sock->packs->first->nb; + nb = sock->packs.first->nb; return grub_netbuff_push (nb, file->offset - offset); } - auto void *NESTED_FUNC_ATTR dummy (void *dest, const void *src, grub_size_t n); - void *NESTED_FUNC_ATTR dummy (void *dest __attribute__ ((unused)), const void *src __attribute__ ((unused)), - grub_size_t n __attribute__ ((unused))) - { - return NULL; - } - process_packets (file, NULL, len, dummy); + grub_net_read_real (file, NULL, len); return GRUB_ERR_NONE; } diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 278f6ed14..1daf11bc7 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -21,8 +21,12 @@ tftp_open (struct grub_file *file, const char *filename) int hdrlen; char open_data[1500]; struct grub_net_buff nb; - tftp_data_t data = grub_malloc (sizeof *data); + tftp_data_t data; grub_err_t err; + + data = grub_malloc (sizeof *data); + if (!data) + return grub_errno; file->device->net->socket->data = (void *) data; nb.head = open_data; @@ -74,7 +78,7 @@ tftp_open (struct grub_file *file, const char *filename) /* Receive OACK packet. */ for ( i = 0; i < 3; i++) { - grub_net_pool_cards (100); + grub_net_poll_cards (100); if (grub_errno) return grub_errno; if (file->device->net->socket->status != 0) @@ -110,10 +114,13 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) switch (grub_be_to_cpu16 (tftph->opcode)) { case TFTP_OACK: - for (ptr = nb->data; ptr < nb->tail; ) + for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail; ) { if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) - data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1, 0, 0); + { + data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1, + 0, 0); + } while (ptr < nb->tail && *ptr) ptr++; ptr++; @@ -150,7 +157,7 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) tftph = (struct tftphdr *) nb_ack.data; tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); - tftph->u.ack.block = data->block; + tftph->u.ack.block = grub_cpu_to_be16 (data->block); err = grub_net_send_udp_packet (sock, &nb_ack); return err; diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 16b2011ff..4477b3c2b 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -36,15 +36,14 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb) if (grub_be_to_cpu16 (udph->dst) == sock->in_port) { if (sock->status == 0) - sock->out_port = udph->src; + sock->out_port = grub_be_to_cpu16 (udph->src); - /* App protocol remove its own reader. */ sock->app->read (sock,nb); /* If there is data, puts packet in socket list */ if ((nb->tail - nb->data) > 0) - grub_net_put_packet (sock->packs, nb); + grub_net_put_packet (&sock->packs, nb); else grub_netbuff_free (nb); return GRUB_ERR_NONE; diff --git a/include/grub/net.h b/include/grub/net.h index cb6db06d8..1b113972b 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -63,7 +63,7 @@ struct grub_net_card_driver grub_err_t (*init) (struct grub_net_card *dev); grub_err_t (*fini) (struct grub_net_card *dev); grub_err_t (*send) (struct grub_net_card *dev, struct grub_net_buff *buf); - grub_size_t (*recv) (struct grub_net_card *dev, struct grub_net_buff *buf); + grub_ssize_t (*recv) (struct grub_net_card *dev, struct grub_net_buff *buf); }; extern struct grub_net_card_driver *grub_net_card_drivers; @@ -207,24 +207,24 @@ struct grub_net_socket grub_net_app_level_t app; grub_net_network_level_address_t out_nla; struct grub_net_network_level_interface *inf; - grub_net_packets_t *packs; + grub_net_packets_t packs; void *data; }; extern struct grub_net_socket *grub_net_sockets; static inline void -grub_net_socket_register (grub_net_socket_t socket) +grub_net_socket_register (grub_net_socket_t sock) { grub_list_push (GRUB_AS_LIST_P (&grub_net_sockets), - GRUB_AS_LIST (socket)); + GRUB_AS_LIST (sock)); } static inline void -grub_net_socket_unregister (grub_net_socket_t socket) +grub_net_socket_unregister (grub_net_socket_t sock) { grub_list_remove (GRUB_AS_LIST_P (&grub_net_sockets), - GRUB_AS_LIST (socket)); + GRUB_AS_LIST (sock)); } #define FOR_NET_SOCKETS(var) for (var = grub_net_sockets; var; var = var->next) @@ -432,7 +432,7 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, #define FOR_NET_NL_PACKETS(inf, var) FOR_PACKETS(inf->nl_pending, var) void -grub_net_pool_cards (unsigned time); +grub_net_poll_cards (unsigned time); extern grub_err_t (*EXPORT_VAR (grub_file_net_close)) (grub_file_t file); #endif /* ! GRUB_NET_HEADER */ From f35fa3a664474529be91252380eab589838add6d Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 20 May 2011 11:21:36 +0100 Subject: [PATCH 300/406] * util/grub-mkconfig.in: Export GRUB_CMDLINE_LINUX_XEN_REPLACE and GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT. Reported by: Pawel Tecza. --- ChangeLog | 6 ++++++ util/grub-mkconfig.in | 2 ++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 1a68f911c..c94b7482d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-05-20 Colin Watson + + * util/grub-mkconfig.in: Export GRUB_CMDLINE_LINUX_XEN_REPLACE and + GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT. + Reported by: Pawel Tecza. + 2011-05-19 Vladimir Serbinenko * grub-core/Makefile.core.def (lsacpi): Fix ia64 mismerge. diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index afc66f886..4d627c057 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -239,6 +239,8 @@ export GRUB_DEFAULT \ GRUB_CMDLINE_LINUX_DEFAULT \ GRUB_CMDLINE_XEN \ GRUB_CMDLINE_XEN_DEFAULT \ + GRUB_CMDLINE_LINUX_XEN_REPLACE \ + GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT \ GRUB_CMDLINE_NETBSD \ GRUB_CMDLINE_NETBSD_DEFAULT \ GRUB_TERMINAL_INPUT \ From f767c929f2c430bb574a358e0ba8375d49c6ee64 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Sat, 21 May 2011 07:03:55 +0200 Subject: [PATCH 301/406] Don't stat devices unless we have to. * grub-core/kern/emu/getroot.c (grub_find_device): Recognize dir == /dev/mapper. (grub_guess_root_device): Use already known os_dev if possible. * grub-core/kern/emu/hostdisk.c (convert_system_partition_to_system_disk): Scan only in /dev/mapper if device is known to be a dm one. Also-By: Colin Watson --- ChangeLog | 12 ++++++++++++ grub-core/kern/emu/getroot.c | 33 ++++++++++++++++++++------------- grub-core/kern/emu/hostdisk.c | 3 ++- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index c94b7482d..a01d57576 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-05-21 Colin Watson +2011-05-21 Vladimir Serbinenko + + Don't stat devices unless we have to. + + * grub-core/kern/emu/getroot.c (grub_find_device): Recognize + dir == /dev/mapper. + (grub_guess_root_device): Use already known os_dev if possible. + * grub-core/kern/emu/hostdisk.c + (convert_system_partition_to_system_disk): Scan only in /dev/mapper + if device is known to be a dm one. + 2011-05-20 Colin Watson * util/grub-mkconfig.in: Export GRUB_CMDLINE_LINUX_XEN_REPLACE and diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index b1b4f188c..6e49cc31b 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -358,7 +358,7 @@ grub_find_device (const char *dir, dev_t dev) if (S_ISLNK (st.st_mode)) { #ifdef __linux__ - if (strcmp (dir, "mapper") == 0) { + if (strcmp (dir, "mapper") == 0 || strcmp (dir, "/dev/mapper") == 0) { /* Follow symbolic links under /dev/mapper/; the canonical name may be something like /dev/dm-0, but the names under /dev/mapper/ are more human-readable and so we prefer them if @@ -609,20 +609,27 @@ grub_guess_root_device (const char *dir) if (os_dev) { - if (stat (os_dev, &st) >= 0) - dev = st.st_rdev; - else - grub_util_error ("cannot stat `%s'", os_dev); - free (os_dev); - } - else - { - if (stat (dir, &st) >= 0) - dev = st.st_dev; - else - grub_util_error ("cannot stat `%s'", dir); + char *tmp = os_dev; + os_dev = canonicalize_file_name (os_dev); + free (tmp); } + if (os_dev) + { + if (strncmp (os_dev, "/dev/dm-", sizeof ("/dev/dm-") - 1) != 0) + return os_dev; + if (stat (os_dev, &st) < 0) + grub_util_error ("cannot stat `%s'", os_dev); + free (os_dev); + dev = st.st_rdev; + return grub_find_device ("/dev/mapper", dev); + } + + if (stat (dir, &st) < 0) + grub_util_error ("cannot stat `%s'", dir); + + dev = st.st_dev; + #ifdef __CYGWIN__ /* Cygwin specific function. */ os_dev = grub_find_device (dir, dev); diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index d3db7e6be..d633059c3 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -1408,7 +1408,8 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) if (tree) dm_tree_free (tree); free (path); - char *ret = grub_find_device (NULL, (major << 8) | minor); + char *ret = grub_find_device ("/dev/mapper", + (major << 8) | minor); return ret; } From 245f4aba489e3a21129253c28dc138571738a5e4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 May 2011 07:05:46 +0200 Subject: [PATCH 302/406] * grub-core/disk/arc/arcdisk.c (reopen): Close old handle before opening new one. --- ChangeLog | 5 +++++ grub-core/disk/arc/arcdisk.c | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index a01d57576..198750f6a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-21 Vladimir Serbinenko + + * grub-core/disk/arc/arcdisk.c (reopen): Close old handle before + opening new one. + 2011-05-21 Colin Watson 2011-05-21 Vladimir Serbinenko diff --git a/grub-core/disk/arc/arcdisk.c b/grub-core/disk/arc/arcdisk.c index e8416634a..7dff30931 100644 --- a/grub-core/disk/arc/arcdisk.c +++ b/grub-core/disk/arc/arcdisk.c @@ -1,7 +1,7 @@ /* ofdisk.c - Open Firmware disk access. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2004,2006,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2004,2006,2007,2008,2009,2011 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 @@ -105,11 +105,6 @@ reopen (const char *name) grub_dprintf ("arcdisk", "using already opened %s\n", name); return GRUB_ERR_NONE; } - if (GRUB_ARC_FIRMWARE_VECTOR->open (name, 0, &handle)) - { - grub_dprintf ("arcdisk", "couldn't open %s\n", name); - return grub_error (GRUB_ERR_IO, "couldn't open %s", name); - } if (last_path) { GRUB_ARC_FIRMWARE_VECTOR->close (last_handle); @@ -117,6 +112,11 @@ reopen (const char *name) last_path = NULL; last_handle = 0; } + if (GRUB_ARC_FIRMWARE_VECTOR->open (name, 0, &handle)) + { + grub_dprintf ("arcdisk", "couldn't open %s\n", name); + return grub_error (GRUB_ERR_IO, "couldn't open %s", name); + } last_path = grub_strdup (name); if (!last_path) return grub_errno; From f42313bdb07e5a9bb5f6ca92a37f342aae5a1bfa Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Wed, 25 May 2011 11:10:48 -0300 Subject: [PATCH 303/406] Remove unused structs and functions. --- include/grub/disk.h | 20 +------------------- include/grub/ieee1275/ofnet.h | 3 --- include/grub/net/ieee1275/interface.h | 10 ---------- include/grub/net/mem.h | 9 --------- 4 files changed, 1 insertion(+), 41 deletions(-) delete mode 100644 include/grub/net/ieee1275/interface.h delete mode 100644 include/grub/net/mem.h diff --git a/include/grub/disk.h b/include/grub/disk.h index 101303205..66db1149a 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -42,8 +42,7 @@ enum grub_disk_dev_id GRUB_DISK_DEVICE_PXE_ID, GRUB_DISK_DEVICE_SCSI_ID, GRUB_DISK_DEVICE_FILE_ID, - GRUB_DISK_DEVICE_LUKS_ID, - GRUB_DISK_DEVICE_OFNET_ID + GRUB_DISK_DEVICE_LUKS_ID }; struct grub_disk; @@ -117,23 +116,6 @@ struct grub_disk }; typedef struct grub_disk *grub_disk_t; -/* Net Disk */ -enum grub_netdisk_protocol -{ - GRUB_NETDISK_PROTOCOL_TFTP -}; -typedef enum grub_netdisk_protocol grub_netdisk_protocol_t; - -struct grub_netdisk_data -{ - grub_netdisk_protocol_t protocol; - grub_uint32_t server_ip; - grub_uint32_t port; - char *username; - char *password; -}; -typedef struct grub_netdisk_data *grub_netdisk_data_t; - #ifdef GRUB_UTIL struct grub_disk_memberlist { diff --git a/include/grub/ieee1275/ofnet.h b/include/grub/ieee1275/ofnet.h index 9a0ae29e3..c7284df38 100644 --- a/include/grub/ieee1275/ofnet.h +++ b/include/grub/ieee1275/ofnet.h @@ -23,9 +23,6 @@ #include #include -void grub_ofnet_init(void); -void grub_ofnet_fini(void); - struct grub_ofnet { /* The net name. */ diff --git a/include/grub/net/ieee1275/interface.h b/include/grub/net/ieee1275/interface.h deleted file mode 100644 index c369e35a6..000000000 --- a/include/grub/net/ieee1275/interface.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef GRUB_IEEE1275_INTERFACE_HEADER -#define GRUB_IEEE1275_INTERFACE_HEADER 1 - -#include -#include -#include -#include - -grub_bootp_t bootp_pckt; -#endif diff --git a/include/grub/net/mem.h b/include/grub/net/mem.h deleted file mode 100644 index bbdac512b..000000000 --- a/include/grub/net/mem.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef GRUB_NETMM_H -#define GRUB_NETMM_H 1 - -#include -#include - -void *EXPORT_FUNC(grub_net_malloc) (grub_size_t size); - -#endif /* ! GRUB_MM_H */ From 7dd64f12368b8ee35eb32b52b0f6e69068053ab2 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Fri, 27 May 2011 00:22:35 -0300 Subject: [PATCH 304/406] Use a net fs struct to handle open, reand and close in file. --- grub-core/kern/file.c | 25 ++--------------------- grub-core/kern/fs.c | 4 ++-- grub-core/kern/ieee1275/openfw.c | 1 - grub-core/net/net.c | 34 +++++++++++++++++++++----------- include/grub/net.h | 4 +--- 5 files changed, 27 insertions(+), 41 deletions(-) diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c index 2b3e9d689..749e72dfc 100644 --- a/grub-core/kern/file.c +++ b/grub-core/kern/file.c @@ -25,9 +25,6 @@ #include #include -grub_ssize_t (*grub_file_net_read) (grub_file_t file, void *buf, grub_size_t len) = NULL; -grub_err_t (*grub_file_net_open) (struct grub_file *file, const char *name) = NULL; -grub_err_t (*grub_file_net_close) (grub_file_t file) = NULL; grub_err_t (*grub_file_net_seek) (struct grub_file *file, grub_off_t offset) = NULL; grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX]; @@ -91,13 +88,6 @@ grub_file_open (const char *name) file->device = device; - if (device->net && grub_file_net_open) - { - if (grub_file_net_open (file, file_name)) - goto fail; - return file; - } - if (device->disk && file_name[0] != '/') /* This is a block list. */ file->fs = &grub_fs_blocklist; @@ -143,7 +133,7 @@ grub_file_open (const char *name) grub_ssize_t grub_file_read (grub_file_t file, void *buf, grub_size_t len) { - grub_ssize_t res = 0; + grub_ssize_t res; if (file->offset > file->size) { @@ -161,12 +151,7 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) if (len == 0) return 0; - if (file->device->disk) - res = (file->fs->read) (file, buf, len); - else - if (grub_file_net_read && file->device->net) - res = grub_file_net_read (file, buf, len); - + res = (file->fs->read) (file, buf, len); if (res > 0) file->offset += res; @@ -176,12 +161,6 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) grub_err_t grub_file_close (grub_file_t file) { - if (file->device->net) - { - grub_file_net_close (file); - return grub_errno; - } - if (file->fs->close) (file->fs->close) (file); diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c index 7166648be..14d389e07 100644 --- a/grub-core/kern/fs.c +++ b/grub-core/kern/fs.c @@ -94,8 +94,8 @@ grub_fs_probe (grub_device_t device) count--; } } - else if (device->net) - return NULL; + else if (device->net && device->net->fs) + return device->net->fs; grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem"); return 0; diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 3473fe362..db4bec90a 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/grub-core/net/net.c b/grub-core/net/net.c index a82e73ab0..1232b3c74 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -49,6 +49,7 @@ struct grub_net_network_level_interface *grub_net_network_level_interfaces = NUL struct grub_net_card *grub_net_cards = NULL; struct grub_net_card_driver *grub_net_card_drivers = NULL; struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; +static struct grub_fs grub_net_fs; static inline void grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) @@ -571,6 +572,7 @@ grub_net_open_real (const char *name) grub_free (ret); return NULL; } + ret->fs = &grub_net_fs; return ret; } } @@ -580,7 +582,7 @@ grub_net_open_real (const char *name) } static grub_err_t -grub_net_file_open_real (struct grub_file *file, const char *name) +grub_net_fs_open (struct grub_file *file, const char *name) { grub_err_t err; grub_net_network_level_address_t addr; @@ -620,7 +622,7 @@ grub_net_file_open_real (struct grub_file *file, const char *name) if (err) goto fail; file->not_easily_seekable = 1; - + return GRUB_ERR_NONE; fail: grub_net_socket_unregister (socket); @@ -630,7 +632,7 @@ fail: } static grub_err_t -grub_net_file_close_real (grub_file_t file) +grub_net_fs_close (grub_file_t file) { grub_net_socket_t sock = file->device->net->socket; while (sock->packs.first) @@ -681,11 +683,11 @@ grub_net_poll_cards (unsigned time) /* Read from the packets list*/ static grub_ssize_t -grub_net_read_real (grub_file_t file, void *buf, grub_size_t len) +grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) { grub_net_socket_t sock = file->device->net->socket; struct grub_net_buff *nb; - char *ptr = (char *) buf; + char *ptr = buf; grub_size_t amount, total = 0; int try = 0; while (try <= 3) @@ -744,7 +746,7 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset) return grub_netbuff_push (nb, file->offset - offset); } - grub_net_read_real (file, NULL, len); + grub_net_fs_read (file, NULL, len); return GRUB_ERR_NONE; } @@ -1009,6 +1011,17 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), "unrecognised format specification %s", args[3]); } +static struct grub_fs grub_net_fs = + { + .name = "netfs", + .dir = NULL, + .open = grub_net_fs_open, + .read = grub_net_fs_read, + .close = grub_net_fs_close, + .label = NULL, + .uuid = NULL, + .mtime = NULL, + }; static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; static grub_command_t cmd_lsroutes, cmd_lscards, cmd_getdhcp; @@ -1034,10 +1047,8 @@ GRUB_MOD_INIT(net) N_("VAR INTERFACE NUMBER DESCRIPTION"), N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); + grub_fs_register (&grub_net_fs); grub_net_open = grub_net_open_real; - grub_file_net_open = grub_net_file_open_real; - grub_file_net_close = grub_net_file_close_real; - grub_file_net_read = grub_net_read_real; grub_file_net_seek = grub_net_seek_real; } @@ -1050,8 +1061,7 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_lsroutes); grub_unregister_command (cmd_lscards); grub_unregister_command (cmd_getdhcp); + grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; - grub_file_net_read = NULL; - grub_file_net_open = NULL; - grub_file_net_close = NULL; + grub_file_net_seek = NULL; } diff --git a/include/grub/net.h b/include/grub/net.h index 1b113972b..f9745acec 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -234,11 +234,10 @@ typedef struct grub_net char *name; grub_net_app_level_t protocol; grub_net_socket_t socket; + grub_fs_t fs; } *grub_net_t; extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); -extern grub_ssize_t (*EXPORT_VAR (grub_file_net_read)) (grub_file_t file, void *buf, grub_size_t len); -extern grub_err_t (*EXPORT_VAR (grub_file_net_open)) (struct grub_file *file, const char *name); extern grub_err_t (*EXPORT_VAR (grub_file_net_seek)) (struct grub_file *file, grub_off_t offset); struct grub_net_network_level_interface @@ -434,5 +433,4 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, void grub_net_poll_cards (unsigned time); -extern grub_err_t (*EXPORT_VAR (grub_file_net_close)) (grub_file_t file); #endif /* ! GRUB_NET_HEADER */ From c64db050f7f8669fa0b7e27811c869febbeaa848 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 27 May 2011 13:52:21 +0100 Subject: [PATCH 305/406] * grub-core/kern/emu/hostdisk.c (linux_find_partition): Give up after ten consecutive open failures. Scanning all the way up to 10000 is excessive and can cause serious performance problems in some configurations. Fixes Ubuntu bug #787461. --- ChangeLog | 8 ++++++++ grub-core/kern/emu/hostdisk.c | 9 ++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 198750f6a..351700803 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-05-27 Colin Watson + + * grub-core/kern/emu/hostdisk.c (linux_find_partition): Give up + after ten consecutive open failures. Scanning all the way up to + 10000 is excessive and can cause serious performance problems in + some configurations. + Fixes Ubuntu bug #787461. + 2011-05-21 Vladimir Serbinenko * grub-core/disk/arc/arcdisk.c (reopen): Close old handle before diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index d633059c3..e404c4fea 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -564,6 +564,7 @@ linux_find_partition (char *dev, grub_disk_addr_t sector) int i; char real_dev[PATH_MAX]; struct linux_partition_cache *cache; + int missing = 0; strcpy(real_dev, dev); @@ -602,7 +603,13 @@ linux_find_partition (char *dev, grub_disk_addr_t sector) fd = open (real_dev, O_RDONLY); if (fd == -1) - continue; + { + if (missing++ < 10) + continue; + else + return 0; + } + missing = 0; close (fd); start = find_partition_start (real_dev); From 6b4e643081999c9fe388ad5bd8ad96812777fc76 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 27 May 2011 13:57:22 +0100 Subject: [PATCH 306/406] * grub-core/kern/emu/hostdisk.c (linux_find_partition): Handle partitions under /dev/disk/by-id/. --- ChangeLog | 5 +++++ grub-core/kern/emu/hostdisk.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/ChangeLog b/ChangeLog index 351700803..b9abcd07f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-27 Colin Watson + + * grub-core/kern/emu/hostdisk.c (linux_find_partition): Handle + partitions under /dev/disk/by-id/. + 2011-05-27 Colin Watson * grub-core/kern/emu/hostdisk.c (linux_find_partition): Give up diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index e404c4fea..bb528d9bc 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -573,6 +573,12 @@ linux_find_partition (char *dev, grub_disk_addr_t sector) p = real_dev + len - 4; format = "part%d"; } + else if (strncmp (real_dev, "/dev/disk/by-id/", + sizeof ("/dev/disk/by-id/") - 1) == 0) + { + p = real_dev + len; + format = "-part%d"; + } else if (real_dev[len - 1] >= '0' && real_dev[len - 1] <= '9') { p = real_dev + len; From 351c7c8a155d1c3ace2cbefb9682c5b862082d98 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 29 May 2011 22:15:08 +0100 Subject: [PATCH 307/406] * docs/grub.texi (Obtaining and Building GRUB): Substitute `ftp.gnu.org' for `alpha.gnu.org'. --- ChangeLog | 5 +++++ docs/grub.texi | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index b9abcd07f..fca980c1b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-29 Colin Watson + + * docs/grub.texi (Obtaining and Building GRUB): Substitute + `ftp.gnu.org' for `alpha.gnu.org'. + 2011-05-27 Colin Watson * grub-core/kern/emu/hostdisk.c (linux_find_partition): Handle diff --git a/docs/grub.texi b/docs/grub.texi index 818417d41..45c93d69c 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -4330,11 +4330,11 @@ how to get the latest version. @end quotation GRUB is available from the GNU alpha archive site -@uref{ftp://alpha.gnu.org/gnu/grub} or any of its mirrors. The file +@uref{ftp://ftp.gnu.org/gnu/grub} or any of its mirrors. The file will be named grub-version.tar.gz. The current version is @value{VERSION}, so the file you should grab is: -@uref{ftp://alpha.gnu.org/gnu/grub/grub-@value{VERSION}.tar.gz} +@uref{ftp://ftp.gnu.org/gnu/grub/grub-@value{VERSION}.tar.gz} To unbundle GRUB use the instruction: From 4f24b12e1fb7ad56b59dee6f545701a2864512a2 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 2 Jun 2011 15:13:33 -0300 Subject: [PATCH 308/406] Fix compilation in x86 --- grub-core/net/i386/pc/pxe.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/grub-core/net/i386/pc/pxe.c b/grub-core/net/i386/pc/pxe.c index 8e7f75ed8..27c4af17f 100644 --- a/grub-core/net/i386/pc/pxe.c +++ b/grub-core/net/i386/pc/pxe.c @@ -193,7 +193,7 @@ grub_pxefs_open (struct grub_file *file, const char *name) } file->data = data; - file->not_easly_seekable = 1; + file->not_easily_seekable = 1; grub_memcpy (file_int, file, sizeof (struct grub_file)); curr_file = file_int; @@ -215,7 +215,8 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_pxenv_tftp_read c; struct grub_pxe_data *data; - grub_uint32_t pn, r; + grub_uint32_t pn; + grub_uint64_t r; data = file->data; @@ -292,7 +293,7 @@ grub_pxefs_label (grub_device_t device __attribute ((unused)), return GRUB_ERR_NONE; } -static struct grub_net_app_protocol grub_pxefs_fs = +static struct grub_fs grub_pxefs_fs = { .name = "pxe", .dir = grub_pxefs_dir, @@ -303,7 +304,7 @@ static struct grub_net_app_protocol grub_pxefs_fs = .next = 0 }; -static grub_size_t +static grub_ssize_t grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused)), struct grub_net_buff *buf __attribute__ ((unused))) { @@ -334,7 +335,7 @@ grub_pxe_unload (void) { if (grub_pxe_pxenv) { - grub_net_app_level_unregister (&grub_pxefs_fs); + grub_fs_unregister (&grub_pxefs_fs); grub_net_card_unregister (&grub_pxe_card); grub_pxe_pxenv = 0; } @@ -466,7 +467,7 @@ GRUB_MOD_INIT(pxe) ? bp->hw_len : sizeof (grub_pxe_card.default_address.mac)); grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - grub_net_app_level_register (&grub_pxefs_fs); + grub_fs_register (&grub_pxefs_fs); grub_net_card_register (&grub_pxe_card); grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, GRUB_NET_INTERFACE_PERMANENT From 423a1849ef2d4791e03ef6cd6cd94d5bf75144af Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 7 Jun 2011 11:47:31 -0300 Subject: [PATCH 309/406] Write ChangeLog. --- ChangeLog | 26 ++++++++++++++++++++++++++ grub-core/net/tftp.c | 6 +++--- grub-core/net/udp.c | 3 +-- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 198750f6a..122ea029d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2011-06-07 Vladimir Serbinenko +2011-06-07 Manoel Rebelo Abranches + + Network infrastructure. + The ARP protocol was made by Paulo Pinatti + + * include/grub/net/arp.h: New file. + * include/grub/net/ethernet.h: New file. + * include/grub/net/ip.h: New file. + * include/grub/net/netbuff.h: New file. + * include/grub/net/tftp.h: New file. + * include/grub/net/udp.h: New file. + * include/grub/net.h: New file. + * grub-core/net/arp.c: New file. + * grub-core/net/ethernet.c: New file. + * grub-core/net/ip.c: New file. + * grub-core/net/netbuff.c: New file. + * grub-core/net/net.c: New file. + * grub-core/net/drivers/emu/emunet.c: New file. + * grub-core/net/drivers/ieee1275/ofnet.c: New file. + * grub-core/kern/device.c (grub_net_open) : New function. + (grub_device_open) : Handle Network device. + * grub-core/kern/file.c (grub_file_net_seek) : New function. + (grub_file_net_seek): Seek in network device. + + 2011-05-21 Vladimir Serbinenko * grub-core/disk/arc/arcdisk.c (reopen): Close old handle before diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 1daf11bc7..010a4a4bd 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -84,9 +84,9 @@ tftp_open (struct grub_file *file, const char *filename) if (file->device->net->socket->status != 0) break; /* Retry. */ - //err = grub_net_send_udp_packet (file->device->net->socket, &nb); - // if (err) - // return err; + /*err = grub_net_send_udp_packet (file->device->net->socket, &nb); + if (err) + return err;*/ } if (file->device->net->socket->status == 0) diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 4477b3c2b..0b19c3098 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -25,7 +25,6 @@ grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff grub_err_t grub_net_recv_udp_packet (struct grub_net_buff *nb) { - //grub_err_t err; struct udphdr *udph; grub_net_socket_t sock; udph = (struct udphdr *) nb->data; @@ -41,7 +40,7 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb) /* App protocol remove its own reader. */ sock->app->read (sock,nb); - /* If there is data, puts packet in socket list */ + /* If there is data, puts packet in socket list. */ if ((nb->tail - nb->data) > 0) grub_net_put_packet (&sock->packs, nb); else From 4700d08bb4ed597a9aa122340b06fba137327bb7 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 7 Jun 2011 21:59:53 -0300 Subject: [PATCH 310/406] Run indent on files. --- grub-core/net/arp.c | 91 ++++++++------- grub-core/net/drivers/emu/emunet.c | 39 +++---- grub-core/net/drivers/ieee1275/ofnet.c | 154 +++++++++++++------------ grub-core/net/ethernet.c | 28 ++--- grub-core/net/ip.c | 53 ++++----- grub-core/net/netbuff.c | 59 ++++++---- grub-core/net/tftp.c | 118 +++++++++---------- grub-core/net/udp.c | 53 ++++----- 8 files changed, 307 insertions(+), 288 deletions(-) diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index 1300def25..0644d3d2e 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -9,10 +9,10 @@ static struct arp_entry arp_table[10]; static grub_int8_t new_table_entry = -1; -static -void arp_init_table(void) +static void +arp_init_table (void) { - grub_memset (arp_table, 0, sizeof (arp_table)); + grub_memset (arp_table, 0, sizeof (arp_table)); new_table_entry = 0; } @@ -20,19 +20,19 @@ static struct arp_entry * arp_find_entry (const grub_net_network_level_address_t *proto) { unsigned i; - for(i = 0; i < ARRAY_SIZE (arp_table); i++) + for (i = 0; i < ARRAY_SIZE (arp_table); i++) { - if(arp_table[i].avail == 1 && - arp_table[i].nl_address.ipv4 == proto->ipv4) - return &(arp_table[i]); + if (arp_table[i].avail == 1 && + arp_table[i].nl_address.ipv4 == proto->ipv4) + return &(arp_table[i]); } return NULL; } grub_err_t -grub_net_arp_resolve(struct grub_net_network_level_interface *inf, - const grub_net_network_level_address_t *proto_addr, - grub_net_link_level_address_t *hw_addr) +grub_net_arp_resolve (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr, + grub_net_link_level_address_t *hw_addr) { struct arp_entry *entry; struct grub_net_buff nb; @@ -51,10 +51,10 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, /* Build a request packet. */ nb.head = arp_data; nb.end = arp_data + sizeof (arp_data); - grub_netbuff_clear (&nb); + grub_netbuff_clear (&nb); - grub_netbuff_reserve (&nb,128); - grub_netbuff_push (&nb, sizeof(*arp_header) + 2 * (6 + 4)); + grub_netbuff_reserve (&nb, 128); + grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4)); arp_header = (struct arphdr *) nb.data; arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET); arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP); @@ -71,11 +71,11 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, grub_memcpy (aux, &inf->address.ipv4, 4); aux += 4; /* Target hardware address */ - for(i = 0; i < 6; i++) + for (i = 0; i < 6; i++) aux[i] = 0x00; aux += 6; /* Target protocol address */ - grub_memcpy(aux, &proto_addr->ipv4, 4); + grub_memcpy (aux, &proto_addr->ipv4, 4); grub_memset (&target_hw_addr.mac, 0xff, 6); send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); @@ -96,56 +96,59 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, grub_err_t grub_net_arp_receive (struct grub_net_buff *nb) { - struct arphdr *arp_header = (struct arphdr *)nb->data; + struct arphdr *arp_header = (struct arphdr *) nb->data; struct arp_entry *entry; grub_uint8_t *sender_hardware_address, *sender_protocol_address; grub_uint8_t *target_hardware_address, *target_protocol_address; grub_net_network_level_address_t hwaddress; struct grub_net_network_level_interface *inf; - sender_hardware_address = (grub_uint8_t *) arp_header + sizeof(*arp_header); + sender_hardware_address = + (grub_uint8_t *) arp_header + sizeof (*arp_header); sender_protocol_address = sender_hardware_address + arp_header->hln; target_hardware_address = sender_protocol_address + arp_header->pln; target_protocol_address = target_hardware_address + arp_header->hln; grub_memcpy (&hwaddress.ipv4, sender_protocol_address, 4); - /* Check if the sender is in the cache table */ - entry = arp_find_entry(&hwaddress); - /* Update sender hardware address */ + /* Check if the sender is in the cache table. */ + entry = arp_find_entry (&hwaddress); + /* Update sender hardware address. */ if (entry) - grub_memcpy(entry->ll_address.mac, sender_hardware_address, 6); + grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6); else { - /* Add sender to cache table */ + /* Add sender to cache table. */ if (new_table_entry == -1) - arp_init_table(); + arp_init_table (); entry = &(arp_table[new_table_entry]); entry->avail = 1; - grub_memcpy(&entry->nl_address.ipv4, sender_protocol_address, 4); - grub_memcpy(entry->ll_address.mac, sender_hardware_address, 6); + grub_memcpy (&entry->nl_address.ipv4, sender_protocol_address, 4); + grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6); new_table_entry++; if (new_table_entry == ARRAY_SIZE (arp_table)) new_table_entry = 0; } - FOR_NET_NETWORK_LEVEL_INTERFACES(inf) - { - /* Am I the protocol address target? */ - if (grub_memcmp (target_protocol_address, &inf->address.ipv4, 6) == 0 - && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) - { - grub_net_link_level_address_t aux; - /* Swap hardware fields */ - grub_memcpy (target_hardware_address, sender_hardware_address, arp_header->hln); - grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6); - grub_memcpy (aux.mac, sender_protocol_address, 6); - grub_memcpy (sender_protocol_address, target_protocol_address, arp_header->pln); - grub_memcpy (target_protocol_address, aux.mac, arp_header->pln); - /* Change operation to REPLY and send packet */ - arp_header->op = grub_be_to_cpu16 (ARP_REPLY); - grub_memcpy (aux.mac, target_hardware_address, 6); - send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP); - } - } + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + /* Am I the protocol address target? */ + if (grub_memcmp (target_protocol_address, &inf->address.ipv4, 6) == 0 + && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) + { + grub_net_link_level_address_t aux; + /* Swap hardware fields */ + grub_memcpy (target_hardware_address, sender_hardware_address, + arp_header->hln); + grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6); + grub_memcpy (aux.mac, sender_protocol_address, 6); + grub_memcpy (sender_protocol_address, target_protocol_address, + arp_header->pln); + grub_memcpy (target_protocol_address, aux.mac, arp_header->pln); + /* Change operation to REPLY and send packet */ + arp_header->op = grub_be_to_cpu16 (ARP_REPLY); + grub_memcpy (aux.mac, target_hardware_address, 6); + send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP); + } + } return GRUB_ERR_NONE; } diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c index d707d8015..ee4ba4773 100644 --- a/grub-core/net/drivers/emu/emunet.c +++ b/grub-core/net/drivers/emu/emunet.c @@ -13,7 +13,7 @@ static int fd; -static grub_err_t +static grub_err_t send_card_buffer (struct grub_net_card *dev __attribute__ ((unused)), struct grub_net_buff *pack) { @@ -22,7 +22,7 @@ send_card_buffer (struct grub_net_card *dev __attribute__ ((unused)), actual = write (fd, pack->data, pack->tail - pack->data); if (actual < 0) return grub_error (GRUB_ERR_IO, "couldn't send packets"); - + return GRUB_ERR_NONE; } @@ -32,32 +32,32 @@ get_card_packet (struct grub_net_card *dev __attribute__ ((unused)), { ssize_t actual; - grub_netbuff_clear(pack); + grub_netbuff_clear (pack); actual = read (fd, pack->data, 1500); if (actual < 0) return -1; grub_netbuff_put (pack, actual); - return actual; + return actual; } static struct grub_net_card_driver emudriver = -{ - .name = "emu", - .send = send_card_buffer, - .recv = get_card_packet -}; + { + .name = "emu", + .send = send_card_buffer, + .recv = get_card_packet + }; static struct grub_net_card emucard = -{ - .name = "emu0", - .driver = &emudriver, - .default_address = { - .type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET, - { .mac = { 0, 1, 2, 3, 4, 5} } - }, - .flags = 0 -}; + { + .name = "emu0", + .driver = &emudriver, + .default_address = { + .type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET, + {.mac = {0, 1, 2, 3, 4, 5}} + }, + .flags = 0 + }; GRUB_MOD_INIT(emunet) { @@ -84,6 +84,3 @@ GRUB_MOD_FINI(emunet) grub_net_card_unregister (&emucard); } } - - - diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 10d0b979e..751583e9d 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -7,15 +7,18 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static grub_err_t +static grub_err_t card_open (struct grub_net_card *dev) { int status; struct grub_ofnetcard_data *data = dev->data; - char path[grub_strlen(data->path) + grub_strlen(":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512") + 1]; + char path[grub_strlen (data->path) + + grub_strlen (":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512") + 1]; + /* The full string will prevent a bootp packet to be sent. Just put some valid ip in there. */ - grub_snprintf(path,sizeof(path),"%s%s",data->path,":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512"); - status = grub_ieee1275_open (path,&(data->handle)); + grub_snprintf (path, sizeof (path), "%s%s", data->path, + ":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512"); + status = grub_ieee1275_open (path, &(data->handle)); if (status) return grub_error (GRUB_ERR_IO, "Couldn't open network card."); @@ -23,23 +26,23 @@ card_open (struct grub_net_card *dev) return GRUB_ERR_NONE; } -static grub_err_t +static grub_err_t card_close (struct grub_net_card *dev) { struct grub_ofnetcard_data *data = dev->data; - + if (data->handle) grub_ieee1275_close (data->handle); return GRUB_ERR_NONE; } -static grub_err_t +static grub_err_t send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) -{ +{ int actual; int status; struct grub_ofnetcard_data *data = dev->data; - + status = grub_ieee1275_write (data->handle, pack->data, pack->tail - pack->data, &actual); @@ -56,27 +59,27 @@ get_card_packet (struct grub_net_card *dev, struct grub_net_buff *nb) struct grub_ofnetcard_data *data = dev->data; grub_uint64_t start_time; - grub_netbuff_clear (nb); + grub_netbuff_clear (nb); start_time = grub_get_time_ms (); do rc = grub_ieee1275_read (data->handle, nb->data, data->mtu, &actual); while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200)); if (actual) { - grub_netbuff_put (nb, actual); + grub_netbuff_put (nb, actual); return actual; } return -1; } -static struct grub_net_card_driver ofdriver = -{ - .name = "ofnet", - .init = card_open, - .fini = card_close, - .send = send_card_buffer, - .recv = get_card_packet -}; +static struct grub_net_card_driver ofdriver = + { + .name = "ofnet", + .init = card_open, + .fini = card_close, + .send = send_card_buffer, + .recv = get_card_packet + }; static const struct { @@ -84,23 +87,23 @@ static const struct int offset; } -bootp_response_properties[] = -{ - { .name = "bootp-response", .offset = 0 }, - { .name = "dhcp-response", .offset = 0 }, - { .name = "bootpreply-packet", .offset = 0x2a }, -}; +bootp_response_properties[] = + { + { .name = "bootp-response", .offset = 0}, + { .name = "dhcp-response", .offset = 0}, + { .name = "bootpreply-packet", .offset = 0x2a}, + }; -static grub_bootp_t -grub_getbootp_real ( void ) +static grub_bootp_t +grub_getbootp_real (void) { grub_bootp_t packet = grub_malloc (sizeof *packet); - char *bootp_response; + char *bootp_response; grub_ssize_t size; unsigned int i; - for ( i = 0; i < ARRAY_SIZE (bootp_response_properties); i++) - if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, + for (i = 0; i < ARRAY_SIZE (bootp_response_properties); i++) + if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, bootp_response_properties[i].name, &size) >= 0) break; @@ -111,8 +114,7 @@ grub_getbootp_real ( void ) bootp_response = grub_malloc (size); if (grub_ieee1275_get_property (grub_ieee1275_chosen, bootp_response_properties[i].name, - bootp_response , - size, 0) < 0) + bootp_response, size, 0) < 0) return NULL; grub_memcpy (packet, bootp_response + bootp_response_properties[i].offset, sizeof (*packet)); @@ -120,52 +122,55 @@ grub_getbootp_real ( void ) return packet; } -static -void grub_ofnet_findcards (void) +static void +grub_ofnet_findcards (void) { struct grub_net_card *card; grub_ieee1275_phandle_t devhandle; - grub_net_link_level_address_t lla; + grub_net_link_level_address_t lla; int i = 0; auto int search_net_devices (struct grub_ieee1275_devalias *alias); int search_net_devices (struct grub_ieee1275_devalias *alias) - { - if ( !grub_strcmp (alias->type,"network") ) - { - - card = grub_malloc (sizeof (struct grub_net_card)); - struct grub_ofnetcard_data *ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data)); - ofdata->path = grub_strdup (alias->path); - - grub_ieee1275_finddevice (ofdata->path, &devhandle); - - if (grub_ieee1275_get_integer_property - (devhandle, "max-frame-size", &(ofdata->mtu), sizeof (ofdata->mtu), 0)) - return grub_error (GRUB_ERR_IO, "Couldn't retrieve mtu size."); + { + if (!grub_strcmp (alias->type, "network")) + { - if (grub_ieee1275_get_property (devhandle, "mac-address", &(lla.mac), 6, 0)) - return grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address."); - - lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - card->default_address = lla; + card = grub_malloc (sizeof (struct grub_net_card)); + struct grub_ofnetcard_data *ofdata = + grub_malloc (sizeof (struct grub_ofnetcard_data)); + ofdata->path = grub_strdup (alias->path); - card->driver = NULL; - card->data = ofdata; + grub_ieee1275_finddevice (ofdata->path, &devhandle); + + if (grub_ieee1275_get_integer_property + (devhandle, "max-frame-size", &(ofdata->mtu), + sizeof (ofdata->mtu), 0)) + return grub_error (GRUB_ERR_IO, "Couldn't retrieve mtu size."); + + if (grub_ieee1275_get_property + (devhandle, "mac-address", &(lla.mac), 6, 0)) + return grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address."); + + lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + card->default_address = lla; + + card->driver = NULL; + card->data = ofdata; card->flags = 0; - card->name = grub_xasprintf("eth%d",i++); // grub_strdup (alias->name); - grub_net_card_register (card); + card->name = grub_xasprintf ("eth%d", i++); + grub_net_card_register (card); return 0; - } - return 0; + } + return 0; } /* Look at all nodes for devices of the type network. */ grub_ieee1275_devices_iterate (search_net_devices); } -static -void grub_ofnet_probecards (void) +static void +grub_ofnet_probecards (void) { struct grub_net_card *card; struct grub_net_card_driver *driver; @@ -175,19 +180,21 @@ void grub_ofnet_probecards (void) grub_net_network_level_netaddress_t net; bootp_pckt = grub_getbootp (); - /* Assign correspondent driver for each device. */ + /* Assign correspondent driver for each device. */ FOR_NET_CARDS (card) { FOR_NET_CARD_DRIVERS (driver) { - if (driver->init(card) == GRUB_ERR_NONE) + if (driver->init (card) == GRUB_ERR_NONE) { card->driver = driver; - if (bootp_pckt && grub_memcmp(bootp_pckt->chaddr,card->default_address.mac,6) == 0) + if (bootp_pckt + && grub_memcmp (bootp_pckt->chaddr, card->default_address.mac, 6) == 0) { addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; addr.ipv4 = bootp_pckt->yiaddr; - grub_net_add_addr ("bootp_cli_addr", card, addr, card->default_address, 0); + grub_net_add_addr ("bootp_cli_addr", card, addr, + card->default_address, 0); FOR_NET_NETWORK_LEVEL_INTERFACES (inter) if (grub_strcmp (inter->name, "bootp_cli_addr") == 0) break; @@ -197,30 +204,27 @@ void grub_ofnet_probecards (void) grub_net_add_route ("bootp-router", net, inter); } break; - } + } } } grub_free (bootp_pckt); - + } -GRUB_MOD_INIT (ofnet) +GRUB_MOD_INIT(ofnet) { struct grub_net_card *card; grub_getbootp = grub_getbootp_real; grub_net_card_driver_register (&ofdriver); - grub_ofnet_findcards (); - grub_ofnet_probecards (); - FOR_NET_CARDS (card) + grub_ofnet_findcards (); + grub_ofnet_probecards (); + FOR_NET_CARDS (card) if (card->driver == NULL) grub_net_card_unregister (card); } -GRUB_MOD_FINI (ofnet) +GRUB_MOD_FINI(ofnet) { grub_net_card_driver_unregister (&ofdriver); grub_getbootp = NULL; } - - - diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index c96a65602..d29193afe 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -8,25 +8,25 @@ #include #include -grub_err_t +grub_err_t send_ethernet_packet (struct grub_net_network_level_interface *inf, struct grub_net_buff *nb, grub_net_link_level_address_t target_addr, grub_uint16_t ethertype) { - struct etherhdr *eth; + struct etherhdr *eth; - grub_netbuff_push (nb,sizeof(*eth)); - eth = (struct etherhdr *) nb->data; - grub_memcpy(eth->dst, target_addr.mac, 6); - grub_memcpy(eth->src, inf->hwaddress.mac, 6); + grub_netbuff_push (nb, sizeof (*eth)); + eth = (struct etherhdr *) nb->data; + grub_memcpy (eth->dst, target_addr.mac, 6); + grub_memcpy (eth->src, inf->hwaddress.mac, 6); eth->type = grub_cpu_to_be16 (ethertype); return inf->card->driver->send (inf->card, nb); } -grub_err_t +grub_err_t grub_net_recv_ethernet_packet (struct grub_net_buff *nb) { struct etherhdr *eth; @@ -34,32 +34,32 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb) struct snaphdr *snaph; grub_uint16_t type; - eth = (struct etherhdr *) nb->data; + eth = (struct etherhdr *) nb->data; type = grub_be_to_cpu16 (eth->type); grub_netbuff_pull (nb, sizeof (*eth)); - + if (type <= 1500) { llch = (struct llchdr *) nb->data; type = llch->dsap & LLCADDRMASK; if (llch->dsap == 0xaa && llch->ssap == 0xaa && llch->ctrl == 0x3) - { - grub_netbuff_pull (nb,sizeof(*llch)); + { + grub_netbuff_pull (nb, sizeof (*llch)); snaph = (struct snaphdr *) nb->data; type = snaph->type; } } - /* ARP packet */ + /* ARP packet. */ if (type == GRUB_NET_ETHERTYPE_ARP) { grub_net_arp_receive (nb); grub_netbuff_free (nb); } - /* IP packet */ + /* IP packet. */ if (type == GRUB_NET_ETHERTYPE_IP) grub_net_recv_ip_packets (nb); - return GRUB_ERR_NONE; + return GRUB_ERR_NONE; } diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index d6684c29e..4adc2b028 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -8,54 +8,55 @@ #include grub_uint16_t -ipchksum(void *ipv, int len) +ipchksum (void *ipv, int len) { - grub_uint16_t *ip = (grub_uint16_t *)ipv; - grub_uint32_t sum = 0; + grub_uint16_t *ip = (grub_uint16_t *) ipv; + grub_uint32_t sum = 0; - len >>= 1; - while (len--) - { - sum += grub_be_to_cpu16 (*(ip++)); - if (sum > 0xFFFF) - sum -= 0xFFFF; - } + len >>= 1; + while (len--) + { + sum += grub_be_to_cpu16 (*(ip++)); + if (sum > 0xFFFF) + sum -= 0xFFFF; + } - return grub_cpu_to_be16 ((~sum) & 0x0000FFFF); + return grub_cpu_to_be16 ((~sum) & 0x0000FFFF); } grub_err_t grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *target, struct grub_net_buff *nb) -{ +{ struct iphdr *iph; - static int id = 0x2400; + static int id = 0x2400; grub_net_link_level_address_t ll_target_addr; grub_err_t err; - - grub_netbuff_push (nb, sizeof(*iph)); - iph = (struct iphdr *) nb->data; + + grub_netbuff_push (nb, sizeof (*iph)); + iph = (struct iphdr *) nb->data; iph->verhdrlen = ((4 << 4) | 5); iph->service = 0; - iph->len = grub_cpu_to_be16 (nb->tail - nb-> data); + iph->len = grub_cpu_to_be16 (nb->tail - nb->data); iph->ident = grub_cpu_to_be16 (++id); iph->frags = 0; iph->ttl = 0xff; iph->protocol = 0x11; iph->src = inf->address.ipv4; iph->dest = target->ipv4; - - iph->chksum = 0 ; - iph->chksum = ipchksum((void *)nb->data, sizeof(*iph)); - + + iph->chksum = 0; + iph->chksum = ipchksum ((void *) nb->data, sizeof (*iph)); + /* Determine link layer target address via ARP. */ err = grub_net_arp_resolve (inf, target, &ll_target_addr); if (err) return err; return send_ethernet_packet (inf, nb, ll_target_addr, GRUB_NET_ETHERTYPE_IP); } + /* static int ip_filter (struct grub_net_buff *nb) @@ -80,7 +81,7 @@ ip_filter (struct grub_net_buff *nb) return 1; } */ -grub_err_t +grub_err_t grub_net_recv_ip_packets (struct grub_net_buff *nb) { struct iphdr *iph = (struct iphdr *) nb->data; @@ -88,11 +89,11 @@ grub_net_recv_ip_packets (struct grub_net_buff *nb) switch (iph->protocol) { - case IP_UDP: - return grub_net_recv_udp_packet (nb); + case IP_UDP: + return grub_net_recv_udp_packet (nb); break; - default: - grub_netbuff_free (nb); + default: + grub_netbuff_free (nb); break; } diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c index be9fc9de2..aae2f4d8f 100644 --- a/grub-core/net/netbuff.c +++ b/grub-core/net/netbuff.c @@ -22,73 +22,84 @@ #include -grub_err_t grub_netbuff_put (struct grub_net_buff *nb ,grub_size_t len) +grub_err_t +grub_netbuff_put (struct grub_net_buff *nb, grub_size_t len) { nb->tail += len; if (nb->tail > nb->end) return grub_error (GRUB_ERR_OUT_OF_RANGE, "put out of the packet range."); - return GRUB_ERR_NONE; + return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_unput (struct grub_net_buff *nb ,grub_size_t len) +grub_err_t +grub_netbuff_unput (struct grub_net_buff *nb, grub_size_t len) { nb->tail -= len; if (nb->tail < nb->head) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "unput out of the packet range."); - return GRUB_ERR_NONE; + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "unput out of the packet range."); + return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_push (struct grub_net_buff *nb ,grub_size_t len) +grub_err_t +grub_netbuff_push (struct grub_net_buff *nb, grub_size_t len) { nb->data -= len; if (nb->data < nb->head) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "push out of the packet range."); - return GRUB_ERR_NONE; + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "push out of the packet range."); + return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_pull (struct grub_net_buff *nb ,grub_size_t len) +grub_err_t +grub_netbuff_pull (struct grub_net_buff *nb, grub_size_t len) { nb->data += len; if (nb->data > nb->end) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "pull out of the packet range."); - return GRUB_ERR_NONE; + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "pull out of the packet range."); + return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_reserve (struct grub_net_buff *nb ,grub_size_t len) +grub_err_t +grub_netbuff_reserve (struct grub_net_buff *nb, grub_size_t len) { nb->data += len; nb->tail += len; if ((nb->tail > nb->end) || (nb->data > nb->end)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "reserve out of the packet range."); - return GRUB_ERR_NONE; + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "reserve out of the packet range."); + return GRUB_ERR_NONE; } -struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len ) +struct grub_net_buff * +grub_netbuff_alloc (grub_size_t len) { struct grub_net_buff *nb; void *data; - if (len < NETBUFFMINLEN) + if (len < NETBUFFMINLEN) len = NETBUFFMINLEN; - - len = ALIGN_UP (len,NETBUFF_ALIGN); + + len = ALIGN_UP (len, NETBUFF_ALIGN); data = grub_memalign (NETBUFF_ALIGN, len + sizeof (*nb)); if (!data) return NULL; - nb = (struct grub_net_buff *) ((grub_uint8_t *) data + len); + nb = (struct grub_net_buff *) ((grub_uint8_t *) data + len); nb->head = nb->data = nb->tail = data; - nb->end = (char *) nb; - return nb; + nb->end = (char *) nb; + return nb; } -grub_err_t grub_netbuff_free (struct grub_net_buff *nb) +grub_err_t +grub_netbuff_free (struct grub_net_buff *nb) { grub_free (nb->head); return 0; - } -grub_err_t grub_netbuff_clear (struct grub_net_buff *nb) +grub_err_t +grub_netbuff_clear (struct grub_net_buff *nb) { nb->data = nb->tail = nb->head; return 0; diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 010a4a4bd..ac3b3e9db 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -11,15 +11,15 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static grub_err_t +static grub_err_t tftp_open (struct grub_file *file, const char *filename) { - struct tftphdr *tftph; + struct tftphdr *tftph; char *rrq; int i; int rrqlen; int hdrlen; - char open_data[1500]; + char open_data[1500]; struct grub_net_buff nb; tftp_data_t data; grub_err_t err; @@ -27,47 +27,47 @@ tftp_open (struct grub_file *file, const char *filename) data = grub_malloc (sizeof *data); if (!data) return grub_errno; - + file->device->net->socket->data = (void *) data; nb.head = open_data; nb.end = open_data + sizeof (open_data); - grub_netbuff_clear (&nb); + grub_netbuff_clear (&nb); - grub_netbuff_reserve (&nb,1500); - grub_netbuff_push (&nb,sizeof (*tftph)); + grub_netbuff_reserve (&nb, 1500); + grub_netbuff_push (&nb, sizeof (*tftph)); + + tftph = (struct tftphdr *) nb.data; - tftph = (struct tftphdr *) nb.data; - rrq = (char *) tftph->u.rrq; rrqlen = 0; - + tftph->opcode = grub_cpu_to_be16 (TFTP_RRQ); grub_strcpy (rrq, filename); rrqlen += grub_strlen (filename) + 1; - rrq += grub_strlen (filename) + 1; - - grub_strcpy (rrq,"octet"); + rrq += grub_strlen (filename) + 1; + + grub_strcpy (rrq, "octet"); rrqlen += grub_strlen ("octet") + 1; - rrq += grub_strlen ("octet") + 1; + rrq += grub_strlen ("octet") + 1; - grub_strcpy (rrq,"blksize"); - rrqlen += grub_strlen("blksize") + 1; - rrq += grub_strlen ("blksize") + 1; + grub_strcpy (rrq, "blksize"); + rrqlen += grub_strlen ("blksize") + 1; + rrq += grub_strlen ("blksize") + 1; - grub_strcpy (rrq,"1024"); + grub_strcpy (rrq, "1024"); rrqlen += grub_strlen ("1024") + 1; - rrq += grub_strlen ("1024") + 1; - - grub_strcpy (rrq,"tsize"); - rrqlen += grub_strlen ("tsize") + 1; - rrq += grub_strlen ("tsize") + 1; + rrq += grub_strlen ("1024") + 1; - grub_strcpy (rrq,"0"); + grub_strcpy (rrq, "tsize"); + rrqlen += grub_strlen ("tsize") + 1; + rrq += grub_strlen ("tsize") + 1; + + grub_strcpy (rrq, "0"); rrqlen += grub_strlen ("0") + 1; rrq += grub_strlen ("0") + 1; hdrlen = sizeof (tftph->opcode) + rrqlen; - - grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen)); + + grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen)); file->device->net->socket->out_port = TFTP_SERVER_PORT; @@ -76,7 +76,7 @@ tftp_open (struct grub_file *file, const char *filename) return err; /* Receive OACK packet. */ - for ( i = 0; i < 3; i++) + for (i = 0; i < 3; i++) { grub_net_poll_cards (100); if (grub_errno) @@ -85,22 +85,22 @@ tftp_open (struct grub_file *file, const char *filename) break; /* Retry. */ /*err = grub_net_send_udp_packet (file->device->net->socket, &nb); - if (err) - return err;*/ + if (err) + return err; */ } if (file->device->net->socket->status == 0) - return grub_error (GRUB_ERR_TIMEOUT,"Time out opening tftp."); + return grub_error (GRUB_ERR_TIMEOUT, "Time out opening tftp."); file->size = data->file_size; return GRUB_ERR_NONE; } -static grub_err_t +static grub_err_t tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) { struct tftphdr *tftph; - char nbdata[128]; + char nbdata[128]; tftp_data_t data = sock->data; grub_err_t err; char *ptr; @@ -112,9 +112,9 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) tftph = (struct tftphdr *) nb->data; switch (grub_be_to_cpu16 (tftph->opcode)) - { + { case TFTP_OACK: - for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail; ) + for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;) { if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) { @@ -125,13 +125,14 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) ptr++; ptr++; } - sock->status = 1; + sock->status = 1; data->block = 0; - grub_netbuff_clear(nb); - break; + grub_netbuff_clear (nb); + break; case TFTP_DATA: - grub_netbuff_pull (nb,sizeof (tftph->opcode) + sizeof (tftph->u.data.block)); - + grub_netbuff_pull (nb, sizeof (tftph->opcode) + + sizeof (tftph->u.data.block)); + if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) { data->block++; @@ -140,22 +141,23 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) sock->status = 2; /* Prevent garbage in broken cards. */ if (size > 1024) - grub_netbuff_unput (nb, size - 1024); + grub_netbuff_unput (nb, size - 1024); } else - grub_netbuff_clear(nb); - - break; + grub_netbuff_clear (nb); + + break; case TFTP_ERROR: grub_netbuff_clear (nb); - return grub_error (GRUB_ERR_IO, (char *)tftph->u.err.errmsg); - break; - } + return grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg); + break; + } grub_netbuff_clear (&nb_ack); - grub_netbuff_reserve (&nb_ack,128); - grub_netbuff_push (&nb_ack,sizeof (tftph->opcode) + sizeof (tftph->u.ack.block)); + grub_netbuff_reserve (&nb_ack, 128); + grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) + + sizeof (tftph->u.ack.block)); - tftph = (struct tftphdr *) nb_ack.data; + tftph = (struct tftphdr *) nb_ack.data; tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); tftph->u.ack.block = grub_cpu_to_be16 (data->block); @@ -163,7 +165,7 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) return err; } -static grub_err_t +static grub_err_t tftp_close (struct grub_file *file __attribute__ ((unused))) { grub_free (file->device->net->socket->data); @@ -171,19 +173,19 @@ tftp_close (struct grub_file *file __attribute__ ((unused))) } static struct grub_net_app_protocol grub_tftp_protocol = -{ - .name = "tftp", - .open = tftp_open, - .read = tftp_receive, - .close = tftp_close -}; + { + .name = "tftp", + .open = tftp_open, + .read = tftp_receive, + .close = tftp_close + }; -GRUB_MOD_INIT (tftp) +GRUB_MOD_INIT(tftp) { grub_net_app_level_register (&grub_tftp_protocol); } -GRUB_MOD_FINI (tftp) +GRUB_MOD_FINI(tftp) { grub_net_app_level_unregister (&grub_tftp_protocol); } diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 0b19c3098..86220bf0f 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -5,24 +5,25 @@ #include grub_err_t -grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff *nb) +grub_net_send_udp_packet (const grub_net_socket_t socket, + struct grub_net_buff *nb) { struct udphdr *udph; - grub_netbuff_push (nb,sizeof(*udph)); - - udph = (struct udphdr *) nb->data; + grub_netbuff_push (nb, sizeof (*udph)); + + udph = (struct udphdr *) nb->data; udph->src = grub_cpu_to_be16 (socket->in_port); udph->dst = grub_cpu_to_be16 (socket->out_port); /* No chechksum. */ - udph->chksum = 0; + udph->chksum = 0; udph->len = grub_cpu_to_be16 (nb->tail - nb->data); - + return grub_net_send_ip_packet (socket->inf, &(socket->out_nla), nb); } -grub_err_t +grub_err_t grub_net_recv_udp_packet (struct grub_net_buff *nb) { struct udphdr *udph; @@ -30,24 +31,24 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb) udph = (struct udphdr *) nb->data; grub_netbuff_pull (nb, sizeof (*udph)); - FOR_NET_SOCKETS(sock) - { - if (grub_be_to_cpu16 (udph->dst) == sock->in_port) - { - if (sock->status == 0) - sock->out_port = grub_be_to_cpu16 (udph->src); - - /* App protocol remove its own reader. */ - sock->app->read (sock,nb); - - /* If there is data, puts packet in socket list. */ - if ((nb->tail - nb->data) > 0) - grub_net_put_packet (&sock->packs, nb); - else - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } - } - grub_netbuff_free (nb); + FOR_NET_SOCKETS (sock) + { + if (grub_be_to_cpu16 (udph->dst) == sock->in_port) + { + if (sock->status == 0) + sock->out_port = grub_be_to_cpu16 (udph->src); + + /* App protocol remove its own reader. */ + sock->app->read (sock, nb); + + /* If there is data, puts packet in socket list. */ + if ((nb->tail - nb->data) > 0) + grub_net_put_packet (&sock->packs, nb); + else + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + } + grub_netbuff_free (nb); return GRUB_ERR_NONE; } From 1e9aef7d963e86016cbb0568c5f9d01eee31fd99 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 13 Jun 2011 17:35:50 +0100 Subject: [PATCH 311/406] * docs/man/grub-mklayout.h2m (DESCRIPTION): Add a reference to the input format. --- ChangeLog | 5 +++++ docs/man/grub-mklayout.h2m | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/ChangeLog b/ChangeLog index fca980c1b..5ac0ffb5c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-13 Colin Watson + + * docs/man/grub-mklayout.h2m (DESCRIPTION): Add a reference to the + input format. + 2011-05-29 Colin Watson * docs/grub.texi (Obtaining and Building GRUB): Substitute diff --git a/docs/man/grub-mklayout.h2m b/docs/man/grub-mklayout.h2m index cda6f3676..1e43409c0 100644 --- a/docs/man/grub-mklayout.h2m +++ b/docs/man/grub-mklayout.h2m @@ -1,4 +1,10 @@ [NAME] grub-mklayout \- generate a GRUB keyboard layout file +[DESCRIPTION] +grub-mklayout processes a keyboard layout description in +.BR keymaps (5) +format into a format that can be used by GRUB's +.B keymap +command. [SEE ALSO] .BR grub-mkconfig (8) From e23bc603f8e799dd85839ffe928b9e41d9a09d83 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Wed, 15 Jun 2011 15:11:26 -0300 Subject: [PATCH 312/406] Prevent crash when detecting fs. --- grub-core/net/net.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 1232b3c74..380eec3b5 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -581,6 +581,16 @@ grub_net_open_real (const char *name) return NULL; } +static grub_err_t +grub_net_fs_dir (grub_device_t device, const char *path __attribute__ ((unused)), + int (*hook) (const char *filename, + const struct grub_dirhook_info *info) __attribute__ ((unused))) +{ + if (!device->net) + return grub_error (GRUB_ERR_BAD_FS, "invalid extent"); + return GRUB_ERR_NONE; +} + static grub_err_t grub_net_fs_open (struct grub_file *file, const char *name) { @@ -1014,7 +1024,7 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), static struct grub_fs grub_net_fs = { .name = "netfs", - .dir = NULL, + .dir = grub_net_fs_dir, .open = grub_net_fs_open, .read = grub_net_fs_read, .close = grub_net_fs_close, From 881ac815d00ecf1aa9093b015edf8c2da334d191 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Thu, 16 Jun 2011 14:33:11 +0200 Subject: [PATCH 313/406] 2011-06-16 Robert Millan Detect `ataraid' devices on GNU/kFreeBSD. Fix for ATA devices using `ata' driver on kernel of FreeBSD 9. * util/deviceiter.c [__FreeBSD_kernel__] (get_ada_disk_name) (get_ataraid_disk_name): New functions. [__FreeBSD_kernel__] (grub_util_iterate_devices): Scan for ataraid (/dev/ar[0-9]+) and ada (/dev/ada[0-9]+) devices using get_ataraid_disk_name() and get_ada_disk_name(). --- ChangeLog | 11 +++++++++++ util/deviceiter.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 5ac0ffb5c..043b858a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-06-16 Robert Millan + + Detect `ataraid' devices on GNU/kFreeBSD. Fix for ATA devices using + `ata' driver on kernel of FreeBSD 9. + + * util/deviceiter.c [__FreeBSD_kernel__] (get_ada_disk_name) + (get_ataraid_disk_name): New functions. + [__FreeBSD_kernel__] (grub_util_iterate_devices): Scan for ataraid + (/dev/ar[0-9]+) and ada (/dev/ada[0-9]+) devices using + get_ataraid_disk_name() and get_ada_disk_name(). + 2011-06-13 Colin Watson * docs/man/grub-mklayout.h2m (DESCRIPTION): Add a reference to the diff --git a/util/deviceiter.c b/util/deviceiter.c index 30c18beea..2a8acec0e 100644 --- a/util/deviceiter.c +++ b/util/deviceiter.c @@ -1,7 +1,7 @@ /* deviceiter.c - iterate over system devices */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2011 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 @@ -286,6 +286,20 @@ get_scsi_disk_name (char *name, int unit) #endif } +#ifdef __FreeBSD_kernel__ +static void +get_ada_disk_name (char *name, int unit) +{ + sprintf (name, "/dev/ada%d", unit); +} + +static void +get_ataraid_disk_name (char *name, int unit) +{ + sprintf (name, "/dev/ar%d", unit); +} +#endif + #ifdef __linux__ static void get_virtio_disk_name (char *name, int unit) @@ -620,6 +634,35 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), } } +#ifdef __FreeBSD_kernel__ + /* IDE disks using ATA Direct Access driver. */ + if (get_kfreebsd_version () >= 800000) + for (i = 0; i < 96; i++) + { + char name[16]; + + get_ada_disk_name (name, i); + if (check_device_readable_unique (name)) + { + if (hook (name, 0)) + goto out; + } + } + + /* ATARAID disks. */ + for (i = 0; i < 8; i++) + { + char name[20]; + + get_ataraid_disk_name (name, i); + if (check_device_readable_unique (name)) + { + if (hook (name, 0)) + goto out; + } + } +#endif + #ifdef __linux__ /* Virtio disks. */ for (i = 0; i < 26; i++) From d6d205568f4ea7e6a49cd2ca745a8584d3bbca5d Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Sat, 18 Jun 2011 20:18:25 -0300 Subject: [PATCH 314/406] Close cards before boot. --- grub-core/kern/ieee1275/init.c | 2 ++ grub-core/net/drivers/ieee1275/ofnet.c | 4 ++++ grub-core/net/net.c | 11 +++++++++++ include/grub/net.h | 1 + 4 files changed, 18 insertions(+) diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index ad34ea188..3c55096a4 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -264,6 +264,8 @@ grub_machine_init (void) void grub_machine_fini (void) { + if (grub_grubnet_fini) + grub_grubnet_fini (); grub_ofdisk_fini (); grub_console_fini (); } diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 751583e9d..9789f2261 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -225,6 +225,10 @@ GRUB_MOD_INIT(ofnet) GRUB_MOD_FINI(ofnet) { + struct grub_net_card *card; + FOR_NET_CARDS (card) + if (card->driver && !grub_strcmp (card->driver->name, "ofnet")) + card->driver->fini (card); grub_net_card_driver_unregister (&ofdriver); grub_getbootp = NULL; } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 380eec3b5..c7732ecbf 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -1021,6 +1021,15 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), "unrecognised format specification %s", args[3]); } +static void +grub_grubnet_fini_real (void) +{ + struct grub_net_card *card; + FOR_NET_CARDS (card) + if (card->driver) + card->driver->fini (card); +} + static struct grub_fs grub_net_fs = { .name = "netfs", @@ -1060,6 +1069,7 @@ GRUB_MOD_INIT(net) grub_fs_register (&grub_net_fs); grub_net_open = grub_net_open_real; grub_file_net_seek = grub_net_seek_real; + grub_grubnet_fini = grub_grubnet_fini_real; } GRUB_MOD_FINI(net) @@ -1074,4 +1084,5 @@ GRUB_MOD_FINI(net) grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; grub_file_net_seek = NULL; + grub_grubnet_fini = NULL; } diff --git a/include/grub/net.h b/include/grub/net.h index f9745acec..006ec0686 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -239,6 +239,7 @@ typedef struct grub_net extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); extern grub_err_t (*EXPORT_VAR (grub_file_net_seek)) (struct grub_file *file, grub_off_t offset); +void (*EXPORT_VAR (grub_grubnet_fini)) (void); struct grub_net_network_level_interface { From d855fbcf37fa97de08952aae80fc5bf704fdf149 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Sat, 18 Jun 2011 20:20:53 -0300 Subject: [PATCH 315/406] Add error verification in netbuff operations. --- grub-core/net/arp.c | 7 +++++-- grub-core/net/drivers/ieee1275/ofnet.c | 5 ++++- grub-core/net/ethernet.c | 11 ++++++++--- grub-core/net/ip.c | 5 ++++- grub-core/net/netbuff.c | 4 ++-- grub-core/net/tftp.c | 21 ++++++++++++--------- grub-core/net/udp.c | 4 +++- 7 files changed, 38 insertions(+), 19 deletions(-) diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index 0644d3d2e..6fc7554cd 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -39,6 +39,7 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf, struct arphdr *arp_header; grub_net_link_level_address_t target_hw_addr; char *aux, arp_data[128]; + grub_err_t err; int i; /* Check cache table. */ @@ -52,9 +53,11 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf, nb.head = arp_data; nb.end = arp_data + sizeof (arp_data); grub_netbuff_clear (&nb); - grub_netbuff_reserve (&nb, 128); - grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4)); + + if ((err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4))) != GRUB_ERR_NONE) + return err; + arp_header = (struct arphdr *) nb.data; arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET); arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP); diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 9789f2261..2c264edb1 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -228,7 +228,10 @@ GRUB_MOD_FINI(ofnet) struct grub_net_card *card; FOR_NET_CARDS (card) if (card->driver && !grub_strcmp (card->driver->name, "ofnet")) - card->driver->fini (card); + { + card->driver->fini (card); + card->driver = NULL; + } grub_net_card_driver_unregister (&ofdriver); grub_getbootp = NULL; } diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index d29193afe..d33a07010 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -15,8 +15,10 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, grub_uint16_t ethertype) { struct etherhdr *eth; + grub_err_t err; - grub_netbuff_push (nb, sizeof (*eth)); + if ((err = grub_netbuff_push (nb, sizeof (*eth))) != GRUB_ERR_NONE) + return err; eth = (struct etherhdr *) nb->data; grub_memcpy (eth->dst, target_addr.mac, 6); grub_memcpy (eth->src, inf->hwaddress.mac, 6); @@ -33,10 +35,12 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb) struct llchdr *llch; struct snaphdr *snaph; grub_uint16_t type; + grub_err_t err; eth = (struct etherhdr *) nb->data; type = grub_be_to_cpu16 (eth->type); - grub_netbuff_pull (nb, sizeof (*eth)); + if ((err = grub_netbuff_pull (nb, sizeof (*eth))) != GRUB_ERR_NONE) + return err; if (type <= 1500) { @@ -45,7 +49,8 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb) if (llch->dsap == 0xaa && llch->ssap == 0xaa && llch->ctrl == 0x3) { - grub_netbuff_pull (nb, sizeof (*llch)); + if ((err = grub_netbuff_pull (nb, sizeof (*llch))) != GRUB_ERR_NONE) + return err; snaph = (struct snaphdr *) nb->data; type = snaph->type; } diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 4adc2b028..749b41d02 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -85,7 +85,10 @@ grub_err_t grub_net_recv_ip_packets (struct grub_net_buff *nb) { struct iphdr *iph = (struct iphdr *) nb->data; - grub_netbuff_pull (nb, sizeof (*iph)); + grub_err_t err; + + if ((err = grub_netbuff_pull (nb, sizeof (*iph))) != GRUB_ERR_NONE) + return err; switch (iph->protocol) { diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c index aae2f4d8f..d20104ab0 100644 --- a/grub-core/net/netbuff.c +++ b/grub-core/net/netbuff.c @@ -95,12 +95,12 @@ grub_err_t grub_netbuff_free (struct grub_net_buff *nb) { grub_free (nb->head); - return 0; + return GRUB_ERR_NONE; } grub_err_t grub_netbuff_clear (struct grub_net_buff *nb) { nb->data = nb->tail = nb->head; - return 0; + return GRUB_ERR_NONE; } diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index ac3b3e9db..138020b08 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -34,7 +34,8 @@ tftp_open (struct grub_file *file, const char *filename) grub_netbuff_clear (&nb); grub_netbuff_reserve (&nb, 1500); - grub_netbuff_push (&nb, sizeof (*tftph)); + if ((err = grub_netbuff_push (&nb, sizeof (*tftph))) != GRUB_ERR_NONE) + return err; tftph = (struct tftphdr *) nb.data; @@ -67,8 +68,8 @@ tftp_open (struct grub_file *file, const char *filename) rrq += grub_strlen ("0") + 1; hdrlen = sizeof (tftph->opcode) + rrqlen; - grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen)); - + if ((err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen))) != GRUB_ERR_NONE) + return err; file->device->net->socket->out_port = TFTP_SERVER_PORT; err = grub_net_send_udp_packet (file->device->net->socket, &nb); @@ -130,9 +131,9 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) grub_netbuff_clear (nb); break; case TFTP_DATA: - grub_netbuff_pull (nb, sizeof (tftph->opcode) + - sizeof (tftph->u.data.block)); - + if ((err = grub_netbuff_pull (nb, sizeof (tftph->opcode) + + sizeof (tftph->u.data.block))) != GRUB_ERR_NONE) + return err; if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) { data->block++; @@ -141,7 +142,8 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) sock->status = 2; /* Prevent garbage in broken cards. */ if (size > 1024) - grub_netbuff_unput (nb, size - 1024); + if ((err = grub_netbuff_unput (nb, size - 1024)) != GRUB_ERR_NONE) + return err; } else grub_netbuff_clear (nb); @@ -154,8 +156,9 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) } grub_netbuff_clear (&nb_ack); grub_netbuff_reserve (&nb_ack, 128); - grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) - + sizeof (tftph->u.ack.block)); + if ((err = grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) + + sizeof (tftph->u.ack.block))) != GRUB_ERR_NONE) + return err; tftph = (struct tftphdr *) nb_ack.data; tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 86220bf0f..b070cbb64 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -9,8 +9,10 @@ grub_net_send_udp_packet (const grub_net_socket_t socket, struct grub_net_buff *nb) { struct udphdr *udph; + grub_err_t err; - grub_netbuff_push (nb, sizeof (*udph)); + if ((err = grub_netbuff_push (nb, sizeof (*udph))) != GRUB_ERR_NONE) + return err; udph = (struct udphdr *) nb->data; udph->src = grub_cpu_to_be16 (socket->in_port); From 77ba5392d0e482de3618c00129c7bc2a35691cce Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 08:45:12 +0200 Subject: [PATCH 316/406] New testload grub-fstest command --- Makefile.util.def | 1 + util/grub-fstest.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Makefile.util.def b/Makefile.util.def index 829b16fac..1fcd9465e 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -34,6 +34,7 @@ library = { common_nodist = grub_script.tab.h; common = grub-core/commands/blocklist.c; + common = grub-core/commands/testload.c; common = grub-core/commands/extcmd.c; common = grub-core/commands/ls.c; common = grub-core/disk/dmraid_nvidia.c; diff --git a/util/grub-fstest.c b/util/grub-fstest.c index f253a96f6..c2c8b1148 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -61,7 +61,8 @@ enum { CMD_CMP, CMD_HEX, CMD_CRC, - CMD_BLOCKLIST + CMD_BLOCKLIST, + CMD_TESTLOAD }; #define BUF_SIZE 32256 @@ -359,6 +360,9 @@ fstest (int n, char **args) case CMD_BLOCKLIST: execute_command ("blocklist", n, args); grub_printf ("\n"); + case CMD_TESTLOAD: + execute_command ("testload", n, args); + grub_printf ("\n"); } for (i = 0; i < num_disks; i++) @@ -520,6 +524,11 @@ argp_parser (int key, char *arg, struct argp_state *state) cmd = CMD_BLOCKLIST; nparm = 1; } + else if (!grub_strcmp (arg, "testload")) + { + cmd = CMD_TESTLOAD; + nparm = 1; + } else { fprintf (stderr, _("Invalid command %s.\n"), arg); From 2df2e89fee627a098b0192a526a2b6999699211c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 09:39:12 +0200 Subject: [PATCH 317/406] Fixed a cache collision bug. Thanks guufy1 for bugreport and test --- grub-core/kern/disk.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index 30bc604f0..f1456defd 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -544,6 +544,17 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, break; } + if (data) + { + grub_memcpy ((char *) buf + + (agglomerate << (GRUB_DISK_CACHE_BITS + + GRUB_DISK_SECTOR_BITS)), + data, GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); + grub_disk_cache_unlock (disk->dev->id, disk->id, + sector + (agglomerate + << GRUB_DISK_CACHE_BITS)); + } + if (agglomerate) { grub_disk_addr_t i; @@ -568,17 +579,12 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, buf = (char *) buf + (agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS)); } - + if (data) { - grub_memcpy (buf, data, - GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); sector += GRUB_DISK_CACHE_SIZE; buf = (char *) buf + (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); size -= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); - grub_disk_cache_unlock (disk->dev->id, disk->id, - sector + (agglomerate - << GRUB_DISK_CACHE_BITS)); } } From 8a5d6919e169d5839c474a5c0e8d8ed6b492fef1 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 23 Jun 2011 18:08:53 +0200 Subject: [PATCH 318/406] Avoid NULL deref in grub_device_open. * grub-core/kern/device.c (grub_device_open): Don't dereference a NULL pointer upon failed grub_env_get. --- ChangeLog | 6 ++++++ grub-core/kern/device.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e3ed5d13a..a7f6ce738 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-23 Jim Meyering + + avoid NULL deref in grub_device_open + * grub-core/kern/device.c (grub_device_open): Don't dereference + a NULL pointer upon failed grub_env_get. + 2011-06-23 Vladimir Serbinenko Support non-512B sectors and agglomerate reads. diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c index 3db14f50e..50f49ae6b 100644 --- a/grub-core/kern/device.c +++ b/grub-core/kern/device.c @@ -35,7 +35,7 @@ grub_device_open (const char *name) if (! name) { name = grub_env_get ("root"); - if (*name == '\0') + if (name == NULL || *name == '\0') { grub_error (GRUB_ERR_BAD_DEVICE, "no device is set"); goto fail; From e2d1dba0ae8d87c9f9fc8ecbb4b10243507b2615 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 19:50:41 +0200 Subject: [PATCH 319/406] * grub-core/kern/emu/getroot.c (grub_guess_root_device): Don't accept /dev/root as a valid device. --- ChangeLog | 8 +++++++- grub-core/kern/emu/getroot.c | 6 ++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index a7f6ce738..0ea09a0ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,12 @@ +2011-06-23 Vladimir Serbinenko + + * grub-core/kern/emu/getroot.c (grub_guess_root_device): Don't accept + /dev/root as a valid device. + 2011-06-23 Jim Meyering - avoid NULL deref in grub_device_open + Avoid NULL deref in grub_device_open. + * grub-core/kern/device.c (grub_device_open): Don't dereference a NULL pointer upon failed grub_env_get. diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index 6e49cc31b..db27abf74 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -616,13 +616,15 @@ grub_guess_root_device (const char *dir) if (os_dev) { - if (strncmp (os_dev, "/dev/dm-", sizeof ("/dev/dm-") - 1) != 0) + int dm = (strncmp (os_dev, "/dev/dm-", sizeof ("/dev/dm-") - 1) == 0); + int root = (strcmp (os_dev, "/dev/root") == 0); + if (!dm && !root) return os_dev; if (stat (os_dev, &st) < 0) grub_util_error ("cannot stat `%s'", os_dev); free (os_dev); dev = st.st_rdev; - return grub_find_device ("/dev/mapper", dev); + return grub_find_device (dm ? "/dev/mapper" : "/dev", dev); } if (stat (dir, &st) < 0) From a199a8cd1a5d01847e21bb40f21e044f4d728244 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 20:05:39 +0200 Subject: [PATCH 320/406] Fix spurious warning. * grub-core/partmap/acorn.c (grub_acorn_boot_block): Make a union. (acorn_partition_map_find): Use .bin member. --- ChangeLog | 7 +++++++ grub-core/partmap/acorn.c | 19 +++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0ea09a0ab..a455d9b6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-06-23 Vladimir Serbinenko + + Fix spurious warning. + + * grub-core/partmap/acorn.c (grub_acorn_boot_block): Make a union. + (acorn_partition_map_find): Use .bin member. + 2011-06-23 Vladimir Serbinenko * grub-core/kern/emu/getroot.c (grub_guess_root_device): Don't accept diff --git a/grub-core/partmap/acorn.c b/grub-core/partmap/acorn.c index 9a68ddd92..341b8ac5f 100644 --- a/grub-core/partmap/acorn.c +++ b/grub-core/partmap/acorn.c @@ -34,11 +34,18 @@ GRUB_MOD_LICENSE ("GPLv3+"); struct grub_acorn_boot_block { - grub_uint8_t misc[0x1C0]; - struct grub_filecore_disc_record disc_record; - grub_uint8_t flags; - grub_uint16_t start_cylinder; - grub_uint8_t checksum; + union + { + struct + { + grub_uint8_t misc[0x1C0]; + struct grub_filecore_disc_record disc_record; + grub_uint8_t flags; + grub_uint16_t start_cylinder; + grub_uint8_t checksum; + } __attribute__ ((packed, aligned)); + grub_uint8_t bin[0x200]; + }; } __attribute__ ((packed, aligned)); struct linux_part @@ -71,7 +78,7 @@ acorn_partition_map_find (grub_disk_t disk, struct linux_part *m, goto fail; for (i = 0; i != 0x1ff; ++i) - checksum = (checksum & 0xff) + (checksum >> 8) + boot.misc[i]; + checksum = ((checksum & 0xff) + (checksum >> 8) + boot.bin[i]); if ((grub_uint8_t) checksum != boot.checksum) goto fail; From e98c83e910e7fd3e39dd021213d111526e80775c Mon Sep 17 00:00:00 2001 From: David Volgyes Date: Thu, 23 Jun 2011 20:28:04 +0200 Subject: [PATCH 321/406] * grub-core/bus/usb/ohci.c (grub_ohci_pci_iter): Avoid NULL-pointer dereference. --- ChangeLog | 5 +++++ grub-core/bus/usb/ohci.c | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index a455d9b6b..ad72c8da2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-23 David Volgyes + + * grub-core/bus/usb/ohci.c (grub_ohci_pci_iter): Avoid NULL-pointer + dereference. + 2011-06-23 Vladimir Serbinenko Fix spurious warning. diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c index df0d0f4af..7e8eaaac2 100644 --- a/grub-core/bus/usb/ohci.c +++ b/grub-core/bus/usb/ohci.c @@ -454,10 +454,12 @@ grub_ohci_pci_iter (grub_pci_device_t dev, fail: if (o) - grub_dma_free (o->td_chunk); - grub_dma_free (o->ed_bulk_chunk); - grub_dma_free (o->ed_ctrl_chunk); - grub_dma_free (o->hcca_chunk); + { + grub_dma_free (o->td_chunk); + grub_dma_free (o->ed_bulk_chunk); + grub_dma_free (o->ed_ctrl_chunk); + grub_dma_free (o->hcca_chunk); + } grub_free (o); return 0; From fbc626665f458d60cc3d19e1e8eedb68638cb4dc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 20:38:19 +0200 Subject: [PATCH 322/406] * grub-core/loader/i386/xnu.c (grub_cpu_xnu_fill_devprop): Don't attempt to continue if allocation is failed. Reported by: David Volgyes . --- ChangeLog | 7 +++++++ grub-core/loader/i386/xnu.c | 10 +++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index ad72c8da2..66c55d101 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-06-23 Vladimir Serbinenko + + * grub-core/loader/i386/xnu.c (grub_cpu_xnu_fill_devprop): Don't attempt + to continue if allocation is failed. + + Reported by: David Volgyes . + 2011-06-23 David Volgyes * grub-core/bus/usb/ohci.c (grub_ohci_pci_iter): Avoid NULL-pointer diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c index b877b0ea5..6128ec384 100644 --- a/grub-core/loader/i386/xnu.c +++ b/grub-core/loader/i386/xnu.c @@ -452,11 +452,11 @@ grub_cpu_xnu_fill_devprop (void) } devprop = grub_xnu_create_value (&(efikey->first_child), "device-properties"); - if (devprop) - { - devprop->data = grub_malloc (total_length); - devprop->datasize = total_length; - } + if (!devprop) + return grub_errno; + + devprop->data = grub_malloc (total_length); + devprop->datasize = total_length; ptr = devprop->data; head = ptr; From 1abe47dc9935106c0079d0e50388d2c6168864a5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 20:55:36 +0200 Subject: [PATCH 323/406] * grub-core/lib/reed_solomon.c (rs_recover): Prevent memory leak. (main): Close file. --- ChangeLog | 5 +++++ grub-core/lib/reed_solomon.c | 25 +++++++++++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 66c55d101..c267a8a0f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-23 Vladimir Serbinenko + + * grub-core/lib/reed_solomon.c (rs_recover): Prevent memory leak. + (main): Close file. + 2011-06-23 Vladimir Serbinenko * grub-core/loader/i386/xnu.c (grub_cpu_xnu_fill_devprop): Don't attempt diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c index e500ba32d..8b5e8235a 100644 --- a/grub-core/lib/reed_solomon.c +++ b/grub-core/lib/reed_solomon.c @@ -265,6 +265,22 @@ rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs) syndroms (m, s, rs, sy); + for (i = 0; i < (int) rs; i++) + if (sy[i] != 0) + break; + + /* No error detected. */ + if (i == (int) rs) + { +#ifndef STANDALONE + free (sigma); + free (errpot); + free (errpos); + free (sy); +#endif + return; + } + { gf_single_t *eq; @@ -275,14 +291,6 @@ rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs) scratch += rs2 * (rs2 + 1) * sizeof (gf_single_t); #endif - for (i = 0; i < (int) rs; i++) - if (sy[i] != 0) - break; - - /* No error detected. */ - if (i == (int) rs) - return; - for (i = 0; i < (int) rs2; i++) for (j = 0; j < (int) rs2 + 1; j++) eq[i * (rs2 + 1) + j] = sy[i+j]; @@ -504,6 +512,7 @@ main (int argc, char **argv) rs = s / 3; buf = xmalloc (s + rs + SECTOR_SIZE); fread (buf, 1, s, in); + fclose (in); grub_reed_solomon_add_redundancy (buf, s, rs); From e061a1b537b1f8b719bfa69c49bdf39877fdf4d7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 20:58:35 +0200 Subject: [PATCH 324/406] * grub-core/lib/reed_solomon.c (rs_recover) [STANDALONE]: Prevent memory leak. --- ChangeLog | 6 ++++++ grub-core/lib/reed_solomon.c | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/ChangeLog b/ChangeLog index c267a8a0f..327b52afc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,13 @@ +2011-06-23 Vladimir Serbinenko + + * grub-core/lib/reed_solomon.c (rs_recover) [STANDALONE]: + Prevent memory leak. + 2011-06-23 Vladimir Serbinenko * grub-core/lib/reed_solomon.c (rs_recover): Prevent memory leak. (main): Close file. + Reported by: David Volgyes . 2011-06-23 Vladimir Serbinenko diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c index 8b5e8235a..365b76003 100644 --- a/grub-core/lib/reed_solomon.c +++ b/grub-core/lib/reed_solomon.c @@ -277,6 +277,11 @@ rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs) free (errpot); free (errpos); free (sy); +#else + scratch -= rs2 * sizeof (gf_single_t); + scratch -= rs2 * sizeof (gf_single_t); + scratch -= rs2 * sizeof (int); + scratch -= rs * sizeof (gf_single_t); #endif return; } From 13548d26e9492450da911aa5b7c5d9e6850cb327 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 21:06:50 +0200 Subject: [PATCH 325/406] * util/raid.c (grub_util_raid_getmembers): Close fd before returning. Reported by: David Volgyes . --- ChangeLog | 6 ++++++ util/raid.c | 2 ++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 327b52afc..058116fbb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-23 Vladimir Serbinenko + + * util/raid.c (grub_util_raid_getmembers): Close fd before returning. + + Reported by: David Volgyes . + 2011-06-23 Vladimir Serbinenko * grub-core/lib/reed_solomon.c (rs_recover) [STANDALONE]: diff --git a/util/raid.c b/util/raid.c index a6aa5f95e..c1c32b959 100644 --- a/util/raid.c +++ b/util/raid.c @@ -80,6 +80,8 @@ grub_util_raid_getmembers (const char *name) devicelist[j] = NULL; + close (fd); + return devicelist; } From cad3237fb5ecf1a21f9e1bad957942a0cac8d6cc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 22:02:05 +0200 Subject: [PATCH 326/406] * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): Close file after stat. Reported by: David Volgyes . --- ChangeLog | 6 ++++++ grub-core/kern/emu/hostdisk.c | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 058116fbb..abe285ee9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-23 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): Close + file after stat. + Reported by: David Volgyes . + 2011-06-23 Vladimir Serbinenko * util/raid.c (grub_util_raid_getmembers): Close fd before returning. diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index e53a39c39..f4af73858 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -1866,7 +1866,12 @@ grub_util_biosdisk_is_floppy (grub_disk_t disk) /* Shouldn't happen either. */ if (fstat (fd, &st) < 0) - return 0; + { + close (fd); + return 0; + } + + close (fd); #if defined(__NetBSD__) if (major(st.st_rdev) == RAW_FLOPPY_MAJOR) From 03147f46671e2270ef4849a710b20572462844ac Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 22:11:42 +0200 Subject: [PATCH 327/406] * util/grub-mkpasswd-pbkdf2.c (main): Don't double-close. Reported by: David Volgyes . --- ChangeLog | 5 +++++ util/grub-mkpasswd-pbkdf2.c | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index abe285ee9..59cb3ec57 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-23 Vladimir Serbinenko + + * util/grub-mkpasswd-pbkdf2.c (main): Don't double-close. + Reported by: David Volgyes . + 2011-06-23 Vladimir Serbinenko * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): Close diff --git a/util/grub-mkpasswd-pbkdf2.c b/util/grub-mkpasswd-pbkdf2.c index dc2afdb6e..709ba7da7 100644 --- a/util/grub-mkpasswd-pbkdf2.c +++ b/util/grub-mkpasswd-pbkdf2.c @@ -270,7 +270,6 @@ main (int argc, char *argv[]) free (bufhex); free (salthex); free (salt); - fclose (f); grub_util_error ("couldn't retrieve random data for salt"); } fclose (f); From fe12fd5b439956ab5354dde8699870cb0fd7c8bd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 22:18:31 +0200 Subject: [PATCH 328/406] * util/ieee1275/ofpath.c (check_sas): Close fd. (main): Free of_path. Reported by: David Volgyes . --- ChangeLog | 6 ++++++ util/ieee1275/ofpath.c | 2 ++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 59cb3ec57..062f66c00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-23 Vladimir Serbinenko + + * util/ieee1275/ofpath.c (check_sas): Close fd. + (main): Free of_path. + Reported by: David Volgyes . + 2011-06-23 Vladimir Serbinenko * util/grub-mkpasswd-pbkdf2.c (main): Don't double-close. diff --git a/util/ieee1275/ofpath.c b/util/ieee1275/ofpath.c index 1a433345d..f72bea8a5 100644 --- a/util/ieee1275/ofpath.c +++ b/util/ieee1275/ofpath.c @@ -297,6 +297,7 @@ check_sas (char *sysfs_path, int *tgt) free (path); free (p); + close (fd); } static void @@ -419,6 +420,7 @@ int main(int argc, char **argv) of_path = grub_util_devname_to_ofpath (argv[1]); printf("%s\n", of_path); + free (of_path); return 0; } From c31dc5f5e4291e2aa7fb9fbf5ed88640fb05cc83 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 23 Jun 2011 23:13:20 +0200 Subject: [PATCH 329/406] Add support for DRI and RSTn markers in JPEG files. * grub-core/video/readers/jpeg.c (JPEG_MARKER_DRI): New define. (JPEG_MARKER_RST0): Likewise. (JPEG_MARKER_RST1): Likewise. (JPEG_MARKER_RST2): Likewise. (JPEG_MARKER_RST3): Likewise. (JPEG_MARKER_RST4): Likewise. (JPEG_MARKER_RST5): Likewise. (JPEG_MARKER_RST6): Likewise. (JPEG_MARKER_RST7): Likewise. (grub_jpeg_data): New fields dri, r1, bitmap_ptr. (grub_jpeg_decode_dri): New function. (grub_jpeg_decode_sos): Move image data related part into grub_jpeg_decode_data function. (grub_jpeg_decode_data): New function. (grub_jpeg_reset): New function. (grub_jpeg_decode_jpeg): Handle new markers. --- ChangeLog | 21 +++++++++ grub-core/video/readers/jpeg.c | 78 ++++++++++++++++++++++++++++------ 2 files changed, 87 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 062f66c00..655cbe25e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2011-06-23 Szymon Janc + + Add support for DRI and RSTn markers in JPEG files. + + * grub-core/video/readers/jpeg.c (JPEG_MARKER_DRI): New define. + (JPEG_MARKER_RST0): Likewise. + (JPEG_MARKER_RST1): Likewise. + (JPEG_MARKER_RST2): Likewise. + (JPEG_MARKER_RST3): Likewise. + (JPEG_MARKER_RST4): Likewise. + (JPEG_MARKER_RST5): Likewise. + (JPEG_MARKER_RST6): Likewise. + (JPEG_MARKER_RST7): Likewise. + (grub_jpeg_data): New fields dri, r1, bitmap_ptr. + (grub_jpeg_decode_dri): New function. + (grub_jpeg_decode_sos): Move image data related part into + grub_jpeg_decode_data function. + (grub_jpeg_decode_data): New function. + (grub_jpeg_reset): New function. + (grub_jpeg_decode_jpeg): Handle new markers. + 2011-06-23 Vladimir Serbinenko * util/ieee1275/ofpath.c (check_sas): Close fd. diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c index 8cdb2f61d..d61c90ec9 100644 --- a/grub-core/video/readers/jpeg.c +++ b/grub-core/video/readers/jpeg.c @@ -39,6 +39,15 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define JPEG_MARKER_DQT 0xdb #define JPEG_MARKER_SOF0 0xc0 #define JPEG_MARKER_SOS 0xda +#define JPEG_MARKER_DRI 0xdd +#define JPEG_MARKER_RST0 0xd0 +#define JPEG_MARKER_RST1 0xd1 +#define JPEG_MARKER_RST2 0xd2 +#define JPEG_MARKER_RST3 0xd3 +#define JPEG_MARKER_RST4 0xd4 +#define JPEG_MARKER_RST5 0xd5 +#define JPEG_MARKER_RST6 0xd6 +#define JPEG_MARKER_RST7 0xd7 #define SHIFT_BITS 8 #define CONST(x) ((int) ((x) * (1L << SHIFT_BITS) + 0.5)) @@ -66,6 +75,7 @@ struct grub_jpeg_data { grub_file_t file; struct grub_video_bitmap **bitmap; + grub_uint8_t *bitmap_ptr; int image_width; int image_height; @@ -82,6 +92,8 @@ struct grub_jpeg_data jpeg_data_unit_t cbdu; int vs, hs; + int dri; + int r1; int dc_value[3]; @@ -315,6 +327,18 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data) return grub_errno; } +static grub_err_t +grub_jpeg_decode_dri (struct grub_jpeg_data *data) +{ + if (grub_jpeg_get_word (data) != 4) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "jpeg: DRI marker length must be 4"); + + data->dri = grub_jpeg_get_word (data); + + return grub_errno; +} + static void grub_jpeg_idct_transform (jpeg_data_unit_t du) { @@ -526,8 +550,7 @@ grub_jpeg_ycrcb_to_rgb (int yy, int cr, int cb, grub_uint8_t * rgb) static grub_err_t grub_jpeg_decode_sos (struct grub_jpeg_data *data) { - int i, cc, r1, c1, nr1, nc1, vb, hb; - grub_uint8_t *ptr1; + int i, cc; grub_uint32_t data_offset; data_offset = data->file->offset; @@ -563,17 +586,25 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) GRUB_VIDEO_BLIT_FORMAT_RGB_888)) return grub_errno; - data->bit_mask = 0x0; + data->bitmap_ptr = (*data->bitmap)->data; + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_jpeg_decode_data (struct grub_jpeg_data *data) +{ + int c1, vb, hb, nr1, nc1; + int rst = data->dri; vb = data->vs * 8; hb = data->hs * 8; nr1 = (data->image_height + vb - 1) / vb; nc1 = (data->image_width + hb - 1) / hb; - ptr1 = (*data->bitmap)->data; - for (r1 = 0; r1 < nr1; - r1++, ptr1 += (vb * data->image_width - hb * nc1) * 3) - for (c1 = 0; c1 < nc1; c1++, ptr1 += hb * 3) + for (; data->r1 < nr1 && (!data->dri || rst); + data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3) + for (c1 = 0; c1 < nc1 && (!data->dri || rst); + c1++, rst--, data->bitmap_ptr += hb * 3) { int r2, c2, nr2, nc2; grub_uint8_t *ptr2; @@ -588,10 +619,10 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) if (grub_errno) return grub_errno; - nr2 = (r1 == nr1 - 1) ? (data->image_height - r1 * vb) : vb; + nr2 = (data->r1 == nr1 - 1) ? (data->image_height - data->r1 * vb) : vb; nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb; - ptr2 = ptr1; + ptr2 = data->bitmap_ptr; for (r2 = 0; r2 < nr2; r2++, ptr2 += (data->image_width - nc2) * 3) for (c2 = 0; c2 < nc2; c2++, ptr2 += 3) { @@ -600,8 +631,7 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) i0 = (r2 / data->vs) * 8 + (c2 / data->hs); cr = data->crdu[i0]; cb = data->cbdu[i0]; - yy = - data->ydu[(r2 / 8) * 2 + (c2 / 8)][(r2 % 8) * 8 + (c2 % 8)]; + yy = data->ydu[(r2 / 8) * 2 + (c2 / 8)][(r2 % 8) * 8 + (c2 % 8)]; grub_jpeg_ycrcb_to_rgb (yy, cr, cb, ptr2); } @@ -610,6 +640,16 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) return grub_errno; } +static void +grub_jpeg_reset (struct grub_jpeg_data *data) +{ + data->bit_mask = 0x0; + + data->dc_value[0] = 0; + data->dc_value[1] = 0; + data->dc_value[2] = 0; +} + static grub_uint8_t grub_jpeg_get_marker (struct grub_jpeg_data *data) { @@ -655,8 +695,22 @@ grub_jpeg_decode_jpeg (struct grub_jpeg_data *data) case JPEG_MARKER_SOF0: /* Start Of Frame 0. */ grub_jpeg_decode_sof (data); break; + case JPEG_MARKER_DRI: /* Define Restart Interval. */ + grub_jpeg_decode_dri (data); + break; case JPEG_MARKER_SOS: /* Start Of Scan. */ - grub_jpeg_decode_sos (data); + if (grub_jpeg_decode_sos (data)) + break; + case JPEG_MARKER_RST0: /* Restart. */ + case JPEG_MARKER_RST1: + case JPEG_MARKER_RST2: + case JPEG_MARKER_RST3: + case JPEG_MARKER_RST4: + case JPEG_MARKER_RST5: + case JPEG_MARKER_RST6: + case JPEG_MARKER_RST7: + grub_jpeg_decode_data (data); + grub_jpeg_reset (data); break; case JPEG_MARKER_EOI: /* End Of Image. */ return grub_errno; From 005dd67cb68ece8ea1af43c5c11096d0d32614ea Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 00:29:21 +0200 Subject: [PATCH 330/406] * grub-core/disk/ahci.c: Add missing license statements. * grub-core/fs/romfs.c: Likewise. * grub-core/lib/ia64/setjmp.S: Likewise. * grub-core/loader/i386/pc/freedos.c: Likewise. * grub-core/loader/ia64/efi/linux.c: Likewise. * grub-core/video/colors.c: Likewise. * include/grub/dl.h (GRUB_MOD_DEP): New macro. --- grub-core/disk/ahci.c | 2 ++ grub-core/fs/romfs.c | 2 ++ grub-core/lib/ia64/setjmp.S | 6 ++++++ grub-core/loader/i386/pc/freedos.c | 2 ++ grub-core/loader/ia64/efi/linux.c | 2 ++ grub-core/video/colors.c | 3 +++ include/grub/dl.h | 3 +++ 7 files changed, 20 insertions(+) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 699df767c..0f355aa53 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + struct grub_ahci_cmd_head { grub_uint32_t config; diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c index 07632e635..58dc98f34 100644 --- a/grub-core/fs/romfs.c +++ b/grub-core/fs/romfs.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + struct grub_romfs_superblock { char magic[8]; diff --git a/grub-core/lib/ia64/setjmp.S b/grub-core/lib/ia64/setjmp.S index 0851885c5..190623d35 100644 --- a/grub-core/lib/ia64/setjmp.S +++ b/grub-core/lib/ia64/setjmp.S @@ -64,6 +64,12 @@ 0x1b0 f30 0x1c0 f31 */ +#include +#include + + .file "setjmp.S" + +GRUB_MOD_LICENSE ("GPLv2+") /* The following two entry points are the traditional entry points: */ diff --git a/grub-core/loader/i386/pc/freedos.c b/grub-core/loader/i386/pc/freedos.c index 0ae815490..f796e08f4 100644 --- a/grub-core/loader/i386/pc/freedos.c +++ b/grub-core/loader/i386/pc/freedos.c @@ -33,6 +33,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_dl_t my_mod; static struct grub_relocator *rel; static grub_uint32_t ebx = 0xffffffff; diff --git a/grub-core/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c index b018e4549..247eebae5 100644 --- a/grub-core/loader/ia64/efi/linux.c +++ b/grub-core/loader/ia64/efi/linux.c @@ -31,6 +31,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define ALIGN_MIN (256*1024*1024) #define GRUB_ELF_SEARCH 1024 diff --git a/grub-core/video/colors.c b/grub-core/video/colors.c index 0637c5508..3119c0249 100644 --- a/grub-core/video/colors.c +++ b/grub-core/video/colors.c @@ -21,6 +21,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); struct named_color { diff --git a/include/grub/dl.h b/include/grub/dl.h index 5ce01199c..75cd71758 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -90,6 +90,9 @@ static const char grub_module_name_##name[] \ #ifndef ASM_FILE #define GRUB_MOD_LICENSE(license) \ static char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), used)) = "LICENSE=" license; +#define GRUB_MOD_DEP(name) \ +static const char grub_module_depend_##name[] \ + __attribute__((section(GRUB_MOD_SECTION(moddeps)), __used__)) = #name #else #define GRUB_MOD_LICENSE(license) \ .section GRUB_MOD_SECTION(module_license), "a"; \ From 290766fb770aa9d3ebd3ada989ae3b24d21a093a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 00:31:29 +0200 Subject: [PATCH 331/406] ZFS zlib support * grub-core/fs/zfs/zfs.c (zlib_decompress): New function. (decomp_table): Add zlib entries. (zio_read): USe 8 bits for compression function rather than 3. * include/grub/zfs/zio.h (zio_compress): Add zlib values. --- ChangeLog | 19 +++++++++++++++++++ grub-core/fs/zfs/zfs.c | 22 ++++++++++++++++++++-- include/grub/zfs/zio.h | 10 +++++++++- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6535b6e17..954166148 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2011-06-24 Vladimir Serbinenko + + ZFS zlib support + + * grub-core/fs/zfs/zfs.c (zlib_decompress): New function. + (decomp_table): Add zlib entries. + (zio_read): USe 8 bits for compression function rather than 3. + * include/grub/zfs/zio.h (zio_compress): Add zlib values. + +2011-06-24 Vladimir Serbinenko + + * grub-core/disk/ahci.c: Add missing license statements. + * grub-core/fs/romfs.c: Likewise. + * grub-core/lib/ia64/setjmp.S: Likewise. + * grub-core/loader/i386/pc/freedos.c: Likewise. + * grub-core/loader/ia64/efi/linux.c: Likewise. + * grub-core/video/colors.c: Likewise. + * include/grub/dl.h (GRUB_MOD_DEP): New macro. + 2011-06-23 Vladimir Serbinenko AHCI support. diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 8d86cf9e5..1eea13b26 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -51,6 +51,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -163,13 +164,30 @@ struct grub_zfs_data grub_disk_addr_t vdev_phys_sector; }; +static grub_err_t +zlib_decompress (void *s, void *d, + grub_size_t slen, grub_size_t dlen) +{ + if (grub_zlib_decompress (s, slen, 0, d, dlen) < 0) + return grub_errno; + return GRUB_ERR_NONE; +} + static decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = { {"inherit", NULL}, /* ZIO_COMPRESS_INHERIT */ {"on", lzjb_decompress}, /* ZIO_COMPRESS_ON */ {"off", NULL}, /* ZIO_COMPRESS_OFF */ {"lzjb", lzjb_decompress}, /* ZIO_COMPRESS_LZJB */ {"empty", NULL}, /* ZIO_COMPRESS_EMPTY */ - {"gzip", NULL}, /* ZIO_COMPRESS_GZIP */ + {"gzip-1", zlib_decompress}, /* ZIO_COMPRESS_GZIP1 */ + {"gzip-2", zlib_decompress}, /* ZIO_COMPRESS_GZIP2 */ + {"gzip-3", zlib_decompress}, /* ZIO_COMPRESS_GZIP3 */ + {"gzip-4", zlib_decompress}, /* ZIO_COMPRESS_GZIP4 */ + {"gzip-5", zlib_decompress}, /* ZIO_COMPRESS_GZIP5 */ + {"gzip-6", zlib_decompress}, /* ZIO_COMPRESS_GZIP6 */ + {"gzip-7", zlib_decompress}, /* ZIO_COMPRESS_GZIP7 */ + {"gzip-8", zlib_decompress}, /* ZIO_COMPRESS_GZIP8 */ + {"gzip-9", zlib_decompress}, /* ZIO_COMPRESS_GZIP9 */ }; static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, @@ -527,7 +545,7 @@ zio_read (blkptr_t * bp, grub_zfs_endian_t endian, void **buf, *buf = NULL; checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff; - comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0x7; + comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0xff; lsize = (BP_IS_HOLE(bp) ? 0 : (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1) << SPA_MINBLOCKSHIFT)); diff --git a/include/grub/zfs/zio.h b/include/grub/zfs/zio.h index 797d4f9b3..3dafb4028 100644 --- a/include/grub/zfs/zio.h +++ b/include/grub/zfs/zio.h @@ -77,7 +77,15 @@ enum zio_compress { ZIO_COMPRESS_OFF, ZIO_COMPRESS_LZJB, ZIO_COMPRESS_EMPTY, - ZIO_COMPRESS_GZIP, + ZIO_COMPRESS_GZIP1, + ZIO_COMPRESS_GZIP2, + ZIO_COMPRESS_GZIP3, + ZIO_COMPRESS_GZIP4, + ZIO_COMPRESS_GZIP5, + ZIO_COMPRESS_GZIP6, + ZIO_COMPRESS_GZIP7, + ZIO_COMPRESS_GZIP8, + ZIO_COMPRESS_GZIP9, ZIO_COMPRESS_FUNCTIONS }; From bc09e1a23804bd4132a51bca01851135d7307bff Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 04:32:54 +0200 Subject: [PATCH 332/406] * grub-core/kern/emu/getroot.c (grub_guess_root_device): Revert to old method if mountinfo would return /dev/root and /dev/root doesn't exist. --- ChangeLog | 6 ++++++ grub-core/kern/emu/getroot.c | 10 ++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 954166148..1b63af871 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-24 Vladimir Serbinenko + + * grub-core/kern/emu/getroot.c (grub_guess_root_device): Revert to + old method if mountinfo would return /dev/root and /dev/root doesn't + exist. + 2011-06-24 Vladimir Serbinenko ZFS zlib support diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index db27abf74..6d6c8ef8b 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -620,11 +620,13 @@ grub_guess_root_device (const char *dir) int root = (strcmp (os_dev, "/dev/root") == 0); if (!dm && !root) return os_dev; - if (stat (os_dev, &st) < 0) - grub_util_error ("cannot stat `%s'", os_dev); + if (stat (os_dev, &st) >= 0) + { + free (os_dev); + dev = st.st_rdev; + return grub_find_device (dm ? "/dev/mapper" : "/dev", dev); + } free (os_dev); - dev = st.st_rdev; - return grub_find_device (dm ? "/dev/mapper" : "/dev", dev); } if (stat (dir, &st) < 0) From 535c191059459b9212991f59aea494db1c1da767 Mon Sep 17 00:00:00 2001 From: Alexander Kurtz Date: Fri, 24 Jun 2011 12:38:24 +0200 Subject: [PATCH 333/406] * util/grub-mkconfig_lib.in: Add missing quotes. --- ChangeLog | 4 ++++ util/grub-mkconfig_lib.in | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1b63af871..d5c97b6e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-06-24 Alexander Kurtz + + * util/grub-mkconfig_lib.in: Add missing quotes. + 2011-06-24 Vladimir Serbinenko * grub-core/kern/emu/getroot.c (grub_guess_root_device): Revert to diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 2c5fd8c6f..759bcba1b 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -63,7 +63,7 @@ is_path_readable_by_grub () # ... or if we can't figure out the abstraction module, for example if # memberlist fails on an LVM volume group. - if ${grub_probe} -t abstraction $path > /dev/null 2>&1 ; then : ; else + if "${grub_probe}" -t abstraction "$path" > /dev/null 2>&1 ; then : ; else return 1 fi From 2a5e94d84abd9efad39e7eafe68fb766cea87314 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 12:41:05 +0200 Subject: [PATCH 334/406] * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Load partmap before abstraction. --- ChangeLog | 5 +++++ util/grub-mkconfig_lib.in | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index d5c97b6e0..1e7a468ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-24 Vladimir Serbinenko + + * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Load + partmap before abstraction. + 2011-06-24 Alexander Kurtz * util/grub-mkconfig_lib.in: Add missing quotes. diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 759bcba1b..090fcf314 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -105,12 +105,6 @@ prepare_grub_to_access_device () { device="$1" - # Abstraction modules aren't auto-loaded. - abstraction="`"${grub_probe}" --device "${device}" --target=abstraction`" - for module in ${abstraction} ; do - echo "insmod ${module}" - done - partmap="`"${grub_probe}" --device "${device}" --target=partmap`" for module in ${partmap} ; do case "${module}" in @@ -121,6 +115,12 @@ prepare_grub_to_access_device () esac done + # Abstraction modules aren't auto-loaded. + abstraction="`"${grub_probe}" --device "${device}" --target=abstraction`" + for module in ${abstraction} ; do + echo "insmod ${module}" + done + fs="`"${grub_probe}" --device "${device}" --target=fs`" for module in ${fs} ; do echo "insmod ${module}" From 98e2f50661b63494a7d94d3ad04d31669468f9b4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 13:02:49 +0200 Subject: [PATCH 335/406] * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Skip . and .. --- ChangeLog | 4 ++++ grub-core/fs/iso9660.c | 11 ++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1e7a468ec..d21fa1026 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-06-24 Vladimir Serbinenko + + * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Skip . and .. + 2011-06-24 Vladimir Serbinenko * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Load diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 508cc5b71..5b53ca597 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -598,7 +598,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, return 0; } - while (offset < dir->size) + for (; offset < dir->size; offset += dirent.len) { if (grub_disk_read (dir->data->disk, (dir->blk << GRUB_ISO9660_LOG2_BLKSZ) @@ -676,10 +676,9 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, if (filename) *filename = '\0'; - if (dirent.namelen == 1 && name[0] == 0) - filename = "."; - else if (dirent.namelen == 1 && name[0] == 1) - filename = ".."; + /* . and .. */ + if (dirent.namelen == 1 && (name[0] == 0 || name[0] == 1)) + continue; else filename = name; } @@ -712,8 +711,6 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, if (filename_alloc) grub_free (filename); } - - offset += dirent.len; } return 0; From 4388ca7224904dd35cafb7aa4a48fe60af1cdd4d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 13:43:10 +0200 Subject: [PATCH 336/406] * grub-core/commands/wildcard.c (match_files): Add a useful dprintf. (wildcard_expand): Don't stop on nonregexp parts after regexp ones since it truncates the output. Reported by: Ximin Luo. --- ChangeLog | 7 +++++++ grub-core/commands/wildcard.c | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index d21fa1026..eaee6266a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-06-24 Vladimir Serbinenko + + * grub-core/commands/wildcard.c (match_files): Add a useful dprintf. + (wildcard_expand): Don't stop on nonregexp parts after regexp ones since + it truncates the output. + Reported by: Ximin Luo. + 2011-06-24 Vladimir Serbinenko * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Skip . and .. diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c index 32561abe6..45d819a3e 100644 --- a/grub-core/commands/wildcard.c +++ b/grub-core/commands/wildcard.c @@ -288,6 +288,8 @@ match_files (const char *prefix, const char *suffix, const char *end, if (regexec (regexp, name, 0, 0, 0)) return 0; + grub_dprintf ("expand", "matched\n"); + buffer = grub_xasprintf ("%s%s", dir, name); if (! buffer) return 1; @@ -423,8 +425,6 @@ wildcard_expand (const char *s, char ***strs) while (*start) { split_path (start, &noregexop, ®exop); - if (noregexop >= regexop) /* no more wildcards */ - break; if (make_regex (noregexop, regexop, ®exp)) goto fail; From 031f22a01f81f3b65bdc8bc8fde473a5f847752e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 18:26:20 +0200 Subject: [PATCH 337/406] * grub-core/disk/raid.c (insert_array): Ensure uniqueness of readable names. --- ChangeLog | 5 +++++ grub-core/disk/raid.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/ChangeLog b/ChangeLog index eaee6266a..d70c7c6c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-24 Vladimir Serbinenko + + * grub-core/disk/raid.c (insert_array): Ensure uniqueness of readable + names. + 2011-06-24 Vladimir Serbinenko * grub-core/commands/wildcard.c (match_files): Add a useful dprintf. diff --git a/grub-core/disk/raid.c b/grub-core/disk/raid.c index c6be3efde..7c7dbc3dc 100644 --- a/grub-core/disk/raid.c +++ b/grub-core/disk/raid.c @@ -679,6 +679,49 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, scanner_name); #endif + { + int max_used_number = 0, len, need_new_name = 0; + int add_us = 0; + len = grub_strlen (array->name); + if (len && grub_isdigit (array->name[len-1])) + add_us = 1; + for (p = array_list; p != NULL; p = p->next) + { + int cur_num; + char *num, *end; + if (grub_strncmp (p->name, array->name, len) != 0) + continue; + if (p->name[len] == 0) + { + need_new_name = 1; + continue; + } + if (add_us && p->name[len] != '_') + continue; + if (add_us) + num = p->name + len + 1; + else + num = p->name + len; + if (!grub_isdigit (num[0])) + continue; + cur_num = grub_strtoull (num, &end, 10); + if (end[0]) + continue; + if (cur_num > max_used_number) + max_used_number = cur_num; + } + if (need_new_name) + { + char *tmp; + tmp = grub_xasprintf ("%s%s%d", array->name, add_us ? "_" : "", + max_used_number + 1); + if (!tmp) + return grub_errno; + grub_free (array->name); + array->name = tmp; + } + } + /* Add our new array to the list. */ array->next = array_list; array_list = array; From 8b51fd98b90531c9a3407ee0d00c935171f58e92 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 20:35:25 +0200 Subject: [PATCH 338/406] bootp support --- grub-core/net/arp.c | 8 + grub-core/net/drivers/emu/emunet.c | 6 +- grub-core/net/ethernet.c | 11 +- grub-core/net/ip.c | 69 +++++--- grub-core/net/net.c | 268 ++++++++++++++++++++++++++--- grub-core/net/tftp.c | 12 +- grub-core/net/udp.c | 10 +- include/grub/emu/export.h | 6 + include/grub/net.h | 38 ++-- include/grub/net/ethernet.h | 16 +- include/grub/net/netbuff.h | 2 +- include/grub/net/udp.h | 5 +- 12 files changed, 360 insertions(+), 91 deletions(-) create mode 100644 include/grub/emu/export.h diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index 0644d3d2e..1dbd8a58f 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -41,6 +41,14 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf, char *aux, arp_data[128]; int i; + if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && proto_addr->ipv4 == 0xffffffff) + { + hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memset (hw_addr->mac, -1, 6); + return GRUB_ERR_NONE; + } + /* Check cache table. */ entry = arp_find_entry (proto_addr); if (entry) diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c index ee4ba4773..d1e49a2f4 100644 --- a/grub-core/net/drivers/emu/emunet.c +++ b/grub-core/net/drivers/emu/emunet.c @@ -13,8 +13,8 @@ static int fd; -static grub_err_t -send_card_buffer (struct grub_net_card *dev __attribute__ ((unused)), +static grub_err_t +send_card_buffer (const struct grub_net_card *dev __attribute__ ((unused)), struct grub_net_buff *pack) { ssize_t actual; @@ -27,7 +27,7 @@ send_card_buffer (struct grub_net_card *dev __attribute__ ((unused)), } static grub_ssize_t -get_card_packet (struct grub_net_card *dev __attribute__ ((unused)), +get_card_packet (const struct grub_net_card *dev __attribute__ ((unused)), struct grub_net_buff *pack) { ssize_t actual; diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index d29193afe..f1bc8c1d0 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -27,12 +27,14 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, } grub_err_t -grub_net_recv_ethernet_packet (struct grub_net_buff *nb) +grub_net_recv_ethernet_packet (struct grub_net_buff * nb, + const struct grub_net_card * card) { struct etherhdr *eth; struct llchdr *llch; struct snaphdr *snaph; grub_uint16_t type; + grub_net_link_level_address_t hwaddress; eth = (struct etherhdr *) nb->data; type = grub_be_to_cpu16 (eth->type); @@ -51,7 +53,10 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb) } } - /* ARP packet. */ + hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (hwaddress.mac, eth->dst, sizeof (hwaddress.mac)); + + /* ARP packet. */ if (type == GRUB_NET_ETHERTYPE_ARP) { grub_net_arp_receive (nb); @@ -59,7 +64,7 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb) } /* IP packet. */ if (type == GRUB_NET_ETHERTYPE_IP) - grub_net_recv_ip_packets (nb); + grub_net_recv_ip_packets (nb, card, &hwaddress); return GRUB_ERR_NONE; } diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 4adc2b028..808532a4a 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -25,9 +25,9 @@ ipchksum (void *ipv, int len) } grub_err_t -grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, - const grub_net_network_level_address_t *target, - struct grub_net_buff *nb) +grub_net_send_ip_packet (struct grub_net_network_level_interface * inf, + const grub_net_network_level_address_t * target, + struct grub_net_buff * nb) { struct iphdr *iph; static int id = 0x2400; @@ -54,43 +54,58 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, err = grub_net_arp_resolve (inf, target, &ll_target_addr); if (err) return err; - return send_ethernet_packet (inf, nb, ll_target_addr, GRUB_NET_ETHERTYPE_IP); + return send_ethernet_packet (inf, nb, ll_target_addr, + GRUB_NET_ETHERTYPE_IP); } -/* -static int -ip_filter (struct grub_net_buff *nb) +grub_err_t +grub_net_recv_ip_packets (struct grub_net_buff * nb, + const struct grub_net_card * card, + const grub_net_link_level_address_t * hwaddress) { struct iphdr *iph = (struct iphdr *) nb->data; grub_err_t err; + struct grub_net_network_level_interface *inf; - if (nb->end - nb->data < (signed) sizeof (*iph)) - return 0; - - if (iph->protocol != 0x11 || - iph->dest != inf->address.ipv4) - return 0; - - grub_netbuff_pull (nb, sizeof (iph)); - err = grub_net_put_packet (&inf->nl_pending, nb); + err = grub_netbuff_pull (nb, sizeof (*iph)); if (err) + return err; + + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + if (inf->card == card + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && inf->address.ipv4 == iph->dest + && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) + break; + } + if (!inf) { - grub_print_error (); - return 0; + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + if (inf->card == card + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC + && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) + break; + } + if (!inf) + { + if (iph->protocol == IP_UDP + && grub_net_hwaddr_cmp (&card->default_address, hwaddress) == 0) + { + struct udphdr *udph; + udph = (struct udphdr *) nb->data; + grub_netbuff_pull (nb, sizeof (*udph)); + if (grub_be_to_cpu16 (udph->dst) == 68) + grub_net_process_dhcp (nb, card); + } + grub_netbuff_free (nb); + return GRUB_ERR_NONE; } - return 1; -} -*/ -grub_err_t -grub_net_recv_ip_packets (struct grub_net_buff *nb) -{ - struct iphdr *iph = (struct iphdr *) nb->data; - grub_netbuff_pull (nb, sizeof (*iph)); switch (iph->protocol) { case IP_UDP: - return grub_net_recv_udp_packet (nb); + return grub_net_recv_udp_packet (nb, inf); break; default: grub_netbuff_free (nb); diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 1232b3c74..2da60256c 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -16,6 +16,7 @@ * along with GRUB. If not, see . */ +#include #include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -54,8 +56,11 @@ static struct grub_fs grub_net_fs; static inline void grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) { - grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), - GRUB_AS_LIST (inter)); + *inter->prev = inter->next; + if (inter->next) + inter->next->prev = inter->prev; + inter->next = 0; + inter->prev = 0; } static inline void @@ -112,6 +117,8 @@ match_net (const grub_net_network_level_netaddress_t *net, return 0; switch (net->type) { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC: + return 0; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { grub_int32_t mask = ((1 << net->ipv4.masksize) - 1) << (32 - net->ipv4.masksize); @@ -229,6 +236,9 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf) { switch (target->type) { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC: + grub_strcpy (buf, "promisc"); + return; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { grub_uint32_t n = grub_be_to_cpu32 (target->ipv4); @@ -270,6 +280,23 @@ hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str) grub_printf ("Unsupported hw address type %d\n", addr->type); } +int +grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, + const grub_net_link_level_address_t *b) +{ + if (a->type < b->type) + return -1; + if (a->type > b->type) + return +1; + switch (a->type) + { + case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET: + return grub_memcmp (a->mac, b->mac, sizeof (a->mac)); + } + grub_printf ("Unsupported hw address type %d\n", a->type); + return 1; +} + /* FIXME: implement this. */ static char * hwaddr_set_env (struct grub_env_var *var __attribute__ ((unused)), @@ -307,12 +334,16 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa grub_register_variable_hook (name, 0, addr_set_env); } - grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), - GRUB_AS_LIST (inter)); + inter->prev = &grub_net_network_level_interfaces; + inter->next = grub_net_network_level_interfaces; + if (inter->next) + inter->next->prev = &inter->next; + grub_net_network_level_interfaces = inter; } struct grub_net_network_level_interface * -grub_net_add_addr (const char *name, struct grub_net_card *card, +grub_net_add_addr (const char *name, + const struct grub_net_card *card, grub_net_network_level_address_t addr, grub_net_link_level_address_t hwaddress, grub_net_interface_flags_t flags) @@ -488,6 +519,9 @@ print_net_address (const grub_net_network_level_netaddress_t *target) { switch (target->type) { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC: + grub_printf ("promisc\n"); + break; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { grub_uint32_t n = grub_be_to_cpu32 (target->ipv4.base); @@ -546,6 +580,23 @@ grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } +static grub_err_t +grub_cmd_listaddrs (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + struct grub_net_network_level_interface *inf; + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + char bufh[MAX_STR_HWADDR_LEN]; + char bufn[GRUB_NET_MAX_STR_ADDR_LEN]; + hwaddr_to_str (&inf->hwaddress, bufh); + grub_net_addr_to_str (&inf->address, bufn); + grub_printf ("%s %s %s\n", inf->name, bufh, bufn); + } + return GRUB_ERR_NONE; +} + grub_net_app_level_t grub_net_app_level_list; struct grub_net_socket *grub_net_sockets; @@ -649,22 +700,27 @@ grub_net_fs_close (grub_file_t file) static void receive_packets (struct grub_net_card *card) { - /* Maybe should be better have a fixed number of packets for each card - and just mark them as used and not used. */ - struct grub_net_buff *nb; - grub_ssize_t actual; - nb = grub_netbuff_alloc (1500); - if (!nb) + while (1) { - grub_print_error (); - return; - } + /* Maybe should be better have a fixed number of packets for each card + and just mark them as used and not used. */ + struct grub_net_buff *nb; + grub_ssize_t actual; + nb = grub_netbuff_alloc (1500); + if (!nb) + { + grub_print_error (); + return; + } - actual = card->driver->recv (card, nb); - if (actual < 0) - grub_netbuff_free (nb); - else - grub_net_recv_ethernet_packet (nb); + actual = card->driver->recv (card, nb); + if (actual < 0) + { + grub_netbuff_free (nb); + break; + } + grub_net_recv_ethernet_packet (nb, card); + } grub_print_error (); } @@ -828,9 +884,10 @@ parse_dhcp_vendor (const char *name, void *vend, int limit) #define OFFSET_OF(x, y) ((grub_uint8_t *)((y)->x) - (grub_uint8_t *)(y)) struct grub_net_network_level_interface * -grub_net_configure_by_dhcp_ack (const char *name, struct grub_net_card *card, +grub_net_configure_by_dhcp_ack (const char *name, + const struct grub_net_card *card, grub_net_interface_flags_t flags, - struct grub_net_bootp_ack *bp, + const struct grub_net_bootp_packet *bp, grub_size_t size) { grub_net_network_level_address_t addr; @@ -889,6 +946,38 @@ grub_net_configure_by_dhcp_ack (const char *name, struct grub_net_card *card, return inter; } +void +grub_net_process_dhcp (struct grub_net_buff *nb, + const struct grub_net_card *card) +{ + char *name; + struct grub_net_network_level_interface *inf; + + name = grub_xasprintf ("%s:dhcp", card->name); + if (!name) + { + grub_print_error (); + return; + } + grub_net_configure_by_dhcp_ack (name, card, + 0, (const struct grub_net_bootp_packet *) nb->data, + (nb->tail - nb->data)); + grub_free (name); + if (grub_errno) + grub_print_error (); + else + { + FOR_NET_NETWORK_LEVEL_INTERFACES(inf) + if (grub_memcmp (inf->name, card->name, grub_strlen (card->name)) == 0 + && grub_memcmp (inf->name + grub_strlen (card->name), + ":dhcp_tmp", sizeof (":dhcp_tmp") - 1) == 0) + { + grub_net_network_level_interface_unregister (inf); + break; + } + } +} + static char hexdigit (grub_uint8_t val) { @@ -1011,6 +1100,131 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), "unrecognised format specification %s", args[3]); } +static grub_err_t +grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_card *card; + struct grub_net_network_level_interface *ifaces; + grub_size_t ncards = 0; + unsigned j = 0; + int interval; + grub_err_t err; + + FOR_NET_CARDS (card) + { + if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) + continue; + ncards++; + } + + ifaces = grub_zalloc (ncards * sizeof (ifaces[0])); + if (!ifaces) + return grub_errno; + + j = 0; + FOR_NET_CARDS (card) + { + if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) + continue; + ifaces[j].card = card; + ifaces[j].next = &ifaces[j+1]; + if (j) + ifaces[j].prev = &ifaces[j-1].next; + ifaces[j].name = grub_xasprintf ("%s:dhcp_tmp", card->name); + if (!ifaces[j].name) + { + unsigned i; + for (i = 0; i < j; i++) + grub_free (ifaces[i].name); + grub_free (ifaces); + return grub_errno; + } + ifaces[j].address.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC; + grub_memcpy (&ifaces[j].hwaddress, &card->default_address, + sizeof (ifaces[j].hwaddress)); + j++; + } + ifaces[ncards - 1].next = grub_net_network_level_interfaces; + if (grub_net_network_level_interfaces) + grub_net_network_level_interfaces->prev = & ifaces[ncards - 1].next; + grub_net_network_level_interfaces = &ifaces[0]; + ifaces[0].prev = &grub_net_network_level_interfaces; + for (interval = 200; interval < 10000; interval *= 2) + { + int done = 0; + for (j = 0; j < ncards; j++) + { + struct grub_net_bootp_packet *pack; + struct grub_datetime date; + grub_int32_t t; + struct grub_net_buff *nb; + struct udphdr *udph; + grub_net_network_level_address_t target; + + if (!ifaces[j].prev) + continue; + nb = grub_netbuff_alloc (sizeof (*pack)); + if (!nb) + return grub_errno; + err = grub_netbuff_reserve (nb, sizeof (*pack) + 64 + 128); + if (err) + return err; + err = grub_netbuff_push (nb, sizeof (*pack) + 64); + if (err) + return err; + pack = (void *) nb->data; + done = 1; + grub_memset (pack, 0, sizeof (*pack) + 64); + pack->opcode = 1; + pack->hw_type = 1; + pack->hw_len = 6; + err = grub_get_datetime (&date); + if (err || !grub_datetime2unixtime (&date, &t)) + { + grub_errno = GRUB_ERR_NONE; + t = 0; + } + pack->ident = grub_cpu_to_be32 (t); + pack->seconds = 0;//grub_cpu_to_be16 (t); + + grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6); + + grub_netbuff_push (nb, sizeof (*udph)); + + udph = (struct udphdr *) nb->data; + udph->src = grub_cpu_to_be16 (68); + udph->dst = grub_cpu_to_be16 (67); + udph->chksum = 0; + udph->len = grub_cpu_to_be16 (nb->tail - nb->data); + + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4 = 0xffffffff; + + err = grub_net_send_ip_packet (&ifaces[j], &target, nb); + if (err) + return err; + } + if (!done) + break; + grub_net_poll_cards (interval); + } + + err = GRUB_ERR_NONE; + for (j = 0; j < ncards; j++) + { + if (!ifaces[j].prev) + continue; + grub_error_push (); + grub_net_network_level_interface_unregister (&ifaces[j]); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't configure %s", + ifaces[j].card->name); + } + + return err; +} + + static struct grub_fs grub_net_fs = { .name = "netfs", @@ -1023,7 +1237,8 @@ static struct grub_fs grub_net_fs = .mtime = NULL, }; static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; -static grub_command_t cmd_lsroutes, cmd_lscards, cmd_getdhcp; +static grub_command_t cmd_lsroutes, cmd_lscards, cmd_getdhcp, cmd_bootp; +static grub_command_t cmd_dhcp, cmd_lsaddr; GRUB_MOD_INIT(net) { @@ -1043,6 +1258,14 @@ GRUB_MOD_INIT(net) "", N_("list network routes")); cmd_lscards = grub_register_command ("net_ls_cards", grub_cmd_listcards, "", N_("list network cards")); + cmd_lsaddr = grub_register_command ("net_ls_addr", grub_cmd_listaddrs, + "", N_("list network addresses")); + cmd_bootp = grub_register_command ("net_bootp", grub_cmd_bootp, + "[CARD]", + N_("perform a bootp autoconfiguration")); + cmd_dhcp = grub_register_command ("net_dhcp", grub_cmd_bootp, + "[CARD]", + N_("perform a bootp autoconfiguration")); cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt, N_("VAR INTERFACE NUMBER DESCRIPTION"), N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); @@ -1060,6 +1283,7 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_delroute); grub_unregister_command (cmd_lsroutes); grub_unregister_command (cmd_lscards); + grub_unregister_command (cmd_lsaddr); grub_unregister_command (cmd_getdhcp); grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index ac3b3e9db..545862092 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -24,7 +24,7 @@ tftp_open (struct grub_file *file, const char *filename) tftp_data_t data; grub_err_t err; - data = grub_malloc (sizeof *data); + data = grub_malloc (sizeof (*data)); if (!data) return grub_errno; @@ -86,7 +86,7 @@ tftp_open (struct grub_file *file, const char *filename) /* Retry. */ /*err = grub_net_send_udp_packet (file->device->net->socket, &nb); if (err) - return err; */ + return err; */ } if (file->device->net->socket->status == 0) @@ -154,8 +154,8 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) } grub_netbuff_clear (&nb_ack); grub_netbuff_reserve (&nb_ack, 128); - grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) - + sizeof (tftph->u.ack.block)); + grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) + + sizeof (tftph->u.ack.block)); tftph = (struct tftphdr *) nb_ack.data; tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); @@ -180,12 +180,12 @@ static struct grub_net_app_protocol grub_tftp_protocol = .close = tftp_close }; -GRUB_MOD_INIT(tftp) +GRUB_MOD_INIT (tftp) { grub_net_app_level_register (&grub_tftp_protocol); } -GRUB_MOD_FINI(tftp) +GRUB_MOD_FINI (tftp) { grub_net_app_level_unregister (&grub_tftp_protocol); } diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 86220bf0f..cc7534ea1 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -24,7 +24,8 @@ grub_net_send_udp_packet (const grub_net_socket_t socket, } grub_err_t -grub_net_recv_udp_packet (struct grub_net_buff *nb) +grub_net_recv_udp_packet (struct grub_net_buff * nb, + struct grub_net_network_level_interface * inf) { struct udphdr *udph; grub_net_socket_t sock; @@ -33,7 +34,8 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb) FOR_NET_SOCKETS (sock) { - if (grub_be_to_cpu16 (udph->dst) == sock->in_port) + if (grub_be_to_cpu16 (udph->dst) == sock->in_port + && inf == sock->inf && sock->app) { if (sock->status == 0) sock->out_port = grub_be_to_cpu16 (udph->src); @@ -41,7 +43,7 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb) /* App protocol remove its own reader. */ sock->app->read (sock, nb); - /* If there is data, puts packet in socket list. */ + /* If there is data, puts packet in socket list. */ if ((nb->tail - nb->data) > 0) grub_net_put_packet (&sock->packs, nb); else @@ -49,6 +51,8 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb) return GRUB_ERR_NONE; } } + if (grub_be_to_cpu16 (udph->dst) == 68) + grub_net_process_dhcp (nb, inf->card); grub_netbuff_free (nb); return GRUB_ERR_NONE; } diff --git a/include/grub/emu/export.h b/include/grub/emu/export.h new file mode 100644 index 000000000..1e2f0432b --- /dev/null +++ b/include/grub/emu/export.h @@ -0,0 +1,6 @@ +void EXPORT_FUNC (open64) (void); +void EXPORT_FUNC (close) (void); +void EXPORT_FUNC (read) (void); +void EXPORT_FUNC (write) (void); +void EXPORT_FUNC (ioctl) (void); + diff --git a/include/grub/net.h b/include/grub/net.h index f9745acec..5d99cace3 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -62,8 +62,10 @@ struct grub_net_card_driver char *name; grub_err_t (*init) (struct grub_net_card *dev); grub_err_t (*fini) (struct grub_net_card *dev); - grub_err_t (*send) (struct grub_net_card *dev, struct grub_net_buff *buf); - grub_ssize_t (*recv) (struct grub_net_card *dev, struct grub_net_buff *buf); + grub_err_t (*send) (const struct grub_net_card *dev, + struct grub_net_buff *buf); + grub_ssize_t (*recv) (const struct grub_net_card *dev, + struct grub_net_buff *buf); }; extern struct grub_net_card_driver *grub_net_card_drivers; @@ -116,6 +118,7 @@ struct grub_net_network_level_interface; typedef enum grub_network_level_protocol_id { + GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC, GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 } grub_network_level_protocol_id_t; @@ -243,12 +246,13 @@ extern grub_err_t (*EXPORT_VAR (grub_file_net_seek)) (struct grub_file *file, gr struct grub_net_network_level_interface { struct grub_net_network_level_interface *next; + struct grub_net_network_level_interface **prev; char *name; - struct grub_net_card *card; + const struct grub_net_card *card; grub_net_network_level_address_t address; grub_net_link_level_address_t hwaddress; grub_net_interface_flags_t flags; - struct grub_net_bootp_ack *dhcp_ack; + struct grub_net_bootp_packet *dhcp_ack; grub_size_t dhcp_acklen; void *data; }; @@ -291,7 +295,8 @@ grub_net_session_recv (struct grub_net_session *session, void *buf, } struct grub_net_network_level_interface * -grub_net_add_addr (const char *name, struct grub_net_card *card, +grub_net_add_addr (const char *name, + const struct grub_net_card *card, grub_net_network_level_address_t addr, grub_net_link_level_address_t hwaddress, grub_net_interface_flags_t flags); @@ -369,7 +374,7 @@ grub_net_add_route_gw (const char *name, typedef grub_uint8_t grub_net_bootp_mac_addr_t[GRUB_NET_BOOTP_MAC_ADDR_LEN]; -struct grub_net_bootp_ack +struct grub_net_bootp_packet { grub_uint8_t opcode; grub_uint8_t hw_type; /* hardware type. */ @@ -391,11 +396,21 @@ struct grub_net_bootp_ack #define GRUB_NET_BOOTP_RFC1048_MAGIC 0x63825363L struct grub_net_network_level_interface * -grub_net_configure_by_dhcp_ack (const char *name, struct grub_net_card *card, +grub_net_configure_by_dhcp_ack (const char *name, + const struct grub_net_card *card, grub_net_interface_flags_t flags, - struct grub_net_bootp_ack *bp, + const struct grub_net_bootp_packet *bp, grub_size_t size); +void +grub_net_process_dhcp (struct grub_net_buff *nb, + const struct grub_net_card *card); + +int +grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, + const grub_net_link_level_address_t *b); + + /* Currently suppoerted adresses: IPv4: XXX.XXX.XXX.XXX @@ -420,8 +435,11 @@ typedef int grub_err_t grub_net_recv_link_layer (struct grub_net_network_level_interface *inf, grub_net_packet_handler_t handler); -grub_err_t -grub_net_recv_ip_packets (struct grub_net_buff *nb); + +grub_err_t +grub_net_recv_ip_packets (struct grub_net_buff *nb, + const struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddress); grub_err_t grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h index 7ff7a4562..a841dc12c 100644 --- a/include/grub/net/ethernet.h +++ b/include/grub/net/ethernet.h @@ -12,19 +12,6 @@ struct etherhdr grub_uint16_t type; } __attribute__ ((packed)); -#define PCP(x) x & 0xe000 -#define CFI(x) x & 0x1000 -#define VID(x) x & 0x0fff -#define PRINT_ETH_ADDR(name,addr) grub_printf("%s %x:%x:%x:%x:%x:%x\n",\ - name,\ - addr[0],\ - addr[1],\ - addr[2],\ - addr[3],\ - addr[4],\ - addr[5]\ - ) - struct llchdr { grub_uint8_t dsap; @@ -52,6 +39,7 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, grub_net_link_level_address_t target_addr, grub_uint16_t ethertype); grub_err_t -grub_net_recv_ethernet_packet (struct grub_net_buff *nb); +grub_net_recv_ethernet_packet (struct grub_net_buff *nb, + const struct grub_net_card *card); #endif diff --git a/include/grub/net/netbuff.h b/include/grub/net/netbuff.h index 8ce508ead..245e813c3 100644 --- a/include/grub/net/netbuff.h +++ b/include/grub/net/netbuff.h @@ -26,5 +26,5 @@ grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff); struct grub_net_buff * grub_netbuff_alloc ( grub_size_t len ); grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff); -grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff); + #endif diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h index 86311ccf1..eacf3325c 100644 --- a/include/grub/net/udp.h +++ b/include/grub/net/udp.h @@ -14,8 +14,9 @@ struct udphdr grub_err_t grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff *nb); -grub_err_t -grub_net_recv_udp_packet (struct grub_net_buff *nb); +grub_err_t +grub_net_recv_udp_packet (struct grub_net_buff *nb, + struct grub_net_network_level_interface *inf); #define FOR_NET_UDP_PACKETS(inf, var) FOR_PACKETS(inf->udp_pending, var) From 40ea05dee4d26693cb03e3d3157626b64f671da4 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 24 Jun 2011 22:37:17 +0200 Subject: [PATCH 339/406] * grub-core/io/xzio.c: Fix code style issues --- ChangeLog | 4 ++++ grub-core/io/xzio.c | 16 +++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4f42719bc..286648a46 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-06-24 Szymon Janc + + * grub-core/io/xzio.c: Fix code style issues + 2011-06-24 Vladimir Serbinenko 2011-06-24 Manoel Rebelo Abranches diff --git a/grub-core/io/xzio.c b/grub-core/io/xzio.c index 1f42cd242..1575ca236 100644 --- a/grub-core/io/xzio.c +++ b/grub-core/io/xzio.c @@ -48,7 +48,7 @@ static struct grub_fs grub_xzio_fs; static grub_size_t decode_vli (const grub_uint8_t buf[], grub_size_t size_max, - grub_uint64_t * num) + grub_uint64_t *num) { if (size_max == 0) return 0; @@ -71,7 +71,7 @@ decode_vli (const grub_uint8_t buf[], grub_size_t size_max, } static grub_ssize_t -read_vli (grub_file_t file, grub_uint64_t * num) +read_vli (grub_file_t file, grub_uint64_t *num) { grub_uint8_t buf[VLI_MAX_DIGITS]; grub_ssize_t read; @@ -92,6 +92,8 @@ static int test_header (grub_file_t file) { grub_xzio_t xzio = file->data; + enum xz_ret ret; + xzio->buf.in_size = grub_file_read (xzio->file, xzio->inbuf, STREAM_HEADER_SIZE); @@ -101,7 +103,7 @@ test_header (grub_file_t file) return 0; } - enum xz_ret ret = xz_dec_run (xzio->dec, &xzio->buf); + ret = xz_dec_run (xzio->dec, &xzio->buf); if (ret == XZ_FORMAT_ERROR) { @@ -132,8 +134,8 @@ test_footer (grub_file_t file) grub_uint64_t records; grub_file_seek (xzio->file, xzio->file->size - FOOTER_MAGIC_SIZE); - if (grub_file_read (xzio->file, footer, FOOTER_MAGIC_SIZE) != - FOOTER_MAGIC_SIZE + if (grub_file_read (xzio->file, footer, FOOTER_MAGIC_SIZE) + != FOOTER_MAGIC_SIZE || grub_memcmp (footer, FOOTER_MAGIC, FOOTER_MAGIC_SIZE) != 0) goto ERROR; @@ -150,8 +152,8 @@ test_footer (grub_file_t file) xzio->file->size - XZ_STREAM_FOOTER_SIZE - backsize); /* Test index marker. */ - if (grub_file_read (xzio->file, &imarker, sizeof (imarker)) != - sizeof (imarker) && imarker != 0x00) + if (grub_file_read (xzio->file, &imarker, sizeof (imarker)) + != sizeof (imarker) && imarker != 0x00) goto ERROR; if (read_vli (xzio->file, &records) <= 0) From 77c0840ba67302031363479dfbf8bf44ef1ab6d0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Jun 2011 00:18:36 +0200 Subject: [PATCH 340/406] * grub-core/net/i386/pc/pxe.c (grub_pxe_recv): Fix declaration. (grub_pxe_send): Likewise. (GRUB_MOD_INIT): Fix types. --- ChangeLog | 6 ++++++ grub-core/net/i386/pc/pxe.c | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 286648a46..4cac3cd65 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-25 Vladimir Serbinenko + + * grub-core/net/i386/pc/pxe.c (grub_pxe_recv): Fix declaration. + (grub_pxe_send): Likewise. + (GRUB_MOD_INIT): Fix types. + 2011-06-24 Szymon Janc * grub-core/io/xzio.c: Fix code style issues diff --git a/grub-core/net/i386/pc/pxe.c b/grub-core/net/i386/pc/pxe.c index 27c4af17f..a23104bad 100644 --- a/grub-core/net/i386/pc/pxe.c +++ b/grub-core/net/i386/pc/pxe.c @@ -305,14 +305,14 @@ static struct grub_fs grub_pxefs_fs = }; static grub_ssize_t -grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused)), +grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), struct grub_net_buff *buf __attribute__ ((unused))) { return 0; } static grub_err_t -grub_pxe_send (struct grub_net_card *dev __attribute__ ((unused)), +grub_pxe_send (const struct grub_net_card *dev __attribute__ ((unused)), struct grub_net_buff *buf __attribute__ ((unused))) { return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "not implemented"); @@ -424,7 +424,7 @@ GRUB_MOD_INIT(pxe) { struct grub_pxe_bangpxe *pxenv; struct grub_pxenv_get_cached_info ci; - struct grub_net_bootp_ack *bp; + struct grub_net_bootp_packet *bp; char *buf; pxenv = grub_pxe_scan (); From 6295b32f79acb93df2208321eec491aa6b214fa0 Mon Sep 17 00:00:00 2001 From: Patrick Date: Sat, 25 Jun 2011 01:09:32 +0200 Subject: [PATCH 341/406] * grub-core/kern/main.c (grub_load_normal_mode): Correct the comment. --- ChangeLog | 4 ++++ grub-core/kern/main.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 4cac3cd65..c639cb9de 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-06-25 Patrick + + * grub-core/kern/main.c (grub_load_normal_mode): Correct the comment. + 2011-06-25 Vladimir Serbinenko * grub-core/net/i386/pc/pxe.c (grub_pxe_recv): Fix declaration. diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index cc9758988..447f0ae33 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -159,7 +159,7 @@ grub_load_normal_mode (void) /* Load the module. */ grub_dl_load ("normal"); - /* Something went wrong. Print errors here to let user know why we're entering rescue mode. */ + /* Print errors if any. */ grub_print_error (); grub_errno = 0; From cc4bfec8fac9a6fdea9ce38f5c7a92bc5579f22e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 04:18:45 +0200 Subject: [PATCH 342/406] Fix a memory leak --- grub-core/net/ethernet.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index 863e659a8..175d0b65f 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -69,10 +69,14 @@ grub_net_recv_ethernet_packet (struct grub_net_buff * nb, { grub_net_arp_receive (nb); grub_netbuff_free (nb); + return GRUB_ERR_NONE; } /* IP packet. */ if (type == GRUB_NET_ETHERTYPE_IP) - grub_net_recv_ip_packets (nb, card, &hwaddress); - + { + grub_net_recv_ip_packets (nb, card, &hwaddress); + return GRUB_ERR_NONE; + } + grub_netbuff_free (nb); return GRUB_ERR_NONE; } From 8e60fc8f85b27fb513ef0b83efa07c531ec8e9a7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 04:19:12 +0200 Subject: [PATCH 343/406] Send network packets on PXE --- grub-core/Makefile.core.def | 2 +- grub-core/net/drivers/i386/pc/pxe.c | 304 ++++++++++++++++++ grub-core/net/i386/pc/pxe.c | 482 ---------------------------- 3 files changed, 305 insertions(+), 483 deletions(-) create mode 100644 grub-core/net/drivers/i386/pc/pxe.c delete mode 100644 grub-core/net/i386/pc/pxe.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 927718359..5c3ce99be 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1100,7 +1100,7 @@ module = { module = { name = pxe; - i386_pc = net/i386/pc/pxe.c; + i386_pc = net/drivers/i386/pc/pxe.c; enable = i386_pc; }; diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c new file mode 100644 index 000000000..7d6e3adca --- /dev/null +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -0,0 +1,304 @@ +/* pxe.c - Driver to provide access to the pxe filesystem */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009,2011 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 + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define SEGMENT(x) ((x) >> 4) +#define OFFSET(x) ((x) & 0xF) +#define SEGOFS(x) ((SEGMENT(x) << 16) + OFFSET(x)) +#define LINEAR(x) (void *) ((((x) >> 16) << 4) + ((x) & 0xFFFF)) + +struct grub_pxe_undi_open +{ + grub_uint16_t status; + grub_uint16_t open_flag; + grub_uint16_t pkt_filter; + grub_uint16_t mcast_count; + grub_uint8_t mcast[8][6]; +} __attribute__ ((packed)); + +struct grub_pxe_undi_isr +{ + grub_uint16_t status; + grub_uint16_t func_flag; + grub_uint16_t buffer_len; + grub_uint16_t frame_len; + grub_uint16_t frame_hdr_len; + grub_uint32_t buffer; + grub_uint8_t prot_type; + grub_uint8_t pkt_type; +} __attribute__ ((packed)); + +enum + { + GRUB_PXE_ISR_IN_START = 1, + GRUB_PXE_ISR_IN_PROCESS, + GRUB_PXE_ISR_IN_GET_NEXT + }; + +enum + { + GRUB_PXE_ISR_OUT_OURS = 0, + GRUB_PXE_ISR_OUT_NOT_OURS = 1 + }; + +enum + { + GRUB_PXE_ISR_OUT_DONE = 0, + GRUB_PXE_ISR_OUT_TRANSMIT = 2, + GRUB_PXE_ISR_OUT_RECEIVE = 3, + GRUB_PXE_ISR_OUT_BUSY = 4, + }; + +struct grub_pxe_undi_transmit +{ + grub_uint16_t status; + grub_uint8_t protocol; + grub_uint8_t xmitflag; + grub_uint32_t dest; + grub_uint32_t tbd; + grub_uint32_t reserved[2]; +} __attribute__ ((packed)); + +struct grub_pxe_undi_tbd +{ + grub_uint16_t len; + grub_uint32_t buf; + grub_uint16_t blk_count; + struct + { + grub_uint8_t ptr_type; + grub_uint8_t reserved; + grub_uint16_t len; + grub_uint32_t ptr; + } blocks[8]; +} __attribute__ ((packed)); + +struct grub_pxe_bangpxe *grub_pxe_pxenv; +static grub_uint32_t pxe_rm_entry = 0; + +static struct grub_pxe_bangpxe * +grub_pxe_scan (void) +{ + struct grub_bios_int_registers regs; + struct grub_pxenv *pxenv; + struct grub_pxe_bangpxe *bangpxe; + + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + + regs.ebx = 0; + regs.ecx = 0; + regs.eax = 0x5650; + regs.es = 0; + + grub_bios_interrupt (0x1a, ®s); + + if ((regs.eax & 0xffff) != 0x564e) + return NULL; + + pxenv = (struct grub_pxenv *) ((regs.es << 4) + (regs.ebx & 0xffff)); + if (grub_memcmp (pxenv->signature, GRUB_PXE_SIGNATURE, + sizeof (pxenv->signature)) + != 0) + return NULL; + + if (pxenv->version < 0x201) + return NULL; + + bangpxe = (void *) ((((pxenv->pxe_ptr & 0xffff0000) >> 16) << 4) + + (pxenv->pxe_ptr & 0xffff)); + + if (!bangpxe) + return NULL; + + if (grub_memcmp (bangpxe->signature, GRUB_PXE_BANGPXE_SIGNATURE, + sizeof (bangpxe->signature)) != 0) + return NULL; + + pxe_rm_entry = bangpxe->rm_entry; + + return bangpxe; +} + +static grub_ssize_t +grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), + struct grub_net_buff *buf) +{ + struct grub_pxe_undi_isr *isr; + static int in_progress = 0; + char *ptr, *end; + int len; + + isr = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + + if (!in_progress) + { + grub_memset (isr, 0, sizeof (*isr)); + isr->func_flag = GRUB_PXE_ISR_IN_START; + grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); + if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_OURS) + return -1; + grub_memset (isr, 0, sizeof (*isr)); + isr->func_flag = GRUB_PXE_ISR_IN_PROCESS; + grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); + } + else + { + grub_memset (isr, 0, sizeof (*isr)); + isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT; + grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); + } + + while (isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE) + { + if (isr->status || isr->func_flag == GRUB_PXE_ISR_OUT_DONE) + return -1; + grub_memset (isr, 0, sizeof (*isr)); + isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT; + grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); + } + + grub_netbuff_put (buf, isr->frame_len); + ptr = buf->data; + end = ptr + isr->frame_len; + len = isr->frame_len; + grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len); + ptr += isr->buffer_len; + while (ptr < end) + { + grub_memset (isr, 0, sizeof (*isr)); + isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT; + grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); + if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE) + return -1; + + grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len); + ptr += isr->buffer_len; + } + + grub_printf ("<%d>\n", len); + return len; +} + +static grub_err_t +grub_pxe_send (const struct grub_net_card *dev __attribute__ ((unused)), + struct grub_net_buff *pack) +{ + struct grub_pxe_undi_transmit *trans; + struct grub_pxe_undi_tbd *tbd; + char *buf; + + trans = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + grub_memset (trans, 0, sizeof (*trans)); + tbd = (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 128); + grub_memset (tbd, 0, sizeof (*tbd)); + buf = (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 256); + grub_memcpy (buf, pack->data, pack->tail - pack->data); + + trans->tbd = SEGOFS ((grub_addr_t) tbd); + trans->protocol = 0; + tbd->len = pack->tail - pack->data; + tbd->buf = SEGOFS ((grub_addr_t) buf); + + grub_pxe_call (GRUB_PXENV_UNDI_TRANSMIT, trans, pxe_rm_entry); + if (trans->status) + return grub_error (GRUB_ERR_IO, "PXE send failed (status 0x%x)", + trans->status); + return 0; +} + +struct grub_net_card_driver grub_pxe_card_driver = +{ + .send = grub_pxe_send, + .recv = grub_pxe_recv +}; + +struct grub_net_card grub_pxe_card = +{ + .driver = &grub_pxe_card_driver, + .name = "pxe" +}; + +void +grub_pxe_unload (void) +{ + if (grub_pxe_pxenv) + { + grub_pxe_call (GRUB_PXENV_UNDI_CLOSE, + (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, + pxe_rm_entry); + grub_net_card_unregister (&grub_pxe_card); + grub_pxe_pxenv = 0; + } +} + +GRUB_MOD_INIT(pxe) +{ + struct grub_pxe_bangpxe *pxenv; + struct grub_pxenv_get_cached_info ci; + struct grub_net_bootp_packet *bp; + struct grub_pxe_undi_open *ou; + + pxenv = grub_pxe_scan (); + if (! pxenv) + return; + + ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK; + ci.buffer = 0; + ci.buffer_size = 0; + grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry); + if (ci.status) + return; + + bp = LINEAR (ci.buffer); + + grub_memcpy (grub_pxe_card.default_address.mac, bp->mac_addr, + bp->hw_len < sizeof (grub_pxe_card.default_address.mac) + ? bp->hw_len : sizeof (grub_pxe_card.default_address.mac)); + grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + + ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + grub_memset (ou, 0, sizeof (ou)); + ou->pkt_filter = 4; + grub_pxe_call (GRUB_PXENV_UNDI_OPEN, ou, pxe_rm_entry); + + if (ou->status) + return; + + grub_net_card_register (&grub_pxe_card); + grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, 0, + bp, GRUB_PXE_BOOTP_SIZE); +} + +GRUB_MOD_FINI(pxe) +{ + grub_pxe_unload (); +} diff --git a/grub-core/net/i386/pc/pxe.c b/grub-core/net/i386/pc/pxe.c deleted file mode 100644 index 27c4af17f..000000000 --- a/grub-core/net/i386/pc/pxe.c +++ /dev/null @@ -1,482 +0,0 @@ -/* pxe.c - Driver to provide access to the pxe filesystem */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008,2009 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 - -#define SEGMENT(x) ((x) >> 4) -#define OFFSET(x) ((x) & 0xF) -#define SEGOFS(x) ((SEGMENT(x) << 16) + OFFSET(x)) -#define LINEAR(x) (void *) (((x >> 16) << 4) + (x & 0xFFFF)) - -struct grub_pxe_bangpxe *grub_pxe_pxenv; -static grub_uint32_t grub_pxe_default_server_ip; -#if 0 -static grub_uint32_t grub_pxe_default_gateway_ip; -#endif -static unsigned grub_pxe_blksize = GRUB_PXE_MIN_BLKSIZE; -static grub_uint32_t pxe_rm_entry = 0; -static grub_file_t curr_file = 0; - -struct grub_pxe_data -{ - grub_uint32_t packet_number; - grub_uint32_t block_size; - grub_uint32_t server_ip; - grub_uint32_t gateway_ip; - char filename[0]; -}; - - -static struct grub_pxe_bangpxe * -grub_pxe_scan (void) -{ - struct grub_bios_int_registers regs; - struct grub_pxenv *pxenv; - struct grub_pxe_bangpxe *bangpxe; - - regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; - - regs.ebx = 0; - regs.ecx = 0; - regs.eax = 0x5650; - regs.es = 0; - - grub_bios_interrupt (0x1a, ®s); - - if ((regs.eax & 0xffff) != 0x564e) - return NULL; - - pxenv = (struct grub_pxenv *) ((regs.es << 4) + (regs.ebx & 0xffff)); - if (grub_memcmp (pxenv->signature, GRUB_PXE_SIGNATURE, - sizeof (pxenv->signature)) - != 0) - return NULL; - - if (pxenv->version < 0x201) - return NULL; - - bangpxe = (void *) ((((pxenv->pxe_ptr & 0xffff0000) >> 16) << 4) - + (pxenv->pxe_ptr & 0xffff)); - - if (!bangpxe) - return NULL; - - if (grub_memcmp (bangpxe->signature, GRUB_PXE_BANGPXE_SIGNATURE, - sizeof (bangpxe->signature)) != 0) - return NULL; - - pxe_rm_entry = bangpxe->rm_entry; - - return bangpxe; -} - -static grub_err_t -grub_pxefs_dir (grub_device_t device __attribute__ ((unused)), - const char *path __attribute__ ((unused)), - int (*hook) (const char *filename, - const struct grub_dirhook_info *info) - __attribute__ ((unused))) -{ - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_pxefs_open (struct grub_file *file, const char *name) -{ - union - { - struct grub_pxenv_tftp_get_fsize c1; - struct grub_pxenv_tftp_open c2; - } c; - struct grub_pxe_data *data; - grub_file_t file_int, bufio; - - data = grub_zalloc (sizeof (*data) + grub_strlen (name) + 1); - if (!data) - return grub_errno; - - { - grub_net_network_level_address_t addr; - grub_net_network_level_address_t gateway; - struct grub_net_network_level_interface *interf; - grub_err_t err; - - if (grub_strncmp (file->device->net->name, - "pxe,", sizeof ("pxe,") - 1) == 0 - || grub_strncmp (file->device->net->name, - "pxe:", sizeof ("pxe:") - 1) == 0) - { - err = grub_net_resolve_address (file->device->net->name - + sizeof ("pxe,") - 1, &addr); - if (err) - { - grub_free (data); - return err; - } - } - else - { - addr.ipv4 = grub_pxe_default_server_ip; - addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - } - err = grub_net_route_address (addr, &gateway, &interf); - if (err) - { - grub_free (data); - return err; - } - data->server_ip = addr.ipv4; - data->gateway_ip = gateway.ipv4; - } - - if (curr_file != 0) - { - grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c.c2, pxe_rm_entry); - curr_file = 0; - } - - c.c1.server_ip = data->server_ip; - c.c1.gateway_ip = data->gateway_ip; - grub_strcpy ((char *)&c.c1.filename[0], name); - grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1, pxe_rm_entry); - if (c.c1.status) - { - grub_free (data); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); - } - - file->size = c.c1.file_size; - - c.c2.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT); - c.c2.packet_size = grub_pxe_blksize; - grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &c.c2, pxe_rm_entry); - if (c.c2.status) - { - grub_free (data); - return grub_error (GRUB_ERR_BAD_FS, "open fails"); - } - - data->block_size = c.c2.packet_size; - grub_strcpy (data->filename, name); - - file_int = grub_malloc (sizeof (*file_int)); - if (! file_int) - { - grub_free (data); - return grub_errno; - } - - file->data = data; - file->not_easily_seekable = 1; - grub_memcpy (file_int, file, sizeof (struct grub_file)); - curr_file = file_int; - - bufio = grub_bufio_open (file_int, data->block_size); - if (! bufio) - { - grub_free (file_int); - grub_free (data); - return grub_errno; - } - - grub_memcpy (file, bufio, sizeof (struct grub_file)); - - return GRUB_ERR_NONE; -} - -static grub_ssize_t -grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len) -{ - struct grub_pxenv_tftp_read c; - struct grub_pxe_data *data; - grub_uint32_t pn; - grub_uint64_t r; - - data = file->data; - - pn = grub_divmod64 (file->offset, data->block_size, &r); - if (r) - { - grub_error (GRUB_ERR_BAD_FS, - "read access must be aligned to packet size"); - return -1; - } - - if ((curr_file != file) || (data->packet_number > pn)) - { - struct grub_pxenv_tftp_open o; - - if (curr_file != 0) - grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o, pxe_rm_entry); - - o.server_ip = data->server_ip; - o.gateway_ip = data->gateway_ip; - grub_strcpy ((char *)&o.filename[0], data->filename); - o.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT); - o.packet_size = data->block_size; - grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &o, pxe_rm_entry); - if (o.status) - { - grub_error (GRUB_ERR_BAD_FS, "open fails"); - return -1; - } - data->block_size = o.packet_size; - data->packet_number = 0; - curr_file = file; - } - - c.buffer = SEGOFS (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); - while (pn >= data->packet_number) - { - c.buffer_size = data->block_size; - grub_pxe_call (GRUB_PXENV_TFTP_READ, &c, pxe_rm_entry); - if (c.status) - { - grub_error (GRUB_ERR_BAD_FS, "read fails"); - return -1; - } - data->packet_number++; - } - - grub_memcpy (buf, (char *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, len); - - return len; -} - -static grub_err_t -grub_pxefs_close (grub_file_t file) -{ - struct grub_pxenv_tftp_close c; - - if (curr_file == file) - { - grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c, pxe_rm_entry); - curr_file = 0; - } - - grub_free (file->data); - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_pxefs_label (grub_device_t device __attribute ((unused)), - char **label __attribute ((unused))) -{ - *label = 0; - return GRUB_ERR_NONE; -} - -static struct grub_fs grub_pxefs_fs = - { - .name = "pxe", - .dir = grub_pxefs_dir, - .open = grub_pxefs_open, - .read = grub_pxefs_read, - .close = grub_pxefs_close, - .label = grub_pxefs_label, - .next = 0 - }; - -static grub_ssize_t -grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused)), - struct grub_net_buff *buf __attribute__ ((unused))) -{ - return 0; -} - -static grub_err_t -grub_pxe_send (struct grub_net_card *dev __attribute__ ((unused)), - struct grub_net_buff *buf __attribute__ ((unused))) -{ - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "not implemented"); -} - -struct grub_net_card_driver grub_pxe_card_driver = -{ - .send = grub_pxe_send, - .recv = grub_pxe_recv -}; - -struct grub_net_card grub_pxe_card = -{ - .driver = &grub_pxe_card_driver, - .name = "pxe" -}; - -void -grub_pxe_unload (void) -{ - if (grub_pxe_pxenv) - { - grub_fs_unregister (&grub_pxefs_fs); - grub_net_card_unregister (&grub_pxe_card); - grub_pxe_pxenv = 0; - } -} - -static void -set_ip_env (char *varname, grub_uint32_t ip) -{ - char buf[GRUB_NET_MAX_STR_ADDR_LEN]; - grub_net_network_level_address_t addr; - addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - addr.ipv4 = ip; - - grub_net_addr_to_str (&addr, buf); - grub_env_set (varname, buf); -} - -static char * -write_ip_env (grub_uint32_t *ip, const char *val) -{ - char *buf; - grub_err_t err; - grub_net_network_level_address_t addr; - - err = grub_net_resolve_address (val, &addr); - if (err) - return 0; - if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) - return NULL; - - /* Normalize the IP. */ - buf = grub_malloc (GRUB_NET_MAX_STR_ADDR_LEN); - if (!buf) - return 0; - grub_net_addr_to_str (&addr, buf); - - *ip = addr.ipv4; - - return buf; -} - -static char * -grub_env_write_pxe_default_server (struct grub_env_var *var - __attribute__ ((unused)), - const char *val) -{ - return write_ip_env (&grub_pxe_default_server_ip, val); -} - -#if 0 -static char * -grub_env_write_pxe_default_gateway (struct grub_env_var *var - __attribute__ ((unused)), - const char *val) -{ - return write_ip_env (&grub_pxe_default_gateway_ip, val); -} -#endif - -static char * -grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__ ((unused)), - const char *val) -{ - unsigned size; - char *buf; - - size = grub_strtoul (val, 0, 0); - if (grub_errno) - return 0; - - if (size < GRUB_PXE_MIN_BLKSIZE) - size = GRUB_PXE_MIN_BLKSIZE; - else if (size > GRUB_PXE_MAX_BLKSIZE) - size = GRUB_PXE_MAX_BLKSIZE; - - buf = grub_xasprintf ("%d", size); - if (!buf) - return 0; - - grub_pxe_blksize = size; - - return buf; -} - -GRUB_MOD_INIT(pxe) -{ - struct grub_pxe_bangpxe *pxenv; - struct grub_pxenv_get_cached_info ci; - struct grub_net_bootp_ack *bp; - char *buf; - - pxenv = grub_pxe_scan (); - if (! pxenv) - return; - - ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK; - ci.buffer = 0; - ci.buffer_size = 0; - grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry); - if (ci.status) - return; - - bp = LINEAR (ci.buffer); - - grub_pxe_default_server_ip = bp->server_ip; - grub_pxe_pxenv = pxenv; - - set_ip_env ("pxe_default_server", grub_pxe_default_server_ip); - grub_register_variable_hook ("pxe_default_server", 0, - grub_env_write_pxe_default_server); - -#if 0 - grub_pxe_default_gateway_ip = bp->gateway_ip; - - grub_register_variable_hook ("pxe_default_gateway", 0, - grub_env_write_pxe_default_gateway); -#endif - - buf = grub_xasprintf ("%d", grub_pxe_blksize); - if (buf) - grub_env_set ("pxe_blksize", buf); - grub_free (buf); - - grub_register_variable_hook ("pxe_blksize", 0, - grub_env_write_pxe_blocksize); - - grub_memcpy (grub_pxe_card.default_address.mac, bp->mac_addr, - bp->hw_len < sizeof (grub_pxe_card.default_address.mac) - ? bp->hw_len : sizeof (grub_pxe_card.default_address.mac)); - grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - - grub_fs_register (&grub_pxefs_fs); - grub_net_card_register (&grub_pxe_card); - grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, - GRUB_NET_INTERFACE_PERMANENT - | GRUB_NET_INTERFACE_ADDRESS_IMMUTABLE - | GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE, - bp, GRUB_PXE_BOOTP_SIZE); -} - -GRUB_MOD_FINI(pxe) -{ - grub_pxe_unload (); -} From bf651f790717fd5b73c80e6bedd9df66069c847e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 14:47:38 +0200 Subject: [PATCH 344/406] Fix incorrect memset --- grub-core/net/drivers/i386/pc/pxe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index 7d6e3adca..e667d42ef 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -286,7 +286,7 @@ GRUB_MOD_INIT(pxe) grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; - grub_memset (ou, 0, sizeof (ou)); + grub_memset (ou, 0, sizeof (*ou)); ou->pkt_filter = 4; grub_pxe_call (GRUB_PXENV_UNDI_OPEN, ou, pxe_rm_entry); From 80ca250565745aa1f587216ed8af6dc70e036e92 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 17:06:18 +0200 Subject: [PATCH 345/406] Add backward compatibiulity with old (pxe) syntax. Several cleanups --- grub-core/commands/probe.c | 2 +- grub-core/kern/device.c | 2 +- grub-core/net/drivers/i386/pc/pxe.c | 1 - grub-core/net/net.c | 114 ++++++++++++++++++++-------- include/grub/net.h | 6 +- 5 files changed, 87 insertions(+), 38 deletions(-) diff --git a/grub-core/commands/probe.c b/grub-core/commands/probe.c index 7ed2a4e51..ce1e9aac0 100644 --- a/grub-core/commands/probe.c +++ b/grub-core/commands/probe.c @@ -74,7 +74,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) { const char *val = "none"; if (dev->net) - val = dev->net->name; + val = dev->net->protocol->name; if (dev->disk) val = dev->disk->dev->name; if (state[0].set) diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c index 45bcd8210..c998d4d4b 100644 --- a/grub-core/kern/device.c +++ b/grub-core/kern/device.c @@ -79,7 +79,7 @@ grub_device_close (grub_device_t device) if (device->net) { - grub_free (device->net->name); + grub_free (device->net->server); grub_free (device->net); } diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index e667d42ef..084cdb876 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -204,7 +204,6 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), ptr += isr->buffer_len; } - grub_printf ("<%d>\n", len); return len; } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 5c7d00991..2932986b2 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2010 Free Software Foundation, Inc. + * Copyright (C) 2010,2011 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 @@ -32,6 +32,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); +static char *default_server; + struct grub_net_route { struct grub_net_route *next; @@ -603,26 +605,63 @@ struct grub_net_socket *grub_net_sockets; static grub_net_t grub_net_open_real (const char *name) { - const char *comma = grub_strchr (name, ','); grub_net_app_level_t proto; + const char *protname, *server; + grub_size_t protnamelen; + + if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0) + { + protname = "tftp"; + protnamelen = sizeof ("tftp") - 1; + server = name + sizeof ("pxe:") - 1; + } + else if (grub_strcmp (name, "pxe") == 0) + { + protname = "tftp"; + protnamelen = sizeof ("tftp") - 1; + server = default_server; + } + else + { + const char *comma; + comma = grub_strchr (name, ','); + if (comma) + { + protnamelen = comma - name; + server = comma + 1; + } + else + { + protnamelen = grub_strlen (name); + server = default_server; + } + } + if (!server) + { + grub_error (GRUB_ERR_NET_BAD_ADDRESS, "no server"); + return NULL; + } - if (!comma) - comma = name + grub_strlen (name); FOR_NET_APP_LEVEL (proto) { - if (comma - name == (grub_ssize_t) grub_strlen (proto->name) - && grub_memcmp (proto->name, name, comma - name) == 0) + if (grub_memcmp (proto->name, protname, protnamelen) == 0 + && proto->name[protnamelen] == 0) { grub_net_t ret = grub_malloc (sizeof (*ret)); if (!ret) return NULL; ret->protocol = proto; - ret->name = grub_strdup (name); - if (!ret->name) + if (server) { - grub_free (ret); - return NULL; + ret->server = grub_strdup (server); + if (!ret->server) + { + grub_free (ret); + return NULL; + } } + else + ret->server = NULL; ret->fs = &grub_net_fs; return ret; } @@ -651,13 +690,8 @@ grub_net_fs_open (struct grub_file *file, const char *name) grub_net_network_level_address_t gateway; grub_net_socket_t socket; static int port = 25300; - const char *comma; - comma = grub_strchr (file->device->net->name, ','); - if (!comma) - return grub_error (GRUB_ERR_NET_BAD_ADDRESS, "no separator"); - - err = grub_net_resolve_address (comma + 1, &addr); + err = grub_net_resolve_address (file->device->net->server, &addr); if (err) return err; @@ -913,20 +947,19 @@ grub_net_configure_by_dhcp_ack (const char *name, hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; inter = grub_net_add_addr (name, card, addr, hwaddr, flags); - if (bp->gateway_ip != bp->server_ip) - { - grub_net_network_level_netaddress_t target; - grub_net_network_level_address_t gw; - char rname[grub_strlen (name) + sizeof ("_gw")]; + { + grub_net_network_level_netaddress_t target; + grub_net_network_level_address_t gw; + char rname[grub_strlen (name) + sizeof ("_gw")]; - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4.base = bp->server_ip; - target.ipv4.masksize = 32; - gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - gw.ipv4 = bp->gateway_ip; - grub_snprintf (rname, sizeof (rname), "%s_gw", name); - grub_net_add_route_gw (rname, target, gw); - } + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = bp->server_ip; + target.ipv4.masksize = 32; + gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + gw.ipv4 = bp->gateway_ip; + grub_snprintf (rname, sizeof (rname), "%s_gw", name); + grub_net_add_route_gw (rname, target, gw); + } { grub_net_network_level_netaddress_t target; target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; @@ -938,9 +971,26 @@ grub_net_configure_by_dhcp_ack (const char *name, if (size > OFFSET_OF (boot_file, bp)) set_env_limn_ro (name, "boot_file", (char *) bp->boot_file, sizeof (bp->boot_file)); - if (size > OFFSET_OF (server_name, bp)) - set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name, - sizeof (bp->server_name)); + if (size > OFFSET_OF (server_name, bp) + && bp->server_name[0]) + { + set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name, + sizeof (bp->server_name)); + if (!default_server) + { + default_server = grub_strdup (bp->server_name); + grub_errno = GRUB_ERR_NONE; + } + } + if (!default_server) + { + default_server = grub_xasprintf ("%d.%d.%d.%d", + ((grub_uint8_t *) &bp->server_ip)[0], + ((grub_uint8_t *) &bp->server_ip)[1], + ((grub_uint8_t *) &bp->server_ip)[2], + ((grub_uint8_t *) &bp->server_ip)[3]); + grub_errno = GRUB_ERR_NONE; + } if (size > OFFSET_OF (vendor, bp)) parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp)); diff --git a/include/grub/net.h b/include/grub/net.h index 068ccec41..6595a8276 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -234,7 +234,7 @@ grub_net_socket_unregister (grub_net_socket_t sock) typedef struct grub_net { - char *name; + char *server; grub_net_app_level_t protocol; grub_net_socket_t socket; grub_fs_t fs; @@ -389,8 +389,8 @@ struct grub_net_bootp_packet grub_uint32_t server_ip; grub_uint32_t gateway_ip; grub_net_bootp_mac_addr_t mac_addr; - grub_uint8_t server_name[64]; - grub_uint8_t boot_file[128]; + char server_name[64]; + char boot_file[128]; grub_uint8_t vendor[0]; } __attribute__ ((packed)); From cbf597afb158a54ff1d35d4e21f0f6df3c1a01b9 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sun, 26 Jun 2011 17:17:41 +0200 Subject: [PATCH 346/406] * grub-core/commands/cmp.c (grub_cmd_cmp): Remove unnecessary NULL pointer checks before calling grub_free(). * grub-core/commands/wildcard.c (match_devices): Likewise. * grub-core/commands/wildcard.c (match_files): Likewise. * grub-core/fs/cpio.c (grub_cpio_dir): Likewise. * grub-core/fs/cpio.c (grub_cpio_open): Likewise. * grub-core/fs/udf.c (grub_udf_read_block): Likewise. * grub-core/fs/xfs.c (grub_xfs_read_block): Likewise. * grub-core/loader/efi/chainloader.c (grub_cmd_chainloader): Likewise. * grub-core/normal/cmdline.c (grub_cmdline_get): Likewise. * grub-core/script/yylex.l (grub_lexer_unput): Likewise. * grub-core/video/readers/jpeg.c (grub_video_reader_jpeg): Likewise. * grub-core/video/readers/png.c (grub_png_output_byte): Likewise. --- ChangeLog | 16 ++++++++++++++++ grub-core/commands/cmp.c | 6 ++---- grub-core/commands/wildcard.c | 12 ++++-------- grub-core/fs/cpio.c | 13 ++++--------- grub-core/fs/udf.c | 3 +-- grub-core/fs/xfs.c | 3 +-- grub-core/loader/efi/chainloader.c | 3 +-- grub-core/normal/cmdline.c | 6 ++---- grub-core/script/yylex.l | 3 +-- grub-core/video/readers/jpeg.c | 3 +-- grub-core/video/readers/png.c | 3 +-- 11 files changed, 34 insertions(+), 37 deletions(-) diff --git a/ChangeLog b/ChangeLog index c639cb9de..17be445af 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2011-06-26 Szymon Janc + + * grub-core/commands/cmp.c (grub_cmd_cmp): Remove unnecessary NULL + pointer checks before calling grub_free(). + * grub-core/commands/wildcard.c (match_devices): Likewise. + * grub-core/commands/wildcard.c (match_files): Likewise. + * grub-core/fs/cpio.c (grub_cpio_dir): Likewise. + * grub-core/fs/cpio.c (grub_cpio_open): Likewise. + * grub-core/fs/udf.c (grub_udf_read_block): Likewise. + * grub-core/fs/xfs.c (grub_xfs_read_block): Likewise. + * grub-core/loader/efi/chainloader.c (grub_cmd_chainloader): Likewise. + * grub-core/normal/cmdline.c (grub_cmdline_get): Likewise. + * grub-core/script/yylex.l (grub_lexer_unput): Likewise. + * grub-core/video/readers/jpeg.c (grub_video_reader_jpeg): Likewise. + * grub-core/video/readers/png.c (grub_png_output_byte): Likewise. + 2011-06-25 Patrick * grub-core/kern/main.c (grub_load_normal_mode): Correct the comment. diff --git a/grub-core/commands/cmp.c b/grub-core/commands/cmp.c index 0222927b6..526459311 100644 --- a/grub-core/commands/cmp.c +++ b/grub-core/commands/cmp.c @@ -94,10 +94,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)), cleanup: - if (buf1) - grub_free (buf1); - if (buf2) - grub_free (buf2); + grub_free (buf1); + grub_free (buf2); if (file1) grub_file_close (file1); if (file2) diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c index 45d819a3e..d2f4347d5 100644 --- a/grub-core/commands/wildcard.c +++ b/grub-core/commands/wildcard.c @@ -255,8 +255,7 @@ match_devices (const regex_t *regexp, int noparts) for (i = 0; devs && devs[i]; i++) grub_free (devs[i]); - if (devs) - grub_free (devs); + grub_free (devs); return 0; } @@ -342,20 +341,17 @@ match_files (const char *prefix, const char *suffix, const char *end, fail: - if (dir) - grub_free (dir); + grub_free (dir); for (i = 0; files && files[i]; i++) grub_free (files[i]); - if (files) - grub_free (files); + grub_free (files); if (dev) grub_device_close (dev); - if (device_name) - grub_free (device_name); + grub_free (device_name); grub_error_pop (); return 0; diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index 3a07873ec..0d84382ac 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -239,8 +239,7 @@ grub_cpio_dir (grub_device_t device, const char *path, info.mtimeset = 1; hook (name + len, &info); - if (prev) - grub_free (prev); + grub_free (prev); prev = name; } else @@ -251,11 +250,8 @@ grub_cpio_dir (grub_device_t device, const char *path, fail: - if (prev) - grub_free (prev); - - if (data) - grub_free (data); + grub_free (prev); + grub_free (data); grub_dl_unref (my_mod); @@ -326,8 +322,7 @@ grub_cpio_open (grub_file_t file, const char *name) fail: - if (data) - grub_free (data); + grub_free (data); grub_dl_unref (my_mod); diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index 48906f84f..e1f115015 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -546,8 +546,7 @@ grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) } fail: - if (buf) - grub_free (buf); + grub_free (buf); return 0; } diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 1e466465b..eb0783407 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -324,8 +324,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) } } - if (leaf) - grub_free (leaf); + grub_free (leaf); return GRUB_XFS_FSB_TO_BLOCK(node->data, ret); } diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c index 5dd5adab2..3ecdca534 100644 --- a/grub-core/loader/efi/chainloader.c +++ b/grub-core/loader/efi/chainloader.c @@ -329,8 +329,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), if (file) grub_file_close (file); - if (file_path) - grub_free (file_path); + grub_free (file_path); if (address) efi_call_2 (b->free_pages, address, pages); diff --git a/grub-core/normal/cmdline.c b/grub-core/normal/cmdline.c index 09f2271ea..ea06b4cc7 100644 --- a/grub-core/normal/cmdline.c +++ b/grub-core/normal/cmdline.c @@ -500,8 +500,7 @@ grub_cmdline_get (const char *prompt) case GRUB_TERM_CTRL | 'k': if (lpos < llen) { - if (kill_buf) - grub_free (kill_buf); + grub_free (kill_buf); kill_buf = grub_malloc ((llen - lpos + 1) * sizeof (grub_uint32_t)); @@ -566,8 +565,7 @@ grub_cmdline_get (const char *prompt) { grub_size_t n = lpos; - if (kill_buf) - grub_free (kill_buf); + grub_free (kill_buf); kill_buf = grub_malloc (n + 1); if (grub_errno) diff --git a/grub-core/script/yylex.l b/grub-core/script/yylex.l index 53ae4c54f..96f57dbe6 100644 --- a/grub-core/script/yylex.l +++ b/grub-core/script/yylex.l @@ -355,8 +355,7 @@ grub_lexer_unput (const char *text, yyscan_t yyscanner) { struct grub_lexer_param *lexerstate = yyget_extra (yyscanner)->lexerstate; - if (lexerstate->prefix) - grub_free (lexerstate->prefix); + grub_free (lexerstate->prefix); lexerstate->prefix = grub_strdup (text); if (! lexerstate->prefix) diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c index d61c90ec9..f2351dee9 100644 --- a/grub-core/video/readers/jpeg.c +++ b/grub-core/video/readers/jpeg.c @@ -750,8 +750,7 @@ grub_video_reader_jpeg (struct grub_video_bitmap **bitmap, grub_jpeg_decode_jpeg (data); for (i = 0; i < 4; i++) - if (data->huff_value[i]) - grub_free (data->huff_value[i]); + grub_free (data->huff_value[i]); grub_free (data); } diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c index 5728651e0..ae9879b16 100644 --- a/grub-core/video/readers/png.c +++ b/grub-core/video/readers/png.c @@ -625,8 +625,7 @@ grub_png_output_byte (struct grub_png_data *data, grub_uint8_t n) } } - if (blank_line) - grub_free (blank_line); + grub_free (blank_line); data->cur_column = 0; data->first_line = 0; From a8fae12c5be48b4dafeec7c47d99132630be51cb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 17:18:53 +0200 Subject: [PATCH 347/406] minor cleanups --- grub-core/net/tftp.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index d0ed7c43a..24f30eb7a 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -131,8 +131,9 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) grub_netbuff_clear (nb); break; case TFTP_DATA: - if ((err = grub_netbuff_pull (nb, sizeof (tftph->opcode) + - sizeof (tftph->u.data.block))) != GRUB_ERR_NONE) + err = grub_netbuff_pull (nb, sizeof (tftph->opcode) + + sizeof (tftph->u.data.block)); + if (err) return err; if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) { @@ -142,8 +143,11 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) sock->status = 2; /* Prevent garbage in broken cards. */ if (size > 1024) - if ((err = grub_netbuff_unput (nb, size - 1024)) != GRUB_ERR_NONE) - return err; + { + err = grub_netbuff_unput (nb, size - 1024); + if (err) + return err; + } } else grub_netbuff_clear (nb); From b1f9b7249afa234d64454b3db3c5a77a64db1e87 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 17:28:19 +0200 Subject: [PATCH 348/406] mknetdir support for ieee1275 --- util/grub-mknetdir.in | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in index 61a7ec3ad..3b4f051c5 100644 --- a/util/grub-mknetdir.in +++ b/util/grub-mknetdir.in @@ -196,11 +196,17 @@ process_input_dir () config_opt="-c ${grubdir}/load.cfg " fi + prefix="/${subdir}/${platform}"; case "${platform}" in i386-pc) mkimage_target=i386-pc-pxe; netmodules="pxe"; - prefix="(pxe)/${subdir}/${platform}"; ext=0 ;; + sparc64-ieee1275) mkimage_target=sparc64-ieee1275-aout; + netmodules=""; + ext=img ;; + *-ieee1275) mkimage_target="${platform}"; + netmodules=""; + ext=elf ;; *) echo Unsupported platform ${platform}; exit 1;; esac From 2f804a7ff6cf37ac69584b88c63e6e5cc209da73 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 17:28:57 +0200 Subject: [PATCH 349/406] remove leftover directory From a27fe54f96b3dc19f3222b2872cd0e365059e1a6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 17:51:46 +0200 Subject: [PATCH 350/406] missing part of previous commit --- util/grub-mknetdir.in | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in index 3b4f051c5..a561004e6 100644 --- a/util/grub-mknetdir.in +++ b/util/grub-mknetdir.in @@ -45,6 +45,9 @@ debug=no debug_image= subdir=`echo /boot/grub | sed ${transform}` pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc +ppc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/powerpc-ieee1275 +sparc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/sparc64-ieee1275 +i386_ieee1275_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-ieee1275 # Usage: usage # Print the usage. @@ -223,6 +226,15 @@ if [ "${override_dir}" = "" ] ; then if test -e "${pc_dir}" ; then process_input_dir ${pc_dir} i386-pc fi + if test -e "${ppc_dir}" ; then + process_input_dir ${ppc_dir} powerpc-ieee1275 + fi + if test -e "${sparc_dir}" ; then + process_input_dir ${sparc_dir} sparc64-ieee1275 + fi + if test -e "${i386_ieee1275_dir}" ; then + process_input_dir ${sparc_dir} i386-ieee1275 + fi else source "${override_dir}"/modinfo.sh process_input_dir "${override_dir}" ${grub_modinfo_target_cpu}-${grub_modinfo_platform} From cf2bba0ef43bd2708d705ab3bf40fb841310b398 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 18:23:12 +0200 Subject: [PATCH 351/406] add missing quotes and fix variable name --- util/grub-mknetdir.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in index a561004e6..fa0cafe54 100644 --- a/util/grub-mknetdir.in +++ b/util/grub-mknetdir.in @@ -224,16 +224,16 @@ EOF if [ "${override_dir}" = "" ] ; then if test -e "${pc_dir}" ; then - process_input_dir ${pc_dir} i386-pc + process_input_dir "${pc_dir}" i386-pc fi if test -e "${ppc_dir}" ; then - process_input_dir ${ppc_dir} powerpc-ieee1275 + process_input_dir "${ppc_dir}" powerpc-ieee1275 fi if test -e "${sparc_dir}" ; then process_input_dir ${sparc_dir} sparc64-ieee1275 fi if test -e "${i386_ieee1275_dir}" ; then - process_input_dir ${sparc_dir} i386-ieee1275 + process_input_dir "${i386_ieee1275_dir}" i386-ieee1275 fi else source "${override_dir}"/modinfo.sh From e552d93a8b28cac6fd1a1b4116980f80794a80ca Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 19:52:50 +0200 Subject: [PATCH 352/406] Add ofnet and tftp modules --- util/grub-mknetdir.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in index fa0cafe54..a36e33cab 100644 --- a/util/grub-mknetdir.in +++ b/util/grub-mknetdir.in @@ -205,10 +205,10 @@ process_input_dir () netmodules="pxe"; ext=0 ;; sparc64-ieee1275) mkimage_target=sparc64-ieee1275-aout; - netmodules=""; + netmodules="ofnet"; ext=img ;; *-ieee1275) mkimage_target="${platform}"; - netmodules=""; + netmodules="ofnet"; ext=elf ;; *) echo Unsupported platform ${platform}; exit 1;; @@ -218,7 +218,7 @@ process_input_dir () source ${subdir}/grub.cfg EOF - $grub_mkimage ${config_opt} -d "${input_dir}" -O ${mkimage_target} --output=${grubdir}/core.$ext --prefix=$prefix $modules $netmodules || exit 1 + $grub_mkimage ${config_opt} -d "${input_dir}" -O ${mkimage_target} --output=${grubdir}/core.$ext --prefix=$prefix $modules $netmodules tftp || exit 1 echo "Netboot directory for ${platform} created. Configure your DHCP server to point to ${subdir}/${platform}/core.$ext" } From 9e322ce8de8526c2c752362749663e6c186f60e3 Mon Sep 17 00:00:00 2001 From: Yves Blusseau Date: Sun, 26 Jun 2011 21:48:52 +0200 Subject: [PATCH 353/406] Display the path of the file when file is not found * grub-core/fs/fat.c: Display the filename when file is not found. * grub-core/fs/fshelp.c: Likewise. * grub-core/fs/hfs.c: Likewise. * grub-core/fs/jfs.c: Likewise. * grub-core/fs/minix.c: Likewise. * grub-core/fs/ufs.c: Likewise. * grub-core/fs/btrfs.c: Likewise. * grub-core/commands/i386/pc/play.c: Likewise. --- ChangeLog | 13 +++++++++++++ grub-core/commands/i386/pc/play.c | 4 ++-- grub-core/fs/btrfs.c | 32 +++++++++++++++++++++++++++---- grub-core/fs/fat.c | 11 +++++++++-- grub-core/fs/fshelp.c | 2 +- grub-core/fs/hfs.c | 2 +- grub-core/fs/jfs.c | 2 +- grub-core/fs/minix.c | 2 +- grub-core/fs/ufs.c | 2 +- 9 files changed, 57 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 17be445af..bd6e311bd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2011-06-26 Yves Blusseau + + Display the path of the file when file is not found + + * grub-core/fs/fat.c: Display the filename when file is not found. + * grub-core/fs/fshelp.c: Likewise. + * grub-core/fs/hfs.c: Likewise. + * grub-core/fs/jfs.c: Likewise. + * grub-core/fs/minix.c: Likewise. + * grub-core/fs/ufs.c: Likewise. + * grub-core/fs/btrfs.c: Likewise. + * grub-core/commands/i386/pc/play.c: Likewise. + 2011-06-26 Szymon Janc * grub-core/commands/cmp.c (grub_cmd_cmp): Remove unnecessary NULL diff --git a/grub-core/commands/i386/pc/play.c b/grub-core/commands/i386/pc/play.c index 57980eb92..1adf296ec 100644 --- a/grub-core/commands/i386/pc/play.c +++ b/grub-core/commands/i386/pc/play.c @@ -192,7 +192,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), file = grub_file_open (args[0]); if (! file) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", args[0]); if (grub_file_read (file, &tempo, sizeof (tempo)) != sizeof (tempo)) { @@ -227,7 +227,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), if (*end) /* Was not a number either, assume it was supposed to be a file name. */ - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", args[0]); grub_dprintf ("play","tempo = %d\n", tempo); diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 533529e3f..6470c9819 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -1054,6 +1054,7 @@ find_path (struct grub_btrfs_data *data, const char *ctoken; grub_size_t ctokenlen; char *path_alloc = NULL; + char *origpath = NULL; unsigned symlinks_max = 32; *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; @@ -1062,6 +1063,9 @@ find_path (struct grub_btrfs_data *data, key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; key->offset = 0; skip_default = 1; + origpath = grub_strdup (path); + if (!origpath) + return grub_errno; while (1) { @@ -1086,6 +1090,7 @@ find_path (struct grub_btrfs_data *data, if (*type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) { grub_free (path_alloc); + grub_free (origpath); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); } @@ -1098,13 +1103,16 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); return err; } if (key_cmp (key, &key_out) != 0) { grub_free (direl); grub_free (path_alloc); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + grub_free (origpath); + return err; } struct grub_btrfs_dir_item *cdirel; @@ -1116,6 +1124,7 @@ find_path (struct grub_btrfs_data *data, if (!direl) { grub_free (path_alloc); + grub_free (origpath); return grub_errno; } } @@ -1125,6 +1134,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); return err; } @@ -1144,7 +1154,9 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + grub_free (origpath); + return err; } if (!skip_default) @@ -1158,6 +1170,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks"); } @@ -1168,6 +1181,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); return err; } tmp = grub_malloc (grub_le_to_cpu64 (inode.size) @@ -1176,6 +1190,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); return grub_errno; } @@ -1186,12 +1201,14 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); grub_free (tmp); return grub_errno; } grub_memcpy (tmp + grub_le_to_cpu64 (inode.size), path, grub_strlen (path) + 1); grub_free (path_alloc); + grub_free (origpath); path = path_alloc = tmp; if (path[0] == '/') { @@ -1218,6 +1235,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); return err; } if (cdirel->key.object_id != key_out.object_id @@ -1225,7 +1243,9 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + grub_free (origpath); + return err; } err = grub_btrfs_read_logical (data, elemaddr, &ri, sizeof (ri)); @@ -1233,6 +1253,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); return err; } key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; @@ -1246,7 +1267,9 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + grub_free (origpath); + return err; } *key = cdirel->key; if (*type == GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) @@ -1254,6 +1277,7 @@ find_path (struct grub_btrfs_data *data, break; default: grub_free (path_alloc); + grub_free (origpath); grub_free (direl); return grub_error (GRUB_ERR_BAD_FS, "unrecognised object type 0x%x", cdirel->key.type); diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index f617bb0f4..c78d3fbe6 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -565,6 +565,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, const struct grub_dirhook_info *info)) { char *dirname, *dirp; + char *origpath = NULL; int call_hook; int found = 0; @@ -605,6 +606,10 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, return 0; } + origpath = grub_strdup (path); + if (!origpath) + return 0; + /* Extract a directory name. */ while (*path == '/') path++; @@ -616,7 +621,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, dirname = grub_malloc (len + 1); if (! dirname) - return 0; + goto fail; grub_memcpy (dirname, path, len); dirname[len] = '\0'; @@ -629,9 +634,11 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, grub_fat_iterate_dir (disk, data, iter_hook); if (grub_errno == GRUB_ERR_NONE && ! found && !call_hook) - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + fail: grub_free (dirname); + grub_free (origpath); return found ? dirp : 0; } diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c index f879885ac..2ff78c423 100644 --- a/grub-core/fs/fshelp.c +++ b/grub-core/fs/fshelp.c @@ -197,7 +197,7 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, name = next; } - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path); } if (!path || path[0] != '/') diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index cb7679ecb..6f27c69c4 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -921,7 +921,7 @@ grub_hfs_find_dir (struct grub_hfs_data *data, const char *path, if (! grub_hfs_find_node (data, (char *) &key, data->cat_root, 0, (char *) &fdrec.frec, sizeof (fdrec.frec))) { - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); goto fail; } diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index c131169d8..36ec5fd25 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -699,7 +699,7 @@ grub_jfs_find_file (struct grub_jfs_data *data, const char *path) } grub_jfs_closedir (diro); - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path); return grub_errno; } diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 64a64cca0..055f89095 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -424,7 +424,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path) pos += sizeof (ino) + data->filename_size; } while (pos < GRUB_MINIX_INODE_SIZE (data)); - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path); return grub_errno; } diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c index 86fe8af65..0f4ea0019 100644 --- a/grub-core/fs/ufs.c +++ b/grub-core/fs/ufs.c @@ -514,7 +514,7 @@ grub_ufs_find_file (struct grub_ufs_data *data, const char *path) pos += grub_le_to_cpu16 (dirent.direntlen); } while (pos < INODE_SIZE (data)); - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path); return grub_errno; } From d36f20db4608fa7a8e66bdc86993fcd813e22c08 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 22:37:19 +0200 Subject: [PATCH 354/406] Don't do unaligned access when parsing DHCP packet --- grub-core/net/net.c | 11 ++++++++--- include/grub/net.h | 5 ++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 2932986b2..560fa7a31 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -879,7 +879,10 @@ parse_dhcp_vendor (const char *name, void *vend, int limit) ptr = ptr0 = vend; - if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr) != GRUB_NET_BOOTP_RFC1048_MAGIC) + if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0 + || ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1 + || ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2 + || ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3) return; ptr = ptr + sizeof (grub_uint32_t); while (ptr - ptr0 < limit) @@ -1078,8 +1081,10 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), ptr = inter->dhcp_ack->vendor; - if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr) - != GRUB_NET_BOOTP_RFC1048_MAGIC) + if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0 + || ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1 + || ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2 + || ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3) return grub_error (GRUB_ERR_IO, N_("no DHCP options found")); ptr = ptr + sizeof (grub_uint32_t); while (1) diff --git a/include/grub/net.h b/include/grub/net.h index 6595a8276..ee94ebcc6 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -394,7 +394,10 @@ struct grub_net_bootp_packet grub_uint8_t vendor[0]; } __attribute__ ((packed)); -#define GRUB_NET_BOOTP_RFC1048_MAGIC 0x63825363L +#define GRUB_NET_BOOTP_RFC1048_MAGIC_0 0x63 +#define GRUB_NET_BOOTP_RFC1048_MAGIC_1 0x82 +#define GRUB_NET_BOOTP_RFC1048_MAGIC_2 0x53 +#define GRUB_NET_BOOTP_RFC1048_MAGIC_3 0x63 struct grub_net_network_level_interface * grub_net_configure_by_dhcp_ack (const char *name, From 14f0752dcf5f55f9b50f0b6dce3362d53b180cce Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 22:37:49 +0200 Subject: [PATCH 355/406] Print MAC address when listing cards --- grub-core/net/net.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 560fa7a31..34148f52c 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -576,9 +576,10 @@ grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)), struct grub_net_card *card; FOR_NET_CARDS(card) { - grub_printf ("%s ", card->name); + char buf[MAX_STR_HWADDR_LEN]; + hwaddr_to_str (&card->default_address, buf); + grub_printf ("%s %s\n", card->name, buf); } - grub_printf ("\n"); return GRUB_ERR_NONE; } From f8614119a02110e8ccd69499b5a03147e9535372 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 22:38:43 +0200 Subject: [PATCH 356/406] Few ofnet cleanups --- grub-core/net/drivers/ieee1275/ofnet.c | 47 ++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 2c264edb1..48c3cd635 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 @@ -37,7 +55,8 @@ card_close (struct grub_net_card *dev) } static grub_err_t -send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) +send_card_buffer (const struct grub_net_card *dev, + struct grub_net_buff *pack) { int actual; int status; @@ -52,7 +71,8 @@ send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) } static grub_ssize_t -get_card_packet (struct grub_net_card *dev, struct grub_net_buff *nb) +get_card_packet (const struct grub_net_card *dev, + struct grub_net_buff *nb) { int actual, rc; @@ -125,20 +145,33 @@ grub_getbootp_real (void) static void grub_ofnet_findcards (void) { - struct grub_net_card *card; - grub_ieee1275_phandle_t devhandle; - grub_net_link_level_address_t lla; int i = 0; + auto int search_net_devices (struct grub_ieee1275_devalias *alias); int search_net_devices (struct grub_ieee1275_devalias *alias) { if (!grub_strcmp (alias->type, "network")) { + struct grub_ofnetcard_data *ofdata; + struct grub_net_card *card; + grub_ieee1275_phandle_t devhandle; + grub_net_link_level_address_t lla; + ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data)); + if (!ofdata) + { + grub_print_error (); + return 1; + } card = grub_malloc (sizeof (struct grub_net_card)); - struct grub_ofnetcard_data *ofdata = - grub_malloc (sizeof (struct grub_ofnetcard_data)); + if (!card) + { + grub_free (ofdata); + grub_print_error (); + return 1; + } + ofdata->path = grub_strdup (alias->path); grub_ieee1275_finddevice (ofdata->path, &devhandle); From 9d22909b8561f72a6503a1f26eab9652670db43f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 22:42:04 +0200 Subject: [PATCH 357/406] efinet support --- grub-core/Makefile.core.def | 8 +- grub-core/kern/x86_64/efi/callwrap.S | 14 +++ grub-core/net/drivers/efi/efinet.c | 165 +++++++++++++++++++++++++++ include/grub/efi/api.h | 81 +++++++++++++ 4 files changed, 267 insertions(+), 1 deletion(-) create mode 100644 grub-core/net/drivers/efi/efinet.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 5c3ce99be..ac969e09c 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1588,10 +1588,16 @@ module = { module = { name = ofnet; - ieee1275 = net/drivers/ieee1275/ofnet.c; + common = net/drivers/ieee1275/ofnet.c; enable = ieee1275; }; +module = { + name = efinet; + common = net/drivers/efi/efinet.c; + enable = efi; +}; + module = { name = emunet; emu = net/drivers/emu/emunet.c; diff --git a/grub-core/kern/x86_64/efi/callwrap.S b/grub-core/kern/x86_64/efi/callwrap.S index aae267872..cc2c8aa05 100644 --- a/grub-core/kern/x86_64/efi/callwrap.S +++ b/grub-core/kern/x86_64/efi/callwrap.S @@ -95,6 +95,20 @@ FUNCTION(efi_wrap_6) addq $64, %rsp ret +FUNCTION(efi_wrap_7) + subq $96, %rsp + mov 96+16(%rsp), %rax + mov %rax, 48(%rsp) + mov 96+8(%rsp), %rax + mov %rax, 40(%rsp) + mov %r9, 32(%rsp) + mov %r8, %r9 + mov %rcx, %r8 + mov %rsi, %rcx + call *%rdi + addq $96, %rsp + ret + FUNCTION(efi_wrap_10) subq $96, %rsp mov 96+40(%rsp), %rax diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c new file mode 100644 index 000000000..a6e005601 --- /dev/null +++ b/grub-core/net/drivers/efi/efinet.c @@ -0,0 +1,165 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* GUID. */ +static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID; + + +static grub_err_t +send_card_buffer (const struct grub_net_card *dev, + struct grub_net_buff *pack) +{ + grub_efi_status_t st; + grub_efi_simple_network_t *net = dev->data; + st = efi_call_7 (net->transmit, net, 0, pack->tail - pack->data, + pack->data, NULL, NULL, NULL); + if (st != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_IO, "Couldn't send network packet."); + return GRUB_ERR_NONE; +} + +static grub_ssize_t +get_card_packet (const struct grub_net_card *dev, + struct grub_net_buff *nb) +{ + grub_efi_simple_network_t *net = dev->data; + grub_err_t err; + grub_efi_status_t st; + grub_efi_uintn_t bufsize = 1500; + + err = grub_netbuff_clear (nb); + if (err) + return -1; + + err = grub_netbuff_put (nb, 1500); + if (err) + return -1; + + st = efi_call_7 (net->receive, net, NULL, &bufsize, + nb->data, NULL, NULL, NULL); + if (st == GRUB_EFI_BUFFER_TOO_SMALL) + { + err = grub_netbuff_put (nb, bufsize - 1500); + if (err) + return -1; + st = efi_call_7 (net->receive, net, NULL, &bufsize, + nb->data, NULL, NULL, NULL); + } + if (st != GRUB_EFI_SUCCESS) + { + grub_netbuff_clear (nb); + return -1; + } + err = grub_netbuff_unput (nb, (nb->tail - nb->data) - bufsize); + if (err) + return -1; + + return bufsize; +} + +static struct grub_net_card_driver efidriver = + { + .name = "efinet", + .send = send_card_buffer, + .recv = get_card_packet + }; + + +static void +grub_efinet_findcards (void) +{ + grub_efi_uintn_t num_handles; + grub_efi_handle_t *handles; + grub_efi_handle_t *handle; + int i = 0; + + /* Find handles which support the disk io interface. */ + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &net_io_guid, + 0, &num_handles); + if (! handles) + return; + for (handle = handles; num_handles--; handle++) + { + grub_efi_simple_network_t *net; + struct grub_net_card *card; + + net = grub_efi_open_protocol (*handle, &net_io_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (! net) + /* This should not happen... Why? */ + continue; + + if (net->mode->state == GRUB_EFI_NETWORK_STOPPED + && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS) + continue; + + if (net->mode->state == GRUB_EFI_NETWORK_STOPPED) + continue; + + if (net->mode->state == GRUB_EFI_NETWORK_STARTED + && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS) + continue; + + card = grub_zalloc (sizeof (struct grub_net_card)); + if (!card) + { + grub_print_error (); + grub_free (handles); + return; + } + + card->name = grub_xasprintf ("efinet%d", i++); + card->driver = &efidriver; + card->flags = 0; + card->default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (card->default_address.mac, + net->mode->current_address, + sizeof (card->default_address.mac)); + card->data = net; + + grub_net_card_register (card); + } + grub_free (handles); +} + +GRUB_MOD_INIT(efinet) +{ + grub_efinet_findcards (); +} + +GRUB_MOD_FINI(ofnet) +{ + struct grub_net_card *card; + FOR_NET_CARDS (card) + if (card->driver && !grub_strcmp (card->driver->name, "efinet")) + { + card->driver->fini (card); + card->driver = NULL; + } + grub_net_card_driver_unregister (&efidriver); +} + diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index ded03a1b3..a3dde0eff 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -84,6 +84,11 @@ { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ } +#define GRUB_EFI_SIMPLE_NETWORK_GUID \ + { 0xa19832b9, 0xac25, 0x11d3, \ + { 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + #define GRUB_EFI_DEVICE_PATH_GUID \ { 0x09576e91, 0x6d3f, 0x11d2, \ { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ @@ -1214,6 +1219,74 @@ struct grub_efi_block_io_media }; typedef struct grub_efi_block_io_media grub_efi_block_io_media_t; +typedef grub_uint8_t grub_efi_mac_t[32]; + +struct grub_efi_simple_network_mode +{ + grub_uint32_t state; + grub_uint32_t hwaddr_size; + grub_uint32_t media_header_size; + grub_uint32_t max_packet_size; + grub_uint32_t nvram_size; + grub_uint32_t nvram_access_size; + grub_uint32_t receive_filter_mask; + grub_uint32_t receive_filter_setting; + grub_uint32_t max_mcast_filter_count; + grub_uint32_t mcast_filter_count; + grub_efi_mac_t mcast_filter[16]; + grub_efi_mac_t current_address; + grub_efi_mac_t broadcast_address; + grub_efi_mac_t permanent_address; + grub_uint8_t if_type; + grub_uint8_t mac_changeable; + grub_uint8_t multitx_supported; + grub_uint8_t media_present_supported; + grub_uint8_t media_present; +}; + +enum + { + GRUB_EFI_NETWORK_STOPPED, + GRUB_EFI_NETWORK_STARTED, + GRUB_EFI_NETWORK_INITIALIZED, + }; + +struct grub_efi_simple_network +{ + grub_uint64_t revision; + grub_efi_status_t (*start) (struct grub_efi_simple_network *this); + void (*stop) (void); + grub_efi_status_t (*initialize) (struct grub_efi_simple_network *this, + grub_efi_uintn_t extra_rx, + grub_efi_uintn_t extra_tx); + void (*reset) (void); + void (*shutdown) (void); + void (*receive_filters) (void); + void (*station_address) (void); + void (*statistics) (void); + void (*mcastiptomac) (void); + void (*nvdata) (void); + void (*getstatus) (void); + grub_efi_status_t (*transmit) (struct grub_efi_simple_network *this, + grub_efi_uintn_t header_size, + grub_efi_uintn_t buffer_size, + void *buffer, + grub_efi_mac_t *src_addr, + grub_efi_mac_t *dest_addr, + grub_efi_uint16_t *protocol); + grub_efi_status_t (*receive) (struct grub_efi_simple_network *this, + grub_efi_uintn_t *header_size, + grub_efi_uintn_t *buffer_size, + void *buffer, + grub_efi_mac_t *src_addr, + grub_efi_mac_t *dest_addr, + grub_uint16_t *protocol); + void (*waitforpacket) (void); + struct grub_efi_simple_network_mode *mode; +}; +typedef struct grub_efi_simple_network grub_efi_simple_network_t; + + struct grub_efi_block_io { grub_efi_uint64_t revision; @@ -1243,6 +1316,7 @@ typedef struct grub_efi_block_io grub_efi_block_io_t; #define efi_call_4(func, a, b, c, d) func(a, b, c, d) #define efi_call_5(func, a, b, c, d, e) func(a, b, c, d, e) #define efi_call_6(func, a, b, c, d, e, f) func(a, b, c, d, e, f) +#define efi_call_7(func, a, b, c, d, e, f, g) func(a, b, c, d, e, f, g) #define efi_call_10(func, a, b, c, d, e, f, g, h, i, j) func(a, b, c, d, e, f, g, h, i, j) #else @@ -1264,6 +1338,9 @@ typedef struct grub_efi_block_io grub_efi_block_io_t; #define efi_call_6(func, a, b, c, d, e, f) \ efi_wrap_6(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f) +#define efi_call_7(func, a, b, c, d, e, f, g) \ + efi_wrap_7(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ + (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f, (grub_uint64_t) g) #define efi_call_10(func, a, b, c, d, e, f, g, h, i, j) \ efi_wrap_10(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f, (grub_uint64_t) g, \ @@ -1285,6 +1362,10 @@ grub_uint64_t EXPORT_FUNC(efi_wrap_6) (void *func, grub_uint64_t arg1, grub_uint64_t arg2, grub_uint64_t arg3, grub_uint64_t arg4, grub_uint64_t arg5, grub_uint64_t arg6); +grub_uint64_t EXPORT_FUNC(efi_wrap_7) (void *func, grub_uint64_t arg1, + grub_uint64_t arg2, grub_uint64_t arg3, + grub_uint64_t arg4, grub_uint64_t arg5, + grub_uint64_t arg6, grub_uint64_t arg7); grub_uint64_t EXPORT_FUNC(efi_wrap_10) (void *func, grub_uint64_t arg1, grub_uint64_t arg2, grub_uint64_t arg3, grub_uint64_t arg4, grub_uint64_t arg5, From 0ff2c51b82c629e93fff4cc53c129b4d05a73667 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 22:47:05 +0200 Subject: [PATCH 358/406] mknetdir support for EFI --- util/grub-mknetdir.in | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in index a36e33cab..52598a8c9 100644 --- a/util/grub-mknetdir.in +++ b/util/grub-mknetdir.in @@ -48,6 +48,9 @@ pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc ppc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/powerpc-ieee1275 sparc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/sparc64-ieee1275 i386_ieee1275_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-ieee1275 +efi32_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-efi +efi64_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/x86_64-efi +itanium_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/ia64-efi # Usage: usage # Print the usage. @@ -210,6 +213,9 @@ process_input_dir () *-ieee1275) mkimage_target="${platform}"; netmodules="ofnet"; ext=elf ;; + *-efi) mkimage_target="${platform}"; + netmodules="efinet"; + ext=efi ;; *) echo Unsupported platform ${platform}; exit 1;; esac @@ -235,6 +241,15 @@ if [ "${override_dir}" = "" ] ; then if test -e "${i386_ieee1275_dir}" ; then process_input_dir "${i386_ieee1275_dir}" i386-ieee1275 fi + if test -e "${efi32_dir}" ; then + process_input_dir "${efi32_dir}" i386-efi + fi + if test -e "${efi64_dir}" ; then + process_input_dir "${efi64_dir}" x86_64-efi + fi + if test -e "${itanium_dir}" ; then + process_input_dir "${itanium_dir}" ia64-efi + fi else source "${override_dir}"/modinfo.sh process_input_dir "${override_dir}" ${grub_modinfo_target_cpu}-${grub_modinfo_platform} From 59b455fceaee233e7221831e520c2dd76d42a466 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 06:31:25 +0200 Subject: [PATCH 359/406] Fix incorrect ISR PXE calls --- grub-core/net/drivers/i386/pc/pxe.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index 084cdb876..144df964c 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -165,7 +165,10 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), isr->func_flag = GRUB_PXE_ISR_IN_START; grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_OURS) - return -1; + { + in_progress = 0; + return -1; + } grub_memset (isr, 0, sizeof (*isr)); isr->func_flag = GRUB_PXE_ISR_IN_PROCESS; grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); @@ -180,7 +183,10 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), while (isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE) { if (isr->status || isr->func_flag == GRUB_PXE_ISR_OUT_DONE) - return -1; + { + in_progress = 0; + return -1; + } grub_memset (isr, 0, sizeof (*isr)); isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT; grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); @@ -198,11 +204,15 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT; grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE) - return -1; + { + in_progress = 1; + return -1; + } grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len); ptr += isr->buffer_len; } + in_progress = 1; return len; } From ca80309d32c9d8890d5a16888eac80043a9a16ec Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 08:40:17 +0200 Subject: [PATCH 360/406] * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer): Fix prototype. (get_card_packet): Likewise. --- ChangeLog | 6 ++++++ grub-core/net/drivers/ieee1275/ofnet.c | 5 ++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index bd6e311bd..62976120f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer): Fix + prototype. + (get_card_packet): Likewise. + 2011-06-26 Yves Blusseau Display the path of the file when file is not found diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 2c264edb1..0394e0dc0 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -37,7 +37,7 @@ card_close (struct grub_net_card *dev) } static grub_err_t -send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) +send_card_buffer (const struct grub_net_card *dev, struct grub_net_buff *pack) { int actual; int status; @@ -52,9 +52,8 @@ send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) } static grub_ssize_t -get_card_packet (struct grub_net_card *dev, struct grub_net_buff *nb) +get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb) { - int actual, rc; struct grub_ofnetcard_data *data = dev->data; grub_uint64_t start_time; From 41bec7fec9b8a56172ab99997d5c86de9cffd405 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 08:43:13 +0200 Subject: [PATCH 361/406] * grub-core/disk/ahci.c (grub_ahci_readwrite_real): Use proper definitions for dprintf. * grub-core/disk/pata.c (grub_pata_readwrite): Likewise. --- ChangeLog | 6 ++++++ grub-core/disk/ahci.c | 3 ++- grub-core/disk/pata.c | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 62976120f..df640a0ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/disk/ahci.c (grub_ahci_readwrite_real): Use proper + definitions for dprintf. + * grub-core/disk/pata.c (grub_pata_readwrite): Likewise. + 2011-06-27 Vladimir Serbinenko * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer): Fix diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 0f355aa53..415004fcf 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -590,7 +590,8 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, dev->command_table[0].prdt[0].size = (parms->size + (parms->size & 1) - 1) | GRUB_AHCI_INTERRUPT_ON_COMPLETE; - grub_dprintf ("ahci", "PRDT = %" PRIxGRUB_UINT64_T ", %x, %x (%x)\n", + grub_dprintf ("ahci", "PRDT = %" PRIxGRUB_UINT64_T ", %x, %x (%" + PRIuGRUB_SIZE ")\n", dev->command_table[0].prdt[0].data_base, dev->command_table[0].prdt[0].unused, dev->command_table[0].prdt[0].size, diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index 1cb42d04b..ac3b91a41 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -156,7 +156,8 @@ grub_pata_readwrite (struct grub_ata *disk, parms->taskfile.cmd, parms->taskfile.features, parms->taskfile.sectors); - grub_dprintf ("pata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%d\n", + grub_dprintf ("pata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%" + PRIuGRUB_SIZE "\n", parms->taskfile.lba_high, parms->taskfile.lba_mid, parms->taskfile.lba_low, parms->size); From 9fc9ce3795196effead800fecffff70c0b3415bd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 08:54:55 +0200 Subject: [PATCH 362/406] Coreboot video support. * grub-core/Makefile.core.def (vga): Extend to coreboot and multiboot. (vbe): Likewise. * grub-core/kern/i386/coreboot/startup.S: Include int.S. * grub-core/kern/i386/pc/startup.S (grub_bios_interrupt): Moved from here ... * grub-core/kern/i386/int.S: ... here. * grub-core/video/i386/pc/vbe.c: Updated includes. * grub-core/video/i386/pc/vga.c: Likewise. * include/grub/i386/coreboot/memory.h (GRUB_MEMORY_MACHINE_SCRATCH_ADDR): New definition. (GRUB_MEMORY_MACHINE_SCRATCH_SEG): Likewise. (GRUB_MEMORY_MACHINE_SCRATCH_SIZE): Likewise. * include/grub/i386/pc/int.h (GRUB_CPU_INT_FLAGS_DEFAULT) [!PCBIOS]: Disable interrupts. * include/grub/i386/pc/vga.h: Removed. All users updated. --- ChangeLog | 20 ++++ grub-core/Makefile.am | 2 + grub-core/Makefile.core.def | 8 +- grub-core/kern/i386/coreboot/startup.S | 1 + grub-core/kern/i386/int.S | 140 +++++++++++++++++++++++++ grub-core/kern/i386/pc/startup.S | 100 +----------------- grub-core/video/i386/pc/vbe.c | 7 +- grub-core/video/i386/pc/vga.c | 5 +- include/grub/i386/coreboot/memory.h | 4 + include/grub/i386/pc/int.h | 5 + include/grub/i386/pc/vga.h | 28 ----- 11 files changed, 184 insertions(+), 136 deletions(-) create mode 100644 grub-core/kern/i386/int.S delete mode 100644 include/grub/i386/pc/vga.h diff --git a/ChangeLog b/ChangeLog index df640a0ef..311e65b05 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2011-06-27 Vladimir Serbinenko + + Coreboot video support. + + * grub-core/Makefile.core.def (vga): Extend to coreboot and multiboot. + (vbe): Likewise. + * grub-core/kern/i386/coreboot/startup.S: Include int.S. + * grub-core/kern/i386/pc/startup.S (grub_bios_interrupt): Moved from + here ... + * grub-core/kern/i386/int.S: ... here. + * grub-core/video/i386/pc/vbe.c: Updated includes. + * grub-core/video/i386/pc/vga.c: Likewise. + * include/grub/i386/coreboot/memory.h + (GRUB_MEMORY_MACHINE_SCRATCH_ADDR): New definition. + (GRUB_MEMORY_MACHINE_SCRATCH_SEG): Likewise. + (GRUB_MEMORY_MACHINE_SCRATCH_SIZE): Likewise. + * include/grub/i386/pc/int.h (GRUB_CPU_INT_FLAGS_DEFAULT) [!PCBIOS]: + Disable interrupts. + * include/grub/i386/pc/vga.h: Removed. All users updated. + 2011-06-27 Vladimir Serbinenko * grub-core/disk/ahci.c (grub_ahci_readwrite_real): Use proper diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index a8862b309..c3ecba9cf 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -100,10 +100,12 @@ endif if COND_i386_coreboot KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h endif if COND_i386_multiboot KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h endif if COND_i386_qemu diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 927718359..7a0536b97 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1454,8 +1454,10 @@ module = { module = { name = vga; - i386_pc = video/i386/pc/vga.c; + common = video/i386/pc/vga.c; enable = i386_pc; + enable = i386_coreboot; + enable = i386_multiboot; }; module = { @@ -1533,8 +1535,10 @@ module = { module = { name = vbe; - i386_pc = video/i386/pc/vbe.c; + common = video/i386/pc/vbe.c; enable = i386_pc; + enable = i386_coreboot; + enable = i386_multiboot; }; module = { diff --git a/grub-core/kern/i386/coreboot/startup.S b/grub-core/kern/i386/coreboot/startup.S index cac023ddf..07c5437c0 100644 --- a/grub-core/kern/i386/coreboot/startup.S +++ b/grub-core/kern/i386/coreboot/startup.S @@ -87,3 +87,4 @@ codestart: */ #include "../realmode.S" +#include "../int.S" diff --git a/grub-core/kern/i386/int.S b/grub-core/kern/i386/int.S new file mode 100644 index 000000000..58ccfdaab --- /dev/null +++ b/grub-core/kern/i386/int.S @@ -0,0 +1,140 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + +FUNCTION(grub_bios_interrupt) + pushf + cli +#ifndef GRUB_MACHINE_PCBIOS + sidt protidt +#endif + popf + pushl %ebp + pushl %ecx + pushl %eax + pushl %ebx + pushl %esi + pushl %edi + pushl %edx + + movb %al, intno + movl (%edx), %eax + movl %eax, LOCAL(bios_register_eax) + movw 4(%edx), %ax + movw %ax, LOCAL(bios_register_es) + movw 6(%edx), %ax + movw %ax, LOCAL(bios_register_ds) + movw 8(%edx), %ax + movw %ax, LOCAL(bios_register_flags) + + movl 12(%edx), %ebx + movl 16(%edx), %ecx + movl 20(%edx), %edi + movl 24(%edx), %esi + movl 28(%edx), %edx + + call prot_to_real + .code16 + pushf + cli +#ifndef GRUB_MACHINE_PCBIOS + lidt realidt +#endif + + mov %ds, %ax + push %ax + + /* movw imm16, %ax*/ + .byte 0xb8 +LOCAL(bios_register_es): + .short 0 + movw %ax, %es + /* movw imm16, %ax*/ + .byte 0xb8 +LOCAL(bios_register_ds): + .short 0 + movw %ax, %ds + + /* movw imm16, %ax*/ + .byte 0xb8 +LOCAL(bios_register_flags): + .short 0 + push %ax + popf + + /* movl imm32, %eax*/ + .byte 0x66, 0xb8 +LOCAL(bios_register_eax): + .long 0 + + /* int imm8. */ + .byte 0xcd +intno: + .byte 0 + + movl %eax, %cs:LOCAL(bios_register_eax) + movw %ds, %ax + movw %ax, %cs:LOCAL(bios_register_ds) + pop %ax + mov %ax, %ds + pushf + pop %ax + movw %ax, LOCAL(bios_register_flags) + mov %es, %ax + movw %ax, LOCAL(bios_register_es) + + popf + DATA32 call real_to_prot + .code32 + + popl %eax + + movl %ebx, 12(%eax) + movl %ecx, 16(%eax) + movl %edi, 20(%eax) + movl %esi, 24(%eax) + movl %edx, 28(%eax) + + movl %eax, %edx + + movl LOCAL(bios_register_eax), %eax + movl %eax, (%edx) + movw LOCAL(bios_register_es), %ax + movw %ax, 4(%edx) + movw LOCAL(bios_register_ds), %ax + movw %ax, 6(%edx) + movw LOCAL(bios_register_flags), %ax + movw %ax, 8(%edx) + + popl %edi + popl %esi + popl %ebx + popl %eax + popl %ecx + popl %ebp +#ifndef GRUB_MACHINE_PCBIOS + lidt protidt +#endif + ret +#ifndef GRUB_MACHINE_PCBIOS +realidt: + .word 0x100 + .long 0 +protidt: + .word 0 + .long 0 +#endif diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index e78a0aa9a..0fe114add 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -910,102 +910,4 @@ FUNCTION(grub_pxe_call) popl %ebp ret -FUNCTION(grub_bios_interrupt) - pushl %ebp - pushl %ecx - pushl %eax - pushl %ebx - pushl %esi - pushl %edi - pushl %edx - - movb %al, intno - movl (%edx), %eax - movl %eax, LOCAL(bios_register_eax) - movw 4(%edx), %ax - movw %ax, LOCAL(bios_register_es) - movw 6(%edx), %ax - movw %ax, LOCAL(bios_register_ds) - movw 8(%edx), %ax - movw %ax, LOCAL(bios_register_flags) - - movl 12(%edx), %ebx - movl 16(%edx), %ecx - movl 20(%edx), %edi - movl 24(%edx), %esi - movl 28(%edx), %edx - - call prot_to_real - .code16 - - mov %ds, %ax - push %ax - - /* movw imm16, %ax*/ - .byte 0xb8 -LOCAL(bios_register_es): - .short 0 - movw %ax, %es - /* movw imm16, %ax*/ - .byte 0xb8 -LOCAL(bios_register_ds): - .short 0 - movw %ax, %ds - - /* movw imm16, %ax*/ - .byte 0xb8 -LOCAL(bios_register_flags): - .short 0 - push %ax - popf - - /* movl imm32, %eax*/ - .byte 0x66, 0xb8 -LOCAL(bios_register_eax): - .long 0 - - /* int imm8. */ - .byte 0xcd -intno: - .byte 0 - - movl %eax, %cs:LOCAL(bios_register_eax) - movw %ds, %ax - movw %ax, %cs:LOCAL(bios_register_ds) - pop %ax - mov %ax, %ds - pushf - pop %ax - movw %ax, LOCAL(bios_register_flags) - mov %es, %ax - movw %ax, LOCAL(bios_register_es) - - DATA32 call real_to_prot - .code32 - - popl %eax - - movl %ebx, 12(%eax) - movl %ecx, 16(%eax) - movl %edi, 20(%eax) - movl %esi, 24(%eax) - movl %edx, 28(%eax) - - movl %eax, %edx - - movl LOCAL(bios_register_eax), %eax - movl %eax, (%edx) - movw LOCAL(bios_register_es), %ax - movw %ax, 4(%edx) - movw LOCAL(bios_register_ds), %ax - movw %ax, 6(%edx) - movw LOCAL(bios_register_flags), %ax - movw %ax, 8(%edx) - - popl %edi - popl %esi - popl %ebx - popl %eax - popl %ecx - popl %ebp - ret +#include "../int.S" diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index a109bcf43..c11b9a627 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -20,15 +20,14 @@ #include #include -#include -#include +#include #include #include #include #include #include #include -#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -377,7 +376,7 @@ grub_vbe_set_video_mode (grub_uint32_t vbe_mode, if (vbe_mode < 0x100) { /* If this is not a VESA mode, guess address. */ - framebuffer.ptr = (grub_uint8_t *) GRUB_MEMORY_MACHINE_VGA_ADDR; + framebuffer.ptr = (grub_uint8_t *) 0xa0000; } else { diff --git a/grub-core/video/i386/pc/vga.c b/grub-core/video/i386/pc/vga.c index fe387a26b..08c9ca37d 100644 --- a/grub-core/video/i386/pc/vga.c +++ b/grub-core/video/i386/pc/vga.c @@ -18,8 +18,7 @@ #define grub_video_render_target grub_video_fbrender_target -#include -#include +#include #include #include #include @@ -34,7 +33,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define VGA_WIDTH 640 #define VGA_HEIGHT 350 -#define VGA_MEM ((grub_uint8_t *) GRUB_MEMORY_MACHINE_VGA_ADDR) +#define VGA_MEM ((grub_uint8_t *) 0xa0000) #define PAGE_OFFSET(x) ((x) * (VGA_WIDTH * VGA_HEIGHT / 8)) static unsigned char text_mode; diff --git a/include/grub/i386/coreboot/memory.h b/include/grub/i386/coreboot/memory.h index 0642280b9..2859b1d7c 100644 --- a/include/grub/i386/coreboot/memory.h +++ b/include/grub/i386/coreboot/memory.h @@ -28,6 +28,10 @@ #include #endif +#define GRUB_MEMORY_MACHINE_SCRATCH_ADDR 0x68000 +#define GRUB_MEMORY_MACHINE_SCRATCH_SEG (GRUB_MEMORY_MACHINE_SCRATCH_ADDR >> 4) +#define GRUB_MEMORY_MACHINE_SCRATCH_SIZE 0x10000 + #define GRUB_MEMORY_MACHINE_LOWER_USABLE 0x9fc00 /* 640 kiB - 1 kiB */ #define GRUB_MEMORY_MACHINE_UPPER_START 0x100000 /* 1 MiB */ diff --git a/include/grub/i386/pc/int.h b/include/grub/i386/pc/int.h index de23775d0..337752587 100644 --- a/include/grub/i386/pc/int.h +++ b/include/grub/i386/pc/int.h @@ -45,7 +45,12 @@ struct grub_bios_int_registers #define GRUB_CPU_INT_FLAGS_INTERRUPT 0x200 #define GRUB_CPU_INT_FLAGS_DIRECTION 0x400 #define GRUB_CPU_INT_FLAGS_OVERFLOW 0x800 +#ifdef GRUB_MACHINE_PCBIOS #define GRUB_CPU_INT_FLAGS_DEFAULT GRUB_CPU_INT_FLAGS_INTERRUPT +#else +#define GRUB_CPU_INT_FLAGS_DEFAULT 0 +#endif + void EXPORT_FUNC (grub_bios_interrupt) (grub_uint8_t intno, struct grub_bios_int_registers *regs); diff --git a/include/grub/i386/pc/vga.h b/include/grub/i386/pc/vga.h deleted file mode 100644 index ecc169022..000000000 --- a/include/grub/i386/pc/vga.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003,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 . - */ - -#ifndef GRUB_VGA_MACHINE_HEADER -#define GRUB_VGA_MACHINE_HEADER 1 - -#include -#include - -/* The VGA (at the beginning of upper memory). */ -#define GRUB_MEMORY_MACHINE_VGA_ADDR GRUB_MEMORY_MACHINE_UPPER - -#endif /* ! GRUB_VGA_MACHINE_HEADER */ From efff4b1cc3e390533a7333420cf980d304bd10bc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 09:06:15 +0200 Subject: [PATCH 363/406] * util/grub-mkrescue.in: Rename "ata" to "pata" and add ahci when necessary. --- ChangeLog | 5 +++++ util/grub-mkrescue.in | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 311e65b05..ca4145e33 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-27 Vladimir Serbinenko + + * util/grub-mkrescue.in: Rename "ata" to "pata" and add ahci when + necessary. + 2011-06-27 Vladimir Serbinenko Coreboot video support. diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in index 8367c4dd4..f054c43a9 100644 --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in @@ -275,7 +275,7 @@ if test -e "${pc_dir}" ; then fi # build multiboot core.img -make_image "${multiboot_dir}" i386-multiboot "${iso9660_dir}/boot/multiboot.img" "ata at_keyboard" +make_image "${multiboot_dir}" i386-multiboot "${iso9660_dir}/boot/multiboot.img" "pata ahci at_keyboard" if test -e "${efi64_dir}" || test -e "${efi32_dir}"; then efi_dir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 @@ -296,11 +296,11 @@ if test -e "${efi64_dir}" || test -e "${efi32_dir}"; then grub_mkisofs_arguments="${grub_mkisofs_arguments} --efi-boot efi.img" fi -make_image "${qemu_dir}" i386-qemu "${iso9660_dir}/boot/qemu.img" "ata at_keyboard" +make_image "${qemu_dir}" i386-qemu "${iso9660_dir}/boot/qemu.img" "pata at_keyboard" if [ -e "${iso9660_dir}/boot/qemu.img" ] && [ -d "${rom_directory}" ]; then cp "${iso9660_dir}/boot/qemu.img" "${rom_directory}/qemu.img" fi -make_image "${coreboot_dir}" i386-coreboot "${iso9660_dir}/boot/coreboot.elf" "ata at_keyboard" +make_image "${coreboot_dir}" i386-coreboot "${iso9660_dir}/boot/coreboot.elf" "pata ahci at_keyboard" if [ -e "${iso9660_dir}/boot/coreboot.elf" ] && [ -d "${rom_directory}" ]; then cp "${iso9660_dir}/boot/coreboot.elf" "${rom_directory}/coreboot.elf" fi From 1e3d9b8612a3f2a4c907b98d6465fcf4e7a53c4e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 10:12:35 +0200 Subject: [PATCH 364/406] * grub-core/disk/scsi.c (grub_scsi_read): Limit SCSI reads to 32K because of underlying system restrictions. --- ChangeLog | 5 +++++ grub-core/disk/scsi.c | 33 ++++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index ca4145e33..360842279 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/disk/scsi.c (grub_scsi_read): Limit SCSI reads to 32K + because of underlying system restrictions. + 2011-06-27 Vladimir Serbinenko * util/grub-mkrescue.in: Rename "ata" to "pata" and add ahci when diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index 35b8525c2..902564164 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -524,17 +524,36 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector, scsi = disk->data; - /* Depending on the type, select a read function. */ - switch (scsi->devtype) + while (size) { - case grub_scsi_devtype_direct: - return grub_scsi_read10 (disk, sector, size, buf); + /* PATA doesn't support more than 32K reads. + Not sure about AHCI and USB. If it's confirmed that either of + them can do bigger reads reliably this value can be moved to 'scsi' + structure. */ + grub_size_t len = 32768 >> disk->log_sector_size; + grub_err_t err; + if (len > size) + len = size; + /* Depending on the type, select a read function. */ + switch (scsi->devtype) + { + case grub_scsi_devtype_direct: + err = grub_scsi_read10 (disk, sector, len, buf); + if (err) + return err; + break; - case grub_scsi_devtype_cdrom: - return grub_scsi_read12 (disk, sector, size, buf); + case grub_scsi_devtype_cdrom: + err = grub_scsi_read12 (disk, sector, len, buf); + if (err) + return err; + break; + } + size -= len; + sector += len; + buf += len << disk->log_sector_size; } - /* XXX: Never reached. */ return GRUB_ERR_NONE; #if 0 /* Workaround - it works - but very slowly, from some reason From f9b75e8a67f54b425b64c62ea68d7ced88c566bd Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 27 Jun 2011 10:47:02 +0100 Subject: [PATCH 365/406] * grub-core/commands/videoinfo.c (hook): Indicate current video mode with `*'. (grub_cmd_videoinfo): Fetch current video mode. --- ChangeLog | 6 ++++++ grub-core/commands/videoinfo.c | 25 +++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 360842279..1aabd6b18 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-27 Colin Watson + + * grub-core/commands/videoinfo.c (hook): Indicate current video mode + with `*'. + (grub_cmd_videoinfo): Fetch current video mode. + 2011-06-27 Vladimir Serbinenko * grub-core/disk/scsi.c (grub_scsi_read): Limit SCSI reads to 32K diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index 3e0c1a12e..91a87fecc 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -28,6 +28,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); static unsigned height, width, depth; +static struct grub_video_mode_info *current_mode; static int hook (const struct grub_video_mode_info *info) @@ -41,7 +42,13 @@ hook (const struct grub_video_mode_info *info) if (info->mode_number == GRUB_VIDEO_MODE_NUMBER_INVALID) grub_printf (" "); else - grub_printf (" 0x%03x ", info->mode_number); + { + if (current_mode && info->mode_number == current_mode->mode_number) + grub_printf ("*"); + else + grub_printf (" "); + grub_printf (" 0x%03x ", info->mode_number); + } grub_printf ("%4d x %4d x %2d ", info->width, info->height, info->bpp); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT) @@ -122,6 +129,8 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), FOR_VIDEO_ADAPTERS (adapter) { + struct grub_video_mode_info info; + grub_printf ("Adapter '%s':\n", adapter->name); if (!adapter->iterate) @@ -130,7 +139,17 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), continue; } - if (adapter->id != id) + current_mode = NULL; + + if (adapter->id == id) + { + if (grub_video_get_info (&info) == GRUB_ERR_NONE) + current_mode = &info; + else + /* Don't worry about errors. */ + grub_errno = GRUB_ERR_NONE; + } + else { if (adapter->init ()) { @@ -145,6 +164,8 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), adapter->iterate (hook); + current_mode = NULL; + if (adapter->id != id) { if (adapter->fini ()) From b6f945dccbf99c7126cca5b01f4cea807ccffc9e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 12:13:21 +0200 Subject: [PATCH 366/406] * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer) Use right type in pointers on sparc64. (get_card_packet): Likewise. --- ChangeLog | 6 ++++++ grub-core/net/drivers/ieee1275/ofnet.c | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1aabd6b18..1a3237f88 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer) Use right + type in pointers on sparc64. + (get_card_packet): Likewise. + 2011-06-27 Colin Watson * grub-core/commands/videoinfo.c (hook): Indicate current video mode diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 0394e0dc0..b5bb03dc8 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -39,7 +39,7 @@ card_close (struct grub_net_card *dev) static grub_err_t send_card_buffer (const struct grub_net_card *dev, struct grub_net_buff *pack) { - int actual; + grub_ssize_t actual; int status; struct grub_ofnetcard_data *data = dev->data; @@ -54,7 +54,8 @@ send_card_buffer (const struct grub_net_card *dev, struct grub_net_buff *pack) static grub_ssize_t get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb) { - int actual, rc; + grub_ssize_t actual; + int rc; struct grub_ofnetcard_data *data = dev->data; grub_uint64_t start_time; From b28c56559b446bdc824fe650a641aa9e11923448 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 12:16:00 +0200 Subject: [PATCH 367/406] * util/ieee1275/grub-ofpathname.c (main): Handle --help and --version so that help2man doesn't fail. --- ChangeLog | 5 +++++ util/ieee1275/grub-ofpathname.c | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1a3237f88..37446af70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-27 Vladimir Serbinenko + + * util/ieee1275/grub-ofpathname.c (main): Handle --help and --version + so that help2man doesn't fail. + 2011-06-27 Vladimir Serbinenko * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer) Use right diff --git a/util/ieee1275/grub-ofpathname.c b/util/ieee1275/grub-ofpathname.c index 3ac6fce8b..a9bc2cfda 100644 --- a/util/ieee1275/grub-ofpathname.c +++ b/util/ieee1275/grub-ofpathname.c @@ -32,11 +32,16 @@ int main(int argc, char **argv) grub_util_init_nls (); - if (argc != 2) + if (argc != 2 || strcmp (argv[1], "--help") == 0) { printf("Usage: %s DEVICE\n", program_name); return 1; } + if (strcmp (argv[1], "--version") == 0) + { + printf ("%s\n", PACKAGE_STRING); + return 1; + } of_path = grub_util_devname_to_ofpath (argv[1]); printf("%s\n", of_path); From bdea37983323f19d0cf8d2ef529d4d0f88ba2d81 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 12:18:44 +0200 Subject: [PATCH 368/406] * grub-core/lib/relocator.c (malloc_in_range): Fix a memory corruption when handling leftovers. --- ChangeLog | 5 +++++ grub-core/lib/relocator.c | 13 +++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 37446af70..e35b7c7ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/lib/relocator.c (malloc_in_range): Fix a memory corruption + when handling leftovers. + 2011-06-27 Vladimir Serbinenko * util/ieee1275/grub-ofpathname.c (main): Handle --help and --version diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c index 6eb20b865..aa404731f 100644 --- a/grub-core/lib/relocator.c +++ b/grub-core/lib/relocator.c @@ -764,6 +764,9 @@ malloc_in_range (struct grub_relocator *rel, int inreg = 0, regbeg = 0, ncol = 0; #if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS int fwin = 0, fwb = 0, fwlefto = 0; +#endif +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + int last_lo = 0; #endif int last_start = 0; for (j = 0; j < N; j++) @@ -855,7 +858,7 @@ malloc_in_range (struct grub_relocator *rel, unsigned offend = alloc_end % GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; struct grub_relocator_fw_leftover *lo - = events[last_start].leftover; + = events[last_lo].leftover; lo->freebytes[offstart / 8] &= ((1 << (8 - (start % 8))) - 1); grub_memset (lo->freebytes + (offstart + 7) / 8, 0, @@ -910,6 +913,7 @@ malloc_in_range (struct grub_relocator *rel, #if GRUB_RELOCATOR_HAVE_LEFTOVERS case REG_LEFTOVER_START: fwlefto++; + last_lo = j; break; case REG_LEFTOVER_END: @@ -1009,7 +1013,8 @@ malloc_in_range (struct grub_relocator *rel, curschu->extra = ne; } } -#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS if (!oom && typepre == CHUNK_TYPE_FIRMWARE) { grub_addr_t fstart, fend; @@ -1021,7 +1026,6 @@ malloc_in_range (struct grub_relocator *rel, = ALIGN_UP (alloc_end, GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); -#if GRUB_RELOCATOR_HAVE_LEFTOVERS { struct grub_relocator_fw_leftover *lo1 = NULL; struct grub_relocator_fw_leftover *lo2 = NULL; @@ -1081,10 +1085,8 @@ malloc_in_range (struct grub_relocator *rel, curschu->pre = lo1; curschu->post = lo2; } -#endif } -#if GRUB_RELOCATOR_HAVE_LEFTOVERS if (typepre == CHUNK_TYPE_LEFTOVER) { curschu->pre = events[last_start].leftover; @@ -1092,7 +1094,6 @@ malloc_in_range (struct grub_relocator *rel, } #endif -#endif if (!oom) cural++; else From 5ebaad7eec21a1d209d781b8c0b17f993a238380 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 12:28:47 +0200 Subject: [PATCH 369/406] * include/grub/loader.h (grub_loader_unregister_preboot_hook): Export. --- ChangeLog | 4 ++++ include/grub/loader.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e35b7c7ff..866e2ccaf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-06-27 Vladimir Serbinenko + + * include/grub/loader.h (grub_loader_unregister_preboot_hook): Export. + 2011-06-27 Vladimir Serbinenko * grub-core/lib/relocator.c (malloc_in_range): Fix a memory corruption diff --git a/include/grub/loader.h b/include/grub/loader.h index c71e8dd10..f38deb96a 100644 --- a/include/grub/loader.h +++ b/include/grub/loader.h @@ -61,6 +61,6 @@ void *EXPORT_FUNC(grub_loader_register_preboot_hook) (grub_err_t (*preboot_func) grub_loader_preboot_hook_prio_t prio); /* Unregister given preboot hook. */ -void grub_loader_unregister_preboot_hook (void *hnd); +void EXPORT_FUNC (grub_loader_unregister_preboot_hook) (void *hnd); #endif /* ! GRUB_LOADER_HEADER */ From 5ff1d945ed89aa6203fdc005a55dbb83b3380ea1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 12:31:37 +0200 Subject: [PATCH 370/406] Implement time command. * grub-core/Makefile.core.def (time): New module. * grub-core/commands/time.c: New file. * grub-core/script/parser.y: Remove "time" keyword. * grub-core/script/yylex.l: Likewise. --- ChangeLog | 9 +++++ grub-core/Makefile.core.def | 5 +++ grub-core/commands/time.c | 68 +++++++++++++++++++++++++++++++++++++ grub-core/script/parser.y | 2 -- grub-core/script/yylex.l | 1 - 5 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 grub-core/commands/time.c diff --git a/ChangeLog b/ChangeLog index 866e2ccaf..4cdbc2b15 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-06-27 Vladimir Serbinenko + + Implement time command. + + * grub-core/Makefile.core.def (time): New module. + * grub-core/commands/time.c: New file. + * grub-core/script/parser.y: Remove "time" keyword. + * grub-core/script/yylex.l: Likewise. + 2011-06-27 Vladimir Serbinenko * include/grub/loader.h (grub_loader_unregister_preboot_hook): Export. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 7a0536b97..b10c16d55 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1641,3 +1641,8 @@ module = { common = commands/keylayouts.c; enable = videomodules; }; + +module = { + name = time; + common = commands/time.c; +}; diff --git a/grub-core/commands/time.c b/grub-core/commands/time.c new file mode 100644 index 000000000..687495964 --- /dev/null +++ b/grub-core/commands/time.c @@ -0,0 +1,68 @@ +/* echo.c - Command to display a line of text */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 + +GRUB_MOD_LICENSE ("GPLv3+"); + + +static grub_err_t +grub_cmd_time (grub_command_t ctxt __attribute__ ((unused)), + int argc, char **args) +{ + grub_command_t cmd; + grub_uint32_t start; + grub_uint32_t end; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "command expected"); + + cmd = grub_command_find (args[0]); + + if (!cmd) + return grub_error (GRUB_ERR_UNKNOWN_COMMAND, "Unknown command `%s'\n", + args[0]); + + start = grub_get_time_ms (); + (cmd->func) (cmd, argc - 1, &args[1]); + end = grub_get_time_ms (); + + grub_printf ("Elapsed time: %d.%03d seconds \n", (end - start) / 1000, + (end - start) % 1000); + + return grub_errno; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(time) +{ + cmd = grub_register_command ("time", grub_cmd_time, + N_("COMMAND [ARGS]"), + N_("Measure time used by COMMAND")); +} + +GRUB_MOD_FINI(time) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/script/parser.y b/grub-core/script/parser.y index 683b3ac4b..cc20b5479 100644 --- a/grub-core/script/parser.y +++ b/grub-core/script/parser.y @@ -74,7 +74,6 @@ %token GRUB_PARSER_TOKEN_THEN "then" %token GRUB_PARSER_TOKEN_UNTIL "until" %token GRUB_PARSER_TOKEN_WHILE "while" -%token GRUB_PARSER_TOKEN_TIME "time" %token GRUB_PARSER_TOKEN_FUNCTION "function" %token GRUB_PARSER_TOKEN_NAME "name" %token GRUB_PARSER_TOKEN_WORD "word" @@ -147,7 +146,6 @@ argument : "case" { $$ = grub_script_add_arglist (state, 0, $1); } | "until" { $$ = grub_script_add_arglist (state, 0, $1); } | "while" { $$ = grub_script_add_arglist (state, 0, $1); } | "function" { $$ = grub_script_add_arglist (state, 0, $1); } - | "time" { $$ = grub_script_add_arglist (state, 0, $1); } | word { $$ = $1; } ; diff --git a/grub-core/script/yylex.l b/grub-core/script/yylex.l index 96f57dbe6..7195a880d 100644 --- a/grub-core/script/yylex.l +++ b/grub-core/script/yylex.l @@ -161,7 +161,6 @@ MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)|(\\\n)) "}" { RECORD; return GRUB_PARSER_TOKEN_RBR; } "[[" { RECORD; return GRUB_PARSER_TOKEN_RSQBR2; } "]]" { RECORD; return GRUB_PARSER_TOKEN_LSQBR2; } -"time" { RECORD; return GRUB_PARSER_TOKEN_TIME; } "case" { RECORD; return GRUB_PARSER_TOKEN_CASE; } "do" { RECORD; return GRUB_PARSER_TOKEN_DO; } "done" { RECORD; return GRUB_PARSER_TOKEN_DONE; } From d0b526b2778db75c5cfd01182de7f3808f466a1a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 13:57:03 +0200 Subject: [PATCH 371/406] * grub-core/loader/i386/bsd.c (grub_bsd_load): Handle relocator failure if it happens. --- ChangeLog | 5 +++++ grub-core/loader/i386/bsd.c | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 4cdbc2b15..c097af2f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/loader/i386/bsd.c (grub_bsd_load): Handle relocator failure + if it happens. + 2011-06-27 Vladimir Serbinenko Implement time command. diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c index 6487dc3df..dffe48257 100644 --- a/grub-core/loader/i386/bsd.c +++ b/grub-core/loader/i386/bsd.c @@ -1322,6 +1322,11 @@ grub_bsd_load (int argc, char *argv[]) goto fail; relocator = grub_relocator_new (); + if (!relocator) + { + grub_file_close (file); + goto fail; + } elf = grub_elf_file (file); if (elf) @@ -1343,7 +1348,7 @@ grub_bsd_load (int argc, char *argv[]) fail: if (grub_errno != GRUB_ERR_NONE) - grub_dl_unref (my_mod); + grub_dl_unref (my_mod); return grub_errno; } From ba7df45ee6be05bb9fd781041f915f112fa8e52c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 14:14:11 +0200 Subject: [PATCH 372/406] Chainloading on coreboot support. * grub-core/Makefile.core.def (chain): Add coreboot. * grub-core/loader/i386/coreboot/chainloader.c: New file. --- ChangeLog | 7 + grub-core/Makefile.core.def | 2 + grub-core/loader/i386/coreboot/chainloader.c | 145 +++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 grub-core/loader/i386/coreboot/chainloader.c diff --git a/ChangeLog b/ChangeLog index c097af2f7..9922f2a2b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-06-27 Vladimir Serbinenko + + Chainloading on coreboot support. + + * grub-core/Makefile.core.def (chain): Add coreboot. + * grub-core/loader/i386/coreboot/chainloader.c: New file. + 2011-06-27 Vladimir Serbinenko * grub-core/loader/i386/bsd.c (grub_bsd_load): Handle relocator failure diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index b10c16d55..faed6cc85 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1298,7 +1298,9 @@ module = { name = chain; efi = loader/efi/chainloader.c; i386_pc = loader/i386/pc/chainloader.c; + i386_coreboot = loader/i386/corepayload.c; enable = i386_pc; + enable = i386_coreboot; enable = efi; }; diff --git a/grub-core/loader/i386/coreboot/chainloader.c b/grub-core/loader/i386/coreboot/chainloader.c new file mode 100644 index 000000000..3f85aa3a9 --- /dev/null +++ b/grub-core/loader/i386/coreboot/chainloader.c @@ -0,0 +1,145 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_addr_t entry; +static struct grub_relocator *relocator = NULL; + +static grub_err_t +grub_chain_boot (void) +{ + struct grub_relocator32_state state; + + grub_video_set_mode ("text", 0, 0); + + state.eip = entry; + return grub_relocator32_boot (relocator, state); +} + +static grub_err_t +grub_chain_unload (void) +{ + grub_relocator_unload (relocator); + relocator = NULL; + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_chain_elf32_hook (Elf32_Phdr * phdr, grub_addr_t * addr, int *do_load) +{ + grub_err_t err; + grub_relocator_chunk_t ch; + + if (phdr->p_type != PT_LOAD) + { + *do_load = 0; + return 0; + } + + *do_load = 1; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + phdr->p_paddr, phdr->p_memsz); + if (err) + return err; + + *addr = (grub_addr_t) get_virtual_current_address (ch); + + return GRUB_ERR_NONE; +} + + +static grub_err_t +grub_cmd_chain (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + grub_err_t err; + grub_file_t file; + grub_elf_t elf; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "filename expected"); + + grub_loader_unset (); + + file = grub_file_open (argv[0]); + if (!file) + return grub_errno; + + relocator = grub_relocator_new (); + if (!relocator) + { + grub_file_close (file); + return grub_errno; + } + + elf = grub_elf_file (file); + if (!elf) + { + grub_relocator_unload (relocator); + relocator = 0; + grub_file_close (file); + } + + if (!grub_elf_is_elf32 (elf)) + { + grub_relocator_unload (relocator); + relocator = 0; + grub_elf_close (elf); + } + + entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF; + + err = grub_elf32_load (elf, grub_chain_elf32_hook, 0, 0); + + grub_elf_close (elf); + if (err) + return err; + + grub_loader_set (grub_chain_boot, grub_chain_unload, 0); + return GRUB_ERR_NONE; +} + +static grub_command_t cmd_chain; + +GRUB_MOD_INIT (chain) +{ + cmd_chain = grub_register_command ("chainloader", grub_cmd_chain, + N_("FILE"), N_("Load another payload")); +} + +GRUB_MOD_FINI (chain) +{ + grub_unregister_command (cmd_chain); + grub_chain_unload (); +} From 5afeb5bdd615f18ef58316132112a3a9b6e4c823 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 19:26:52 +0200 Subject: [PATCH 373/406] * grub-core/disk/pata.c (grub_pata_initialize) [QEMU_MIPS]: Fix a mismerge. --- ChangeLog | 5 +++++ grub-core/disk/pata.c | 8 +++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9922f2a2b..a9dacd42b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/disk/pata.c (grub_pata_initialize) [QEMU_MIPS]: Fix a + mismerge. + 2011-06-27 Vladimir Serbinenko Chainloading on coreboot support. diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index ac3b91a41..95828e8f6 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -438,15 +438,13 @@ grub_pata_initialize (void) } #else static grub_err_t -grub_ata_initialize (void) +grub_pata_initialize (void) { int i; for (i = 0; i < 2; i++) { - grub_ata_device_initialize (i, 0, grub_ata_ioaddress[i], - grub_ata_ioaddress2[i]); - grub_ata_device_initialize (i, 1, grub_ata_ioaddress[i], - grub_ata_ioaddress2[i]); + grub_pata_device_initialize (i, 0, grub_pata_ioaddress[i]); + grub_pata_device_initialize (i, 1, grub_pata_ioaddress[i]); } return 0; } From 8d5d8444bd95338d487e715e9c93fa3328137b9d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 19:30:16 +0200 Subject: [PATCH 374/406] * grub-core/Makefile.core.def (chain): Fix coreboot filename. --- ChangeLog | 4 ++++ grub-core/Makefile.core.def | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a9dacd42b..81d98716d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/Makefile.core.def (chain): Fix coreboot filename. + 2011-06-27 Vladimir Serbinenko * grub-core/disk/pata.c (grub_pata_initialize) [QEMU_MIPS]: Fix a diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index faed6cc85..fd69e9c22 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1298,7 +1298,7 @@ module = { name = chain; efi = loader/efi/chainloader.c; i386_pc = loader/i386/pc/chainloader.c; - i386_coreboot = loader/i386/corepayload.c; + i386_coreboot = loader/i386/coreboot/chainloader.c; enable = i386_pc; enable = i386_coreboot; enable = efi; From 548947916b74f8b4b66f88a4cf08b233fd31047c Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 28 Jun 2011 17:05:41 +0100 Subject: [PATCH 375/406] * grub-core/term/gfxterm.c (grub_virtual_screen_setup): Use default_bg_color rather than black. (grub_gfxterm_fullscreen): Likewise. (grub_gfxterm_background_color_cmd): Save new background color in default_bg_color. --- ChangeLog | 8 ++++++++ grub-core/term/gfxterm.c | 16 +++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 81d98716d..4b8d8f149 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-06-28 Colin Watson + + * grub-core/term/gfxterm.c (grub_virtual_screen_setup): Use + default_bg_color rather than black. + (grub_gfxterm_fullscreen): Likewise. + (grub_gfxterm_background_color_cmd): Save new background color in + default_bg_color. + 2011-06-27 Vladimir Serbinenko * grub-core/Makefile.core.def (chain): Fix coreboot filename. diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c index 9e3d8eeb1..2f8deac18 100644 --- a/grub-core/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -131,6 +131,7 @@ static unsigned int bitmap_width; static unsigned int bitmap_height; static struct grub_video_bitmap *bitmap; static int blend_text_bg; +static grub_video_rgba_color_t default_bg_color = { 0, 0, 0, 0 }; static struct grub_dirty_region dirty_region; @@ -266,7 +267,8 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y, grub_video_set_active_render_target (render_target); - virtual_screen.bg_color_display = grub_video_map_rgba(0, 0, 0, 0); + virtual_screen.bg_color_display = + grub_video_map_rgba_color (default_bg_color); /* Clear out text buffer. */ for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++) @@ -338,8 +340,8 @@ grub_gfxterm_fullscreen (void) double_redraw = mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED && !(mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); - /* Make sure screen is black. */ - color = grub_video_map_rgb (0, 0, 0); + /* Make sure screen is set to the default background color. */ + color = grub_video_map_rgba_color (default_bg_color); grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height); if (double_redraw) { @@ -1189,7 +1191,6 @@ static grub_err_t grub_gfxterm_background_color_cmd (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { - grub_video_rgba_color_t color; struct grub_video_render_target *old_target; if (argc != 1) @@ -1199,7 +1200,7 @@ grub_gfxterm_background_color_cmd (grub_command_t cmd __attribute__ ((unused)), if (grub_video_get_info (NULL) != GRUB_ERR_NONE) return grub_errno; - if (grub_video_parse_color (args[0], &color) != GRUB_ERR_NONE) + if (grub_video_parse_color (args[0], &default_bg_color) != GRUB_ERR_NONE) return grub_errno; /* Destroy existing background bitmap if loaded. */ @@ -1216,9 +1217,10 @@ grub_gfxterm_background_color_cmd (grub_command_t cmd __attribute__ ((unused)), compatible with the text layer. */ grub_video_get_active_render_target (&old_target); grub_video_set_active_render_target (text_layer); - virtual_screen.bg_color = grub_video_map_rgba_color (color); + virtual_screen.bg_color = grub_video_map_rgba_color (default_bg_color); grub_video_set_active_render_target (old_target); - virtual_screen.bg_color_display = grub_video_map_rgba_color (color); + virtual_screen.bg_color_display = + grub_video_map_rgba_color (default_bg_color); blend_text_bg = 1; /* Mark whole screen as dirty. */ From 574618a2e9a1dc8daf46c0e929acb0353f5f0101 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 2 Jul 2011 14:09:36 +0200 Subject: [PATCH 376/406] unify prefix handling across platforms --- grub-core/Makefile.core.def | 5 +- grub-core/boot/i386/pc/diskboot.S | 2 +- grub-core/disk/efi/efidisk.c | 30 +++-- grub-core/kern/efi/init.c | 84 ++---------- grub-core/kern/emu/main.c | 16 +-- grub-core/kern/i386/coreboot/init.c | 5 +- grub-core/kern/i386/efi/init.c | 6 - grub-core/kern/i386/pc/init.c | 78 +++++------ grub-core/kern/ia64/efi/init.c | 6 - grub-core/kern/ieee1275/cmain.c | 4 + grub-core/kern/ieee1275/init.c | 90 ++++++------- grub-core/kern/ieee1275/openfw.c | 5 + grub-core/kern/main.c | 70 ++++++++-- grub-core/kern/mips/init.c | 4 +- grub-core/kern/sparc64/ieee1275/init.c | 174 ------------------------- include/grub/kernel.h | 5 +- include/grub/offsets.h | 4 +- 17 files changed, 189 insertions(+), 399 deletions(-) delete mode 100644 grub-core/kern/sparc64/ieee1275/init.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index ac969e09c..df852e09e 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -102,6 +102,7 @@ kernel = { ieee1275 = kern/ieee1275/mmap.c; ieee1275 = kern/ieee1275/openfw.c; ieee1275 = term/ieee1275/ofconsole.c; + ieee1275 = kern/ieee1275/init.c; terminfoinkernel = term/terminfo.c; terminfoinkernel = term/tparm.c; @@ -153,8 +154,6 @@ kernel = { i386_multiboot = kern/i386/multiboot_mmap.c; i386_multiboot = kern/i386/tsc.c; - i386_ieee1275 = kern/ieee1275/init.c; - mips = kern/mips/cache.S; mips = kern/mips/dl.c; mips = kern/mips/init.c; @@ -179,14 +178,12 @@ kernel = { extra_dist = video/sm712_init.c; mips_loongson = commands/keylayouts.c; - powerpc_ieee1275 = kern/ieee1275/init.c; powerpc_ieee1275 = kern/powerpc/cache.S; powerpc_ieee1275 = kern/powerpc/dl.c; sparc64_ieee1275 = kern/sparc64/cache.S; sparc64_ieee1275 = kern/sparc64/dl.c; sparc64_ieee1275 = kern/sparc64/ieee1275/ieee1275.c; - sparc64_ieee1275 = kern/sparc64/ieee1275/init.c; emu = disk/host.c; emu = gnulib/progname.c; diff --git a/grub-core/boot/i386/pc/diskboot.S b/grub-core/boot/i386/pc/diskboot.S index 92f223f0d..336c3bcca 100644 --- a/grub-core/boot/i386/pc/diskboot.S +++ b/grub-core/boot/i386/pc/diskboot.S @@ -83,7 +83,7 @@ LOCAL(setup_sectors): /* the maximum is limited to 0x7f because of Phoenix EDD */ xorl %eax, %eax - movb $0x7f, %al + movb $0x1, %al /* how many do we really want to read? */ cmpw %ax, 8(%di) /* compare against total number of sectors */ diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 35602513e..5dc753046 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -530,7 +530,7 @@ grub_efidisk_open (const char *name, struct grub_disk *disk) and total sectors should be replaced with total blocks. */ grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n", m, (unsigned long long) m->last_block, m->block_size); - disk->total_sectors = m->last_block; + disk->total_sectors = m->last_block + 1; if (m->block_size & (m->block_size - 1) || !m->block_size) return grub_error (GRUB_ERR_IO, "invalid sector size %d", m->block_size); @@ -788,19 +788,27 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) /* Find a partition which matches the hard drive device path. */ grub_memcpy (&hd, ldp, sizeof (hd)); - grub_partition_iterate (parent, find_partition); - - if (! tpart) + if (hd.partition_start == 0 + && hd.partition_size == grub_disk_get_size (parent)) { - grub_disk_close (parent); - return 0; + device_name = grub_strdup (parent->name); } + else + { + char *partition_name; - { - char *partition_name = grub_partition_get_name (tpart); - device_name = grub_xasprintf ("%s,%s", parent->name, partition_name); - grub_free (partition_name); - } + grub_partition_iterate (parent, find_partition); + + if (! tpart) + { + grub_disk_close (parent); + return 0; + } + + partition_name = grub_partition_get_name (tpart); + device_name = grub_xasprintf ("%s,%s", parent->name, partition_name); + grub_free (partition_name); + } grub_disk_close (parent); return device_name; diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index 1b0a872b4..a7325acc6 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -43,83 +43,21 @@ grub_efi_init (void) } void -grub_efi_set_prefix (void) +grub_machine_get_bootlocation (char **device, char **path) { grub_efi_loaded_image_t *image = NULL; - char *device = NULL; - char *path = NULL; + char *p; - { - char *pptr = NULL; - if (grub_prefix[0] == '(') - { - pptr = grub_strrchr (grub_prefix, ')'); - if (pptr) - { - device = grub_strndup (grub_prefix + 1, pptr - grub_prefix - 1); - pptr++; - } - } - if (!pptr) - pptr = grub_prefix; - if (pptr[0]) - path = grub_strdup (pptr); - } + image = grub_efi_get_loaded_image (grub_efi_image_handle); + if (!image) + return; + *device = grub_efidisk_get_device_name (image->device_handle); + *path = grub_efi_get_filename (image->file_path); - if ((!device || device[0] == ',' || !device[0]) || !path) - image = grub_efi_get_loaded_image (grub_efi_image_handle); - if (image) - { - if (!device) - device = grub_efidisk_get_device_name (image->device_handle); - else if (device[0] == ',' || !device[0]) - { - /* We have a partition, but still need to fill in the drive. */ - char *image_device, *comma, *new_device; - - image_device = grub_efidisk_get_device_name (image->device_handle); - comma = grub_strchr (image_device, ','); - if (comma) - { - char *drive = grub_strndup (image_device, comma - image_device); - new_device = grub_xasprintf ("%s%s", drive, device); - grub_free (drive); - } - else - new_device = grub_xasprintf ("%s%s", image_device, device); - - grub_free (image_device); - grub_free (device); - device = new_device; - } - } - - if (image && !path) - { - char *p; - - path = grub_efi_get_filename (image->file_path); - - /* Get the directory. */ - p = grub_strrchr (path, '/'); - if (p) - *p = '\0'; - } - - if (device && path) - { - char *prefix; - - prefix = grub_xasprintf ("(%s)%s", device, path); - if (prefix) - { - grub_env_set ("prefix", prefix); - grub_free (prefix); - } - } - - grub_free (device); - grub_free (path); + /* Get the directory. */ + p = grub_strrchr (*path, '/'); + if (p) + *p = '\0'; } void diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c index 0a7645992..096e97090 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -49,7 +49,7 @@ static jmp_buf main_env; /* Store the prefix specified by an argument. */ -static char *prefix = NULL; +static char *root_dev = NULL, *dir = DEFAULT_DIRECTORY; int grub_no_autoload; @@ -71,11 +71,10 @@ grub_machine_init (void) } void -grub_machine_set_prefix (void) +grub_machine_get_bootlocation (char **device, char **path) { - grub_env_set ("prefix", prefix); - free (prefix); - prefix = 0; + *device = root_dev; + *path = dir; } void @@ -84,6 +83,8 @@ grub_machine_fini (void) grub_console_fini (); } +char grub_prefix[64] = ""; + static struct option options[] = @@ -132,8 +133,6 @@ void grub_emu_init (void); int main (int argc, char *argv[]) { - char *root_dev = 0; - char *dir = DEFAULT_DIRECTORY; char *dev_map = DEFAULT_DEVICE_MAP; volatile int hold = 0; int opt; @@ -219,9 +218,6 @@ main (int argc, char *argv[]) dir = xstrdup (dir); else dir = grub_make_system_path_relative_to_its_root (dir); - prefix = xmalloc (strlen (root_dev) + 2 + strlen (dir) + 1); - sprintf (prefix, "(%s)%s", root_dev, dir); - free (dir); /* Start GRUB! */ if (setjmp (main_env) == 0) diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c index 434b9b5a8..ebbea2523 100644 --- a/grub-core/kern/i386/coreboot/init.c +++ b/grub-core/kern/i386/coreboot/init.c @@ -107,10 +107,9 @@ grub_machine_init (void) } void -grub_machine_set_prefix (void) +grub_machine_get_bootlocation (char **device __attribute__ ((unused)), + char **path __attribute__ ((unused))) { - /* Initialize the prefix. */ - grub_env_set ("prefix", grub_prefix); } void diff --git a/grub-core/kern/i386/efi/init.c b/grub-core/kern/i386/efi/init.c index f73f828c6..6bd8f3e87 100644 --- a/grub-core/kern/i386/efi/init.c +++ b/grub-core/kern/i386/efi/init.c @@ -39,9 +39,3 @@ grub_machine_fini (void) { grub_efi_fini (); } - -void -grub_machine_set_prefix (void) -{ - grub_efi_set_prefix (); -} diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index d8c337bde..3aedaf6d8 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -45,52 +45,39 @@ struct mem_region static struct mem_region mem_regions[MAX_REGIONS]; static int num_regions; -static char * -make_install_device (void) +void +grub_machine_get_bootlocation (char **device, + char **path __attribute__ ((unused))) { + char *ptr; + + /* No hardcoded root partition - make it from the boot drive and the + partition number encoded at the install time. */ + if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL) + { + *device = grub_strdup ("pxe"); + return; + } + /* XXX: This should be enough. */ - char dev[100], *ptr = dev; +#define DEV_SIZE 100 + *device = grub_malloc (DEV_SIZE); + ptr = *device; + grub_snprintf (*device, DEV_SIZE, + "%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f', + grub_boot_drive & 0x7f); + ptr += grub_strlen (ptr); - if (grub_prefix[0] != '(') - { - /* No hardcoded root partition - make it from the boot drive and the - partition number encoded at the install time. */ - if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL) - { - grub_strcpy (dev, "(pxe"); - ptr += sizeof ("(pxe") - 1; - } - else - { - grub_snprintf (dev, sizeof (dev), - "(%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f', - grub_boot_drive & 0x7f); - ptr += grub_strlen (ptr); + if (grub_install_dos_part >= 0) + grub_snprintf (ptr, DEV_SIZE - (ptr - *device), + ",%u", grub_install_dos_part + 1); + ptr += grub_strlen (ptr); - if (grub_install_dos_part >= 0) - grub_snprintf (ptr, sizeof (dev) - (ptr - dev), - ",%u", grub_install_dos_part + 1); - ptr += grub_strlen (ptr); - - if (grub_install_bsd_part >= 0) - grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ",%u", - grub_install_bsd_part + 1); - ptr += grub_strlen (ptr); - } - - grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ")%s", grub_prefix); - grub_strcpy (grub_prefix, dev); - } - else if (grub_prefix[1] == ',' || grub_prefix[1] == ')') - { - /* We have a prefix, but still need to fill in the boot drive. */ - grub_snprintf (dev, sizeof (dev), - "(%cd%u%s", (grub_boot_drive & 0x80) ? 'h' : 'f', - grub_boot_drive & 0x7f, grub_prefix + 1); - grub_strcpy (grub_prefix, dev); - } - - return grub_prefix; + if (grub_install_bsd_part >= 0) + grub_snprintf (ptr, DEV_SIZE - (ptr - *device), ",%u", + grub_install_bsd_part + 1); + ptr += grub_strlen (ptr); + *ptr = 0; } /* Add a memory region. */ @@ -211,13 +198,6 @@ grub_machine_init (void) grub_tsc_init (); } -void -grub_machine_set_prefix (void) -{ - /* Initialize the prefix. */ - grub_env_set ("prefix", make_install_device ()); -} - void grub_machine_fini (void) { diff --git a/grub-core/kern/ia64/efi/init.c b/grub-core/kern/ia64/efi/init.c index 6bb4219ac..e2fa58090 100644 --- a/grub-core/kern/ia64/efi/init.c +++ b/grub-core/kern/ia64/efi/init.c @@ -40,12 +40,6 @@ 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) { diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c index 2fbe809b2..eeb462c5e 100644 --- a/grub-core/kern/ieee1275/cmain.c +++ b/grub-core/kern/ieee1275/cmain.c @@ -60,6 +60,10 @@ grub_ieee1275_find_options (void) int is_olpc = 0; int is_qemu = 0; +#ifdef _sparc64 + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0); +#endif + grub_ieee1275_finddevice ("/", &root); grub_ieee1275_finddevice ("/options", &options); grub_ieee1275_finddevice ("/openprom", &openprom); diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index 3c55096a4..3c6332553 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -35,6 +35,9 @@ #include #include #include +#ifdef __sparc__ +#include +#endif /* The minimal heap size we can live with. */ #define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024) @@ -49,6 +52,10 @@ extern char _start[]; extern char _end[]; +#ifdef __sparc__ +grub_addr_t grub_ieee1275_original_stack; +#endif + void grub_exit (void) { @@ -71,51 +78,39 @@ grub_translate_ieee1275_path (char *filepath) } void -grub_machine_set_prefix (void) +grub_machine_get_bootlocation (char **device, char **path) { char bootpath[64]; /* XXX check length */ char *filename; - char *prefix; grub_bootp_t bootp_pckt; - char addr[GRUB_NET_MAX_STR_ADDR_LEN]; /* Set the net prefix when possible. */ if (grub_getbootp && (bootp_pckt = grub_getbootp())) { - grub_uint32_t n = bootp_pckt->siaddr; - grub_snprintf (addr, GRUB_NET_MAX_STR_ADDR_LEN, "%d.%d.%d.%d", - ((n >> 24) & 0xff), ((n >> 16) & 0xff), - ((n >> 8) & 0xff), ((n >> 0) & 0xff)); - prefix = grub_xasprintf ("(tftp,%s)%s", addr,grub_prefix); - grub_env_set ("prefix", prefix); - grub_free (prefix); + grub_uint32_t n = bootp_pckt->siaddr; + char addr[GRUB_NET_MAX_STR_ADDR_LEN]; + grub_snprintf (addr, GRUB_NET_MAX_STR_ADDR_LEN, "%d.%d.%d.%d", + ((n >> 24) & 0xff), ((n >> 16) & 0xff), + ((n >> 8) & 0xff), ((n >> 0) & 0xff)); + *device = grub_xasprintf ("(tftp,%s)", addr); return; } - if (grub_prefix[0]) - { - grub_env_set ("prefix", grub_prefix); - /* Prefix is hardcoded in the core image. */ - return; - } - if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath, sizeof (bootpath), 0)) { /* Should never happen. */ grub_printf ("/chosen/bootpath property missing!\n"); - grub_env_set ("prefix", ""); return; } /* Transform an OF device path to a GRUB path. */ - prefix = grub_ieee1275_encode_devname (bootpath); + *device = grub_ieee1275_encode_devname (bootpath); filename = grub_ieee1275_get_filename (bootpath); if (filename) { - char *newprefix; char *lastslash = grub_strrchr (filename, '\\'); /* Truncate at last directory. */ @@ -124,23 +119,22 @@ grub_machine_set_prefix (void) *lastslash = '\0'; grub_translate_ieee1275_path (filename); - newprefix = grub_xasprintf ("%s%s", prefix, filename); - if (newprefix) - { - grub_free (prefix); - prefix = newprefix; - } + *path = filename; } } - - grub_env_set ("prefix", prefix); - - grub_free (filename); - grub_free (prefix); } /* Claim some available memory in the first /memory node. */ -static void grub_claim_heap (void) +#ifdef __sparc__ +static void +grub_claim_heap (void) +{ + grub_mm_init_region ((void *) (grub_modules_get_end () + + GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000); +} +#else +static void +grub_claim_heap (void) { unsigned long total = 0; @@ -208,23 +202,14 @@ static void grub_claim_heap (void) else grub_machine_mmap_iterate (heap_init); } +#endif -static grub_uint64_t ieee1275_get_time_ms (void); - -void -grub_machine_init (void) +static void +grub_parse_cmdline (void) { - char args[256]; grub_ssize_t actual; + char args[256]; - grub_ieee1275_init (); - - grub_console_init_early (); - grub_claim_heap (); - grub_console_init_lately (); - grub_ofdisk_init (); - - /* Process commandline. */ if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args, sizeof args, &actual) == 0 && actual > 1) @@ -257,6 +242,21 @@ grub_machine_init (void) } } } +} + +static grub_uint64_t ieee1275_get_time_ms (void); + +void +grub_machine_init (void) +{ + grub_ieee1275_init (); + + grub_console_init_early (); + grub_claim_heap (); + grub_console_init_lately (); + grub_ofdisk_init (); + + grub_parse_cmdline (); grub_install_get_time_ms (ieee1275_get_time_ms); } diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index db4bec90a..8fc373c55 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -369,6 +369,11 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype) ret = grub_strdup (args); else ret = grub_strndup (args, (grub_size_t)(comma - args)); + /* Consistently provide numbered partitions to GRUB. + OpenBOOT traditionally uses alphabetical partition + specifiers. */ + if (ret[0] >= 'a' && ret[0] <= 'z') + ret[0] = '1' + (ret[0] - 'a'); } } diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index cc9758988..4818d6af3 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -129,27 +129,74 @@ grub_env_write_root (struct grub_env_var *var __attribute__ ((unused)), return grub_strdup (val); } -/* Set the root device according to the dl prefix. */ static void -grub_set_root_dev (void) +grub_set_prefix_and_root (void) { - const char *prefix; + char *device = NULL; + char *path = NULL; + char *fwdevice = NULL; + char *fwpath = NULL; grub_register_variable_hook ("root", 0, grub_env_write_root); - prefix = grub_env_get ("prefix"); + { + char *pptr = NULL; + if (grub_prefix[0] == '(') + { + pptr = grub_strrchr (grub_prefix, ')'); + if (pptr) + { + device = grub_strndup (grub_prefix + 1, pptr - grub_prefix - 1); + pptr++; + } + } + if (!pptr) + pptr = grub_prefix; + if (pptr[0]) + path = grub_strdup (pptr); + } + if ((!device || device[0] == ',' || !device[0]) || !path) + grub_machine_get_bootlocation (&fwdevice, &fwpath); - if (prefix) + if (!device && fwdevice) + device = fwdevice; + else if (fwdevice && (device[0] == ',' || !device[0])) { - char *dev; + /* We have a partition, but still need to fill in the drive. */ + char *comma, *new_device; - dev = grub_file_get_device_name (prefix); - if (dev) + comma = grub_strchr (fwdevice, ','); + if (comma) { - grub_env_set ("root", dev); - grub_free (dev); + char *drive = grub_strndup (fwdevice, comma - fwdevice); + new_device = grub_xasprintf ("%s%s", drive, device); + grub_free (drive); } + else + new_device = grub_xasprintf ("%s%s", fwdevice, device); + + grub_free (fwdevice); + grub_free (device); + device = new_device; } + if (fwpath && !path) + path = fwpath; + if (device) + { + char *prefix; + + prefix = grub_xasprintf ("(%s)%s", device, path ? : ""); + if (prefix) + { + grub_env_set ("prefix", prefix); + grub_free (prefix); + } + grub_env_set ("root", device); + } + + grub_free (device); + grub_free (path); + grub_print_error (); } /* Load the normal mode module and execute the normal mode if possible. */ @@ -187,8 +234,7 @@ grub_main (void) /* It is better to set the root device as soon as possible, for convenience. */ - grub_machine_set_prefix (); - grub_set_root_dev (); + grub_set_prefix_and_root (); grub_env_export ("root"); grub_env_export ("prefix"); diff --git a/grub-core/kern/mips/init.c b/grub-core/kern/mips/init.c index bfa08f56a..353f679e6 100644 --- a/grub-core/kern/mips/init.c +++ b/grub-core/kern/mips/init.c @@ -38,7 +38,7 @@ grub_get_rtc (void) } void -grub_machine_set_prefix (void) +grub_machine_get_bootlocation (char **device __attribute__ ((unused)), + char **path __attribute__ ((unused))) { - grub_env_set ("prefix", grub_prefix); } diff --git a/grub-core/kern/sparc64/ieee1275/init.c b/grub-core/kern/sparc64/ieee1275/init.c deleted file mode 100644 index 72ee1f136..000000000 --- a/grub-core/kern/sparc64/ieee1275/init.c +++ /dev/null @@ -1,174 +0,0 @@ -/* init.c -- Initialize GRUB on SPARC64. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 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 - -grub_addr_t grub_ieee1275_original_stack; - -void -grub_exit (void) -{ - grub_ieee1275_exit (); -} - -static grub_uint64_t -ieee1275_get_time_ms (void) -{ - grub_uint32_t msecs = 0; - - grub_ieee1275_milliseconds (&msecs); - - return msecs; -} - -grub_uint32_t -grub_get_rtc (void) -{ - return ieee1275_get_time_ms (); -} - -grub_addr_t -grub_arch_modules_addr (void) -{ - extern char _end[]; - return (grub_addr_t) _end; -} - -void -grub_machine_set_prefix (void) -{ - if (grub_prefix[0] != '(') - { - char bootpath[IEEE1275_MAX_PATH_LEN]; - char *prefix, *path, *colon; - grub_ssize_t actual; - - if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", - &bootpath, sizeof (bootpath), &actual)) - { - /* Should never happen. */ - grub_printf ("/chosen/bootpath property missing!\n"); - grub_env_set ("prefix", ""); - return; - } - - /* Transform an OF device path to a GRUB path. */ - colon = grub_strchr (bootpath, ':'); - if (colon) - { - char *part = colon + 1; - - /* Consistently provide numbered partitions to GRUB. - OpenBOOT traditionally uses alphabetical partition - specifiers. */ - if (part[0] >= 'a' && part[0] <= 'z') - part[0] = '1' + (part[0] - 'a'); - } - prefix = grub_ieee1275_encode_devname (bootpath); - - path = grub_xasprintf("%s%s", prefix, grub_prefix); - - grub_strcpy (grub_prefix, path); - - grub_free (path); - grub_free (prefix); - } - - grub_env_set ("prefix", grub_prefix); -} - -static void -grub_heap_init (void) -{ - grub_mm_init_region ((void *) (grub_modules_get_end () - + GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000); -} - -static void -grub_parse_cmdline (void) -{ - grub_ssize_t actual; - char args[256]; - - if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args, - sizeof args, &actual) == 0 - && actual > 1) - { - int i = 0; - - while (i < actual) - { - char *command = &args[i]; - char *end; - char *val; - - end = grub_strchr (command, ';'); - if (end == 0) - i = actual; /* No more commands after this one. */ - else - { - *end = '\0'; - i += end - command + 1; - while (grub_isspace(args[i])) - i++; - } - - /* Process command. */ - val = grub_strchr (command, '='); - if (val) - { - *val = '\0'; - grub_env_set (command, val + 1); - } - } - } -} - -void -grub_machine_init (void) -{ - grub_ieee1275_init (); - grub_console_init_early (); - grub_heap_init (); - grub_console_init_lately (); - - grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0); - grub_ofdisk_init (); - - grub_parse_cmdline (); - grub_install_get_time_ms (ieee1275_get_time_ms); -} - -void -grub_machine_fini (void) -{ - grub_ofdisk_fini (); - grub_console_fini (); -} diff --git a/include/grub/kernel.h b/include/grub/kernel.h index 2ecc73df4..6a5f91c3d 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -84,12 +84,13 @@ void grub_machine_init (void); void EXPORT_FUNC(grub_machine_fini) (void); /* The machine-specific prefix initialization. */ -void grub_machine_set_prefix (void); +void +grub_machine_get_bootlocation (char **device, char **path); /* Register all the exported symbols. This is automatically generated. */ void grub_register_exported_symbols (void); -#if ! defined (ASM_FILE) && !defined (GRUB_MACHINE_EMU) +#if ! defined (ASM_FILE) extern char grub_prefix[]; #endif diff --git a/include/grub/offsets.h b/include/grub/offsets.h index af724096d..c04961fc6 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -169,8 +169,10 @@ /* Non-zero value is only needed for PowerMacs. */ #define GRUB_KERNEL_I386_IEEE1275_MOD_GAP 0x0 #define GRUB_KERNEL_I386_COREBOOT_MOD_GAP 0x0 +#define GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP 0x0 #define GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN 0x1000 +#define GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN 0x1 #define GRUB_KERNEL_MIPS_LOONGSON_MOD_ALIGN 0x1 #define GRUB_KERNEL_MIPS_ARC_MOD_ALIGN 0x1 @@ -179,7 +181,7 @@ /* Minimal gap between _end and the start of the modules. It's a hack for PowerMac to prevent "CLAIM failed" error. The real fix is to rewrite grub-mkimage to generate valid ELF files. */ -#define GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP 0x8000 +#define GRUB_KERNEL_SPARC64_IEEE1275_MOD_GAP 0x8000 #ifdef GRUB_MACHINE #define GRUB_OFFSETS_CONCAT_(a,b,c) a ## b ## c From cae730b4526f250a3d5073c00911e35b7abdd7d7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 2 Jul 2011 16:56:35 +0200 Subject: [PATCH 377/406] Automatically determine prefix when netbooted on EFI --- grub-core/disk/efi/efidisk.c | 153 ++++++++--------------------- grub-core/kern/efi/efi.c | 48 +++++++++ grub-core/kern/efi/init.c | 6 ++ grub-core/net/drivers/efi/efinet.c | 49 ++++++++- grub-core/net/net.c | 53 ++++++++-- include/grub/efi/api.h | 35 +++++++ include/grub/efi/efi.h | 8 ++ include/grub/net.h | 8 +- 8 files changed, 237 insertions(+), 123 deletions(-) diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 5dc753046..07f0f6859 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -84,54 +84,6 @@ find_last_device_path (const grub_efi_device_path_t *dp) return p; } -/* Compare device paths. */ -static int -compare_device_paths (const grub_efi_device_path_t *dp1, - const grub_efi_device_path_t *dp2) -{ - if (! dp1 || ! dp2) - /* Return non-zero. */ - return 1; - - while (1) - { - grub_efi_uint8_t type1, type2; - grub_efi_uint8_t subtype1, subtype2; - grub_efi_uint16_t len1, len2; - int ret; - - type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1); - type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2); - - if (type1 != type2) - return (int) type2 - (int) type1; - - subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1); - subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2); - - if (subtype1 != subtype2) - return (int) subtype1 - (int) subtype2; - - len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1); - len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2); - - if (len1 != len2) - return (int) len1 - (int) len2; - - ret = grub_memcmp (dp1, dp2, len1); - if (ret != 0) - return ret; - - if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1)) - break; - - dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1); - dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2); - } - - return 0; -} - static struct grub_efidisk_data * make_devices (void) { @@ -214,7 +166,7 @@ find_parent_device (struct grub_efidisk_data *devices, if (parent == d) continue; - if (compare_device_paths (parent->device_path, dp) == 0) + if (grub_efi_compare_device_paths (parent->device_path, dp) == 0) { /* Found. */ if (! parent->last_device_path) @@ -249,7 +201,7 @@ iterate_child_devices (struct grub_efidisk_data *devices, ldp->length[0] = sizeof (*ldp); ldp->length[1] = 0; - if (compare_device_paths (dp, d->device_path) == 0) + if (grub_efi_compare_device_paths (dp, d->device_path) == 0) if (hook (p)) { grub_free (dp); @@ -273,11 +225,11 @@ add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d) { int ret; - ret = compare_device_paths (find_last_device_path ((*p)->device_path), - find_last_device_path (d->device_path)); + ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path), + find_last_device_path (d->device_path)); if (ret == 0) - ret = compare_device_paths ((*p)->device_path, - d->device_path); + ret = grub_efi_compare_device_paths ((*p)->device_path, + d->device_path); if (ret == 0) return; else if (ret > 0) @@ -706,7 +658,35 @@ grub_efidisk_get_device_handle (grub_disk_t disk) char * grub_efidisk_get_device_name (grub_efi_handle_t *handle) { - grub_efi_device_path_t *dp, *ldp; + grub_efi_device_path_t *dp, *ldp, *sdp; + /* This is a hard disk partition. */ + grub_disk_t parent = 0; + auto int find_parent_disk (const char *name); + + /* Find the disk which is the parent of a given hard disk partition. */ + int find_parent_disk (const char *name) + { + grub_disk_t disk; + + disk = grub_disk_open (name); + if (! disk) + return 1; + + if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID) + { + struct grub_efidisk_data *d; + + d = disk->data; + if (grub_efi_compare_device_paths (d->device_path, sdp) == 0) + { + parent = disk; + return 1; + } + } + + grub_disk_close (disk); + return 0; + } dp = grub_efi_get_device_path (handle); if (! dp) @@ -720,40 +700,12 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)) { - /* This is a hard disk partition. */ - grub_disk_t parent = 0; grub_partition_t tpart = NULL; char *device_name; grub_efi_device_path_t *dup_dp, *dup_ldp; grub_efi_hard_drive_device_path_t hd; - auto int find_parent_disk (const char *name); auto int find_partition (grub_disk_t disk, const grub_partition_t part); - /* Find the disk which is the parent of a given hard disk partition. */ - int find_parent_disk (const char *name) - { - grub_disk_t disk; - - disk = grub_disk_open (name); - if (! disk) - return 1; - - if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID) - { - struct grub_efidisk_data *d; - - d = disk->data; - if (compare_device_paths (d->device_path, dup_dp) == 0) - { - parent = disk; - return 1; - } - } - - grub_disk_close (disk); - return 0; - } - /* Find the identical partition. */ int find_partition (grub_disk_t disk __attribute__ ((unused)), const grub_partition_t part) @@ -780,6 +732,8 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) dup_ldp->length[0] = sizeof (*dup_ldp); dup_ldp->length[1] = 0; + sdp = dup_dp; + grub_efidisk_iterate (find_parent_disk); grub_free (dup_dp); @@ -816,36 +770,15 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) else { /* This should be an entire disk. */ - auto int find_disk (const char *name); char *device_name = 0; - int find_disk (const char *name) - { - grub_disk_t disk; + sdp = dp; - disk = grub_disk_open (name); - if (! disk) - return 1; - - if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID) - { - struct grub_efidisk_data *d; - - d = disk->data; - if (compare_device_paths (d->device_path, dp) == 0) - { - device_name = grub_strdup (disk->name); - grub_disk_close (disk); - return 1; - } - } - - grub_disk_close (disk); - return 0; - - } - - grub_efidisk_iterate (find_disk); + grub_efidisk_iterate (find_parent_disk); + if (!parent) + return NULL; + device_name = grub_strdup (parent->name); + grub_disk_close (parent); return device_name; } diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index c95058733..d0994a940 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -746,3 +746,51 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) dp = (grub_efi_device_path_t *) ((char *) dp + len); } } + +/* Compare device paths. */ +int +grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1, + const grub_efi_device_path_t *dp2) +{ + if (! dp1 || ! dp2) + /* Return non-zero. */ + return 1; + + while (1) + { + grub_efi_uint8_t type1, type2; + grub_efi_uint8_t subtype1, subtype2; + grub_efi_uint16_t len1, len2; + int ret; + + type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1); + type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2); + + if (type1 != type2) + return (int) type2 - (int) type1; + + subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1); + subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2); + + if (subtype1 != subtype2) + return (int) subtype1 - (int) subtype2; + + len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1); + len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2); + + if (len1 != len2) + return (int) len1 - (int) len2; + + ret = grub_memcmp (dp1, dp2, len1); + if (ret != 0) + return ret; + + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1)) + break; + + dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1); + dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2); + } + + return 0; +} diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index a7325acc6..4dfb06284 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -42,6 +42,10 @@ grub_efi_init (void) grub_efidisk_init (); } +void (*grub_efi_net_config) (grub_efi_handle_t hnd, + char **device, + char **path); + void grub_machine_get_bootlocation (char **device, char **path) { @@ -53,6 +57,8 @@ grub_machine_get_bootlocation (char **device, char **path) return; *device = grub_efidisk_get_device_name (image->device_handle); *path = grub_efi_get_filename (image->file_path); + if (!*device && grub_efi_net_config) + grub_efi_net_config (image->device_handle, device, path); /* Get the directory. */ p = grub_strrchr (*path, '/'); diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index a6e005601..29bc66183 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -27,14 +27,14 @@ GRUB_MOD_LICENSE ("GPLv3+"); /* GUID. */ static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID; - +static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID; static grub_err_t send_card_buffer (const struct grub_net_card *dev, struct grub_net_buff *pack) { grub_efi_status_t st; - grub_efi_simple_network_t *net = dev->data; + grub_efi_simple_network_t *net = dev->efi_net; st = efi_call_7 (net->transmit, net, 0, pack->tail - pack->data, pack->data, NULL, NULL, NULL); if (st != GRUB_EFI_SUCCESS) @@ -46,7 +46,7 @@ static grub_ssize_t get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb) { - grub_efi_simple_network_t *net = dev->data; + grub_efi_simple_network_t *net = dev->efi_net; grub_err_t err; grub_efi_status_t st; grub_efi_uintn_t bufsize = 1500; @@ -139,21 +139,62 @@ grub_efinet_findcards (void) grub_memcpy (card->default_address.mac, net->mode->current_address, sizeof (card->default_address.mac)); - card->data = net; + card->efi_net = net; + card->efi_handle = *handle; grub_net_card_register (card); } grub_free (handles); } +static void +grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + char **path) +{ + struct grub_net_card *card; + grub_efi_device_path_t *dp; + + dp = grub_efi_get_device_path (hnd); + if (! dp) + return; + + FOR_NET_CARDS (card) + { + grub_efi_device_path_t *cdp; + struct grub_efi_pxe *pxe; + struct grub_efi_pxe_mode *pxe_mode; + if (card->driver != &efidriver) + continue; + cdp = grub_efi_get_device_path (card->efi_handle); + if (! cdp) + continue; + if (grub_efi_compare_device_paths (dp, cdp) != 0) + continue; + pxe = grub_efi_open_protocol (hnd, &pxe_io_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (! pxe) + continue; + pxe_mode = pxe->mode; + grub_net_configure_by_dhcp_ack (card->name, card, 0, + (struct grub_net_bootp_packet *) + &pxe_mode->dhcp_ack, + sizeof (pxe_mode->dhcp_ack), + 1, device, path); + return; + } +} + + GRUB_MOD_INIT(efinet) { grub_efinet_findcards (); + grub_efi_net_config = grub_efi_net_config_real; } GRUB_MOD_FINI(ofnet) { struct grub_net_card *card; + grub_efi_net_config = 0; FOR_NET_CARDS (card) if (card->driver && !grub_strcmp (card->driver->name, "efinet")) { diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 34148f52c..2ecb709b9 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -936,7 +936,8 @@ grub_net_configure_by_dhcp_ack (const char *name, const struct grub_net_card *card, grub_net_interface_flags_t flags, const struct grub_net_bootp_packet *bp, - grub_size_t size) + grub_size_t size, + int is_def, char **device, char **path) { grub_net_network_level_address_t addr; grub_net_link_level_address_t hwaddr; @@ -945,6 +946,11 @@ grub_net_configure_by_dhcp_ack (const char *name, addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; addr.ipv4 = bp->your_ip; + if (device) + *device = 0; + if (path) + *path = 0; + grub_memcpy (hwaddr.mac, bp->mac_addr, bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len : sizeof (hwaddr.mac)); @@ -975,26 +981,57 @@ grub_net_configure_by_dhcp_ack (const char *name, if (size > OFFSET_OF (boot_file, bp)) set_env_limn_ro (name, "boot_file", (char *) bp->boot_file, sizeof (bp->boot_file)); + if (is_def) + default_server = 0; if (size > OFFSET_OF (server_name, bp) && bp->server_name[0]) { set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name, sizeof (bp->server_name)); - if (!default_server) + if (is_def && !default_server) { default_server = grub_strdup (bp->server_name); - grub_errno = GRUB_ERR_NONE; - } + grub_print_error (); + } + if (device && !*device) + { + *device = grub_xasprintf ("tftp,%s", bp->server_name); + grub_print_error (); + } } - if (!default_server) + if (is_def && !default_server) { default_server = grub_xasprintf ("%d.%d.%d.%d", ((grub_uint8_t *) &bp->server_ip)[0], ((grub_uint8_t *) &bp->server_ip)[1], ((grub_uint8_t *) &bp->server_ip)[2], ((grub_uint8_t *) &bp->server_ip)[3]); - grub_errno = GRUB_ERR_NONE; - } + grub_print_error (); + } + + if (device && !*device) + { + *device = grub_xasprintf ("tftp,%d.%d.%d.%d", + ((grub_uint8_t *) &bp->server_ip)[0], + ((grub_uint8_t *) &bp->server_ip)[1], + ((grub_uint8_t *) &bp->server_ip)[2], + ((grub_uint8_t *) &bp->server_ip)[3]); + grub_print_error (); + } + if (size > OFFSET_OF (boot_file, bp) && path) + { + *path = grub_strndup (bp->boot_file, sizeof (bp->boot_file)); + grub_print_error (); + if (*path) + { + char *slash; + slash = grub_strrchr (*path, '/'); + if (slash) + *slash = 0; + else + **path = 0; + } + } if (size > OFFSET_OF (vendor, bp)) parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp)); @@ -1025,7 +1062,7 @@ grub_net_process_dhcp (struct grub_net_buff *nb, } grub_net_configure_by_dhcp_ack (name, card, 0, (const struct grub_net_bootp_packet *) nb->data, - (nb->tail - nb->data)); + (nb->tail - nb->data), 0, 0, 0); grub_free (name); if (grub_errno) grub_print_error (); diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index a3dde0eff..5cd1686ea 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -89,6 +89,11 @@ { 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ } +#define GRUB_EFI_PXE_GUID \ + { 0x03c4e603, 0xac28, 0x11d3, \ + { 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + #define GRUB_EFI_DEVICE_PATH_GUID \ { 0x09576e91, 0x6d3f, 0x11d2, \ { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ @@ -1118,6 +1123,36 @@ struct grub_efi_simple_text_output_interface }; typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output_interface_t; +typedef grub_uint8_t grub_efi_pxe_packet_t[1472]; + +typedef struct grub_efi_pxe_mode +{ + grub_uint8_t unused[52]; + grub_efi_pxe_packet_t dhcp_discover; + grub_efi_pxe_packet_t dhcp_ack; + grub_efi_pxe_packet_t proxy_offer; + grub_efi_pxe_packet_t pxe_discover; + grub_efi_pxe_packet_t pxe_reply; +} grub_efi_pxe_mode_t; + +typedef struct grub_efi_pxe +{ + grub_uint64_t rev; + void (*start) (void); + void (*stop) (void); + void (*dhcp) (void); + void (*discover) (void); + void (*mftp) (void); + void (*udpwrite) (void); + void (*udpread) (void); + void (*setipfilter) (void); + void (*arp) (void); + void (*setparams) (void); + void (*setstationip) (void); + void (*setpackets) (void); + struct grub_efi_pxe_mode *mode; +} grub_efi_pxe_t; + #define GRUB_EFI_BLACK 0x00 #define GRUB_EFI_BLUE 0x01 #define GRUB_EFI_GREEN 0x02 diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h index e9c57dd11..e98f99507 100644 --- a/include/grub/efi/efi.h +++ b/include/grub/efi/efi.h @@ -62,6 +62,14 @@ grub_err_t EXPORT_FUNC (grub_efi_set_virtual_address_map) (grub_efi_uintn_t memo grub_efi_uint32_t descriptor_version, grub_efi_memory_descriptor_t *virtual_map); +int +EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1, + const grub_efi_device_path_t *dp2); + +extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, + char **device, + char **path); + void grub_efi_mm_init (void); void grub_efi_mm_fini (void); void grub_efi_init (void); diff --git a/include/grub/net.h b/include/grub/net.h index ee94ebcc6..6aaf391d5 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -109,6 +109,11 @@ struct grub_net_card grub_net_card_flags_t flags; union { + struct + { + struct grub_efi_simple_network *efi_net; + void *efi_handle; + }; void *data; int data_num; }; @@ -404,7 +409,8 @@ grub_net_configure_by_dhcp_ack (const char *name, const struct grub_net_card *card, grub_net_interface_flags_t flags, const struct grub_net_bootp_packet *bp, - grub_size_t size); + grub_size_t size, + int is_def, char **device, char **path); void grub_net_process_dhcp (struct grub_net_buff *nb, From 6708faafdea4e3b27879e089e772babb78bfe7f2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 2 Jul 2011 17:58:23 +0200 Subject: [PATCH 378/406] Fix broken blksize negotiation, fix broken seek and change a way net device is filled n i386-pc --- grub-core/kern/file.c | 4 -- grub-core/kern/i386/pc/init.c | 8 ++-- grub-core/net/drivers/i386/pc/pxe.c | 73 +++++++++++++++++++++++------ grub-core/net/net.c | 28 +++++++---- grub-core/net/tftp.c | 26 +++++++--- include/grub/i386/pc/kernel.h | 2 + include/grub/net.h | 2 +- include/grub/net/tftp.h | 6 --- 8 files changed, 105 insertions(+), 44 deletions(-) diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c index 2407e72c5..f69ef6fd4 100644 --- a/grub-core/kern/file.c +++ b/grub-core/kern/file.c @@ -25,7 +25,6 @@ #include #include -grub_err_t (*grub_file_net_seek) (struct grub_file *file, grub_off_t offset) = NULL; void (*EXPORT_VAR (grub_grubnet_fini)) (void); grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX]; @@ -183,9 +182,6 @@ grub_file_seek (grub_file_t file, grub_off_t offset) return -1; } - if (file->device->net && grub_file_net_seek) - grub_file_net_seek (file, offset); - old = file->offset; file->offset = offset; diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index 3aedaf6d8..24fe8fed9 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -45,9 +45,10 @@ struct mem_region static struct mem_region mem_regions[MAX_REGIONS]; static int num_regions; +void (*grub_pc_net_config) (char **device, char **path); + void -grub_machine_get_bootlocation (char **device, - char **path __attribute__ ((unused))) +grub_machine_get_bootlocation (char **device, char **path) { char *ptr; @@ -55,7 +56,8 @@ grub_machine_get_bootlocation (char **device, partition number encoded at the install time. */ if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL) { - *device = grub_strdup ("pxe"); + if (grub_pc_net_config) + grub_pc_net_config (device, path); return; } diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index 144df964c..51f4023a6 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -28,6 +28,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -45,6 +46,22 @@ struct grub_pxe_undi_open grub_uint8_t mcast[8][6]; } __attribute__ ((packed)); +struct grub_pxe_undi_info +{ + grub_uint16_t status; + grub_uint16_t base_io; + grub_uint16_t int_number; + grub_uint16_t mtu; + grub_uint16_t hwtype; + grub_uint16_t hwaddrlen; + grub_uint8_t current_addr[16]; + grub_uint8_t permanent_addr[16]; + grub_uint32_t romaddr; + grub_uint16_t rxbufct; + grub_uint16_t txbufct; +} __attribute__ ((packed)); + + struct grub_pxe_undi_isr { grub_uint16_t status; @@ -259,7 +276,7 @@ struct grub_net_card grub_pxe_card = void grub_pxe_unload (void) { - if (grub_pxe_pxenv) + if (pxe_rm_entry) { grub_pxe_call (GRUB_PXENV_UNDI_CLOSE, (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, @@ -269,17 +286,11 @@ grub_pxe_unload (void) } } -GRUB_MOD_INIT(pxe) +static void +grub_pc_net_config_real (char **device, char **path) { - struct grub_pxe_bangpxe *pxenv; - struct grub_pxenv_get_cached_info ci; struct grub_net_bootp_packet *bp; - struct grub_pxe_undi_open *ou; - - pxenv = grub_pxe_scan (); - if (! pxenv) - return; - + struct grub_pxenv_get_cached_info ci; ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK; ci.buffer = 0; ci.buffer_size = 0; @@ -289,9 +300,41 @@ GRUB_MOD_INIT(pxe) bp = LINEAR (ci.buffer); - grub_memcpy (grub_pxe_card.default_address.mac, bp->mac_addr, - bp->hw_len < sizeof (grub_pxe_card.default_address.mac) - ? bp->hw_len : sizeof (grub_pxe_card.default_address.mac)); + grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, 0, + bp, GRUB_PXE_BOOTP_SIZE, + 1, device, path); +} + +GRUB_MOD_INIT(pxe) +{ + struct grub_pxe_bangpxe *pxenv; + struct grub_pxe_undi_open *ou; + struct grub_pxe_undi_info *ui; + unsigned i; + + pxenv = grub_pxe_scan (); + if (! pxenv) + return; + + ui = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + grub_memset (ui, 0, sizeof (*ui)); + grub_pxe_call (GRUB_PXENV_UNDI_GET_INFORMATION, ui, pxe_rm_entry); + + grub_memcpy (grub_pxe_card.default_address.mac, ui->current_addr, + sizeof (grub_pxe_card.default_address.mac)); + for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++) + if (grub_pxe_card.default_address.mac[i] != 0) + break; + if (i != sizeof (grub_pxe_card.default_address.mac)) + { + for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++) + if (grub_pxe_card.default_address.mac[i] != 0xff) + break; + } + if (i == sizeof (grub_pxe_card.default_address.mac)) + grub_memcpy (grub_pxe_card.default_address.mac, ui->permanent_addr, + sizeof (grub_pxe_card.default_address.mac)); + grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; @@ -303,11 +346,11 @@ GRUB_MOD_INIT(pxe) return; grub_net_card_register (&grub_pxe_card); - grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, 0, - bp, GRUB_PXE_BOOTP_SIZE); + grub_pc_net_config = grub_pc_net_config_real; } GRUB_MOD_FINI(pxe) { + grub_pc_net_config = 0; grub_pxe_unload (); } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 2ecb709b9..a56860eed 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -664,6 +664,7 @@ grub_net_open_real (const char *name) else ret->server = NULL; ret->fs = &grub_net_fs; + ret->offset = 0; return ret; } } @@ -784,7 +785,7 @@ grub_net_poll_cards (unsigned time) /* Read from the packets list*/ static grub_ssize_t -grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) +grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) { grub_net_socket_t sock = file->device->net->socket; struct grub_net_buff *nb; @@ -802,6 +803,7 @@ grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) amount = len; len -= amount; total += amount; + file->device->net->offset += amount; if (buf) { grub_memcpy (ptr, nb->data, amount); @@ -829,28 +831,40 @@ grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) return total; } -/* Read from the packets list*/ static grub_err_t grub_net_seek_real (struct grub_file *file, grub_off_t offset) { grub_net_socket_t sock = file->device->net->socket; struct grub_net_buff *nb; - grub_size_t len = offset - file->offset; + grub_size_t len = offset - file->device->net->offset; if (!len) return GRUB_ERR_NONE; /* We cant seek backwards past the current packet. */ - if (file->offset > offset) + if (file->device->net->offset > offset) { nb = sock->packs.first->nb; - return grub_netbuff_push (nb, file->offset - offset); + return grub_netbuff_push (nb, file->device->net->offset - offset); } - grub_net_fs_read (file, NULL, len); + grub_net_fs_read_real (file, NULL, len); return GRUB_ERR_NONE; } +static grub_ssize_t +grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) +{ + if (file->offset != file->device->net->offset) + { + grub_err_t err; + err = grub_net_seek_real (file, file->offset); + if (err) + return err; + } + return grub_net_fs_read_real (file, buf, len); +} + static char * grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), const char *val __attribute__ ((unused))) @@ -1384,7 +1398,6 @@ GRUB_MOD_INIT(net) grub_fs_register (&grub_net_fs); grub_net_open = grub_net_open_real; - grub_file_net_seek = grub_net_seek_real; grub_grubnet_fini = grub_grubnet_fini_real; } @@ -1400,6 +1413,5 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_getdhcp); grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; - grub_file_net_seek = NULL; grub_grubnet_fini = NULL; } diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 24f30eb7a..b112f643e 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -11,6 +11,13 @@ GRUB_MOD_LICENSE ("GPLv3+"); +typedef struct tftp_data +{ + grub_uint64_t file_size; + grub_uint64_t block; + grub_uint32_t block_size; +} *tftp_data_t; + static grub_err_t tftp_open (struct grub_file *file, const char *filename) { @@ -85,9 +92,9 @@ tftp_open (struct grub_file *file, const char *filename) if (file->device->net->socket->status != 0) break; /* Retry. */ - /*err = grub_net_send_udp_packet (file->device->net->socket, &nb); - if (err) - return err; */ + err = grub_net_send_udp_packet (file->device->net->socket, &nb); + if (err) + return err; } if (file->device->net->socket->status == 0) @@ -110,11 +117,11 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) nb_ack.head = nbdata; nb_ack.end = nbdata + sizeof (nbdata); - tftph = (struct tftphdr *) nb->data; switch (grub_be_to_cpu16 (tftph->opcode)) { case TFTP_OACK: + data->block_size = 512; for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;) { if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) @@ -122,6 +129,11 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1, 0, 0); } + if (grub_memcmp (ptr, "blksize\0", sizeof ("blksize\0") - 1) == 0) + { + data->block_size = grub_strtoul (ptr + sizeof ("blksize\0") - 1, + 0, 0); + } while (ptr < nb->tail && *ptr) ptr++; ptr++; @@ -139,12 +151,12 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) { data->block++; unsigned size = nb->tail - nb->data; - if (size < 1024) + if (size < data->block_size) sock->status = 2; /* Prevent garbage in broken cards. */ - if (size > 1024) + if (size > data->block_size) { - err = grub_netbuff_unput (nb, size - 1024); + err = grub_netbuff_unput (nb, size - data->block_size); if (err) return err; } diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h index 1de37a5d5..dd50aa833 100644 --- a/include/grub/i386/pc/kernel.h +++ b/include/grub/i386/pc/kernel.h @@ -44,6 +44,8 @@ extern grub_int32_t grub_install_bsd_part; /* The boot BIOS drive number. */ extern grub_uint8_t EXPORT_VAR(grub_boot_drive); +extern void (*EXPORT_VAR(grub_pc_net_config)) (char **device, char **path); + #endif /* ! ASM_FILE */ #endif /* ! KERNEL_MACHINE_HEADER */ diff --git a/include/grub/net.h b/include/grub/net.h index 6aaf391d5..494826625 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -242,11 +242,11 @@ typedef struct grub_net char *server; grub_net_app_level_t protocol; grub_net_socket_t socket; + grub_off_t offset; grub_fs_t fs; } *grub_net_t; extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); -extern grub_err_t (*EXPORT_VAR (grub_file_net_seek)) (struct grub_file *file, grub_off_t offset); extern void (*EXPORT_VAR (grub_grubnet_fini)) (void); struct grub_net_network_level_interface diff --git a/include/grub/net/tftp.h b/include/grub/net/tftp.h index c67380817..0d8cbd1de 100644 --- a/include/grub/net/tftp.h +++ b/include/grub/net/tftp.h @@ -43,12 +43,6 @@ /* * own here because this is cleaner, and maps to the same data layout. * */ -typedef struct tftp_data - { - int file_size; - int block; - } *tftp_data_t; - struct tftphdr { grub_uint16_t opcode; From cbe20661f64d0820c3768ec1fe319436be192f22 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 2 Jul 2011 18:05:40 +0200 Subject: [PATCH 379/406] minor stylistic cleanup --- grub-core/net/tftp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index b112f643e..700f0effd 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -75,7 +75,8 @@ tftp_open (struct grub_file *file, const char *filename) rrq += grub_strlen ("0") + 1; hdrlen = sizeof (tftph->opcode) + rrqlen; - if ((err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen))) != GRUB_ERR_NONE) + err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen)); + if (err) return err; file->device->net->socket->out_port = TFTP_SERVER_PORT; From 0c51bb63c5ef4555dab8aeedcaed309160111cd7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 2 Jul 2011 18:57:24 +0200 Subject: [PATCH 380/406] add missing brackets in efi_wrap macroses --- include/grub/efi/api.h | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index 5cd1686ea..b20baa015 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -1359,27 +1359,31 @@ typedef struct grub_efi_block_io grub_efi_block_io_t; #define efi_call_0(func) \ efi_wrap_0(func) #define efi_call_1(func, a) \ - efi_wrap_1(func, (grub_uint64_t) a) + efi_wrap_1(func, (grub_uint64_t) (a)) #define efi_call_2(func, a, b) \ - efi_wrap_2(func, (grub_uint64_t) a, (grub_uint64_t) b) + efi_wrap_2(func, (grub_uint64_t) (a), (grub_uint64_t) (b)) #define efi_call_3(func, a, b, c) \ - efi_wrap_3(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c) + efi_wrap_3(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \ + (grub_uint64_t) (c)) #define efi_call_4(func, a, b, c, d) \ - efi_wrap_4(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ - (grub_uint64_t) d) + efi_wrap_4(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \ + (grub_uint64_t) (c), (grub_uint64_t) (d)) #define efi_call_5(func, a, b, c, d, e) \ - efi_wrap_5(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ - (grub_uint64_t) d, (grub_uint64_t) e) + efi_wrap_5(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \ + (grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e)) #define efi_call_6(func, a, b, c, d, e, f) \ - efi_wrap_6(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ - (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f) + efi_wrap_6(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \ + (grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e), \ + (grub_uint64_t) (f)) #define efi_call_7(func, a, b, c, d, e, f, g) \ - efi_wrap_7(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ - (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f, (grub_uint64_t) g) + efi_wrap_7(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \ + (grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e), \ + (grub_uint64_t) (f), (grub_uint64_t) (g)) #define efi_call_10(func, a, b, c, d, e, f, g, h, i, j) \ - efi_wrap_10(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ - (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f, (grub_uint64_t) g, \ - (grub_uint64_t) h, (grub_uint64_t) i, (grub_uint64_t) j) + efi_wrap_10(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \ + (grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e), \ + (grub_uint64_t) (f), (grub_uint64_t) (g), (grub_uint64_t) (h), \ + (grub_uint64_t) (i), (grub_uint64_t) (j)) grub_uint64_t EXPORT_FUNC(efi_wrap_0) (void *func); grub_uint64_t EXPORT_FUNC(efi_wrap_1) (void *func, grub_uint64_t arg1); From c4d038f632e39faba9506122af29d926cff9267e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 2 Jul 2011 20:11:29 +0200 Subject: [PATCH 381/406] Don't react to adressed bootp packets unless in bootp transaction --- grub-core/kern/emu/main.c | 10 +++++--- grub-core/net/ip.c | 51 +++++++++++++++++++-------------------- grub-core/net/net.c | 12 ++++----- grub-core/net/udp.c | 7 +++--- include/grub/net.h | 2 +- 5 files changed, 43 insertions(+), 39 deletions(-) diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c index 096e97090..2092d03cb 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -49,7 +49,7 @@ static jmp_buf main_env; /* Store the prefix specified by an argument. */ -static char *root_dev = NULL, *dir = DEFAULT_DIRECTORY; +static char *root_dev = NULL, *dir = NULL; int grub_no_autoload; @@ -139,14 +139,18 @@ main (int argc, char *argv[]) set_program_name (argv[0]); + dir = xstrdup (DEFAULT_DIRECTORY); + while ((opt = getopt_long (argc, argv, "r:d:m:vH:hV", options, 0)) != -1) switch (opt) { case 'r': - root_dev = optarg; + free (root_dev); + root_dev = xstrdup (optarg); break; case 'd': - dir = optarg; + free (dir); + dir = xstrdup (optarg); break; case 'm': dev_map = optarg; diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 776937a6e..8b06f7d11 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -65,50 +65,49 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, { struct iphdr *iph = (struct iphdr *) nb->data; grub_err_t err; - struct grub_net_network_level_interface *inf; + struct grub_net_network_level_interface *inf = NULL; err = grub_netbuff_pull (nb, sizeof (*iph)); if (err) return err; - FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + /* DHCP needs special treatment since we don't know IP yet. */ { - if (inf->card == card - && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 - && inf->address.ipv4 == iph->dest - && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) - break; + struct udphdr *udph; + udph = (struct udphdr *) nb->data; + if (iph->protocol == IP_UDP && grub_be_to_cpu16 (udph->dst) == 68) + { + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + if (inf->card == card + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV + && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) + { + err = grub_netbuff_pull (nb, sizeof (*udph)); + if (err) + return err; + grub_net_process_dhcp (nb, inf->card); + grub_netbuff_free (nb); + } + return GRUB_ERR_NONE; + } } + if (!inf) { FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { if (inf->card == card - && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && inf->address.ipv4 == iph->dest && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) - break; - } - if (!inf) - { - if (iph->protocol == IP_UDP - && grub_net_hwaddr_cmp (&card->default_address, hwaddress) == 0) - { - struct udphdr *udph; - udph = (struct udphdr *) nb->data; - err = grub_netbuff_pull (nb, sizeof (*udph)); - if (err) - return err; - if (grub_be_to_cpu16 (udph->dst) == 68) - grub_net_process_dhcp (nb, card); - } - grub_netbuff_free (nb); - return GRUB_ERR_NONE; + break; + } } switch (iph->protocol) { case IP_UDP: return grub_net_recv_udp_packet (nb, inf); - break; default: grub_netbuff_free (nb); break; diff --git a/grub-core/net/net.c b/grub-core/net/net.c index a56860eed..d5f9e374e 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -119,7 +119,7 @@ match_net (const grub_net_network_level_netaddress_t *net, return 0; switch (net->type) { - case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC: + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: return 0; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { @@ -238,8 +238,8 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf) { switch (target->type) { - case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC: - grub_strcpy (buf, "promisc"); + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: + grub_strcpy (buf, "temporary"); return; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { @@ -521,8 +521,8 @@ print_net_address (const grub_net_network_level_netaddress_t *target) { switch (target->type) { - case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC: - grub_printf ("promisc\n"); + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: + grub_printf ("temporary\n"); break; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { @@ -1257,7 +1257,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), grub_free (ifaces); return grub_errno; } - ifaces[j].address.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC; + ifaces[j].address.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV; grub_memcpy (&ifaces[j].hwaddress, &card->default_address, sizeof (ifaces[j].hwaddress)); j++; diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 95134c0cf..b9339e49a 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -32,8 +32,11 @@ grub_net_recv_udp_packet (struct grub_net_buff * nb, { struct udphdr *udph; grub_net_socket_t sock; + grub_err_t err; udph = (struct udphdr *) nb->data; - grub_netbuff_pull (nb, sizeof (*udph)); + err = grub_netbuff_pull (nb, sizeof (*udph)); + if (err) + return err; FOR_NET_SOCKETS (sock) { @@ -54,8 +57,6 @@ grub_net_recv_udp_packet (struct grub_net_buff * nb, return GRUB_ERR_NONE; } } - if (grub_be_to_cpu16 (udph->dst) == 68) - grub_net_process_dhcp (nb, inf->card); grub_netbuff_free (nb); return GRUB_ERR_NONE; } diff --git a/include/grub/net.h b/include/grub/net.h index 494826625..630fd33fb 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -123,7 +123,7 @@ struct grub_net_network_level_interface; typedef enum grub_network_level_protocol_id { - GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC, + GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV, GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 } grub_network_level_protocol_id_t; From 77546584e1466b4702a60b83df674ca4337b2627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Sutre?= Date: Sat, 2 Jul 2011 21:22:19 +0200 Subject: [PATCH 382/406] Use @PACKAGE@ instead of hardcoded name when sourcing grub-mkconfig_lib. --- ChangeLog | 14 ++++++++++++++ util/grub-mkconfig.in | 2 +- util/grub.d/00_header.in | 2 +- util/grub.d/10_hurd.in | 2 +- util/grub.d/10_kfreebsd.in | 2 +- util/grub.d/10_linux.in | 2 +- util/grub.d/10_netbsd.in | 2 +- util/grub.d/10_windows.in | 2 +- util/grub.d/20_linux_xen.in | 2 +- util/grub.d/30_os-prober.in | 2 +- util/update-grub_lib.in | 2 +- 11 files changed, 24 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4b8d8f149..e091265d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2011-07-02 GrĂ©goire Sutre + + * util/grub-mkconfig.in: Use @PACKAGE@ instead of hardcoded name when + sourcing grub-mkconfig_lib. + * util/update-grub_lib.in: Likewise. + * util/grub.d/00_header.in: Likewise. + * util/grub.d/10_hurd.in: Likewise. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + * util/grub.d/10_netbsd.in: Likewise. + * util/grub.d/10_windows.in: Likewise. + * util/grub.d/20_linux_xen.in: Likewise. + * util/grub.d/30_os-prober.in: Likewise. + 2011-06-28 Colin Watson * grub-core/term/gfxterm.c (grub_virtual_screen_setup): Use diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index 4d627c057..cf94d1065 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -95,7 +95,7 @@ do esac done -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib if [ "x$EUID" = "x" ] ; then EUID=`id -u` diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index 9da1511f5..7b8871d4d 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -25,7 +25,7 @@ libdir=@libdir@ locale_dir=`echo ${GRUB_PREFIX}/locale | sed ${transform}` grub_lang=`echo $LANG | cut -d . -f 1` -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib # Do this as early as possible, since other commands might depend on it. # (e.g. the `loadfont' command might need lvm or raid modules) diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in index 8c54eab97..9ca01f0a8 100644 --- a/util/grub.d/10_hurd.in +++ b/util/grub.d/10_hurd.in @@ -20,7 +20,7 @@ set -e prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib CLASS="--class gnu --class os" diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index 3600c74f9..2ade4ea35 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -21,7 +21,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib export TEXTDOMAIN=@PACKAGE@ export TEXTDOMAINDIR=@localedir@ diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index 1d1eb403f..97e7c6523 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -21,7 +21,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib export TEXTDOMAIN=@PACKAGE@ export TEXTDOMAINDIR=@localedir@ diff --git a/util/grub.d/10_netbsd.in b/util/grub.d/10_netbsd.in index ffd31ad93..c257aeb3c 100644 --- a/util/grub.d/10_netbsd.in +++ b/util/grub.d/10_netbsd.in @@ -21,7 +21,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib export TEXTDOMAIN=@PACKAGE@ export TEXTDOMAINDIR=@localedir@ diff --git a/util/grub.d/10_windows.in b/util/grub.d/10_windows.in index fd068dd2d..941267a9f 100644 --- a/util/grub.d/10_windows.in +++ b/util/grub.d/10_windows.in @@ -20,7 +20,7 @@ set -e prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib case "`uname 2>/dev/null`" in CYGWIN*) ;; diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in index 083391c40..c0b255598 100644 --- a/util/grub.d/20_linux_xen.in +++ b/util/grub.d/20_linux_xen.in @@ -21,7 +21,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib export TEXTDOMAIN=@PACKAGE@ export TEXTDOMAINDIR=@localedir@ diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in index d9d4b0a96..c0b5d7cd7 100644 --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in @@ -21,7 +21,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then exit 0 diff --git a/util/update-grub_lib.in b/util/update-grub_lib.in index 998452e67..430ce1308 100644 --- a/util/update-grub_lib.in +++ b/util/update-grub_lib.in @@ -18,6 +18,6 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib grub_warn "update-grub_lib is deprecated, use grub-mkconfig_lib instead" From 7e0c2d162afd175580074eb7386811e0694aaed3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 2 Jul 2011 22:13:33 +0200 Subject: [PATCH 383/406] Restructurisations, cleanups and few bugfixes --- grub-core/net/arp.c | 3 +- grub-core/net/net.c | 94 +++++++---------- grub-core/net/tftp.c | 226 ++++++++++++++++++++++++----------------- grub-core/net/udp.c | 65 +++++++++--- include/grub/net.h | 25 +++-- include/grub/net/udp.h | 16 +++ 6 files changed, 251 insertions(+), 178 deletions(-) diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index fecde3282..d726f2c3a 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -144,7 +144,8 @@ grub_net_arp_receive (struct grub_net_buff *nb) FOR_NET_NETWORK_LEVEL_INTERFACES (inf) { /* Am I the protocol address target? */ - if (grub_memcmp (target_protocol_address, &inf->address.ipv4, 6) == 0 + if (inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && grub_memcmp (target_protocol_address, &inf->address.ipv4, 4) == 0 && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) { grub_net_link_level_address_t aux; diff --git a/grub-core/net/net.c b/grub-core/net/net.c index d5f9e374e..595379a99 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -630,25 +631,27 @@ grub_net_open_real (const char *name) { protnamelen = comma - name; server = comma + 1; + protname = name; } else { protnamelen = grub_strlen (name); server = default_server; + protname = name; } } if (!server) { grub_error (GRUB_ERR_NET_BAD_ADDRESS, "no server"); return NULL; - } + } FOR_NET_APP_LEVEL (proto) { if (grub_memcmp (proto->name, protname, protnamelen) == 0 && proto->name[protnamelen] == 0) { - grub_net_t ret = grub_malloc (sizeof (*ret)); + grub_net_t ret = grub_zalloc (sizeof (*ret)); if (!ret) return NULL; ret->protocol = proto; @@ -665,6 +668,7 @@ grub_net_open_real (const char *name) ret->server = NULL; ret->fs = &grub_net_fs; ret->offset = 0; + ret->eof = 0; return ret; } } @@ -686,61 +690,26 @@ grub_net_fs_dir (grub_device_t device, const char *path __attribute__ ((unused)) static grub_err_t grub_net_fs_open (struct grub_file *file, const char *name) { - grub_err_t err; - grub_net_network_level_address_t addr; - struct grub_net_network_level_interface *inf; - grub_net_network_level_address_t gateway; - grub_net_socket_t socket; - static int port = 25300; - - err = grub_net_resolve_address (file->device->net->server, &addr); - if (err) - return err; - - err = grub_net_route_address (addr, &gateway, &inf); - if (err) - return err; - - socket = (grub_net_socket_t) grub_malloc (sizeof (*socket)); - if (socket == NULL) - return grub_errno; - - socket->inf = inf; - socket->out_nla = addr; - socket->in_port = port++; - socket->status = 0; - socket->app = file->device->net->protocol; - socket->packs.first = NULL; - socket->packs.last = NULL; - file->device->net->socket = socket; - grub_net_socket_register (socket); - - err = file->device->net->protocol->open (file,name); - if (err) - goto fail; - file->not_easily_seekable = 1; - - return GRUB_ERR_NONE; -fail: - grub_net_socket_unregister (socket); - grub_free (socket); - return err; + file->device->net->packs.first = NULL; + file->device->net->packs.last = NULL; + file->device->net->name = grub_strdup (name); + if (!file->device->net->name) + return grub_errno; + return file->device->net->protocol->open (file, name); } static grub_err_t grub_net_fs_close (grub_file_t file) { - grub_net_socket_t sock = file->device->net->socket; - while (sock->packs.first) + while (file->device->net->packs.first) { - grub_netbuff_free (sock->packs.first->nb); - grub_net_remove_packet (sock->packs.first); + grub_netbuff_free (file->device->net->packs.first->nb); + grub_net_remove_packet (file->device->net->packs.first); } - grub_net_socket_unregister (sock); - grub_free (sock); + file->device->net->protocol->close (file); + grub_free (file->device->net->name); return GRUB_ERR_NONE; - } static void @@ -787,9 +756,9 @@ grub_net_poll_cards (unsigned time) static grub_ssize_t grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) { - grub_net_socket_t sock = file->device->net->socket; + grub_net_t sock = file->device->net; struct grub_net_buff *nb; - char *ptr = buf; + char *ptr = buf; grub_size_t amount, total = 0; int try = 0; while (try <= 3) @@ -820,7 +789,7 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) if (!len) return total; } - if (sock->status == 1) + if (!sock->eof) { try++; grub_net_poll_cards (200); @@ -834,18 +803,29 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) static grub_err_t grub_net_seek_real (struct grub_file *file, grub_off_t offset) { - grub_net_socket_t sock = file->device->net->socket; - struct grub_net_buff *nb; grub_size_t len = offset - file->device->net->offset; if (!len) return GRUB_ERR_NONE; - /* We cant seek backwards past the current packet. */ if (file->device->net->offset > offset) - { - nb = sock->packs.first->nb; - return grub_netbuff_push (nb, file->device->net->offset - offset); + { + grub_err_t err; + while (file->device->net->packs.first) + { + grub_netbuff_free (file->device->net->packs.first->nb); + grub_net_remove_packet (file->device->net->packs.first); + } + file->device->net->protocol->close (file); + + file->device->net->packs.first = NULL; + file->device->net->packs.last = NULL; + file->device->net->offset = 0; + file->device->net->eof = 0; + err = file->device->net->protocol->open (file, file->device->net->name); + if (err) + return err; + len = offset; } grub_net_fs_read_real (file, NULL, len); diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 700f0effd..6ffe27669 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -16,8 +16,107 @@ typedef struct tftp_data grub_uint64_t file_size; grub_uint64_t block; grub_uint32_t block_size; + int have_oack; + grub_net_socket_t sock; } *tftp_data_t; +static grub_err_t +tftp_receive (grub_net_socket_t sock __attribute__ ((unused)), + struct grub_net_buff *nb, + void *f) +{ + grub_file_t file = f; + struct tftphdr *tftph = (void *) nb->data; + char nbdata[512]; + tftp_data_t data = file->data; + grub_err_t err; + char *ptr; + struct grub_net_buff nb_ack; + + nb_ack.head = nbdata; + nb_ack.end = nbdata + sizeof (nbdata); + + tftph = (struct tftphdr *) nb->data; + switch (grub_be_to_cpu16 (tftph->opcode)) + { + case TFTP_OACK: + data->block_size = 512; + data->have_oack = 1; + for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;) + { + if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) + { + data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1, + 0, 0); + } + if (grub_memcmp (ptr, "blksize\0", sizeof ("blksize\0") - 1) == 0) + { + data->block_size = grub_strtoul (ptr + sizeof ("blksize\0") - 1, + 0, 0); + } + while (ptr < nb->tail && *ptr) + ptr++; + ptr++; + } + data->block = 0; + grub_netbuff_free (nb); + break; + case TFTP_DATA: + err = grub_netbuff_pull (nb, sizeof (tftph->opcode) + + sizeof (tftph->u.data.block)); + if (err) + return err; + if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) + { + unsigned size = nb->tail - nb->data; + data->block++; + if (size < data->block_size) + { + file->device->net->eof = 1; + } + /* Prevent garbage in broken cards. */ + if (size > data->block_size) + { + err = grub_netbuff_unput (nb, size - data->block_size); + if (err) + return err; + } + /* If there is data, puts packet in socket list. */ + if ((nb->tail - nb->data) > 0) + grub_net_put_packet (&file->device->net->packs, nb); + else + grub_netbuff_free (nb); + } + else + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + break; + case TFTP_ERROR: + grub_netbuff_free (nb); + return grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg); + } + grub_netbuff_clear (&nb_ack); + grub_netbuff_reserve (&nb_ack, 512); + err = grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) + + sizeof (tftph->u.ack.block)); + if (err) + return err; + + tftph = (struct tftphdr *) nb_ack.data; + tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); + tftph->u.ack.block = grub_cpu_to_be16 (data->block); + + err = grub_net_send_udp_packet (data->sock, &nb_ack); + if (file->device->net->eof) + { + grub_net_udp_close (data->sock); + data->sock = NULL; + } + return err; +} + static grub_err_t tftp_open (struct grub_file *file, const char *filename) { @@ -31,17 +130,17 @@ tftp_open (struct grub_file *file, const char *filename) tftp_data_t data; grub_err_t err; - data = grub_malloc (sizeof (*data)); + data = grub_zalloc (sizeof (*data)); if (!data) return grub_errno; - file->device->net->socket->data = (void *) data; nb.head = open_data; nb.end = open_data + sizeof (open_data); grub_netbuff_clear (&nb); grub_netbuff_reserve (&nb, 1500); - if ((err = grub_netbuff_push (&nb, sizeof (*tftph))) != GRUB_ERR_NONE) + err = grub_netbuff_push (&nb, sizeof (*tftph)); + if (err) return err; tftph = (struct tftphdr *) nb.data; @@ -78,11 +177,21 @@ tftp_open (struct grub_file *file, const char *filename) err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen)); if (err) return err; - file->device->net->socket->out_port = TFTP_SERVER_PORT; - err = grub_net_send_udp_packet (file->device->net->socket, &nb); + file->not_easily_seekable = 1; + file->data = data; + data->sock = grub_net_udp_open (file->device->net->server, + TFTP_SERVER_PORT, tftp_receive, + file); + if (!data->sock) + return grub_errno; + + err = grub_net_send_udp_packet (data->sock, &nb); if (err) - return err; + { + grub_net_udp_close (data->sock); + return err; + } /* Receive OACK packet. */ for (i = 0; i < 3; i++) @@ -90,106 +199,34 @@ tftp_open (struct grub_file *file, const char *filename) grub_net_poll_cards (100); if (grub_errno) return grub_errno; - if (file->device->net->socket->status != 0) + if (data->have_oack) break; /* Retry. */ - err = grub_net_send_udp_packet (file->device->net->socket, &nb); + err = grub_net_send_udp_packet (data->sock, &nb); if (err) - return err; + { + grub_net_udp_close (data->sock); + return err; + } } - if (file->device->net->socket->status == 0) - return grub_error (GRUB_ERR_TIMEOUT, "Time out opening tftp."); + if (!data->have_oack) + { + grub_net_udp_close (data->sock); + return grub_error (GRUB_ERR_TIMEOUT, "Time out opening tftp."); + } file->size = data->file_size; return GRUB_ERR_NONE; } static grub_err_t -tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) +tftp_close (struct grub_file *file) { - struct tftphdr *tftph; - char nbdata[128]; - tftp_data_t data = sock->data; - grub_err_t err; - char *ptr; - struct grub_net_buff nb_ack; - - nb_ack.head = nbdata; - nb_ack.end = nbdata + sizeof (nbdata); - - tftph = (struct tftphdr *) nb->data; - switch (grub_be_to_cpu16 (tftph->opcode)) - { - case TFTP_OACK: - data->block_size = 512; - for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;) - { - if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) - { - data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1, - 0, 0); - } - if (grub_memcmp (ptr, "blksize\0", sizeof ("blksize\0") - 1) == 0) - { - data->block_size = grub_strtoul (ptr + sizeof ("blksize\0") - 1, - 0, 0); - } - while (ptr < nb->tail && *ptr) - ptr++; - ptr++; - } - sock->status = 1; - data->block = 0; - grub_netbuff_clear (nb); - break; - case TFTP_DATA: - err = grub_netbuff_pull (nb, sizeof (tftph->opcode) + - sizeof (tftph->u.data.block)); - if (err) - return err; - if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) - { - data->block++; - unsigned size = nb->tail - nb->data; - if (size < data->block_size) - sock->status = 2; - /* Prevent garbage in broken cards. */ - if (size > data->block_size) - { - err = grub_netbuff_unput (nb, size - data->block_size); - if (err) - return err; - } - } - else - grub_netbuff_clear (nb); - - break; - case TFTP_ERROR: - grub_netbuff_clear (nb); - return grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg); - break; - } - grub_netbuff_clear (&nb_ack); - grub_netbuff_reserve (&nb_ack, 128); - err = grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) - + sizeof (tftph->u.ack.block)); - if (err) - return err; - - tftph = (struct tftphdr *) nb_ack.data; - tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); - tftph->u.ack.block = grub_cpu_to_be16 (data->block); - - err = grub_net_send_udp_packet (sock, &nb_ack); - return err; -} - -static grub_err_t -tftp_close (struct grub_file *file __attribute__ ((unused))) -{ - grub_free (file->device->net->socket->data); + tftp_data_t data = file->data; + if (data->sock) + grub_net_udp_close (data->sock); + grub_free (data); return GRUB_ERR_NONE; } @@ -197,7 +234,6 @@ static struct grub_net_app_protocol grub_tftp_protocol = { .name = "tftp", .open = tftp_open, - .read = tftp_receive, .close = tftp_close }; diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index b9339e49a..47a67a967 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -4,6 +4,46 @@ #include #include +grub_net_socket_t +grub_net_udp_open (char *server, + grub_uint16_t out_port, + grub_err_t (*recv_hook) (grub_net_socket_t sock, + struct grub_net_buff *nb, + void *data), + void *recv_hook_data) +{ + grub_err_t err; + grub_net_network_level_address_t addr; + struct grub_net_network_level_interface *inf; + grub_net_network_level_address_t gateway; + grub_net_socket_t socket; + static int in_port = 25300; + + err = grub_net_resolve_address (server, &addr); + if (err) + return NULL; + + err = grub_net_route_address (addr, &gateway, &inf); + if (err) + return NULL; + + socket = grub_zalloc (sizeof (*socket)); + if (socket == NULL) + return NULL; + + socket->x_out_port = out_port; + socket->x_inf = inf; + socket->x_out_nla = addr; + socket->x_in_port = in_port++; + socket->x_status = GRUB_NET_SOCKET_START; + socket->recv_hook = recv_hook; + socket->recv_hook_data = recv_hook_data; + + grub_net_socket_register (socket); + + return socket; +} + grub_err_t grub_net_send_udp_packet (const grub_net_socket_t socket, struct grub_net_buff *nb) @@ -16,14 +56,14 @@ grub_net_send_udp_packet (const grub_net_socket_t socket, return err; udph = (struct udphdr *) nb->data; - udph->src = grub_cpu_to_be16 (socket->in_port); - udph->dst = grub_cpu_to_be16 (socket->out_port); + udph->src = grub_cpu_to_be16 (socket->x_in_port); + udph->dst = grub_cpu_to_be16 (socket->x_out_port); /* No chechksum. */ udph->chksum = 0; udph->len = grub_cpu_to_be16 (nb->tail - nb->data); - return grub_net_send_ip_packet (socket->inf, &(socket->out_nla), nb); + return grub_net_send_ip_packet (socket->x_inf, &(socket->x_out_nla), nb); } grub_err_t @@ -40,20 +80,17 @@ grub_net_recv_udp_packet (struct grub_net_buff * nb, FOR_NET_SOCKETS (sock) { - if (grub_be_to_cpu16 (udph->dst) == sock->in_port - && inf == sock->inf && sock->app) + if (grub_be_to_cpu16 (udph->dst) == sock->x_in_port + && inf == sock->x_inf && sock->recv_hook) { - if (sock->status == 0) - sock->out_port = grub_be_to_cpu16 (udph->src); + if (sock->x_status == GRUB_NET_SOCKET_START) + { + sock->x_out_port = grub_be_to_cpu16 (udph->src); + sock->x_status = GRUB_NET_SOCKET_ESTABLISHED; + } /* App protocol remove its own reader. */ - sock->app->read (sock, nb); - - /* If there is data, puts packet in socket list. */ - if ((nb->tail - nb->data) > 0) - grub_net_put_packet (&sock->packs, nb); - else - grub_netbuff_free (nb); + sock->recv_hook (sock, nb, sock->recv_hook_data); return GRUB_ERR_NONE; } } diff --git a/include/grub/net.h b/include/grub/net.h index 630fd33fb..0656787a6 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -201,22 +201,23 @@ struct grub_net_app_protocol int (*hook) (const char *filename, const struct grub_dirhook_info *info)); grub_err_t (*open) (struct grub_file *file, const char *filename); - grub_err_t (*read) (grub_net_socket_t sock, struct grub_net_buff *nb); grub_err_t (*close) (struct grub_file *file); - grub_err_t (*label) (grub_device_t device, char **label); }; struct grub_net_socket { struct grub_net_socket *next; - int status; - int in_port; - int out_port; - grub_net_app_level_t app; - grub_net_network_level_address_t out_nla; - struct grub_net_network_level_interface *inf; - grub_net_packets_t packs; - void *data; + + enum { GRUB_NET_SOCKET_START, + GRUB_NET_SOCKET_ESTABLISHED, + GRUB_NET_SOCKET_CLOSED } x_status; + int x_in_port; + int x_out_port; + grub_err_t (*recv_hook) (grub_net_socket_t sock, struct grub_net_buff *nb, + void *recv); + void *recv_hook_data; + grub_net_network_level_address_t x_out_nla; + struct grub_net_network_level_interface *x_inf; }; extern struct grub_net_socket *grub_net_sockets; @@ -240,10 +241,12 @@ grub_net_socket_unregister (grub_net_socket_t sock) typedef struct grub_net { char *server; + char *name; grub_net_app_level_t protocol; - grub_net_socket_t socket; + grub_net_packets_t packs; grub_off_t offset; grub_fs_t fs; + int eof; } *grub_net_t; extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h index eacf3325c..272612299 100644 --- a/include/grub/net/udp.h +++ b/include/grub/net/udp.h @@ -11,6 +11,22 @@ struct udphdr grub_uint16_t chksum; } __attribute__ ((packed)); + +grub_net_socket_t +grub_net_udp_open (char *server, + grub_uint16_t out_port, + grub_err_t (*recv_hook) (grub_net_socket_t sock, + struct grub_net_buff *nb, + void *data), + void *recv_hook_data); + +static inline void +grub_net_udp_close (grub_net_socket_t sock) +{ + grub_net_socket_unregister (sock); + grub_free (sock); +} + grub_err_t grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff *nb); From 671a78acb0648d3d73c95ab0f021f907499aacc0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 14:34:10 +0200 Subject: [PATCH 384/406] cleanup pxe and efi network release --- grub-core/Makefile.core.def | 6 ---- grub-core/commands/i386/pc/pxecmd.c | 54 ----------------------------- grub-core/net/drivers/efi/efinet.c | 17 ++++----- grub-core/net/drivers/i386/pc/pxe.c | 50 ++++++++++++++++++++------ grub-core/net/net.c | 13 ------- include/grub/net.h | 23 ++---------- 6 files changed, 47 insertions(+), 116 deletions(-) delete mode 100644 grub-core/commands/i386/pc/pxecmd.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 2c9f48076..7004aaf23 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -714,12 +714,6 @@ module = { common = commands/probe.c; }; -module = { - name = pxecmd; - i386_pc = commands/i386/pc/pxecmd.c; - enable = i386_pc; -}; - module = { name = read; common = commands/read.c; diff --git a/grub-core/commands/i386/pc/pxecmd.c b/grub-core/commands/i386/pc/pxecmd.c deleted file mode 100644 index dffa15a3a..000000000 --- a/grub-core/commands/i386/pc/pxecmd.c +++ /dev/null @@ -1,54 +0,0 @@ -/* pxe.c - command to control the pxe driver */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008,2009 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 - -GRUB_MOD_LICENSE ("GPLv3+"); - -static grub_err_t -grub_cmd_pxe_unload (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) -{ - if (! grub_pxe_pxenv) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no pxe environment"); - - grub_pxe_unload (); - - return 0; -} - -static grub_command_t cmd; - -GRUB_MOD_INIT(pxecmd) -{ - cmd = grub_register_command ("pxe_unload", grub_cmd_pxe_unload, - 0, - N_("Unload PXE environment.")); -} - -GRUB_MOD_FINI(pxecmd) -{ - grub_unregister_command (cmd); -} diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index 1328cd57c..4b2ffc038 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -184,23 +184,18 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, } } - GRUB_MOD_INIT(efinet) { grub_efinet_findcards (); grub_efi_net_config = grub_efi_net_config_real; } -GRUB_MOD_FINI(ofnet) +GRUB_MOD_FINI(efinet) { - struct grub_net_card *card; - grub_efi_net_config = 0; - FOR_NET_CARDS (card) - if (card->driver && !grub_strcmp (card->driver->name, "efinet")) - { - card->driver->fini (card); - card->driver = NULL; - } - grub_net_card_driver_unregister (&efidriver); + struct grub_net_card *card, *next; + + FOR_NET_CARDS_SAFE (card, next) + if (card->driver && grub_strcmp (card->driver->name, "efinet") == 0) + grub_net_card_unregister (card); } diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index 51f4023a6..81607eb57 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -22,8 +22,8 @@ #include #include #include -#include #include +#include #include #include @@ -273,19 +273,36 @@ struct grub_net_card grub_pxe_card = .name = "pxe" }; -void -grub_pxe_unload (void) +static grub_err_t +grub_pxe_fini_hw (int noreturn __attribute__ ((unused))) { if (pxe_rm_entry) - { - grub_pxe_call (GRUB_PXENV_UNDI_CLOSE, - (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, - pxe_rm_entry); - grub_net_card_unregister (&grub_pxe_card); - grub_pxe_pxenv = 0; - } + grub_pxe_call (GRUB_PXENV_UNDI_CLOSE, + (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, + pxe_rm_entry); + + return GRUB_ERR_NONE; } +static grub_err_t +grub_pxe_restore_hw (void) +{ + struct grub_pxe_undi_open *ou; + ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + grub_memset (ou, 0, sizeof (*ou)); + ou->pkt_filter = 4; + grub_pxe_call (GRUB_PXENV_UNDI_OPEN, ou, pxe_rm_entry); + + if (ou->status) + { + grub_net_card_unregister (&grub_pxe_card); + return grub_error (GRUB_ERR_IO, "can't open UNDI"); + } + return GRUB_ERR_NONE; +} + +static void *fini_hnd; + static void grub_pc_net_config_real (char **device, char **path) { @@ -303,6 +320,7 @@ grub_pc_net_config_real (char **device, char **path) grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, 0, bp, GRUB_PXE_BOOTP_SIZE, 1, device, path); + } GRUB_MOD_INIT(pxe) @@ -347,10 +365,20 @@ GRUB_MOD_INIT(pxe) grub_net_card_register (&grub_pxe_card); grub_pc_net_config = grub_pc_net_config_real; + fini_hnd = grub_loader_register_preboot_hook (grub_pxe_fini_hw, + grub_pxe_restore_hw, + GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); } GRUB_MOD_FINI(pxe) { + struct grub_net_card *card, *next; + grub_pc_net_config = 0; - grub_pxe_unload (); + grub_pxe_fini_hw (0); + grub_net_card_unregister (&grub_pxe_card); + FOR_NET_CARDS_SAFE (card, next) + if (card->driver && grub_strcmp (card->driver->name, "pxe") == 0) + grub_net_card_unregister (card); + grub_loader_unregister_preboot_hook (fini_hnd); } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 595379a99..96bbd1712 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -52,7 +52,6 @@ struct grub_net_route struct grub_net_route *grub_net_routes = NULL; struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL; struct grub_net_card *grub_net_cards = NULL; -struct grub_net_card_driver *grub_net_card_drivers = NULL; struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; static struct grub_fs grub_net_fs; @@ -1321,16 +1320,6 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), return err; } -static void -grub_grubnet_fini_real (void) -{ - struct grub_net_card *card; - - FOR_NET_CARDS (card) - if (card->driver) - card->driver->fini (card); -} - static struct grub_fs grub_net_fs = { .name = "netfs", @@ -1378,7 +1367,6 @@ GRUB_MOD_INIT(net) grub_fs_register (&grub_net_fs); grub_net_open = grub_net_open_real; - grub_grubnet_fini = grub_grubnet_fini_real; } GRUB_MOD_FINI(net) @@ -1393,5 +1381,4 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_getdhcp); grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; - grub_grubnet_fini = NULL; } diff --git a/include/grub/net.h b/include/grub/net.h index 0656787a6..e9a3793db 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -60,32 +60,12 @@ struct grub_net_card_driver { struct grub_net_card_driver *next; char *name; - grub_err_t (*init) (struct grub_net_card *dev); - grub_err_t (*fini) (struct grub_net_card *dev); grub_err_t (*send) (const struct grub_net_card *dev, struct grub_net_buff *buf); grub_ssize_t (*recv) (const struct grub_net_card *dev, struct grub_net_buff *buf); }; -extern struct grub_net_card_driver *grub_net_card_drivers; - -static inline void -grub_net_card_driver_register (struct grub_net_card_driver *driver) -{ - grub_list_push (GRUB_AS_LIST_P (&grub_net_card_drivers), - GRUB_AS_LIST (driver)); -} - -static inline void -grub_net_card_driver_unregister (struct grub_net_card_driver *driver) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_card_drivers), - GRUB_AS_LIST (driver)); -} - -#define FOR_NET_CARD_DRIVERS(var) for (var = grub_net_card_drivers; var; var = var->next) - typedef struct grub_net_packet { struct grub_net_packet *next; @@ -250,7 +230,6 @@ typedef struct grub_net } *grub_net_t; extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); -extern void (*EXPORT_VAR (grub_grubnet_fini)) (void); struct grub_net_network_level_interface { @@ -350,6 +329,8 @@ grub_net_card_unregister (struct grub_net_card *card) } #define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) +#define FOR_NET_CARDS_SAFE(var, next) for (var = grub_net_cards, next = var->next; var; var = next, next = var->next) + struct grub_net_session * grub_net_open_tcp (char *address, grub_uint16_t port); From 275f8264e42781db403a26871462a6a25e53bb50 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 14:55:28 +0200 Subject: [PATCH 385/406] Prevent garbage from getting into aout header --- util/grub-mkimage.c | 1 + 1 file changed, 1 insertion(+) diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 9fc37df2b..042bcf2df 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -1278,6 +1278,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], aout_size = core_size + sizeof (*aout_head); aout_img = xmalloc (aout_size); aout_head = aout_img; + grub_memset (aout_head, 0, sizeof (*aout_head)); aout_head->a_midmag = grub_host_to_target32 ((AOUT_MID_SUN << 16) | AOUT32_OMAGIC); aout_head->a_text = grub_host_to_target32 (core_size); From 382077365b92c5727f748dcd87f90ea30dd320ad Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 15:10:47 +0200 Subject: [PATCH 386/406] Fix mod_gap definition --- include/grub/offsets.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/grub/offsets.h b/include/grub/offsets.h index c04961fc6..e8170fcbe 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -169,7 +169,7 @@ /* Non-zero value is only needed for PowerMacs. */ #define GRUB_KERNEL_I386_IEEE1275_MOD_GAP 0x0 #define GRUB_KERNEL_I386_COREBOOT_MOD_GAP 0x0 -#define GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP 0x0 +#define GRUB_KERNEL_SPARC64_IEEE1275_MOD_GAP 0x0 #define GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN 0x1000 #define GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN 0x1 @@ -181,7 +181,7 @@ /* Minimal gap between _end and the start of the modules. It's a hack for PowerMac to prevent "CLAIM failed" error. The real fix is to rewrite grub-mkimage to generate valid ELF files. */ -#define GRUB_KERNEL_SPARC64_IEEE1275_MOD_GAP 0x8000 +#define GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP 0x8000 #ifdef GRUB_MACHINE #define GRUB_OFFSETS_CONCAT_(a,b,c) a ## b ## c From 0bc2cd0f82b274ab67fea73da9c5ead92b63a05f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 16:37:14 +0200 Subject: [PATCH 387/406] Reintroduce open/close of net cards. Clean up ofnet. --- grub-core/Makefile.am | 3 - grub-core/kern/ieee1275/init.c | 44 +++--- grub-core/kern/ieee1275/openfw.c | 111 ++++++++------ grub-core/net/drivers/efi/efinet.c | 2 +- grub-core/net/drivers/i386/pc/pxe.c | 54 ++----- grub-core/net/drivers/ieee1275/ofnet.c | 203 +++++++++++++------------ grub-core/net/ethernet.c | 10 +- grub-core/net/net.c | 71 ++++++++- include/grub/i386/pc/pxe.h | 2 - include/grub/ieee1275/ieee1275.h | 10 +- include/grub/ieee1275/ofnet.h | 66 -------- include/grub/net.h | 22 +-- 12 files changed, 313 insertions(+), 285 deletions(-) delete mode 100644 include/grub/ieee1275/ofnet.h diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index c3ecba9cf..2edf85a50 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -115,7 +115,6 @@ endif if COND_i386_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h @@ -175,7 +174,6 @@ endif if COND_powerpc_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h @@ -183,7 +181,6 @@ endif if COND_sparc64_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index 3c6332553..81b06c88e 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -77,25 +76,16 @@ grub_translate_ieee1275_path (char *filepath) } } +void (*grub_ieee1275_net_config) (const char *dev, + char **device, + char **path); void grub_machine_get_bootlocation (char **device, char **path) { char bootpath[64]; /* XXX check length */ char *filename; - grub_bootp_t bootp_pckt; - - /* Set the net prefix when possible. */ - if (grub_getbootp && (bootp_pckt = grub_getbootp())) - { - grub_uint32_t n = bootp_pckt->siaddr; - char addr[GRUB_NET_MAX_STR_ADDR_LEN]; - grub_snprintf (addr, GRUB_NET_MAX_STR_ADDR_LEN, "%d.%d.%d.%d", - ((n >> 24) & 0xff), ((n >> 16) & 0xff), - ((n >> 8) & 0xff), ((n >> 0) & 0xff)); - *device = grub_xasprintf ("(tftp,%s)", addr); - return; - } - + char *type; + if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath, sizeof (bootpath), 0)) { @@ -106,7 +96,27 @@ grub_machine_get_bootlocation (char **device, char **path) /* Transform an OF device path to a GRUB path. */ - *device = grub_ieee1275_encode_devname (bootpath); + type = grub_ieee1275_get_device_type (bootpath); + if (type && grub_strcmp (type, "network") == 0) + { + char *dev, *canon; + char *ptr; + dev = grub_ieee1275_get_aliasdevname (bootpath); + canon = grub_ieee1275_canonicalise_devname (dev); + ptr = canon + grub_strlen (canon) - 1; + while (ptr > canon && (*ptr == ',' || *ptr == ':')) + ptr--; + ptr++; + *ptr = 0; + + if (grub_ieee1275_net_config) + grub_ieee1275_net_config (canon, device, path); + grub_free (dev); + grub_free (canon); + } + else + *device = grub_ieee1275_encode_devname (bootpath); + grub_free (type); filename = grub_ieee1275_get_filename (bootpath); if (filename) @@ -264,8 +274,6 @@ grub_machine_init (void) void grub_machine_fini (void) { - if (grub_grubnet_fini) - grub_grubnet_fini (); grub_ofdisk_fini (); grub_console_fini (); } diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 8fc373c55..2cecd8c7f 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -22,16 +22,15 @@ #include #include #include -#include #include #include -grub_bootp_t (*grub_getbootp) (void); enum grub_ieee1275_parse_type { GRUB_PARSE_FILENAME, GRUB_PARSE_PARTITION, - GRUB_PARSE_DEVICE + GRUB_PARSE_DEVICE, + GRUB_PARSE_DEVICE_TYPE }; /* Walk children of 'devpath', calling hook for each. */ @@ -322,14 +321,9 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype) { char type[64]; /* XXX check size. */ char *device = grub_ieee1275_get_devname (path); - char *args = grub_ieee1275_get_devargs (path); char *ret = 0; grub_ieee1275_phandle_t dev; - if (!args) - /* Shouldn't happen. */ - return 0; - /* We need to know what type of device it is in order to parse the full file path properly. */ if (grub_ieee1275_finddevice (device, &dev)) @@ -344,55 +338,86 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype) goto fail; } - if (!grub_strcmp ("block", type)) + switch (ptype) { - /* The syntax of the device arguments is defined in the CHRP and PReP - IEEE1275 bindings: "[partition][,[filename]]". */ - char *comma = grub_strchr (args, ','); + case GRUB_PARSE_DEVICE: + ret = grub_strdup (device); + break; + case GRUB_PARSE_DEVICE_TYPE: + ret = grub_strdup (type); + break; + case GRUB_PARSE_FILENAME: + { + char *comma; + char *args; - if (ptype == GRUB_PARSE_FILENAME) - { - if (comma) - { - char *filepath = comma + 1; + if (grub_strcmp ("block", type) != 0) + goto unknown; - /* Make sure filepath has leading backslash. */ - if (filepath[0] != '\\') - ret = grub_xasprintf ("\\%s", filepath); - else - ret = grub_strdup (filepath); + args = grub_ieee1275_get_devargs (path); + if (!args) + /* Shouldn't happen. */ + return 0; + + /* The syntax of the device arguments is defined in the CHRP and PReP + IEEE1275 bindings: "[partition][,[filename]]". */ + comma = grub_strchr (args, ','); + + if (comma) + { + char *filepath = comma + 1; + + /* Make sure filepath has leading backslash. */ + if (filepath[0] != '\\') + ret = grub_xasprintf ("\\%s", filepath); + else + ret = grub_strdup (filepath); } + grub_free (args); } - else if (ptype == GRUB_PARSE_PARTITION) - { - if (!comma) - ret = grub_strdup (args); - else - ret = grub_strndup (args, (grub_size_t)(comma - args)); - /* Consistently provide numbered partitions to GRUB. - OpenBOOT traditionally uses alphabetical partition - specifiers. */ - if (ret[0] >= 'a' && ret[0] <= 'z') - ret[0] = '1' + (ret[0] - 'a'); - } - } + break; + case GRUB_PARSE_PARTITION: + { + char *comma; + char *args; - else if (!grub_strcmp ("network", type)) - { - if (ptype == GRUB_PARSE_DEVICE) - ret = grub_strdup(device); - } - else - { + if (grub_strcmp ("block", type) != 0) + goto unknown; + + args = grub_ieee1275_get_devargs (path); + if (!args) + /* Shouldn't happen. */ + return 0; + + comma = grub_strchr (args, ','); + if (!comma) + ret = grub_strdup (args); + else + ret = grub_strndup (args, (grub_size_t)(comma - args)); + /* Consistently provide numbered partitions to GRUB. + OpenBOOT traditionally uses alphabetical partition + specifiers. */ + if (ret[0] >= 'a' && ret[0] <= 'z') + ret[0] = '1' + (ret[0] - 'a'); + grub_free (args); + } + break; + default: + unknown: grub_printf ("Unsupported type %s for device %s\n", type, device); } fail: grub_free (device); - grub_free (args); return ret; } +char * +grub_ieee1275_get_device_type (const char *path) +{ + return grub_ieee1275_parse_args (path, GRUB_PARSE_DEVICE_TYPE); +} + char * grub_ieee1275_get_aliasdevname (const char *path) { diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index 4b2ffc038..5c6aac608 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -195,7 +195,7 @@ GRUB_MOD_FINI(efinet) struct grub_net_card *card, *next; FOR_NET_CARDS_SAFE (card, next) - if (card->driver && grub_strcmp (card->driver->name, "efinet") == 0) + if (card->driver == &efidriver) grub_net_card_unregister (card); } diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index 81607eb57..aa10cbbfa 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -261,20 +260,8 @@ grub_pxe_send (const struct grub_net_card *dev __attribute__ ((unused)), return 0; } -struct grub_net_card_driver grub_pxe_card_driver = -{ - .send = grub_pxe_send, - .recv = grub_pxe_recv -}; - -struct grub_net_card grub_pxe_card = -{ - .driver = &grub_pxe_card_driver, - .name = "pxe" -}; - static grub_err_t -grub_pxe_fini_hw (int noreturn __attribute__ ((unused))) +grub_pxe_close (const struct grub_net_card *dev __attribute__ ((unused))) { if (pxe_rm_entry) grub_pxe_call (GRUB_PXENV_UNDI_CLOSE, @@ -285,7 +272,7 @@ grub_pxe_fini_hw (int noreturn __attribute__ ((unused))) } static grub_err_t -grub_pxe_restore_hw (void) +grub_pxe_open (const struct grub_net_card *dev __attribute__ ((unused))) { struct grub_pxe_undi_open *ou; ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; @@ -294,14 +281,23 @@ grub_pxe_restore_hw (void) grub_pxe_call (GRUB_PXENV_UNDI_OPEN, ou, pxe_rm_entry); if (ou->status) - { - grub_net_card_unregister (&grub_pxe_card); - return grub_error (GRUB_ERR_IO, "can't open UNDI"); - } + return grub_error (GRUB_ERR_IO, "can't open UNDI"); return GRUB_ERR_NONE; } -static void *fini_hnd; +struct grub_net_card_driver grub_pxe_card_driver = +{ + .open = grub_pxe_open, + .close = grub_pxe_close, + .send = grub_pxe_send, + .recv = grub_pxe_recv +}; + +struct grub_net_card grub_pxe_card = +{ + .driver = &grub_pxe_card_driver, + .name = "pxe" +}; static void grub_pc_net_config_real (char **device, char **path) @@ -355,30 +351,12 @@ GRUB_MOD_INIT(pxe) grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; - grub_memset (ou, 0, sizeof (*ou)); - ou->pkt_filter = 4; - grub_pxe_call (GRUB_PXENV_UNDI_OPEN, ou, pxe_rm_entry); - - if (ou->status) - return; - grub_net_card_register (&grub_pxe_card); grub_pc_net_config = grub_pc_net_config_real; - fini_hnd = grub_loader_register_preboot_hook (grub_pxe_fini_hw, - grub_pxe_restore_hw, - GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); } GRUB_MOD_FINI(pxe) { - struct grub_net_card *card, *next; - grub_pc_net_config = 0; - grub_pxe_fini_hw (0); grub_net_card_unregister (&grub_pxe_card); - FOR_NET_CARDS_SAFE (card, next) - if (card->driver && grub_strcmp (card->driver->name, "pxe") == 0) - grub_net_card_unregister (card); - grub_loader_unregister_preboot_hook (fini_hnd); } diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index e5a6bfcad..cc29d0987 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -17,7 +17,6 @@ */ #include -#include #include #include #include @@ -25,8 +24,15 @@ GRUB_MOD_LICENSE ("GPLv3+"); +struct grub_ofnetcard_data +{ + char *path; + grub_ieee1275_ihandle_t handle; + grub_uint32_t mtu; +}; + static grub_err_t -card_open (struct grub_net_card *dev) +card_open (const struct grub_net_card *dev) { int status; struct grub_ofnetcard_data *data = dev->data; @@ -44,14 +50,13 @@ card_open (struct grub_net_card *dev) return GRUB_ERR_NONE; } -static grub_err_t -card_close (struct grub_net_card *dev) +static void +card_close (const struct grub_net_card *dev) { struct grub_ofnetcard_data *data = dev->data; if (data->handle) grub_ieee1275_close (data->handle); - return GRUB_ERR_NONE; } static grub_err_t @@ -93,8 +98,8 @@ get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb) static struct grub_net_card_driver ofdriver = { .name = "ofnet", - .init = card_open, - .fini = card_close, + .open = card_open, + .close = card_close, .send = send_card_buffer, .recv = get_card_packet }; @@ -112,39 +117,87 @@ bootp_response_properties[] = { .name = "bootpreply-packet", .offset = 0x2a}, }; -static grub_bootp_t -grub_getbootp_real (void) +static void +grub_ieee1275_net_config_real (const char *devpath, char **device, char **path) { - grub_bootp_t packet = grub_malloc (sizeof *packet); - char *bootp_response; - grub_ssize_t size; - unsigned int i; + struct grub_net_card *card; - for (i = 0; i < ARRAY_SIZE (bootp_response_properties); i++) - if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, - bootp_response_properties[i].name, - &size) >= 0) - break; + /* FIXME: Check that it's the right card. */ + FOR_NET_CARDS (card) + { + char *bootp_response; + char *cardpath; + char *canon; - if (size < 0) - return NULL; + grub_ssize_t size = -1; + unsigned int i; - bootp_response = grub_malloc (size); - if (grub_ieee1275_get_property (grub_ieee1275_chosen, - bootp_response_properties[i].name, - bootp_response, size, 0) < 0) - return NULL; + if (card->driver != &ofdriver) + continue; - grub_memcpy (packet, bootp_response + bootp_response_properties[i].offset, sizeof (*packet)); - grub_free (bootp_response); - return packet; + cardpath = ((struct grub_ofnetcard_data *) card->data)->path; + canon = grub_ieee1275_canonicalise_devname (cardpath); + if (grub_strcmp (devpath, canon) != 0) + { + grub_free (canon); + continue; + } + grub_free (canon); + + for (i = 0; i < ARRAY_SIZE (bootp_response_properties); i++) + if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, + bootp_response_properties[i].name, + &size) >= 0) + break; + + if (size < 0) + return; + + bootp_response = grub_malloc (size); + if (!bootp_response) + { + grub_print_error (); + return; + } + if (grub_ieee1275_get_property (grub_ieee1275_chosen, + bootp_response_properties[i].name, + bootp_response, size, 0) < 0) + return; + + grub_net_configure_by_dhcp_ack (card->name, card, 0, + (struct grub_net_bootp_packet *) + &bootp_response + + bootp_response_properties[i].offset, + size - bootp_response_properties[i].offset, + 1, device, path); + return; + } +} + +static char * +find_alias (const char *fullname) +{ + char *ret = NULL; + auto int find_alias_hook (struct grub_ieee1275_devalias *alias); + + int find_alias_hook (struct grub_ieee1275_devalias *alias) + { + if (grub_strcmp (alias->path, fullname) == 0) + { + ret = grub_strdup (alias->name); + return 1; + } + return 0; + } + + grub_devalias_iterate (find_alias_hook); + grub_errno = GRUB_ERR_NONE; + return ret; } static void grub_ofnet_findcards (void) { - int i = 0; - auto int search_net_devices (struct grub_ieee1275_devalias *alias); int search_net_devices (struct grub_ieee1275_devalias *alias) @@ -155,6 +208,7 @@ grub_ofnet_findcards (void) struct grub_net_card *card; grub_ieee1275_phandle_t devhandle; grub_net_link_level_address_t lla; + char *shortname; ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data)); if (!ofdata) @@ -162,7 +216,7 @@ grub_ofnet_findcards (void) grub_print_error (); return 1; } - card = grub_malloc (sizeof (struct grub_net_card)); + card = grub_zalloc (sizeof (struct grub_net_card)); if (!card) { grub_free (ofdata); @@ -177,11 +231,19 @@ grub_ofnet_findcards (void) if (grub_ieee1275_get_integer_property (devhandle, "max-frame-size", &(ofdata->mtu), sizeof (ofdata->mtu), 0)) - return grub_error (GRUB_ERR_IO, "Couldn't retrieve mtu size."); + { + ofdata->mtu = 1500; + } - if (grub_ieee1275_get_property - (devhandle, "mac-address", &(lla.mac), 6, 0)) - return grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address."); + if (grub_ieee1275_get_property (devhandle, "mac-address", + &(lla.mac), 6, 0) + && grub_ieee1275_get_property (devhandle, "local-mac-address", + &(lla.mac), 6, 0)) + { + grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address."); + grub_print_error (); + return 0; + } lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; card->default_address = lla; @@ -189,7 +251,11 @@ grub_ofnet_findcards (void) card->driver = NULL; card->data = ofdata; card->flags = 0; - card->name = grub_xasprintf ("eth%d", i++); + shortname = find_alias (alias->path); + card->name = grub_xasprintf ("ofnet_%s", shortname ? : alias->path); + grub_free (shortname); + + card->driver = &ofdriver; grub_net_card_register (card); return 0; } @@ -200,69 +266,18 @@ grub_ofnet_findcards (void) grub_ieee1275_devices_iterate (search_net_devices); } -static void -grub_ofnet_probecards (void) -{ - struct grub_net_card *card; - struct grub_net_card_driver *driver; - struct grub_net_network_level_interface *inter; - grub_bootp_t bootp_pckt; - grub_net_network_level_address_t addr; - grub_net_network_level_netaddress_t net; - bootp_pckt = grub_getbootp (); - - /* Assign correspondent driver for each device. */ - FOR_NET_CARDS (card) - { - FOR_NET_CARD_DRIVERS (driver) - { - if (driver->init (card) == GRUB_ERR_NONE) - { - card->driver = driver; - if (bootp_pckt - && grub_memcmp (bootp_pckt->chaddr, card->default_address.mac, 6) == 0) - { - addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - addr.ipv4 = bootp_pckt->yiaddr; - grub_net_add_addr ("bootp_cli_addr", card, addr, - card->default_address, 0); - FOR_NET_NETWORK_LEVEL_INTERFACES (inter) - if (grub_strcmp (inter->name, "bootp_cli_addr") == 0) - break; - net.type = addr.type; - net.ipv4.base = addr.ipv4; - net.ipv4.masksize = 24; - grub_net_add_route ("bootp-router", net, inter); - } - break; - } - } - } - grub_free (bootp_pckt); - -} - GRUB_MOD_INIT(ofnet) { - struct grub_net_card *card; - grub_getbootp = grub_getbootp_real; - grub_net_card_driver_register (&ofdriver); grub_ofnet_findcards (); - grub_ofnet_probecards (); - FOR_NET_CARDS (card) - if (card->driver == NULL) - grub_net_card_unregister (card); + grub_ieee1275_net_config = grub_ieee1275_net_config_real; } GRUB_MOD_FINI(ofnet) { - struct grub_net_card *card; - FOR_NET_CARDS (card) - if (card->driver && !grub_strcmp (card->driver->name, "ofnet")) - { - card->driver->fini (card); - card->driver = NULL; - } - grub_net_card_driver_unregister (&ofdriver); - grub_getbootp = NULL; + struct grub_net_card *card, *next; + + FOR_NET_CARDS_SAFE (card, next) + if (card->driver && grub_strcmp (card->driver->name, "ofnet") == 0) + grub_net_card_unregister (card); + grub_ieee1275_net_config = 0; } diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index 175d0b65f..3006c9d93 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -25,7 +25,15 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, grub_memcpy (eth->src, inf->hwaddress.mac, 6); eth->type = grub_cpu_to_be16 (ethertype); - + if (!inf->card->opened) + { + err = GRUB_ERR_NONE; + if (inf->card->driver->open) + err = inf->card->driver->open (inf->card); + if (err) + return err; + inf->card->opened = 1; + } return inf->card->driver->send (inf->card, nb); } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 96bbd1712..a3b76cae0 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -30,6 +30,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -58,6 +59,7 @@ static struct grub_fs grub_net_fs; static inline void grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) { + inter->card->num_ifaces--; *inter->prev = inter->next; if (inter->next) inter->next->prev = inter->prev; @@ -65,6 +67,24 @@ grub_net_network_level_interface_unregister (struct grub_net_network_level_inter inter->prev = 0; } +void +grub_net_card_unregister (struct grub_net_card *card) +{ + struct grub_net_network_level_interface *inf, *next; + FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(inf, next) + if (inf->card == card) + grub_net_network_level_interface_unregister (inf); + if (card->opened) + { + if (card->driver->close) + card->driver->close (card); + card->opened = 0; + } + grub_list_remove (GRUB_AS_LIST_P (&grub_net_cards), + GRUB_AS_LIST (card)); +} + + static inline void grub_net_route_register (struct grub_net_route *route) { @@ -336,6 +356,7 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa grub_register_variable_hook (name, 0, addr_set_env); } + inter->card->num_ifaces++; inter->prev = &grub_net_network_level_interfaces; inter->next = grub_net_network_level_interfaces; if (inter->next) @@ -345,7 +366,7 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa struct grub_net_network_level_interface * grub_net_add_addr (const char *name, - const struct grub_net_card *card, + struct grub_net_card *card, grub_net_network_level_address_t addr, grub_net_link_level_address_t hwaddress, grub_net_interface_flags_t flags) @@ -714,6 +735,20 @@ grub_net_fs_close (grub_file_t file) static void receive_packets (struct grub_net_card *card) { + if (card->num_ifaces == 0) + return; + if (!card->opened) + { + grub_err_t err = GRUB_ERR_NONE; + if (card->driver->open) + err = card->driver->open (card); + if (err) + { + grub_errno = GRUB_ERR_NONE; + return; + } + card->opened = 1; + } while (1) { /* Maybe should be better have a fixed number of packets for each card @@ -926,7 +961,7 @@ parse_dhcp_vendor (const char *name, void *vend, int limit) struct grub_net_network_level_interface * grub_net_configure_by_dhcp_ack (const char *name, - const struct grub_net_card *card, + struct grub_net_card *card, grub_net_interface_flags_t flags, const struct grub_net_bootp_packet *bp, grub_size_t size, @@ -1042,7 +1077,7 @@ grub_net_configure_by_dhcp_ack (const char *name, void grub_net_process_dhcp (struct grub_net_buff *nb, - const struct grub_net_card *card) + struct grub_net_card *card) { char *name; struct grub_net_network_level_interface *inf; @@ -1228,6 +1263,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), if (j) ifaces[j].prev = &ifaces[j-1].next; ifaces[j].name = grub_xasprintf ("%s:dhcp_tmp", card->name); + card->num_ifaces++; if (!ifaces[j].name) { unsigned i; @@ -1331,6 +1367,29 @@ static struct grub_fs grub_net_fs = .uuid = NULL, .mtime = NULL, }; + +static grub_err_t +grub_net_fini_hw (int noreturn __attribute__ ((unused))) +{ + struct grub_net_card *card; + FOR_NET_CARDS (card) + if (card->opened) + { + if (card->driver->close) + card->driver->close (card); + card->opened = 0; + } + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_net_restore_hw (void) +{ + return GRUB_ERR_NONE; +} + +static void *fini_hnd; + static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; static grub_command_t cmd_lsroutes, cmd_lscards, cmd_getdhcp, cmd_bootp; static grub_command_t cmd_dhcp, cmd_lsaddr; @@ -1367,6 +1426,11 @@ GRUB_MOD_INIT(net) grub_fs_register (&grub_net_fs); grub_net_open = grub_net_open_real; + fini_hnd = grub_loader_register_preboot_hook (grub_net_fini_hw, + grub_net_restore_hw, + GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); + grub_net_fini_hw (0); + grub_loader_unregister_preboot_hook (fini_hnd); } GRUB_MOD_FINI(net) @@ -1381,4 +1445,5 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_getdhcp); grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; + grub_loader_unregister_preboot_hook (fini_hnd); } diff --git a/include/grub/i386/pc/pxe.h b/include/grub/i386/pc/pxe.h index 781b53df5..376a18962 100644 --- a/include/grub/i386/pc/pxe.h +++ b/include/grub/i386/pc/pxe.h @@ -287,8 +287,6 @@ int EXPORT_FUNC(grub_pxe_call) (int func, void * data, grub_uint32_t pxe_rm_entr extern struct grub_pxe_bangpxe *grub_pxe_pxenv; -void grub_pxe_unload (void); - #endif #endif /* GRUB_CPU_PXE_H */ diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index 87294610d..81590ee4b 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -64,12 +64,9 @@ struct grub_ieee1275_common_hdr typedef grub_uint32_t grub_ieee1275_ihandle_t; typedef grub_uint32_t grub_ieee1275_phandle_t; -struct grub_ofnetcard_data -{ - char *path; - grub_ieee1275_ihandle_t handle; - grub_uint32_t mtu; -}; +extern void (*EXPORT_VAR(grub_ieee1275_net_config)) (const char *dev, + char **device, + char **path); /* Maps a device alias to a pathname. */ extern grub_ieee1275_phandle_t EXPORT_VAR(grub_ieee1275_chosen); @@ -203,5 +200,6 @@ int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook) alias)); char *EXPORT_FUNC(grub_ieee1275_get_aliasdevname) (const char *path); char *EXPORT_FUNC(grub_ieee1275_canonicalise_devname) (const char *path); +char *EXPORT_FUNC(grub_ieee1275_get_device_type) (const char *path); #endif /* ! GRUB_IEEE1275_HEADER */ diff --git a/include/grub/ieee1275/ofnet.h b/include/grub/ieee1275/ofnet.h deleted file mode 100644 index c7284df38..000000000 --- a/include/grub/ieee1275/ofnet.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,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_OFNET_HEADER -#define GRUB_OFNET_HEADER 1 - -#include -#include -#include - -struct grub_ofnet -{ - /* The net name. */ - const char *name; - - /* The OF device string. */ - char *dev; - /*server ip*/ - char *sip; - /*client ip*/ - char *cip; - /*gateway*/ - char *gat; - /**/ - int type; -}; - -typedef struct grub_ofnet *grub_ofnet_t; - -struct grub_bootp { - grub_uint8_t op; /* 1 = BOOTREQUEST, 2 = BOOTREPLY */ - grub_uint8_t htype; /* Hardware address type. */ - grub_uint8_t hlen; /* Hardware address length */ - grub_uint8_t hops; /* Used by gateways in cross-gateway booting. */ - grub_uint32_t xid; /* Transaction ID */ - grub_uint16_t secs; /* Seconds elapsed. */ - grub_uint16_t unused; /* Unused. */ - grub_uint32_t ciaddr; /* Client IP address, */ - grub_uint32_t yiaddr; /* Client IP address filled by server. */ - grub_uint32_t siaddr; /* Server IP address. */ - grub_uint32_t giaddr; /* Gateway IP address. */ - unsigned char chaddr [16]; /* Client hardware address */ - char sname [64]; /* Server name */ - char file [128]; /* Boot filename */ - unsigned char vend [64]; -}; - -typedef struct grub_bootp* grub_bootp_t; - -extern grub_bootp_t (*EXPORT_VAR (grub_getbootp)) (void); -#endif /* ! GRUB_NET_HEADER */ diff --git a/include/grub/net.h b/include/grub/net.h index e9a3793db..85fdef365 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -60,6 +60,8 @@ struct grub_net_card_driver { struct grub_net_card_driver *next; char *name; + grub_err_t (*open) (const struct grub_net_card *dev); + void (*close) (const struct grub_net_card *dev); grub_err_t (*send) (const struct grub_net_card *dev, struct grub_net_buff *buf); grub_ssize_t (*recv) (const struct grub_net_card *dev, @@ -87,6 +89,8 @@ struct grub_net_card struct grub_net_card_driver *driver; grub_net_link_level_address_t default_address; grub_net_card_flags_t flags; + int num_ifaces; + int opened; union { struct @@ -236,7 +240,7 @@ struct grub_net_network_level_interface struct grub_net_network_level_interface *next; struct grub_net_network_level_interface **prev; char *name; - const struct grub_net_card *card; + struct grub_net_card *card; grub_net_network_level_address_t address; grub_net_link_level_address_t hwaddress; grub_net_interface_flags_t flags; @@ -284,7 +288,7 @@ grub_net_session_recv (struct grub_net_session *session, void *buf, struct grub_net_network_level_interface * grub_net_add_addr (const char *name, - const struct grub_net_card *card, + struct grub_net_card *card, grub_net_network_level_address_t addr, grub_net_link_level_address_t hwaddress, grub_net_interface_flags_t flags); @@ -321,12 +325,8 @@ grub_net_card_register (struct grub_net_card *card) GRUB_AS_LIST (card)); } -static inline void -grub_net_card_unregister (struct grub_net_card *card) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_cards), - GRUB_AS_LIST (card)); -} +void +grub_net_card_unregister (struct grub_net_card *card); #define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) #define FOR_NET_CARDS_SAFE(var, next) for (var = grub_net_cards, next = var->next; var; var = next, next = var->next) @@ -390,7 +390,7 @@ struct grub_net_bootp_packet struct grub_net_network_level_interface * grub_net_configure_by_dhcp_ack (const char *name, - const struct grub_net_card *card, + struct grub_net_card *card, grub_net_interface_flags_t flags, const struct grub_net_bootp_packet *bp, grub_size_t size, @@ -398,7 +398,7 @@ grub_net_configure_by_dhcp_ack (const char *name, void grub_net_process_dhcp (struct grub_net_buff *nb, - const struct grub_net_card *card); + struct grub_net_card *card); int grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, @@ -418,6 +418,8 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; #define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) +#define FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(var,next) for (var = grub_net_network_level_interfaces, next = var->next; var; var = next, next = var->next) + grub_err_t grub_net_send_link_layer (struct grub_net_network_level_interface *inf, struct grub_net_buff *nb, grub_net_link_level_address_t *target); From a07a81b33550ed050cbd70b18f8eb0d9177559fc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 20:24:20 +0200 Subject: [PATCH 388/406] CMOS support on sparc. * gentpl.py (cmos): Add powerpc and sparc. * grub-core/Makefile.core.def (datetime): Add lib/ieee1275/cmos.c on powerpc and sparc. * grub-core/lib/cmos_datetime.c (grub_get_datetime) [__powerpc__ || __sparc__]: Rename to grub_get_datetime_cmos. (grub_set_datetime) [__powerpc__ || __sparc__]: Likewise to grub_set_datetime_cmos. * grub-core/lib/ieee1275/cmos.c: New file. * grub-core/lib/ieee1275/datetime.c (no_ieee1275_rtc): New vaiable. (find_rtc): Set no_ieee1275_rtc on error. (grub_get_datetime): Call grub_get_datetime_cmos on error. (grub_set_datetime): Call grub_set_datetime_cmos on error. * include/grub/cmos.h (grub_cmos_read): Return grub_err_t since it may fail. Move value to argument. All users updated (grub_cmos_write): Likewise. (grub_cmos_read) [__powerpc__ || __sparc__]: Rewritten. (grub_cmos_write) [__powerpc__ || __sparc__]: Likewise. * include/grub/datetime.h [__powerpc__ || __sparc__]: Declare grub_get_datetime_cmos and grub_set_datetime_cmos. --- ChangeLog | 24 ++++++++++ gentpl.py | 4 +- grub-core/Makefile.core.def | 3 ++ grub-core/commands/i386/cmostest.c | 14 ++++-- grub-core/lib/cmos_datetime.c | 68 ++++++++++++++++++++------- grub-core/lib/ieee1275/cmos.c | 75 ++++++++++++++++++++++++++++++ grub-core/lib/ieee1275/datetime.c | 14 +++++- include/grub/cmos.h | 48 +++++++++++++++++-- include/grub/datetime.h | 7 +++ 9 files changed, 231 insertions(+), 26 deletions(-) create mode 100644 grub-core/lib/ieee1275/cmos.c diff --git a/ChangeLog b/ChangeLog index e091265d4..694a97972 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2011-07-05 Vladimir Serbinenko + + CMOS support on sparc. + + * gentpl.py (cmos): Add powerpc and sparc. + * grub-core/Makefile.core.def (datetime): Add lib/ieee1275/cmos.c on + powerpc and sparc. + * grub-core/lib/cmos_datetime.c (grub_get_datetime) + [__powerpc__ || __sparc__]: Rename to grub_get_datetime_cmos. + (grub_set_datetime) [__powerpc__ || __sparc__]: Likewise to + grub_set_datetime_cmos. + * grub-core/lib/ieee1275/cmos.c: New file. + * grub-core/lib/ieee1275/datetime.c (no_ieee1275_rtc): New vaiable. + (find_rtc): Set no_ieee1275_rtc on error. + (grub_get_datetime): Call grub_get_datetime_cmos on error. + (grub_set_datetime): Call grub_set_datetime_cmos on error. + * include/grub/cmos.h (grub_cmos_read): Return grub_err_t since it may + fail. Move value to argument. All users updated + (grub_cmos_write): Likewise. + (grub_cmos_read) [__powerpc__ || __sparc__]: Rewritten. + (grub_cmos_write) [__powerpc__ || __sparc__]: Likewise. + * include/grub/datetime.h [__powerpc__ || __sparc__]: Declare + grub_get_datetime_cmos and grub_set_datetime_cmos. + 2011-07-02 GrĂ©goire Sutre * util/grub-mkconfig.in: Use @PACKAGE@ instead of hardcoded name when diff --git a/gentpl.py b/gentpl.py index 6e2df076b..31cde1e81 100644 --- a/gentpl.py +++ b/gentpl.py @@ -30,7 +30,9 @@ GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu") # Groups based on hardware features -GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips"]; GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi") +GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips", + "sparc64_ieee1275", "powerpc_ieee1275"] +GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi") GROUPS["pci"] = GROUPS["x86"] + ["mips_loongson"] GROUPS["usb"] = GROUPS["pci"] diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index fd69e9c22..16c940c61 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1192,6 +1192,9 @@ module = { efi = lib/efi/datetime.c; sparc64_ieee1275 = lib/ieee1275/datetime.c; powerpc_ieee1275 = lib/ieee1275/datetime.c; + sparc64_ieee1275 = lib/ieee1275/cmos.c; + powerpc_ieee1275 = lib/ieee1275/cmos.c; + mips_arc = lib/arc/datetime.c; enable = noemu; }; diff --git a/grub-core/commands/i386/cmostest.c b/grub-core/commands/i386/cmostest.c index c79bd0387..6439159bd 100644 --- a/grub-core/commands/i386/cmostest.c +++ b/grub-core/commands/i386/cmostest.c @@ -46,12 +46,17 @@ grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)), { int byte, bit; grub_err_t err; + grub_uint8_t value; err = parse_args (argc, argv, &byte, &bit); if (err) return err; - if (grub_cmos_read (byte) & (1 << bit)) + err = grub_cmos_read (byte, &value); + if (err) + return err; + + if (value & (1 << bit)) return GRUB_ERR_NONE; return grub_error (GRUB_ERR_TEST_FAILURE, "false"); @@ -63,13 +68,16 @@ grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)), { int byte, bit; grub_err_t err; + grub_uint8_t value; err = parse_args (argc, argv, &byte, &bit); + if (err) + return err; + err = grub_cmos_read (byte, &value); if (err) return err; - grub_cmos_write (byte, grub_cmos_read (byte) & (~(1 << bit))); - return GRUB_ERR_NONE; + return grub_cmos_write (byte, value & (~(1 << bit))); } static grub_command_t cmd, cmd_clean; diff --git a/grub-core/lib/cmos_datetime.c b/grub-core/lib/cmos_datetime.c index 73c5a03c0..86cd91180 100644 --- a/grub-core/lib/cmos_datetime.c +++ b/grub-core/lib/cmos_datetime.c @@ -23,30 +23,44 @@ GRUB_MOD_LICENSE ("GPLv3+"); +#if !defined (__powerpc__) && !defined (__sparc__) +#define grub_get_datetime_cmos grub_get_datetime +#define grub_set_datetime_cmos grub_set_datetime +#endif + grub_err_t -grub_get_datetime (struct grub_datetime *datetime) +grub_get_datetime_cmos (struct grub_datetime *datetime) { int is_bcd, is_12hour; grub_uint8_t value, flag; + grub_err_t err; - flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B); + err = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B, &flag); + if (err) + return err; is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY); - value = grub_cmos_read (GRUB_CMOS_INDEX_YEAR); + err = grub_cmos_read (GRUB_CMOS_INDEX_YEAR, &value); + if (err) + return err; if (is_bcd) value = grub_bcd_to_num (value); datetime->year = value; datetime->year += (value < 80) ? 2000 : 1900; - value = grub_cmos_read (GRUB_CMOS_INDEX_MONTH); + err = grub_cmos_read (GRUB_CMOS_INDEX_MONTH, &value); + if (err) + return err; if (is_bcd) value = grub_bcd_to_num (value); datetime->month = value; - value = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH); + err = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH, &value); + if (err) + return err; if (is_bcd) value = grub_bcd_to_num (value); @@ -54,7 +68,9 @@ grub_get_datetime (struct grub_datetime *datetime) is_12hour = ! (flag & GRUB_CMOS_STATUS_B_24HOUR); - value = grub_cmos_read (GRUB_CMOS_INDEX_HOUR); + err = grub_cmos_read (GRUB_CMOS_INDEX_HOUR, &value); + if (err) + return err; if (is_12hour) { is_12hour = (value & 0x80); @@ -71,13 +87,18 @@ grub_get_datetime (struct grub_datetime *datetime) datetime->hour = value; - value = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE); + err = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE, &value); + if (err) + return err; + if (is_bcd) value = grub_bcd_to_num (value); datetime->minute = value; - value = grub_cmos_read (GRUB_CMOS_INDEX_SECOND); + err = grub_cmos_read (GRUB_CMOS_INDEX_SECOND, &value); + if (err) + return err; if (is_bcd) value = grub_bcd_to_num (value); @@ -87,12 +108,15 @@ grub_get_datetime (struct grub_datetime *datetime) } grub_err_t -grub_set_datetime (struct grub_datetime *datetime) +grub_set_datetime_cmos (struct grub_datetime *datetime) { int is_bcd, is_12hour; grub_uint8_t value, flag; + grub_err_t err; - flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B); + err = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B, &flag); + if (err) + return err; is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY); @@ -102,21 +126,27 @@ grub_set_datetime (struct grub_datetime *datetime) if (is_bcd) value = grub_num_to_bcd (value); - grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value); + err = grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value); + if (err) + return err; value = datetime->month; if (is_bcd) value = grub_num_to_bcd (value); - grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value); + err = grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value); + if (err) + return err; value = datetime->day; if (is_bcd) value = grub_num_to_bcd (value); - grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value); + err = grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value); + if (err) + return err; value = datetime->hour; @@ -138,21 +168,27 @@ grub_set_datetime (struct grub_datetime *datetime) if (is_12hour) value |= 0x80; - grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value); + err = grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value); + if (err) + return err; value = datetime->minute; if (is_bcd) value = grub_num_to_bcd (value); - grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value); + err = grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value); + if (err) + return err; value = datetime->second; if (is_bcd) value = grub_num_to_bcd (value); - grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value); + err = grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value); + if (err) + return err; return 0; } diff --git a/grub-core/lib/ieee1275/cmos.c b/grub-core/lib/ieee1275/cmos.c new file mode 100644 index 000000000..fa57db9e7 --- /dev/null +++ b/grub-core/lib/ieee1275/cmos.c @@ -0,0 +1,75 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 + +volatile grub_uint8_t *grub_cmos_port = 0; +grub_err_t +grub_cmos_find_port (void) +{ + auto int hook (struct grub_ieee1275_devalias *alias); + int hook (struct grub_ieee1275_devalias *alias) + { + grub_ieee1275_phandle_t dev; + grub_uint32_t addr[2]; + grub_ssize_t actual; + /* Enough to check if it's "m5819" */ + char compat[100]; + if (grub_ieee1275_finddevice (alias->path, &dev)) + return 0; + if (grub_ieee1275_get_property (dev, "compatible", compat, sizeof (compat), + 0)) + return 0; + if (grub_strcmp (compat, "m5819") != 0) + return 0; + if (grub_ieee1275_get_integer_property (dev, "address", + addr, sizeof (addr), &actual)) + return 0; + if (actual == 4) + { + grub_cmos_port = (volatile grub_uint8_t *) (grub_addr_t) addr[0]; + return 1; + } + +#if GRUB_CPU_SIZEOF_VOID_P == 8 + if (actual == 8) + { + grub_cmos_port = (volatile grub_uint8_t *) + ((((grub_addr_t) addr[0]) << 32) | addr[1]); + return 1; + } +#else + if (actual == 8 && addr[0] == 0) + { + grub_cmos_port = (volatile grub_uint8_t *) addr[1]; + return 1; + } +#endif + return 0; + } + + grub_ieee1275_devices_iterate (hook); + if (!grub_cmos_port) + return grub_error (GRUB_ERR_IO, "no cmos found"); + + return GRUB_ERR_NONE; +} diff --git a/grub-core/lib/ieee1275/datetime.c b/grub-core/lib/ieee1275/datetime.c index 4105c639b..1947135fe 100644 --- a/grub-core/lib/ieee1275/datetime.c +++ b/grub-core/lib/ieee1275/datetime.c @@ -21,10 +21,14 @@ #include #include #include +#if defined (__powerpc__) || defined (__sparc__) +#include +#endif GRUB_MOD_LICENSE ("GPLv3+"); static char *rtc = 0; +static int no_ieee1275_rtc = 0; static void find_rtc (void) @@ -42,6 +46,8 @@ find_rtc (void) } grub_ieee1275_devices_iterate (hook); + if (!rtc) + no_ieee1275_rtc = 1; } grub_err_t @@ -64,10 +70,12 @@ grub_get_datetime (struct grub_datetime *datetime) int status; grub_ieee1275_ihandle_t ihandle; + if (no_ieee1275_rtc) + return grub_get_datetime_cmos (datetime); if (!rtc) find_rtc (); if (!rtc) - return grub_error (GRUB_ERR_IO, "no RTC found"); + return grub_get_datetime_cmos (datetime); status = grub_ieee1275_open (rtc, &ihandle); if (status == -1) @@ -114,10 +122,12 @@ grub_set_datetime (struct grub_datetime *datetime) int status; grub_ieee1275_ihandle_t ihandle; + if (no_ieee1275_rtc) + return grub_set_datetime_cmos (datetime); if (!rtc) find_rtc (); if (!rtc) - return grub_error (GRUB_ERR_IO, "no RTC found"); + return grub_set_datetime_cmos (datetime); status = grub_ieee1275_open (rtc, &ihandle); if (status == -1) diff --git a/include/grub/cmos.h b/include/grub/cmos.h index f508e3bf6..331513cd7 100644 --- a/include/grub/cmos.h +++ b/include/grub/cmos.h @@ -20,8 +20,10 @@ #define GRUB_CMOS_H 1 #include +#if !defined (__powerpc__) && !defined (__sparc__) #include #include +#endif #define GRUB_CMOS_INDEX_SECOND 0 #define GRUB_CMOS_INDEX_SECOND_ALARM 1 @@ -55,18 +57,56 @@ grub_num_to_bcd (grub_uint8_t a) return (((a / 10) << 4) + (a % 10)); } -static inline grub_uint8_t -grub_cmos_read (grub_uint8_t index) +#if !defined (__powerpc__) && !defined (__sparc__) +static inline grub_err_t +grub_cmos_read (grub_uint8_t index, grub_uint8_t *val) { grub_outb (index, GRUB_CMOS_ADDR_REG); - return grub_inb (GRUB_CMOS_DATA_REG); + *val = grub_inb (GRUB_CMOS_DATA_REG); + return GRUB_ERR_NONE; } -static inline void +static inline grub_err_t grub_cmos_write (grub_uint8_t index, grub_uint8_t value) { grub_outb (index, GRUB_CMOS_ADDR_REG); grub_outb (value, GRUB_CMOS_DATA_REG); + return GRUB_ERR_NONE; +} +#else +grub_err_t grub_cmos_find_port (void); +extern volatile grub_uint8_t *grub_cmos_port; + +static inline grub_err_t +grub_cmos_read (grub_uint8_t index, grub_uint8_t *val) +{ + if (!grub_cmos_port) + { + grub_err_t err; + err = grub_cmos_find_port (); + if (err) + return err; + } + grub_cmos_port[0] = index; + *val = grub_cmos_port[1]; + return GRUB_ERR_NONE; } +static inline grub_err_t +grub_cmos_write (grub_uint8_t index, grub_uint8_t val) +{ + if (!grub_cmos_port) + { + grub_err_t err; + err = grub_cmos_find_port (); + if (err) + return err; + } + grub_cmos_port[0] = index; + grub_cmos_port[1] = val; + return GRUB_ERR_NONE; +} + +#endif + #endif /* GRUB_CMOS_H */ diff --git a/include/grub/datetime.h b/include/grub/datetime.h index c20fc8c36..dea0f8ea9 100644 --- a/include/grub/datetime.h +++ b/include/grub/datetime.h @@ -125,4 +125,11 @@ grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) return 1; } +#if defined (__powerpc__) || defined (__sparc__) +grub_err_t +grub_get_datetime_cmos (struct grub_datetime *datetime); +grub_err_t +grub_set_datetime_cmos (struct grub_datetime *datetime); +#endif + #endif /* ! KERNEL_DATETIME_HEADER */ From d73459943924af0345797052934ab61417a5f84d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 21:00:01 +0200 Subject: [PATCH 389/406] MIPS qemu at_keyboard support. * gentpl.py (videoinkernel): Add qemu-mips. * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add necessary headers. * grub-core/Makefile.core.def (kernel): Add at_keyboard and layout. * grub-core/kern/mips/qemu_mips/init.c (grub_machine_init): Init new modules. * grub-core/term/at_keyboard.c (grub_keyboard_controller_init) [GRUB_MACHINE_MIPS_QEMU_MIPS]: Don't consider original set. * grub-core/term/serial.c (grub_serial_register) [GRUB_MACHINE_MIPS_QEMU_MIPS]: Make com0 explicitly active. --- ChangeLog | 14 +++++++++++++ gentpl.py | 2 +- grub-core/Makefile.am | 13 ++++++++++++ grub-core/Makefile.core.def | 2 ++ grub-core/kern/mips/qemu_mips/init.c | 20 ++++++++++++++++++ grub-core/term/at_keyboard.c | 4 ++-- grub-core/term/serial.c | 11 ++++++++++ include/grub/mips/qemu_mips/at_keyboard.h | 25 +++++++++++++++++++++++ 8 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 include/grub/mips/qemu_mips/at_keyboard.h diff --git a/ChangeLog b/ChangeLog index 694a97972..644a7cf6a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2011-07-05 Vladimir Serbinenko + + MIPS qemu at_keyboard support. + + * gentpl.py (videoinkernel): Add qemu-mips. + * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add necessary headers. + * grub-core/Makefile.core.def (kernel): Add at_keyboard and layout. + * grub-core/kern/mips/qemu_mips/init.c (grub_machine_init): Init new + modules. + * grub-core/term/at_keyboard.c (grub_keyboard_controller_init) + [GRUB_MACHINE_MIPS_QEMU_MIPS]: Don't consider original set. + * grub-core/term/serial.c (grub_serial_register) + [GRUB_MACHINE_MIPS_QEMU_MIPS]: Make com0 explicitly active. + 2011-07-05 Vladimir Serbinenko CMOS support on sparc. diff --git a/gentpl.py b/gentpl.py index 31cde1e81..e431293eb 100644 --- a/gentpl.py +++ b/gentpl.py @@ -37,7 +37,7 @@ GROUPS["pci"] = GROUPS["x86"] + ["mips_loongson"] GROUPS["usb"] = GROUPS["pci"] # If gfxterm is main output console integrate it into kernel -GROUPS["videoinkernel"] = ["mips_loongson"] +GROUPS["videoinkernel"] = ["mips_loongson", "mips_qemu_mips"] GROUPS["videomodules"] = GRUB_PLATFORMS[:]; for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i) diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index c3ecba9cf..28a143413 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -145,7 +145,20 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arc/arc.h endif if COND_mips_qemu_mips +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/cache.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap_scale.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/serial.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h endif if COND_mips_loongson diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 16c940c61..328f7186f 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -162,6 +162,8 @@ kernel = { mips_qemu_mips = kern/mips/qemu_mips/init.c; mips_qemu_mips = term/ns8250.c; mips_qemu_mips = term/serial.c; + mips_qemu_mips = term/at_keyboard.c; + mips_qemu_mips = commands/keylayouts.c; mips_arc = kern/mips/arc/init.c; mips_arc = term/arc/console.c; diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c index 2180b347a..2016aeb3d 100644 --- a/grub-core/kern/mips/qemu_mips/init.c +++ b/grub-core/kern/mips/qemu_mips/init.c @@ -12,6 +12,16 @@ extern void grub_serial_init (void); extern void grub_terminfo_init (void); +extern void grub_at_keyboard_init (void); +extern void grub_video_init (void); +extern void grub_bitmap_init (void); +extern void grub_font_init (void); +extern void grub_gfxterm_init (void); +extern void grub_at_keyboard_init (void); +extern void grub_serial_init (void); +extern void grub_terminfo_init (void); +extern void grub_keylayouts_init (void); +extern void grub_boot_init (void); void grub_machine_init (void) @@ -27,8 +37,18 @@ grub_machine_init (void) grub_install_get_time_ms (grub_rtc_get_time_ms); + grub_video_init (); + grub_bitmap_init (); + grub_font_init (); + grub_gfxterm_init (); + + grub_keylayouts_init (); + grub_at_keyboard_init (); + grub_terminfo_init (); grub_serial_init (); + + grub_boot_init (); } void diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c index e86df6f35..b81e76230 100644 --- a/grub-core/term/at_keyboard.c +++ b/grub-core/term/at_keyboard.c @@ -259,7 +259,7 @@ grub_keyboard_controller_write (grub_uint8_t c) grub_outb (c, KEYBOARD_REG_DATA); } -#if !defined (GRUB_MACHINE_MIPS_LOONGSON) && !defined (GRUB_MACHINE_QEMU) +#if !defined (GRUB_MACHINE_MIPS_LOONGSON) && !defined (GRUB_MACHINE_QEMU) && !defined (GRUB_MACHINE_MIPS_QEMU_MIPS) static grub_uint8_t grub_keyboard_controller_read (void) @@ -569,7 +569,7 @@ grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unus keyboard_controller_wait_until_ready (); grub_inb (KEYBOARD_REG_DATA); } -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_QEMU) +#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_QEMU) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) grub_keyboard_controller_orig = 0; grub_keyboard_orig_set = 2; #else diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c index add112f4a..0381349a4 100644 --- a/grub-core/term/serial.c +++ b/grub-core/term/serial.c @@ -313,6 +313,17 @@ grub_serial_register (struct grub_serial_port *port) grub_term_register_input_inactive ("serial_*", in); grub_term_register_output_inactive ("serial_*", out); } +#elif defined (GRUB_MACHINE_MIPS_QEMU_MIPS) + if (grub_strcmp (port->name, "com0") == 0) + { + grub_term_register_input_active ("serial_*", in); + grub_term_register_output_active ("serial_*", out); + } + else + { + grub_term_register_input_inactive ("serial_*", in); + grub_term_register_output_inactive ("serial_*", out); + } #else grub_term_register_input ("serial_*", in); grub_term_register_output ("serial_*", out); diff --git a/include/grub/mips/qemu_mips/at_keyboard.h b/include/grub/mips/qemu_mips/at_keyboard.h new file mode 100644 index 000000000..37cc625d1 --- /dev/null +++ b/include/grub/mips/qemu_mips/at_keyboard.h @@ -0,0 +1,25 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009 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_AT_KEYBOARD_HEADER +#define GRUB_MACHINE_AT_KEYBOARD_HEADER 1 + +#define KEYBOARD_REG_DATA 0xb4000060 +#define KEYBOARD_REG_STATUS 0xb4000064 + +#endif From 748ccabea1fe40d6240f1abaa5e0612920b366ea Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 21:42:36 +0200 Subject: [PATCH 390/406] MIPS qemu flash support. * grub-core/boot/mips/startup_raw.S [GRUB_MACHINE_MIPS_QEMU_MIPS]: Check magic. * grub-core/kern/mips/qemu_mips/init.c (probe_mem): New function. (grub_machine_init): Probe memory if its size isn't known. * util/grub-mkimage.c (image_targets): Add flash targets. (generate_image): Handle flash targets. --- ChangeLog | 11 +++++ grub-core/boot/mips/startup_raw.S | 16 ++++++- grub-core/kern/mips/qemu_mips/init.c | 28 ++++++++++- util/grub-mkimage.c | 69 +++++++++++++++++++++++++++- 4 files changed, 121 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 644a7cf6a..3772dc028 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-07-05 Vladimir Serbinenko + + MIPS qemu flash support. + + * grub-core/boot/mips/startup_raw.S [GRUB_MACHINE_MIPS_QEMU_MIPS]: Check + magic. + * grub-core/kern/mips/qemu_mips/init.c (probe_mem): New function. + (grub_machine_init): Probe memory if its size isn't known. + * util/grub-mkimage.c (image_targets): Add flash targets. + (generate_image): Handle flash targets. + 2011-07-05 Vladimir Serbinenko MIPS qemu at_keyboard support. diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index e6dfadaf9..4ecff5efd 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -54,8 +54,22 @@ codestart: /* Parse arguments. Has to be done before relocation. So need to do it in asm. */ #ifdef GRUB_MACHINE_MIPS_QEMU_MIPS + lui $t0, %hi (((16 << 20) - 264 + 4) | 0x80000000) + lw $t1, %lo (((16 << 20) - 264 + 4) | 0x80000000) ($t0) + + lui $t2, 0x1234 + ori $t2, 0x5678 + + bne $t1, $t2, 1f + nop + lui $t0, %hi (((16 << 20) - 264) | 0x80000000) - lw $s4, %lo (((16 << 20) - 264) | 0x80000000) ($t0) + b 2f + lw $s4, %lo (((16 << 20) - 264) | 0x80000000) ($t0) + +1: + li $s4, 0 +2: #endif #ifdef GRUB_MACHINE_MIPS_LOONGSON diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c index 2016aeb3d..0c3113fe2 100644 --- a/grub-core/kern/mips/qemu_mips/init.c +++ b/grub-core/kern/mips/qemu_mips/init.c @@ -23,11 +23,36 @@ extern void grub_terminfo_init (void); extern void grub_keylayouts_init (void); extern void grub_boot_init (void); +static inline int +probe_mem (grub_addr_t addr) +{ + volatile grub_uint8_t *ptr = (grub_uint8_t *) (0xa0000000 | addr); + grub_uint8_t c = *ptr; + *ptr = 0xAA; + if (*ptr != 0xAA) + return 0; + *ptr = 0x55; + if (*ptr != 0x55) + return 0; + *ptr = c; + return 1; +} + void grub_machine_init (void) { grub_addr_t modend; + if (grub_arch_memsize == 0) + { + int i; + + for (i = 27; i >= 0; i--) + if (probe_mem (grub_arch_memsize | (1 << i))) + grub_arch_memsize |= (1 << i); + grub_arch_memsize++; + } + /* FIXME: measure this. */ grub_arch_cpuclock = 64000000; @@ -40,7 +65,6 @@ grub_machine_init (void) grub_video_init (); grub_bitmap_init (); grub_font_init (); - grub_gfxterm_init (); grub_keylayouts_init (); grub_at_keyboard_init (); @@ -49,6 +73,8 @@ grub_machine_init (void) grub_serial_init (); grub_boot_init (); + + grub_gfxterm_init (); } void diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 9fc37df2b..002696d07 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -67,7 +67,8 @@ struct image_target_desc IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT, IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_I386_IEEE1275, IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH, - IMAGE_FULOONG_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC + IMAGE_FULOONG_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC, + IMAGE_QEMU_MIPS_FLASH } id; enum { @@ -466,6 +467,50 @@ struct image_target_desc image_targets[] = .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN, .default_compression = COMPRESSION_NONE }, + { + .dirname = "mips-qemu_mips", + .names = { "mips-qemu_mips-flash", NULL }, + .voidp_sizeof = 4, + .bigendian = 1, + .id = IMAGE_QEMU_MIPS_FLASH, + .flags = PLATFORM_FLAGS_DECOMPRESSORS, + .prefix = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX, + .prefix_end = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END, + .raw_size = 0, + .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, + .compressed_size = TARGET_NO_FIELD, + .kernel_image_size = TARGET_NO_FIELD, + .section_align = 1, + .vaddr_offset = 0, + .install_dos_part = TARGET_NO_FIELD, + .install_bsd_part = TARGET_NO_FIELD, + .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR, + .elf_target = EM_MIPS, + .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN, + .default_compression = COMPRESSION_NONE + }, + { + .dirname = "mipsel-qemu_mips", + .names = { "mipsel-qemu_mips-flash", NULL }, + .voidp_sizeof = 4, + .bigendian = 0, + .id = IMAGE_QEMU_MIPS_FLASH, + .flags = PLATFORM_FLAGS_DECOMPRESSORS, + .prefix = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX, + .prefix_end = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END, + .raw_size = 0, + .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, + .compressed_size = TARGET_NO_FIELD, + .kernel_image_size = TARGET_NO_FIELD, + .section_align = 1, + .vaddr_offset = 0, + .install_dos_part = TARGET_NO_FIELD, + .install_bsd_part = TARGET_NO_FIELD, + .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR, + .elf_target = EM_MIPS, + .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN, + .default_compression = COMPRESSION_NONE + }, { .dirname = "mips-qemu_mips", .names = { "mips-qemu_mips-elf", NULL }, @@ -1389,6 +1434,28 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], core_size = rom_size; } break; + case IMAGE_QEMU_MIPS_FLASH: + { + char *rom_img; + size_t rom_size; + + if (core_size > 512 * 1024) + grub_util_error ("firmware image is too big"); + rom_size = 512 * 1024; + + rom_img = xmalloc (rom_size); + memset (rom_img, 0, rom_size); + + memcpy (rom_img, core_img, core_size); + + memset (rom_img + core_size, 0, + rom_size - core_size); + + free (core_img); + core_img = rom_img; + core_size = rom_size; + } + break; case IMAGE_MIPS_ARC: { char *ecoff_img; From 93c06ff9c6490af246ce3620c11d5cc638903e7f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 23:46:15 +0200 Subject: [PATCH 391/406] VGA text support in qemu-mips * grub-core/Makefile.core.def (kernel): Add term/i386/pc/vga_text.c, term/i386/vga_common.c and kern/vga_init.c on qemu-mips. * grub-core/kern/mips/qemu_mips/init.c (grub_machine_init): Init vga text. * grub-core/kern/i386/qemu/init.c: Renamed to ... * grub-core/kern/vga_init.c: ... this. * grub-core/kern/vga_init.c (VGA_ADDR) [__mips__]: Adjust. (grub_qemu_init_cirrus) [__mips__]: Skip PCI and adjust the I/O base. * grub-core/term/i386/pc/vga_text.c (VGA_TEXT_SCREEN) [__mips__]: Adjust. * include/grub/vga.h [GRUB_MACHINE_MIPS_QEMU_MIPS]: Declare GRUB_MACHINE_PCI_IO_BASE. --- ChangeLog | 17 ++++++++++++++ grub-core/Makefile.core.def | 5 +++- grub-core/kern/mips/qemu_mips/init.c | 5 ++++ .../kern/{i386/qemu/init.c => vga_init.c} | 23 +++++++++++++++---- grub-core/term/i386/pc/vga_text.c | 6 ++++- include/grub/mips/qemu_mips/kernel.h | 1 + include/grub/vga.h | 5 ++++ 7 files changed, 56 insertions(+), 6 deletions(-) rename grub-core/kern/{i386/qemu/init.c => vga_init.c} (90%) diff --git a/ChangeLog b/ChangeLog index 3772dc028..c2d386032 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2011-07-05 Vladimir Serbinenko + + VGA text support in qemu-mips + + * grub-core/Makefile.core.def (kernel): Add term/i386/pc/vga_text.c, + term/i386/vga_common.c and kern/vga_init.c on qemu-mips. + * grub-core/kern/mips/qemu_mips/init.c (grub_machine_init): Init vga + text. + * grub-core/kern/i386/qemu/init.c: Renamed to ... + * grub-core/kern/vga_init.c: ... this. + * grub-core/kern/vga_init.c (VGA_ADDR) [__mips__]: Adjust. + (grub_qemu_init_cirrus) [__mips__]: Skip PCI and adjust the I/O base. + * grub-core/term/i386/pc/vga_text.c (VGA_TEXT_SCREEN) [__mips__]: + Adjust. + * include/grub/vga.h [GRUB_MACHINE_MIPS_QEMU_MIPS]: Declare + GRUB_MACHINE_PCI_IO_BASE. + 2011-07-05 Vladimir Serbinenko MIPS qemu flash support. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 328f7186f..807f5b357 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -143,7 +143,7 @@ kernel = { i386_pc = term/i386/pc/console.c; i386_qemu = bus/pci.c; - i386_qemu = kern/i386/qemu/init.c; + i386_qemu = kern/vga_init.c; i386_qemu = kern/i386/qemu/mmap.c; i386_qemu = kern/i386/tsc.c; @@ -164,6 +164,9 @@ kernel = { mips_qemu_mips = term/serial.c; mips_qemu_mips = term/at_keyboard.c; mips_qemu_mips = commands/keylayouts.c; + mips_qemu_mips = term/i386/pc/vga_text.c; + mips_qemu_mips = term/i386/vga_common.c; + mips_qemu_mips = kern/vga_init.c; mips_arc = kern/mips/arc/init.c; mips_arc = term/arc/console.c; diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c index 0c3113fe2..db9cc796a 100644 --- a/grub-core/kern/mips/qemu_mips/init.c +++ b/grub-core/kern/mips/qemu_mips/init.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -22,6 +23,7 @@ extern void grub_serial_init (void); extern void grub_terminfo_init (void); extern void grub_keylayouts_init (void); extern void grub_boot_init (void); +extern void grub_vga_text_init (void); static inline int probe_mem (grub_addr_t addr) @@ -69,6 +71,9 @@ grub_machine_init (void) grub_keylayouts_init (); grub_at_keyboard_init (); + grub_qemu_init_cirrus (); + grub_vga_text_init (); + grub_terminfo_init (); grub_serial_init (); diff --git a/grub-core/kern/i386/qemu/init.c b/grub-core/kern/vga_init.c similarity index 90% rename from grub-core/kern/i386/qemu/init.c rename to grub-core/kern/vga_init.c index 054dfa86b..889d0128e 100644 --- a/grub-core/kern/i386/qemu/init.c +++ b/grub-core/kern/vga_init.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2010 Free Software Foundation, Inc. + * Copyright (C) 2010,2011 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 @@ -16,7 +16,9 @@ * along with GRUB. If not, see . */ +#ifndef __mips__ #include +#endif #include #include #include @@ -43,7 +45,17 @@ static struct {grub_uint8_t r, g, b, a; } colors[] = {0xFE, 0xFE, 0xFE, 0xFF} // 15 = white }; +#ifdef __mips__ +extern unsigned char ascii_bitmaps[]; +#else #include +#endif + +#ifdef __mips__ +#define VGA_ADDR 0xb00a0000 +#else +#define VGA_ADDR 0xa0000 +#endif static void load_font (void) @@ -61,7 +73,7 @@ load_font (void) grub_vga_gr_write (0xff, GRUB_VGA_GR_BITMASK); for (i = 0; i < 128; i++) - grub_memcpy ((void *) (0xa0000 + 32 * i), ascii_bitmaps + 16 * i, 16); + grub_memcpy ((void *) (VGA_ADDR + 32 * i), ascii_bitmaps + 16 * i, 16); } static void @@ -78,6 +90,7 @@ load_palette (void) void grub_qemu_init_cirrus (void) { +#ifndef __mips__ auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid); int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))) { @@ -106,8 +119,10 @@ grub_qemu_init_cirrus (void) } grub_pci_iterate (find_card); +#endif - grub_outb (GRUB_VGA_IO_MISC_COLOR, GRUB_VGA_IO_MISC_WRITE); + grub_outb (GRUB_VGA_IO_MISC_COLOR, + GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_MISC_WRITE); load_font (); @@ -143,5 +158,5 @@ grub_qemu_init_cirrus (void) grub_vga_cr_write (14, GRUB_VGA_CR_CURSOR_START); grub_vga_cr_write (15, GRUB_VGA_CR_CURSOR_END); - grub_outb (0x20, 0x3c0); + grub_outb (0x20, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX); } diff --git a/grub-core/term/i386/pc/vga_text.c b/grub-core/term/i386/pc/vga_text.c index 1816bfae2..9abffcc0a 100644 --- a/grub-core/term/i386/pc/vga_text.c +++ b/grub-core/term/i386/pc/vga_text.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include @@ -29,7 +29,11 @@ GRUB_MOD_LICENSE ("GPLv3+"); static int grub_curr_x, grub_curr_y; +#ifdef __mips__ +#define VGA_TEXT_SCREEN ((grub_uint16_t *) 0xb00b8000) +#else #define VGA_TEXT_SCREEN ((grub_uint16_t *) 0xb8000) +#endif static void screen_write_char (int x, int y, short c) diff --git a/include/grub/mips/qemu_mips/kernel.h b/include/grub/mips/qemu_mips/kernel.h index c08405e83..66add4b2e 100644 --- a/include/grub/mips/qemu_mips/kernel.h +++ b/include/grub/mips/qemu_mips/kernel.h @@ -25,6 +25,7 @@ void EXPORT_FUNC (grub_reboot) (void); void EXPORT_FUNC (grub_halt) (void); +void grub_qemu_init_cirrus (void); #endif diff --git a/include/grub/vga.h b/include/grub/vga.h index bf4439599..58ec3ba15 100644 --- a/include/grub/vga.h +++ b/include/grub/vga.h @@ -19,7 +19,12 @@ #ifndef GRUB_VGA_HEADER #define GRUB_VGA_HEADER 1 +#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS #include +#else +#include +#define GRUB_MACHINE_PCI_IO_BASE 0xb4000000 +#endif enum { From 72b9ad936abf84dbcd4a55b31fe64d316d1bd62a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 02:49:04 +0200 Subject: [PATCH 392/406] fix declarations in pxe --- grub-core/net/drivers/i386/pc/pxe.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index aa10cbbfa..cd598ea72 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -260,15 +260,13 @@ grub_pxe_send (const struct grub_net_card *dev __attribute__ ((unused)), return 0; } -static grub_err_t +static void grub_pxe_close (const struct grub_net_card *dev __attribute__ ((unused))) { if (pxe_rm_entry) grub_pxe_call (GRUB_PXENV_UNDI_CLOSE, (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, pxe_rm_entry); - - return GRUB_ERR_NONE; } static grub_err_t @@ -322,7 +320,6 @@ grub_pc_net_config_real (char **device, char **path) GRUB_MOD_INIT(pxe) { struct grub_pxe_bangpxe *pxenv; - struct grub_pxe_undi_open *ou; struct grub_pxe_undi_info *ui; unsigned i; From cf1337aa029a66e8936fa799dbf48d4feabf1f8f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 02:50:35 +0200 Subject: [PATCH 393/406] * grub-core/kern/i386/qemu/mmap.c (grub_machine_mmap_init): Use new grub_read_cmos prototype. --- ChangeLog | 5 +++++ grub-core/kern/i386/qemu/mmap.c | 21 ++++++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index c2d386032..06b71a246 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-07-05 Vladimir Serbinenko + + * grub-core/kern/i386/qemu/mmap.c (grub_machine_mmap_init): Use new + grub_read_cmos prototype. + 2011-07-05 Vladimir Serbinenko VGA text support in qemu-mips diff --git a/grub-core/kern/i386/qemu/mmap.c b/grub-core/kern/i386/qemu/mmap.c index 208f36b7e..2b0c7f6a7 100644 --- a/grub-core/kern/i386/qemu/mmap.c +++ b/grub-core/kern/i386/qemu/mmap.c @@ -41,8 +41,11 @@ static grub_uint64_t mem_size, above_4g; void grub_machine_mmap_init () { - mem_size = ((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH)) << 24 - | ((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE_LOW)) << 16; + grub_uint8_t high, low, b, c, d; + grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH, &high); + grub_cmos_read (QEMU_CMOS_MEMSIZE_LOW, &low); + mem_size = ((grub_uint64_t) high) << 24 + | ((grub_uint64_t) low) << 16; if (mem_size > 0) { /* Don't ask... */ @@ -50,15 +53,19 @@ grub_machine_mmap_init () } else { + grub_cmos_read (QEMU_CMOS_MEMSIZE2_HIGH, &high); + grub_cmos_read (QEMU_CMOS_MEMSIZE2_LOW, &low); mem_size - = ((((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE2_HIGH)) << 18) - | ((grub_uint64_t) (grub_cmos_read (QEMU_CMOS_MEMSIZE2_LOW)) << 10)) + = ((((grub_uint64_t) high) << 18) | (((grub_uint64_t) low) << 10)) + 1024 * 1024; } - above_4g = (((grub_uint64_t) grub_cmos_read (0x5b)) << 16) - | (((grub_uint64_t) grub_cmos_read (0x5c)) << 24) - | (((grub_uint64_t) grub_cmos_read (0x5d)) << 32); + grub_cmos_read (0x5b, &b); + grub_cmos_read (0x5c, &c); + grub_cmos_read (0x5d, &d); + above_4g = (((grub_uint64_t) b) << 16) + | (((grub_uint64_t) c) << 24) + | (((grub_uint64_t) d) << 32); } grub_err_t From b975df6348fdf7bb02d107dd4fff92965e5f9182 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 12:53:37 +0200 Subject: [PATCH 394/406] Send TFTP_ERROR on tftp premature close. Several cleanups --- grub-core/net/ethernet.c | 40 ++++++++++++ grub-core/net/ip.c | 46 +++++++++++++- grub-core/net/net.c | 1 + grub-core/net/tftp.c | 118 +++++++++++++++++++++++++++++++++++- include/grub/net.h | 34 +++-------- include/grub/net/device.h | 0 include/grub/net/ethernet.h | 41 ++++++------- include/grub/net/ip.h | 63 ++++++++++--------- include/grub/net/tftp.h | 68 --------------------- include/grub/net/udp.h | 4 +- 10 files changed, 262 insertions(+), 153 deletions(-) delete mode 100644 include/grub/net/device.h delete mode 100644 include/grub/net/tftp.h diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index 3006c9d93..acd33bcf6 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 @@ -8,6 +26,28 @@ #include #include +#define LLCADDRMASK 0x7f + +struct etherhdr +{ + grub_uint8_t dst[6]; + grub_uint8_t src[6]; + grub_uint16_t type; +} __attribute__ ((packed)); + +struct llchdr +{ + grub_uint8_t dsap; + grub_uint8_t ssap; + grub_uint8_t ctrl; +} __attribute__ ((packed)); + +struct snaphdr +{ + grub_uint8_t oui[3]; + grub_uint16_t type; +} __attribute__ ((packed)); + grub_err_t send_ethernet_packet (struct grub_net_network_level_interface *inf, struct grub_net_buff *nb, diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 8b06f7d11..642a67f18 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 @@ -7,8 +25,32 @@ #include #include +struct iphdr { + grub_uint8_t verhdrlen; + grub_uint8_t service; + grub_uint16_t len; + grub_uint16_t ident; + grub_uint16_t frags; + grub_uint8_t ttl; + grub_uint8_t protocol; + grub_uint16_t chksum; + grub_uint32_t src; + grub_uint32_t dest; +} __attribute__ ((packed)) ; + +struct ip6hdr +{ + grub_uint8_t version:4, priority:4; + grub_uint8_t flow_lbl[3]; + grub_uint16_t payload_len; + grub_uint8_t nexthdr; + grub_uint8_t hop_limit; + grub_uint8_t saddr[16]; + grub_uint8_t daddr[16]; +} __attribute__ ((packed)); + grub_uint16_t -ipchksum (void *ipv, int len) +grub_net_ip_chksum (void *ipv, int len) { grub_uint16_t *ip = (grub_uint16_t *) ipv; grub_uint32_t sum = 0; @@ -48,7 +90,7 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface * inf, iph->dest = target->ipv4; iph->chksum = 0; - iph->chksum = ipchksum ((void *) nb->data, sizeof (*iph)); + iph->chksum = grub_net_ip_chksum ((void *) nb->data, sizeof (*iph)); /* Determine link layer target address via ARP. */ err = grub_net_arp_resolve (inf, target, &ll_target_addr); diff --git a/grub-core/net/net.c b/grub-core/net/net.c index a3b76cae0..0d664d9b5 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 6ffe27669..be1534021 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -1,5 +1,22 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 @@ -11,6 +28,74 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* IP port for the MTFTP server used for Intel's PXE */ +enum + { + MTFTP_SERVER_PORT = 75, + MTFTP_CLIENT_PORT = 76, + /* IP port for the TFTP server */ + TFTP_SERVER_PORT = 69 + }; + +enum + { + TFTP_DEFAULTSIZE_PACKET = 512, + TFTP_MAX_PACKET = 1432 + }; + +enum + { + TFTP_CODE_EOF = 1, + TFTP_CODE_MORE = 2, + TFTP_CODE_ERROR = 3, + TFTP_CODE_BOOT = 4, + TFTP_CODE_CFG = 5 + }; + +enum + { + TFTP_RRQ = 1, + TFTP_WRQ = 2, + TFTP_DATA = 3, + TFTP_ACK = 4, + TFTP_ERROR = 5, + TFTP_OACK = 6 + }; + +enum + { + TFTP_EUNDEF = 0, /* not defined */ + TFTP_ENOTFOUND = 1, /* file not found */ + TFTP_EACCESS = 2, /* access violation */ + TFTP_ENOSPACE = 3, /* disk full or allocation exceeded */ + TFTP_EBADOP = 4, /* illegal TFTP operation */ + TFTP_EBADID = 5, /* unknown transfer ID */ + TFTP_EEXISTS = 6, /* file already exists */ + TFTP_ENOUSER = 7 /* no such user */ + }; + +struct tftphdr { + grub_uint16_t opcode; + union { + grub_int8_t rrq[TFTP_DEFAULTSIZE_PACKET]; + struct { + grub_uint16_t block; + grub_int8_t download[TFTP_MAX_PACKET]; + } data; + struct { + grub_uint16_t block; + } ack; + struct { + grub_uint16_t errcode; + grub_int8_t errmsg[TFTP_DEFAULTSIZE_PACKET]; + } err; + struct { + grub_int8_t data[TFTP_DEFAULTSIZE_PACKET+2]; + } oack; + } u; +} __attribute__ ((packed)) ; + + typedef struct tftp_data { grub_uint64_t file_size; @@ -40,7 +125,7 @@ tftp_receive (grub_net_socket_t sock __attribute__ ((unused)), switch (grub_be_to_cpu16 (tftph->opcode)) { case TFTP_OACK: - data->block_size = 512; + data->block_size = TFTP_DEFAULTSIZE_PACKET; data->have_oack = 1; for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;) { @@ -224,8 +309,35 @@ static grub_err_t tftp_close (struct grub_file *file) { tftp_data_t data = file->data; + if (data->sock) - grub_net_udp_close (data->sock); + { + char nbdata[512]; + grub_err_t err; + struct grub_net_buff nb_err; + struct tftphdr *tftph; + + nb_err.head = nbdata; + nb_err.end = nbdata + sizeof (nbdata); + + grub_netbuff_clear (&nb_err); + grub_netbuff_reserve (&nb_err, 512); + err = grub_netbuff_push (&nb_err, sizeof (tftph->opcode) + + sizeof (tftph->u.err.errcode) + + sizeof ("closed")); + if (!err) + { + tftph = (struct tftphdr *) nb_err.data; + tftph->opcode = grub_cpu_to_be16 (TFTP_ERROR); + tftph->u.err.errcode = grub_cpu_to_be16 (TFTP_EUNDEF); + grub_memcpy (tftph->u.err.errmsg, "closed", sizeof ("closed")); + + err = grub_net_send_udp_packet (data->sock, &nb_err); + } + if (err) + grub_print_error (); + grub_net_udp_close (data->sock); + } grub_free (data); return GRUB_ERR_NONE; } diff --git a/include/grub/net.h b/include/grub/net.h index 85fdef365..0ac0838cf 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2010 Free Software Foundation, Inc. + * Copyright (C) 2010,2011 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 @@ -82,6 +82,10 @@ typedef struct grub_net_packets grub_net_packet_t *last; } grub_net_packets_t; +#ifdef GRUB_MACHINE_EFI +#include +#endif + struct grub_net_card { struct grub_net_card *next; @@ -93,11 +97,13 @@ struct grub_net_card int opened; union { +#ifdef GRUB_MACHINE_EFI struct { struct grub_efi_simple_network *efi_net; - void *efi_handle; + grub_efi_handle_t efi_handle; }; +#endif void *data; int data_num; }; @@ -420,30 +426,6 @@ extern struct grub_net_network_level_interface *grub_net_network_level_interface #define FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(var,next) for (var = grub_net_network_level_interfaces, next = var->next; var; var = next, next = var->next) -grub_err_t grub_net_send_link_layer (struct grub_net_network_level_interface *inf, - struct grub_net_buff *nb, - grub_net_link_level_address_t *target); - -typedef int -(*grub_net_packet_handler_t) (struct grub_net_buff *nb, - struct grub_net_network_level_interface *inf); - -grub_err_t grub_net_recv_link_layer (struct grub_net_network_level_interface *inf, - grub_net_packet_handler_t handler); - - -grub_err_t -grub_net_recv_ip_packets (struct grub_net_buff *nb, - const struct grub_net_card *card, - const grub_net_link_level_address_t *hwaddress); - -grub_err_t -grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, - const grub_net_network_level_address_t *target, - struct grub_net_buff *nb); - -#define FOR_NET_NL_PACKETS(inf, var) FOR_PACKETS(inf->nl_pending, var) - void grub_net_poll_cards (unsigned time); diff --git a/include/grub/net/device.h b/include/grub/net/device.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h index a841dc12c..a68aafd96 100644 --- a/include/grub/net/ethernet.h +++ b/include/grub/net/ethernet.h @@ -1,30 +1,26 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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_NET_ETHERNET_HEADER #define GRUB_NET_ETHERNET_HEADER 1 #include #include -#define LLCADDRMASK 0x7f - -struct etherhdr -{ - grub_uint8_t dst[6]; - grub_uint8_t src[6]; - grub_uint16_t type; -} __attribute__ ((packed)); - -struct llchdr -{ - grub_uint8_t dsap; - grub_uint8_t ssap; - grub_uint8_t ctrl; -} __attribute__ ((packed)); - -struct snaphdr -{ - grub_uint8_t oui[3]; - grub_uint16_t type; -} __attribute__ ((packed)); - /* IANA Ethertype */ enum { @@ -32,7 +28,6 @@ enum GRUB_NET_ETHERTYPE_ARP = 0x0806 }; - grub_err_t send_ethernet_packet (struct grub_net_network_level_interface *inf, struct grub_net_buff *nb, diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index cb8481a7d..9bed1e19c 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -1,35 +1,42 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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_NET_IP_HEADER #define GRUB_NET_IP_HEADER 1 #include +#include -struct iphdr { - grub_uint8_t verhdrlen; - grub_uint8_t service; - grub_uint16_t len; - grub_uint16_t ident; - grub_uint16_t frags; - grub_uint8_t ttl; - grub_uint8_t protocol; - grub_uint16_t chksum; - grub_uint32_t src; - grub_uint32_t dest; -} __attribute__ ((packed)) ; - -struct ip6hdr -{ - grub_uint8_t version:4, priority:4; - grub_uint8_t flow_lbl[3]; - grub_uint16_t payload_len; - grub_uint8_t nexthdr; - grub_uint8_t hop_limit; - grub_uint8_t saddr[16]; - grub_uint8_t daddr[16]; -} __attribute__ ((packed)); - -#define IP_UDP 0x11 /* UDP protocol */ +enum + { + IP_UDP = 0x11 /* UDP protocol */ + }; #define IP_BROADCAST 0xFFFFFFFF -grub_uint16_t ipchksum(void *ipv, int len); -void ipv4_ini(void); -void ipv4_fini(void); +grub_uint16_t grub_net_ip_chksum(void *ipv, int len); + +grub_err_t +grub_net_recv_ip_packets (struct grub_net_buff *nb, + const struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddress); + +grub_err_t +grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *target, + struct grub_net_buff *nb); + #endif diff --git a/include/grub/net/tftp.h b/include/grub/net/tftp.h deleted file mode 100644 index 0d8cbd1de..000000000 --- a/include/grub/net/tftp.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef GRUB_NET_TFTP_HEADER -#define GRUB_NET_TFTP_HEADER 1 - -#include -#include -#include - -/* IP port for the MTFTP server used for Intel's PXE */ -#define MTFTP_SERVER_PORT 75 -#define MTFTP_CLIENT_PORT 76 - -#define TFTP_DEFAULTSIZE_PACKET 512 -#define TFTP_MAX_PACKET 1432 - -/* IP port for the TFTP server */ -#define TFTP_SERVER_PORT 69 - - -/* We define these based on what's in arpa/tftp.h. We just like our - * names better, cause they're clearer */ -#define TFTP_RRQ 1 -#define TFTP_WRQ 2 -#define TFTP_DATA 3 -#define TFTP_ACK 4 -#define TFTP_ERROR 5 -#define TFTP_OACK 6 - -#define TFTP_CODE_EOF 1 -#define TFTP_CODE_MORE 2 -#define TFTP_CODE_ERROR 3 -#define TFTP_CODE_BOOT 4 -#define TFTP_CODE_CFG 5 - -#define TFTP_EUNDEF 0 /* not defined */ -#define TFTP_ENOTFOUND 1 /* file not found */ -#define TFTP_EACCESS 2 /* access violation */ -#define TFTP_ENOSPACE 3 /* disk full or allocation exceeded */ -#define TFTP_EBADOP 4 /* illegal TFTP operation */ -#define TFTP_EBADID 5 /* unknown transfer ID */ -#define TFTP_EEXISTS 6 /* file already exists */ -#define TFTP_ENOUSER 7 /* no such user */ - - /* * own here because this is cleaner, and maps to the same data layout. - * */ - - -struct tftphdr { - grub_uint16_t opcode; - union { - grub_int8_t rrq[TFTP_DEFAULTSIZE_PACKET]; - struct { - grub_uint16_t block; - grub_int8_t download[TFTP_MAX_PACKET]; - } data; - struct { - grub_uint16_t block; - } ack; - struct { - grub_uint16_t errcode; - grub_int8_t errmsg[TFTP_DEFAULTSIZE_PACKET]; - } err; - struct { - grub_int8_t data[TFTP_DEFAULTSIZE_PACKET+2]; - } oack; - } u; -} __attribute__ ((packed)) ; - -#endif diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h index 272612299..5aacf8abb 100644 --- a/include/grub/net/udp.h +++ b/include/grub/net/udp.h @@ -28,13 +28,11 @@ grub_net_udp_close (grub_net_socket_t sock) } grub_err_t -grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff *nb); +grub_net_send_udp_packet (const grub_net_socket_t socket, struct grub_net_buff *nb); grub_err_t grub_net_recv_udp_packet (struct grub_net_buff *nb, struct grub_net_network_level_interface *inf); -#define FOR_NET_UDP_PACKETS(inf, var) FOR_PACKETS(inf->udp_pending, var) - #endif From 1c3fcdee151a95730444352b2fb5774bfdd75ce6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 13:13:45 +0200 Subject: [PATCH 395/406] buffer network files. Fix incorrect net_fini_hw and unregister calls --- grub-core/net/net.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 0d664d9b5..1f2e2b7d4 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -32,6 +32,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -709,15 +710,36 @@ grub_net_fs_dir (grub_device_t device, const char *path __attribute__ ((unused)) } static grub_err_t -grub_net_fs_open (struct grub_file *file, const char *name) +grub_net_fs_open (struct grub_file *file_out, const char *name) { + grub_err_t err; + struct grub_file *file, *bufio; + + file = grub_malloc (sizeof (*file)); + if (!file) + return grub_errno; + + grub_memcpy (file, file_out, sizeof (struct grub_file)); file->device->net->packs.first = NULL; file->device->net->packs.last = NULL; file->device->net->name = grub_strdup (name); if (!file->device->net->name) return grub_errno; - return file->device->net->protocol->open (file, name); + err = file->device->net->protocol->open (file, name); + if (err) + return err; + bufio = grub_bufio_open (file, 32768); + if (! bufio) + { + file->device->net->protocol->close (file); + grub_free (file->device->net->name); + grub_free (file); + return grub_errno; + } + + grub_memcpy (file_out, bufio, sizeof (struct grub_file)); + return GRUB_ERR_NONE; } static grub_err_t @@ -1430,8 +1452,6 @@ GRUB_MOD_INIT(net) fini_hnd = grub_loader_register_preboot_hook (grub_net_fini_hw, grub_net_restore_hw, GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); - grub_net_fini_hw (0); - grub_loader_unregister_preboot_hook (fini_hnd); } GRUB_MOD_FINI(net) @@ -1446,5 +1466,6 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_getdhcp); grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; + grub_net_fini_hw (0); grub_loader_unregister_preboot_hook (fini_hnd); } From 228ccedb5e7870931b628da5f1f758be65dac623 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 13:37:33 +0200 Subject: [PATCH 396/406] poll cards when idle --- grub-core/kern/term.c | 4 ++++ grub-core/net/net.c | 11 +++++++++++ include/grub/kernel.h | 3 +++ 3 files changed, 18 insertions(+) diff --git a/grub-core/kern/term.c b/grub-core/kern/term.c index 7b3593161..d7c65dd82 100644 --- a/grub-core/kern/term.c +++ b/grub-core/kern/term.c @@ -29,6 +29,7 @@ struct grub_term_output *grub_term_outputs; struct grub_term_input *grub_term_inputs; void (*grub_term_poll_usb) (void) = NULL; +void (*grub_net_poll_cards_idle) (void) = NULL; /* Put a Unicode character. */ static void @@ -91,6 +92,9 @@ grub_checkkey (void) if (grub_term_poll_usb) grub_term_poll_usb (); + if (grub_net_poll_cards_idle) + grub_net_poll_cards_idle (); + FOR_ACTIVE_TERM_INPUTS(term) { pending_key = term->getkey (term); diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 1f2e2b7d4..bee4f8321 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -33,6 +33,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -809,6 +810,14 @@ grub_net_poll_cards (unsigned time) } } +static void +grub_net_poll_cards_idle_real (void) +{ + struct grub_net_card *card; + FOR_NET_CARDS (card) + receive_packets (card); +} + /* Read from the packets list*/ static grub_ssize_t grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) @@ -1452,6 +1461,7 @@ GRUB_MOD_INIT(net) fini_hnd = grub_loader_register_preboot_hook (grub_net_fini_hw, grub_net_restore_hw, GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); + grub_net_poll_cards_idle = grub_net_poll_cards_idle_real; } GRUB_MOD_FINI(net) @@ -1468,4 +1478,5 @@ GRUB_MOD_FINI(net) grub_net_open = NULL; grub_net_fini_hw (0); grub_loader_unregister_preboot_hook (fini_hnd); + grub_net_poll_cards_idle = grub_net_poll_cards_idle_real; } diff --git a/include/grub/kernel.h b/include/grub/kernel.h index 6a5f91c3d..aef585668 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -90,6 +90,9 @@ grub_machine_get_bootlocation (char **device, char **path); /* Register all the exported symbols. This is automatically generated. */ void grub_register_exported_symbols (void); +extern void (*EXPORT_VAR(grub_net_poll_cards_idle)) (void); + + #if ! defined (ASM_FILE) extern char grub_prefix[]; #endif From 138eeb3625b22b9b5b286813088d8edca09ff2af Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 13:52:35 +0200 Subject: [PATCH 397/406] Move bootp into a separate file --- grub-core/Makefile.core.def | 1 + grub-core/net/net.c | 514 +----------------------------------- include/grub/net.h | 16 ++ 3 files changed, 24 insertions(+), 507 deletions(-) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index d1e1d30e4..7bceaa98f 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1579,6 +1579,7 @@ module = { module = { name = net; common = net/net.c; + common = net/bootp.c; common = net/ip.c; common = net/udp.c; common = net/ethernet.c; diff --git a/grub-core/net/net.c b/grub-core/net/net.c index bee4f8321..bc16fbde5 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -16,10 +16,8 @@ * along with GRUB. If not, see . */ -#include #include #include -#include #include #include #include @@ -28,16 +26,14 @@ #include #include #include -#include #include -#include #include #include #include GRUB_MOD_LICENSE ("GPLv3+"); -static char *default_server; +char *grub_net_default_server; struct grub_net_route { @@ -59,17 +55,6 @@ struct grub_net_card *grub_net_cards = NULL; struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; static struct grub_fs grub_net_fs; -static inline void -grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) -{ - inter->card->num_ifaces--; - *inter->prev = inter->next; - if (inter->next) - inter->next->prev = inter->prev; - inter->next = 0; - inter->prev = 0; -} - void grub_net_card_unregister (struct grub_net_card *card) { @@ -644,7 +629,7 @@ grub_net_open_real (const char *name) { protname = "tftp"; protnamelen = sizeof ("tftp") - 1; - server = default_server; + server = grub_net_default_server; } else { @@ -659,7 +644,7 @@ grub_net_open_real (const char *name) else { protnamelen = grub_strlen (name); - server = default_server; + server = grub_net_default_server; protname = name; } } @@ -911,483 +896,6 @@ grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) return grub_net_fs_read_real (file, buf, len); } -static char * -grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), - const char *val __attribute__ ((unused))) -{ - return NULL; -} - -static void -set_env_limn_ro (const char *intername, const char *suffix, - char *value, grub_size_t len) -{ - char c; - char varname[sizeof ("net_") + grub_strlen (intername) + sizeof ("_") - + grub_strlen (suffix)]; - grub_snprintf (varname, sizeof (varname), "net_%s_%s", intername, suffix); - c = value[len]; - value[len] = 0; - grub_env_set (varname, value); - value[len] = c; - grub_register_variable_hook (varname, 0, grub_env_write_readonly); -} - -static void -parse_dhcp_vendor (const char *name, void *vend, int limit) -{ - grub_uint8_t *ptr, *ptr0; - - ptr = ptr0 = vend; - - if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0 - || ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1 - || ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2 - || ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3) - return; - ptr = ptr + sizeof (grub_uint32_t); - while (ptr - ptr0 < limit) - { - grub_uint8_t tagtype; - grub_uint8_t taglength; - - tagtype = *ptr++; - - /* Pad tag. */ - if (tagtype == 0) - continue; - - /* End tag. */ - if (tagtype == 0xff) - return; - - taglength = *ptr++; - - switch (tagtype) - { - case 12: - set_env_limn_ro (name, "hostname", (char *) ptr, taglength); - break; - - case 15: - set_env_limn_ro (name, "domain", (char *) ptr, taglength); - break; - - case 17: - set_env_limn_ro (name, "rootpath", (char *) ptr, taglength); - break; - - case 18: - set_env_limn_ro (name, "extensionspath", (char *) ptr, taglength); - break; - - /* If you need any other options please contact GRUB - developpement team. */ - } - - ptr += taglength; - } -} - -#define OFFSET_OF(x, y) ((grub_uint8_t *)((y)->x) - (grub_uint8_t *)(y)) - -struct grub_net_network_level_interface * -grub_net_configure_by_dhcp_ack (const char *name, - struct grub_net_card *card, - grub_net_interface_flags_t flags, - const struct grub_net_bootp_packet *bp, - grub_size_t size, - int is_def, char **device, char **path) -{ - grub_net_network_level_address_t addr; - grub_net_link_level_address_t hwaddr; - struct grub_net_network_level_interface *inter; - - addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - addr.ipv4 = bp->your_ip; - - if (device) - *device = 0; - if (path) - *path = 0; - - grub_memcpy (hwaddr.mac, bp->mac_addr, - bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len - : sizeof (hwaddr.mac)); - hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - - inter = grub_net_add_addr (name, card, addr, hwaddr, flags); - { - grub_net_network_level_netaddress_t target; - grub_net_network_level_address_t gw; - char rname[grub_strlen (name) + sizeof ("_gw")]; - - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4.base = bp->server_ip; - target.ipv4.masksize = 32; - gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - gw.ipv4 = bp->gateway_ip; - grub_snprintf (rname, sizeof (rname), "%s_gw", name); - grub_net_add_route_gw (rname, target, gw); - } - { - grub_net_network_level_netaddress_t target; - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4.base = bp->gateway_ip; - target.ipv4.masksize = 32; - grub_net_add_route (name, target, inter); - } - - if (size > OFFSET_OF (boot_file, bp)) - set_env_limn_ro (name, "boot_file", (char *) bp->boot_file, - sizeof (bp->boot_file)); - if (is_def) - default_server = 0; - if (size > OFFSET_OF (server_name, bp) - && bp->server_name[0]) - { - set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name, - sizeof (bp->server_name)); - if (is_def && !default_server) - { - default_server = grub_strdup (bp->server_name); - grub_print_error (); - } - if (device && !*device) - { - *device = grub_xasprintf ("tftp,%s", bp->server_name); - grub_print_error (); - } - } - if (is_def && !default_server) - { - default_server = grub_xasprintf ("%d.%d.%d.%d", - ((grub_uint8_t *) &bp->server_ip)[0], - ((grub_uint8_t *) &bp->server_ip)[1], - ((grub_uint8_t *) &bp->server_ip)[2], - ((grub_uint8_t *) &bp->server_ip)[3]); - grub_print_error (); - } - - if (device && !*device) - { - *device = grub_xasprintf ("tftp,%d.%d.%d.%d", - ((grub_uint8_t *) &bp->server_ip)[0], - ((grub_uint8_t *) &bp->server_ip)[1], - ((grub_uint8_t *) &bp->server_ip)[2], - ((grub_uint8_t *) &bp->server_ip)[3]); - grub_print_error (); - } - if (size > OFFSET_OF (boot_file, bp) && path) - { - *path = grub_strndup (bp->boot_file, sizeof (bp->boot_file)); - grub_print_error (); - if (*path) - { - char *slash; - slash = grub_strrchr (*path, '/'); - if (slash) - *slash = 0; - else - **path = 0; - } - } - if (size > OFFSET_OF (vendor, bp)) - parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp)); - - inter->dhcp_ack = grub_malloc (size); - if (inter->dhcp_ack) - { - grub_memcpy (inter->dhcp_ack, bp, size); - inter->dhcp_acklen = size; - } - else - grub_errno = GRUB_ERR_NONE; - - return inter; -} - -void -grub_net_process_dhcp (struct grub_net_buff *nb, - struct grub_net_card *card) -{ - char *name; - struct grub_net_network_level_interface *inf; - - name = grub_xasprintf ("%s:dhcp", card->name); - if (!name) - { - grub_print_error (); - return; - } - grub_net_configure_by_dhcp_ack (name, card, - 0, (const struct grub_net_bootp_packet *) nb->data, - (nb->tail - nb->data), 0, 0, 0); - grub_free (name); - if (grub_errno) - grub_print_error (); - else - { - FOR_NET_NETWORK_LEVEL_INTERFACES(inf) - if (grub_memcmp (inf->name, card->name, grub_strlen (card->name)) == 0 - && grub_memcmp (inf->name + grub_strlen (card->name), - ":dhcp_tmp", sizeof (":dhcp_tmp") - 1) == 0) - { - grub_net_network_level_interface_unregister (inf); - break; - } - } -} - -static char -hexdigit (grub_uint8_t val) -{ - if (val < 10) - return val + '0'; - return val + 'a' - 10; -} - -static grub_err_t -grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), - int argc, char **args) -{ - struct grub_net_network_level_interface *inter; - int num; - grub_uint8_t *ptr; - grub_uint8_t taglength; - - if (argc < 4) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "4 arguments expected"); - - FOR_NET_NETWORK_LEVEL_INTERFACES (inter) - if (grub_strcmp (inter->name, args[1]) == 0) - break; - - if (!inter) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - N_("unrecognised interface %s"), args[1]); - - if (!inter->dhcp_ack) - return grub_error (GRUB_ERR_IO, N_("no DHCP info found")); - - if (inter->dhcp_acklen <= OFFSET_OF (vendor, inter->dhcp_ack)) - return grub_error (GRUB_ERR_IO, N_("no DHCP options found")); - - num = grub_strtoul (args[2], 0, 0); - if (grub_errno) - return grub_errno; - - ptr = inter->dhcp_ack->vendor; - - if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0 - || ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1 - || ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2 - || ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3) - return grub_error (GRUB_ERR_IO, N_("no DHCP options found")); - ptr = ptr + sizeof (grub_uint32_t); - while (1) - { - grub_uint8_t tagtype; - - if (ptr >= ((grub_uint8_t *) inter->dhcp_ack) + inter->dhcp_acklen) - return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num); - - tagtype = *ptr++; - - /* Pad tag. */ - if (tagtype == 0) - continue; - - /* End tag. */ - if (tagtype == 0xff) - return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num); - - taglength = *ptr++; - - if (tagtype == num) - break; - ptr += taglength; - } - - if (grub_strcmp (args[3], "string") == 0) - { - char *val = grub_malloc (taglength + 1); - if (!val) - return grub_errno; - grub_memcpy (val, ptr, taglength); - val[taglength] = 0; - if (args[0][0] == '-' && args[0][1] == 0) - grub_printf ("%s\n", val); - else - return grub_env_set (args[0], val); - return GRUB_ERR_NONE; - } - - if (grub_strcmp (args[3], "number") == 0) - { - grub_uint64_t val = 0; - int i; - for (i = 0; i < taglength; i++) - val = (val << 8) | ptr[i]; - if (args[0][0] == '-' && args[0][1] == 0) - grub_printf ("%llu\n", (unsigned long long) val); - else - { - char valn[64]; - grub_printf (valn, sizeof (valn), "%lld\n", (unsigned long long) val); - return grub_env_set (args[0], valn); - } - return GRUB_ERR_NONE; - } - - if (grub_strcmp (args[3], "hex") == 0) - { - char *val = grub_malloc (2 * taglength + 1); - int i; - if (!val) - return grub_errno; - for (i = 0; i < taglength; i++) - { - val[2 * i] = hexdigit (ptr[i] >> 4); - val[2 * i + 1] = hexdigit (ptr[i] & 0xf); - } - val[2 * taglength] = 0; - if (args[0][0] == '-' && args[0][1] == 0) - grub_printf ("%s\n", val); - else - return grub_env_set (args[0], val); - return GRUB_ERR_NONE; - } - - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "unrecognised format specification %s", args[3]); -} - -static grub_err_t -grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), - int argc, char **args) -{ - struct grub_net_card *card; - struct grub_net_network_level_interface *ifaces; - grub_size_t ncards = 0; - unsigned j = 0; - int interval; - grub_err_t err; - - FOR_NET_CARDS (card) - { - if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) - continue; - ncards++; - } - - ifaces = grub_zalloc (ncards * sizeof (ifaces[0])); - if (!ifaces) - return grub_errno; - - j = 0; - FOR_NET_CARDS (card) - { - if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) - continue; - ifaces[j].card = card; - ifaces[j].next = &ifaces[j+1]; - if (j) - ifaces[j].prev = &ifaces[j-1].next; - ifaces[j].name = grub_xasprintf ("%s:dhcp_tmp", card->name); - card->num_ifaces++; - if (!ifaces[j].name) - { - unsigned i; - for (i = 0; i < j; i++) - grub_free (ifaces[i].name); - grub_free (ifaces); - return grub_errno; - } - ifaces[j].address.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV; - grub_memcpy (&ifaces[j].hwaddress, &card->default_address, - sizeof (ifaces[j].hwaddress)); - j++; - } - ifaces[ncards - 1].next = grub_net_network_level_interfaces; - if (grub_net_network_level_interfaces) - grub_net_network_level_interfaces->prev = & ifaces[ncards - 1].next; - grub_net_network_level_interfaces = &ifaces[0]; - ifaces[0].prev = &grub_net_network_level_interfaces; - for (interval = 200; interval < 10000; interval *= 2) - { - int done = 0; - for (j = 0; j < ncards; j++) - { - struct grub_net_bootp_packet *pack; - struct grub_datetime date; - grub_int32_t t; - struct grub_net_buff *nb; - struct udphdr *udph; - grub_net_network_level_address_t target; - - if (!ifaces[j].prev) - continue; - nb = grub_netbuff_alloc (sizeof (*pack)); - if (!nb) - return grub_errno; - err = grub_netbuff_reserve (nb, sizeof (*pack) + 64 + 128); - if (err) - return err; - err = grub_netbuff_push (nb, sizeof (*pack) + 64); - if (err) - return err; - pack = (void *) nb->data; - done = 1; - grub_memset (pack, 0, sizeof (*pack) + 64); - pack->opcode = 1; - pack->hw_type = 1; - pack->hw_len = 6; - err = grub_get_datetime (&date); - if (err || !grub_datetime2unixtime (&date, &t)) - { - grub_errno = GRUB_ERR_NONE; - t = 0; - } - pack->ident = grub_cpu_to_be32 (t); - pack->seconds = 0;//grub_cpu_to_be16 (t); - - grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6); - - grub_netbuff_push (nb, sizeof (*udph)); - - udph = (struct udphdr *) nb->data; - udph->src = grub_cpu_to_be16 (68); - udph->dst = grub_cpu_to_be16 (67); - udph->chksum = 0; - udph->len = grub_cpu_to_be16 (nb->tail - nb->data); - - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4 = 0xffffffff; - - err = grub_net_send_ip_packet (&ifaces[j], &target, nb); - if (err) - return err; - } - if (!done) - break; - grub_net_poll_cards (interval); - } - - err = GRUB_ERR_NONE; - for (j = 0; j < ncards; j++) - { - if (!ifaces[j].prev) - continue; - grub_error_push (); - grub_net_network_level_interface_unregister (&ifaces[j]); - err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't configure %s", - ifaces[j].card->name); - } - - return err; -} - static struct grub_fs grub_net_fs = { .name = "netfs", @@ -1423,8 +931,8 @@ grub_net_restore_hw (void) static void *fini_hnd; static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; -static grub_command_t cmd_lsroutes, cmd_lscards, cmd_getdhcp, cmd_bootp; -static grub_command_t cmd_dhcp, cmd_lsaddr; +static grub_command_t cmd_lsroutes, cmd_lscards; +static grub_command_t cmd_lsaddr; GRUB_MOD_INIT(net) { @@ -1446,15 +954,7 @@ GRUB_MOD_INIT(net) "", N_("list network cards")); cmd_lsaddr = grub_register_command ("net_ls_addr", grub_cmd_listaddrs, "", N_("list network addresses")); - cmd_bootp = grub_register_command ("net_bootp", grub_cmd_bootp, - "[CARD]", - N_("perform a bootp autoconfiguration")); - cmd_dhcp = grub_register_command ("net_dhcp", grub_cmd_bootp, - "[CARD]", - N_("perform a bootp autoconfiguration")); - cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt, - N_("VAR INTERFACE NUMBER DESCRIPTION"), - N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); + grub_bootp_init (); grub_fs_register (&grub_net_fs); grub_net_open = grub_net_open_real; @@ -1466,6 +966,7 @@ GRUB_MOD_INIT(net) GRUB_MOD_FINI(net) { + grub_bootp_fini (); grub_unregister_command (cmd_addaddr); grub_unregister_command (cmd_deladdr); grub_unregister_command (cmd_addroute); @@ -1473,7 +974,6 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_lsroutes); grub_unregister_command (cmd_lscards); grub_unregister_command (cmd_lsaddr); - grub_unregister_command (cmd_getdhcp); grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; grub_net_fini_hw (0); diff --git a/include/grub/net.h b/include/grub/net.h index 0ac0838cf..92e637d89 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -429,4 +429,20 @@ extern struct grub_net_network_level_interface *grub_net_network_level_interface void grub_net_poll_cards (unsigned time); +void grub_bootp_init (void); +void grub_bootp_fini (void); + +static inline void +grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) +{ + inter->card->num_ifaces--; + *inter->prev = inter->next; + if (inter->next) + inter->next->prev = inter->prev; + inter->next = 0; + inter->prev = 0; +} + +extern char *grub_net_default_server; + #endif /* ! GRUB_NET_HEADER */ From 6cf88dfd7aa8091e7dfe48c5a1e6e722b48c8a37 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 15:02:19 +0200 Subject: [PATCH 398/406] add missing file --- grub-core/net/bootp.c | 527 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 527 insertions(+) create mode 100644 grub-core/net/bootp.c diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c new file mode 100644 index 000000000..a1aaf402f --- /dev/null +++ b/grub-core/net/bootp.c @@ -0,0 +1,527 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 + +static char * +grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), + const char *val __attribute__ ((unused))) +{ + return NULL; +} + +static void +set_env_limn_ro (const char *intername, const char *suffix, + char *value, grub_size_t len) +{ + char c; + char varname[sizeof ("net_") + grub_strlen (intername) + sizeof ("_") + + grub_strlen (suffix)]; + grub_snprintf (varname, sizeof (varname), "net_%s_%s", intername, suffix); + c = value[len]; + value[len] = 0; + grub_env_set (varname, value); + value[len] = c; + grub_register_variable_hook (varname, 0, grub_env_write_readonly); +} + +static void +parse_dhcp_vendor (const char *name, void *vend, int limit) +{ + grub_uint8_t *ptr, *ptr0; + + ptr = ptr0 = vend; + + if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0 + || ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1 + || ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2 + || ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3) + return; + ptr = ptr + sizeof (grub_uint32_t); + while (ptr - ptr0 < limit) + { + grub_uint8_t tagtype; + grub_uint8_t taglength; + + tagtype = *ptr++; + + /* Pad tag. */ + if (tagtype == 0) + continue; + + /* End tag. */ + if (tagtype == 0xff) + return; + + taglength = *ptr++; + + switch (tagtype) + { + case 12: + set_env_limn_ro (name, "hostname", (char *) ptr, taglength); + break; + + case 15: + set_env_limn_ro (name, "domain", (char *) ptr, taglength); + break; + + case 17: + set_env_limn_ro (name, "rootpath", (char *) ptr, taglength); + break; + + case 18: + set_env_limn_ro (name, "extensionspath", (char *) ptr, taglength); + break; + + /* If you need any other options please contact GRUB + developpement team. */ + } + + ptr += taglength; + } +} + +#define OFFSET_OF(x, y) ((grub_uint8_t *)((y)->x) - (grub_uint8_t *)(y)) + +struct grub_net_network_level_interface * +grub_net_configure_by_dhcp_ack (const char *name, + struct grub_net_card *card, + grub_net_interface_flags_t flags, + const struct grub_net_bootp_packet *bp, + grub_size_t size, + int is_def, char **device, char **path) +{ + grub_net_network_level_address_t addr; + grub_net_link_level_address_t hwaddr; + struct grub_net_network_level_interface *inter; + + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + addr.ipv4 = bp->your_ip; + + if (device) + *device = 0; + if (path) + *path = 0; + + grub_memcpy (hwaddr.mac, bp->mac_addr, + bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len + : sizeof (hwaddr.mac)); + hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + + inter = grub_net_add_addr (name, card, addr, hwaddr, flags); + { + grub_net_network_level_netaddress_t target; + grub_net_network_level_address_t gw; + char rname[grub_strlen (name) + sizeof ("_gw")]; + + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = bp->server_ip; + target.ipv4.masksize = 32; + gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + gw.ipv4 = bp->gateway_ip; + grub_snprintf (rname, sizeof (rname), "%s_gw", name); + grub_net_add_route_gw (rname, target, gw); + } + { + grub_net_network_level_netaddress_t target; + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = bp->gateway_ip; + target.ipv4.masksize = 32; + grub_net_add_route (name, target, inter); + } + + if (size > OFFSET_OF (boot_file, bp)) + set_env_limn_ro (name, "boot_file", (char *) bp->boot_file, + sizeof (bp->boot_file)); + if (is_def) + grub_net_default_server = 0; + if (size > OFFSET_OF (server_name, bp) + && bp->server_name[0]) + { + set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name, + sizeof (bp->server_name)); + if (is_def && !grub_net_default_server) + { + grub_net_default_server = grub_strdup (bp->server_name); + grub_print_error (); + } + if (device && !*device) + { + *device = grub_xasprintf ("tftp,%s", bp->server_name); + grub_print_error (); + } + } + if (is_def && !grub_net_default_server) + { + grub_net_default_server = grub_xasprintf ("%d.%d.%d.%d", + ((grub_uint8_t *) &bp->server_ip)[0], + ((grub_uint8_t *) &bp->server_ip)[1], + ((grub_uint8_t *) &bp->server_ip)[2], + ((grub_uint8_t *) &bp->server_ip)[3]); + grub_print_error (); + } + + if (device && !*device) + { + *device = grub_xasprintf ("tftp,%d.%d.%d.%d", + ((grub_uint8_t *) &bp->server_ip)[0], + ((grub_uint8_t *) &bp->server_ip)[1], + ((grub_uint8_t *) &bp->server_ip)[2], + ((grub_uint8_t *) &bp->server_ip)[3]); + grub_print_error (); + } + if (size > OFFSET_OF (boot_file, bp) && path) + { + *path = grub_strndup (bp->boot_file, sizeof (bp->boot_file)); + grub_print_error (); + if (*path) + { + char *slash; + slash = grub_strrchr (*path, '/'); + if (slash) + *slash = 0; + else + **path = 0; + } + } + if (size > OFFSET_OF (vendor, bp)) + parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp)); + + inter->dhcp_ack = grub_malloc (size); + if (inter->dhcp_ack) + { + grub_memcpy (inter->dhcp_ack, bp, size); + inter->dhcp_acklen = size; + } + else + grub_errno = GRUB_ERR_NONE; + + return inter; +} + +void +grub_net_process_dhcp (struct grub_net_buff *nb, + struct grub_net_card *card) +{ + char *name; + struct grub_net_network_level_interface *inf; + + name = grub_xasprintf ("%s:dhcp", card->name); + if (!name) + { + grub_print_error (); + return; + } + grub_net_configure_by_dhcp_ack (name, card, + 0, (const struct grub_net_bootp_packet *) nb->data, + (nb->tail - nb->data), 0, 0, 0); + grub_free (name); + if (grub_errno) + grub_print_error (); + else + { + FOR_NET_NETWORK_LEVEL_INTERFACES(inf) + if (grub_memcmp (inf->name, card->name, grub_strlen (card->name)) == 0 + && grub_memcmp (inf->name + grub_strlen (card->name), + ":dhcp_tmp", sizeof (":dhcp_tmp") - 1) == 0) + { + grub_net_network_level_interface_unregister (inf); + break; + } + } +} + +static char +hexdigit (grub_uint8_t val) +{ + if (val < 10) + return val + '0'; + return val + 'a' - 10; +} + +static grub_err_t +grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_network_level_interface *inter; + int num; + grub_uint8_t *ptr; + grub_uint8_t taglength; + + if (argc < 4) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "4 arguments expected"); + + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + if (grub_strcmp (inter->name, args[1]) == 0) + break; + + if (!inter) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unrecognised interface %s"), args[1]); + + if (!inter->dhcp_ack) + return grub_error (GRUB_ERR_IO, N_("no DHCP info found")); + + if (inter->dhcp_acklen <= OFFSET_OF (vendor, inter->dhcp_ack)) + return grub_error (GRUB_ERR_IO, N_("no DHCP options found")); + + num = grub_strtoul (args[2], 0, 0); + if (grub_errno) + return grub_errno; + + ptr = inter->dhcp_ack->vendor; + + if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0 + || ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1 + || ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2 + || ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3) + return grub_error (GRUB_ERR_IO, N_("no DHCP options found")); + ptr = ptr + sizeof (grub_uint32_t); + while (1) + { + grub_uint8_t tagtype; + + if (ptr >= ((grub_uint8_t *) inter->dhcp_ack) + inter->dhcp_acklen) + return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num); + + tagtype = *ptr++; + + /* Pad tag. */ + if (tagtype == 0) + continue; + + /* End tag. */ + if (tagtype == 0xff) + return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num); + + taglength = *ptr++; + + if (tagtype == num) + break; + ptr += taglength; + } + + if (grub_strcmp (args[3], "string") == 0) + { + char *val = grub_malloc (taglength + 1); + if (!val) + return grub_errno; + grub_memcpy (val, ptr, taglength); + val[taglength] = 0; + if (args[0][0] == '-' && args[0][1] == 0) + grub_printf ("%s\n", val); + else + return grub_env_set (args[0], val); + return GRUB_ERR_NONE; + } + + if (grub_strcmp (args[3], "number") == 0) + { + grub_uint64_t val = 0; + int i; + for (i = 0; i < taglength; i++) + val = (val << 8) | ptr[i]; + if (args[0][0] == '-' && args[0][1] == 0) + grub_printf ("%llu\n", (unsigned long long) val); + else + { + char valn[64]; + grub_printf (valn, sizeof (valn), "%lld\n", (unsigned long long) val); + return grub_env_set (args[0], valn); + } + return GRUB_ERR_NONE; + } + + if (grub_strcmp (args[3], "hex") == 0) + { + char *val = grub_malloc (2 * taglength + 1); + int i; + if (!val) + return grub_errno; + for (i = 0; i < taglength; i++) + { + val[2 * i] = hexdigit (ptr[i] >> 4); + val[2 * i + 1] = hexdigit (ptr[i] & 0xf); + } + val[2 * taglength] = 0; + if (args[0][0] == '-' && args[0][1] == 0) + grub_printf ("%s\n", val); + else + return grub_env_set (args[0], val); + return GRUB_ERR_NONE; + } + + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "unrecognised format specification %s", args[3]); +} + +static grub_err_t +grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_card *card; + struct grub_net_network_level_interface *ifaces; + grub_size_t ncards = 0; + unsigned j = 0; + int interval; + grub_err_t err; + + FOR_NET_CARDS (card) + { + if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) + continue; + ncards++; + } + + ifaces = grub_zalloc (ncards * sizeof (ifaces[0])); + if (!ifaces) + return grub_errno; + + j = 0; + FOR_NET_CARDS (card) + { + if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) + continue; + ifaces[j].card = card; + ifaces[j].next = &ifaces[j+1]; + if (j) + ifaces[j].prev = &ifaces[j-1].next; + ifaces[j].name = grub_xasprintf ("%s:dhcp_tmp", card->name); + card->num_ifaces++; + if (!ifaces[j].name) + { + unsigned i; + for (i = 0; i < j; i++) + grub_free (ifaces[i].name); + grub_free (ifaces); + return grub_errno; + } + ifaces[j].address.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV; + grub_memcpy (&ifaces[j].hwaddress, &card->default_address, + sizeof (ifaces[j].hwaddress)); + j++; + } + ifaces[ncards - 1].next = grub_net_network_level_interfaces; + if (grub_net_network_level_interfaces) + grub_net_network_level_interfaces->prev = & ifaces[ncards - 1].next; + grub_net_network_level_interfaces = &ifaces[0]; + ifaces[0].prev = &grub_net_network_level_interfaces; + for (interval = 200; interval < 10000; interval *= 2) + { + int done = 0; + for (j = 0; j < ncards; j++) + { + struct grub_net_bootp_packet *pack; + struct grub_datetime date; + grub_int32_t t; + struct grub_net_buff *nb; + struct udphdr *udph; + grub_net_network_level_address_t target; + + if (!ifaces[j].prev) + continue; + nb = grub_netbuff_alloc (sizeof (*pack)); + if (!nb) + return grub_errno; + err = grub_netbuff_reserve (nb, sizeof (*pack) + 64 + 128); + if (err) + return err; + err = grub_netbuff_push (nb, sizeof (*pack) + 64); + if (err) + return err; + pack = (void *) nb->data; + done = 1; + grub_memset (pack, 0, sizeof (*pack) + 64); + pack->opcode = 1; + pack->hw_type = 1; + pack->hw_len = 6; + err = grub_get_datetime (&date); + if (err || !grub_datetime2unixtime (&date, &t)) + { + grub_errno = GRUB_ERR_NONE; + t = 0; + } + pack->ident = grub_cpu_to_be32 (t); + pack->seconds = 0;//grub_cpu_to_be16 (t); + + grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6); + + grub_netbuff_push (nb, sizeof (*udph)); + + udph = (struct udphdr *) nb->data; + udph->src = grub_cpu_to_be16 (68); + udph->dst = grub_cpu_to_be16 (67); + udph->chksum = 0; + udph->len = grub_cpu_to_be16 (nb->tail - nb->data); + + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4 = 0xffffffff; + + err = grub_net_send_ip_packet (&ifaces[j], &target, nb); + if (err) + return err; + } + if (!done) + break; + grub_net_poll_cards (interval); + } + + err = GRUB_ERR_NONE; + for (j = 0; j < ncards; j++) + { + if (!ifaces[j].prev) + continue; + grub_error_push (); + grub_net_network_level_interface_unregister (&ifaces[j]); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't configure %s", + ifaces[j].card->name); + } + + return err; +} + +static grub_command_t cmd_dhcp, cmd_getdhcp, cmd_bootp; + +void +grub_bootp_init (void) +{ + cmd_bootp = grub_register_command ("net_bootp", grub_cmd_bootp, + "[CARD]", + N_("perform a bootp autoconfiguration")); + cmd_dhcp = grub_register_command ("net_dhcp", grub_cmd_bootp, + "[CARD]", + N_("perform a bootp autoconfiguration")); + cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt, + N_("VAR INTERFACE NUMBER DESCRIPTION"), + N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); +} + +void +grub_bootp_fini (void) +{ + grub_unregister_command (cmd_getdhcp); + grub_unregister_command (cmd_dhcp); + grub_unregister_command (cmd_bootp); +} From c97dbbf2f28c7d3026e9109790167b646d76ac5e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 17:40:24 +0200 Subject: [PATCH 399/406] Fix a memory leak --- grub-core/disk/ieee1275/ofdisk.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c index 0a935d5c2..7868b14b1 100644 --- a/grub-core/disk/ieee1275/ofdisk.c +++ b/grub-core/disk/ieee1275/ofdisk.c @@ -243,14 +243,24 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) grub_dprintf ("disk", "Opening `%s'.\n", devpath); if (grub_ieee1275_finddevice (devpath, &dev)) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties"); + { + grub_free (devpath); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + "can't read device properties"); + } if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop), &actual)) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type"); + { + grub_free (devpath); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type"); + } if (grub_strcmp (prop, "block")) - return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device"); + { + grub_free (devpath); + return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device"); + } /* XXX: There is no property to read the number of blocks. There should be a property `#blocks', but it is not there. Perhaps it From c2aa00f059ab09bd427703c874d8ff7936ba3d39 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 17:40:36 +0200 Subject: [PATCH 400/406] Fix a memory leak --- grub-core/kern/dl.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 5f214e378..1841bf1f5 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -688,11 +688,9 @@ grub_dl_load_file (const char *filename) grub_file_close (file); mod = grub_dl_load_core (core, size); + grub_free (core); if (! mod) - { - grub_free (core); - return 0; - } + return 0; mod->ref_count--; return mod; From f872d4744e66dde8cccbc9a189ac39e432851e92 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 17:40:56 +0200 Subject: [PATCH 401/406] Fix compilation error --- grub-core/kern/ieee1275/openfw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 2cecd8c7f..4e705a4d8 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -23,7 +23,6 @@ #include #include #include -#include enum grub_ieee1275_parse_type { From e1a0e1b42841f02481f8051cccf9669aa5a231a4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 17:41:19 +0200 Subject: [PATCH 402/406] Fix the usage of unsupported %zx --- grub-core/kern/mm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c index d54f3f240..ee4d58d81 100644 --- a/grub-core/kern/mm.c +++ b/grub-core/kern/mm.c @@ -515,7 +515,7 @@ grub_debug_malloc (const char *file, int line, grub_size_t size) void *ptr; if (grub_mm_debug) - grub_printf ("%s:%d: malloc (0x%zx) = ", file, line, size); + grub_printf ("%s:%d: malloc (0x%" PRIxGRUB_SIZE ") = ", file, line, size); ptr = grub_malloc (size); if (grub_mm_debug) grub_printf ("%p\n", ptr); @@ -528,7 +528,7 @@ grub_debug_zalloc (const char *file, int line, grub_size_t size) void *ptr; if (grub_mm_debug) - grub_printf ("%s:%d: zalloc (0x%zx) = ", file, line, size); + grub_printf ("%s:%d: zalloc (0x%" PRIxGRUB_SIZE ") = ", file, line, size); ptr = grub_zalloc (size); if (grub_mm_debug) grub_printf ("%p\n", ptr); @@ -547,7 +547,7 @@ void * grub_debug_realloc (const char *file, int line, void *ptr, grub_size_t size) { if (grub_mm_debug) - grub_printf ("%s:%d: realloc (%p, 0x%zx) = ", file, line, ptr, size); + grub_printf ("%s:%d: realloc (%p, 0x%" PRIxGRUB_SIZE ") = ", file, line, ptr, size); ptr = grub_realloc (ptr, size); if (grub_mm_debug) grub_printf ("%p\n", ptr); @@ -561,8 +561,8 @@ grub_debug_memalign (const char *file, int line, grub_size_t align, void *ptr; if (grub_mm_debug) - grub_printf ("%s:%d: memalign (0x%zx, 0x%zx) = ", - file, line, align, size); + grub_printf ("%s:%d: memalign (0x%" PRIxGRUB_SIZE ", 0x%" PRIxGRUB_SIZE + ") = ", file, line, align, size); ptr = grub_memalign (align, size); if (grub_mm_debug) grub_printf ("%p\n", ptr); From c3bf5267b016238d09455c843d425e7a9ce30e83 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 17:41:49 +0200 Subject: [PATCH 403/406] Fix a memory leak --- grub-core/net/bootp.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index a1aaf402f..84bdc04d7 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -444,13 +444,22 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), continue; nb = grub_netbuff_alloc (sizeof (*pack)); if (!nb) - return grub_errno; + { + grub_netbuff_free (nb); + return grub_errno; + } err = grub_netbuff_reserve (nb, sizeof (*pack) + 64 + 128); if (err) - return err; + { + grub_netbuff_free (nb); + return err; + } err = grub_netbuff_push (nb, sizeof (*pack) + 64); if (err) - return err; + { + grub_netbuff_free (nb); + return err; + } pack = (void *) nb->data; done = 1; grub_memset (pack, 0, sizeof (*pack) + 64); @@ -480,6 +489,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), target.ipv4 = 0xffffffff; err = grub_net_send_ip_packet (&ifaces[j], &target, nb); + grub_netbuff_free (nb); if (err) return err; } @@ -491,6 +501,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), err = GRUB_ERR_NONE; for (j = 0; j < ncards; j++) { + grub_free (ifaces[j].name); if (!ifaces[j].prev) continue; grub_error_push (); @@ -499,6 +510,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), ifaces[j].card->name); } + grub_free (ifaces); return err; } From d1831ca48a8ee052599f129c36e346336fae6b17 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 18:21:07 +0200 Subject: [PATCH 404/406] Limit idle polling frequency --- grub-core/net/drivers/ieee1275/ofnet.c | 1 + grub-core/net/net.c | 10 +++++++++- include/grub/net.h | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index cc29d0987..20d45ee3d 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -253,6 +253,7 @@ grub_ofnet_findcards (void) card->flags = 0; shortname = find_alias (alias->path); card->name = grub_xasprintf ("ofnet_%s", shortname ? : alias->path); + card->idle_poll_delay_ms = 1; grub_free (shortname); card->driver = &ofdriver; diff --git a/grub-core/net/net.c b/grub-core/net/net.c index bc16fbde5..641aebd64 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -768,6 +768,7 @@ receive_packets (struct grub_net_card *card) if (!nb) { grub_print_error (); + card->last_poll = grub_get_time_ms (); return; } @@ -775,6 +776,7 @@ receive_packets (struct grub_net_card *card) if (actual < 0) { grub_netbuff_free (nb); + card->last_poll = grub_get_time_ms (); break; } grub_net_recv_ethernet_packet (nb, card); @@ -800,7 +802,13 @@ grub_net_poll_cards_idle_real (void) { struct grub_net_card *card; FOR_NET_CARDS (card) - receive_packets (card); + { + grub_uint64_t ctime = grub_get_time_ms (); + + if (ctime < card->last_poll + || ctime >= card->last_poll + card->idle_poll_delay_ms) + receive_packets (card); + } } /* Read from the packets list*/ diff --git a/include/grub/net.h b/include/grub/net.h index 92e637d89..45d08f3f5 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -95,6 +95,8 @@ struct grub_net_card grub_net_card_flags_t flags; int num_ifaces; int opened; + unsigned idle_poll_delay_ms; + grub_uint64_t last_poll; union { #ifdef GRUB_MACHINE_EFI From 697ffdc55b6fcb150e19ad5f746142edbcf5e372 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 18:21:24 +0200 Subject: [PATCH 405/406] Fix a memory leak --- grub-core/net/net.c | 1 + 1 file changed, 1 insertion(+) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 641aebd64..0f8a60413 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -725,6 +725,7 @@ grub_net_fs_open (struct grub_file *file_out, const char *name) } grub_memcpy (file_out, bufio, sizeof (struct grub_file)); + grub_free (bufio); return GRUB_ERR_NONE; } From 1c358e5948c43ac7684c2067c9aa035dd3493778 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 22:15:58 +0200 Subject: [PATCH 406/406] * po/POTFILES.in: Regenerate. --- ChangeLog | 4 + po/POTFILES.in | 342 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 328 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 110a980f0..e6aace254 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-07-06 Vladimir Serbinenko + + * po/POTFILES.in: Regenerate. + 2011-07-06 Vladimir Serbinenko Unify sparc init with other ieee1275. diff --git a/po/POTFILES.in b/po/POTFILES.in index 8329fdf0a..2bf4aa10c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,5 +1,22 @@ -# List of files which contain translatable strings. +grub-core/boot/decompressor/minilib.c +grub-core/boot/decompressor/none.c +grub-core/boot/decompressor/xz.c +grub-core/bus/bonito.c +grub-core/bus/cs5536.c +grub-core/bus/emu/pci.c +grub-core/bus/pci.c +grub-core/bus/usb/emu/usb.c +grub-core/bus/usb/ohci.c +grub-core/bus/usb/serial/common.c +grub-core/bus/usb/serial/ftdi.c +grub-core/bus/usb/serial/pl2303.c +grub-core/bus/usb/uhci.c +grub-core/bus/usb/usb.c +grub-core/bus/usb/usbhub.c +grub-core/bus/usb/usbtrans.c grub-core/commands/acpi.c +grub-core/commands/acpihalt.c +grub-core/commands/arc/lsdev.c grub-core/commands/blocklist.c grub-core/commands/boot.c grub-core/commands/cat.c @@ -7,33 +24,41 @@ grub-core/commands/cmp.c grub-core/commands/configfile.c grub-core/commands/date.c grub-core/commands/echo.c +grub-core/commands/efi/acpi.c grub-core/commands/efi/fixvideo.c grub-core/commands/efi/loadbios.c +grub-core/commands/efi/lsefimmap.c +grub-core/commands/efi/lsefisystab.c +grub-core/commands/efi/lssal.c +grub-core/commands/extcmd.c grub-core/commands/gptsync.c grub-core/commands/halt.c grub-core/commands/hashsum.c grub-core/commands/hdparm.c grub-core/commands/help.c grub-core/commands/hexdump.c +grub-core/commands/i386/cmostest.c grub-core/commands/i386/cpuid.c +grub-core/commands/i386/pc/acpi.c grub-core/commands/i386/pc/drivemap.c grub-core/commands/i386/pc/halt.c grub-core/commands/i386/pc/lsapm.c grub-core/commands/i386/pc/play.c -grub-core/commands/i386/pc/pxecmd.c +grub-core/commands/i386/pc/sendkey.c grub-core/commands/ieee1275/suspend.c grub-core/commands/iorw.c grub-core/commands/keylayouts.c grub-core/commands/keystatus.c grub-core/commands/legacycfg.c grub-core/commands/loadenv.c -grub-core/commands/ls.c grub-core/commands/lsacpi.c +grub-core/commands/ls.c grub-core/commands/lsmmap.c grub-core/commands/lspci.c grub-core/commands/memrw.c grub-core/commands/menuentry.c grub-core/commands/minicmd.c +grub-core/commands/mips/loongson/lsspd.c grub-core/commands/parttool.c grub-core/commands/password.c grub-core/commands/password_pbkdf2.c @@ -51,67 +76,348 @@ grub-core/commands/sleep.c grub-core/commands/terminal.c grub-core/commands/test.c grub-core/commands/testload.c +grub-core/commands/time.c grub-core/commands/true.c grub-core/commands/usbtest.c grub-core/commands/videoinfo.c grub-core/commands/videotest.c +grub-core/commands/wildcard.c grub-core/commands/xnu_uuid.c - +grub-core/disk/ahci.c +grub-core/disk/arc/arcdisk.c +grub-core/disk/ata.c +grub-core/disk/dmraid_nvidia.c +grub-core/disk/efi/efidisk.c +grub-core/disk/host.c +grub-core/disk/i386/pc/biosdisk.c +grub-core/disk/ieee1275/nand.c +grub-core/disk/ieee1275/ofdisk.c grub-core/disk/loopback.c - +grub-core/disk/lvm.c +grub-core/disk/mdraid1x_linux.c +grub-core/disk/mdraid_linux.c +grub-core/disk/memdisk.c +grub-core/disk/pata.c +grub-core/disk/raid5_recover.c +grub-core/disk/raid6_recover.c +grub-core/disk/raid.c +grub-core/disk/scsi.c +grub-core/disk/usbms.c +grub-core/efiemu/i386/coredetect.c +grub-core/efiemu/i386/loadcore32.c +grub-core/efiemu/i386/loadcore64.c +grub-core/efiemu/i386/nocfgtables.c +grub-core/efiemu/i386/pc/cfgtables.c +grub-core/efiemu/loadcore32.c +grub-core/efiemu/loadcore64.c +grub-core/efiemu/loadcore.c +grub-core/efiemu/loadcore_common.c grub-core/efiemu/main.c - +grub-core/efiemu/mm.c +grub-core/efiemu/pnvram.c +grub-core/efiemu/prepare32.c +grub-core/efiemu/prepare64.c +grub-core/efiemu/prepare.c +grub-core/efiemu/runtime/efiemu.c +grub-core/efiemu/symbols.c +grub-core/font/font.c grub-core/font/font_cmd.c - +grub-core/fs/affs.c +grub-core/fs/afs_be.c +grub-core/fs/afs.c +grub-core/fs/befs_be.c +grub-core/fs/befs.c +grub-core/fs/btrfs.c +grub-core/fs/cpio.c +grub-core/fs/ext2.c +grub-core/fs/fat.c +grub-core/fs/fshelp.c +grub-core/fs/hfs.c +grub-core/fs/hfsplus.c +grub-core/fs/iso9660.c +grub-core/fs/jfs.c +grub-core/fs/minix2.c +grub-core/fs/minix3.c +grub-core/fs/minix.c +grub-core/fs/nilfs2.c +grub-core/fs/ntfs.c +grub-core/fs/ntfscomp.c +grub-core/fs/reiserfs.c +grub-core/fs/romfs.c +grub-core/fs/sfs.c +grub-core/fs/squash4.c +grub-core/fs/tar.c +grub-core/fs/udf.c +grub-core/fs/ufs2.c +grub-core/fs/ufs.c +grub-core/fs/xfs.c +grub-core/fs/zfs/zfs.c +grub-core/fs/zfs/zfs_fletcher.c +grub-core/fs/zfs/zfsinfo.c +grub-core/fs/zfs/zfs_lzjb.c +grub-core/fs/zfs/zfs_sha256.c +grub-core/gentrigtables.c grub-core/gettext/gettext.c - +grub-core/gfxmenu/font.c +grub-core/gfxmenu/gfxmenu.c +grub-core/gfxmenu/gui_box.c +grub-core/gfxmenu/gui_canvas.c +grub-core/gfxmenu/gui_circular_progress.c +grub-core/gfxmenu/gui_image.c +grub-core/gfxmenu/gui_label.c +grub-core/gfxmenu/gui_list.c grub-core/gfxmenu/gui_progress_bar.c - +grub-core/gfxmenu/gui_string_util.c +grub-core/gfxmenu/gui_util.c +grub-core/gfxmenu/icon_manager.c +grub-core/gfxmenu/model.c +grub-core/gfxmenu/theme_loader.c +grub-core/gfxmenu/view.c +grub-core/gfxmenu/widget-box.c grub-core/hello/hello.c - +grub-core/hook/datehook.c +grub-core/io/bufio.c +grub-core/io/gzio.c +grub-core/io/xzio.c +grub-core/kern/command.c grub-core/kern/corecmd.c +grub-core/kern/device.c +grub-core/kern/disk.c +grub-core/kern/dl.c +grub-core/kern/efi/efi.c +grub-core/kern/efi/init.c +grub-core/kern/efi/mm.c +grub-core/kern/elf.c +grub-core/kern/emu/cache.c +grub-core/kern/emu/console.c +grub-core/kern/emu/full.c +grub-core/kern/emu/getroot.c grub-core/kern/emu/hostdisk.c +grub-core/kern/emu/hostfs.c +grub-core/kern/emu/lite.c +grub-core/kern/emu/main.c grub-core/kern/emu/misc.c +grub-core/kern/emu/mm.c +grub-core/kern/emu/time.c +grub-core/kern/env.c grub-core/kern/err.c - +grub-core/kern/file.c +grub-core/kern/fs.c +grub-core/kern/generic/millisleep.c +grub-core/kern/generic/rtc_get_time_ms.c +grub-core/kern/i386/coreboot/init.c +grub-core/kern/i386/coreboot/mmap.c +grub-core/kern/i386/dl.c +grub-core/kern/i386/efi/init.c +grub-core/kern/i386/multiboot_mmap.c +grub-core/kern/i386/pc/init.c +grub-core/kern/i386/pc/mmap.c +grub-core/kern/i386/pit.c +grub-core/kern/i386/qemu/mmap.c +grub-core/kern/i386/tsc.c +grub-core/kern/ia64/dl.c +grub-core/kern/ia64/dl_helper.c +grub-core/kern/ia64/efi/init.c +grub-core/kern/ieee1275/cmain.c +grub-core/kern/ieee1275/ieee1275.c +grub-core/kern/ieee1275/init.c +grub-core/kern/ieee1275/mmap.c +grub-core/kern/ieee1275/openfw.c +grub-core/kern/list.c +grub-core/kern/main.c +grub-core/kern/mips/arc/init.c +grub-core/kern/mips/dl.c +grub-core/kern/mips/init.c +grub-core/kern/mips/loongson/init.c +grub-core/kern/mips/qemu_mips/init.c +grub-core/kern/misc.c +grub-core/kern/mm.c +grub-core/kern/parser.c +grub-core/kern/partition.c +grub-core/kern/powerpc/dl.c +grub-core/kern/rescue_parser.c +grub-core/kern/rescue_reader.c +grub-core/kern/sparc64/dl.c +grub-core/kern/sparc64/ieee1275/ieee1275.c +grub-core/kern/term.c +grub-core/kern/time.c +grub-core/kern/vga_init.c +grub-core/kern/x86_64/dl.c +grub-core/lib/arc/datetime.c grub-core/lib/arg.c - +grub-core/lib/cmdline.c +grub-core/lib/cmos_datetime.c +grub-core/lib/crc.c +grub-core/lib/crypto.c +grub-core/lib/efi/datetime.c +grub-core/lib/efi/halt.c +grub-core/lib/efi/relocator.c +grub-core/lib/emu/halt.c +grub-core/lib/envblk.c +grub-core/lib/hexdump.c +grub-core/lib/i386/halt.c +grub-core/lib/i386/pc/biosnum.c +grub-core/lib/i386/pc/vesa_modes_table.c +grub-core/lib/i386/relocator.c +grub-core/lib/ieee1275/cmos.c +grub-core/lib/ieee1275/datetime.c +grub-core/lib/ieee1275/halt.c +grub-core/lib/ieee1275/relocator.c +grub-core/lib/legacy_parse.c +grub-core/lib/LzFind.c +grub-core/lib/LzmaDec.c +grub-core/lib/LzmaEnc.c +grub-core/lib/mips/relocator.c +grub-core/lib/pbkdf2.c +grub-core/lib/powerpc/relocator.c +grub-core/lib/reed_solomon.c +grub-core/lib/relocator.c +grub-core/lib/xzembed/xz_dec_bcj.c +grub-core/lib/xzembed/xz_dec_lzma2.c +grub-core/lib/xzembed/xz_dec_stream.c +grub-core/loader/aout.c grub-core/loader/efi/appleloader.c grub-core/loader/efi/chainloader.c +grub-core/loader/i386/bsd32.c +grub-core/loader/i386/bsd64.c grub-core/loader/i386/bsd.c +grub-core/loader/i386/bsd_pagetable.c +grub-core/loader/i386/bsdXX.c +grub-core/loader/i386/coreboot/chainloader.c grub-core/loader/i386/linux.c +grub-core/loader/i386/multiboot_mbi.c grub-core/loader/i386/pc/chainloader.c +grub-core/loader/i386/pc/freedos.c grub-core/loader/i386/pc/linux.c grub-core/loader/i386/pc/ntldr.c grub-core/loader/i386/xnu.c +grub-core/loader/ia64/efi/linux.c +grub-core/loader/macho32.c +grub-core/loader/macho64.c +grub-core/loader/macho.c +grub-core/loader/machoXX.c grub-core/loader/mips/linux.c grub-core/loader/multiboot.c +grub-core/loader/multiboot_elfxx.c +grub-core/loader/multiboot_mbi2.c grub-core/loader/powerpc/ieee1275/linux.c grub-core/loader/sparc64/ieee1275/linux.c grub-core/loader/xnu.c - +grub-core/loader/xnu_resume.c +grub-core/mmap/efi/mmap.c +grub-core/mmap/i386/mmap.c +grub-core/mmap/i386/pc/mmap.c +grub-core/mmap/i386/uppermem.c +grub-core/mmap/mips/uppermem.c grub-core/mmap/mmap.c - +grub-core/net/arp.c +grub-core/net/bootp.c +grub-core/net/drivers/efi/efinet.c +grub-core/net/drivers/emu/emunet.c +grub-core/net/drivers/i386/pc/pxe.c +grub-core/net/drivers/ieee1275/ofnet.c +grub-core/net/ethernet.c +grub-core/net/ip.c +grub-core/net/netbuff.c +grub-core/net/net.c +grub-core/net/tftp.c +grub-core/net/udp.c grub-core/normal/auth.c +grub-core/normal/autofs.c +grub-core/normal/charset.c grub-core/normal/cmdline.c grub-core/normal/color.c +grub-core/normal/completion.c grub-core/normal/context.c +grub-core/normal/crypto.c +grub-core/normal/datetime.c grub-core/normal/dyncmd.c grub-core/normal/main.c grub-core/normal/menu.c grub-core/normal/menu_entry.c grub-core/normal/menu_text.c grub-core/normal/misc.c - +grub-core/normal/term.c +grub-core/partmap/acorn.c +grub-core/partmap/amiga.c +grub-core/partmap/apple.c +grub-core/partmap/bsdlabel.c +grub-core/partmap/dvh.c +grub-core/partmap/gpt.c +grub-core/partmap/msdos.c +grub-core/partmap/sun.c +grub-core/partmap/sunpc.c +grub-core/parttool/msdospart.c +grub-core/script/argv.c +grub-core/script/execute.c +grub-core/script/function.c +grub-core/script/lexer.c grub-core/script/main.c - +grub-core/script/script.c +grub-core/term/arc/console.c +grub-core/term/at_keyboard.c +grub-core/term/efi/console.c grub-core/term/gfxterm.c +grub-core/term/i386/pc/console.c +grub-core/term/i386/pc/vga_text.c +grub-core/term/i386/vga_common.c +grub-core/term/ieee1275/ofconsole.c +grub-core/term/ns8250.c grub-core/term/serial.c grub-core/term/terminfo.c - +grub-core/term/tparm.c +grub-core/term/usb_keyboard.c +grub-core/tests/example_functional_test.c +grub-core/tests/lib/functional_test.c +grub-core/tests/lib/test.c grub-core/tests/test_blockarg.c - +grub-core/video/bitmap.c +grub-core/video/bitmap_scale.c +grub-core/video/bochs.c +grub-core/video/cirrus.c +grub-core/video/colors.c +grub-core/video/efi_gop.c +grub-core/video/efi_uga.c +grub-core/video/emu/sdl.c +grub-core/video/fb/fbblit.c +grub-core/video/fb/fbfill.c +grub-core/video/fb/fbutil.c +grub-core/video/fb/video_fb.c +grub-core/video/i386/pc/vbe.c +grub-core/video/i386/pc/vga.c +grub-core/video/ieee1275.c +grub-core/video/readers/jpeg.c +grub-core/video/readers/png.c +grub-core/video/readers/tga.c +grub-core/video/sis315_init.c +grub-core/video/sis315pro.c +grub-core/video/sm712.c +grub-core/video/sm712_init.c +grub-core/video/video.c +tests/example_unit_test.c +tests/lib/unit_test.c +util/bin2h.c +util/deviceiter.c +util/devicemap.c util/grub-editenv.c util/grub-fstest.c +util/grub-macho2img.c +util/grub-menulst2cfg.c +util/grub-mkdevicemap.c +util/grub-mkfont.c util/grub-mkimage.c +util/grub-mkimagexx.c +util/grub-mklayout.c +util/grub-mkpasswd-pbkdf2.c +util/grub-mkrelpath.c +util/grub-pe2elf.c +util/grub-probe.c +util/grub-script-check.c util/grub-setup.c +util/ieee1275/devicemap.c +util/ieee1275/grub-ofpathname.c +util/ieee1275/ofpath.c +util/lvm.c +util/misc.c +util/raid.c +util/resolve.c