vaseboot/VasEBoot-core/efiemu/loadcore_common.c

197 lines
5.0 KiB
C

/* Load runtime image of EFIemu. Functions common to 32/64-bit mode */
/*
* VasEBoot -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* VasEBoot 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.
*
* VasEBoot 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 VasEBoot. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/file.h>
#include <VasEBoot/err.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/efiemu/efiemu.h>
#include <VasEBoot/cpu/efiemu.h>
/* Are we in 32 or 64-bit mode?*/
static VasEBoot_efiemu_mode_t VasEBoot_efiemu_mode = VasEBoot_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 == VasEBoot_EFIEMU32)
return 4;
if (VasEBoot_efiemu_mode == VasEBoot_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 == VasEBoot_EFIEMU_NOTLOADED || *mode == VasEBoot_EFIEMU32)
&& VasEBoot_efiemu_check_header32 (ehdr,size))
{
*mode = VasEBoot_EFIEMU32;
return VasEBoot_ERR_NONE;
}
if ((*mode == VasEBoot_EFIEMU_NOTLOADED || *mode == VasEBoot_EFIEMU64)
&& VasEBoot_efiemu_check_header64 (ehdr,size))
{
*mode = VasEBoot_EFIEMU64;
return VasEBoot_ERR_NONE;
}
return VasEBoot_error (VasEBoot_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 VasEBoot_EFIEMU32:
VasEBoot_efiemu_loadcore_unload32 ();
break;
case VasEBoot_EFIEMU64:
VasEBoot_efiemu_loadcore_unload64 ();
break;
default:
break;
}
VasEBoot_efiemu_mode = VasEBoot_EFIEMU_NOTLOADED;
VasEBoot_free (efiemu_core);
efiemu_core = 0;
VasEBoot_efiemu_unload_segs (efiemu_segments);
efiemu_segments = 0;
VasEBoot_efiemu_free_syms ();
return VasEBoot_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 VasEBoot_ERR_BAD_MODULE;
}
switch (VasEBoot_efiemu_mode)
{
case VasEBoot_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 = VasEBoot_EFIEMU_NOTLOADED;
return err;
}
break;
case VasEBoot_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 = VasEBoot_EFIEMU_NOTLOADED;
return err;
}
break;
default:
return VasEBoot_error (VasEBoot_ERR_BUG, "unknown EFI runtime");
}
return VasEBoot_ERR_NONE;
}
VasEBoot_err_t
VasEBoot_efiemu_loadcore_load (void)
{
VasEBoot_err_t err;
switch (VasEBoot_efiemu_mode)
{
case VasEBoot_EFIEMU32:
err = VasEBoot_efiemu_loadcore_load32 (efiemu_core, efiemu_core_size,
efiemu_segments);
if (err)
VasEBoot_efiemu_loadcore_unload ();
return err;
case VasEBoot_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 (VasEBoot_ERR_BUG, "unknown EFI runtime");
}
}