This will need fixes. I already have a newer version. Real problem though is testing it
Regards Vladimir 'phcoder' Serbinenko Le mar. 22 avr. 2025, 23:33, Paymon MARANDI <pay...@encs.concordia.ca> a écrit : > From: Vladimir Serbinenko <phco...@gmail.com> > > This is a replacement workaround for EFIs that do not map memory above 4G > and allows to increase maximum available address to 128TiB > --- > grub-core/Makefile.core.def | 1 + > grub-core/kern/efi/mm.c | 10 ++++ > grub-core/kern/x86_64/efi/mm.c | 84 ++++++++++++++++++++++++++++++++++ > include/grub/efi/memory.h | 5 ++ > 4 files changed, 100 insertions(+) > create mode 100644 grub-core/kern/x86_64/efi/mm.c > > diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def > index 7f8cb3f7d..57e76dda5 100644 > --- a/grub-core/Makefile.core.def > +++ b/grub-core/Makefile.core.def > @@ -219,6 +219,7 @@ kernel = { > efi = kern/efi/acpi.c; > efi = kern/efi/sb.c; > efi = kern/lockdown.c; > + x86_64_efi = kern/x86_64/efi/mm.c; > i386_coreboot = kern/i386/pc/acpi.c; > i386_multiboot = kern/i386/pc/acpi.c; > i386_coreboot = kern/acpi.c; > diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c > index df238b165..60ac7ed00 100644 > --- a/grub-core/kern/efi/mm.c > +++ b/grub-core/kern/efi/mm.c > @@ -160,6 +160,16 @@ grub_efi_allocate_pages_real > (grub_efi_physical_address_t address, > } > } > > +#ifdef __x86_64__ > + status = grub_efi_arch_ensure_mapping (address, pages); > + if (status != GRUB_EFI_SUCCESS) > + { > + b->free_pages (address, pages); > + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); > + return NULL; > + } > +#endif > + > grub_efi_store_alloc (address, pages); > > return (void *) ((grub_addr_t) address); > diff --git a/grub-core/kern/x86_64/efi/mm.c > b/grub-core/kern/x86_64/efi/mm.c > new file mode 100644 > index 000000000..01e2b9ac4 > --- /dev/null > +++ b/grub-core/kern/x86_64/efi/mm.c > @@ -0,0 +1,84 @@ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2025 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/types.h> > +#include <grub/misc.h> > +#include <grub/mm.h> > +#include <grub/err.h> > +#include <grub/dl.h> > +#include <grub/cache.h> > +#include <grub/kernel.h> > +#include <grub/efi/efi.h> > + > +static grub_efi_status_t > +create_paging_entry(grub_uint64_t *entry) > +{ > + grub_efi_status_t status; > + grub_efi_boot_services_t *b; > + > + grub_uint64_t address = 0xffffffff; > + > + b = grub_efi_system_table->boot_services; > + /* TODO: Which type should it be? */ > + status = b->allocate_pages (GRUB_EFI_ALLOCATE_MAX_ADDRESS, > GRUB_EFI_LOADER_DATA, 1, &address); > + if (status != GRUB_EFI_SUCCESS) > + return status; > + *entry = address | 7; > + return GRUB_EFI_SUCCESS; > +} > + > +grub_efi_status_t > +grub_efi_arch_ensure_mapping (grub_efi_physical_address_t address, > + grub_efi_uintn_t pages) > +{ > + grub_uint64_t cr3; > + asm volatile("movq %%cr3, %0\n" : "=r"(cr3)); > + for (grub_uint64_t page = 0; page < pages; page++) > + { > + grub_uint64_t pageidx = (address >> 12) + page; > + grub_uint64_t *pt4 = (grub_uint64_t *) cr3; > + if (!(pt4[pageidx >> 27] & 1)) { > + grub_efi_status_t status = create_paging_entry(&pt4[pageidx >> > 27]); > + if (status != GRUB_EFI_SUCCESS) > + return status; > + } > + grub_uint64_t *pt3 = (grub_uint64_t *) (pt4[pageidx >> 27] & > ~0xfff); > + if (!(pt3[pageidx >> 18] & 1)) { > + grub_efi_status_t status = create_paging_entry(&pt3[pageidx >> > 18]); > + if (status != GRUB_EFI_SUCCESS) > + return status; > + } > + if (pt3[pageidx >> 18] & 0x80) > + continue; > + grub_uint64_t *pt2 = (grub_uint64_t *) (pt3[pageidx >> 18] & > ~0xfff); > + if (!(pt2[pageidx >> 9] & 1)) { > + grub_efi_status_t status = create_paging_entry(&pt3[pageidx >> 9]); > + if (status != GRUB_EFI_SUCCESS) > + return status; > + } > + if (pt2[pageidx >> 9] & 0x80) > + continue; > + > + grub_uint64_t *pt1 = (grub_uint64_t *) (pt2[pageidx >> 9] & ~0xfff); > + if (!(pt1[pageidx] & 1)) { > + pt1[pageidx] = (pageidx << 12) | 7; > + } > + } > + > + return GRUB_EFI_SUCCESS; > +} > diff --git a/include/grub/efi/memory.h b/include/grub/efi/memory.h > index 08fe62277..2e5e4f84a 100644 > --- a/include/grub/efi/memory.h > +++ b/include/grub/efi/memory.h > @@ -21,6 +21,7 @@ > > #include <grub/err.h> > #include <grub/types.h> > +#include <grub/efi/api.h> > > /* The term "page" in UEFI refers only to a 4 KiB-aligned 4 KiB size > region of > memory. It is not concerned with underlying translation management > concepts, > @@ -35,4 +36,8 @@ grub_err_t grub_machine_mmap_register (grub_uint64_t > start, grub_uint64_t size, > int type, int handle); > grub_err_t grub_machine_mmap_unregister (int handle); > > +grub_efi_status_t > +grub_efi_arch_ensure_mapping (grub_efi_physical_address_t address, > + grub_efi_uintn_t pages); > + > #endif /* ! GRUB_MEMORY_MACHINE_HEADER */ > -- > 2.49.0 > >
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel