diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:29:51 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:29:51 +0000 |
commit | 6e7a315eb67cb6c113cf37e1d66c4f11a51a2b3e (patch) | |
tree | 32451fa3cdd9321fb2591fada9891b2cb70a9cd1 /grub-core/lib/xen/relocator.c | |
parent | Initial commit. (diff) | |
download | grub2-upstream/2.06.tar.xz grub2-upstream/2.06.zip |
Adding upstream version 2.06.upstream/2.06upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | grub-core/lib/xen/relocator.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/grub-core/lib/xen/relocator.c b/grub-core/lib/xen/relocator.c new file mode 100644 index 0000000..4d0cbca --- /dev/null +++ b/grub-core/lib/xen/relocator.c @@ -0,0 +1,137 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + */ + +#include <grub/mm.h> +#include <grub/misc.h> + +#include <grub/types.h> +#include <grub/err.h> +#include <grub/term.h> +#include <grub/xen.h> + +#include <grub/xen/relocator.h> +#include <grub/relocator_private.h> + +typedef grub_addr_t grub_xen_reg_t; + +struct grub_relocator_xen_paging_area { + grub_xen_reg_t start; + grub_xen_reg_t size; +} GRUB_PACKED; + +extern grub_uint8_t grub_relocator_xen_start; +extern grub_uint8_t grub_relocator_xen_end; +extern grub_uint8_t grub_relocator_xen_remap_start; +extern grub_uint8_t grub_relocator_xen_remap_end; +extern grub_xen_reg_t grub_relocator_xen_stack; +extern grub_xen_reg_t grub_relocator_xen_start_info; +extern grub_xen_reg_t grub_relocator_xen_entry_point; +extern grub_xen_reg_t grub_relocator_xen_remapper_virt; +extern grub_xen_reg_t grub_relocator_xen_remapper_virt2; +extern grub_xen_reg_t grub_relocator_xen_remapper_map; +extern grub_xen_reg_t grub_relocator_xen_mfn_list; +extern struct grub_relocator_xen_paging_area + grub_relocator_xen_paging_areas[XEN_MAX_MAPPINGS]; +extern grub_xen_reg_t grub_relocator_xen_remap_continue; +#ifdef __i386__ +extern grub_xen_reg_t grub_relocator_xen_mmu_op_addr; +extern grub_xen_reg_t grub_relocator_xen_paging_areas_addr; +extern grub_xen_reg_t grub_relocator_xen_remapper_map_high; +#endif +extern mmuext_op_t grub_relocator_xen_mmu_op[3]; + +#define RELOCATOR_SIZEOF(x) (&grub_relocator##x##_end - &grub_relocator##x##_start) + +grub_err_t +grub_relocator_xen_boot (struct grub_relocator *rel, + struct grub_relocator_xen_state state, + grub_uint64_t remapper_pfn, + grub_addr_t remapper_virt, + grub_uint64_t trampoline_pfn, + grub_addr_t trampoline_virt) +{ + grub_err_t err; + void *relst; + int i; + grub_relocator_chunk_t ch, ch_tramp; + grub_xen_mfn_t *mfn_list = + (grub_xen_mfn_t *) grub_xen_start_page_addr->mfn_list; + + err = grub_relocator_alloc_chunk_addr (rel, &ch, remapper_pfn << 12, + RELOCATOR_SIZEOF (_xen_remap)); + if (err) + return err; + err = grub_relocator_alloc_chunk_addr (rel, &ch_tramp, trampoline_pfn << 12, + RELOCATOR_SIZEOF (_xen)); + if (err) + return err; + + grub_relocator_xen_stack = state.stack; + grub_relocator_xen_start_info = state.start_info; + grub_relocator_xen_entry_point = state.entry_point; + for (i = 0; i < XEN_MAX_MAPPINGS; i++) + { + grub_relocator_xen_paging_areas[i].start = state.paging_start[i]; + grub_relocator_xen_paging_areas[i].size = state.paging_size[i]; + } + grub_relocator_xen_remapper_virt = remapper_virt; + grub_relocator_xen_remapper_virt2 = remapper_virt; + grub_relocator_xen_remap_continue = trampoline_virt; + + grub_relocator_xen_remapper_map = (mfn_list[remapper_pfn] << 12) | 5; +#ifdef __i386__ + grub_relocator_xen_remapper_map_high = (mfn_list[remapper_pfn] >> 20); + grub_relocator_xen_mmu_op_addr = (char *) &grub_relocator_xen_mmu_op + - (char *) &grub_relocator_xen_remap_start + remapper_virt; + grub_relocator_xen_paging_areas_addr = + (char *) &grub_relocator_xen_paging_areas + - (char *) &grub_relocator_xen_remap_start + remapper_virt; +#endif + + grub_relocator_xen_mfn_list = state.mfn_list; + + grub_memset (grub_relocator_xen_mmu_op, 0, + sizeof (grub_relocator_xen_mmu_op)); +#ifdef __i386__ + grub_relocator_xen_mmu_op[0].cmd = MMUEXT_PIN_L3_TABLE; +#else + grub_relocator_xen_mmu_op[0].cmd = MMUEXT_PIN_L4_TABLE; +#endif + grub_relocator_xen_mmu_op[0].arg1.mfn = mfn_list[state.paging_start[0]]; + grub_relocator_xen_mmu_op[1].cmd = MMUEXT_NEW_BASEPTR; + grub_relocator_xen_mmu_op[1].arg1.mfn = mfn_list[state.paging_start[0]]; + grub_relocator_xen_mmu_op[2].cmd = MMUEXT_UNPIN_TABLE; + grub_relocator_xen_mmu_op[2].arg1.mfn = + mfn_list[grub_xen_start_page_addr->pt_base >> 12]; + + grub_memmove (get_virtual_current_address (ch), + &grub_relocator_xen_remap_start, + RELOCATOR_SIZEOF (_xen_remap)); + grub_memmove (get_virtual_current_address (ch_tramp), + &grub_relocator_xen_start, RELOCATOR_SIZEOF (_xen)); + + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + &relst, NULL); + if (err) + return err; + + ((void (*)(void)) relst) (); + + /* Not reached. */ + return GRUB_ERR_NONE; +} |