This command for x86_64 and arm64 shows current paging table on platforms in question.
Signed-off-by: Vladimir Serbinenko <phco...@gmail.com> --- grub-core/Makefile.core.def | 8 ++ grub-core/commands/arm64/lspaging.c | 138 +++++++++++++++++++++++++++ grub-core/commands/x86_64/lspaging.c | 115 ++++++++++++++++++++++ 3 files changed, 261 insertions(+) create mode 100644 grub-core/commands/arm64/lspaging.c create mode 100644 grub-core/commands/x86_64/lspaging.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index f70e02e69..7f8cb3f7d 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -814,6 +814,14 @@ module = { enable = efi; }; +module = { + name = lspaging; + x86_64_efi = commands/x86_64/lspaging.c; + arm64_efi = commands/arm64/lspaging.c; + enable = arm64_efi; + enable = x86_64_efi; +}; + module = { name = lsefimmap; diff --git a/grub-core/commands/arm64/lspaging.c b/grub-core/commands/arm64/lspaging.c new file mode 100644 index 000000000..3d18a09c3 --- /dev/null +++ b/grub-core/commands/arm64/lspaging.c @@ -0,0 +1,138 @@ +/* lspaging.c - Display paging table. */ +/* + * 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/mm.h> +#include <grub/misc.h> +#include <grub/normal.h> +#include <grub/charset.h> +#include <grub/efi/api.h> +#include <grub/efi/efi.h> +#include <grub/dl.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +typedef enum {UNMAPPED, NONIDENTITY, IDENTITY} mapping_type_t; + +static const char *mapping_names[] = { + "unmapped", + "non-identity", + "identity", +}; + +static bool +process_level(grub_uint64_t *start_address, mapping_type_t *start_type, + grub_uint64_t *next_address, grub_uint64_t *lx, grub_uint64_t cur_address, int offset) +{ + mapping_type_t cur_type; + grub_uint64_t entry = ((grub_uint64_t *)*lx)[(cur_address >> offset) & 0x1ff]; + switch (entry & 3) + { + case 0: + case 2: + cur_type = UNMAPPED; + break; + case 3: /* Table entry */ + if (offset != 12) + { + *lx = (entry & 0xfffffffff000); + return false; + } + /* Fallthrough */ + case 1: + cur_type = ((entry & 0xfffffffff000) == (cur_address & 0xfffffffff000)) ? IDENTITY : NONIDENTITY; + break; + } + + *next_address = ((cur_address >> offset) + 1) << offset; + + if (*start_type != cur_type) + { + if (cur_address != 0) + grub_printf("%08lx-%08lx: %s\n", *start_address, cur_address, mapping_names[*start_type]); + *start_type = cur_type; + *start_address = cur_address; + } + + return true; +} + +static grub_err_t +grub_cmd_lspaging (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + grub_uint64_t tcr_el1, ttbr0_el1; + grub_uint64_t id_aa64mmfr3_el1; + asm volatile ("mrs %0, id_aa64mmfr3_el1": "=r"(id_aa64mmfr3_el1)); + + if (id_aa64mmfr3_el1 & 0xf) + { + grub_uint64_t tcr2_el1; + + asm volatile ("mrs %0, s3_0_c2_c0_3": "=r"(tcr2_el1)); + if ((tcr2_el1 >> 5) & 1) + return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET, "Parsing D128 tables isn't supported yet"); + } + asm volatile ("mrs %0, tcr_el1": "=r"(tcr_el1)); + + if ((tcr_el1 >> 14) & 3) + return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET, "non-4K page tables aren't supported yet"); + + grub_uint64_t t0sz = tcr_el1 & 0x3f; + + if (t0sz >= 25) + return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET, "T0SZ %ld isn't supported yet", t0sz); + + asm volatile ("mrs %0, ttbr0_el1": "=r"(ttbr0_el1)); + + grub_uint64_t baddr = (ttbr0_el1 & 0xfffffffffffell); + grub_uint64_t start_address = 0, cur_address = 0, next_address = 0; + mapping_type_t start_type = UNMAPPED; + + grub_printf("baddr=%lx\n", baddr); + + for (cur_address = 0; cur_address < 0x7fffffffffff; cur_address = next_address) + { + grub_uint64_t lx = baddr; + if (process_level(&start_address, &start_type, &next_address, &lx, cur_address, 39)) + continue; + if (process_level(&start_address, &start_type, &next_address, &lx, cur_address, 30)) + continue; + if (process_level(&start_address, &start_type, &next_address, &lx, cur_address, 21)) + continue; + process_level(&start_address, &start_type, &next_address, &lx, cur_address, 12); + } + + grub_printf("%08lx-%08lx: %s\n", start_address, cur_address, mapping_names[start_type]); + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lspaging) +{ + cmd = grub_register_command ("lspaging", grub_cmd_lspaging, "", + "Display paging table."); +} + +GRUB_MOD_FINI(lspaging) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/x86_64/lspaging.c b/grub-core/commands/x86_64/lspaging.c new file mode 100644 index 000000000..ddd39904f --- /dev/null +++ b/grub-core/commands/x86_64/lspaging.c @@ -0,0 +1,115 @@ +/* lspaging.c - Display paging table. */ +/* + * 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/mm.h> +#include <grub/misc.h> +#include <grub/normal.h> +#include <grub/charset.h> +#include <grub/efi/api.h> +#include <grub/efi/efi.h> +#include <grub/dl.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +typedef enum {UNMAPPED, NONIDENTITY, IDENTITY} mapping_type_t; + +static const char *mapping_names[] = { + "unmapped", + "non-identity", + "identity", +}; + +static bool +process_level(grub_uint64_t *start_address, mapping_type_t *start_type, + grub_uint64_t *next_address, grub_uint64_t *lx, grub_uint64_t cur_address, int offset) +{ + mapping_type_t cur_type; + grub_uint64_t entry = ((grub_uint64_t *)*lx)[(cur_address >> offset) & 0x1ff]; + if ((entry & 1) && offset != 12 && !(entry & 0x80)) + { + *lx = (entry & 0xfffffffff000); + return false; + } + + if ((entry & 1) == 0) + { + cur_type = UNMAPPED; + } + else + { + cur_type = ((entry & 0xfffffffff000) == (cur_address & 0xfffffffff000)) ? IDENTITY : NONIDENTITY; + } + + *next_address = ((cur_address >> offset) + 1) << offset; + + if (*start_type != cur_type) + { + if (cur_address != 0) + grub_printf("%08lx-%08lx: %s\n", *start_address, cur_address, mapping_names[*start_type]); + *start_type = cur_type; + *start_address = cur_address; + } + + return true; +} + +static grub_err_t +grub_cmd_lspaging (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + grub_uint64_t cr3; + + asm volatile ("movq %%cr3, %0": "=r"(cr3)); + + grub_uint64_t baddr = cr3; + grub_uint64_t start_address = 0, cur_address = 0, next_address = 0; + mapping_type_t start_type = UNMAPPED; + + grub_printf("baddr=%lx\n", baddr); + + for (cur_address = 0; cur_address < 0x7fffffffffff; cur_address = next_address) + { + grub_uint64_t lx = baddr; + if (process_level(&start_address, &start_type, &next_address, &lx, cur_address, 39)) + continue; + if (process_level(&start_address, &start_type, &next_address, &lx, cur_address, 30)) + continue; + if (process_level(&start_address, &start_type, &next_address, &lx, cur_address, 21)) + continue; + process_level(&start_address, &start_type, &next_address, &lx, cur_address, 12); + } + + grub_printf("%08lx-%08lx: %s\n", start_address, cur_address, mapping_names[start_type]); + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lspaging) +{ + cmd = grub_register_command ("lspaging", grub_cmd_lspaging, "", + "Display paging table."); +} + +GRUB_MOD_FINI(lspaging) +{ + grub_unregister_command (cmd); +} -- 2.49.0 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel