/* Prepare efiemu. E.g. allocate memory, load the runtime to appropriate place, etc */ /* * 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 grub_err_t SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks, struct grub_efiemu_configuration_table *config_tables) { grub_err_t err; int conftable_handle; struct grub_efiemu_configuration_table *cur; struct grub_efiemu_prepare_hook *curhook; int cntconftables = 0; TYPE (grub_efiemu_configuration_table) *conftables = 0; TYPE (grub_efiemu_runtime_services) *runtime_services; int i; int handle; grub_off_t off; grub_dprintf ("efiemu", "Preparing EfiEmu\n"); /* Request space for the list of configuration tables */ for (cur = config_tables; cur; cur = cur->next) cntconftables++; conftable_handle = grub_efiemu_request_memalign (GRUB_EFIEMU_PAGESIZE, cntconftables * sizeof (*conftables), GRUB_EFI_RUNTIME_SERVICES_DATA); /* Switch from phase 1 (counting) to phase 2 (real job) */ grub_efiemu_alloc_syms (); grub_efiemu_mm_do_alloc (); grub_efiemu_system_table32 = 0; grub_efiemu_system_table64 = 0; /* Execute hooks */ for (curhook = prepare_hooks; curhook; curhook = curhook->next) curhook->hook (curhook->data); /* Move runtime to its due place */ if ((err = grub_efiemu_loadcore_load ())) { grub_efiemu_unload (); return err; } if ((err = grub_efiemu_resolve_symbol ("efiemu_system_table", &handle, &off))) { grub_efiemu_unload (); return err; } SUFFIX (grub_efiemu_system_table) = (TYPE (grub_efi_system_table) *) ((grub_uint8_t *)grub_efiemu_mm_obtain_request (handle) + off); /* compute CRC32 of runtime_services */ if ((err = grub_efiemu_resolve_symbol ("efiemu_runtime_services", &handle, &off))) return err; runtime_services = (TYPE (grub_efiemu_runtime_services) *) ((grub_uint8_t *)grub_efiemu_mm_obtain_request (handle) + off); runtime_services->hdr.crc32 = 0; runtime_services->hdr.crc32 = grub_getcrc32 (0, runtime_services, runtime_services->hdr.header_size); /* Put pointer to the list of configuration tables in system table */ grub_efiemu_write_value (&(SUFFIX (grub_efiemu_system_table)->configuration_table), 0, conftable_handle, 0, 1, sizeof (SUFFIX (grub_efiemu_system_table)->configuration_table)); SUFFIX(grub_efiemu_system_table)->num_table_entries = cntconftables; /* Fill the list of configuration tables */ conftables = (TYPE (grub_efiemu_configuration_table) *) grub_efiemu_mm_obtain_request (conftable_handle); i = 0; for (cur = config_tables; cur; cur = cur->next, i++) { grub_memcpy (&(conftables[i].vendor_guid), &(cur->guid), sizeof (cur->guid)); if (cur->get_table) conftables[i].vendor_table = PTR_TO_UINT64 (cur->get_table (cur->data)); else conftables[i].vendor_table = PTR_TO_UINT64 (cur->data); } /* compute CRC32 of system table */ SUFFIX (grub_efiemu_system_table)->hdr.crc32 = 0; SUFFIX (grub_efiemu_system_table)->hdr.crc32 = grub_getcrc32 (0, SUFFIX (grub_efiemu_system_table), SUFFIX (grub_efiemu_system_table)->hdr.header_size); grub_dprintf ("efiemu","system_table = %p, runtime_services = %p," " conftables = %p (%d entries)\n", SUFFIX (grub_efiemu_system_table), runtime_services, conftables, cntconftables); return GRUB_ERR_NONE; }