diff --git a/conf/common.rmk b/conf/common.rmk index 100fae7..e64a1a4 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -507,3 +507,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 6f4e8f3..1304eb3 100644 --- a/conf/i386-coreboot.rmk +++ b/conf/i386-coreboot.rmk @@ -102,8 +102,7 @@ pkglib_MODULES = _linux.mod linux.mod normal.mod \ _multiboot.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 @@ -211,10 +210,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 a2454d9..4303b1c 100644 --- a/conf/i386-efi.rmk +++ b/conf/i386-efi.rmk @@ -80,7 +80,20 @@ grub_install_SOURCES = util/i386/efi/grub-install.in # Modules. pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \ _linux.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 multiboot.mod + +# For _multiboot.mod. +_multiboot_mod_SOURCES = loader/i386/multiboot.c \ + loader/i386/multiboot_helper.S \ + loader/multiboot_loader.c +_multiboot_mod_CFLAGS = $(COMMON_CFLAGS) +_multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) +_multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS) + +# For multiboot.mod. +multiboot_mod_SOURCES = loader/multiboot_loader_normal.c +multiboot_mod_CFLAGS = $(COMMON_CFLAGS) +multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) # For kernel.mod. kernel_mod_EXPORTS = no @@ -90,14 +103,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/efi/mmap.c kern/time.c kern/list.c kern/handler.c \ kern/i386/tsc.c kern/i386/pit.c \ kern/generic/rtc_get_time_ms.c \ kern/generic/millisleep.c kernel_mod_HEADERS = arg.h 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 + efi/efi.h efi/time.h efi/disk.h efi/memory.h list.h handler.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 305b31d..460dfdd 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 _multiboot.mod aout.mod serial.mod linux.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 @@ -209,10 +209,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 e1ed9aa..0be2729 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -178,8 +178,8 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \ _multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod \ vbe.mod vbetest.mod vbeinfo.mod play.mod serial.mod \ ata.mod vga.mod memdisk.mod pci.mod lspci.mod \ - aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod datetime.mod date.mod \ - datehook.mod lsmmap.mod ata_pthru.mod hdparm.mod \ + pxe.mod pxecmd.mod datetime.mod date.mod \ + datehook.mod ata_pthru.mod hdparm.mod \ usb.mod uhci.mod ohci.mod usbtest.mod usbms.mod usb_keyboard.mod \ efiemu.mod efiemu_acpi.mod efiemu_pnvram.mod @@ -318,21 +318,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 bsd.mod -bsd_mod_SOURCES = loader/i386/bsd_normal.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) @@ -388,11 +373,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 4e86ed8..5338457 100644 --- a/conf/i386.rmk +++ b/conf/i386.rmk @@ -19,3 +19,21 @@ 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 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) + +# For bsd.mod +bsd_mod_SOURCES = loader/i386/bsd_normal.c +bsd_mod_CFLAGS = $(COMMON_CFLAGS) +bsd_mod_LDFLAGS = $(COMMON_LDFLAGS) + diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index 66d1d58..c9e185a 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -112,8 +112,7 @@ pkglib_MODULES = halt.mod \ suspend.mod \ _multiboot.mod \ multiboot.mod \ - memdisk.mod \ - lsmmap.mod + memdisk.mod # For _linux.mod. _linux_mod_SOURCES = loader/powerpc/ieee1275/linux.c @@ -178,10 +177,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 00296c9..e8bed00 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; }; @@ -229,4 +231,7 @@ void grub_rescue_cmd_netbsd (int argc, char *argv[]); void grub_rescue_cmd_freebsd_loadenv (int argc, char *argv[]); void grub_rescue_cmd_freebsd_module (int argc, char *argv[]); +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 f858c0a..cb2f918 100644 --- a/include/grub/i386/loader.h +++ b/include/grub/i386/loader.h @@ -32,9 +32,6 @@ extern grub_size_t EXPORT_VAR(grub_os_area_size); grub_err_t EXPORT_FUNC(grub_linux_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[]); diff --git a/include/grub/i386/multiboot.h b/include/grub/i386/multiboot.h index ea68640..85405dc 100644 --- a/include/grub/i386/multiboot.h +++ b/include/grub/i386/multiboot.h @@ -22,7 +22,7 @@ /* 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)); 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/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..11fbc72 --- /dev/null +++ b/kern/efi/mmap.c @@ -0,0 +1,158 @@ +/* + * 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 + +#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; +} diff --git a/kern/i386/loader.S b/kern/i386/loader.S index fc27b86..f1b6c18 100644 --- a/kern/i386/loader.S +++ b/kern/i386/loader.S @@ -117,27 +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) - call EXT_C(grub_stop_floppy) - - /* 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/bsd.c b/loader/i386/bsd.c index 25d0f59..712b013 100644 --- a/loader/i386/bsd.c +++ b/loader/i386/bsd.c @@ -19,8 +19,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -31,6 +31,11 @@ #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,10 +510,10 @@ 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) + /* 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); + paddr);*/ if ((!kern_start) || (paddr < kern_start)) kern_start = paddr; @@ -577,7 +626,7 @@ grub_rescue_cmd_freebsd (int argc, char *argv[]) (grub_freebsd_add_meta_module (1, argc, argv, kern_start, kern_end - kern_start))) return; - grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 1); + grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 0); } } @@ -589,7 +638,7 @@ grub_rescue_cmd_openbsd (int argc, char *argv[]) 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); } void @@ -600,7 +649,7 @@ grub_rescue_cmd_netbsd (int argc, char *argv[]) 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); } void @@ -718,11 +767,11 @@ grub_rescue_cmd_freebsd_module (int argc, char *argv[]) if ((!file) || (!file->size)) goto fail; - if (kern_end + file->size > grub_os_area_addr + grub_os_area_size) + /* if (kern_end + file->size > grub_os_area_addr + grub_os_area_size) { grub_error (GRUB_ERR_OUT_OF_RANGE, "Not enough memory for the module"); goto fail; - } + }*/ grub_file_read (file, (char *) kern_end, file->size); if ((!grub_errno) && 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/multiboot.c b/loader/i386/multiboot.c index ff758d1..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,7 +61,12 @@ static grub_size_t code_size; static grub_err_t grub_multiboot_boot (void) { - grub_stop_floppy (); + 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); @@ -111,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++; @@ -201,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 (); @@ -288,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; @@ -343,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); @@ -372,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/multiboot_helper.S b/loader/i386/multiboot_helper.S index 1e71120..cd07246 100644 --- a/loader/i386/multiboot_helper.S +++ b/loader/i386/multiboot_helper.S @@ -52,7 +52,7 @@ VARIABLE(grub_multiboot_forward_relocator) cld rep movsb - + jmp *%edx VARIABLE(grub_multiboot_forward_relocator_end) @@ -91,7 +91,7 @@ FUNCTION(grub_multiboot_real_boot) /* Move the magic value into eax. */ movl $MULTIBOOT_MAGIC2, %eax - + /* Jump to the relocator. */ popl %ebp jmp *%ebp diff --git a/loader/i386/xnu_helper.S b/loader/i386/xnu_helper.S index 901be68..a83bd9a 100644 --- a/loader/i386/xnu_helper.S +++ b/loader/i386/xnu_helper.S @@ -15,6 +15,9 @@ FUNCTION(grub_xnu_launch) jmp cont1 cont1: lgdt gdtdesc + + jmp cont2 +cont2: .code32 @@ -28,8 +31,8 @@ cont1: and $0xffffffef, %eax wrmsr - jmp cont2 -cont2: + jmp cont3 +cont3: #endif .code32 diff --git a/loader/multiboot_loader.c b/loader/multiboot_loader.c index abcad9b..8abce88 100644 --- a/loader/multiboot_loader.c +++ b/loader/multiboot_loader.c @@ -140,7 +140,7 @@ grub_rescue_cmd_multiboot_loader (int argc, char *argv[]) /* XXX Find a better way to identify this. This is for i386-pc */ -#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_LINUXBIOS) +#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_LINUXBIOS) || defined (GRUB_MACHINE_EFI) if (header_multi_ver_found == 1) { grub_dprintf ("multiboot_loader", @@ -153,7 +153,9 @@ grub_rescue_cmd_multiboot_loader (int argc, char *argv[]) { grub_dprintf ("multiboot_loader", "Launching multiboot 2 grub_multiboot2() function\n"); +#ifndef GRUB_MACHINE_EFI grub_multiboot2 (argc, argv); +#endif module_version_status = 2; } @@ -170,7 +172,7 @@ void grub_rescue_cmd_module_loader (int argc, char *argv[]) { -#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_LINUXBIOS) +#if defined(GRUB_MACHINE_PCBIOS) || defined(GRUB_MACHINE_LINUXBIOS) || defined(GRUB_MACHINE_EFI) if (module_version_status == 1) { grub_dprintf("multiboot_loader", @@ -182,7 +184,9 @@ grub_rescue_cmd_module_loader (int argc, char *argv[]) { grub_dprintf("multiboot_loader", "Launching multiboot 2 grub_module2() function\n"); +#ifndef GRUB_MACHINE_EFI grub_module2 (argc, argv); +#endif } }