From 6e7a315eb67cb6c113cf37e1d66c4f11a51a2b3e Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 18:29:51 +0200 Subject: Adding upstream version 2.06. Signed-off-by: Daniel Baumann --- grub-core/efiemu/loadcore_common.c | 196 +++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 grub-core/efiemu/loadcore_common.c (limited to 'grub-core/efiemu/loadcore_common.c') diff --git a/grub-core/efiemu/loadcore_common.c b/grub-core/efiemu/loadcore_common.c new file mode 100644 index 0000000..64d7960 --- /dev/null +++ b/grub-core/efiemu/loadcore_common.c @@ -0,0 +1,196 @@ +/* Load runtime image of EFIemu. Functions common to 32/64-bit mode */ +/* + * 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 + +/* Are we in 32 or 64-bit mode?*/ +static grub_efiemu_mode_t grub_efiemu_mode = GRUB_EFIEMU_NOTLOADED; +/* Runtime ELF file */ +static grub_ssize_t efiemu_core_size; +static void *efiemu_core = 0; +/* Linked list of segments */ +static grub_efiemu_segment_t efiemu_segments = 0; + +/* equivalent to sizeof (grub_efi_uintn_t) but taking the mode into account*/ +int +grub_efiemu_sizeof_uintn_t (void) +{ + if (grub_efiemu_mode == GRUB_EFIEMU32) + return 4; + if (grub_efiemu_mode == GRUB_EFIEMU64) + return 8; + return 0; +} + +/* Check the header and set mode */ +static grub_err_t +grub_efiemu_check_header (void *ehdr, grub_size_t size, + grub_efiemu_mode_t *mode) +{ + /* Check the magic numbers. */ + if ((*mode == GRUB_EFIEMU_NOTLOADED || *mode == GRUB_EFIEMU32) + && grub_efiemu_check_header32 (ehdr,size)) + { + *mode = GRUB_EFIEMU32; + return GRUB_ERR_NONE; + } + if ((*mode == GRUB_EFIEMU_NOTLOADED || *mode == GRUB_EFIEMU64) + && grub_efiemu_check_header64 (ehdr,size)) + { + *mode = GRUB_EFIEMU64; + return GRUB_ERR_NONE; + } + return grub_error (GRUB_ERR_BAD_OS, "invalid ELF magic"); +} + +/* Unload segments */ +static int +grub_efiemu_unload_segs (grub_efiemu_segment_t seg) +{ + grub_efiemu_segment_t segn; + for (; seg; seg = segn) + { + segn = seg->next; + grub_efiemu_mm_return_request (seg->handle); + grub_free (seg); + } + return 1; +} + + +grub_err_t +grub_efiemu_loadcore_unload(void) +{ + switch (grub_efiemu_mode) + { + case GRUB_EFIEMU32: + grub_efiemu_loadcore_unload32 (); + break; + + case GRUB_EFIEMU64: + grub_efiemu_loadcore_unload64 (); + break; + + default: + break; + } + + grub_efiemu_mode = GRUB_EFIEMU_NOTLOADED; + + grub_free (efiemu_core); + efiemu_core = 0; + + grub_efiemu_unload_segs (efiemu_segments); + efiemu_segments = 0; + + grub_efiemu_free_syms (); + + return GRUB_ERR_NONE; +} + +/* Load runtime file and do some initial preparations */ +grub_err_t +grub_efiemu_loadcore_init (grub_file_t file, + const char *filename) +{ + grub_err_t err; + + efiemu_core_size = grub_file_size (file); + efiemu_core = 0; + efiemu_core = grub_malloc (efiemu_core_size); + if (! efiemu_core) + return grub_errno; + + if (grub_file_read (file, efiemu_core, efiemu_core_size) + != (int) efiemu_core_size) + { + grub_free (efiemu_core); + efiemu_core = 0; + return grub_errno; + } + + if (grub_efiemu_check_header (efiemu_core, efiemu_core_size, + &grub_efiemu_mode)) + { + grub_free (efiemu_core); + efiemu_core = 0; + return GRUB_ERR_BAD_MODULE; + } + + switch (grub_efiemu_mode) + { + case GRUB_EFIEMU32: + err = grub_efiemu_loadcore_init32 (efiemu_core, filename, + efiemu_core_size, + &efiemu_segments); + if (err) + { + grub_free (efiemu_core); + efiemu_core = 0; + grub_efiemu_mode = GRUB_EFIEMU_NOTLOADED; + return err; + } + break; + + case GRUB_EFIEMU64: + err = grub_efiemu_loadcore_init64 (efiemu_core, filename, + efiemu_core_size, + &efiemu_segments); + if (err) + { + grub_free (efiemu_core); + efiemu_core = 0; + grub_efiemu_mode = GRUB_EFIEMU_NOTLOADED; + return err; + } + break; + + default: + return grub_error (GRUB_ERR_BUG, "unknown EFI runtime"); + } + return GRUB_ERR_NONE; +} + +grub_err_t +grub_efiemu_loadcore_load (void) +{ + grub_err_t err; + switch (grub_efiemu_mode) + { + case GRUB_EFIEMU32: + err = grub_efiemu_loadcore_load32 (efiemu_core, efiemu_core_size, + efiemu_segments); + if (err) + grub_efiemu_loadcore_unload (); + return err; + case GRUB_EFIEMU64: + err = grub_efiemu_loadcore_load64 (efiemu_core, efiemu_core_size, + efiemu_segments); + if (err) + grub_efiemu_loadcore_unload (); + return err; + default: + return grub_error (GRUB_ERR_BUG, "unknown EFI runtime"); + } +} -- cgit v1.2.3