From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1Lq95R-0000od-7b for mharc-grub-devel@gnu.org; Sat, 04 Apr 2009 12:51:17 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Lq95N-0000l3-JO for grub-devel@gnu.org; Sat, 04 Apr 2009 12:51:13 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Lq95I-0000kn-Ty for grub-devel@gnu.org; Sat, 04 Apr 2009 12:51:13 -0400 Received: from [199.232.76.173] (port=57547 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Lq95I-0000kk-OE for grub-devel@gnu.org; Sat, 04 Apr 2009 12:51:08 -0400 Received: from mail-fx0-f166.google.com ([209.85.220.166]:58747) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Lq95G-0000Ha-Mx for grub-devel@gnu.org; Sat, 04 Apr 2009 12:51:08 -0400 Received: by fxm10 with SMTP id 10so1420348fxm.42 for ; Sat, 04 Apr 2009 09:51:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from :user-agent:mime-version:to:subject:references:in-reply-to :content-type; bh=Hkuni5I32fWjcPiKGRdeYj+US65937LrS5l+6GzHkqs=; b=hiSloJMiA0WLIPAW4z2/sc+Tyo4P9DmnYX6NoXauuBxKRQxGm+5xtOkHgAsJlaZjVg o8lLCgwmP0m5JpV8Z2GR/Ry02xALvnwFcczewOWwpRKHzH6QsOkBno5jDIZ3N23W3fbl LqCwUQ2S9TgR+YsV4oH6wmzYo1+yGO/9K4gic= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:subject:references :in-reply-to:content-type; b=v8xcvEsWpPvHCrSxDwQ0lIW+QIWHQKMGiaa/lbcpJSB5EGNZ4S6o3jyFWcpsLwUYBh aM2Jt+ddCtaN3kBAICc0ExBqSUES23T1gFGGJkfyhKJHL4lazOs7gsXlUCVOvBLMolFj Tl9unWnHoZXua6y+NL7Cw9LelMpAteK9K7oKc= Received: by 10.86.79.12 with SMTP id c12mr1815294fgb.64.1238863865401; Sat, 04 Apr 2009 09:51:05 -0700 (PDT) Received: from ?192.168.1.2? (5-181.3-85.cust.bluewin.ch [85.3.181.5]) by mx.google.com with ESMTPS id l12sm5129922fgb.1.2009.04.04.09.51.03 (version=SSLv3 cipher=RC4-MD5); Sat, 04 Apr 2009 09:51:04 -0700 (PDT) Message-ID: <49D78FF8.4090807@gmail.com> Date: Sat, 04 Apr 2009 18:51:04 +0200 From: phcoder User-Agent: Thunderbird 2.0.0.21 (X11/20090318) MIME-Version: 1.0 To: The development of GRUB 2 References: <49C780C3.4010403@gmail.com> <20090328131306.GB8493@thorin> <49CEA5CC.1000301@gmail.com> <49D78AB0.3040803@gmail.com> In-Reply-To: <49D78AB0.3040803@gmail.com> Content-Type: multipart/mixed; boundary="------------090206050108090506040703" X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 2) Subject: Re: multiboot on EFI X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GRUB 2 List-Id: The development of GRUB 2 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Apr 2009 16:51:13 -0000 This is a multi-part message in MIME format. --------------090206050108090506040703 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit File was empty. Sorry phcoder wrote: > For those interested in testing: here is a rediff and some updates. Soon > I'll split it into components > phcoder wrote: >> Robert Millan wrote: >>> Would it be hard to split the patch and make it more granular? I see it >>> implements base mmap / lsmmap support on efi, then ports the *BSD >>> loaders >>> and the Multiboot loader too, and the uppermem facility. >> The only reason why it's not splitted is that it's totally "preview". >> When it'll be more ready I'll split it >>> If everybody's fine with it, I'd like to suggest adding stuff to >>> pkglib_MODULES >>> in the same place as its corresponding variables. I've done this >>> already a few >>> times, and I think it makes the build system a bit more >>> maintainable. What do >>> you all think about this? >> >> I also agree with this but I temporarily kept this in >> architecture-specific file because of some minor problems with >> multiboot2. I'll fix this too >> >>> >>>> 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)); >>> >>> Do we need specific knowledge of these two on i386-pc ? >>> >> This one is because some loaders just copy e820 map types and I don't >> want to modify what OS gets on i386-pc >>>> /* 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) >>> >>> Is 1600 MB what we want, or to remove the limit? >>> >> I would suggest to remove the limit altogether >>>> + /* 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; >>>> + } >>>> + } >>> >>> Do we need the memory map to be sorted? AFAIK loadees can cope with >>> unsorted >>> maps fine; is there an exception? >>> >> I prefer to sort. Even as just a precaution. Actually even sorted EFI >> map may break a lot of OS because it usually has more entries (the >> runtime code isn't guaranteed to be contiguous and if it isn't it >> results in mmap having a lot of entries) and sometimes the first N >> kilobytes are defined as unusable (it's the case with qemu-tianocore) >> which under current definition means that low_memory=0 >>>> +#ifdef GRUB_MACHINE_PCBIOS >>>> + grub_stop_floppy (); >>>> +#endif >>> >>> grub_stop_floppy() doesn't do any BIOS-specific stuff. Wouldn't >>> __i386__ >>> be more appropiate? >>> >> I've already moved it to machine_fini just because my computer died I >> couldn't send the new patch >> > > -- Regards Vladimir 'phcoder' Serbinenko --------------090206050108090506040703 Content-Type: text/x-diff; name="efiboot.all.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="efiboot.all.diff" diff --git a/conf/common.rmk b/conf/common.rmk index 43bc683..b812d8b 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -503,3 +503,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 53595de..ab4dc4f 100644 --- a/conf/i386-coreboot.rmk +++ b/conf/i386-coreboot.rmk @@ -99,8 +99,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 @@ -198,10 +197,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 18a99df..6de450e 100644 --- a/conf/i386-efi.rmk +++ b/conf/i386-efi.rmk @@ -79,7 +79,18 @@ 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 + datetime.mod date.mod datehook.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 @@ -89,14 +100,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 a84b5aa..a06f97d 100644 --- a/conf/i386-ieee1275.rmk +++ b/conf/i386-ieee1275.rmk @@ -102,7 +102,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 @@ -127,6 +127,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 @@ -199,10 +200,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 7fa1975..405048f 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -287,16 +287,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) @@ -352,11 +342,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 9ba2981..bcb2e76 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -110,8 +110,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 @@ -166,10 +165,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 +#include + +#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 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 628d888..448fed5 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 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +#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 e88f3b3..27f8293 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 . + */ + +#ifndef EFIEMU +#include +#include +#endif + +#include +#include + +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 . + */ + +#include +#include +#include +#include +#include +#include + +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 #include #include -#include #include +#include #include #include #include @@ -30,8 +30,13 @@ #include #include #include +#include #include +#ifdef GRUB_MACHINE_EFI +#include +#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 . + */ + + +/* + * 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 + +/* + * 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 d8c6a67..7cc13d3 100644 --- a/loader/i386/efi/linux.c +++ b/loader/i386/efi/linux.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -45,9 +46,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))) = @@ -94,26 +96,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) @@ -121,14 +123,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 @@ -136,19 +138,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; } } @@ -160,9 +162,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; @@ -172,11 +173,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; @@ -191,44 +187,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"); @@ -237,20 +229,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; @@ -350,7 +342,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; fake_bios_data (); @@ -370,77 +361,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) + switch (type) { - case GRUB_EFI_ACPI_RECLAIM_MEMORY: - grub_e820_add_region (params->e820_map, &e820_num, - desc->physical_start, - desc->num_pages << 12, - GRUB_E820_ACPI); - break; + case GRUB_MACHINE_MEMORY_AVAILABLE: + grub_e820_add_region (params->e820_map, &e820_num, + addr, size, GRUB_E820_RAM); + break; - case GRUB_EFI_ACPI_MEMORY_NVS: - grub_e820_add_region (params->e820_map, &e820_num, - desc->physical_start, - desc->num_pages << 12, - GRUB_E820_NVS); - 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 - case GRUB_EFI_RUNTIME_SERVICES_CODE: - grub_e820_add_region (params->e820_map, &e820_num, - desc->physical_start, - desc->num_pages << 12, - GRUB_E820_EXEC_CODE); - 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: - { - 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; - } +#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, - desc->physical_start, - desc->num_pages << 12, - GRUB_E820_RESERVED); + 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)) @@ -617,7 +577,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; @@ -908,9 +867,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) @@ -930,11 +886,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; @@ -945,49 +914,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) + 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 a2fff83..daff376 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. */ real_mode_mem = 0; prot_mode_mem = 0; @@ -233,6 +244,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; } @@ -246,6 +259,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", @@ -395,6 +416,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; @@ -690,7 +731,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; @@ -721,11 +762,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 #include #include -#include +#include #include #include #include @@ -43,6 +43,13 @@ #include #include #include +#include +#include +#include + +#ifdef GRUB_MACHINE_EFI +#include +#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_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; --------------090206050108090506040703--