[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: multiboot module in grub2 --with-platform=efi --target=i386
From: |
phcoder |
Subject: |
Re: multiboot module in grub2 --with-platform=efi --target=i386 |
Date: |
Tue, 14 Apr 2009 11:12:41 +0200 |
User-agent: |
Thunderbird 2.0.0.21 (X11/20090318) |
I did the patch for it, however it seems nobody is interested to test
it. With it I'm able to boot grub invaders on qemu-tianocore. And I have
no xserve. For convenience I resend the patch. If it works I'll split it
into components as required for review. Also have a look at
http://grub.enbug.org/TestingOnMacbook for some relevant fixes (in linux
section).
Drew Rosen wrote:
Hi Uzer Cheg.
Any progress on the Xserve?
On Mar 18, 2009, at 6:22 AM, uzer cheg wrote:
Dear all,
I'm trying to run Xen Dom0 kernel on my Xserve.
As I see I need Grub's entry like this:
menuentry "Xen 3.3 unstable -i386
{
search --set /boot/xen-3.3.gz
multiboot /boot/xen-3.3.gz
module /boot/vmlinuz-2.6.29-rc8-tip root=LABEL=/ ro console=tty0
module /boot/initrd-2.6.29-rc8-tip.img
}
I just downloaded from svn latest grub2 (revision 2032) and tried to
build it.
# cd grub2
# ./configure --with-platform=efi --target=i386
# make
# ./grub-mkimage -d . -o grub.efi apple appleldr boot cat chain
configfile cpio date ext2 echo fat gpt help hexdump hfs hfsplus
iso9660 linux ls normal pc reboot reiserfs scsi search sleep xfs
multiboot module
I got error message
# grub-mkimage: error: cannot stat ./multiboot.mod
I think that make did not build multiboot.mod for efi.
Help me please.
Tell me please how to enable multiboot and module support in efi grub2?
Thank you in advance.
_______________________________________________
Grub-devel mailing list
address@hidden
http://lists.gnu.org/mailman/listinfo/grub-devel
_______________________________________________
Grub-devel mailing list
address@hidden
http://lists.gnu.org/mailman/listinfo/grub-devel
--
Regards
Vladimir 'phcoder' Serbinenko
diff --git a/conf/common.rmk b/conf/common.rmk
index b0a78b0..fb36edb 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -525,3 +525,10 @@ gzio_mod_LDFLAGS = $(COMMON_LDFLAGS)
bufio_mod_SOURCES = io/bufio.c
bufio_mod_CFLAGS = $(COMMON_CFLAGS)
bufio_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+pkglib_MODULES += lsmmap.mod
+
+# For lsmmap.mod
+lsmmap_mod_SOURCES = commands/lsmmap.c
+lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
+lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index 41c45db..1cd7484 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -101,8 +101,7 @@ grub_install_SOURCES = util/i386/pc/grub-install.in
pkglib_MODULES = linux.mod normal.mod multiboot.mod \
aout.mod play.mod serial.mod ata.mod \
memdisk.mod pci.mod lspci.mod reboot.mod \
- halt.mod datetime.mod date.mod datehook.mod \
- lsmmap.mod
+ halt.mod datetime.mod date.mod datehook.mod
# For linux.mod.
linux_mod_SOURCES = loader/i386/linux.c
@@ -200,10 +199,5 @@ datehook_mod_SOURCES = hook/datehook.c
datehook_mod_CFLAGS = $(COMMON_CFLAGS)
datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
-# For lsmmap.mod
-lsmmap_mod_SOURCES = commands/lsmmap.c
-lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
-lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
include $(srcdir)/conf/i386.mk
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 399376f..e185337 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -81,7 +81,17 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
# Modules.
pkglib_MODULES = kernel.mod normal.mod chain.mod appleldr.mod \
linux.mod halt.mod reboot.mod pci.mod lspci.mod \
- datetime.mod date.mod datehook.mod loadbios.mod fixvideo.mod
+ datetime.mod date.mod datehook.mod loadbios.mod \
+ fixvideo.mod multiboot.mod
+# For multiboot.mod.
+multiboot_mod_SOURCES = loader/i386/multiboot.c \
+ loader/i386/multiboot_helper.S \
+ loader/multiboot2.c \
+ loader/efi/multiboot2.c \
+ loader/multiboot_loader.c
+multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
+multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS)
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -91,14 +101,14 @@ kernel_mod_SOURCES = kern/i386/efi/startup.S kern/main.c
kern/device.c \
kern/i386/dl.c kern/i386/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 \
- kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \
+ kern/efi/mmap.c kern/time.c kern/list.c kern/handler.c kern/command.c
kern/corecmd.c \
kern/i386/tsc.c kern/i386/pit.c \
kern/generic/rtc_get_time_ms.c \
kern/generic/millisleep.c
kernel_mod_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 rescue.h symbol.h term.h time.h types.h \
- efi/efi.h efi/time.h efi/disk.h list.h handler.h command.h
+ efi/efi.h efi/time.h efi/disk.h efi/memory.h list.h handler.h command.h
kernel_mod_CFLAGS = $(COMMON_CFLAGS)
kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index 96d9c10..df8c062 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -103,7 +103,7 @@ grub_install_SOURCES = util/ieee1275/grub-install.in
pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod \
multiboot.mod aout.mod serial.mod linux.mod \
nand.mod memdisk.mod pci.mod lspci.mod datetime.mod \
- date.mod datehook.mod lsmmap.mod
+ date.mod datehook.mod
#
# Only arch dependant part of normal.mod will be here. Common part for
@@ -128,6 +128,7 @@ normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For multiboot.mod.
multiboot_mod_SOURCES = loader/ieee1275/multiboot2.c \
+ loader/i386/multiboot.c \
loader/i386/multiboot_helper.S \
loader/multiboot2.c \
loader/multiboot_loader.c
@@ -200,10 +201,5 @@ datehook_mod_SOURCES = hook/datehook.c
datehook_mod_CFLAGS = $(COMMON_CFLAGS)
datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
-# For lsmmap.mod
-lsmmap_mod_SOURCES = commands/lsmmap.c
-lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
-lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
include $(srcdir)/conf/i386.mk
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 7dfb854..82ede6e 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -289,16 +289,6 @@ lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
-# For aout.mod
-aout_mod_SOURCES = loader/aout.c
-aout_mod_CFLAGS = $(COMMON_CFLAGS)
-aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
-# For bsd.mod
-bsd_mod_SOURCES = loader/i386/bsd.c
-bsd_mod_CFLAGS = $(COMMON_CFLAGS)
-bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
# For usb.mod
usb_mod_SOURCES = bus/usb/usb.c bus/usb/usbtrans.c bus/usb/usbhub.c
usb_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -354,11 +344,6 @@ datehook_mod_SOURCES = hook/datehook.c
datehook_mod_CFLAGS = $(COMMON_CFLAGS)
datehook_mod_LDFLAGS = $(COMMON_LDFLAGS)
-# For lsmmap.mod
-lsmmap_mod_SOURCES = commands/lsmmap.c
-lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
-lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
# For ata_pthru.mod.
ata_pthru_mod_SOURCES = disk/ata_pthru.c
ata_pthru_mod_CFLAGS = $(COMMON_CFLAGS)
diff --git a/conf/i386.rmk b/conf/i386.rmk
index 93f84ce..ddf7118 100644
--- a/conf/i386.rmk
+++ b/conf/i386.rmk
@@ -14,3 +14,21 @@ pkglib_MODULES += vga_text.mod
vga_text_mod_SOURCES = term/i386/pc/vga_text.c term/i386/vga_common.c
vga_text_mod_CFLAGS = $(COMMON_CFLAGS)
vga_text_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+pkglib_MODULES += uppermem.mod
+uppermem_mod_SOURCES = lib/i386/uppermem.c
+uppermem_mod_CFLAGS = $(COMMON_CFLAGS)
+uppermem_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+pkglib_MODULES += aout.mod bsd.mod
+# For aout.mod
+aout_mod_SOURCES = loader/aout.c
+aout_mod_CFLAGS = $(COMMON_CFLAGS)
+aout_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For bsd.mod
+bsd_mod_SOURCES = loader/i386/bsd.c loader/i386/bsd_helper.S
+bsd_mod_CFLAGS = $(COMMON_CFLAGS) -Werror
+bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
+bsd_mod_ASFLAGS = $(COMMON_ASFLAGS)
+
diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk
index 361fb85..c084370 100644
--- a/conf/powerpc-ieee1275.rmk
+++ b/conf/powerpc-ieee1275.rmk
@@ -111,8 +111,7 @@ pkglib_MODULES = halt.mod \
reboot.mod \
suspend.mod \
multiboot.mod \
- memdisk.mod \
- lsmmap.mod
+ memdisk.mod
# For linux.mod.
linux_mod_SOURCES = loader/powerpc/ieee1275/linux.c
@@ -167,10 +166,5 @@ memdisk_mod_SOURCES = disk/memdisk.c
memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
-# For lsmmap.mod
-lsmmap_mod_SOURCES = commands/lsmmap.c
-lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
-lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
-
include $(srcdir)/conf/common.mk
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 8c277c0..137a437 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -54,6 +54,8 @@ char *EXPORT_FUNC(grub_efi_get_filename)
(grub_efi_device_path_t *dp);
grub_efi_device_path_t *
EXPORT_FUNC(grub_efi_get_device_path) (grub_efi_handle_t handle);
int EXPORT_FUNC(grub_efi_exit_boot_services) (grub_efi_uintn_t map_key);
+int EXPORT_FUNC(grub_efi_finish_boot_services) (void);
+
void EXPORT_FUNC (grub_reboot) (void);
void EXPORT_FUNC (grub_halt) (void);
diff --git a/include/grub/efi/memory.h b/include/grub/efi/memory.h
new file mode 100644
index 0000000..9000642
--- /dev/null
+++ b/include/grub/efi/memory.h
@@ -0,0 +1,15 @@
+#ifndef GRUB_MEMORY_MACHINE_HEADER
+#define GRUB_MEMORY_MACHINE_HEADER 1
+
+#include <grub/err.h>
+#include <grub/types.h>
+
+#define GRUB_MACHINE_MEMORY_AVAILABLE 1
+#define GRUB_MACHINE_MEMORY_RESERVED 2
+#define GRUB_MACHINE_MEMORY_ACPI 3
+#define GRUB_MACHINE_MEMORY_NVS 4
+#define GRUB_MACHINE_MEMORY_CODE 5
+
+grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate)
+(int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t));
+#endif /* ! GRUB_MEMORY_MACHINE_HEADER */
diff --git a/include/grub/i386/bsd.h b/include/grub/i386/bsd.h
index f50f18e..723dff5 100644
--- a/include/grub/i386/bsd.h
+++ b/include/grub/i386/bsd.h
@@ -148,6 +148,8 @@ struct grub_openbsd_bios_mmap
{
grub_uint64_t addr;
grub_uint64_t len;
+#define OPENBSD_MMAP_AVAILABLE 1
+#define OPENBSD_MMAP_RESERVED 2
grub_uint32_t type;
};
@@ -222,4 +224,7 @@ struct grub_netbsd_btinfo_bootdisk
int partition;
};
+void grub_unix_real_boot (grub_addr_t entry, ...)
+ __attribute__ ((cdecl,noreturn));
+
#endif /* ! GRUB_BSD_CPU_HEADER */
diff --git a/include/grub/i386/efi/memory.h b/include/grub/i386/efi/memory.h
new file mode 100644
index 0000000..c9a61bb
--- /dev/null
+++ b/include/grub/i386/efi/memory.h
@@ -0,0 +1 @@
+#include <grub/efi/memory.h>
diff --git a/include/grub/i386/loader.h b/include/grub/i386/loader.h
index afd3eb9..685c2e0 100644
--- a/include/grub/i386/loader.h
+++ b/include/grub/i386/loader.h
@@ -27,12 +27,14 @@ extern grub_uint32_t EXPORT_VAR(grub_linux_prot_size);
extern char *EXPORT_VAR(grub_linux_tmp_addr);
extern char *EXPORT_VAR(grub_linux_real_addr);
extern grub_int32_t EXPORT_VAR(grub_linux_is_bzimage);
-extern grub_addr_t EXPORT_VAR(grub_os_area_addr);
-extern grub_size_t EXPORT_VAR(grub_os_area_size);
grub_err_t EXPORT_FUNC(grub_linux16_boot) (void);
-void EXPORT_FUNC(grub_unix_real_boot) (grub_addr_t entry, ...)
- __attribute__ ((cdecl,noreturn));
+/* 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 EXPORT_FUNC(grub_stop_floppy) (void);
#endif /* ! GRUB_LOADER_CPU_HEADER */
diff --git a/include/grub/i386/multiboot.h b/include/grub/i386/multiboot.h
index 2dd7ec0..a6da360 100644
--- a/include/grub/i386/multiboot.h
+++ b/include/grub/i386/multiboot.h
@@ -22,10 +22,10 @@
/* The asm part of the multiboot loader. */
void grub_multiboot_real_boot (grub_addr_t entry,
struct grub_multiboot_info *mbi)
- __attribute__ ((noreturn));
+ __attribute__ ((noreturn,regparm (3)));
void grub_multiboot2_real_boot (grub_addr_t entry,
struct grub_multiboot_info *mbi)
- __attribute__ ((noreturn));
+ __attribute__ ((noreturn,regparm (3)));
extern grub_addr_t grub_multiboot_payload_orig;
extern grub_addr_t grub_multiboot_payload_dest;
diff --git a/include/grub/i386/pc/memory.h b/include/grub/i386/pc/memory.h
index 08e92a9..e69ff77 100644
--- a/include/grub/i386/pc/memory.h
+++ b/include/grub/i386/pc/memory.h
@@ -92,6 +92,8 @@ struct grub_machine_mmap_entry
grub_uint64_t len;
#define GRUB_MACHINE_MEMORY_AVAILABLE 1
#define GRUB_MACHINE_MEMORY_RESERVED 2
+#define GRUB_MACHINE_MEMORY_ACPI 3
+#define GRUB_MACHINE_MEMORY_NVS 4
grub_uint32_t type;
} __attribute__((packed));
diff --git a/include/grub/i386/uppermem.h b/include/grub/i386/uppermem.h
new file mode 100644
index 0000000..bceed3e
--- /dev/null
+++ b/include/grub/i386/uppermem.h
@@ -0,0 +1,7 @@
+#ifndef GRUB_UPPERMEM_HEADER
+#define GRUB_UPPERMEM_HEADER
+
+grub_err_t
+grub_get_lower_upper_memory (grub_uint64_t *lower, grub_uint64_t *upper);
+
+#endif
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
index 3b5139e..48bc3f2 100644
--- a/include/grub/ieee1275/ieee1275.h
+++ b/include/grub/ieee1275/ieee1275.h
@@ -169,7 +169,6 @@ grub_err_t EXPORT_FUNC(grub_children_iterate) (char
*devpath,
int (*hook) (struct grub_ieee1275_devalias *alias));
grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate)
(int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t,
grub_uint32_t));
-int EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size);
char *EXPORT_FUNC(grub_ieee1275_encode_devname) (const char *path);
char *EXPORT_FUNC(grub_ieee1275_get_filename) (const char *path);
diff --git a/include/grub/loader.h b/include/grub/loader.h
index 1ae5fdd..544b2f5 100644
--- a/include/grub/loader.h
+++ b/include/grub/loader.h
@@ -41,4 +41,8 @@ void EXPORT_FUNC(grub_loader_unset) (void);
depending on the setting by grub_loader_set. */
grub_err_t EXPORT_FUNC(grub_loader_boot) (void);
+int EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size);
+
+void EXPORT_FUNC(grub_declaimmap) (grub_addr_t addr, grub_size_t size);
+
#endif /* ! GRUB_LOADER_HEADER */
diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h
index bfbffcc..1e6701e 100644
--- a/include/grub/multiboot2.h
+++ b/include/grub/multiboot2.h
@@ -39,12 +39,6 @@ void
grub_mb2_arch_unload (struct multiboot_tag_header *tags);
grub_err_t
-grub_mb2_arch_elf32_hook (Elf32_Phdr *phdr, grub_addr_t *addr);
-
-grub_err_t
-grub_mb2_arch_elf64_hook (Elf64_Phdr *phdr, grub_addr_t *addr);
-
-grub_err_t
grub_mb2_arch_module_alloc (grub_size_t size, grub_addr_t *addr);
grub_err_t
diff --git a/include/grub/types.h b/include/grub/types.h
index 8d51b66..faf2257 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -100,6 +100,16 @@ typedef grub_int32_t grub_ssize_t;
# define LONG_MAX 2147483647UL
#endif
+#if GRUB_CPU_SIZEOF_VOID_P == 4
+#define UINT_TO_PTR(x) ((void*)(grub_uint32_t)(x))
+#define PTR_TO_UINT64(x) ((grub_uint64_t)(grub_uint32_t)(x))
+#define PTR_TO_UINT32(x) ((grub_uint32_t)(x))
+#else
+#define UINT_TO_PTR(x) ((void*)(grub_uint64_t)(x))
+#define PTR_TO_UINT64(x) ((grub_uint64_t)(x))
+#define PTR_TO_UINT32(x) ((grub_uint32_t)(grub_uint64_t)(x))
+#endif
+
/* The type for representing a file offset. */
typedef grub_uint64_t grub_off_t;
diff --git a/include/grub/x86_64/efi/memory.h b/include/grub/x86_64/efi/memory.h
new file mode 100644
index 0000000..c9a61bb
--- /dev/null
+++ b/include/grub/x86_64/efi/memory.h
@@ -0,0 +1 @@
+#include <grub/efi/memory.h>
diff --git a/kern/efi/efi.c b/kern/efi/efi.c
index 9c9a400..754f82c 100644
--- a/kern/efi/efi.c
+++ b/kern/efi/efi.c
@@ -187,6 +187,28 @@ grub_efi_exit_boot_services (grub_efi_uintn_t map_key)
return status == GRUB_EFI_SUCCESS;
}
+int
+grub_efi_finish_boot_services (void)
+{
+ grub_efi_uintn_t mmap_size = 0;
+ grub_efi_uintn_t map_key;
+ grub_efi_uintn_t desc_size;
+ grub_efi_uint32_t desc_version;
+ void *mmap_buf;
+
+ if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
+ &desc_size, &desc_version) < 0)
+ return 0;
+
+ mmap_buf = grub_malloc (mmap_size);
+
+ if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
+ &desc_size, &desc_version) <= 0)
+ return 0;
+
+ return grub_efi_exit_boot_services (map_key);
+}
+
grub_uint32_t
grub_get_rtc (void)
{
diff --git a/kern/efi/mm.c b/kern/efi/mm.c
index 35b12ab..4635776 100644
--- a/kern/efi/mm.c
+++ b/kern/efi/mm.c
@@ -47,7 +47,7 @@ static struct allocated_page *allocated_pages = 0;
/* The minimum and maximum heap size for GRUB itself. */
#define MIN_HEAP_SIZE 0x100000
-#define MAX_HEAP_SIZE (16 * 0x100000)
+#define MAX_HEAP_SIZE (1600 * 0x100000)
/* Allocate pages. Return the pointer to the first of allocated pages. */
diff --git a/kern/efi/mmap.c b/kern/efi/mmap.c
new file mode 100644
index 0000000..3f795cb
--- /dev/null
+++ b/kern/efi/mmap.c
@@ -0,0 +1,177 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/machine/memory.h>
+#include <grub/err.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/loader.h>
+
+#define NEXT_MEMORY_DESCRIPTOR(desc, size) \
+ ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
+
+struct region
+{
+ grub_uint64_t start;
+ grub_uint64_t len;
+ grub_uint32_t type;
+};
+
+grub_err_t
+grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t,
grub_uint64_t, grub_uint32_t))
+{
+ grub_efi_uintn_t mmap_size = 0;
+ grub_efi_memory_descriptor_t *map_buf;
+ grub_efi_uintn_t map_key = 0;
+ grub_efi_uintn_t desc_size = 0;
+ grub_efi_uint32_t desc_version = 0;
+ grub_uint64_t curstart, curend;
+ grub_uint32_t curtype;
+ grub_efi_memory_descriptor_t *desc;
+ struct region *regions;
+ struct region t;
+ int i, count, done = 1;
+
+ if (grub_efi_get_memory_map (&mmap_size, map_buf,
+ &map_key, &desc_size,
+ &desc_version) < 0)
+ return grub_errno;
+
+ map_buf = grub_malloc (mmap_size);
+ if (!map_buf)
+ return grub_errno;
+
+ if (grub_efi_get_memory_map (&mmap_size, map_buf,
+ &map_key, &desc_size,
+ &desc_version) <= 0)
+ {
+ grub_free (map_buf);
+ return grub_errno;
+ }
+
+ count = mmap_size / desc_size;
+ if (! count)
+ {
+ grub_free (map_buf);
+ return grub_error (GRUB_ERR_IO, "couldn't get EFI memory map");
+ }
+ regions = (struct region *) grub_malloc (count * sizeof (struct region));
+
+ for (desc = map_buf, i = 0;
+ desc < NEXT_MEMORY_DESCRIPTOR (map_buf, mmap_size);
+ desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size), i++)
+ {
+ grub_dprintf ("efi_mmap", "EFI memory region 0x%llx-0x%llx: %d\n",
+ desc->physical_start, desc->physical_start
+ + desc->num_pages * 4096, desc->type);
+ switch (desc->type)
+ {
+ case GRUB_EFI_RUNTIME_SERVICES_CODE:
+ regions[i].start = desc->physical_start;
+ regions[i].len = desc->num_pages * 4096;
+ regions[i].type = GRUB_MACHINE_MEMORY_CODE;
+ break;
+
+ case GRUB_EFI_RESERVED_MEMORY_TYPE:
+ case GRUB_EFI_RUNTIME_SERVICES_DATA:
+ case GRUB_EFI_UNUSABLE_MEMORY:
+ case GRUB_EFI_MEMORY_MAPPED_IO:
+ case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE:
+ case GRUB_EFI_PAL_CODE:
+ case GRUB_EFI_MAX_MEMORY_TYPE:
+ regions[i].start = desc->physical_start;
+ regions[i].len = desc->num_pages * 4096;
+ regions[i].type = GRUB_MACHINE_MEMORY_RESERVED;
+ break;
+
+ case GRUB_EFI_LOADER_CODE:
+ case GRUB_EFI_LOADER_DATA:
+ case GRUB_EFI_BOOT_SERVICES_CODE:
+ case GRUB_EFI_BOOT_SERVICES_DATA:
+ case GRUB_EFI_CONVENTIONAL_MEMORY:
+ regions[i].start = desc->physical_start;
+ regions[i].len = desc->num_pages * 4096;
+ regions[i].type = GRUB_MACHINE_MEMORY_AVAILABLE;
+ break;
+
+ case GRUB_EFI_ACPI_RECLAIM_MEMORY:
+ regions[i].start = desc->physical_start;
+ regions[i].len = desc->num_pages * 4096;
+ regions[i].type = GRUB_MACHINE_MEMORY_ACPI;
+ break;
+
+ case GRUB_EFI_ACPI_MEMORY_NVS:
+ regions[i].start = desc->physical_start;
+ regions[i].len = desc->num_pages * 4096;
+ regions[i].type = GRUB_MACHINE_MEMORY_NVS;
+ break;
+ }
+ }
+
+ /* Bubble-sort the memory map */
+ while (done)
+ {
+ done = 0;
+ for (i = 0; i < count - 1; i++)
+ if (regions[i].start > regions[i + 1].start)
+ {
+ done = 1;
+ t = regions[i];
+ regions[i] = regions[i + 1];
+ regions[i + 1] = t;
+ }
+ }
+
+ curstart = regions[0].start;
+ curend = regions[0].start + regions[0].len;
+ curtype = regions[0].type;
+ for (i = 1; i < count; i++)
+ {
+ if (curend != regions[i].start || curtype != regions[i].type)
+ {
+ hook (curstart, curend - curstart, curtype);
+ curstart = regions[i].start;
+ curtype = regions[i].type;
+ }
+ curend = regions[i].start + regions[i].len;
+ }
+
+ hook (curstart, curend - curstart, curtype);
+
+ return GRUB_ERR_NONE;
+}
+
+/* XXX: Manage subpage allocations */
+int
+grub_claimmap (grub_addr_t addr, grub_size_t size)
+{
+ void *ret;
+ ret = grub_efi_allocate_pages (addr & (~0xfff),
+ (size + (addr & 0xfff) + 0xfff) >> 12);
+ return (! ret) ? -1 : 0;
+}
+
+/* XXX: Manage subpage allocations */
+void
+grub_declaimmap (grub_addr_t addr, grub_size_t size)
+{
+ grub_efi_free_pages (addr & (~0xfff),
+ (size + (addr & 0xfff) + 0xfff) >> 12);
+}
diff --git a/kern/i386/coreboot/init.c b/kern/i386/coreboot/init.c
index 1348488..9c1aee0 100644
--- a/kern/i386/coreboot/init.c
+++ b/kern/i386/coreboot/init.c
@@ -155,3 +155,18 @@ grub_arch_modules_addr (void)
{
return ALIGN_UP((grub_addr_t) _end, GRUB_MOD_ALIGN);
}
+
+int
+grub_claimmap (grub_addr_t addr, grub_size_t size)
+{
+ if ((addr < grub_os_area_addr)
+ || (addr + size > grub_os_area_addr + grub_os_area_size))
+ return -1;
+ return 0;
+}
+
+void
+grub_declaimmap (grub_addr_t addr __attribute__ ((unused)),
+ grub_size_t size __attribute__ ((unused)))
+{
+}
diff --git a/kern/i386/loader.S b/kern/i386/loader.S
index bbd2187..d9b37bf 100644
--- a/kern/i386/loader.S
+++ b/kern/i386/loader.S
@@ -117,26 +117,3 @@ bzimage:
linux_setup_seg:
.word 0
.code32
-
-/*
- * Use cdecl calling convention for *BSD kernels.
- */
-
-FUNCTION(grub_unix_real_boot)
-
- call EXT_C(grub_dl_unload_all)
-
- /* Interrupts should be disabled. */
- cli
-
- /* Discard `grub_unix_real_boot' return address. */
- popl %eax
-
- /* Fetch `entry' address ... */
- popl %eax
-
- /*
- * ... and put our return address in its place. The kernel will
- * ignore it, but it expects %esp to point to it.
- */
- call *%eax
diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c
index 6191412..17d5343 100644
--- a/kern/i386/pc/init.c
+++ b/kern/i386/pc/init.c
@@ -43,8 +43,8 @@ struct mem_region
static struct mem_region mem_regions[MAX_REGIONS];
static int num_regions;
-grub_addr_t grub_os_area_addr;
-grub_size_t grub_os_area_size;
+static grub_addr_t grub_os_area_addr;
+static grub_size_t grub_os_area_size;
grub_size_t grub_lower_mem, grub_upper_mem;
void
@@ -233,3 +233,18 @@ grub_arch_modules_addr (void)
return GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
+ (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE);
}
+
+int
+grub_claimmap (grub_addr_t addr, grub_size_t size)
+{
+ if ((addr < grub_os_area_addr)
+ || (addr + size > grub_os_area_addr + grub_os_area_size))
+ return -1;
+ return 0;
+}
+
+void
+grub_declaimmap (grub_addr_t addr __attribute__ ((unused)),
+ grub_size_t size __attribute__ ((unused)))
+{
+}
diff --git a/kern/ieee1275/openfw.c b/kern/ieee1275/openfw.c
index d70c3ba..c713d4c 100644
--- a/kern/ieee1275/openfw.c
+++ b/kern/ieee1275/openfw.c
@@ -194,6 +194,13 @@ grub_claimmap (grub_addr_t addr, grub_size_t size)
return 0;
}
+/* XXX Could someone with better OFW knowledge that me fill this? */
+void
+grub_declaimmap (grub_addr_t addr __attribute__ ((unused)),
+ grub_size_t size __attribute__ ((unused)))
+{
+}
+
/* Get the device arguments of the Open Firmware node name `path'. */
static char *
grub_ieee1275_get_devargs (const char *path)
diff --git a/lib/i386/uppermem.c b/lib/i386/uppermem.c
new file mode 100644
index 0000000..623535f
--- /dev/null
+++ b/lib/i386/uppermem.c
@@ -0,0 +1,127 @@
+/* Compute amount of lower and upper memory till the first hole */
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EFIEMU
+#include <grub/machine/memory.h>
+#include <grub/i386/uppermem.h>
+#endif
+
+#include <grub/mm.h>
+#include <grub/misc.h>
+
+struct region
+{
+ grub_uint64_t start;
+ grub_uint64_t end;
+};
+
+#ifdef EFIEMU
+grub_err_t
+grub_efiemu_get_lower_upper_memory (grub_uint64_t *lower, grub_uint64_t *upper)
+#else
+grub_err_t
+grub_get_lower_upper_memory (grub_uint64_t *lower, grub_uint64_t *upper)
+#endif
+{
+ grub_size_t count = 0;
+ struct region *regions = 0;
+ int done = 1;
+ unsigned i;
+ struct region t;
+ grub_uint64_t last_addr;
+
+ auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+ int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
+ grub_uint32_t type)
+ {
+#ifdef EFIEMU
+ if (type != GRUB_EFIEMU_MEMORY_AVAILABLE)
+#else
+ if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
+#endif
+ return 0;
+ regions = (struct region *)
+ grub_realloc (regions, (count + 1) * sizeof (struct region));
+ regions[count].start = addr;
+ regions[count].end = addr + size;
+ count++;
+ return 0;
+ }
+
+#ifdef EFIEMU
+ grub_efiemu_mmap_iterate (hook);
+#else
+ grub_machine_mmap_iterate (hook);
+#endif
+
+ /* Bubble-sort the memory map */
+ while (done)
+ {
+ done = 0;
+ for (i = 0; i < count - 1; i++)
+ if (regions[i].start > regions[i + 1].start)
+ {
+ done = 1;
+ t = regions[i];
+ regions[i] = regions[i + 1];
+ regions[i + 1] = t;
+ }
+ }
+
+ /* Set mem_upper and mem_lower */
+ last_addr = 0;
+ for (i = 0; i < count; i++)
+ {
+ grub_uint64_t end = regions[i].end;
+ /* Don't use memory after 0xa0000*/
+ if (end > 0xa0000)
+ end = 0xa0000;
+
+ /* low memory is finished */
+ if (regions[i].start > end)
+ break;
+
+ /* A hole */
+ if (regions[i].start > last_addr)
+ break;
+
+ last_addr = end;
+ }
+
+ *lower = last_addr;
+
+ /* Skip low memory */
+ for (i = 0; i < count && regions[i].end <= 0x100000;
+ i++);
+
+ last_addr = 0x100000;
+ for (; i < count; i++)
+ {
+ /* A hole */
+ if (regions[i].start > last_addr)
+ break;
+
+ last_addr = regions[i].end;
+ }
+
+ *upper = (last_addr - 0x100000);
+ grub_free (regions);
+
+ return GRUB_ERR_NONE;
+}
diff --git a/loader/efi/multiboot2.c b/loader/efi/multiboot2.c
new file mode 100644
index 0000000..44bb542
--- /dev/null
+++ b/loader/efi/multiboot2.c
@@ -0,0 +1,75 @@
+/* multiboot2.c - boot a multiboot 2 OS image. */
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <multiboot2.h>
+#include <grub/multiboot2.h>
+#include <grub/elf.h>
+#include <grub/err.h>
+#include <grub/machine/loader.h>
+#include <grub/mm.h>
+
+grub_err_t
+grub_mb2_arch_module_alloc (grub_size_t size, grub_addr_t *addr)
+{
+ grub_addr_t modaddr;
+
+ modaddr = (grub_addr_t) grub_memalign (MULTIBOOT2_MOD_ALIGN, size);
+ if (! modaddr)
+ return grub_errno;
+
+ *addr = modaddr;
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_mb2_arch_module_free (grub_addr_t addr, UNUSED grub_size_t size)
+{
+ grub_free((void *) addr);
+ return GRUB_ERR_NONE;
+}
+
+void
+grub_mb2_arch_boot (grub_addr_t entry, void *tags)
+{
+ grub_multiboot2_real_boot (entry, tags);
+}
+
+void
+grub_mb2_arch_unload (struct multiboot_tag_header *tags)
+{
+ struct multiboot_tag_header *tag;
+
+ /* Free all module memory in the tag list. */
+ for_each_tag (tag, tags)
+ {
+ if (tag->key == MULTIBOOT2_TAG_MODULE)
+ {
+ struct multiboot_tag_module *module =
+ (struct multiboot_tag_module *) tag;
+ grub_free((void *) module->addr);
+ }
+ }
+}
+
+grub_err_t
+grub_mb2_tags_arch_create (void)
+{
+ /* XXX Create system table et al. */
+ return GRUB_ERR_NONE;
+}
diff --git a/loader/i386/bsd.c b/loader/i386/bsd.c
index 355cb3f..4023566 100644
--- a/loader/i386/bsd.c
+++ b/loader/i386/bsd.c
@@ -19,8 +19,8 @@
#include <grub/loader.h>
#include <grub/cpu/loader.h>
#include <grub/cpu/bsd.h>
-#include <grub/machine/init.h>
#include <grub/machine/memory.h>
+#include <grub/machine/machine.h>
#include <grub/file.h>
#include <grub/err.h>
#include <grub/dl.h>
@@ -30,8 +30,13 @@
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/aout.h>
+#include <grub/i386/uppermem.h>
#include <grub/command.h>
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/efi.h>
+#endif
+
#define ALIGN_DWORD(a) ALIGN_UP (a, 4)
#define ALIGN_PAGE(a) ALIGN_UP (a, 4096)
@@ -302,6 +307,15 @@ grub_freebsd_boot (void)
bi.bi_kernend = kern_end;
+#ifdef GRUB_MACHINE_PCBIOS
+ grub_stop_floppy ();
+#endif
+
+#ifdef GRUB_MACHINE_EFI
+ if (! grub_efi_finish_boot_services ())
+ grub_fatal ("cannot exit boot services");
+#endif
+
grub_unix_real_boot (entry, bootflags | FREEBSD_RB_BOOTINFO, bootdev,
0, 0, 0, &bi, bi.bi_modulep, kern_end);
@@ -313,30 +327,39 @@ static grub_err_t
grub_openbsd_boot (void)
{
char *buf = (char *) GRUB_BSD_TEMP_BUFFER;
- struct grub_machine_mmap_entry mmap;
struct grub_openbsd_bios_mmap *pm;
struct grub_openbsd_bootargs *pa;
- grub_uint32_t bootdev, biosdev, unit, slice, part, cont;
+ grub_uint32_t bootdev, biosdev, unit, slice, part;
+ grub_uint64_t lower, upper;
+ grub_err_t err;
+
+ auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+ int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
grub_uint32_t type)
+ {
+ pm->addr = addr;
+ pm->len = size;
+
+ switch (type)
+ {
+ case GRUB_MACHINE_MEMORY_AVAILABLE:
+ pm->type = OPENBSD_MMAP_AVAILABLE;
+ break;
+
+ default:
+ pm->type = OPENBSD_MMAP_RESERVED;
+ break;
+ }
+ pm++;
+
+ return 0;
+ }
pa = (struct grub_openbsd_bootargs *) buf;
pa->ba_type = OPENBSD_BOOTARG_MMAP;
pm = (struct grub_openbsd_bios_mmap *) (pa + 1);
- cont = grub_get_mmap_entry (&mmap, 0);
- if (mmap.size)
- do
- {
- pm->addr = mmap.addr;
- pm->len = mmap.len;
- pm->type = mmap.type;
- pm++;
- if (!cont)
- break;
-
- cont = grub_get_mmap_entry (&mmap, cont);
- }
- while (mmap.size);
+ grub_machine_mmap_iterate (hook);
pa->ba_size = (char *) pm - (char *) pa;
pa->ba_next = (struct grub_openbsd_bootargs *) pm;
@@ -348,8 +371,20 @@ grub_openbsd_boot (void)
bootdev = (OPENBSD_B_DEVMAGIC + (unit << OPENBSD_B_UNITSHIFT) +
(part << OPENBSD_B_PARTSHIFT));
+ if ((err = grub_get_lower_upper_memory (&lower, &upper)))
+ return err;
+
+#ifdef GRUB_MACHINE_PCBIOS
+ grub_stop_floppy ();
+#endif
+
+#ifdef GRUB_MACHINE_EFI
+ if (! grub_efi_finish_boot_services ())
+ grub_fatal ("cannot exit boot services");
+#endif
+
grub_unix_real_boot (entry, bootflags, bootdev, OPENBSD_BOOTARG_APIVER,
- 0, grub_upper_mem >> 10, grub_lower_mem >> 10,
+ 0, upper >> 10, lower >> 10,
(char *) pa - buf, buf);
/* Not reached. */
@@ -362,6 +397,8 @@ grub_netbsd_boot (void)
struct grub_netbsd_btinfo_rootdevice *rootdev;
struct grub_netbsd_bootinfo *bootinfo;
grub_uint32_t biosdev, unit, slice, part;
+ grub_uint64_t lower, upper;
+ grub_err_t err;
grub_bsd_get_device (&biosdev, &unit, &slice, &part);
@@ -376,8 +413,20 @@ grub_netbsd_boot (void)
bootinfo->bi_count = 1;
bootinfo->bi_data[0] = rootdev;
+ if ((err = grub_get_lower_upper_memory (&lower, &upper)))
+ return err;
+
+#ifdef GRUB_MACHINE_PCBIOS
+ grub_stop_floppy ();
+#endif
+
+#ifdef GRUB_MACHINE_EFI
+ if (! grub_efi_finish_boot_services ())
+ grub_fatal ("cannot exit boot services");
+#endif
+
grub_unix_real_boot (entry, bootflags, 0, bootinfo,
- 0, grub_upper_mem >> 10, grub_lower_mem >> 10);
+ 0, upper >> 10, lower >> 10);
/* Not reached. */
return GRUB_ERR_NONE;
@@ -461,8 +510,7 @@ grub_bsd_elf32_hook (Elf32_Phdr * phdr, grub_addr_t * addr)
phdr->p_paddr &= 0xFFFFFF;
paddr = phdr->p_paddr;
- if ((paddr < grub_os_area_addr)
- || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size))
+ if (grub_claimmap (paddr, phdr->p_memsz) < 0)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Address 0x%x is out of range",
paddr);
@@ -578,7 +626,7 @@ grub_cmd_freebsd (grub_command_t cmd __attribute__
((unused)),
(grub_freebsd_add_meta_module (1, argc, argv, kern_start,
kern_end - kern_start)))
return grub_errno;
- grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 1);
+ grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 0);
}
return grub_errno;
@@ -593,7 +641,7 @@ grub_cmd_openbsd (grub_command_t cmd __attribute__
((unused)),
grub_bsd_parse_flags (argv[1], openbsd_opts, openbsd_flags));
if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
- grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 1);
+ grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 0);
return grub_errno;
}
@@ -607,7 +655,7 @@ grub_cmd_netbsd (grub_command_t cmd __attribute__
((unused)),
grub_bsd_parse_flags (argv[1], netbsd_opts, netbsd_flags));
if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
- grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 1);
+ grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 0);
return grub_errno;
}
@@ -725,7 +773,7 @@ grub_cmd_freebsd_module (grub_command_t cmd __attribute__
((unused)),
if ((!file) || (!file->size))
goto fail;
- if (kern_end + file->size > grub_os_area_addr + grub_os_area_size)
+ if (grub_claimmap (kern_end, file->size) < 0)
{
grub_error (GRUB_ERR_OUT_OF_RANGE, "Not enough memory for the module");
goto fail;
diff --git a/loader/i386/bsd_helper.S b/loader/i386/bsd_helper.S
new file mode 100644
index 0000000..9cdea0c
--- /dev/null
+++ b/loader/i386/bsd_helper.S
@@ -0,0 +1,65 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+/*
+ * Note: These functions defined in this file may be called from C.
+ * Be careful of that you must not modify some registers. Quote
+ * from gcc-2.95.2/gcc/config/i386/i386.h:
+
+ 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like.
+
+ ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg
+{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
+ */
+
+/*
+ * Note: GRUB is compiled with the options -mrtd and -mregparm=3.
+ * So the first three arguments are passed in %eax, %edx, and %ecx,
+ * respectively, and if a function has a fixed number of arguments
+ * and the number if greater than three, the function must return
+ * with "ret $N" where N is ((the number of arguments) - 3) * 4.
+ */
+
+#include <grub/symbol.h>
+
+/*
+ * Use cdecl calling convention for *BSD kernels.
+ */
+
+FUNCTION(grub_unix_real_boot)
+
+ /* Interrupts should be disabled. */
+ cli
+
+ /* Discard `grub_unix_real_boot' return address. */
+ popl %eax
+
+ /* Fetch `entry' address ... */
+ popl %eax
+
+ /*
+ * ... and put our return address in its place. The kernel will
+ * ignore it, but it expects %esp to point to it.
+ */
+ call *%eax
diff --git a/loader/i386/efi/linux.c b/loader/i386/efi/linux.c
index 100b268..e729a8e 100644
--- a/loader/i386/efi/linux.c
+++ b/loader/i386/efi/linux.c
@@ -18,6 +18,7 @@
#include <grub/loader.h>
#include <grub/machine/loader.h>
+#include <grub/machine/memory.h>
#include <grub/file.h>
#include <grub/disk.h>
#include <grub/err.h>
@@ -46,9 +47,10 @@ static int loaded;
static void *real_mode_mem;
static void *prot_mode_mem;
static void *initrd_mem;
-static grub_efi_uintn_t real_mode_pages;
-static grub_efi_uintn_t prot_mode_pages;
-static grub_efi_uintn_t initrd_pages;
+static grub_size_t real_size;
+static grub_size_t mmap_size;
+static grub_size_t prot_size;
+static grub_size_t initrd_size;
static void *mmap_buf;
static grub_uint8_t gdt[] __attribute__ ((aligned(16))) =
@@ -95,26 +97,26 @@ page_align (grub_size_t size)
/* 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
+static grub_size_t
find_mmap_size (void)
{
- static grub_efi_uintn_t mmap_size = 0;
+ static grub_efi_uintn_t cache_mmap_size = 0;
- if (mmap_size != 0)
- return mmap_size;
+ if (cache_mmap_size != 0)
+ return cache_mmap_size;
- mmap_size = (1 << 12);
+ cache_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);
+ mmap = grub_malloc (cache_mmap_size);
if (! mmap)
return 0;
- ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0);
+ ret = grub_efi_get_memory_map (&cache_mmap_size, mmap, 0, &desc_size, 0);
grub_free (mmap);
if (ret < 0)
@@ -122,14 +124,14 @@ find_mmap_size (void)
else if (ret > 0)
break;
- mmap_size += (1 << 12);
+ cache_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);
+ cache_mmap_size += (1 << 12);
- return page_align (mmap_size);
+ return page_align (cache_mmap_size);
}
static void
@@ -137,19 +139,19 @@ free_pages (void)
{
if (real_mode_mem)
{
- grub_efi_free_pages ((grub_addr_t) real_mode_mem, real_mode_pages);
+ grub_declaimmap ((grub_addr_t) real_mode_mem, real_size + mmap_size);
real_mode_mem = 0;
}
if (prot_mode_mem)
{
- grub_efi_free_pages ((grub_addr_t) prot_mode_mem, prot_mode_pages);
+ grub_declaimmap ((grub_addr_t) prot_mode_mem, prot_size);
prot_mode_mem = 0;
}
if (initrd_mem)
{
- grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages);
+ grub_declaimmap ((grub_addr_t) initrd_mem, initrd_size);
initrd_mem = 0;
}
}
@@ -161,9 +163,8 @@ allocate_pages (grub_size_t prot_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_uintn_t tmp_mmap_size;
grub_efi_memory_descriptor_t *desc;
- grub_size_t real_size;
/* Make sure that each size is aligned to a page boundary. */
real_size = GRUB_LINUX_CL_END_OFFSET;
@@ -173,11 +174,6 @@ allocate_pages (grub_size_t prot_size)
grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n",
(unsigned) real_size, (unsigned) prot_size, (unsigned)
mmap_size);
- /* Calculate the number of pages; Combine the real mode code with
- the memory map buffer for simplicity. */
- real_mode_pages = ((real_size + mmap_size) >> 12);
- prot_mode_pages = (prot_size >> 12);
-
/* Initialize the memory pointers with NULL for convenience. */
real_mode_mem = 0;
prot_mode_mem = 0;
@@ -192,44 +188,40 @@ allocate_pages (grub_size_t prot_size)
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))
+
+ /* FIXME: Should request low memory from the heap when this feature is
+ implemented. */
+
+ auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+ int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
grub_uint32_t type)
{
- /* Probably it is better to put the real mode code in the traditional
- space for safety. */
- if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
- && desc->physical_start <= 0x90000
- && desc->num_pages >= real_mode_pages)
+ /* We must put real mode code in the traditional space. */
+
+ if (type == GRUB_MACHINE_MEMORY_AVAILABLE
+ && addr <= 0x90000)
{
- grub_efi_physical_address_t physical_end;
- grub_efi_physical_address_t addr;
-
- physical_end = desc->physical_start + (desc->num_pages << 12);
- if (physical_end > 0x90000)
- physical_end = 0x90000;
-
- grub_dprintf ("linux", "physical_start = %x, physical_end = %x\n",
- (unsigned) desc->physical_start,
- (unsigned) physical_end);
- addr = physical_end - real_size - mmap_size;
if (addr < 0x10000)
- continue;
+ {
+ size += addr - 0x10000;
+ addr = 0x10000;
+ }
- grub_dprintf ("linux", "trying to allocate %u pages at %lx\n",
- (unsigned) real_mode_pages, (unsigned long) addr);
- real_mode_mem = grub_efi_allocate_pages (addr, real_mode_pages);
- if (! real_mode_mem)
- grub_fatal ("cannot allocate pages");
-
- desc->num_pages -= real_mode_pages;
- break;
+ if (addr + size > 0x90000)
+ size = 0x90000 - addr;
+
+ if (real_size + mmap_size > size)
+ return 0;
+
+ real_mode_mem = (void *) ((addr + size) - (real_size + mmap_size));
+ if (grub_claimmap ((grub_addr_t) real_mode_mem,
+ real_size + mmap_size) < 0)
+ return 0;
+ return 1;
}
- }
+ return 0;
+ }
+ grub_machine_mmap_iterate (hook);
if (! real_mode_mem)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
@@ -238,20 +230,20 @@ allocate_pages (grub_size_t prot_size)
mmap_buf = (void *) ((char *) real_mode_mem + real_size);
+ prot_mode_mem = (void *) 0x100000;
/* Next, find free pages for the protected mode code. */
/* XXX what happens if anything is using this address? */
- prot_mode_mem = grub_efi_allocate_pages (0x100000, prot_mode_pages);
- if (! prot_mode_mem)
+ if (grub_claimmap (0x100000, prot_size) < 0)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY,
"cannot allocate protected mode pages");
goto fail;
}
- grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, "
- "prot_mode_mem = %lx, prot_mode_pages = %x\n",
- (unsigned long) real_mode_mem, (unsigned) real_mode_pages,
- (unsigned long) prot_mode_mem, (unsigned) prot_mode_pages);
+ grub_dprintf ("linux", "real_mode_mem = %lx, real_size = %x, "
+ "prot_mode_mem = %lx, prot_size = %x\n",
+ (unsigned long) real_mode_mem, (unsigned) real_size,
+ (unsigned long) prot_mode_mem, (unsigned) prot_size);
grub_free (mmap);
return 1;
@@ -300,7 +292,6 @@ grub_linux_boot (void)
grub_efi_uintn_t map_key;
grub_efi_uintn_t desc_size;
grub_efi_uint32_t desc_version;
- grub_efi_memory_descriptor_t *desc;
int e820_num;
params = real_mode_mem;
@@ -318,77 +309,46 @@ grub_linux_boot (void)
&desc_size, &desc_version) <= 0)
grub_fatal ("cannot get memory map");
- e820_num = 0;
- for (desc = mmap_buf;
- desc < NEXT_MEMORY_DESCRIPTOR (mmap_buf, mmap_size);
- desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+ auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
+ int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
grub_uint32_t type)
{
- switch (desc->type)
- {
- case GRUB_EFI_ACPI_RECLAIM_MEMORY:
+ switch (type)
+ {
+ case GRUB_MACHINE_MEMORY_AVAILABLE:
grub_e820_add_region (params->e820_map, &e820_num,
- desc->physical_start,
- desc->num_pages << 12,
- GRUB_E820_ACPI);
+ addr, size, GRUB_E820_RAM);
break;
- case GRUB_EFI_ACPI_MEMORY_NVS:
+#ifdef GRUB_MACHINE_MEMORY_ACPI
+ case GRUB_MACHINE_MEMORY_ACPI:
grub_e820_add_region (params->e820_map, &e820_num,
- desc->physical_start,
- desc->num_pages << 12,
- GRUB_E820_NVS);
+ addr, size, GRUB_E820_ACPI);
break;
+#endif
- case GRUB_EFI_RUNTIME_SERVICES_CODE:
+#ifdef GRUB_MACHINE_MEMORY_NVS
+ case GRUB_MACHINE_MEMORY_NVS:
grub_e820_add_region (params->e820_map, &e820_num,
- desc->physical_start,
- desc->num_pages << 12,
- GRUB_E820_EXEC_CODE);
+ addr, size, GRUB_E820_NVS);
break;
+#endif
- case GRUB_EFI_LOADER_CODE:
- case GRUB_EFI_LOADER_DATA:
- case GRUB_EFI_BOOT_SERVICES_CODE:
- case GRUB_EFI_BOOT_SERVICES_DATA:
- case GRUB_EFI_CONVENTIONAL_MEMORY:
- {
- grub_uint64_t start, size, end;
-
- start = desc->physical_start;
- size = desc->num_pages << 12;
- end = start + size;
-
- /* Skip A0000 - 100000 region. */
- if ((start < 0x100000ULL) && (end > 0xA0000ULL))
- {
- if (start < 0xA0000ULL)
- {
- grub_e820_add_region (params->e820_map, &e820_num,
- start,
- 0xA0000ULL - start,
- GRUB_E820_RAM);
- }
-
- if (end <= 0x100000ULL)
- continue;
-
- start = 0x100000ULL;
- size = end - start;
- }
-
- grub_e820_add_region (params->e820_map, &e820_num,
- start, size, GRUB_E820_RAM);
- break;
- }
-
- default:
+#ifdef GRUB_MACHINE_MEMORY_CODE
+ case GRUB_MACHINE_MEMORY_CODE:
grub_e820_add_region (params->e820_map, &e820_num,
- desc->physical_start,
- desc->num_pages << 12,
- GRUB_E820_RESERVED);
- }
+ addr, size, GRUB_E820_EXEC_CODE);
+ break;
+#endif
+
+ default:
+ grub_e820_add_region (params->e820_map, &e820_num,
+ addr, size, GRUB_E820_RESERVED);
+ }
+ return 0;
}
+ e820_num = 0;
+ grub_machine_mmap_iterate (hook);
params->mmap_size = e820_num;
if (! grub_efi_exit_boot_services (map_key))
@@ -633,7 +593,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
struct linux_kernel_header lh;
struct linux_kernel_params *params;
grub_uint8_t setup_sects;
- grub_size_t real_size, prot_size;
grub_ssize_t len;
int i;
char *dest;
@@ -916,9 +875,6 @@ grub_cmd_initrd (grub_command_t cmd __attribute__
((unused)),
grub_ssize_t size;
grub_addr_t addr_min, addr_max;
grub_addr_t addr;
- grub_efi_uintn_t mmap_size;
- grub_efi_memory_descriptor_t *desc;
- grub_efi_uintn_t desc_size;
struct linux_kernel_header *lh;
if (argc == 0)
@@ -938,11 +894,24 @@ grub_cmd_initrd (grub_command_t cmd __attribute__
((unused)),
goto fail;
size = grub_file_size (file);
- initrd_pages = (page_align (size) >> 12);
+ initrd_size = page_align (size);
lh = (struct linux_kernel_header *) real_mode_mem;
+
+ /* Get the highest address available for the initrd. */
+ if (grub_le_to_cpu16 (lh->version) >= 0x0203)
+ {
+ addr_max = grub_cpu_to_le32 (lh->initrd_addr_max);
+
+ /* XXX in reality, Linux specifies a bogus value, so
+ it is necessary to make sure that ADDR_MAX does not exceed
+ 0x3fffffff. */
+ if (addr_max > GRUB_LINUX_INITRD_MAX_ADDRESS)
+ addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
+ }
+ else
+ addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
- addr_max = (grub_cpu_to_le32 (lh->initrd_addr_max) << 10);
if (linux_mem_size != 0 && linux_mem_size < addr_max)
addr_max = linux_mem_size;
@@ -953,49 +922,21 @@ grub_cmd_initrd (grub_command_t cmd __attribute__
((unused)),
addr_max -= 0x10000;
/* Usually, the compression ratio is about 50%. */
- addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12)
- + page_align (size);
+ addr_min = (grub_addr_t) prot_mode_mem + prot_size * 3
+ + page_align (size);
- /* Find the highest address to put the initrd. */
- mmap_size = find_mmap_size ();
- if (grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0) <= 0)
- grub_fatal ("cannot get memory map");
-
- addr = 0;
- for (desc = mmap_buf;
- desc < NEXT_MEMORY_DESCRIPTOR (mmap_buf, mmap_size);
- desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
- {
- if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
- && desc->num_pages >= initrd_pages)
- {
- grub_efi_physical_address_t physical_end;
-
- physical_end = desc->physical_start + (desc->num_pages << 12);
- if (physical_end > addr_max)
- physical_end = addr_max;
-
- if (physical_end < page_align (size))
- continue;
-
- physical_end -= page_align (size);
-
- if ((physical_end >= addr_min) &&
- (physical_end >= desc->physical_start) &&
- (physical_end > addr))
- addr = physical_end;
- }
- }
+ /* Put the initrd as high as possible, 4KiB aligned. */
+ addr = (addr_max - size) & ~0xFFF;
+ while (addr >= addr_min && grub_claimmap (addr, initrd_size) < 0)
+ addr -= 0x1000;
- if (addr == 0)
+ if (addr < addr_min)
{
- grub_error (GRUB_ERR_OUT_OF_MEMORY, "no free pages available");
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "The initrd is too big");
goto fail;
}
- initrd_mem = grub_efi_allocate_pages (addr, initrd_pages);
- if (! initrd_mem)
- grub_fatal ("cannot allocate pages");
+ initrd_mem = (void *) addr;
if (grub_file_read (file, initrd_mem, size) != size)
{
diff --git a/loader/i386/linux.c b/loader/i386/linux.c
index 01d10d5..4811f1a 100644
--- a/loader/i386/linux.c
+++ b/loader/i386/linux.c
@@ -45,9 +45,10 @@ static int loaded;
static void *real_mode_mem;
static void *prot_mode_mem;
static void *initrd_mem;
-static grub_uint32_t real_mode_pages;
-static grub_uint32_t prot_mode_pages;
-static grub_uint32_t initrd_pages;
+static grub_size_t real_size;
+static grub_size_t mmap_size;
+static grub_size_t prot_size;
+static grub_size_t initrd_size;
static grub_uint8_t gdt[] __attribute__ ((aligned(16))) =
{
@@ -182,7 +183,24 @@ find_mmap_size (void)
static void
free_pages (void)
{
- real_mode_mem = prot_mode_mem = initrd_mem = 0;
+ if (real_mode_mem)
+ {
+ grub_declaimmap ((grub_addr_t) real_mode_mem, real_size
+ + mmap_size);
+ real_mode_mem = 0;
+ }
+
+ if (prot_mode_mem)
+ {
+ grub_declaimmap ((grub_addr_t) prot_mode_mem, prot_size);
+ prot_mode_mem = 0;
+ }
+
+ if (initrd_mem)
+ {
+ grub_declaimmap ((grub_addr_t) initrd_mem, initrd_size);
+ initrd_mem = 0;
+ }
}
/* Allocate pages for the real mode code and the protected mode code
@@ -190,8 +208,6 @@ free_pages (void)
static int
allocate_pages (grub_size_t prot_size)
{
- grub_size_t real_size, mmap_size;
-
/* Make sure that each size is aligned to a page boundary. */
real_size = GRUB_LINUX_CL_END_OFFSET;
prot_size = page_align (prot_size);
@@ -200,11 +216,6 @@ allocate_pages (grub_size_t prot_size)
grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n",
(unsigned) real_size, (unsigned) prot_size, (unsigned)
mmap_size);
- /* Calculate the number of pages; Combine the real mode code with
- the memory map buffer for simplicity. */
- real_mode_pages = ((real_size + mmap_size) >> 12);
- prot_mode_pages = (prot_size >> 12);
-
/* Initialize the memory pointers with NULL for convenience. */
free_pages ();
@@ -232,6 +243,8 @@ allocate_pages (grub_size_t prot_size)
return 0;
real_mode_mem = (void *) ((addr + size) - (real_size + mmap_size));
+ if (grub_claimmap (real_mode_mem, real_size + mmap_size) < 0)
+ return 0;
return 1;
}
@@ -245,6 +258,14 @@ allocate_pages (grub_size_t prot_size)
}
prot_mode_mem = (void *) 0x100000;
+ /* Next, find free pages for the protected mode code. */
+ /* XXX what happens if anything is using this address? */
+ if (grub_claimmap (0x100000, prot_size) < 0)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY,
+ "cannot allocate protected mode pages");
+ goto fail;
+ }
grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, "
"prot_mode_mem = %lx, prot_mode_pages = %x\n",
@@ -396,6 +417,27 @@ grub_linux_boot (void)
addr, size, GRUB_E820_RAM);
break;
+#ifdef GRUB_MACHINE_MEMORY_ACPI
+ case GRUB_MACHINE_MEMORY_ACPI:
+ grub_e820_add_region (params->e820_map, &e820_num,
+ addr, size, GRUB_E820_ACPI);
+ break;
+#endif
+
+#ifdef GRUB_MACHINE_MEMORY_NVS
+ case GRUB_MACHINE_MEMORY_NVS:
+ grub_e820_add_region (params->e820_map, &e820_num,
+ addr, size, GRUB_E820_NVS);
+ break;
+#endif
+
+#ifdef GRUB_MACHINE_MEMORY_CODE
+ case GRUB_MACHINE_MEMORY_CODE:
+ grub_e820_add_region (params->e820_map, &e820_num,
+ addr, size, GRUB_E820_EXEC_CODE);
+ break;
+#endif
+
default:
grub_e820_add_region (params->e820_map, &e820_num,
addr, size, GRUB_E820_RESERVED);
@@ -457,7 +499,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
struct linux_kernel_header lh;
struct linux_kernel_params *params;
grub_uint8_t setup_sects;
- grub_size_t real_size, prot_size;
grub_ssize_t len;
int i;
char *dest;
@@ -693,7 +734,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__
((unused)),
goto fail;
size = grub_file_size (file);
- initrd_pages = (page_align (size) >> 12);
+ initrd_size = page_align (size);
lh = (struct linux_kernel_header *) real_mode_mem;
@@ -724,11 +765,10 @@ grub_cmd_initrd (grub_command_t cmd __attribute__
((unused)),
addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12)
+ page_align (size);
- if (addr_max > grub_os_area_addr + grub_os_area_size)
- addr_max = grub_os_area_addr + grub_os_area_size;
-
/* Put the initrd as high as possible, 4KiB aligned. */
addr = (addr_max - size) & ~0xFFF;
+ while (addr >= addr_min && grub_claimmap (addr, initrd_size) < 0)
+ addr -= 0x1000;
if (addr < addr_min)
{
diff --git a/loader/i386/multiboot.c b/loader/i386/multiboot.c
index 27042a5..055b1cf 100644
--- a/loader/i386/multiboot.c
+++ b/loader/i386/multiboot.c
@@ -30,7 +30,7 @@
#include <grub/loader.h>
#include <grub/machine/loader.h>
#include <grub/multiboot.h>
-#include <grub/machine/init.h>
+#include <grub/machine/machine.h>
#include <grub/machine/memory.h>
#include <grub/cpu/multiboot.h>
#include <grub/elf.h>
@@ -43,6 +43,13 @@
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/env.h>
+#include <grub/cpu/loader.h>
+#include <grub/cpu/multiboot.h>
+#include <grub/i386/uppermem.h>
+
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/efi.h>
+#endif
extern grub_dl_t my_mod;
static struct grub_multiboot_info *mbi, *mbi_dest;
@@ -54,6 +61,13 @@ static grub_size_t code_size;
static grub_err_t
grub_multiboot_boot (void)
{
+ grub_printf ("Boot\n");
+
+#ifdef GRUB_MACHINE_EFI
+ if (! grub_efi_finish_boot_services ())
+ grub_fatal ("cannot exit boot services");
+#endif
+
grub_multiboot_real_boot (entry, mbi_dest);
/* Not reached. */
@@ -109,14 +123,24 @@ grub_get_multiboot_mmap_len (void)
static void
grub_fill_multiboot_mmap (struct grub_multiboot_mmap_entry *first_entry)
{
- struct grub_multiboot_mmap_entry *mmap_entry = (struct
grub_multiboot_mmap_entry *) first_entry;
+ struct grub_multiboot_mmap_entry *mmap_entry
+ = (struct grub_multiboot_mmap_entry *) first_entry;
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
grub_uint32_t type)
{
mmap_entry->addr = addr;
mmap_entry->len = size;
- mmap_entry->type = type;
+ switch (type)
+ {
+ case GRUB_MACHINE_MEMORY_AVAILABLE:
+ mmap_entry->type = GRUB_MULTIBOOT_MEMORY_AVAILABLE;
+ break;
+
+ default:
+ mmap_entry->type = GRUB_MULTIBOOT_MEMORY_RESERVED;
+ break;
+ }
mmap_entry->size = sizeof (struct grub_multiboot_mmap_entry) - sizeof
(mmap_entry->size);
mmap_entry++;
@@ -199,6 +223,7 @@ grub_multiboot (int argc, char *argv[])
struct grub_multiboot_header *header;
grub_ssize_t len, cmdline_length, boot_loader_name_length;
grub_uint32_t mmap_length;
+ grub_uint64_t lower, upper;
int i;
grub_loader_unset ();
@@ -286,7 +311,9 @@ grub_multiboot (int argc, char *argv[])
grub_multiboot_payload_dest = header->load_addr;
grub_multiboot_payload_size += code_size;
- playground = grub_malloc (RELOCATOR_SIZEOF(forward) +
grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
+ playground = grub_malloc (RELOCATOR_SIZEOF(forward)
+ + grub_multiboot_payload_size
+ + RELOCATOR_SIZEOF(backward));
if (! playground)
goto fail;
@@ -341,9 +368,12 @@ grub_multiboot (int argc, char *argv[])
grub_multiboot_payload_size,
grub_multiboot_payload_entry_offset);
+ if (grub_get_lower_upper_memory (&lower, &upper))
+ goto fail;
+
/* Convert from bytes to kilobytes. */
- mbi->mem_lower = grub_lower_mem / 1024;
- mbi->mem_upper = grub_upper_mem / 1024;
+ mbi->mem_lower = lower / 1024;
+ mbi->mem_upper = upper / 1024;
mbi->flags |= MULTIBOOT_INFO_MEMORY;
cmdline = p = cmdline_addr (grub_multiboot_payload_orig);
@@ -370,7 +400,7 @@ grub_multiboot (int argc, char *argv[])
if (grub_multiboot_get_bootdev (&mbi->boot_device))
mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
- grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 1);
+ grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);
fail:
if (file)
diff --git a/loader/i386/pc/linux.c b/loader/i386/pc/linux.c
index 8ff97f4..4823ddc 100644
--- a/loader/i386/pc/linux.c
+++ b/loader/i386/pc/linux.c
@@ -71,11 +71,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (! file)
goto fail;
- if ((grub_size_t) grub_file_size (file) > grub_os_area_size)
+ if (grub_claimmap (GRUB_LINUX_BZIMAGE_ADDR, grub_file_size (file)) < 0)
{
- grub_error (GRUB_ERR_OUT_OF_RANGE, "too big kernel (0x%x > 0x%x)",
- (grub_size_t) grub_file_size (file),
- grub_os_area_size);
+ grub_error (GRUB_ERR_OUT_OF_RANGE, "too big kernel (0x%x)",
+ (grub_size_t) grub_file_size (file));
goto fail;
}
@@ -340,9 +339,6 @@ grub_cmd_initrd (grub_command_t cmd __attribute__
((unused)),
worse than that of Linux 2.3.xx, so avoid the last 64kb. */
addr_max -= 0x10000;
- if (addr_max > grub_os_area_addr + grub_os_area_size)
- addr_max = grub_os_area_addr + grub_os_area_size;
-
addr_min = (grub_addr_t) grub_linux_tmp_addr + GRUB_LINUX_CL_END_OFFSET;
file = grub_file_open (argv[0]);
@@ -353,6 +349,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__
((unused)),
/* Put the initrd as high as possible, 4KiB aligned. */
addr = (addr_max - size) & ~0xFFF;
+ while (addr >= addr_min && grub_claimmap (addr, size) < 0)
+ addr -= 0x1000;
if (addr < addr_min)
{
diff --git a/loader/i386/pc/multiboot2.c b/loader/i386/pc/multiboot2.c
index d5fe8e3..b065fa7 100644
--- a/loader/i386/pc/multiboot2.c
+++ b/loader/i386/pc/multiboot2.c
@@ -25,32 +25,6 @@
#include <grub/mm.h>
grub_err_t
-grub_mb2_arch_elf32_hook (Elf32_Phdr *phdr, UNUSED grub_addr_t *addr)
-{
- Elf32_Addr paddr = phdr->p_paddr;
-
- if ((paddr < grub_os_area_addr)
- || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size))
- return grub_error(GRUB_ERR_OUT_OF_RANGE,"Address 0x%x is out of range",
- paddr);
-
- return GRUB_ERR_NONE;
-}
-
-grub_err_t
-grub_mb2_arch_elf64_hook (Elf64_Phdr *phdr, UNUSED grub_addr_t *addr)
-{
- Elf64_Addr paddr = phdr->p_paddr;
-
- if ((paddr < grub_os_area_addr)
- || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size))
- return grub_error (GRUB_ERR_OUT_OF_RANGE, "Address 0x%x is out of range",
- paddr);
-
- return GRUB_ERR_NONE;
-}
-
-grub_err_t
grub_mb2_arch_module_alloc (grub_size_t size, grub_addr_t *addr)
{
grub_addr_t modaddr;
@@ -73,6 +47,7 @@ grub_mb2_arch_module_free (grub_addr_t addr, UNUSED
grub_size_t size)
void
grub_mb2_arch_boot (grub_addr_t entry, void *tags)
{
+ grub_stop_floppy ();
grub_multiboot2_real_boot (entry, tags);
}
diff --git a/loader/ieee1275/multiboot2.c b/loader/ieee1275/multiboot2.c
index c253fc9..462135b 100644
--- a/loader/ieee1275/multiboot2.c
+++ b/loader/ieee1275/multiboot2.c
@@ -31,41 +31,6 @@
typedef void (*kernel_entry_t) (unsigned long, void *, int (void *),
unsigned long, unsigned long);
-/* Claim the memory occupied by the multiboot kernel. */
-grub_err_t
-grub_mb2_arch_elf32_hook (Elf32_Phdr *phdr, UNUSED grub_addr_t *addr)
-{
- int rc;
-
- rc = grub_claimmap (phdr->p_paddr, phdr->p_memsz);
- if (rc)
- return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Couldn't claim %x - %x",
- phdr->p_paddr, phdr->p_paddr + phdr->p_memsz);
-
- grub_dprintf ("loader", "Loading segment at 0x%x - 0x%x\n", phdr->p_paddr,
- phdr->p_paddr + phdr->p_memsz);
-
- return GRUB_ERR_NONE;
-}
-
-/* Claim the memory occupied by the multiboot kernel. */
-grub_err_t
-grub_mb2_arch_elf64_hook (Elf64_Phdr *phdr, UNUSED grub_addr_t *addr)
-{
- int rc;
-
- rc = grub_claimmap (phdr->p_paddr, phdr->p_memsz);
- if (rc)
- return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Couldn't claim 0x%lx - 0x%lx",
- phdr->p_paddr, phdr->p_paddr + phdr->p_memsz);
-
- grub_dprintf ("loader", "Loading segment at 0x%lx - 0x%lx\n",
- (unsigned long) phdr->p_paddr,
- (unsigned long) (phdr->p_paddr + phdr->p_memsz));
-
- return GRUB_ERR_NONE;
-}
-
grub_err_t
grub_mb2_arch_module_alloc (grub_size_t size, grub_addr_t *addr)
{
diff --git a/loader/multiboot2.c b/loader/multiboot2.c
index 2fb56bf..a6cee06 100644
--- a/loader/multiboot2.c
+++ b/loader/multiboot2.c
@@ -38,6 +38,42 @@ static char *grub_mb2_tags_pos;
static grub_size_t grub_mb2_tags_len;
static int grub_mb2_tags_count;
+/* Claim the memory occupied by the multiboot kernel. */
+static grub_err_t
+grub_mb2_elf32_hook (Elf32_Phdr *phdr, UNUSED grub_addr_t *addr)
+{
+ int rc;
+
+ rc = grub_claimmap (phdr->p_paddr, phdr->p_memsz);
+ if (rc)
+ return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Couldn't claim %x - %x",
+ phdr->p_paddr, phdr->p_paddr + phdr->p_memsz);
+
+ grub_dprintf ("loader", "Loading segment at 0x%x - 0x%x\n", phdr->p_paddr,
+ phdr->p_paddr + phdr->p_memsz);
+
+ return GRUB_ERR_NONE;
+}
+
+/* Claim the memory occupied by the multiboot kernel. */
+static grub_err_t
+grub_mb2_elf64_hook (Elf64_Phdr *phdr, UNUSED grub_addr_t *addr)
+{
+ int rc;
+
+ rc = grub_claimmap (phdr->p_paddr, phdr->p_memsz);
+ if (rc)
+ return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Couldn't claim 0x%lx - 0x%lx",
+ phdr->p_paddr, phdr->p_paddr + phdr->p_memsz);
+
+ grub_dprintf ("loader", "Loading segment at 0x%lx - 0x%lx\n",
+ (unsigned long) phdr->p_paddr,
+ (unsigned long) (phdr->p_paddr + phdr->p_memsz));
+
+ return GRUB_ERR_NONE;
+}
+
+
static void
grub_mb2_tags_free (void)
{
@@ -279,13 +315,13 @@ grub_mb2_load_elf (grub_elf_t elf, int argc, char *argv[])
if (grub_elf_is_elf32 (elf))
{
entry = elf->ehdr.ehdr32.e_entry;
- err = grub_elf32_load (elf, grub_mb2_arch_elf32_hook, &kern_base,
+ err = grub_elf32_load (elf, grub_mb2_elf32_hook, &kern_base,
&kern_size);
}
else if (grub_elf_is_elf64 (elf))
{
entry = elf->ehdr.ehdr64.e_entry;
- err = grub_elf64_load (elf, grub_mb2_arch_elf64_hook, &kern_base,
+ err = grub_elf64_load (elf, grub_mb2_elf64_hook, &kern_base,
&kern_size);
}
else
diff --git a/loader/multiboot_loader.c b/loader/multiboot_loader.c
index f4a3933..6c30d5a 100644
--- a/loader/multiboot_loader.c
+++ b/loader/multiboot_loader.c
@@ -137,9 +137,7 @@ grub_cmd_multiboot_loader (grub_command_t cmd __attribute__
((unused)),
/* Launch multi boot with header */
- /* XXX Find a better way to identify this.
- This is for i386-pc */
-#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_LINUXBIOS)
+#if defined(__i386__)
if (header_multi_ver_found == 1)
{
grub_dprintf ("multiboot_loader",
@@ -152,7 +150,9 @@ grub_cmd_multiboot_loader (grub_command_t cmd __attribute__
((unused)),
{
grub_dprintf ("multiboot_loader",
"Launching multiboot 2 grub_multiboot2() function\n");
+#ifndef GRUB_MACHINE_EFI
grub_multiboot2 (argc, argv);
+#endif
module_version_status = 2;
}
@@ -172,7 +172,7 @@ grub_cmd_module_loader (grub_command_t cmd __attribute__
((unused)),
int argc, char *argv[])
{
-#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_LINUXBIOS)
+#if defined(__i386__)
if (module_version_status == 1)
{
grub_dprintf("multiboot_loader",
@@ -184,7 +184,9 @@ grub_cmd_module_loader (grub_command_t cmd __attribute__
((unused)),
{
grub_dprintf("multiboot_loader",
"Launching multiboot 2 grub_module2() function\n");
+#ifndef GRUB_MACHINE_EFI
grub_module2 (argc, argv);
+#endif
}
return grub_errno;
Re: multiboot module in grub2 --with-platform=efi --target=i386, uzer cheg, 2009/04/14