From 3bf12b31c577306f5963518298b8d9e524242a7c Mon Sep 17 00:00:00 2001 From: "James McKenzie james.mckenzie@citrix.com" Date: Wed, 13 Apr 2011 10:58:27 +0100 Subject: [PATCH 1/1] From XC trunk Apr 13 2011 --- master/legacy | 472 +++++++++++++++++++ master/series | 2 + master/xen | 1201 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1675 insertions(+) create mode 100644 master/legacy create mode 100644 master/series create mode 100644 master/xen diff --git a/master/legacy b/master/legacy new file mode 100644 index 0000000..db0d2bd --- /dev/null +++ b/master/legacy @@ -0,0 +1,472 @@ +Index: grub2/conf/i386-efi.rmk +=================================================================== +--- grub2.orig/conf/i386-efi.rmk ++++ grub2/conf/i386-efi.rmk +@@ -85,7 +85,7 @@ grub_install_SOURCES = util/i386/efi/gru + pkglib_MODULES = kernel.mod chain.mod appleldr.mod \ + linux.mod halt.mod reboot.mod pci.mod lspci.mod \ + datetime.mod date.mod datehook.mod loadbios.mod \ +- fixvideo.mod mmap.mod acpi.mod ++ fixvideo.mod mmap.mod acpi.mod legacy.mod + + # For kernel.mod. + kernel_mod_EXPORTS = no +@@ -183,6 +183,11 @@ date_mod_SOURCES = commands/date.c + date_mod_CFLAGS = $(COMMON_CFLAGS) + date_mod_LDFLAGS = $(COMMON_LDFLAGS) + ++# For legacy.mod ++legacy_mod_SOURCES = loader/efi/legacy.c ++legacy_mod_CFLAGS = $(COMMON_CFLAGS) ++legacy_mod_LDFLAGS = $(COMMON_LDFLAGS) ++ + # For datehook.mod + datehook_mod_SOURCES = hook/datehook.c + datehook_mod_CFLAGS = $(COMMON_CFLAGS) +Index: grub2/conf/x86_64-efi.rmk +=================================================================== +--- grub2.orig/conf/x86_64-efi.rmk ++++ grub2/conf/x86_64-efi.rmk +@@ -82,7 +82,7 @@ grub_install_SOURCES = util/i386/efi/gru + pkglib_MODULES = kernel.mod chain.mod appleldr.mod \ + halt.mod reboot.mod linux.mod pci.mod lspci.mod \ + datetime.mod date.mod datehook.mod loadbios.mod \ +- fixvideo.mod mmap.mod acpi.mod ++ fixvideo.mod mmap.mod acpi.mod legacy.mod + + # For kernel.mod. + kernel_mod_EXPORTS = no +@@ -176,6 +176,11 @@ datetime_mod_SOURCES = lib/efi/datetime. + datetime_mod_CFLAGS = $(COMMON_CFLAGS) + datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) + ++# For legacy.mod ++legacy_mod_SOURCES = loader/efi/legacy.c ++legacy_mod_CFLAGS = $(COMMON_CFLAGS) ++legacy_mod_LDFLAGS = $(COMMON_LDFLAGS) ++ + # For date.mod + date_mod_SOURCES = commands/date.c + date_mod_CFLAGS = $(COMMON_CFLAGS) +Index: grub2/loader/efi/legacy.c +=================================================================== +--- /dev/null ++++ grub2/loader/efi/legacy.c +@@ -0,0 +1,417 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2003,2007 Free Software Foundation, Inc. ++ * Copyright (C) 2003 NIIBE Yutaka ++ * ++ * 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 ++#include ++ ++static grub_efi_guid_t loaded_image_guid = GRUB_EFI_LOADED_IMAGE_GUID; ++ ++ ++#if 0 ++#define GRUB_EFI_SET_DEVICE_PATH_END_NODE(a) { \ ++ (a)->type = GRUB_EFI_END_DEVICE_PATH_TYPE; \ ++ (a)->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; \ ++ (a)->length[0] = sizeof(grub_efi_device_path_t); \ ++ (a)->length[1] = 0; \ ++ } ++static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID; ++ ++ ++ ++ ++grub_efi_uintn_t grub_efi_device_path_size(grub_efi_device_path_t *devpath); ++grub_efi_device_path_t *grub_efi_duplicate_device_path(grub_efi_device_path_t *devpath); ++grub_efi_device_path_t *grub_efi_device_path_instance(grub_efi_device_path_t **device_path, grub_efi_uintn_t *size); ++grub_efi_status_t grub_efi_connect_device_path (grub_efi_device_path_t *device_path_to_connect); ++ ++ ++grub_efi_uintn_t grub_efi_device_path_size(grub_efi_device_path_t *devpath) ++{ ++grub_efi_device_path_t *start; ++ ++start=devpath; ++while (!GRUB_EFI_END_ENTIRE_DEVICE_PATH(devpath)) ++ devpath=GRUB_EFI_NEXT_DEVICE_PATH(devpath); ++ ++return ((grub_efi_uintn_t) devpath -(grub_efi_uintn_t) start)+sizeof(grub_efi_device_path_t); ++} ++ ++ ++grub_efi_device_path_t *grub_efi_duplicate_device_path(grub_efi_device_path_t *devpath) ++{ ++grub_efi_device_path_t *new_device_path; ++grub_efi_uintn_t size; ++ ++size=grub_efi_device_path_size(devpath); ++new_device_path=grub_malloc(size); ++if (new_device_path) { ++grub_memcpy(new_device_path,devpath,size); ++} ++ ++return new_device_path; ++} ++ ++ ++grub_efi_device_path_t *grub_efi_device_path_instance(grub_efi_device_path_t **device_path, ++ grub_efi_uintn_t *size) ++{ ++ grub_efi_device_path_t *start, *next, *devpath; ++ grub_efi_uintn_t count; ++ ++ devpath = *device_path; ++ start = devpath; ++ ++ if (!devpath) { ++ return NULL; ++ } ++ ++ // ++ // Check for end of device path type ++ // ++ ++ for (count = 0; ; count++) { ++ next=GRUB_EFI_NEXT_DEVICE_PATH(devpath); ++ ++ if (GRUB_EFI_DEVICE_PATH_TYPE(devpath)==GRUB_EFI_END_DEVICE_PATH_TYPE) ++ break; ++ ++ if (count > 01000) { ++ // ++ // BugBug: Debug code to catch bogus device paths ++ // ++ grub_printf("device_pathInstance: device_path %p Size %d", *device_path, (int) (((grub_uint8_t *) devpath) - ((grub_uint8_t *) start) )); ++// DumpHex (0, 0, ((grub_uint8_t *) devpath) - ((grub_uint8_t *) start), start); ++ break; ++ } ++ ++ devpath = next; ++ } ++ ++ // ++ // Set next position ++ // ++ ++ if (GRUB_EFI_DEVICE_PATH_SUBTYPE(devpath) == GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE) ++ next = NULL; ++ ++ *device_path = next; ++ ++ // ++ // Return size and start of device path instance ++ // ++ ++ *size = ((grub_uint8_t *) devpath) - ((grub_uint8_t *) start); ++ return start; ++} ++ ++ ++ ++ ++grub_efi_status_t grub_efi_connect_device_path (grub_efi_device_path_t *device_path_to_connect) ++/*++ ++ ++Routine Description: ++ This function will create all handles associate with every device ++ path node. If the handle associate with one device path node can not ++ be created success, then still give one chance to do the dispatch, ++ which load the missing drivers if possible. ++ ++Arguments: ++ ++ device_path_to_connect - The device path which will be connected, it can ++ be a multi-instance device path ++ ++Returns: ++ ++ EFI_SUCCESS - All handles associate with every device path ++ node have been created ++ ++ EFI_OUT_OF_RESOURCES - There is no resource to create new handles ++ ++ EFI_NOT_FOUND - Create the handle associate with one device ++ path node failed ++ ++--*/ ++{ ++ grub_efi_status_t status; ++ grub_efi_device_path_t *device_path; ++ grub_efi_device_path_t *copy_of_device_path; ++ grub_efi_device_path_t *instance; ++ grub_efi_device_path_t *remaining_device_path; ++ grub_efi_device_path_t *next; ++ grub_efi_handle_t handle; ++ grub_efi_handle_t previous_handle; ++ grub_efi_uintn_t size; ++ grub_efi_boot_services_t *b; ++ ++ b = grub_efi_system_table->boot_services; ++ ++ if (device_path_to_connect == NULL) { ++ return GRUB_EFI_SUCCESS; ++ } ++ ++ device_path = grub_efi_duplicate_device_path (device_path_to_connect); ++ copy_of_device_path = device_path; ++ ++ if (device_path == NULL) { ++ return GRUB_EFI_OUT_OF_RESOURCES; ++ } ++ ++ do { ++ // ++ // The outer loop handles multi instance device paths. ++ // Only console variables contain multiple instance device paths. ++ // ++ // After this call device_path points to the next instance ++ // ++ instance = grub_efi_device_path_instance (&device_path, &size); ++ next = instance; ++ while (GRUB_EFI_DEVICE_PATH_TYPE(next)!=GRUB_EFI_END_DEVICE_PATH_TYPE) { ++ next=GRUB_EFI_NEXT_DEVICE_PATH(next); ++ } ++ ++ GRUB_EFI_SET_DEVICE_PATH_END_NODE(next); ++ ++ // ++ // start the real work of connect with remaining_device_path ++ // ++ previous_handle = NULL; ++ do { ++ // ++ // Find the handle that best matches the Device Path. If it is only a ++ // partial match the remaining part of the device path is returned in ++ // remaining_device_path. ++ // ++ remaining_device_path = instance; ++ status = efi_call_3(b->locate_device_path,&device_path_guid, &remaining_device_path, &handle); ++ ++ if (status==GRUB_EFI_SUCCESS) { ++ if (handle == previous_handle) { ++ // ++ // If no forward progress is made try invoking the Dispatcher. ++ // A new FV may have been added to the system an new drivers ++ // may now be found. ++ // status == EFI_SUCCESS means a driver was dispatched ++ // status == EFI_NOT_FOUND means no new drivers were dispatched ++ // ++ grub_printf("would have invoked the dispatcher\n"); ++ status = GRUB_EFI_NOT_FOUND; ++ } ++ ++ if (status==GRUB_EFI_SUCCESS) { ++ previous_handle = handle; ++ // ++ // Connect all drivers that apply to handle and remaining_device_path, ++ // the Recursive flag is FALSE so only one level will be expanded. ++ // ++ // Do not check the connect status here, if the connect controller fail, ++ // then still give the chance to do dispatch, because partial ++ // RemainingDevicepath may be in the new FV ++ // ++ // 1. If the connect fail, RemainingDevicepath and handle will not ++ // change, so next time will do the dispatch, then dispatch's status ++ // will take effect ++ // 2. If the connect success, the RemainingDevicepath and handle will ++ // change, then avoid the dispatch, we have chance to continue the ++ // next connection ++ // ++ efi_call_4(b->connect_controller,handle,NULL, remaining_device_path, 0); ++ } ++ } ++ // ++ // Loop until remaining_device_path is an empty device path ++ // ++ } while ((status==GRUB_EFI_SUCCESS) && !GRUB_EFI_END_ENTIRE_DEVICE_PATH(remaining_device_path)); ++ ++ } while (device_path != NULL); ++ ++ if (copy_of_device_path != NULL) { ++ grub_free(copy_of_device_path); ++ } ++ // ++ // All handle with device_path exists in the handle database ++ // ++ return status; ++} ++#endif ++ ++#define NPATHS 6 ++ ++static grub_uint8_t legacy_devpath[NPATHS][256] = { ++ {0x01, 0x03, 0x18, 0x00, 0x0b, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xf9, 0xff, 0x00, 0x00, 0x00, 0x00, ++ 0x04, 0x06, 0x14, 0x00, 0xeb, 0x85, 0x05, 0x2b, ++ 0xb8, 0xd8, 0xa9, 0x49, 0x8b, 0x8c, 0xe2, 0x1b, ++ 0x01, 0xae, 0xf2, 0xb7, 0x7f, 0xff, 0x04, 0x00,}, ++ ++ {0x01, 0x03, 0x18, 0x00, 0x0b, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xf7, 0xff, 0x00, 0x00, 0x00, 0x00, ++ 0x04, 0x06, 0x14, 0x00, 0xeb, 0x85, 0x05, 0x2b, ++ 0xb8, 0xd8, 0xa9, 0x49, 0x8b, 0x8c, 0xe2, 0x1b, ++ 0x01, 0xae, 0xf2, 0xb7, 0x7f, 0xff, 0x04, 0x00,}, ++ ++ {0x01, 0x03, 0x18, 0x00, 0x0b, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, ++ 0x04, 0x06, 0x14, 0x00, 0xeb, 0x85, 0x05, 0x2b, ++ 0xb8, 0xd8, 0xa9, 0x49, 0x8b, 0x8c, 0xe2, 0x1b, ++ 0x01, 0xae, 0xf2, 0xb7, 0x7f, 0xff, 0x04, 0x00,}, ++ ++ {0x01, 0x03, 0x18, 0x00, 0x0b, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xf9, 0xff, 0x00, 0x00, 0x00, 0x00, ++ 0x04, 0x06, 0x14, 0x00, 0xeb, 0x85, 0x05, 0x2b, ++ 0xb8, 0xd8, 0xa9, 0x49, 0x8b, 0x8c, 0xe2, 0x1b, ++ 0x01, 0xae, 0xf2, 0xb7, 0x7f, 0xff, 0x04, 0x00,}, ++ ++ {0x01, 0x03, 0x18, 0x00, 0x0b, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xf9, 0xff, 0x00, 0x00, 0x00, 0x00, ++ 0x04, 0x06, 0x14, 0x00, 0xeb, 0x85, 0x05, 0x2b, ++ 0xb8, 0xd8, 0xa9, 0x49, 0x8b, 0x8c, 0xe2, 0x1b, ++ 0x01, 0xae, 0xf2, 0xb7, 0x7f, 0xff, 0x04, 0x00, ++ 0x48, 0x00, 0x44, 0x00, 0x00, 0x00,}, ++ ++ { ++ 0x01, 0x03, 0x18, 0x00, 0x0b, 0x00, 0x00, 0x00, ++ 0x00, 0x40, 0xcb, 0xff, 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xbf, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, ++ 0x04, 0x06, 0x14, 0x00, 0xeb, 0x85, 0x05, 0x2b, ++ 0xb8, 0xd8, 0xa9, 0x49, 0x8b, 0x8c, 0xe2, 0x1b, ++ 0x01, 0xae, 0xf2, 0xb7, 0x7f, 0xff, 0x04, 0x00,} ++}; ++ ++ ++ ++static grub_err_t ++grub_cmd_legacy (struct grub_extcmd *cmd __attribute__ ((unused)), ++ int argc __attribute__ ((unused)), ++ char **args __attribute__ ((unused))) ++{ ++ int load_options_length; ++ char *load_options; ++ grub_efi_char16_t load_options16[256]; ++ grub_efi_loaded_image_t *loaded_image; ++ grub_efi_boot_services_t *b; ++ grub_efi_status_t status; ++ grub_efi_handle_t image_handle; ++ ++ int i; ++ ++ load_options = (!argc) ? "HD" : args[0]; ++ ++ b = grub_efi_system_table->boot_services; ++ ++#if 0 ++ grub_efi_loaded_image_t *grub_loaded_image; ++ ++ status=efi_call_3 (b->handle_protocol, grub_efi_image_handle,&loaded_image_guid, ++ (void **) &grub_loaded_image); ++ ++ grub_printf ("get grub_loaded_image %x\n",(unsigned int) status); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ return grub_error(GRUB_ERR_BAD_OS,"couldn't find our own loaded image info"); ++#endif ++ ++ ++ { ++ grub_efi_char16_t *ptr16 = load_options16; ++ char *ptr = load_options; ++ load_options_length = 0; ++ while (*ptr) ++ { ++ *(ptr16++) = *(ptr++); ++ load_options_length++; ++ } ++ *ptr16 = 0; ++ } ++ ++ for (i = 0; i < NPATHS; ++i) ++ { ++ ++#if 0 ++ grub_printf ("Looking for legacy boot"); ++ grub_efi_print_device_path( (grub_efi_device_path_t *) legacy_devpath[i]); ++#endif ++ ++ ++ //grub_efi_connect_device_path((grub_efi_device_path_t *) legacy_devpath[i]); ++ ++ status = ++ efi_call_6 (b->load_image, 0,grub_efi_image_handle, ++ (grub_efi_device_path_t *) legacy_devpath[i], NULL, 0, ++ &image_handle); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ continue; ++ ++ grub_printf ("Found legacy boot %d\n", i); ++ ++#if 0 ++ loaded_image = grub_efi_get_loaded_image (image_handle); ++#else ++ status=efi_call_3 (b->handle_protocol, image_handle,&loaded_image_guid, ++ (void **) &loaded_image); ++ ++ grub_printf ("get loaded_image %x\n",(unsigned int) status); ++ ++ if (status != GRUB_EFI_SUCCESS) ++ continue; ++#endif ++ ++ ++ loaded_image->load_options = load_options16; ++ loaded_image->load_options_size = load_options_length; ++ ++ loaded_image->load_options = L"CD"; ++ loaded_image->load_options_size = 6; ++ ++ status = efi_call_3 (b->start_image, image_handle, NULL, NULL); ++ ++ grub_printf ("Failed to start legacy boot %d(%x)\n", i,(unsigned int) status); ++ ++ } ++ ++ grub_printf ("Failed to start a legacy boot\n"); ++ return grub_error (GRUB_ERR_BAD_OS, "unknown error"); ++} ++ ++static grub_extcmd_t cmd; ++ ++GRUB_MOD_INIT (legacy) ++{ ++ (void) mod; /* To stop warning. */ ++ cmd = ++ grub_register_extcmd ("legacy", grub_cmd_legacy, GRUB_COMMAND_FLAG_BOTH, ++ "legacy [source]", "boot in legacy (CSM) mode", 0); ++} ++ ++GRUB_MOD_FINI (legacy) ++{ ++ grub_unregister_extcmd (cmd); ++} diff --git a/master/series b/master/series new file mode 100644 index 0000000..5c3d3da --- /dev/null +++ b/master/series @@ -0,0 +1,2 @@ +legacy +xen diff --git a/master/xen b/master/xen new file mode 100644 index 0000000..c8356bb --- /dev/null +++ b/master/xen @@ -0,0 +1,1201 @@ +Index: grub2/conf/i386-efi.rmk +=================================================================== +diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk +index 5abd720..b5b29e3 100644 +--- a/conf/i386-efi.rmk ++++ b/conf/i386-efi.rmk +@@ -85,7 +85,7 @@ grub_install_SOURCES = util/i386/efi/grub-install.in + pkglib_MODULES = kernel.mod chain.mod appleldr.mod \ + linux.mod halt.mod reboot.mod pci.mod lspci.mod \ + datetime.mod date.mod datehook.mod loadbios.mod \ +- fixvideo.mod mmap.mod acpi.mod legacy.mod ++ fixvideo.mod mmap.mod acpi.mod legacy.mod xen.mod + + # For kernel.mod. + kernel_mod_EXPORTS = no +@@ -188,6 +188,11 @@ legacy_mod_SOURCES = loader/efi/legacy.c + legacy_mod_CFLAGS = $(COMMON_CFLAGS) + legacy_mod_LDFLAGS = $(COMMON_LDFLAGS) + ++# For xen.mod ++xen_mod_SOURCES = loader/i386/efi/xen.c ++xen_mod_CFLAGS = $(COMMON_CFLAGS) ++xen_mod_LDFLAGS = $(COMMON_LDFLAGS) ++ + # For datehook.mod + datehook_mod_SOURCES = hook/datehook.c + datehook_mod_CFLAGS = $(COMMON_CFLAGS) +diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk +index 6ffa2e0..8ccd3bf 100644 +--- a/conf/x86_64-efi.rmk ++++ b/conf/x86_64-efi.rmk +@@ -82,7 +82,7 @@ grub_install_SOURCES = util/i386/efi/grub-install.in + pkglib_MODULES = kernel.mod chain.mod appleldr.mod \ + halt.mod reboot.mod linux.mod pci.mod lspci.mod \ + datetime.mod date.mod datehook.mod loadbios.mod \ +- fixvideo.mod mmap.mod acpi.mod legacy.mod ++ fixvideo.mod mmap.mod acpi.mod legacy.mod xen.mod + + # For kernel.mod. + kernel_mod_EXPORTS = no +@@ -181,6 +181,11 @@ legacy_mod_SOURCES = loader/efi/legacy.c + legacy_mod_CFLAGS = $(COMMON_CFLAGS) + legacy_mod_LDFLAGS = $(COMMON_LDFLAGS) + ++# For xen.mod ++xen_mod_SOURCES = loader/i386/efi/xen.c ++xen_mod_CFLAGS = $(COMMON_CFLAGS) ++xen_mod_LDFLAGS = $(COMMON_LDFLAGS) ++ + # For date.mod + date_mod_SOURCES = commands/date.c + date_mod_CFLAGS = $(COMMON_CFLAGS) +diff --git a/loader/i386/efi/xen.c b/loader/i386/efi/xen.c +new file mode 100644 +index 0000000..baed2e1 +--- /dev/null ++++ b/loader/i386/efi/xen.c +@@ -0,0 +1,1143 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++static grub_dl_t my_mod; ++static int loaded; ++static grub_addr_t entry; ++ ++#define XEN_EFI_MAGIC 0xdeadbeefef104eadULL ++#define XEN_LOADER_GRUB_64 0x0034365f36387847ULL ++#define XEN_LOADER_GRUB_32 0x0000003233616947ULL ++ ++struct xen_efi_hdr ++{ ++ grub_uint64_t magic; ++ grub_uint64_t efi_loader_signature; ++ grub_uint64_t efi_system_table_addr; ++ grub_uint64_t realmode_available; ++ grub_uint64_t boot_vid_mode; ++ grub_uint64_t boot_vid_info; ++} __attribute__((packed)); ++ ++struct xen_boot_video_info { ++ grub_uint8_t orig_x; /* 0x00 */ ++ grub_uint8_t orig_y; /* 0x01 */ ++ grub_uint8_t orig_video_mode; /* 0x02 */ ++ grub_uint8_t orig_video_cols; /* 0x03 */ ++ grub_uint8_t orig_video_lines; /* 0x04 */ ++ grub_uint8_t orig_video_isVGA; /* 0x05 */ ++ grub_uint16_t orig_video_points; /* 0x06 */ ++ ++ /* VESA graphic mode -- linear frame buffer */ ++ grub_uint32_t capabilities; /* 0x08 */ ++ grub_uint16_t lfb_linelength; /* 0x0c */ ++ grub_uint16_t lfb_width; /* 0x0e */ ++ grub_uint16_t lfb_height; /* 0x10 */ ++ grub_uint16_t lfb_depth; /* 0x12 */ ++ grub_uint32_t lfb_base; /* 0x14 */ ++ grub_uint32_t lfb_size; /* 0x18 */ ++ grub_uint8_t red_size; /* 0x1c */ ++ grub_uint8_t red_pos; /* 0x1d */ ++ grub_uint8_t green_size; /* 0x1e */ ++ grub_uint8_t green_pos; /* 0x1f */ ++ grub_uint8_t blue_size; /* 0x20 */ ++ grub_uint8_t blue_pos; /* 0x21 */ ++ grub_uint8_t rsvd_size; /* 0x22 */ ++ grub_uint8_t rsvd_pos; /* 0x23 */ ++ grub_uint16_t vesapm_seg; /* 0x24 */ ++ grub_uint16_t vesapm_off; /* 0x26 */ ++ grub_uint16_t vesa_attrib; /* 0x28 */ ++} __attribute__((packed)); ++ ++ ++struct xen_mbi ++{ ++ grub_uint32_t flags; ++ grub_uint32_t mem_lower; ++ grub_uint32_t mem_upper; ++ grub_uint32_t boot_device; ++ grub_uint32_t cmdline; ++ grub_uint32_t mods_count; ++ grub_uint32_t mods_addr; ++ grub_uint32_t syms[4]; ++ grub_uint32_t mmap_length; ++ grub_uint32_t mmap_addr; ++ grub_uint8_t pad[100]; ++}; ++ ++ ++ ++struct xen_module_rec ++{ ++ grub_uint32_t start; ++ grub_uint32_t end; ++ grub_uint32_t string; ++ grub_uint32_t reserved; ++}; ++ ++struct xen_mm_rec ++{ ++ grub_uint32_t size; ++ grub_uint32_t base_addr_low; ++ grub_uint32_t base_addr_high; ++ grub_uint32_t length_low; ++ grub_uint32_t length_high; ++ grub_uint32_t type; ++} __attribute__ ((packed)); ++ ++ ++#define MAX_MODULES 32 ++#define DUMMY_MAP_SIZE 128 ++ ++struct xen_play_pen ++{ ++ struct xen_mbi mbi; ++ char cmdline[1024]; ++ struct xen_module_rec modules[MAX_MODULES]; ++ char module_strings[MAX_MODULES][1024]; ++} *play_pen = NULL; ++ ++int module_no = 0; ++ ++ ++ ++static grub_uint8_t gdt[] __attribute__ ((aligned (16))) = ++{ ++ /* NULL. */ ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ /* Reserved. */ ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ /* Code segment. */ ++ 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00, ++ /* Data segment. */ ++0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00}; ++ ++struct gdt_descriptor ++{ ++ grub_uint16_t limit; ++ void *base; ++} __attribute__ ((packed)); ++ ++static struct gdt_descriptor gdt_desc = { ++ sizeof (gdt) - 1, ++ gdt ++}; ++ ++struct idt_descriptor ++{ ++ grub_uint16_t limit; ++ void *base; ++} __attribute__ ((packed)); ++ ++static struct idt_descriptor idt_desc = { ++ 0, ++ 0 ++}; ++ ++ ++ ++static struct xen_mem_tab ++{ ++ struct xen_mem_tab *next; ++ grub_efi_physical_address_t addr; ++ int pages; ++} *mem_tab = NULL; ++ ++ ++#define PAGE_SHIFT 12 /*4kb Pages */ ++#define PAGE_SIZE (1<< PAGE_SHIFT) ++ ++#define ONE_MB 0x100000 ++ ++static grub_efi_physical_address_t ++calculate_hwm (void) ++{ ++ struct xen_mem_tab *ptr; ++ ++ grub_efi_physical_address_t hwm = ONE_MB, end; ++ ++ for (ptr = mem_tab; ptr; ptr = ptr->next) ++ { ++ end = ptr->addr + (ptr->pages << PAGE_SHIFT); ++ if (end > hwm) ++ hwm = end; ++ } ++ ++ return hwm; ++} ++ ++static int ++size_to_pages (int size) ++{ ++ return (size + (PAGE_SIZE - 1)) >> PAGE_SHIFT; ++} ++ ++static void * ++give_me_some_low_pages (grub_efi_physical_address_t phys, int pages) ++{ ++ (void) phys; ++ (void) pages; ++ return NULL; ++} ++ ++static void * ++give_me_some_pages (grub_efi_physical_address_t phys, int pages) ++{ ++ struct xen_mem_tab *te; ++ ++ te = grub_malloc (sizeof (struct xen_mem_tab)); ++ ++ if (phys && (phys < ONE_MB)) ++ return give_me_some_low_pages (phys, pages); ++ ++ if (!phys) ++ phys = calculate_hwm (); ++ ++ ++ te->addr = ++ (grub_efi_physical_address_t) grub_efi_allocate_pages (phys, pages); ++ te->pages = pages; ++ ++ if (!te->addr) ++ { ++ grub_free (te); ++ return NULL; ++ } ++ ++ te->next = mem_tab; ++ mem_tab = te; ++ ++ return (void *) te->addr; ++} ++ ++static void ++mop_up_my_allocations (void) ++{ ++ struct xen_mem_tab *te; ++ ++ while ((te = mem_tab)) ++ { ++ mem_tab = te->next; ++ grub_efi_free_pages (te->addr, te->pages); ++ grub_free (te); ++ } ++ ++} ++ ++static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID; ++ ++ ++#define RGB_MASK 0xffffff ++#define RGB_MAGIC 0x121314 ++#define LINE_MIN 800 ++#define LINE_MAX 4096 ++#define FBTEST_STEP (0x10000 >> 2) ++#define FBTEST_COUNT 8 ++ ++static int ++find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len) ++{ ++ grub_uint32_t *base = (grub_uint32_t *) (grub_target_addr_t) *fb_base; ++ int i; ++ ++ for (i = 0; i < FBTEST_COUNT; i++, base += FBTEST_STEP) ++ { ++ grub_printf("Checking %p %x %x\n",base,*base,RGB_MAGIC); ++ grub_printf("fish %p %x %x\n",base,(*base & RGB_MASK),RGB_MAGIC); ++ ++ if ((*base & RGB_MASK) == RGB_MAGIC) ++ { ++ int j; ++ ++ for (j = LINE_MIN; j <= LINE_MAX; j++) ++ { ++ if ((base[j] & RGB_MASK) == RGB_MAGIC) ++ { ++ grub_printf("%p[%d]=%x\n",base,j,base[j]); ++ ++ *fb_base = (grub_uint32_t) (grub_target_addr_t) base; ++ *line_len = j << 2; ++ ++ return 1; ++ } ++ } ++ ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++static int ++find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len) ++{ ++ int found = 0; ++ ++ auto int NESTED_FUNC_ATTR find_card (int bus, int dev, int func, ++ grub_pci_id_t pciid); ++ ++ int NESTED_FUNC_ATTR find_card (int bus, int dev, int func, ++ grub_pci_id_t pciid) ++ { ++ grub_pci_address_t addr; ++ ++ addr = grub_pci_make_address (bus, dev, func, 2); ++ if (grub_pci_read (addr) >> 24 == 0x3) ++ { ++ int i; ++ ++ grub_printf ("Display controller: %d:%d.%d\nDevice id: %x\n", ++ bus, dev, func, pciid); ++ addr += 8; ++ for (i = 0; i < 6; i++, addr += 4) ++ { ++ grub_uint32_t old_bar1, old_bar2, type; ++ grub_uint64_t base64; ++ ++ old_bar1 = grub_pci_read (addr); ++ if ((! old_bar1) || (old_bar1 & GRUB_PCI_ADDR_SPACE_IO)) ++ continue; ++ ++ type = old_bar1 & GRUB_PCI_ADDR_MEM_TYPE_MASK; ++ if (type == GRUB_PCI_ADDR_MEM_TYPE_64) ++ { ++ if (i == 5) ++ break; ++ ++ old_bar2 = grub_pci_read (addr + 4); ++ } ++ else ++ old_bar2 = 0; ++ ++ base64 = old_bar2; ++ base64 <<= 32; ++ base64 |= (old_bar1 & GRUB_PCI_ADDR_MEM_MASK); ++ ++ grub_printf ("%s(%d): 0x%llx\n", ++ ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) ? ++ "VMEM" : "MMIO"), i, ++ (unsigned long long) base64); ++ ++ if ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) && (! found)) ++ { ++ *fb_base = base64; ++ if (find_line_len (fb_base, line_len)) { ++ grub_printf("Found %x %d\n",*fb_base,*line_len); ++ found++; ++ } ++ } ++ ++ if (type == GRUB_PCI_ADDR_MEM_TYPE_64) ++ { ++ i++; ++ addr += 4; ++ } ++ } ++ } ++ ++ return found; ++ } ++ ++ grub_pci_iterate (find_card); ++ return found; ++} ++static int ++xen_setup_video (struct xen_boot_video_info *bvi) ++{ ++ grub_efi_uga_draw_protocol_t *c; ++ grub_uint32_t width, height, depth, rate, pixel, fb_base, line_len; ++ int ret; ++ ++ c = grub_efi_locate_protocol (&uga_draw_guid, 0); ++ if (!c) ++ return 1; ++ ++#if 0 ++ if (efi_call_5 (c->get_mode, c, &width, &height, &depth, &rate)) ++ return 1; ++#else ++ if (efi_call_5 (c->get_mode, c, &width, &height, &depth, &rate)) { ++ width=1280; ++ height=800; ++ depth=32; ++ rate=60; ++ } ++#endif ++ ++ ++ grub_printf ("Video mode: %ux%u-%u@%u\n", width, height, depth, rate); ++ ++ grub_efi_set_text_mode (0); ++ pixel = RGB_MAGIC; ++ efi_call_10 (c->blt, c, (struct grub_efi_uga_pixel *) &pixel, ++ GRUB_EFI_UGA_VIDEO_FILL, 0, 0, 0, 0, 1, height, 0); ++ ret = find_framebuf (&fb_base, &line_len); ++ grub_efi_set_text_mode (1); ++ ++ ++ if (!ret) ++ { ++ grub_printf ("Can\'t find frame buffer address\n"); ++ return 1; ++ } ++ ++ grub_printf ("Video frame buffer: 0x%x\n", fb_base); ++ grub_printf ("Video line length: %d\n", line_len); ++ ++ bvi->orig_video_isVGA=0x23; /*XXX: what is 0x23? */ ++ ++ bvi->lfb_linelength=line_len; ++ bvi->lfb_width=width; ++ bvi->lfb_height=height; ++ bvi->lfb_depth=32; ++ bvi->lfb_base=(grub_uint32_t) fb_base; ++ ++ bvi->red_size=8; ++ bvi->red_pos=16; ++ ++ bvi->green_size=8; ++ bvi->green_pos=8; ++ ++ bvi->blue_size=8; ++ bvi->blue_pos=0; ++ ++ bvi->rsvd_size=8; ++ bvi->rsvd_pos=24; ++ ++ bvi->vesa_attrib=0x3; /*Possible(0x1) and has extended data(0x2)*/ ++ ++ /*Size of video ram in 64k blocks*/ ++ { ++ int i=line_len*height; ++ i+=65535; ++ ++ bvi->lfb_size= i >> 16; ++ } ++ ++ /* No protected mode*/ ++ bvi->vesapm_seg=0x0; ++ bvi->vesapm_off=0x0; ++ ++ bvi->vesa_attrib=0x1; /*Dac is 8 bit capable*/ ++ ++ ++ return 0; ++} ++ ++ ++static grub_err_t ++xen_setup (grub_uint8_t * base) ++{ ++ struct xen_efi_hdr *hdr; ++ grub_uint8_t *realmode_available; ++ grub_uint16_t *boot_vid_mode; ++ grub_uint64_t *efi_system_table_addr; ++ grub_uint64_t *efi_loader_signature; ++ struct xen_boot_video_info *bvi; ++ ++ int i; ++ ++ for (i = 0; i <0x200; i++) ++ { ++ hdr = (struct xen_efi_hdr *) (base + i); ++ if (hdr->magic == XEN_EFI_MAGIC) ++ break; ++ } ++ ++ if (hdr->magic != XEN_EFI_MAGIC) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "No EFI support in hypervisor"); ++ ++ grub_printf("base addr is %p\n",base); ++ ++ realmode_available=(grub_uint8_t *)hdr->realmode_available; ++ grub_printf("realmode_available was %x@%p\n",(int) *realmode_available,realmode_available); ++ *realmode_available=0; ++ ++ efi_loader_signature=(grub_uint64_t*)hdr->efi_loader_signature; ++ ++#if defined(__x86_64__) ++ *efi_loader_signature=XEN_LOADER_GRUB_64; ++#elif defined (__i386__) ++ *efi_loader_signature=XEN_LOADER_GRUB_32; ++#else ++ *efi_loader_signature=0; ++#endif ++ ++ efi_system_table_addr=(grub_uint64_t*)hdr->efi_system_table_addr; ++ ++ grub_printf("efi_system_table_addr was %llx@%p\n",(long long unsigned) *efi_system_table_addr, efi_system_table_addr); ++ ++ { ++ char buf[1024]; ++ grub_sprintf(buf,"Wrote %llx into efi_system_table (was %llx@%p)\n", ++ (long long unsigned) grub_efi_system_table, ++ (long long unsigned) *efi_system_table_addr, efi_system_table_addr); ++ grub_net_syslog (buf); ++ } ++ ++ *efi_system_table_addr= (grub_uint64_t) grub_efi_system_table; ++ ++ boot_vid_mode=(grub_uint16_t *)hdr->boot_vid_mode; ++ grub_printf("boot_vid_mode was 0x%x@%p\n",(int) *boot_vid_mode,boot_vid_mode); ++ *boot_vid_mode=0xf00; ++ ++ bvi=(struct xen_boot_video_info *)hdr->boot_vid_info; ++ grub_printf("boot_vid_info @%p\n",bvi); ++ ++ xen_setup_video (bvi); ++ ++ return GRUB_ERR_NONE; ++} ++ ++ ++ ++static grub_err_t ++elf32_hook (Elf32_Phdr * phdr, UNUSED grub_addr_t * addr) ++{ ++ int pages = size_to_pages (phdr->p_memsz); ++ ++ if (!give_me_some_pages (phdr->p_paddr, pages)) ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Couldn't claim 0x%lx - 0x%lx", ++ (long unsigned int) phdr->p_paddr, ++ (long unsigned int) (phdr->p_paddr + phdr->p_memsz)); ++ ++ ++ grub_printf ("Claimed 0x%lx - 0x%lx\n", (long unsigned int) phdr->p_paddr, ++ (long unsigned int) (phdr->p_paddr + phdr->p_memsz)); ++ ++ ++ return GRUB_ERR_NONE; ++} ++ ++ ++static void ++add_region (struct xen_mm_rec *map, int *nrecs, grub_uint64_t start, ++ grub_uint64_t len, grub_uint32_t type) ++{ ++ int n = *nrecs; ++ ++ if (!len) ++ return; ++ ++ if (!map) ++ { ++ (*nrecs)++; ++ return; ++ } ++ ++ if (n > 1) ++ { ++ grub_uint64_t last_end, last_len; ++ ++ last_end = map[n - 1].base_addr_high; ++ last_end <<= 32; ++ last_end |= map[n - 1].base_addr_low; ++ ++ last_len = map[n - 1].length_high; ++ last_len <<= 32; ++ last_len |= map[n - 1].length_low; ++ ++ last_end += last_len; ++ ++ if ((last_end == start) && (map[n - 1].type == type)) ++ { ++ last_len += len; ++ ++ map[n - 1].length_low = last_len & 0xffffffff; ++ map[n - 1].length_high = last_len >> 32; ++ ++ return; ++ } ++ } ++ ++ map[n].size = sizeof (struct xen_mm_rec) - sizeof (uint32_t); ++ ++ map[n].base_addr_low = start & 0xffffffff; ++ map[n].base_addr_high = start >> 32; ++ ++ map[n].length_low = len & 0xffffffff; ++ map[n].length_high = len >> 32; ++ ++ map[n].type = type; ++ ++ (*nrecs)++; ++ ++} ++ ++#define NEXT_MEMORY_DESCRIPTOR(desc, size) \ ++ ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) ++ ++ ++ ++static int ++make_mm (struct xen_mm_rec *map, grub_efi_memory_descriptor_t * tab, ++ int desc_size, int tab_size) ++{ ++ grub_efi_memory_descriptor_t *desc; ++ int n = 0; ++ ++ for (desc = tab; ++ desc < NEXT_MEMORY_DESCRIPTOR (tab, tab_size); ++ desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) ++ { ++ switch (desc->type) ++ { ++ case GRUB_EFI_ACPI_RECLAIM_MEMORY: ++ add_region (map, &n, desc->physical_start, desc->num_pages << 12, ++ GRUB_E820_ACPI); ++ break; ++ ++ case GRUB_EFI_ACPI_MEMORY_NVS: ++ add_region (map, &n, ++ desc->physical_start, ++ desc->num_pages << 12, GRUB_E820_NVS); ++ break; ++ ++ case GRUB_EFI_RUNTIME_SERVICES_CODE: ++ add_region (map, &n, ++ 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) ++ { ++ add_region (map, &n, ++ start, 0xA0000ULL - start, GRUB_E820_RAM); ++ } ++ ++ if (end <= 0x100000ULL) ++ continue; ++ ++ start = 0x100000ULL; ++ size = end - start; ++ } ++ ++ { ++ grub_uint64_t efifb_start = 0xC0010000ULL; ++ grub_uint64_t efifb_end = 0xC0700000ULL; ++ ++ /* Skip fb region */ ++ if ((start < efifb_end) && (end > efifb_start)) ++ { ++ if (start < efifb_start) ++ { ++ add_region (map, &n, ++ start, efifb_start - start, GRUB_E820_RAM); ++ } ++ ++ if (end <= efifb_end) ++ continue; ++ ++ start = efifb_end; ++ size = end - start; ++ } ++ } ++ ++ ++ add_region (map, &n, start, size, GRUB_E820_RAM); ++ break; ++ } ++ ++ default: ++ add_region (map, &n, ++ desc->physical_start, ++ desc->num_pages << 12, GRUB_E820_RESERVED); ++ } ++ } ++ ++ return n; ++} ++ ++static grub_efi_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID; ++static grub_efi_guid_t acpi2_guid = GRUB_EFI_ACPI_20_TABLE_GUID; ++static grub_efi_guid_t smbios_guid = GRUB_EFI_SMBIOS_TABLE_GUID; ++ ++#define EBDA_SEG_ADDR 0x40e ++#define LOW_MEM_ADDR 0x413 ++#if 0 ++#define FAKE_EBDA_SEG 0x9fc0 ++#else ++#define FAKE_EBDA_SEG 0x9400 ++#define FAKE_SMBIOS_SEG 0x9800 ++#endif ++ ++static void ++fake_more_bios_data(void) ++{ ++ unsigned i; ++ void *smbios; ++ ++ smbios = 0; ++ for (i = 0; i < grub_efi_system_table->num_table_entries; i++) ++ { ++ grub_efi_guid_t *guid = ++ &grub_efi_system_table->configuration_table[i].vendor_guid; ++ ++ if (!grub_memcmp (guid, &smbios_guid, sizeof (grub_efi_guid_t))) ++ { ++ smbios = grub_efi_system_table->configuration_table[i].vendor_table; ++ grub_printf ("SMBIOS: %p\n", smbios); ++ } ++ } ++ ++ if (smbios == 0) ++ return; ++ ++ grub_memcpy ((char *) (FAKE_SMBIOS_SEG << 4), smbios, 0x20); ++} ++ ++ ++ ++ ++ ++ ++ ++ ++static void ++fake_bios_data (void) ++{ ++ unsigned i; ++ void *acpi; ++ grub_uint16_t *ebda_seg_ptr, *low_mem_ptr; ++ ++ acpi = 0; ++ for (i = 0; i < grub_efi_system_table->num_table_entries; i++) ++ { ++ grub_efi_guid_t *guid = ++ &grub_efi_system_table->configuration_table[i].vendor_guid; ++ ++ if (!grub_memcmp (guid, &acpi2_guid, sizeof (grub_efi_guid_t))) ++ { ++ acpi = grub_efi_system_table->configuration_table[i].vendor_table; ++ grub_printf ("ACPI2: %p\n", acpi); ++ } ++ else if (!grub_memcmp (guid, &acpi_guid, sizeof (grub_efi_guid_t))) ++ { ++ void *t; ++ ++ t = grub_efi_system_table->configuration_table[i].vendor_table; ++ if (!acpi) ++ acpi = t; ++ grub_printf ("ACPI: %p\n", t); ++ } ++ } ++ ++ if (acpi == 0) ++ return; ++ ++ ebda_seg_ptr = (grub_uint16_t *) EBDA_SEG_ADDR; ++ low_mem_ptr = (grub_uint16_t *) LOW_MEM_ADDR; ++ ++ if ((*ebda_seg_ptr) || (*low_mem_ptr)) ++ return; ++ ++ *ebda_seg_ptr = FAKE_EBDA_SEG; ++ *low_mem_ptr = FAKE_EBDA_SEG >> 6; ++ ++ grub_memcpy ((char *) (FAKE_EBDA_SEG << 4), acpi, 1024); ++} ++ ++ ++#ifdef __x86_64__ ++struct ++{ ++ grub_uint32_t xen_entry; ++ grub_uint32_t xen_cs; ++} jumpvector; ++#endif ++ ++ ++ ++static grub_err_t ++grub_xen_boot (void) ++{ ++ grub_efi_uintn_t map_key; ++ grub_efi_uintn_t mmap_size; ++ grub_efi_uintn_t desc_size; ++ grub_efi_uint32_t desc_version; ++ struct xen_mm_rec *xen_mm; ++ //grub_efi_memory_descriptor_t *desc; ++ void *mmap_buf; ++ ++ int pages = 32; ++ int xen_pages = 32; ++ int xen_mm_size; ++ int len; ++ ++ ++ grub_printf ("entry = %x, idt_desc = %lx, gdt_desc = %lx\n", ++ (unsigned) entry, ++ (unsigned long) &(idt_desc.limit), ++ (unsigned long) &(gdt_desc.limit)); ++ grub_printf ("idt = %x:%lx, gdt = %x:%lx\n", ++ (unsigned) idt_desc.limit, (unsigned long) idt_desc.base, ++ (unsigned) gdt_desc.limit, (unsigned long) gdt_desc.base); ++ ++ fake_bios_data (); ++ fake_more_bios_data(); ++ ++ mmap_buf = give_me_some_pages (0, pages); ++ mmap_size = pages << PAGE_SHIFT; ++ ++ xen_mm = give_me_some_pages (0, xen_pages); ++ xen_mm_size = xen_pages << PAGE_SHIFT; ++ ++ if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key, ++ &desc_size, &desc_version) <= 0) ++ grub_fatal ("cannot get memory map"); ++ ++ ++ len = make_mm (NULL, mmap_buf, desc_size, mmap_size); ++ len *= sizeof (struct xen_mm_rec); ++ ++ if (len > xen_mm_size) ++ grub_fatal ("out of memory for e820ish map"); ++ ++ len = make_mm (xen_mm, mmap_buf, desc_size, mmap_size); ++ len *= sizeof (struct xen_mm_rec); ++ ++ play_pen->mbi.flags |= 1 << 6; ++ play_pen->mbi.mmap_length = len; ++ play_pen->mbi.mmap_addr = (uint32_t) (grub_efi_physical_address_t) xen_mm; ++ ++ if (!grub_efi_exit_boot_services (map_key)) ++ grub_fatal ("cannot exit boot services"); ++ ++ /* Hardware interrupts are not safe any longer. */ ++ asm volatile ("cli"::); ++ ++ /* Load the IDT and the GDT for the bootstrap. */ ++ asm volatile ("lidt %0"::"m" (idt_desc)); ++ asm volatile ("lgdt %0"::"m" (gdt_desc)); ++ ++#ifdef __x86_64__ ++ ++ grub_uint64_t grub_magic = 0x2badb002; ++ grub_uint64_t mbi_ptr = (grub_uint64_t) & play_pen->mbi.flags; ++ ++ ++ jumpvector.xen_entry = (grub_uint64_t) entry; ++ jumpvector.xen_cs = 0x10; ++ ++ ++ asm volatile ("mov %0, %%rax\n" ++ "mov %1, %%rbx\n" ++ "ljmp *%2"::"m" (grub_magic), "m" (mbi_ptr), ++ "m" (jumpvector)); ++ ++#else ++ grub_uint32_t grub_magic = 0x2badb002; ++ ++ ++ /* Hardware interrupts are not safe any longer. */ ++ asm volatile ("cli" : : ); ++ ++ /* Pass parameters. */ ++ asm volatile ("movl %0, %%ecx"::"m" (entry)); ++ asm volatile ("movl %0, %%eax"::"m" (grub_magic)); ++ asm volatile ("movl %0, %%ebx"::"m" (play_pen->mbi.flags)); ++ ++ /* Enter Linux. */ ++ asm volatile ("jmp *%%ecx"::); ++#endif ++ ++ /* Never reach here. */ ++ return GRUB_ERR_NONE; ++} ++ ++ ++static grub_err_t ++grub_xen_unload (void) ++{ ++ mop_up_my_allocations (); ++ grub_dl_unref (my_mod); ++ loaded = 0; ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_xenmod_command (grub_command_t cmd __attribute__ ((unused)), ++ int argc, char *argv[]) ++{ ++ char *module; ++ grub_ssize_t size; ++ grub_errno = GRUB_ERR_NONE; ++ grub_file_t file = 0; ++ int i; ++ ++ if (argc == 0) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); ++ goto fail; ++ } ++ ++ if (!loaded) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "no hypervisor loaded"); ++ goto fail; ++ } ++ ++ file = grub_gzfile_open (argv[0], 1); ++ if (!file) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file"); ++ goto fail; ++ } ++ ++ size = grub_file_size (file); ++ ++ ++ module = give_me_some_pages (0, size_to_pages (size)); ++ ++ if (!module) ++ goto fail; ++ ++ ++ if (grub_file_read (file, module, size) != size) ++ { ++ grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file"); ++ goto fail; ++ } ++ grub_printf ("module loaded at 0x%lx.\n", (unsigned long) module); ++ ++ play_pen->modules[module_no].start = ++ (grub_uint32_t) (grub_efi_physical_address_t) module; ++ play_pen->modules[module_no].end = ++ (grub_uint32_t) (grub_efi_physical_address_t) (module + size); ++ ++#if 0 ++ if (argc > 1) ++ { ++#endif ++ play_pen->modules[module_no].string = ++ (grub_uint32_t) (grub_efi_physical_address_t) & play_pen-> ++ module_strings[module_no]; ++ ++ for (i = 0; i < argc; ++i) ++ { ++ if (i) ++ grub_strcat (play_pen->module_strings[module_no], " "); ++ grub_strcat (play_pen->module_strings[module_no], argv[i]); ++ } ++#if 0 ++ } ++#endif ++ ++ ++ module_no++; ++ play_pen->mbi.flags |= 1 << 3; ++ play_pen->mbi.mods_count = module_no; ++ play_pen->mbi.mods_addr = ++ (grub_uint32_t) (grub_efi_physical_address_t) & play_pen->modules[0]; ++ ++fail: ++ if (file) ++ grub_file_close (file); ++ ++ return grub_errno; ++} ++ ++static grub_err_t ++grub_xen_command (grub_command_t cmd __attribute__ ((unused)), ++ int argc, char *argv[]) ++{ ++ grub_file_t file = 0; ++ grub_elf_t elf = 0; ++ grub_err_t err = 0; ++ int i; ++ ++ ++ grub_addr_t kern_base; ++ grub_size_t kern_size; ++ ++ grub_errno = GRUB_ERR_NONE; ++ ++ mop_up_my_allocations (); ++ ++ module_no = 0; ++ ++ grub_dl_ref (my_mod); ++ ++ if (argc == 0) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); ++ goto fail; ++ } ++ ++ file = grub_gzfile_open (argv[0], 1); ++ if (!file) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file"); ++ goto fail; ++ } ++ ++ elf = grub_elf_file (file); ++ if (!elf) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't parse elf headers"); ++ goto fail; ++ ++ } ++ ++ if (!grub_elf_is_elf32 (elf)) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "expecting 32 bit elf"); ++ goto fail; ++ } ++ ++ ++ entry = elf->ehdr.ehdr32.e_entry; ++ err = grub_elf32_load (elf, elf32_hook, &kern_base, &kern_size); ++ ++ ++ ++ if (err) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "didn't parse the elf"); ++ goto fail; ++ } ++ ++ grub_printf ("Entry point is 0x%lx. (%lx %lx)\n", (unsigned long) entry, ++ (unsigned long) kern_base, (unsigned long) kern_size); ++ ++ play_pen = ++ give_me_some_pages (0, size_to_pages (sizeof (struct xen_play_pen))); ++ ++ if (!play_pen) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to allocate play_pen"); ++ goto fail; ++ ++ } ++ grub_memset (play_pen, 0, sizeof (play_pen)); ++ ++ grub_printf ("Play pen is at 0x%lx.\n", (unsigned long) play_pen); ++ { ++ char buf[1024]; ++ grub_sprintf (buf, "Play pen is at 0x%lx.\n", (unsigned long) play_pen); ++ grub_net_syslog (buf); ++ grub_sprintf (buf, "mbi is at 0x%lx.\n", ++ (unsigned long) (&play_pen->mbi.flags)); ++ grub_net_syslog (buf); ++ } ++ ++ ++ ++ if (argc > 1) ++ { ++ play_pen->mbi.flags |= 1 << 2; ++ ++ play_pen->mbi.cmdline = ++ (grub_uint32_t) (grub_efi_physical_address_t) & play_pen->cmdline[0]; ++ ++ for (i = 0; i < argc; ++i) ++ { ++ if (i) ++ grub_strcat (play_pen->cmdline, " "); ++ grub_strcat (play_pen->cmdline, argv[i]); ++ } ++ } ++ ++ ++ if (xen_setup ((void *) (grub_efi_physical_address_t) kern_base)) ++ { ++ grub_printf ("xen_setup fialed\n"); ++ goto fail; ++ } ++ ++ ++ ++ grub_loader_set (grub_xen_boot, grub_xen_unload, 1); ++ loaded = 1; ++ ++fail: ++ ++ if (file) ++ grub_file_close (file); ++ ++ if (grub_errno != GRUB_ERR_NONE) ++ { ++ mop_up_my_allocations (); ++ grub_dl_unref (my_mod); ++ loaded = 0; ++ } ++ return grub_errno; ++} ++ ++static grub_command_t xen_cmd, xenmod_cmd; ++ ++GRUB_MOD_INIT (xen) ++{ ++ (void) mod; /* To stop warning. */ ++ xen_cmd = ++ grub_register_command ("xen", grub_xen_command, 0, ++ "Load a xen hypervisor."); ++ xenmod_cmd = ++ grub_register_command ("xenmod", grub_xenmod_command, 0, ++ "Load a xen module."); ++ ++ my_mod = mod; ++} ++ ++GRUB_MOD_FINI (xen) ++{ ++ grub_unregister_command (xenmod_cmd); ++ grub_unregister_command (xen_cmd); ++} -- 2.39.5