From: phcoder <phcoder@gmail.com>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: Re: multiboot module in grub2 --with-platform=efi --target=i386
Date: Tue, 14 Apr 2009 11:12:41 +0200 [thread overview]
Message-ID: <49E45389.8040301@gmail.com> (raw)
In-Reply-To: <63BFAF74-73DE-4AB9-9243-FB54293863C8@mac.com>
[-- Attachment #1: Type: text/plain, Size: 1838 bytes --]
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
>> Grub-devel@gnu.org
>> http://lists.gnu.org/mailman/listinfo/grub-devel
>
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
--
Regards
Vladimir 'phcoder' Serbinenko
[-- Attachment #2: efiboot.diff --]
[-- Type: text/x-patch, Size: 66592 bytes --]
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;
next prev parent reply other threads:[~2009-04-14 9:12 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <fd8d61830903180608l2ad4b32ag8122fbc748c64515@mail.gmail.com>
2009-03-18 13:22 ` multiboot module in grub2 --with-platform=efi --target=i386 uzer cheg
2009-03-18 13:38 ` phcoder
2009-03-18 13:54 ` uzer cheg
2009-03-18 14:09 ` phcoder
2009-03-18 14:15 ` uzer cheg
2009-03-18 14:58 ` phcoder
2009-04-14 8:22 ` Drew Rosen
2009-04-14 9:12 ` phcoder [this message]
2009-04-15 13:58 ` Drew Rosen
2009-04-15 15:24 ` Bean
2009-04-15 16:23 ` multiboot module in grub2 --with-platform=efi --target=i386 - TestingOnXserve Drew Rosen
2009-04-15 17:15 ` Bean
2009-04-14 20:31 ` multiboot module in grub2 --with-platform=efi --target=i386 uzer cheg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=49E45389.8040301@gmail.com \
--to=phcoder@gmail.com \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.