From 8231fb77c63188c47b00107ab576a41c1ef81f9e Mon Sep 17 00:00:00 2001 From: robertmh Date: Sat, 27 Jun 2009 11:18:10 +0000 Subject: [PATCH] 2009-06-27 Pavel Roskin 2009-06-27 Robert Millan * include/grub/dl.h: Include grub/elf.h. (struct grub_dl): Add symtab field. * kern/dl.c [GRUB_MACHINE_QEMU]: Define GRUB_MODULES_MACHINE_READONLY. (grub_dl_resolve_symbols): Populate mod->symtab, making a copy of the header for read-only modules. (grub_dl_unload): Free mod->symtab for read-only modules. * kern/i386/dl.c: Use mod->symtab. * kern/powerpc/dl.c: Likewise. * kern/sparc64/dl.c: Likewise. * kern/x86_64/dl.c: Likewise. * conf/i386-qemu.rmk: New file. * kern/i386/qemu/startup.S: Likewise. * kern/i386/qemu/mmap.c: Likewise. * boot/i386/qemu/boot.S: Likewise. * include/grub/i386/qemu/time.h: Likewise. * include/grub/i386/qemu/serial.h: Likewise. * include/grub/i386/qemu/kernel.h: Likewise. * include/grub/i386/qemu/console.h: Likewise. * include/grub/i386/qemu/boot.h: Likewise. * include/grub/i386/qemu/init.h: Likewise. * include/grub/i386/qemu/machine.h: Likewise. * include/grub/i386/qemu/loader.h: Likewise. * include/grub/i386/qemu/memory.h: Likewise. * conf/i386-coreboot.rmk (GRUB_BOOT_MACHINE_LINK_ADDR) (GRUB_KERNEL_MACHINE_LINK_ADDR): New variables. [qemu] (pkglib_IMAGES): Add `boot.img'. [qemu] (boot_img_SOURCES, boot_img_ASFLAGS, boot_img_LDFLAGS) [qemu] (boot_img_FORMAT): New variables. [qemu] (bin_UTILITIES): Add `grub-mkimage'. [qemu] (grub_mkimage_SOURCES, grub_mkimage_CFLAGS): New variables. [qemu] (kernel_img_SOURCES, kernel_img_HEADERS, kernel_img_CFLAGS) [qemu] (kernel_img_ASFLAGS, kernel_img_LDFLAGS) [qemu] (kernel_img_FORMAT): New variables. * configure.ac: Recognise `i386-qemu'. * util/i386/pc/grub-mkimage.c (compress_kernel): Add dummy variant (for no compression). [GRUB_MACHINE_QEMU] (generate_image): Misc adjustments to produce a valid i386 ROM image. Make `GRUB_KERNEL_MACHINE_COMPRESSED_SIZE', `GRUB_KERNEL_MACHINE_INSTALL_DOS_PART' and `GRUB_KERNEL_MACHINE_INSTALL_BSD_PART' optional features (with ifdefs). --- ChangeLog | 50 ++++++++++++++++ boot/i386/qemu/boot.S | 67 ++++++++++++++++++++++ conf/i386-coreboot.rmk | 54 +++++++++++++++++- conf/i386-qemu.rmk | 2 + configure.ac | 1 + include/grub/dl.h | 4 +- include/grub/i386/qemu/boot.h | 28 +++++++++ include/grub/i386/qemu/console.h | 1 + include/grub/i386/qemu/init.h | 1 + include/grub/i386/qemu/kernel.h | 53 +++++++++++++++++ include/grub/i386/qemu/loader.h | 1 + include/grub/i386/qemu/machine.h | 24 ++++++++ include/grub/i386/qemu/memory.h | 45 +++++++++++++++ include/grub/i386/qemu/serial.h | 1 + include/grub/i386/qemu/time.h | 1 + kern/dl.c | 19 ++++++- kern/i386/coreboot/init.c | 7 ++- kern/i386/dl.c | 4 +- kern/i386/qemu/mmap.c | 74 ++++++++++++++++++++++++ kern/i386/qemu/startup.S | 97 ++++++++++++++++++++++++++++++++ kern/powerpc/dl.c | 4 +- kern/sparc64/dl.c | 4 +- kern/x86_64/dl.c | 4 +- util/i386/pc/grub-mkimage.c | 57 +++++++++++++++++++ 24 files changed, 584 insertions(+), 19 deletions(-) create mode 100644 boot/i386/qemu/boot.S create mode 100644 conf/i386-qemu.rmk create mode 100644 include/grub/i386/qemu/boot.h create mode 100644 include/grub/i386/qemu/console.h create mode 100644 include/grub/i386/qemu/init.h create mode 100644 include/grub/i386/qemu/kernel.h create mode 100644 include/grub/i386/qemu/loader.h create mode 100644 include/grub/i386/qemu/machine.h create mode 100644 include/grub/i386/qemu/memory.h create mode 100644 include/grub/i386/qemu/serial.h create mode 100644 include/grub/i386/qemu/time.h create mode 100644 kern/i386/qemu/mmap.c create mode 100644 kern/i386/qemu/startup.S diff --git a/ChangeLog b/ChangeLog index 0cab9cd94..5bd20acd2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,53 @@ +2009-06-27 Pavel Roskin +2009-06-27 Robert Millan + + * include/grub/dl.h: Include grub/elf.h. + (struct grub_dl): Add symtab field. + * kern/dl.c [GRUB_MACHINE_QEMU]: Define + GRUB_MODULES_MACHINE_READONLY. + (grub_dl_resolve_symbols): Populate mod->symtab, making a copy + of the header for read-only modules. + (grub_dl_unload): Free mod->symtab for read-only modules. + * kern/i386/dl.c: Use mod->symtab. + * kern/powerpc/dl.c: Likewise. + * kern/sparc64/dl.c: Likewise. + * kern/x86_64/dl.c: Likewise. + + * conf/i386-qemu.rmk: New file. + * kern/i386/qemu/startup.S: Likewise. + * kern/i386/qemu/mmap.c: Likewise. + * boot/i386/qemu/boot.S: Likewise. + * include/grub/i386/qemu/time.h: Likewise. + * include/grub/i386/qemu/serial.h: Likewise. + * include/grub/i386/qemu/kernel.h: Likewise. + * include/grub/i386/qemu/console.h: Likewise. + * include/grub/i386/qemu/boot.h: Likewise. + * include/grub/i386/qemu/init.h: Likewise. + * include/grub/i386/qemu/machine.h: Likewise. + * include/grub/i386/qemu/loader.h: Likewise. + * include/grub/i386/qemu/memory.h: Likewise. + + * conf/i386-coreboot.rmk (GRUB_BOOT_MACHINE_LINK_ADDR) + (GRUB_KERNEL_MACHINE_LINK_ADDR): New variables. + [qemu] (pkglib_IMAGES): Add `boot.img'. + [qemu] (boot_img_SOURCES, boot_img_ASFLAGS, boot_img_LDFLAGS) + [qemu] (boot_img_FORMAT): New variables. + [qemu] (bin_UTILITIES): Add `grub-mkimage'. + [qemu] (grub_mkimage_SOURCES, grub_mkimage_CFLAGS): New variables. + [qemu] (kernel_img_SOURCES, kernel_img_HEADERS, kernel_img_CFLAGS) + [qemu] (kernel_img_ASFLAGS, kernel_img_LDFLAGS) + [qemu] (kernel_img_FORMAT): New variables. + + * configure.ac: Recognise `i386-qemu'. + + * util/i386/pc/grub-mkimage.c (compress_kernel): Add dummy variant + (for no compression). + [GRUB_MACHINE_QEMU] (generate_image): Misc adjustments to produce + a valid i386 ROM image. Make `GRUB_KERNEL_MACHINE_COMPRESSED_SIZE', + `GRUB_KERNEL_MACHINE_INSTALL_DOS_PART' and + `GRUB_KERNEL_MACHINE_INSTALL_BSD_PART' optional features (with + ifdefs). + 2009-06-27 Pavel Roskin * efiemu/prepare.c: Eliminate TYPE macro, it makes code hard to diff --git a/boot/i386/qemu/boot.S b/boot/i386/qemu/boot.S new file mode 100644 index 000000000..a93fe3943 --- /dev/null +++ b/boot/i386/qemu/boot.S @@ -0,0 +1,67 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,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 . + */ + +#include +#include +#include +#include +#include + + .text + .code16 + .globl _start +_start: + /* Disable interrupts. */ + cli + + jmp 1f + + . = _start + GRUB_BOOT_MACHINE_CORE_ENTRY_ADDR +VARIABLE(grub_core_entry_addr) + .long 0 +1: + + /* Process VGA rom. */ + call $0xc000, $0x3 + + /* Set up %ds, %ss, and %es. */ + xorw %ax, %ax + movw %ax, %ds + movw %ax, %ss + movw %ax, %es + + /* Set up the real mode stack. */ + movl $GRUB_MEMORY_MACHINE_REAL_STACK, %esp + + /* Transition to protected mode. We use pushl to force generation + of a flat return address. */ + pushl $1f + DATA32 jmp real_to_prot + .code32 +1: + movl grub_core_entry_addr, %edx + jmp *%edx + +#include "../../../kern/i386/realmode.S" + + /* Intel, in its infinite wisdom, decided to put the i8086 entry point + *right here* and this is why we need this kludge. */ + + . = GRUB_BOOT_MACHINE_SIZE - 16 + jmp _start + . = GRUB_BOOT_MACHINE_SIZE diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk index a76f42507..119e116da 100644 --- a/conf/i386-coreboot.rmk +++ b/conf/i386-coreboot.rmk @@ -8,9 +8,12 @@ COMMON_LDFLAGS = -m32 -nostdlib script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. -pkglib_PROGRAMS = kernel.img -# For kernel.img. +GRUB_KERNEL_MACHINE_LINK_ADDR = 0x8200 + +ifeq ($(platform), coreboot) + +pkglib_PROGRAMS += kernel.img kernel_img_SOURCES = kern/i386/coreboot/startup.S \ kern/i386/misc.S \ kern/i386/coreboot/init.c \ @@ -34,7 +37,52 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ machine/memory.h machine/loader.h list.h handler.h command.h kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) -kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x8200,-Bstatic +kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,$(GRUB_KERNEL_MACHINE_LINK_ADDR),-Bstatic + +endif + +ifeq ($(platform), qemu) + +GRUB_BOOT_MACHINE_LINK_ADDR = 0xffe00 + +pkglib_IMAGES += boot.img +boot_img_SOURCES = boot/i386/qemu/boot.S +boot_img_ASFLAGS = $(COMMON_ASFLAGS) -DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR) +boot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)$(GRUB_BOOT_MACHINE_LINK_ADDR) +boot_img_FORMAT = binary + +bin_UTILITIES += grub-mkimage +grub_mkimage_SOURCES = util/i386/pc/grub-mkimage.c util/misc.c \ + util/resolve.c +grub_mkimage_CFLAGS = -DGRUB_KERNEL_MACHINE_LINK_ADDR=$(GRUB_KERNEL_MACHINE_LINK_ADDR) + +pkglib_IMAGES += kernel.img +kernel_img_SOURCES = kern/i386/qemu/startup.S \ + kern/i386/misc.S \ + kern/i386/coreboot/init.c \ + kern/i386/qemu/mmap.c \ + 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/reader.c kern/term.c \ + kern/rescue_parser.c kern/rescue_reader.c \ + kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ + kern/i386/dl.c kern/parser.c kern/partition.c \ + kern/i386/tsc.c kern/i386/pit.c \ + kern/generic/rtc_get_time_ms.c \ + kern/generic/millisleep.c \ + kern/env.c \ + term/i386/pc/vga_text.c term/i386/vga_common.c \ + symlist.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 pc_partition.h reader.h symbol.h term.h time.h types.h \ + machine/boot.h machine/console.h machine/init.h \ + machine/memory.h machine/loader.h list.h handler.h command.h +kernel_img_CFLAGS = $(COMMON_CFLAGS) -DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR) +kernel_img_ASFLAGS = $(COMMON_ASFLAGS) -DGRUB_KERNEL_MACHINE_LINK_ADDR=$(GRUB_KERNEL_MACHINE_LINK_ADDR) +kernel_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)$(GRUB_KERNEL_MACHINE_LINK_ADDR) +kernel_img_FORMAT = binary +endif MOSTLYCLEANFILES += symlist.c kernel_syms.lst DEFSYMFILES += kernel_syms.lst diff --git a/conf/i386-qemu.rmk b/conf/i386-qemu.rmk new file mode 100644 index 000000000..573a5d0f3 --- /dev/null +++ b/conf/i386-qemu.rmk @@ -0,0 +1,2 @@ +# -*- makefile -*- +include $(srcdir)/conf/i386-coreboot.mk diff --git a/configure.ac b/configure.ac index 9032ee3f0..cf1b197a5 100644 --- a/configure.ac +++ b/configure.ac @@ -85,6 +85,7 @@ case "$target_cpu"-"$platform" in i386-coreboot) ;; i386-linuxbios) platform=coreboot ;; i386-ieee1275) ;; + i386-qemu) ;; powerpc-ieee1275) ;; sparc64-ieee1275) ;; *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;; diff --git a/include/grub/dl.h b/include/grub/dl.h index 894da1d33..bebb810a8 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -1,7 +1,7 @@ /* dl.h - types and prototypes for loadable module support */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2004,2005,2007,2008 Free Software Foundation, Inc. + * Copyright (C) 2002,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 @@ -23,6 +23,7 @@ #include #include #include +#include #define GRUB_MOD_INIT(name) \ static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \ @@ -78,6 +79,7 @@ struct grub_dl int ref_count; grub_dl_dep_t dep; grub_dl_segment_t segment; + Elf_Sym *symtab; void (*init) (struct grub_dl *mod); void (*fini) (void); }; diff --git a/include/grub/i386/qemu/boot.h b/include/grub/i386/qemu/boot.h new file mode 100644 index 000000000..6fbb57750 --- /dev/null +++ b/include/grub/i386/qemu/boot.h @@ -0,0 +1,28 @@ +/* + * 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_BOOT_MACHINE_HEADER +#define GRUB_BOOT_MACHINE_HEADER 1 + +/* The size of boot.img. */ +#define GRUB_BOOT_MACHINE_SIZE (0x100000 - GRUB_BOOT_MACHINE_LINK_ADDR) + +/* The offset of GRUB_CORE_ENTRY_ADDR. */ +#define GRUB_BOOT_MACHINE_CORE_ENTRY_ADDR 0x4 + +#endif diff --git a/include/grub/i386/qemu/console.h b/include/grub/i386/qemu/console.h new file mode 100644 index 000000000..774399a4e --- /dev/null +++ b/include/grub/i386/qemu/console.h @@ -0,0 +1 @@ +#include diff --git a/include/grub/i386/qemu/init.h b/include/grub/i386/qemu/init.h new file mode 100644 index 000000000..fd935c3a2 --- /dev/null +++ b/include/grub/i386/qemu/init.h @@ -0,0 +1 @@ +#include diff --git a/include/grub/i386/qemu/kernel.h b/include/grub/i386/qemu/kernel.h new file mode 100644 index 000000000..bc0b93d4f --- /dev/null +++ b/include/grub/i386/qemu/kernel.h @@ -0,0 +1,53 @@ +/* + * 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 + +/* The offset of GRUB_CORE_ENTRY_ADDR. */ +#define GRUB_KERNEL_MACHINE_CORE_ENTRY_ADDR 0x8 + +/* The offset of GRUB_KERNEL_IMAGE_SIZE. */ +#define GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE 0xc + +/* The offset of GRUB_PREFIX. */ +#define GRUB_KERNEL_MACHINE_PREFIX 0x10 + +/* End of the data section. */ +#define GRUB_KERNEL_MACHINE_DATA_END 0x50 + +#ifndef ASM_FILE + +#include +#include + +extern grub_addr_t grub_core_entry_addr; + +/* The size of kernel image. */ +extern grub_int32_t grub_kernel_image_size; + +/* The total size of module images following the kernel. */ +extern grub_int32_t grub_total_module_size; + +/* The prefix which points to the directory where GRUB modules and its + configuration file are located. */ +extern char grub_prefix[]; + +#endif /* ! ASM_FILE */ + +#endif /* ! GRUB_KERNEL_MACHINE_HEADER */ diff --git a/include/grub/i386/qemu/loader.h b/include/grub/i386/qemu/loader.h new file mode 100644 index 000000000..d3f36bba5 --- /dev/null +++ b/include/grub/i386/qemu/loader.h @@ -0,0 +1 @@ +#include diff --git a/include/grub/i386/qemu/machine.h b/include/grub/i386/qemu/machine.h new file mode 100644 index 000000000..b57932b49 --- /dev/null +++ b/include/grub/i386/qemu/machine.h @@ -0,0 +1,24 @@ +/* + * 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_MACHINE_MACHINE_HEADER +#define GRUB_MACHINE_MACHINE_HEADER 1 + +#define GRUB_MACHINE_QEMU 1 + +#endif /* ! GRUB_MACHINE_MACHINE_HEADER */ diff --git a/include/grub/i386/qemu/memory.h b/include/grub/i386/qemu/memory.h new file mode 100644 index 000000000..de559443d --- /dev/null +++ b/include/grub/i386/qemu/memory.h @@ -0,0 +1,45 @@ +/* memory.h - describe the memory map */ +/* + * 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_MEMORY_MACHINE_HEADER +#define _GRUB_MEMORY_MACHINE_HEADER 1 + +#include +#include + +#ifndef ASM_FILE +#include +#include +#endif + +#define GRUB_MEMORY_MACHINE_LOWER_USABLE 0x9fc00 /* 640 kiB - 1 kiB */ + +#define GRUB_MEMORY_MACHINE_UPPER_START 0x100000 /* 1 MiB */ +#define GRUB_MEMORY_MACHINE_LOWER_SIZE GRUB_MEMORY_MACHINE_UPPER_START + +#ifndef ASM_FILE + +void grub_machine_mmap_init (void); + +grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) + (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); + +#endif + +#endif /* ! _GRUB_MEMORY_MACHINE_HEADER */ diff --git a/include/grub/i386/qemu/serial.h b/include/grub/i386/qemu/serial.h new file mode 100644 index 000000000..2d8563414 --- /dev/null +++ b/include/grub/i386/qemu/serial.h @@ -0,0 +1 @@ +#include diff --git a/include/grub/i386/qemu/time.h b/include/grub/i386/qemu/time.h new file mode 100644 index 000000000..7177c7488 --- /dev/null +++ b/include/grub/i386/qemu/time.h @@ -0,0 +1 @@ +#include diff --git a/kern/dl.c b/kern/dl.c index cd34e3178..af4e5aa89 100644 --- a/kern/dl.c +++ b/kern/dl.c @@ -1,7 +1,7 @@ /* dl.c - loadable module support */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2004,2005,2007,2008 Free Software Foundation, Inc. + * Copyright (C) 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 @@ -28,6 +28,12 @@ #include #include #include +#include + +/* Platforms where modules are in a readonly area of memory. */ +#if defined(GRUB_MACHINE_QEMU) +#define GRUB_MODULES_MACHINE_READONLY +#endif @@ -309,7 +315,13 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) if (i == e->e_shnum) return grub_error (GRUB_ERR_BAD_MODULE, "no symbol table"); - sym = (Elf_Sym *) ((char *) e + s->sh_offset); +#ifdef GRUB_MODULES_MACHINE_READONLY + mod->symtab = grub_malloc (s->sh_size); + memcpy (mod->symtab, (char *) e + s->sh_offset, s->sh_size); +#else + mod->symtab = (Elf_Sym *) ((char *) e + s->sh_offset); +#endif + sym = mod->symtab; size = s->sh_size; entsize = s->sh_entsize; @@ -671,6 +683,9 @@ grub_dl_unload (grub_dl_t mod) } grub_free (mod->name); +#ifdef GRUB_MODULES_MACHINE_READONLY + grub_free (mod->symtab); +#endif grub_free (mod); return 1; } diff --git a/kern/i386/coreboot/init.c b/kern/i386/coreboot/init.c index 611e9d1b4..1b9ca3815 100644 --- a/kern/i386/coreboot/init.c +++ b/kern/i386/coreboot/init.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc. + * Copyright (C) 2002,2003,2004,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 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -144,5 +145,9 @@ grub_machine_fini (void) grub_addr_t grub_arch_modules_addr (void) { +#ifdef GRUB_MACHINE_QEMU + return grub_core_entry_addr + grub_kernel_image_size; +#else return ALIGN_UP((grub_addr_t) _end, GRUB_MOD_ALIGN); +#endif } diff --git a/kern/i386/dl.c b/kern/i386/dl.c index 978bfb166..a17f17576 100644 --- a/kern/i386/dl.c +++ b/kern/i386/dl.c @@ -43,7 +43,6 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) { Elf32_Ehdr *e = ehdr; Elf32_Shdr *s; - Elf32_Sym *symtab; Elf32_Word entsize; unsigned i; @@ -57,7 +56,6 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) if (i == e->e_shnum) return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found"); - symtab = (Elf32_Sym *) ((char *) e + s->sh_offset); entsize = s->sh_entsize; for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff); @@ -89,7 +87,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) "reloc offset is out of the segment"); addr = (Elf32_Word *) ((char *) seg->addr + rel->r_offset); - sym = (Elf32_Sym *) ((char *) symtab + sym = (Elf32_Sym *) ((char *) mod->symtab + entsize * ELF32_R_SYM (rel->r_info)); switch (ELF32_R_TYPE (rel->r_info)) diff --git a/kern/i386/qemu/mmap.c b/kern/i386/qemu/mmap.c new file mode 100644 index 000000000..736457eea --- /dev/null +++ b/kern/i386/qemu/mmap.c @@ -0,0 +1,74 @@ +/* + * 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 + +#define QEMU_CMOS_MEMSIZE_HIGH 0x35 +#define QEMU_CMOS_MEMSIZE_LOW 0x34 + +#define min(a,b) ((a) > (b) ? (b) : (a)) + +extern char _start[]; +extern char _end[]; + +grub_size_t grub_lower_mem, grub_upper_mem; +grub_uint64_t mem_size; + +void +grub_machine_mmap_init () +{ + mem_size = grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH) << 24 | grub_cmos_read (QEMU_CMOS_MEMSIZE_LOW) << 16; + + /* Don't ask... */ + mem_size += (16 * 1024 * 1024); +} + +grub_err_t +grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) +{ + if (hook (0x0, + _start, + GRUB_MACHINE_MEMORY_AVAILABLE)) + return 1; + + if (hook (GRUB_MEMORY_MACHINE_UPPER, + 0x100000 - GRUB_MEMORY_MACHINE_UPPER, + GRUB_MACHINE_MEMORY_RESERVED)) + return 1; + + /* Protect boot.img, which contains the gdt. It is mapped at the top of memory + (it is also mapped below 0x100000, but we already reserved that area). */ + if (hook ((grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE, + GRUB_BOOT_MACHINE_SIZE, + GRUB_MACHINE_MEMORY_RESERVED)) + return 1; + + /* Everything else is free. */ + if (hook (0x100000, + min (mem_size, (grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE) - 0x100000, + GRUB_MACHINE_MEMORY_AVAILABLE)) + return 1; + + return 0; +} diff --git a/kern/i386/qemu/startup.S b/kern/i386/qemu/startup.S new file mode 100644 index 000000000..0be5ae84f --- /dev/null +++ b/kern/i386/qemu/startup.S @@ -0,0 +1,97 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,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 . + */ + +#include +#include +#include +#include + + .text + .code32 + .globl _start +_start: + jmp codestart + + . = _start + GRUB_KERNEL_MACHINE_CORE_ENTRY_ADDR +VARIABLE(grub_core_entry_addr) + .long 0 +VARIABLE(grub_kernel_image_size) + .long 0 +VARIABLE(grub_prefix) + /* to be filled by grub-mkimage */ + + /* + * Leave some breathing room for the prefix. + */ + + . = _start + GRUB_KERNEL_MACHINE_DATA_END + +codestart: + /* Relocate to low memory. First we figure out our location. + We will derive the rom start address from it. */ + call 1f +1: popl %esi + + /* Rom size is a multiple of 64 kiB. With this we get the + value of `grub_core_entry_addr' in %esi. */ + xorw %si, %si + + /* ... which allows us to access `grub_kernel_image_size' + before relocation. */ + movl (grub_kernel_image_size - _start)(%esi), %ecx + + + movl $_start, %edi + cld + rep + movsb + ljmp $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $1f +1: + +#ifdef APPLE_CC + /* clean out the bss */ + bss_start_abs = ABS (bss_start) + bss_end_abs = ABS (bss_end) + + movl bss_start_abs, %edi + + /* compute the bss length */ + movl bss_end_abs, %ecx + subl %edi, %ecx +#else + /* clean out the bss */ + movl $BSS_START_SYMBOL, %edi + + /* compute the bss length */ + movl $END_SYMBOL, %ecx + subl %edi, %ecx +#endif + + /* clean out */ + xorl %eax, %eax + cld + rep + stosb + + /* + * Call the start of main body of C code. + */ + call EXT_C(grub_main) + + /* This should never happen. */ + jmp EXT_C(grub_stop) diff --git a/kern/powerpc/dl.c b/kern/powerpc/dl.c index ae987c087..9b1cb1407 100644 --- a/kern/powerpc/dl.c +++ b/kern/powerpc/dl.c @@ -44,7 +44,6 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) { Elf32_Ehdr *e = ehdr; Elf32_Shdr *s; - Elf32_Sym *symtab; Elf32_Word entsize; unsigned i; @@ -58,7 +57,6 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) if (i == e->e_shnum) return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found"); - symtab = (Elf32_Sym *) ((char *) e + s->sh_offset); entsize = s->sh_entsize; for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff); @@ -91,7 +89,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) "reloc offset is out of the segment"); addr = (Elf32_Word *) ((char *) seg->addr + rel->r_offset); - sym = (Elf32_Sym *) ((char *) symtab + sym = (Elf32_Sym *) ((char *) mod->symtab + entsize * ELF32_R_SYM (rel->r_info)); /* On the PPC the value does not have an explicit diff --git a/kern/sparc64/dl.c b/kern/sparc64/dl.c index d998dafe8..533489677 100644 --- a/kern/sparc64/dl.c +++ b/kern/sparc64/dl.c @@ -44,7 +44,6 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) { Elf64_Ehdr *e = ehdr; Elf64_Shdr *s; - Elf64_Sym *symtab; Elf64_Word entsize; unsigned i; @@ -58,7 +57,6 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) if (i == e->e_shnum) return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found"); - symtab = (Elf64_Sym *) ((char *) e + s->sh_offset); entsize = s->sh_entsize; for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff); @@ -91,7 +89,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) "reloc offset is out of the segment"); addr = (Elf64_Word *) ((char *) seg->addr + rel->r_offset); - sym = (Elf64_Sym *) ((char *) symtab + sym = (Elf64_Sym *) ((char *) mod->symtab + entsize * ELF64_R_SYM (rel->r_info)); value = sym->st_value + rel->r_addend; diff --git a/kern/x86_64/dl.c b/kern/x86_64/dl.c index a60690148..9e5de6e09 100644 --- a/kern/x86_64/dl.c +++ b/kern/x86_64/dl.c @@ -43,7 +43,6 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) { Elf64_Ehdr *e = ehdr; Elf64_Shdr *s; - Elf64_Sym *symtab; Elf64_Word entsize; unsigned i; @@ -57,7 +56,6 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) if (i == e->e_shnum) return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found"); - symtab = (Elf64_Sym *) ((char *) e + s->sh_offset); entsize = s->sh_entsize; for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff); @@ -91,7 +89,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) addr32 = (Elf64_Word *) ((char *) seg->addr + rel->r_offset); addr64 = (Elf64_Xword *) addr32; - sym = (Elf64_Sym *) ((char *) symtab + sym = (Elf64_Sym *) ((char *) mod->symtab + entsize * ELF64_R_SYM (rel->r_info)); switch (ELF64_R_TYPE (rel->r_info)) diff --git a/util/i386/pc/grub-mkimage.c b/util/i386/pc/grub-mkimage.c index f9c74cd16..ee1af822a 100644 --- a/util/i386/pc/grub-mkimage.c +++ b/util/i386/pc/grub-mkimage.c @@ -124,6 +124,17 @@ compress_kernel (char *kernel_img, size_t kernel_size, *core_size += GRUB_KERNEL_MACHINE_RAW_SIZE; } +#else + +static void +compress_kernel (char *kernel_img, size_t kernel_size, + char **core_img, size_t *core_size) +{ + *core_img = xmalloc (kernel_size); + memcpy (*core_img, kernel_img, kernel_size); + *core_size = kernel_size; +} + #endif static void @@ -237,6 +248,8 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], if (num > 0xffff) grub_util_error ("the core image is too big"); +#if defined(GRUB_MACHINE_PCBIOS) + boot_path = grub_util_get_path (dir, "diskboot.img"); boot_size = grub_util_get_image_size (boot_path); if (boot_size != GRUB_DISK_SECTOR_SIZE) @@ -253,13 +266,54 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], free (boot_img); free (boot_path); +#elif defined(GRUB_MACHINE_QEMU) + + { + char *rom_img; + size_t rom_size; + + boot_path = grub_util_get_path (dir, "boot.img"); + boot_size = grub_util_get_image_size (boot_path); + boot_img = grub_util_read_image (boot_path); + + /* Rom sizes must be 64k-aligned. */ + rom_size = ALIGN_UP (core_size + boot_size, 64 * 1024); + + rom_img = xmalloc (rom_size); + memset (rom_img, 0, rom_size); + + *((grub_int32_t *) (core_img + GRUB_KERNEL_MACHINE_CORE_ENTRY_ADDR)) + = grub_cpu_to_le32 ((grub_uint32_t) -rom_size); + + memcpy (rom_img, core_img, core_size); + + *((grub_int32_t *) (boot_img + GRUB_BOOT_MACHINE_CORE_ENTRY_ADDR)) + = grub_cpu_to_le32 ((grub_uint32_t) -rom_size); + + memcpy (rom_img + rom_size - boot_size, boot_img, boot_size); + + free (core_img); + core_img = rom_img; + core_size = rom_size; + + free (boot_img); + free (boot_path); + } + +#endif + +#ifdef GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE *((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE)) = grub_cpu_to_le32 (total_module_size); +#endif *((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE)) = grub_cpu_to_le32 (kernel_size); +#ifdef GRUB_KERNEL_MACHINE_COMPRESSED_SIZE *((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE)) = grub_cpu_to_le32 (core_size - GRUB_KERNEL_MACHINE_RAW_SIZE); +#endif +#if defined(GRUB_KERNEL_MACHINE_INSTALL_DOS_PART) && defined(GRUB_KERNEL_MACHINE_INSTALL_BSD_PART) /* If we included a drive in our prefix, let GRUB know it doesn't have to prepend the drive told by BIOS. */ if (prefix[0] == '(') @@ -269,10 +323,13 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], *((grub_int32_t *) (core_img + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART)) = grub_cpu_to_le32 (-2); } +#endif +#ifdef GRUB_MACHINE_PCBIOS if (GRUB_KERNEL_MACHINE_LINK_ADDR + core_size > GRUB_MEMORY_MACHINE_UPPER) grub_util_error ("Core image is too big (%p > %p)\n", GRUB_KERNEL_MACHINE_LINK_ADDR + core_size, GRUB_MEMORY_MACHINE_UPPER); +#endif grub_util_write_image (core_img, core_size, out); free (kernel_img);