/* Load runtime image of EFIemu. Functions common to 32/64-bit mode */ /* * VAS_EBOOT -- GRand Unified Bootloader * Copyright (C) 2009 Free Software Foundation, Inc. * * VAS_EBOOT 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. * * VAS_EBOOT 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 VAS_EBOOT. If not, see . */ #include #include #include #include #include #include /* Are we in 32 or 64-bit mode?*/ static VasEBoot_efiemu_mode_t VasEBoot_efiemu_mode = VAS_EBOOT_EFIEMU_NOTLOADED; /* Runtime ELF file */ static VasEBoot_ssize_t efiemu_core_size; static void *efiemu_core = 0; /* Linked list of segments */ static VasEBoot_efiemu_segment_t efiemu_segments = 0; /* equivalent to sizeof (VasEBoot_efi_uintn_t) but taking the mode into account*/ int VasEBoot_efiemu_sizeof_uintn_t (void) { if (VasEBoot_efiemu_mode == VAS_EBOOT_EFIEMU32) return 4; if (VasEBoot_efiemu_mode == VAS_EBOOT_EFIEMU64) return 8; return 0; } /* Check the header and set mode */ static VasEBoot_err_t VasEBoot_efiemu_check_header (void *ehdr, VasEBoot_size_t size, VasEBoot_efiemu_mode_t *mode) { /* Check the magic numbers. */ if ((*mode == VAS_EBOOT_EFIEMU_NOTLOADED || *mode == VAS_EBOOT_EFIEMU32) && VasEBoot_efiemu_check_header32 (ehdr,size)) { *mode = VAS_EBOOT_EFIEMU32; return VAS_EBOOT_ERR_NONE; } if ((*mode == VAS_EBOOT_EFIEMU_NOTLOADED || *mode == VAS_EBOOT_EFIEMU64) && VasEBoot_efiemu_check_header64 (ehdr,size)) { *mode = VAS_EBOOT_EFIEMU64; return VAS_EBOOT_ERR_NONE; } return VasEBoot_error (VAS_EBOOT_ERR_BAD_OS, "invalid ELF magic"); } /* Unload segments */ static int VasEBoot_efiemu_unload_segs (VasEBoot_efiemu_segment_t seg) { VasEBoot_efiemu_segment_t segn; for (; seg; seg = segn) { segn = seg->next; VasEBoot_efiemu_mm_return_request (seg->handle); VasEBoot_free (seg); } return 1; } VasEBoot_err_t VasEBoot_efiemu_loadcore_unload(void) { switch (VasEBoot_efiemu_mode) { case VAS_EBOOT_EFIEMU32: VasEBoot_efiemu_loadcore_unload32 (); break; case VAS_EBOOT_EFIEMU64: VasEBoot_efiemu_loadcore_unload64 (); break; default: break; } VasEBoot_efiemu_mode = VAS_EBOOT_EFIEMU_NOTLOADED; VasEBoot_free (efiemu_core); efiemu_core = 0; VasEBoot_efiemu_unload_segs (efiemu_segments); efiemu_segments = 0; VasEBoot_efiemu_free_syms (); return VAS_EBOOT_ERR_NONE; } /* Load runtime file and do some initial preparations */ VasEBoot_err_t VasEBoot_efiemu_loadcore_init (VasEBoot_file_t file, const char *filename) { VasEBoot_err_t err; efiemu_core_size = VasEBoot_file_size (file); efiemu_core = 0; efiemu_core = VasEBoot_malloc (efiemu_core_size); if (! efiemu_core) return VasEBoot_errno; if (VasEBoot_file_read (file, efiemu_core, efiemu_core_size) != (int) efiemu_core_size) { VasEBoot_free (efiemu_core); efiemu_core = 0; return VasEBoot_errno; } if (VasEBoot_efiemu_check_header (efiemu_core, efiemu_core_size, &VasEBoot_efiemu_mode)) { VasEBoot_free (efiemu_core); efiemu_core = 0; return VAS_EBOOT_ERR_BAD_MODULE; } switch (VasEBoot_efiemu_mode) { case VAS_EBOOT_EFIEMU32: err = VasEBoot_efiemu_loadcore_init32 (efiemu_core, filename, efiemu_core_size, &efiemu_segments); if (err) { VasEBoot_free (efiemu_core); efiemu_core = 0; VasEBoot_efiemu_mode = VAS_EBOOT_EFIEMU_NOTLOADED; return err; } break; case VAS_EBOOT_EFIEMU64: err = VasEBoot_efiemu_loadcore_init64 (efiemu_core, filename, efiemu_core_size, &efiemu_segments); if (err) { VasEBoot_free (efiemu_core); efiemu_core = 0; VasEBoot_efiemu_mode = VAS_EBOOT_EFIEMU_NOTLOADED; return err; } break; default: return VasEBoot_error (VAS_EBOOT_ERR_BUG, "unknown EFI runtime"); } return VAS_EBOOT_ERR_NONE; } VasEBoot_err_t VasEBoot_efiemu_loadcore_load (void) { VasEBoot_err_t err; switch (VasEBoot_efiemu_mode) { case VAS_EBOOT_EFIEMU32: err = VasEBoot_efiemu_loadcore_load32 (efiemu_core, efiemu_core_size, efiemu_segments); if (err) VasEBoot_efiemu_loadcore_unload (); return err; case VAS_EBOOT_EFIEMU64: err = VasEBoot_efiemu_loadcore_load64 (efiemu_core, efiemu_core_size, efiemu_segments); if (err) VasEBoot_efiemu_loadcore_unload (); return err; default: return VasEBoot_error (VAS_EBOOT_ERR_BUG, "unknown EFI runtime"); } }