diff --git a/1000-loongarch64-add-support.patch b/1002-Add-LoongArch64-support-and-update-interface-to-v40.patch similarity index 64% rename from 1000-loongarch64-add-support.patch rename to 1002-Add-LoongArch64-support-and-update-interface-to-v40.patch index 2d83c94d0394b9a249b1a7d2feeda5cdaeaa43f2..4ffe55b3933876d048391fcd8e807646da5dd233 100644 --- a/1000-loongarch64-add-support.patch +++ b/1002-Add-LoongArch64-support-and-update-interface-to-v40.patch @@ -1,87 +1,11 @@ -From febee03c70471fd2ce6f0b4cc0f365c32c106ab3 Mon Sep 17 00:00:00 2001 -From: Fedora Ninjas -Date: Wed, 18 May 2022 23:50:45 +0800 -Subject: [PATCH] add loongarch64 support +From 06644f983935661fa4a8da2d14c574ccd810fe7e Mon Sep 17 00:00:00 2001 +From: yangqiming +Date: Wed, 6 Jul 2022 15:30:44 +0800 +Subject: [PATCH] Add LoongArch64 support and update interface to v40 ---- - conf/Makefile.common | 4 + - configure.ac | 9 + - gentpl.py | 5 +- - grub-core/Makefile.am | 7 + - grub-core/Makefile.core.def | 20 + - grub-core/kern/efi/mm.c | 29 +- - grub-core/kern/elfXX.c | 6 + - grub-core/kern/loongarch64/cache.S | 26 + - grub-core/kern/loongarch64/dl.c | 258 +++++++++ - grub-core/kern/loongarch64/efi/init.c | 76 +++ - grub-core/kern/loongarch64/efi/startup.S | 45 ++ - grub-core/kern/loongarch64/init.c | 47 ++ - grub-core/lib/loongarch64/efi/loongson.c | 505 ++++++++++++++++ - grub-core/lib/loongarch64/efi/loongson_asm.S | 58 ++ - grub-core/lib/loongarch64/relocator.c | 163 ++++++ - grub-core/lib/loongarch64/relocator_asm.S | 51 ++ - grub-core/lib/loongarch64/setjmp.S | 74 +++ - grub-core/lib/loongson/reboot.c | 33 ++ - grub-core/lib/setjmp.S | 2 + - grub-core/loader/efi/chainloader.c | 2 + - grub-core/loader/loongarch64/linux.c | 580 +++++++++++++++++++ - include/grub/dl.h | 2 +- - include/grub/efi/api.h | 3 +- - include/grub/efi/pe32.h | 2 + - include/grub/elf.h | 55 ++ - include/grub/loongarch64/asm.h | 10 + - include/grub/loongarch64/efi/boot.h | 0 - include/grub/loongarch64/efi/loader.h | 25 + - include/grub/loongarch64/efi/loongson.h | 290 ++++++++++ - include/grub/loongarch64/efi/memory.h | 14 + - include/grub/loongarch64/efi/time.h | 0 - include/grub/loongarch64/io.h | 62 ++ - include/grub/loongarch64/kernel.h | 24 + - include/grub/loongarch64/linux.h | 22 + - include/grub/loongarch64/loongarch64.h | 30 + - include/grub/loongarch64/memory.h | 57 ++ - include/grub/loongarch64/relocator.h | 38 ++ - include/grub/loongarch64/setjmp.h | 27 + - include/grub/loongarch64/time.h | 39 ++ - include/grub/loongarch64/types.h | 34 ++ - include/grub/util/install.h | 1 + - util/grub-install-common.c | 43 +- - util/grub-install.c | 16 + - util/grub-mkimagexx.c | 349 ++++++++++- - util/grub-mknetdir.c | 3 +- - util/grub-module-verifier.c | 46 ++ - util/mkimage.c | 16 + - 47 files changed, 3176 insertions(+), 32 deletions(-) - create mode 100644 grub-core/kern/loongarch64/cache.S - create mode 100644 grub-core/kern/loongarch64/dl.c - create mode 100644 grub-core/kern/loongarch64/efi/init.c - create mode 100644 grub-core/kern/loongarch64/efi/startup.S - create mode 100644 grub-core/kern/loongarch64/init.c - create mode 100644 grub-core/lib/loongarch64/efi/loongson.c - create mode 100644 grub-core/lib/loongarch64/efi/loongson_asm.S - create mode 100644 grub-core/lib/loongarch64/relocator.c - create mode 100644 grub-core/lib/loongarch64/relocator_asm.S - create mode 100644 grub-core/lib/loongarch64/setjmp.S - create mode 100644 grub-core/lib/loongson/reboot.c - create mode 100644 grub-core/loader/loongarch64/linux.c - create mode 100644 include/grub/loongarch64/asm.h - create mode 100644 include/grub/loongarch64/efi/boot.h - create mode 100644 include/grub/loongarch64/efi/loader.h - create mode 100644 include/grub/loongarch64/efi/loongson.h - create mode 100644 include/grub/loongarch64/efi/memory.h - create mode 100644 include/grub/loongarch64/efi/time.h - create mode 100644 include/grub/loongarch64/io.h - create mode 100644 include/grub/loongarch64/kernel.h - create mode 100644 include/grub/loongarch64/linux.h - create mode 100644 include/grub/loongarch64/loongarch64.h - create mode 100644 include/grub/loongarch64/memory.h - create mode 100644 include/grub/loongarch64/relocator.h - create mode 100644 include/grub/loongarch64/setjmp.h - create mode 100644 include/grub/loongarch64/time.h - create mode 100644 include/grub/loongarch64/types.h diff --git a/conf/Makefile.common b/conf/Makefile.common -index 521cdda..cc1d190 100644 +index 521cdda..d9f058b 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -20,6 +20,10 @@ endif @@ -89,8 +13,8 @@ index 521cdda..cc1d190 100644 CFLAGS_PLATFORM += -mcpu=powerpc endif +if COND_loongarch64 -+ CFLAGS_PLATFORM += -fno-strict-aliasing -march=loongarch64 -mabi=lp64 -fno-plt -Wa,-mla-global-with-pcrel -+ CPPFLAGS_PLATFORM = -fno-strict-aliasing -march=loongarch64 -mabi=lp64 -fno-plt -Wa,-mla-global-with-pcrel ++ CFLAGS_PLATFORM += -fno-strict-aliasing -march=loongarch64 -mabi=lp64 -fno-plt -Wa,-mla-global-with-abs -mcmodel=large ++ CPPFLAGS_PLATFORM = -fno-strict-aliasing -march=loongarch64 -mabi=lp64 -fno-plt -Wa,-mla-global-with-abs -mcmodel=large +endif # Other options @@ -173,10 +97,10 @@ index d662c30..3afd642 100644 GROUPS["uboot"] = [ "arm_uboot" ] GROUPS["xen"] = [ "i386_xen", "x86_64_xen" ] diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am -index 308ad88..24e2ac3 100644 +index 308ad88..a976fad 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am -@@ -222,6 +222,13 @@ KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h +@@ -222,6 +222,14 @@ KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h endif @@ -184,6 +108,7 @@ index 308ad88..24e2ac3 100644 +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdt.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loongson.h +endif + @@ -191,7 +116,7 @@ index 308ad88..24e2ac3 100644 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index ef06f8c..74e66d3 100644 +index ef06f8c..54f6bf0 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -95,6 +95,9 @@ kernel = { @@ -212,7 +137,7 @@ index ef06f8c..74e66d3 100644 sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S; powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S; arm_uboot_startup = kern/arm/startup.S; -@@ -295,6 +299,14 @@ kernel = { +@@ -295,6 +299,15 @@ kernel = { extra_dist = video/sis315_init.c; mips_loongson = commands/keylayouts.c; @@ -220,14 +145,15 @@ index ef06f8c..74e66d3 100644 + loongarch64 = kern/loongarch64/dl.c; + loongarch64 = kern/loongarch64/cache.S; + loongarch64 = kern/generic/rtc_get_time_ms.c; ++ loongarch64 = kern/efi/fdt.c; ++ loongarch64 = lib/fdt.c; + loongarch64_efi = kern/loongarch64/efi/init.c; + loongarch64_efi = lib/loongarch64/efi/loongson.c; -+ loongarch64_efi = lib/loongarch64/efi/loongson_asm.S; + powerpc_ieee1275 = kern/powerpc/cache.S; powerpc_ieee1275 = kern/powerpc/dl.c; powerpc_ieee1275 = kern/powerpc/compiler-rt.S; -@@ -810,6 +822,7 @@ module = { +@@ -810,6 +823,7 @@ module = { enable = sparc64_ieee1275; enable = powerpc_ieee1275; enable = mips_arc; @@ -235,7 +161,7 @@ index ef06f8c..74e66d3 100644 enable = ia64_efi; enable = arm_efi; enable = arm64_efi; -@@ -896,6 +909,7 @@ module = { +@@ -896,6 +910,7 @@ module = { i386_qemu = lib/i386/halt.c; xen = lib/xen/halt.c; efi = lib/efi/halt.c; @@ -243,7 +169,7 @@ index ef06f8c..74e66d3 100644 ieee1275 = lib/ieee1275/halt.c; emu = lib/emu/halt.c; uboot = lib/dummy/halt.c; -@@ -911,6 +925,7 @@ module = { +@@ -911,6 +926,7 @@ module = { mips_arc = lib/mips/arc/reboot.c; mips_loongson = lib/mips/loongson/reboot.c; mips_qemu_mips = lib/mips/qemu_mips/reboot.c; @@ -251,7 +177,7 @@ index ef06f8c..74e66d3 100644 xen = lib/xen/reboot.c; uboot = lib/uboot/reboot.c; arm_coreboot = lib/dummy/reboot.c; -@@ -1608,6 +1623,8 @@ module = { +@@ -1608,6 +1624,8 @@ module = { efi = lib/efi/relocator.c; mips = lib/mips/relocator_asm.S; mips = lib/mips/relocator.c; @@ -260,7 +186,7 @@ index ef06f8c..74e66d3 100644 powerpc = lib/powerpc/relocator_asm.S; powerpc = lib/powerpc/relocator.c; xen = lib/xen/relocator.c; -@@ -1620,6 +1637,7 @@ module = { +@@ -1620,6 +1638,7 @@ module = { extra_dist = kern/powerpc/cache_flush.S; enable = mips; @@ -268,7 +194,7 @@ index ef06f8c..74e66d3 100644 enable = powerpc; enable = x86; enable = xen; -@@ -1737,6 +1755,7 @@ module = { +@@ -1737,6 +1756,7 @@ module = { xen = loader/i386/xen.c; i386_pc = lib/i386/pc/vesa_modes_table.c; mips = loader/mips/linux.c; @@ -276,7 +202,7 @@ index ef06f8c..74e66d3 100644 powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c; sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c; ia64_efi = loader/ia64/efi/linux.c; -@@ -1838,6 +1857,7 @@ module = { +@@ -1838,6 +1858,7 @@ module = { enable = arm_efi; enable = arm64_efi; enable = mips; @@ -285,22 +211,42 @@ index ef06f8c..74e66d3 100644 module = { diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index 9e76f23..fb087e3 100644 +index 9e76f23..c1dd6d2 100644 --- a/grub-core/kern/efi/mm.c +++ b/grub-core/kern/efi/mm.c -@@ -157,7 +157,11 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, +@@ -122,7 +122,11 @@ grub_efi_allocate_pages_max (grub_efi_physical_address_t max, + grub_efi_boot_services_t *b; + grub_efi_physical_address_t address = max; + ++#ifdef GRUB_CPU_LOONGARCH64 ++ if (max > grub_efi_max_usable_address()) ++#else + if (max > GRUB_EFI_MAX_USABLE_ADDRESS) ++#endif + return 0; + + b = grub_efi_system_table->boot_services; +@@ -157,11 +161,19 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, grub_efi_physical_address_t ret = address; /* Limit the memory access to less than 4GB for 32-bit platforms. */ +#ifdef GRUB_CPU_LOONGARCH64 + if (address > grub_efi_max_usable_address()) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("invalid memory address 0x%llx"), ++ address); +#else if (address > GRUB_EFI_MAX_USABLE_ADDRESS) -+#endif { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid memory address (0x%llx > 0x%llx)"), -@@ -177,7 +181,11 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, + address, GRUB_EFI_MAX_USABLE_ADDRESS); ++#endif + return NULL; + } + +@@ -177,7 +189,11 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, { /* Uggh, the address 0 was allocated... This is too annoying, so reallocate another one. */ @@ -312,23 +258,23 @@ index 9e76f23..fb087e3 100644 status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &ret); grub_efi_free_pages (0, pages); if (status != GRUB_EFI_SUCCESS) -@@ -195,9 +203,14 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, +@@ -195,9 +211,15 @@ grub_efi_allocate_pages_real (grub_efi_physical_address_t address, void * grub_efi_allocate_any_pages (grub_efi_uintn_t pages) { -- return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS, +#ifdef GRUB_CPU_LOONGARCH64 + return grub_efi_allocate_pages_real (grub_efi_max_usable_address(), ++ pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, ++ GRUB_EFI_LOADER_DATA); ++#else + return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS, pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA); -+#else -+ return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS, -+ pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, -+#endif GRUB_EFI_LOADER_DATA); ++#endif } void * -@@ -471,7 +484,9 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, +@@ -471,7 +493,9 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) { if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY @@ -339,11 +285,10 @@ index 9e76f23..fb087e3 100644 && desc->physical_start <= GRUB_EFI_MAX_ALLOCATION_ADDRESS #endif && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000 -@@ -486,8 +501,14 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, - - desc->physical_start); +@@ -487,7 +511,14 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, desc->physical_start = 0x100000; } -- + -#if 1 +#ifdef GRUB_CPU_LOONGARCH64 + if (BYTES_TO_PAGES (filtered_desc->physical_start) @@ -356,23 +301,43 @@ index 9e76f23..fb087e3 100644 if (BYTES_TO_PAGES (filtered_desc->physical_start) + filtered_desc->num_pages > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS)) -diff --git a/grub-core/kern/elfXX.c b/grub-core/kern/elfXX.c -index 1859d18..8b1dce9 100644 ---- a/grub-core/kern/elfXX.c -+++ b/grub-core/kern/elfXX.c -@@ -134,6 +134,12 @@ grub_elfXX_load (grub_elf_t elf, const char *filename, - load_addr &= 0x3FFFFFFFFFFFFFFFULL; - break; - } +@@ -687,7 +718,7 @@ grub_efi_mm_init (void) + 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + } + +-#if defined (__aarch64__) || defined (__arm__) ++#if defined (__aarch64__) || defined (__arm__) || defined (__loongarch__) + grub_err_t + grub_efi_get_ram_base(grub_addr_t *base_addr) + { +@@ -706,9 +737,15 @@ grub_efi_get_ram_base(grub_addr_t *base_addr) + if (ret < 1) + return GRUB_ERR_BUG; + ++#ifdef GRUB_CPU_LOONGARCH64 ++ for (desc = memory_map, *base_addr = grub_efi_max_usable_address(); ++ (grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size); ++ desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) ++#else + for (desc = memory_map, *base_addr = GRUB_EFI_MAX_USABLE_ADDRESS; + (grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size); + desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) ++#endif + { + if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY && + (desc->attribute & GRUB_EFI_MEMORY_WB)) +@@ -722,7 +759,11 @@ grub_efi_get_ram_base(grub_addr_t *base_addr) + } + } + +#ifdef GRUB_CPU_LOONGARCH64 -+ grub_uint64_t addr; -+ asm volatile ("csrrd %0, 0x181" : "=r" (addr)); -+ if ((load_addr >> 48) != (addr >> 48)) -+ return grub_error (GRUB_ERR_BAD_OS, "bad address space"); ++ if (*base_addr == grub_efi_max_usable_address()) ++#else + if (*base_addr == GRUB_EFI_MAX_USABLE_ADDRESS) +#endif - load_addr += (grub_addr_t) load_offset; + grub_dprintf ("efi", "base_addr 0x%016lx is probably wrong.\n", *base_addr); - if (load_addr < load_base) + grub_free(memory_map); diff --git a/grub-core/kern/loongarch64/cache.S b/grub-core/kern/loongarch64/cache.S new file mode 100644 index 0000000..d291c67 @@ -671,10 +636,10 @@ index 0000000..a6fd387 + diff --git a/grub-core/kern/loongarch64/efi/init.c b/grub-core/kern/loongarch64/efi/init.c new file mode 100644 -index 0000000..b21d4f1 +index 0000000..632c39a --- /dev/null +++ b/grub-core/kern/loongarch64/efi/init.c -@@ -0,0 +1,76 @@ +@@ -0,0 +1,74 @@ +/* init.c - initialize an arm-based EFI system */ +/* + * GRUB -- GRand Unified Bootloader @@ -698,7 +663,7 @@ index 0000000..b21d4f1 +#include +#include +#include -+#include ++#include +#include +#include +#include @@ -719,15 +684,13 @@ index 0000000..b21d4f1 + tmr += 10; +} + -+ -+ +void +grub_machine_init (void) +{ + grub_efi_boot_services_t *b; + + grub_efi_init (); -+ ++ + b = grub_efi_system_table->boot_services; + efi_call_5 (b->create_event, GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL, + GRUB_EFI_TPL_CALLBACK, grub_loongson_increment_timer, NULL, &tmr_evt); @@ -857,10 +820,10 @@ index 0000000..b2de930 +} diff --git a/grub-core/lib/loongarch64/efi/loongson.c b/grub-core/lib/loongarch64/efi/loongson.c new file mode 100644 -index 0000000..8b60d82 +index 0000000..eda1e1c --- /dev/null +++ b/grub-core/lib/loongarch64/efi/loongson.c -@@ -0,0 +1,505 @@ +@@ -0,0 +1,119 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2017 Free Software Foundation, Inc. @@ -886,400 +849,14 @@ index 0000000..8b60d82 +#include +#include + -+#define loongson_params (&loongson_boot_params->boot_params.efi.smbios.lp) -+#define loongson_boot_params_size ALIGN_UP (sizeof (*loongson_boot_params), 8) -+#define loongson_reset_code_size (&grub_efi_loongson_reset_end - &grub_efi_loongson_reset_start) -+ -+extern grub_uint8_t grub_efi_loongson_reset_start; -+extern grub_uint8_t grub_efi_loongson_reset_end; -+ -+static struct -+{ -+ grub_efi_loongson_boot_params boot_params; -+ grub_efi_loongson_memory_map memory_map; -+ grub_efi_loongson_cpu_info cpu_info; -+ grub_efi_loongson_system_info system_info; -+ grub_efi_loongson_irq_src_routing_table irq_src_routing_table; -+ grub_efi_loongson_interface_info interface_info; -+ grub_efi_loongson_special_attribute special_attribute; -+ grub_efi_loongson_board_devices board_devices; -+} GRUB_PACKED -+* loongson_boot_params; -+ -+static void -+grub_efi_loongson_init_reset_system (void) -+{ -+ grub_efi_loongson_boot_params *boot_params; -+ grub_uint8_t *reset_code_addr = (grub_uint8_t *) loongson_boot_params + -+ loongson_boot_params_size; -+ -+ boot_params = &loongson_boot_params->boot_params; -+ grub_efi_loongson_reset_system_addr = -+ (grub_uint64_t) grub_efi_system_table->runtime_services->reset_system; -+ grub_memcpy (reset_code_addr, &grub_efi_loongson_reset_start, loongson_reset_code_size); -+ grub_arch_sync_caches (reset_code_addr, loongson_reset_code_size); -+ -+ boot_params->reset_system.reset_cold = (grub_uint64_t) reset_code_addr + -+ ((grub_uint64_t) &grub_efi_loongson_reset_cold - -+ (grub_uint64_t) &grub_efi_loongson_reset_start); -+ boot_params->reset_system.reset_warm = (grub_uint64_t) reset_code_addr + -+ ((grub_uint64_t) &grub_efi_loongson_reset_warm - -+ (grub_uint64_t) &grub_efi_loongson_reset_start); -+ boot_params->reset_system.shutdown = (grub_uint64_t) reset_code_addr + -+ ((grub_uint64_t) &grub_efi_loongson_reset_shutdown - -+ (grub_uint64_t) &grub_efi_loongson_reset_start); -+ boot_params->reset_system.do_suspend = (grub_uint64_t) reset_code_addr + -+ ((grub_uint64_t) &grub_efi_loongson_reset_suspend - -+ (grub_uint64_t) &grub_efi_loongson_reset_start); -+} -+ -+static void -+grub_efi_loongson_init_smbios (grub_efi_loongson_smbios_table *smbios_table) -+{ -+ grub_efi_loongson_smbios_table *dst = &loongson_boot_params->boot_params.efi.smbios; -+ -+ dst->vers = smbios_table->vers; -+ dst->vga_bios = smbios_table->vga_bios; -+} -+ -+static void -+grub_efi_loongson_init_cpu_info (grub_efi_loongson_smbios_table *smbios_table) -+{ -+ grub_efi_loongson_cpu_info *src = (void *) smbios_table->lp.cpu_offset; -+ grub_efi_loongson_cpu_info *dst = &loongson_boot_params->cpu_info; -+ -+ if (!src) -+ return; -+ -+ grub_memcpy (dst, src, sizeof (grub_efi_loongson_cpu_info)); -+ loongson_params->cpu_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; -+} -+ -+static void -+grub_efi_loongson_init_system_info (grub_efi_loongson_smbios_table *smbios_table) -+{ -+ grub_efi_loongson_system_info *src = (void *) smbios_table->lp.system_offset; -+ grub_efi_loongson_system_info *dst = &loongson_boot_params->system_info; -+ -+ if (!src) -+ return; -+ -+ grub_memcpy (dst, src, sizeof (grub_efi_loongson_system_info)); -+ loongson_params->system_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; -+} -+ -+static void -+grub_efi_loongson_init_irq_src_routing_table (grub_efi_loongson_smbios_table *smbios_table) -+{ -+ grub_efi_loongson_irq_src_routing_table *src = (void *) smbios_table->lp.irq_offset; -+ grub_efi_loongson_irq_src_routing_table *dst = &loongson_boot_params->irq_src_routing_table; -+ -+ if (!src) -+ return; -+ -+ grub_memcpy (dst, src, sizeof (grub_efi_loongson_irq_src_routing_table)); -+ loongson_params->irq_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; -+} -+ -+static void -+grub_efi_loongson_init_interface_info (grub_efi_loongson_smbios_table *smbios_table) -+{ -+ grub_efi_loongson_interface_info *src = (void *) smbios_table->lp.interface_offset; -+ grub_efi_loongson_interface_info *dst = &loongson_boot_params->interface_info; -+ -+ if (!src) -+ return; -+ -+ grub_memcpy (dst, src, sizeof (grub_efi_loongson_interface_info)); -+ loongson_params->interface_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; -+} -+ -+static void -+grub_efi_loongson_init_special_attribute (grub_efi_loongson_smbios_table *smbios_table) -+{ -+ grub_efi_loongson_special_attribute *src = (void *) smbios_table->lp.special_offset; -+ grub_efi_loongson_special_attribute *dst = &loongson_boot_params->special_attribute; -+ -+ if (!src) -+ return; -+ -+ grub_memcpy (dst, src, sizeof (grub_efi_loongson_special_attribute)); -+ loongson_params->special_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; -+} -+ -+static void -+grub_efi_loongson_init_board_devices (grub_efi_loongson_smbios_table *smbios_table) -+{ -+ grub_efi_loongson_board_devices *src = (void *) smbios_table->lp.boarddev_table_offset; -+ grub_efi_loongson_board_devices *dst = &loongson_boot_params->board_devices; -+ -+ if (!src) -+ return; -+ -+ grub_memcpy (dst, src, sizeof (grub_efi_loongson_board_devices)); -+ loongson_params->boarddev_table_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; -+} -+ -+#define ADD_MEMORY_DESCRIPTOR(desc, size) \ -+ ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) -+ -+static void -+grub_efi_loongson_init_memory_map (grub_efi_loongson_smbios_table *smbios_table, -+ grub_efi_memory_descriptor_t *mmap_buf, -+ grub_efi_uintn_t mmap_size, -+ grub_efi_uintn_t desc_size) -+{ -+ grub_efi_loongson_memory_map *src = (void *) smbios_table->lp.memory_offset; -+ grub_efi_loongson_memory_map *dst = &loongson_boot_params->memory_map; -+ grub_efi_memory_descriptor_t *mmap_end; -+ grub_efi_memory_descriptor_t *desc; -+ grub_efi_memory_descriptor_t *desc_next; -+ grub_efi_uint32_t mem_types_reserved[] = -+ { -+ 1, // GRUB_EFI_RESERVED_MEMORY_TYPE -+ 0, // GRUB_EFI_LOADER_CODE -+ 0, // GRUB_EFI_LOADER_DATA -+ 0, // GRUB_EFI_BOOT_SERVICES_CODE -+ 0, // GRUB_EFI_BOOT_SERVICES_DATA -+ 1, // GRUB_EFI_RUNTIME_SERVICES_CODE -+ 1, // GRUB_EFI_RUNTIME_SERVICES_DATA -+ 0, // GRUB_EFI_CONVENTIONAL_MEMORY -+ 1, // GRUB_EFI_UNUSABLE_MEMORY -+ 0, // GRUB_EFI_ACPI_RECLAIM_MEMORY -+ 0, // GRUB_EFI_ACPI_MEMORY_NVS -+ 1, // GRUB_EFI_MEMORY_MAPPED_IO -+ 1, // GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE -+ 1, // GRUB_EFI_PAL_CODE -+ 1, // GRUB_EFI_PERSISTENT_MEMORY -+ }; -+ grub_uint32_t need_sort = 1; -+ -+ if (!src) -+ return; -+ -+ dst->vers = src->vers; -+ dst->nr_map = 0; -+ dst->mem_freq = src->mem_freq; -+ loongson_params->memory_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params; -+ -+ if (!mmap_buf || !mmap_size || !desc_size) -+ return; -+ -+ mmap_end = ADD_MEMORY_DESCRIPTOR (mmap_buf, mmap_size); -+ -+ /* drop reserved */ -+ for (desc = mmap_buf, -+ desc_next = desc; -+ desc < mmap_end; -+ desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size)) -+ { -+ desc->type = mem_types_reserved[desc->type]; -+ if (desc->type) -+ continue; -+ -+ if (desc != desc_next) -+ *desc_next = *desc; -+ desc_next = ADD_MEMORY_DESCRIPTOR (desc_next, desc_size); -+ } -+ mmap_end = desc_next; -+ -+ /* sort: low->high */ -+ while (need_sort) -+ { -+ need_sort = 0; -+ -+ for (desc = mmap_buf, -+ desc_next = ADD_MEMORY_DESCRIPTOR (desc, desc_size); -+ (desc < mmap_end) && (desc_next < mmap_end); -+ desc = desc_next, -+ desc_next = ADD_MEMORY_DESCRIPTOR (desc, desc_size)) -+ { -+ grub_efi_memory_descriptor_t tmp; -+ -+ if (desc->physical_start <= desc_next->physical_start) -+ continue; -+ -+ tmp = *desc; -+ *desc = *desc_next; -+ *desc_next = tmp; -+ need_sort = 1; -+ } -+ } -+ -+ /* combine continuous memory map */ -+ for (desc = mmap_buf, -+ desc_next = ADD_MEMORY_DESCRIPTOR (desc, desc_size); -+ desc_next < mmap_end; -+ desc_next = ADD_MEMORY_DESCRIPTOR (desc_next, desc_size)) -+ { -+ grub_efi_physical_address_t prev_end = desc->physical_start + (desc->num_pages << 12); -+ -+ if (prev_end == desc_next->physical_start) -+ { -+ desc->num_pages += desc_next->num_pages; -+ continue; -+ } -+ -+ desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size); -+ grub_memcpy (desc, desc_next, desc_size); -+ } -+ mmap_end = ADD_MEMORY_DESCRIPTOR (desc, desc_size); -+ -+ /* write to loongson memory map */ -+ for (desc = mmap_buf; -+ desc < mmap_end; -+ desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size)) -+ { -+ grub_efi_physical_address_t physical_start = grub_vtop ((void *) desc->physical_start); -+ grub_efi_physical_address_t physical_end = physical_start + (desc->num_pages << 12); -+ -+ physical_start = ALIGN_UP (physical_start, 0x100000); -+ physical_end = ALIGN_DOWN (physical_end, 0x100000); -+ -+ if (physical_start >= physical_end || (physical_end - physical_start) < 0x100000) -+ continue; -+ -+ dst->map[dst->nr_map].node_id = (desc->physical_start >> 44) & 0xf; -+ dst->map[dst->nr_map].mem_type = GRUB_EFI_LOONGSON_SYSTEM_RAM; -+ dst->map[dst->nr_map].mem_start = physical_start; -+ dst->map[dst->nr_map].mem_size = (physical_end - physical_start) >> 20; -+ -+ grub_dprintf ("loongson", "memory map %03u: 0x%016lx 0x%016lx @ %u\n", -+ dst->nr_map, physical_start, physical_end - physical_start, -+ dst->map[dst->nr_map].node_id); -+ -+ dst->nr_map ++; -+ } -+} -+ -+#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) -+#define SUB_MEMORY_DESCRIPTOR(desc, size) \ -+ ((grub_efi_memory_descriptor_t *) ((char *) (desc) - (size))) -+ -+void -+grub_efi_loongson_alloc_boot_params (void) -+{ -+ grub_efi_memory_descriptor_t *mmap_buf; -+ grub_efi_memory_descriptor_t *mmap_end; -+ grub_efi_memory_descriptor_t *desc; -+ grub_efi_uintn_t mmap_size; -+ grub_efi_uintn_t desc_size; -+ grub_efi_physical_address_t address; -+ grub_efi_allocate_type_t type; -+ grub_efi_uintn_t pages; -+ grub_efi_status_t status; -+ grub_efi_boot_services_t *b; -+ int mm_status; -+ -+ type = GRUB_EFI_ALLOCATE_ADDRESS; -+ pages = BYTES_TO_PAGES (loongson_boot_params_size + loongson_reset_code_size); -+ -+ mmap_size = (1 << 12); -+ mmap_buf = grub_malloc (mmap_size); -+ if (!mmap_buf) -+ grub_fatal ("out of memory!"); -+ -+ mm_status = grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0); -+ if (mm_status == 0) -+ { -+ grub_free (mmap_buf); -+ mmap_size += desc_size * 32; -+ -+ mmap_buf = grub_malloc (mmap_size); -+ if (!mmap_buf) -+ grub_fatal ("out of memory!"); -+ -+ mm_status = grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0); -+ } -+ -+ if (mm_status < 0) -+ grub_fatal ("cannot get memory map!"); -+ -+ mmap_end = ADD_MEMORY_DESCRIPTOR (mmap_buf, mmap_size); -+ -+ for (desc = SUB_MEMORY_DESCRIPTOR (mmap_end, desc_size); -+ desc >= mmap_buf; -+ desc = SUB_MEMORY_DESCRIPTOR (desc, desc_size)) -+ { -+ if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY) -+ continue; -+ if (desc->physical_start >= grub_efi_max_usable_address()) -+ continue; -+ if (desc->num_pages < pages) -+ continue; -+ -+ address = desc->physical_start; -+ break; -+ } -+ -+ grub_free (mmap_buf); -+ -+ b = grub_efi_system_table->boot_services; -+ status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_RUNTIME_SERVICES_DATA, pages, &address); -+ if (status != GRUB_EFI_SUCCESS) -+ grub_fatal ("cannot allocate Loongson boot parameters!"); -+ -+ loongson_boot_params = (void *) ((grub_addr_t) address); -+} -+ -+void -+grub_efi_loongson_free_boot_params (void) -+{ -+ grub_efi_free_pages ((grub_addr_t) loongson_boot_params, -+ BYTES_TO_PAGES (loongson_boot_params_size + loongson_reset_code_size)); -+} -+ -+void * -+grub_efi_loongson_get_smbios_table (void) ++unsigned long ++grub_efi_get_bpi_version (const char *str) +{ -+ static grub_efi_loongson_smbios_table *smbios_table; -+ grub_efi_loongson_boot_params *old_boot_params; -+ struct bootparamsinterface* boot_params; -+ void * tmp_boot_params = NULL; -+ char * p = NULL; -+ if(smbios_table) -+ return smbios_table; -+ -+ tmp_boot_params = grub_efi_loongson_get_boot_params(); -+ if(tmp_boot_params == NULL) -+ { -+ grub_dprintf("loongson", "tmp_boot_params is NULL\n"); -+ return tmp_boot_params; -+ } -+ -+ boot_params = (struct bootparamsinterface *)tmp_boot_params; -+ p = (char *)&(boot_params->signature); -+ if(grub_strncmp(p, "BPI", 3) == 0) -+ { -+ grub_dprintf("loongson", "find new bpi\n"); -+ return boot_params ? boot_params : 0; -+ } -+ else -+ { -+ old_boot_params = (grub_efi_loongson_boot_params *)tmp_boot_params; -+ /* -+ { -+ grub_dprintf("loongson", "smbios addr%llx\n", &old_boot_params->efi.smbios); -+ grub_dprintf("loongson", "smbios vers%d\n", (grub_uint16_t)(&old_boot_params->efi.smbios.vers)); -+ grub_dprintf("loongson", "smbios vga_bios%d\n", &old_boot_params->efi.smbios.vga_bios); -+ grub_dprintf("loongson", "lp memory offset %llx\n", &old_boot_params->efi.smbios.lp.memory_offset); -+ grub_dprintf("loongson", "lp cpu offset %llx\n", &old_boot_params->efi.smbios.lp.cpu_offset); -+ grub_dprintf("loongson", "lp system offset %llx\n", &old_boot_params->efi.smbios.lp.system_offset); -+ grub_dprintf("loongson", "lp irq offset %llx\n", &old_boot_params->efi.smbios.lp.irq_offset); -+ grub_dprintf("loongson", "lp interface offset %llx\n", &old_boot_params->efi.smbios.p.interface_offset); -+ grub_dprintf("loongson", "lp special offset %llx\n", &old_boot_params->efi.smbios.lp.special_offset); -+ grub_dprintf("loongson", "lp boarddev table offset %llx\n", &old_boot_params->efi.smbios.lp.boarddev_table_offset); -+ } -+ */ -+ return old_boot_params ? &old_boot_params->efi.smbios : 0; -+ } ++ unsigned long version = GRUB_EFI_BPI_VER_NONE; + -+} ++ version = grub_strtoul (str + 4, 0, 0); + -+int -+grub_efi_is_loongson (void) -+{ -+ return grub_efi_loongson_get_smbios_table () ? 1 : 0; ++ return version; +} + +void * @@ -1287,20 +864,20 @@ index 0000000..8b60d82 +{ + static void * boot_params = NULL; + grub_efi_configuration_table_t *tables; -+ grub_efi_guid_t smbios_guid = GRUB_EFI_LOONGSON_SMBIOS_TABLE_GUID; ++ grub_efi_guid_t loongson_bpi_guid = GRUB_EFI_LOONGSON_BPI_TABLE_GUID; + unsigned int i; + + if (boot_params) + return boot_params; + -+ /* Look for Loongson SMBIOS in UEFI config tables. */ ++ /* Look for Loongson boot params interface in UEFI config tables. */ + tables = grub_efi_system_table->configuration_table; + + for (i = 0; i < grub_efi_system_table->num_table_entries; i++) -+ if (grub_memcmp (&tables[i].vendor_guid, &smbios_guid, sizeof (smbios_guid)) == 0) ++ if (grub_memcmp (&tables[i].vendor_guid, &loongson_bpi_guid, sizeof (loongson_bpi_guid)) == 0) + { + boot_params= tables[i].vendor_table; -+ grub_dprintf ("loongson", "found registered SMBIOS @ %p\n", boot_params); ++ grub_dprintf ("loongson", "found registered BPI @ %p\n", boot_params); + break; + } + return boot_params; @@ -1330,8 +907,9 @@ index 0000000..8b60d82 +} + + -+grub_uint32_t -+grub_efi_loongson_memmap_sort(struct memmap array[], grub_uint32_t length, mem_map * bpmem, grub_uint32_t index, grub_uint32_t memtype) ++grub_uint32_t ++grub_efi_loongson_memmap_v1_sort(struct memmap_v1 array[], grub_uint32_t length, ++ mem_map_v1 * bpmem, grub_uint32_t index, grub_uint32_t memtype) +{ + grub_uint64_t tempmemsize = 0; + grub_uint32_t j = 0; @@ -1342,19 +920,19 @@ index 0000000..8b60d82 + tempmemsize = array[j].memsize; + for(t = j + 1; t < length; t++) + { -+ if(array[j].memstart + tempmemsize == array[t].memstart) ++ if(array[j].memstart + tempmemsize == array[t].memstart) + { + tempmemsize += array[t].memsize; + } + else -+ { ++ { + break; + } + } + bpmem->map[index].memtype = memtype; + bpmem->map[index].memstart = array[j].memstart; + bpmem->map[index].memsize = tempmemsize; -+ grub_dprintf("loongson", "map[%d]:type %x, start 0x%llx, end 0x%llx\n", ++ grub_dprintf("loongson", "v1 map[%d]:type %x, start 0x%lx, end 0x%lx\n", + index, + bpmem->map[index].memtype, + bpmem->map[index].memstart, @@ -1365,74 +943,9 @@ index 0000000..8b60d82 + } + return index; +} -+ -diff --git a/grub-core/lib/loongarch64/efi/loongson_asm.S b/grub-core/lib/loongarch64/efi/loongson_asm.S -new file mode 100644 -index 0000000..4a04d34 ---- /dev/null -+++ b/grub-core/lib/loongarch64/efi/loongson_asm.S -@@ -0,0 +1,58 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2017 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 -+ -+ .file "loongson_asm.S" -+ .text -+ -+ .align 4 -+ -+VARIABLE (grub_efi_loongson_reset_start) -+ -+VARIABLE (grub_efi_loongson_reset_system_addr) -+ .dword 0 -+ -+reset_system: -+ bl 1f -+ move $a1, $zero -+1: -+ ld.d $t8, $ra, -16 -+ move $a2, $zero -+ jr $t8 -+ move $a3, $zero -+ -+FUNCTION(grub_efi_loongson_reset_cold) -+ b reset_system -+ li.w $a0, 0 -+ -+FUNCTION(grub_efi_loongson_reset_warm) -+ b reset_system -+ li.w $a0, 1 -+ -+FUNCTION(grub_efi_loongson_reset_shutdown) -+ b reset_system -+ li.w $a0, 2 -+ -+FUNCTION(grub_efi_loongson_reset_suspend) -+ b reset_system -+ li.w $a0, 3 -+ -+VARIABLE (grub_efi_loongson_reset_end) -+ -+ diff --git a/grub-core/lib/loongarch64/relocator.c b/grub-core/lib/loongarch64/relocator.c new file mode 100644 -index 0000000..f6c1b01 +index 0000000..4b253ca --- /dev/null +++ b/grub-core/lib/loongarch64/relocator.c @@ -0,0 +1,163 @@ @@ -1510,12 +1023,9 @@ index 0000000..f6c1b01 +static void +write_jump (int regn, void **target) +{ -+ grub_uint32_t andi=0x4c000000; -+ grub_uint32_t nop=0x03400000; ++ grub_uint32_t jirl=0x4c000000; + -+ *(grub_uint32_t *) *target = (andi | (grub_uint32_t)(regn<<5)); -+ *target = ((grub_uint32_t *) *target) + 1; -+ *(grub_uint32_t *) *target = nop; ++ *(grub_uint32_t *) *target = (jirl | (grub_uint32_t)(regn<<5)); + *target = ((grub_uint32_t *) *target) + 1; +} + @@ -1585,6 +1095,9 @@ index 0000000..f6c1b01 + + grub_arch_sync_caches ((void *) relst, relsize); + ++ asm volatile ( ++ "ibar 0 \n"); ++ + grub_uint64_t val; + __asm__ __volatile__( + "li.w %0, 0x4\n\t" @@ -1803,10 +1316,10 @@ index 29663f7..c0ca17d 100644 #endif diff --git a/grub-core/loader/loongarch64/linux.c b/grub-core/loader/loongarch64/linux.c new file mode 100644 -index 0000000..c769bb2 +index 0000000..7594ca2 --- /dev/null +++ b/grub-core/loader/loongarch64/linux.c -@@ -0,0 +1,580 @@ +@@ -0,0 +1,690 @@ +/* linux.c - boot Linux */ +/* + * GRUB -- GRand Unified Bootloader @@ -1838,10 +1351,12 @@ index 0000000..c769bb2 +#include +#include +#include ++#include +#include +#include +#include -+ ++#include ++#include + +GRUB_MOD_LICENSE ("GPLv3+"); + @@ -1849,253 +1364,302 @@ index 0000000..c769bb2 + +typedef unsigned long size_t; + -+static grub_dl_t my_mod; ++#define FDT_ADDR_CELLS_STRING "#address-cells" ++#define FDT_SIZE_CELLS_STRING "#size-cells" ++#define FDT_ADDR_SIZE_EXTRA ((2 * grub_fdt_prop_entry_size (sizeof(grub_uint32_t))) + \ ++ sizeof (FDT_ADDR_CELLS_STRING) + \ ++ sizeof (FDT_SIZE_CELLS_STRING)) + ++static grub_dl_t my_mod; +static int loaded; -+ -+static grub_uint32_t tmp_index = 0; ++static int initrd_loaded = 0; +static grub_size_t linux_size; + +static struct grub_relocator *relocator; +static grub_addr_t target_addr, entry_addr; +static int linux_argc; +static grub_uint8_t *linux_args_addr; -+static grub_off_t rd_addr_arg_off, rd_size_arg_off; -+static grub_off_t initrd_addr_arg_off; -+static int initrd_loaded = 0; -+ ++static grub_off_t rd_addr_arg_off, rd_size_arg_off, initrd_addr_arg_off; + -+static grub_uint32_t j = 0; -+static grub_uint32_t t = 0; -+grub_uint64_t tempMemsize = 0; -+grub_uint32_t free_index = 0; -+grub_uint32_t reserve_index = 0; -+grub_uint32_t acpi_table_index = 0; -+grub_uint32_t acpi_nvs_index = 0; ++static void *fdt; ++static int is_fdt_boot; ++static grub_addr_t initrd_start, initrd_end; ++static char *fdt_linux_args; + -+static inline grub_size_t -+page_align (grub_size_t size) ++static grub_err_t ++allocate_fdt_and_exit_boot (void) +{ -+ return (size + (1 << 12) - 1) & (~((1 << 12) - 1)); -+} ++ int node, retval; ++ grub_err_t err; ++ unsigned int size; ++ grub_efi_uintn_t mmap_size; ++ grub_efi_uintn_t desc_size; ++ grub_efi_uint32_t desc_version; ++ grub_efi_memory_descriptor_t *mmap_buf; + -+/* Find the optimal number of pages for the memory map. Is it better to -+ move this code to efi/mm.c? */ -+static grub_efi_uintn_t -+find_mmap_size (void) -+{ -+ static grub_efi_uintn_t mmap_size = 0; ++ size = GRUB_FDT_EMPTY_TREE_SZ + FDT_ADDR_SIZE_EXTRA + GRUB_EFI_LINUX_FDT_EXTRA_SPACE; ++ ++ fdt = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (size)); ++ if (!fdt) ++ return GRUB_ERR_OUT_OF_MEMORY; ++ ++ grub_fdt_create_empty_tree (fdt, size); ++ grub_fdt_set_prop32 (fdt, 0, FDT_ADDR_CELLS_STRING, 2); ++ grub_fdt_set_prop32 (fdt, 0, FDT_SIZE_CELLS_STRING, 2); ++ ++ node = grub_fdt_find_subnode (fdt, 0, "chosen"); ++ if (node < 0) ++ node = grub_fdt_add_subnode (fdt, 0, "chosen"); ++ if (node < 1) ++ goto failure; ++ ++ grub_dprintf ("loongson", "command_line %s, len %ld\n", ++ fdt_linux_args, grub_strlen(fdt_linux_args) + 1); ++ if ((fdt_linux_args != NULL) && (grub_strlen(fdt_linux_args) > 0)) { ++ retval = grub_fdt_set_prop (fdt, node, "bootargs", fdt_linux_args, ++ grub_strlen(fdt_linux_args) + 1); ++ if (retval) ++ goto failure; ++ } + -+ if (mmap_size != 0) -+ return mmap_size; ++ /* Set initrd info */ ++ if (initrd_start && initrd_end > initrd_start) ++ { ++ grub_dprintf ("linux", "Initrd @ %p-%p\n", ++ (void *) initrd_start, (void *) initrd_end); ++ ++ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start", ++ initrd_start); ++ if (retval) ++ goto failure; ++ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end", ++ initrd_end); ++ if (retval) ++ goto failure; ++ } + -+ mmap_size = (1 << 12); -+ while (1) -+ { -+ int ret; -+ grub_efi_memory_descriptor_t *mmap; -+ grub_efi_uintn_t desc_size; ++ node = grub_fdt_find_subnode (fdt, 0, "chosen"); ++ retval = grub_fdt_set_prop64 (fdt, node, "linux,uefi-system-table", ++ (grub_uint64_t)grub_efi_system_table); ++ if (retval) ++ goto failure; ++ ++ mmap_size = grub_efi_find_mmap_size (); ++ if (! mmap_size) ++ return grub_errno; ++ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); ++ if (! mmap_buf) ++ return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); ++ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, ++ &desc_size, &desc_version); ++ if (err) ++ return err; + -+ mmap = grub_malloc (mmap_size); -+ if (! mmap) -+ return 0; ++ if (!mmap_buf || !mmap_size || !desc_size) ++ return GRUB_ERR_BAD_ARGUMENT; + -+ ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0); -+ grub_free (mmap); ++ retval = grub_fdt_set_prop64 (fdt, node, "linux,uefi-mmap-start", ++ (grub_uint64_t)mmap_buf); ++ if (retval) ++ goto failure; + -+ if (ret < 0) -+ { -+ grub_error (GRUB_ERR_IO, "cannot get memory map"); -+ return 0; -+ } -+ else if (ret > 0) -+ break; ++ retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-size", ++ mmap_size); ++ if (retval) ++ goto failure; + -+ mmap_size += (1 << 12); -+ } ++ retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-desc-size", ++ desc_size); ++ if (retval) ++ goto failure; + ++ retval = grub_fdt_set_prop32 (fdt, node, "linux,uefi-mmap-desc-ver", ++ desc_version); ++ if (retval) ++ goto failure; + -+ /* Increase the size a bit for safety, because GRUB allocates more on -+ later, and EFI itself may allocate more. */ -+ mmap_size += (1 << 12); ++ return GRUB_ERR_NONE; + -+ return page_align (mmap_size); ++failure: ++ if (!fdt) { ++ return GRUB_ERR_BAD_OS; ++ } ++ grub_efi_free_pages ((grub_addr_t) fdt, ++ GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt))); ++ fdt = NULL; ++ return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT"); +} + +static grub_err_t -+grub_linux_boot (void) ++allocate_boot_params_and_exit_boot (void) +{ -+ struct grub_relocator64_state state; -+ grub_int8_t checksum = 0; ++ grub_efi_uintn_t mmap_size; ++ grub_efi_uintn_t desc_size; ++ grub_efi_uint32_t desc_version; ++ grub_efi_memory_descriptor_t *mmap_buf; + grub_efi_memory_descriptor_t * lsdesc = NULL; -+ -+ grub_memset (&state, 0, sizeof (state)); -+ -+ /* Boot the kernel. */ -+ state.gpr[1] = entry_addr; -+ grub_dprintf("loongson", "entry_addr is %p\n", state.gpr[1]); -+ state.gpr[4] = linux_argc; -+ grub_dprintf("loongson", "linux_argc is %d\n", state.gpr[4]); -+ state.gpr[5] = (grub_addr_t) linux_args_addr; -+ grub_dprintf("loongson", "args_addr is %p\n", state.gpr[5]); -+ -+ if(grub_efi_is_loongson ()) -+ { -+ grub_efi_uintn_t mmap_size; -+ grub_efi_uintn_t desc_size; -+ grub_efi_memory_descriptor_t *mmap_buf; -+ grub_err_t err; -+ struct bootparamsinterface * boot_params; -+ void * tmp_boot_params = NULL; -+ grub_efi_uint8_t new_interface_flag = 0; -+ mem_map * new_interface_mem = NULL; -+ char *p = NULL; -+ -+ struct memmap reserve_mem[GRUB_EFI_LOONGSON_MMAP_MAX]; -+ struct memmap free_mem[GRUB_EFI_LOONGSON_MMAP_MAX]; -+ struct memmap acpi_table_mem[GRUB_EFI_LOONGSON_MMAP_MAX]; -+ struct memmap acpi_nvs_mem[GRUB_EFI_LOONGSON_MMAP_MAX]; -+ -+ grub_memset(reserve_mem, 0, sizeof(struct memmap) * GRUB_EFI_LOONGSON_MMAP_MAX); -+ grub_memset(free_mem, 0, sizeof(struct memmap) * GRUB_EFI_LOONGSON_MMAP_MAX); -+ grub_memset(acpi_table_mem, 0, sizeof(struct memmap) * GRUB_EFI_LOONGSON_MMAP_MAX); -+ grub_memset(acpi_nvs_mem, 0, sizeof(struct memmap) * GRUB_EFI_LOONGSON_MMAP_MAX); -+ -+ tmp_boot_params = grub_efi_loongson_get_boot_params(); -+ if(tmp_boot_params == NULL) -+ { -+ grub_printf("not find param\n"); -+ return -1; -+ } -+ -+ boot_params = (struct bootparamsinterface *)tmp_boot_params; -+ p = (char *)&(boot_params->signature); -+ if(grub_strncmp(p, "BPI", 3) == 0) ++ grub_err_t err; ++ struct boot_params_interface * boot_params; ++ mem_map_v1 * mem_map_v1_table = NULL; ++ unsigned long bpi_version = 0; ++ grub_int8_t checksum = 0; ++ grub_uint32_t tmp_index = 0; ++ grub_uint32_t free_index = 0; ++ grub_uint32_t reserve_index = 0; ++ grub_uint32_t acpi_table_index = 0; ++ grub_uint32_t acpi_nvs_index = 0; ++ ++ struct memmap_v1 reserve_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; ++ struct memmap_v1 free_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; ++ struct memmap_v1 acpi_table_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; ++ struct memmap_v1 acpi_nvs_mem_v1[GRUB_EFI_LOONGSON_MMAP_MAX]; ++ ++ grub_memset(reserve_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); ++ grub_memset(free_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); ++ grub_memset(acpi_table_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); ++ grub_memset(acpi_nvs_mem_v1, 0, sizeof(struct memmap_v1) * GRUB_EFI_LOONGSON_MMAP_MAX); ++ ++ boot_params = (struct boot_params_interface *)grub_efi_loongson_get_boot_params(); ++ ++ ext_list * listpointer = NULL; ++ /* Check extlist headers */ ++ listpointer = boot_params->extlist; ++ for( ;listpointer != NULL; listpointer = listpointer->next) + { -+ /* Check extlist headers */ -+ ext_list * listpointer = NULL; -+ listpointer = boot_params->extlist; -+ for( ;listpointer != NULL; listpointer = listpointer->next) ++ char *pl= (char *)&(listpointer->signature); ++ if(grub_strncmp(pl, "MEM", 3) == 0) + { -+ char *pl= (char *)&(listpointer->signature); -+ if(grub_strncmp(pl, "MEM", 3) == 0) -+ { -+ new_interface_mem = (mem_map *)listpointer; -+ } ++ mem_map_v1_table = (mem_map_v1 *)listpointer; ++ break; + } -+ -+ new_interface_flag = 1; -+ grub_dprintf("loongson", "get new parameter interface\n"); -+ }else{ -+ new_interface_flag = 0; -+ grub_dprintf("loongson", "get old parameter interface\n"); + } -+ state.gpr[6] = (grub_uint64_t)tmp_boot_params; -+ grub_dprintf("loongson", "boot_params is %p\n", state.gpr[6]); + -+ mmap_size = find_mmap_size (); -+ if (! mmap_size) -+ return grub_errno; -+ mmap_buf = grub_efi_allocate_any_pages (page_align (mmap_size) >> 12); -+ if (! mmap_buf) -+ return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); -+ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, -+ &desc_size, NULL); -+ if (err) -+ return err; ++ mmap_size = grub_efi_find_mmap_size (); ++ if (! mmap_size) ++ return grub_errno; ++ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); ++ if (! mmap_buf) ++ return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); ++ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL, ++ &desc_size, &desc_version); ++ if (err) ++ return err; + -+ if(new_interface_flag) -+ { -+ if (!mmap_buf || !mmap_size || !desc_size) -+ return -1; -+ tmp_index = new_interface_mem -> mapcount; ++ if (!mmap_buf || !mmap_size || !desc_size) ++ return GRUB_ERR_BAD_ARGUMENT; + ++ char *p = (char *)&(boot_params->signature); ++ bpi_version = grub_efi_get_bpi_version(p); ++ grub_dprintf("loongson", "get bpi version:%ld\n", bpi_version); ++ ++ if (bpi_version <= GRUB_EFI_BPI_VER_V2) ++ { + /* -+ According to UEFI SPEC,mmap_buf is the accurate Memory Map array \ -+ now we can fill platform specific memory structure. -+ */ ++ According to UEFI SPEC,mmap_buf is the accurate Memory Map array \ ++ now we can fill platform specific memory structure. ++ */ + for(lsdesc = mmap_buf; lsdesc < (grub_efi_memory_descriptor_t *)((char *)mmap_buf + mmap_size); -+ lsdesc = (grub_efi_memory_descriptor_t *)((char *)lsdesc + desc_size)) ++ lsdesc = (grub_efi_memory_descriptor_t *)((char *)lsdesc + desc_size)) + { -+ /* Recovery */ -+ if((lsdesc->type != GRUB_EFI_ACPI_RECLAIM_MEMORY) && \ -+ (lsdesc->type != GRUB_EFI_ACPI_MEMORY_NVS) && \ -+ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_DATA) && \ -+ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_CODE) && \ -+ (lsdesc->type != GRUB_EFI_RESERVED_MEMORY_TYPE) && \ -+ (lsdesc->type != GRUB_EFI_PAL_CODE)) ++ grub_dprintf("loongson", "type:%d, phy_start:0x%lx, phy_end:0x%lx\n", lsdesc->type, ++ lsdesc->physical_start, lsdesc->physical_start + lsdesc->num_pages * GRUB_EFI_PAGE_SIZE); ++ ++ /* System RAM */ ++ if ((lsdesc->type != GRUB_EFI_ACPI_RECLAIM_MEMORY) && \ ++ (lsdesc->type != GRUB_EFI_ACPI_MEMORY_NVS) && \ ++ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_DATA) && \ ++ (lsdesc->type != GRUB_EFI_RUNTIME_SERVICES_CODE) && \ ++ (lsdesc->type != GRUB_EFI_RESERVED_MEMORY_TYPE) && \ ++ (lsdesc->type != GRUB_EFI_PAL_CODE)) + { -+ free_mem[free_index].memtype = GRUB_EFI_LOONGSON_SYSTEM_RAM; -+ free_mem[free_index].memstart = (lsdesc->physical_start) & 0xffffffffffff; -+ free_mem[free_index].memsize = lsdesc->num_pages * 4096; ++ free_mem_v1[free_index].memtype = GRUB_EFI_LOONGSON_SYSTEM_RAM; ++ free_mem_v1[free_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; ++ free_mem_v1[free_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; + free_index++; + + /*ACPI*/ -+ }else if((lsdesc->type == GRUB_EFI_ACPI_RECLAIM_MEMORY)){ -+ acpi_table_mem[acpi_table_index].memtype = GRUB_EFI_LOONGSON_ACPI_TABLE; -+ acpi_table_mem[acpi_table_index].memstart = (lsdesc->physical_start) & 0xffffffffffff; -+ acpi_table_mem[acpi_table_index].memsize = lsdesc->num_pages * 4096; ++ } else if ((lsdesc->type == GRUB_EFI_ACPI_RECLAIM_MEMORY)){ ++ acpi_table_mem_v1[acpi_table_index].memtype = GRUB_EFI_LOONGSON_ACPI_TABLE; ++ acpi_table_mem_v1[acpi_table_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; ++ acpi_table_mem_v1[acpi_table_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; + acpi_table_index++; -+ }else if((lsdesc->type == GRUB_EFI_ACPI_MEMORY_NVS)){ -+ acpi_nvs_mem[acpi_nvs_index].memtype = GRUB_EFI_LOONGSON_ACPI_NVS; -+ acpi_nvs_mem[acpi_nvs_index].memstart = (lsdesc->physical_start) & 0xffffffffffff; -+ acpi_nvs_mem[acpi_nvs_index].memsize = lsdesc->num_pages * 4096; ++ } else if ((lsdesc->type == GRUB_EFI_ACPI_MEMORY_NVS)){ ++ acpi_nvs_mem_v1[acpi_nvs_index].memtype = GRUB_EFI_LOONGSON_ACPI_NVS; ++ acpi_nvs_mem_v1[acpi_nvs_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; ++ acpi_nvs_mem_v1[acpi_nvs_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; + acpi_nvs_index++; + + /* Reserve */ -+ }else{ -+ reserve_mem[reserve_index].memtype = GRUB_EFI_LOONGSON_MEMORY_RESERVED; -+ reserve_mem[reserve_index].memstart = (lsdesc->physical_start) & 0xffffffffffff; -+ reserve_mem[reserve_index].memsize = lsdesc->num_pages * 4096; ++ } else { ++ reserve_mem_v1[reserve_index].memtype = GRUB_EFI_LOONGSON_MEMORY_RESERVED; ++ reserve_mem_v1[reserve_index].memstart = (lsdesc->physical_start) & GRUB_EFI_MAX_PHY_ADDRESS; ++ reserve_mem_v1[reserve_index].memsize = lsdesc->num_pages * GRUB_EFI_PAGE_SIZE; + reserve_index++; + } + } + -+ /* Recovery sort */ -+ for(j = 0; j < free_index;) -+ { -+ tempMemsize = free_mem[j].memsize; -+ for(t = j + 1; t < free_index; t++) -+ { -+ if((free_mem[j].memstart + tempMemsize == free_mem[t].memstart) && (free_mem[j].memtype == free_mem[t].memtype)) -+ { -+ tempMemsize += free_mem[t].memsize; -+ }else{ -+ break; -+ } -+ } -+ -+ new_interface_mem->map[tmp_index].memtype = GRUB_EFI_LOONGSON_SYSTEM_RAM; -+ new_interface_mem->map[tmp_index].memstart = free_mem[j].memstart; -+ new_interface_mem->map[tmp_index].memsize = tempMemsize; -+ grub_dprintf("loongson", "map[%d]:type %x, start 0x%llx, end 0x%llx\n", -+ tmp_index, -+ new_interface_mem->map[tmp_index].memtype, -+ new_interface_mem->map[tmp_index].memstart, -+ new_interface_mem->map[tmp_index].memstart+ new_interface_mem->map[tmp_index].memsize -+ ); -+ j = t; -+ tmp_index++; -+ } ++ tmp_index = mem_map_v1_table->mapcount; ++ /*System RAM Sort*/ ++ tmp_index = grub_efi_loongson_memmap_v1_sort(free_mem_v1, free_index, mem_map_v1_table, ++ tmp_index, GRUB_EFI_LOONGSON_SYSTEM_RAM); + /*ACPI Sort*/ -+ tmp_index = grub_efi_loongson_memmap_sort(acpi_table_mem, acpi_table_index, new_interface_mem, tmp_index, GRUB_EFI_LOONGSON_ACPI_TABLE); -+ tmp_index = grub_efi_loongson_memmap_sort(acpi_nvs_mem, acpi_nvs_index, new_interface_mem, tmp_index, GRUB_EFI_LOONGSON_ACPI_NVS); ++ tmp_index = grub_efi_loongson_memmap_v1_sort(acpi_table_mem_v1, acpi_table_index, ++ mem_map_v1_table, tmp_index, GRUB_EFI_LOONGSON_ACPI_TABLE); ++ tmp_index = grub_efi_loongson_memmap_v1_sort(acpi_nvs_mem_v1, acpi_nvs_index, ++ mem_map_v1_table, tmp_index, GRUB_EFI_LOONGSON_ACPI_NVS); + /*Reserve Sort*/ -+ grub_uint64_t loongarch_addr; -+ asm volatile ("csrrd %0, 0x181" : "=r" (loongarch_addr)); -+ if((loongarch_addr & 0xff00000000000000) == 0x9000000000000000){ -+ tmp_index = grub_efi_loongson_memmap_sort(reserve_mem, reserve_index, new_interface_mem, tmp_index, GRUB_EFI_LOONGSON_MEMORY_RESERVED); -+ }else{ -+ tmp_index = grub_efi_loongson_memmap_sort(reserve_mem, reserve_index, new_interface_mem, tmp_index, GRUB_EFI_LOONGSON_MEMORY_RESERVED + 1); -+ } -+ -+ new_interface_mem->mapcount = tmp_index; -+ new_interface_mem->header.checksum = 0; ++ { ++ grub_uint64_t loongarch_addr; ++ asm volatile ("csrrd %0, 0x181" : "=r" (loongarch_addr)); ++ if ((loongarch_addr & 0xff00000000000000) == 0x9000000000000000) ++ tmp_index = grub_efi_loongson_memmap_v1_sort(reserve_mem_v1, reserve_index, ++ mem_map_v1_table, tmp_index, ++ GRUB_EFI_LOONGSON_MEMORY_RESERVED); ++ else ++ tmp_index = grub_efi_loongson_memmap_v1_sort(reserve_mem_v1, reserve_index, ++ mem_map_v1_table, tmp_index, ++ GRUB_EFI_LOONGSON_MEMORY_RESERVED + 1); ++ } ++ mem_map_v1_table->mapcount = tmp_index; ++ mem_map_v1_table->header.checksum = 0; + -+ checksum = grub_efi_loongson_grub_calculatechecksum8(new_interface_mem, new_interface_mem->header.length); -+ new_interface_mem->header.checksum = checksum; ++ checksum = grub_efi_loongson_grub_calculatechecksum8((grub_uint8_t *)mem_map_v1_table, ++ mem_map_v1_table->header.length); ++ mem_map_v1_table->header.checksum = checksum; + } ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_linux_boot (void) ++{ ++ struct grub_relocator64_state state; ++ ++ grub_memset (&state, 0, sizeof (state)); ++ ++ /* Boot the kernel. */ ++ state.gpr[1] = entry_addr; ++ grub_dprintf("loongson", "entry_addr is 0x%lx\n", state.gpr[1]); ++ ++ if (is_fdt_boot == 1) ++ { ++ if (allocate_fdt_and_exit_boot () != GRUB_ERR_NONE) ++ return grub_errno; ++ ++ state.gpr[4] = 1 << FLAGS_EFI_SUPPORT_BIT; ++ state.gpr[5] = (grub_uint64_t)fdt; ++ state.gpr[6] = 0; ++ } else { ++ state.gpr[4] = linux_argc; ++ state.gpr[5] = (grub_addr_t) linux_args_addr; ++ state.gpr[6] = (grub_uint64_t)grub_efi_loongson_get_boot_params(); ++ ++ if (allocate_boot_params_and_exit_boot () != GRUB_ERR_NONE) ++ return grub_errno; + } ++ grub_dprintf("loongson", "gpr[4]:%ld, gpr[5]:0x%lx, gpr[6]:0x%lx\n", ++ state.gpr[4], state.gpr[5], state.gpr[6]); + + state.jumpreg = 1; + grub_relocator64_boot (relocator, state); @@ -2108,67 +1672,42 @@ index 0000000..c769bb2 +{ + grub_relocator_unload (relocator); + grub_dl_unref (my_mod); -+ + loaded = 0; + + return GRUB_ERR_NONE; +} + +static grub_err_t -+grub_linux_load32 (grub_elf_t elf, const char *filename) -+{ -+ Elf32_Addr base; -+ grub_err_t err; -+ grub_uint8_t *playground; -+ -+ /* Linux's entry point incorrectly contains a virtual address. */ -+ entry_addr = elf->ehdr.ehdr32.e_entry; -+ -+ linux_size = grub_elf32_size (elf, &base, 0); -+ if (linux_size == 0) -+ return grub_errno; -+ target_addr = base; -+ linux_size = ALIGN_UP (base + linux_size - base, 8); -+ -+ relocator = grub_relocator_new (); -+ if (!relocator) -+ return grub_errno; -+ -+ { -+ grub_relocator_chunk_t ch; -+ err = grub_relocator_alloc_chunk_addr (relocator, &ch, -+ grub_vtop ((void *) target_addr), -+ linux_size); -+ if (err) -+ return err; -+ playground = get_virtual_current_address (ch); -+ } -+ -+ /* Now load the segments into the area we claimed. */ -+ return grub_elf32_load (elf, filename, playground - base, GRUB_ELF_LOAD_FLAGS_NONE, 0, 0); -+} -+ -+static grub_err_t +grub_linux_load64 (grub_elf_t elf, const char *filename) +{ + Elf64_Addr base; + grub_err_t err; + grub_uint8_t *playground; ++ grub_uint64_t addr; ++ int flag; + + /* Linux's entry point incorrectly contains a virtual address. */ + entry_addr = elf->ehdr.ehdr64.e_entry; -+ grub_dprintf("loongson", "entry address = %p\n", entry_addr); ++ grub_dprintf("loongson", "entry address = 0x%lx\n", entry_addr); + + linux_size = grub_elf64_size (elf, &base, 0); -+ grub_dprintf("loongson", "base = %p\n", base); ++ grub_dprintf("loongson", "base = 0x%lx\n", base); + + if (linux_size == 0) + return grub_errno; + target_addr = base; + linux_size = ALIGN_UP (base + linux_size - base, 8); + ++ asm volatile ("csrrd %0, 0x181" : "=r" (addr)); ++ if (addr & 0x1) { ++ flag = GRUB_ELF_LOAD_FLAGS_NONE; ++ } else { ++ flag = GRUB_ELF_LOAD_FLAGS_30BITS; ++ base &= ~ELF64_LOADMASK; ++ entry_addr &= ~ELF64_LOADMASK; ++ } ++ + relocator = grub_relocator_new (); -+ // linux_size=0x322fa80; + if (!relocator) + return grub_errno; + @@ -2183,7 +1722,7 @@ index 0000000..c769bb2 + } + + /* Now load the segments into the area we claimed. */ -+ return grub_elf64_load (elf, filename, playground - base, GRUB_ELF_LOAD_FLAGS_NONE, 0, 0); ++ return grub_elf64_load (elf, filename, playground - base, flag, 0, 0); +} + +static grub_err_t @@ -2191,20 +1730,21 @@ index 0000000..c769bb2 + int argc, char *argv[]) +{ + grub_elf_t elf = 0; -+ int size; -+ int i; -+ grub_uint64_t *linux_argv; -+ char *linux_args; + grub_err_t err; ++ int args_size = 0; ++ ++ grub_dl_ref (my_mod); + + if (argc == 0) ++ { + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ } + -+ elf = grub_elf_open (argv[0],GRUB_FILE_TYPE_LINUX_KERNEL); ++ elf = grub_elf_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL); + if (! elf) + return grub_errno; + -+ if (elf->ehdr.ehdr32.e_type != ET_EXEC) ++ if (elf->ehdr.ehdr64.e_type != ET_EXEC) + { + grub_elf_close (elf); + return grub_error (GRUB_ERR_UNKNOWN_OS, @@ -2215,30 +1755,6 @@ index 0000000..c769bb2 + grub_loader_unset (); + loaded = 0; + -+ /* For arguments. */ -+ linux_argc = argc; -+ /* Main arguments. */ -+ size = (linux_argc) * sizeof (grub_uint64_t); -+ /* Initrd address and size. */ -+ size += 3 * sizeof (grub_uint64_t); -+ /* NULL terminator. */ -+ size += sizeof (grub_uint64_t); -+ /* First argument is always "a0". */ -+ size += ALIGN_UP (sizeof ("a0"), 4); -+ /* Normal arguments. */ -+ for (i = 1; i < argc; i++) -+ size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); -+ -+ /* rd arguments. */ -+ size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); -+ size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); -+ size += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); -+ -+ size = ALIGN_UP (size, 8); -+ -+ if (grub_elf_is_elf32 (elf)) -+ err = grub_linux_load32 (elf, argv[0]); -+ else + if (grub_elf_is_elf64 (elf)) + err = grub_linux_load64 (elf, argv[0]); + else @@ -2249,26 +1765,71 @@ index 0000000..c769bb2 + if (err) + return err; + -+ { -+ grub_relocator_chunk_t ch; -+ err = grub_relocator_alloc_chunk_align (relocator, &ch, -+ 0, (0xffffffff - size) + 1, -+ size, 8, -+ GRUB_RELOCATOR_PREFERENCE_HIGH, 0); -+ if (err) -+ return err; -+ linux_args_addr = get_virtual_current_address (ch); -+ } ++ if (grub_efi_loongson_get_boot_params() == NULL) { ++ grub_size_t cmdline_size; + -+ linux_argv = (grub_uint64_t *) linux_args_addr; -+ linux_args = (char *) (linux_argv + (linux_argc + 1 + 3)); ++ is_fdt_boot = 1; ++ cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE); ++ fdt_linux_args = grub_malloc (cmdline_size); ++ if (!fdt_linux_args) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto fail; ++ } ++ grub_memcpy (fdt_linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); ++ err = grub_create_loader_cmdline (argc, argv, ++ fdt_linux_args + sizeof (LINUX_IMAGE) - 1, ++ cmdline_size, ++ GRUB_VERIFY_KERNEL_CMDLINE); ++ if (err) ++ goto fail; ++ grub_dprintf("loongson", "fdt linux args:%s\n", ++ fdt_linux_args + sizeof (LINUX_IMAGE) - 1); ++ ++ } else { ++ int i; ++ grub_uint64_t *linux_argv; ++ char *linux_args; ++ ++ is_fdt_boot = 0; ++ /* For arguments. */ ++ linux_argc = argc; ++ /* Main arguments. */ ++ args_size = (linux_argc) * sizeof (grub_uint64_t); ++ /* Initrd address/size and initrd */ ++ args_size += 3 * sizeof (grub_uint64_t); ++ /* NULL terminator. */ ++ args_size += sizeof (grub_uint64_t); ++ /* First argument is always "a0". */ ++ args_size += ALIGN_UP (sizeof ("a0"), 4); ++ /* Normal arguments. */ ++ for (i = 1; i < argc; i++) ++ args_size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); ++ ++ /* rd arguments. */ ++ args_size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); ++ args_size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); ++ args_size += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); ++ ++ args_size = ALIGN_UP (args_size, 8); ++ ++ linux_args_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (args_size)); ++ grub_dprintf ("linux", "linux args numpages: %lld\n", ++ (long long) GRUB_EFI_BYTES_TO_PAGES (args_size)); ++ if (!linux_args_addr) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto fail; ++ } ++ linux_argv = (grub_uint64_t *) linux_args_addr; ++ linux_args = (char *) (linux_argv + (linux_argc + 1 + 3)); + -+ grub_memcpy (linux_args, "a0", sizeof ("a0")); -+ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; -+ linux_argv++; -+ linux_args += ALIGN_UP (sizeof ("a0"), 4); ++ grub_memcpy (linux_args, "a0", sizeof ("a0")); ++ *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; ++ linux_argv++; ++ linux_args += ALIGN_UP (sizeof ("a0"), 4); + -+ for (i = 1; i < argc; i++) ++ for (i = 1; i < argc; i++) + { + grub_memcpy (linux_args, argv[i], grub_strlen (argv[i]) + 1); + *linux_argv = (grub_uint64_t) (grub_addr_t) linux_args; @@ -2276,40 +1837,80 @@ index 0000000..c769bb2 + linux_args += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); + } + -+ /* Reserve space for rd arguments. */ -+ rd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; -+ linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); -+ *linux_argv = 0; -+ linux_argv++; ++ /* Reserve space for rd arguments. */ ++ rd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; ++ linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); ++ *linux_argv = 0; ++ linux_argv++; ++ ++ rd_size_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; ++ linux_args += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); ++ *linux_argv = 0; ++ linux_argv++; + -+ rd_size_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; -+ linux_args += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); -+ *linux_argv = 0; -+ linux_argv++; ++ /* Reserve space for initrd arguments. */ ++ initrd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; ++ linux_args += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); ++ *linux_argv = 0; ++ linux_argv++; + -+ /* Reserve space for initrd arguments. */ -+ initrd_addr_arg_off = (grub_uint8_t *) linux_args - linux_args_addr; -+ linux_args += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4); -+ *linux_argv = 0; -+ linux_argv++; ++ *linux_argv = 0; ++ } + -+ *linux_argv = 0; ++ if (grub_errno == GRUB_ERR_NONE) ++ { ++ grub_loader_set (grub_linux_boot, grub_linux_unload, 0); ++ loaded = 1; ++ } + -+ grub_loader_set (grub_linux_boot, grub_linux_unload, 0); + initrd_loaded = 0; -+ loaded = 1; -+ grub_dl_ref (my_mod); + -+ return GRUB_ERR_NONE; ++fail: ++ if (grub_errno != GRUB_ERR_NONE) ++ { ++ grub_dl_unref (my_mod); ++ loaded = 0; ++ } ++ ++ if (fdt_linux_args && !loaded) ++ grub_free (fdt_linux_args); ++ ++ if (linux_args_addr && !loaded) ++ grub_efi_free_pages ((grub_addr_t) linux_args_addr, ++ GRUB_EFI_BYTES_TO_PAGES (args_size)); ++ ++ return grub_errno; ++} ++ ++#define INITRD_MAX_ADDRESS_OFFSET (32ULL * 1024 * 1024 * 1024) ++ ++/* ++ * This function returns a pointer to a legally allocated initrd buffer, ++ * or NULL if unsuccessful ++ */ ++static void * ++allocate_initrd_mem (int initrd_pages) ++{ ++ grub_addr_t max_addr; ++ ++ if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE) ++ return NULL; ++ ++ max_addr += INITRD_MAX_ADDRESS_OFFSET - 1; ++ ++ return grub_efi_allocate_pages_real (max_addr, initrd_pages, ++ GRUB_EFI_ALLOCATE_MAX_ADDRESS, ++ GRUB_EFI_LOADER_DATA); +} + ++ +static grub_err_t +grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ -+ grub_size_t size = 0; -+ void *initrd_dest; ++ grub_size_t initrd_size, initrd_pages; + grub_err_t err; ++ void *initrd_mem = NULL; + struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 }; + + if (argc == 0) @@ -2324,49 +1925,71 @@ index 0000000..c769bb2 + if (grub_initrd_init (argc, argv, &initrd_ctx)) + goto fail; + -+ size = grub_get_initrd_size (&initrd_ctx); ++ initrd_size = grub_get_initrd_size (&initrd_ctx); + ++ if (is_fdt_boot == 1) //fdt + { ++ initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size)); ++ initrd_mem = allocate_initrd_mem (initrd_pages); ++ if (!initrd_mem) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto fail; ++ } ++ } else { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_align (relocator, &ch, -+ 0, (0xffffffff - size) + 1, -+ size, 0x10000, -+ GRUB_RELOCATOR_PREFERENCE_HIGH, 0); ++ 0, (0xffffffff - initrd_size) + 1, ++ initrd_size, 0x10000, ++ GRUB_RELOCATOR_PREFERENCE_HIGH, 0); + + if (err) -+ goto fail; -+ initrd_dest = get_virtual_current_address (ch); ++ return err; ++ initrd_mem = get_virtual_current_address (ch); + } + -+ if (grub_initrd_load (&initrd_ctx, argv, initrd_dest)) ++ if (grub_initrd_load (&initrd_ctx, argv, initrd_mem)) + goto fail; + -+ grub_snprintf ((char *) linux_args_addr + rd_addr_arg_off, -+ sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), "rd_start=0x%lx", -+ (grub_uint64_t) initrd_dest); -+ ((grub_uint64_t *) linux_args_addr)[linux_argc] -+ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_addr_arg_off); -+ linux_argc++; -+ -+ grub_snprintf ((char *) linux_args_addr + rd_size_arg_off, -+ sizeof ("rd_size=0xXXXXXXXXXXXXXXXXX"), "rd_size=0x%lx", -+ (grub_uint64_t) size); -+ ((grub_uint64_t *) linux_args_addr)[linux_argc] -+ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_size_arg_off); -+ linux_argc++; -+ ++ initrd_start = (grub_addr_t) initrd_mem; ++ initrd_end = initrd_start + initrd_size; ++ grub_dprintf ("linux", "[addr=%p, size=0x%lx]\n", ++ (void *) initrd_start, initrd_size); + -+ grub_snprintf ((char *) linux_args_addr + initrd_addr_arg_off, -+ sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), "initrd=0x%lx,0x%lx", -+ ((grub_uint64_t) initrd_dest & 0xffffffff), (grub_uint64_t) size); -+ ((grub_uint64_t *) linux_args_addr)[linux_argc] -+ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + initrd_addr_arg_off); -+ linux_argc++; ++ if (is_fdt_boot == 0) //bpi ++ { ++ grub_snprintf ((char *) linux_args_addr + rd_addr_arg_off, ++ sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), ++ "rd_start=0x%lx", ++ (grub_uint64_t) initrd_mem); ++ ((grub_uint64_t *) linux_args_addr)[linux_argc] ++ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_addr_arg_off); ++ linux_argc++; ++ ++ grub_snprintf ((char *) linux_args_addr + rd_size_arg_off, ++ sizeof ("rd_size=0xXXXXXXXXXXXXXXXXX"), "rd_size=0x%lx", ++ (grub_uint64_t) initrd_size); ++ ((grub_uint64_t *) linux_args_addr)[linux_argc] ++ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + rd_size_arg_off); ++ linux_argc++; ++ ++ grub_snprintf ((char *) linux_args_addr + initrd_addr_arg_off, ++ sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), ++ "initrd=0x%lx,0x%lx", ++ ((grub_uint64_t) initrd_mem & GRUB_EFI_MAX_PHY_ADDRESS), ++ (grub_uint64_t) initrd_size); ++ ((grub_uint64_t *) linux_args_addr)[linux_argc] ++ = (grub_uint64_t) ((grub_addr_t) linux_args_addr + initrd_addr_arg_off); ++ linux_argc++; ++ } + + initrd_loaded = 1; + + fail: + grub_initrd_close (&initrd_ctx); ++ if (is_fdt_boot == 1) ++ if (initrd_mem && !initrd_start) ++ grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages); + + return grub_errno; +} @@ -2414,6 +2037,19 @@ index 37e7b16..049326c 100644 #define efi_call_0(func) func() #define efi_call_1(func, a) func(a) +diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h +index 4411ffa..defdd01 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -129,7 +129,7 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, + char **device, + char **path); + +-#if defined(__arm__) || defined(__aarch64__) ++#if defined(__arm__) || defined(__aarch64__) || defined (__loongarch__) + void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void); + grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *); + #include diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h index c03cc59..be88c54 100644 --- a/include/grub/efi/pe32.h @@ -2507,6 +2143,26 @@ index c8492f9..2c0b163 100644 /* MIPS relocs. */ #define R_MIPS_NONE 0 /* No reloc */ +diff --git a/include/grub/fdt.h b/include/grub/fdt.h +index 6ee57e1..a0710ab 100644 +--- a/include/grub/fdt.h ++++ b/include/grub/fdt.h +@@ -19,11 +19,14 @@ + #ifndef GRUB_FDT_HEADER + #define GRUB_FDT_HEADER 1 + +-#if defined(__arm__) || defined(__aarch64__) ++#if defined(__arm__) || defined(__aarch64__) || defined (__loongarch__) + + #include + #include + ++/* Space required when preparing the /chosen node after boot has been called. */ ++#define GRUB_EFI_LINUX_FDT_EXTRA_SPACE 0x400 ++ + #define FDT_MAGIC 0xD00DFEED + + typedef struct { diff --git a/include/grub/loongarch64/asm.h b/include/grub/loongarch64/asm.h new file mode 100644 index 0000000..c3e77e9 @@ -2523,46 +2179,12 @@ index 0000000..c3e77e9 +#define GRUB_ASM_REG_L ld.d + +#endif -diff --git a/include/grub/loongarch64/efi/boot.h b/include/grub/loongarch64/efi/boot.h -new file mode 100644 -index 0000000..e69de29 -diff --git a/include/grub/loongarch64/efi/loader.h b/include/grub/loongarch64/efi/loader.h -new file mode 100644 -index 0000000..71a0159 ---- /dev/null -+++ b/include/grub/loongarch64/efi/loader.h -@@ -0,0 +1,25 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2002,2003,2004,2006,2007,2017 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 . -+ */ -+ -+#ifndef GRUB_LOADER_MACHINE_HEADER -+#define GRUB_LOADER_MACHINE_HEADER 1 -+ -+#include -+#include -+ -+#endif /* ! GRUB_LOADER_MACHINE_HEADER */ diff --git a/include/grub/loongarch64/efi/loongson.h b/include/grub/loongarch64/efi/loongson.h new file mode 100644 -index 0000000..fa32ef5 +index 0000000..7a9ccb4 --- /dev/null +++ b/include/grub/loongarch64/efi/loongson.h -@@ -0,0 +1,290 @@ +@@ -0,0 +1,113 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2017 Free Software Foundation, Inc. @@ -2588,12 +2210,17 @@ index 0000000..fa32ef5 + +#include + -+#define GRUB_EFI_LOONGSON_SMBIOS_TABLE_GUID \ ++#define GRUB_EFI_LOONGSON_BPI_TABLE_GUID \ + { 0x4660f721, 0x2ec5, 0x416a, \ + { 0x89, 0x9a, 0x43, 0x18, 0x02, 0x50, 0xa0, 0xc9 } \ + } + ++#define GRUB_EFI_MAX_PHY_ADDRESS 0xffffffffffffULL ++#define ELF32_LOADMASK (0xf0000000UL) ++#define ELF64_LOADMASK (0xf000000000000000ULL) ++#define FLAGS_EFI_SUPPORT_BIT 0 +#define GRUB_EFI_LOONGSON_MMAP_MAX 128 ++ +typedef enum + { + GRUB_EFI_LOONGSON_SYSTEM_RAM = 1, @@ -2604,272 +2231,88 @@ index 0000000..fa32ef5 + } +grub_efi_loongson_memory_type; + -+typedef struct -+{ -+ grub_uint16_t vers; /* version */ -+ grub_uint32_t nr_map; /* number of memory_maps */ -+ grub_uint32_t mem_freq; /* memory frequence */ -+ struct mem_map { -+ grub_uint32_t node_id; /* node_id which memory attached to */ -+ grub_uint32_t mem_type; /* system memory, pci memory, pci io, etc. */ -+ grub_uint64_t mem_start; /* memory map start address */ -+ grub_uint32_t mem_size; /* each memory_map size, not the total size */ -+ } map[GRUB_EFI_LOONGSON_MMAP_MAX]; -+} GRUB_PACKED -+grub_efi_loongson_memory_map; -+ -+/* -+ * Capability and feature descriptor structure for LOONGARCH CPU -+ */ -+typedef struct -+{ -+ grub_uint16_t vers; /* version */ -+ grub_uint32_t processor_id; /* PRID, e.g. 6305, 6306 */ -+ grub_uint32_t cputype; /* Loongson_3A/3B, etc. */ -+ grub_uint32_t total_node; /* num of total numa nodes */ -+ grub_uint16_t cpu_startup_core_id; /* Boot core id */ -+ grub_uint16_t reserved_cores_mask; -+ grub_uint32_t cpu_clock_freq; /* cpu_clock */ -+ grub_uint32_t nr_cpus; -+} GRUB_PACKED -+grub_efi_loongson_cpu_info; -+ -+#define GRUB_EFI_LOONGSON_MAX_UARTS 64 -+ -+typedef struct -+{ -+ grub_uint32_t iotype; /* see include/linux/serial_core.h */ -+ grub_uint32_t uartclk; -+ grub_uint32_t int_offset; -+ grub_uint64_t uart_base; -+} GRUB_PACKED -+grub_efi_loongson_uart_device; -+ -+#define GRUB_EFI_LOONGSON_MAX_SENSORS 64 -+ -+typedef struct -+{ -+ char name[32]; /* a formal name */ -+ char label[64]; /* a flexible description */ -+ grub_uint32_t type; /* SENSOR_* */ -+ grub_uint32_t id; /* instance id of a sensor-class */ -+ grub_uint32_t fan_policy; -+ grub_uint32_t fan_percent; /* only for constant speed policy */ -+ grub_uint64_t base_addr; /* base address of device registers */ -+} GRUB_PACKED -+grub_efi_loongson_sensor_device; -+ -+typedef struct -+{ -+ grub_uint16_t vers; /* version */ -+ grub_uint32_t ccnuma_smp; /* 0: no numa; 1: has numa */ -+ grub_uint32_t sing_double_channel; /* 1:single; 2:double */ -+ grub_uint32_t nr_uarts; -+ grub_efi_loongson_uart_device uarts[GRUB_EFI_LOONGSON_MAX_UARTS]; -+ grub_uint32_t nr_sensors; -+ grub_efi_loongson_sensor_device sensors[GRUB_EFI_LOONGSON_MAX_SENSORS]; -+ char has_ec; -+ char ec_name[32]; -+ grub_uint64_t ec_base_addr; -+ char has_tcm; -+ char tcm_name[32]; -+ grub_uint64_t tcm_base_addr; -+ grub_uint64_t workarounds; /* see workarounds.h */ -+} GRUB_PACKED -+grub_efi_loongson_system_info; -+ -+typedef struct -+{ -+ grub_uint16_t vers; -+ grub_uint16_t size; -+ grub_uint16_t rtr_bus; -+ grub_uint16_t rtr_devfn; -+ grub_uint32_t vendor; -+ grub_uint32_t device; -+ grub_uint32_t PIC_type; /* conform use HT or PCI to route to CPU-PIC */ -+ grub_uint64_t ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */ -+ grub_uint64_t ht_enable; /* irqs used in this PIC */ -+ grub_uint32_t node_id; /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */ -+ grub_uint64_t pci_mem_start_addr; -+ grub_uint64_t pci_mem_end_addr; -+ grub_uint64_t pci_io_start_addr; -+ grub_uint64_t pci_io_end_addr; -+ grub_uint64_t pci_config_addr; -+ grub_uint32_t dma_mask_bits; -+} GRUB_PACKED -+grub_efi_loongson_irq_src_routing_table; -+ -+typedef struct -+{ -+ grub_uint16_t vers; /* version */ -+ grub_uint16_t size; -+ grub_uint8_t flag; -+ char description[64]; -+} GRUB_PACKED -+grub_efi_loongson_interface_info; -+ -+#define GRUB_EFI_LOONGSON_MAX_RESOURCE_NUMBER 128 -+ -+typedef struct -+{ -+ grub_uint64_t start; /* resource start address */ -+ grub_uint64_t end; /* resource end address */ -+ char name[64]; -+ grub_uint32_t flags; -+} -+grub_efi_loongson_resource; -+ -+/* arch specific additions */ -+typedef struct -+{ -+} -+grub_efi_loongson_archdev_data; -+ -+typedef struct -+{ -+ char name[64]; /* hold the device name */ -+ grub_uint32_t num_resources; /* number of device_resource */ -+ /* for each device's resource */ -+ grub_efi_loongson_resource resource[GRUB_EFI_LOONGSON_MAX_RESOURCE_NUMBER]; -+ /* arch specific additions */ -+ grub_efi_loongson_archdev_data archdata; -+} -+grub_efi_loongson_board_devices; -+ -+typedef struct -+{ -+ grub_uint16_t vers; /* version */ -+ char special_name[64]; /* special_atribute_name */ -+ grub_uint32_t loongson_special_type; /* type of special device */ -+ /* for each device's resource */ -+ grub_efi_loongson_resource resource[GRUB_EFI_LOONGSON_MAX_RESOURCE_NUMBER]; -+} -+grub_efi_loongson_special_attribute; -+ -+typedef struct -+{ -+ grub_uint64_t memory_offset; /* efi_loongson_memory_map struct offset */ -+ grub_uint64_t cpu_offset; /* efi_loongson_cpuinfo struct offset */ -+ grub_uint64_t system_offset; /* efi_loongson_system_info struct offset */ -+ grub_uint64_t irq_offset; /* efi_loongson_irq_src_routing_table struct offset */ -+ grub_uint64_t interface_offset; /* interface_info struct offset */ -+ grub_uint64_t special_offset; /* efi_loongson_special_attribute struct offset */ -+ grub_uint64_t boarddev_table_offset; /* efi_loongson_board_devices offset */ -+} -+grub_efi_loongson_params; -+ -+typedef struct -+{ -+ grub_uint16_t vers; /* version */ -+ grub_uint64_t vga_bios; /* vga_bios address */ -+ grub_efi_loongson_params lp; -+} -+grub_efi_loongson_smbios_table; -+ -+typedef struct -+{ -+ grub_uint64_t reset_cold; -+ grub_uint64_t reset_warm; -+ grub_uint64_t reset_type; -+ grub_uint64_t shutdown; -+ grub_uint64_t do_suspend; /* NULL if not support */ -+} -+grub_efi_loongson_reset_system; -+ -+typedef struct -+{ -+ grub_uint64_t mps; /* MPS table */ -+ grub_uint64_t acpi; /* ACPI table (IA64 ext 0.71) */ -+ grub_uint64_t acpi20; /* ACPI table (ACPI 2.0) */ -+ grub_efi_loongson_smbios_table smbios; /* SM BIOS table */ -+ grub_uint64_t sal_systab; /* SAL system table */ -+ grub_uint64_t boot_info; /* boot info table */ -+} -+grub_efi_loongson; -+ -+typedef struct -+{ -+ grub_efi_loongson efi; -+ grub_efi_loongson_reset_system reset_system; -+} -+grub_efi_loongson_boot_params; -+ -+extern grub_uint64_t grub_efi_loongson_reset_system_addr; -+ -+extern void grub_efi_loongson_reset_cold (void); -+extern void grub_efi_loongson_reset_warm (void); -+extern void grub_efi_loongson_reset_shutdown (void); -+extern void grub_efi_loongson_reset_suspend (void); -+ -+void grub_efi_loongson_alloc_boot_params (void); -+void grub_efi_loongson_free_boot_params (void); -+void * grub_efi_loongson_get_smbios_table (void); -+ -+int EXPORT_FUNC(grub_efi_is_loongson) (void); ++typedef enum ++ { ++ GRUB_EFI_BPI_VER_NONE = 0, ++ GRUB_EFI_BPI_VER_V1 = 1000, ++ GRUB_EFI_BPI_VER_V2 = 1001, ++ } ++ grub_efi_loongson_bpi_version; + +grub_uint8_t -+EXPORT_FUNC(grub_efi_loongson_calculatesum8) (const grub_uint8_t *Buffer, grub_efi_uintn_t Length); ++EXPORT_FUNC(grub_efi_loongson_calculatesum8) (const grub_uint8_t *Buffer, ++ grub_efi_uintn_t Length); + +grub_uint8_t -+EXPORT_FUNC(grub_efi_loongson_grub_calculatechecksum8) (const grub_uint8_t *Buffer, grub_efi_uintn_t Length); ++EXPORT_FUNC(grub_efi_loongson_grub_calculatechecksum8) (const grub_uint8_t *Buffer, ++ grub_efi_uintn_t Length); + ++unsigned long ++EXPORT_FUNC(grub_efi_get_bpi_version) (const char *str); + +void * +EXPORT_FUNC(grub_efi_loongson_get_boot_params) (void); + -+typedef struct _extention_list_hdr{ ++typedef struct _extention_list_hdr { + grub_uint64_t signature; + grub_uint32_t length; + grub_uint8_t revision; + grub_uint8_t checksum; -+ struct _extention_list_hdr *next; ++ union { ++ struct _extention_list_hdr *next; ++ grub_uint64_t next_offset; ++ }; +}GRUB_PACKED +ext_list; + -+typedef struct bootparamsinterface { -+ grub_uint64_t signature; //{'B', 'P', 'I', '_', '0', '_', '1'} ++typedef struct boot_params_interface { ++ grub_uint64_t signature; //{'B', 'P', 'I', 'x', 'x', 'x', 'x', 'x'} + grub_efi_system_table_t *systemtable; -+ ext_list *extlist; ++ union { ++ ext_list *extlist; ++ grub_uint64_t extlist_offset; ++ }; ++ grub_uint64_t flags; +}GRUB_PACKED -+bootparamsinterface; ++boot_params_interface; + +typedef struct { -+ ext_list header; // {'M', 'E', 'M'} ++ ext_list header; //{MEM} + grub_uint8_t mapcount; -+ struct GRUB_PACKED memmap { ++ struct GRUB_PACKED memmap_v1 { + grub_uint32_t memtype; + grub_uint64_t memstart; + grub_uint64_t memsize; + } map[GRUB_EFI_LOONGSON_MMAP_MAX]; +}GRUB_PACKED -+mem_map; ++mem_map_v1; + +typedef struct { -+ ext_list header; // {VBIOS} ++ ext_list header; //{VBIOS} + grub_uint64_t vbiosaddr; +}GRUB_PACKED +vbios; + -+grub_uint32_t -+EXPORT_FUNC (grub_efi_loongson_memmap_sort) (struct memmap array[], grub_uint32_t length, mem_map * bpmem, grub_uint32_t index, grub_uint32_t memtype); ++grub_uint32_t ++EXPORT_FUNC (grub_efi_loongson_memmap_v1_sort) (struct memmap_v1 array[], ++ grub_uint32_t length, mem_map_v1 * mem, ++ grub_uint32_t index, grub_uint32_t memtype); +#endif /* ! GRUB_EFI_LOONGSON_HEADER */ diff --git a/include/grub/loongarch64/efi/memory.h b/include/grub/loongarch64/efi/memory.h new file mode 100644 -index 0000000..b8556c7 +index 0000000..73641a1 --- /dev/null +++ b/include/grub/loongarch64/efi/memory.h -@@ -0,0 +1,14 @@ +@@ -0,0 +1,12 @@ +#ifndef GRUB_MEMORY_CPU_HEADER +#include + -+#define GRUB_EFI_MAX_USABLE_ADDRESS 0x9800000fffffffffUL -+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS -+ -+static inline grub_uint64_t grub_efi_max_usable_address(void) ++static inline grub_uint64_t ++grub_efi_max_usable_address(void) +{ -+ grub_uint64_t addr; -+ asm volatile ("csrrd %0, 0x181" : "=r" (addr)); -+ return addr |= 0xffffffffffUL; ++ grub_uint64_t addr; ++ asm volatile ("csrrd %0, 0x181" : "=r" (addr)); ++ return addr |= 0xffffffffffUL; +} + +#endif /* ! GRUB_MEMORY_CPU_HEADER */ @@ -2944,15 +2387,15 @@ index 0000000..5f34103 +} + +#endif /* _SYS_IO_H */ -diff --git a/include/grub/loongarch64/kernel.h b/include/grub/loongarch64/kernel.h +diff --git a/include/grub/loongarch64/linux.h b/include/grub/loongarch64/linux.h new file mode 100644 -index 0000000..909d539 +index 0000000..3c6cf65 --- /dev/null -+++ b/include/grub/loongarch64/kernel.h -@@ -0,0 +1,24 @@ ++++ b/include/grub/loongarch64/linux.h +@@ -0,0 +1,74 @@ +/* + * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2005,2006,2007,2008,2009,2017 Free Software Foundation, Inc. ++ * Copyright (C) 2021 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 @@ -2968,38 +2411,60 @@ index 0000000..909d539 + * along with GRUB. If not, see . + */ + -+#ifndef GRUB_KERNEL_CPU_HEADER -+#define GRUB_KERNEL_CPU_HEADER 1 ++#ifndef GRUB_LOONGARCH64_LINUX_HEADER ++#define GRUB_LOONGARCH64_LINUX_HEADER 1 + -+#include ++#include + -+#endif /* ! GRUB_KERNEL_MACHINE_HEADER */ -diff --git a/include/grub/loongarch64/linux.h b/include/grub/loongarch64/linux.h -new file mode 100644 -index 0000000..cbf8775 ---- /dev/null -+++ b/include/grub/loongarch64/linux.h -@@ -0,0 +1,22 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2013 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. ++/* LoongArch linux kernel type */ ++#define GRUB_LOONGARCH_LINUX_BAD 0 ++#define GRUB_LOONGARCH_LINUX_ELF 1 ++#define GRUB_LOONGARCH_LINUX_EFI 2 ++ ++#define GRUB_LOONGSON3_BOOT_MEM_MAP_MAX 128 ++ ++#define GRUB_LINUX_LOONGARCH_MAGIC_SIGNATURE 0x4C6F6F6E67417263 /* 'LoongArc' */ ++#define GRUB_LINUX_LOONGARCH_MAGIC_SIGNATURE2 0x68 /* 'h' */ ++#define linux_arch_kernel_header linux_loongarch64_kernel_header ++ ++/* From linux/Documentation/loongarch/booting.txt + * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . ++ * 0-1: MZ ++ * 0x28: LoongArch\0 ++ * 0x3c: PE/COFF头偏移 ++ * 0x20e:内核版本号偏移-512 ++ * riscv的version字段在0x20偏移处,现在LoongArch没有使用,是0 + */ ++struct linux_loongarch64_kernel_header ++{ ++ grub_uint32_t code0; /* Executable code */ ++ grub_uint32_t code1; /* Executable code */ ++ grub_uint64_t text_offset; /* Image load offset */ ++ grub_uint64_t res0; /* reserved */ ++ grub_uint64_t res1; /* reserved */ ++ grub_uint64_t res2; /* reserved */ ++ grub_uint64_t magic; /* Magic number, little endian, "LoongArc" */ ++ grub_uint32_t magic1; /* Magic number, little endian, "h" */ ++ grub_uint64_t res3; /* reserved */ ++ grub_uint32_t hdr_offset; /* Offset of PE/COFF header */ ++}; + -+#ifndef GRUB_LOONGARCH64_LINUX_HEADER -+#define GRUB_LOONGARCH64_LINUX_HEADER 1 ++struct linux_loongarch64_kernel_params ++{ ++ grub_addr_t kernel_addr; /* kernel entry address */ ++ grub_size_t kernel_size; /* kernel size */ ++ grub_addr_t ramdisk_addr; /* initrd load address */ ++ grub_size_t ramdisk_size; /* initrd size */ ++ int linux_argc; ++ grub_addr_t linux_argv; ++ void* linux_args; ++}; ++ ++#include ++#include ++ ++#define ELF32_LOADMASK (0xf0000000UL) ++#define ELF64_LOADMASK (0xf000000000000000ULL) + +#endif /* ! GRUB_LOONGARCH64_LINUX_HEADER */ diff --git a/include/grub/loongarch64/loongarch64.h b/include/grub/loongarch64/loongarch64.h @@ -3040,10 +2505,10 @@ index 0000000..ea3be3d +#endif diff --git a/include/grub/loongarch64/memory.h b/include/grub/loongarch64/memory.h new file mode 100644 -index 0000000..03398b3 +index 0000000..8281dab --- /dev/null +++ b/include/grub/loongarch64/memory.h -@@ -0,0 +1,57 @@ +@@ -0,0 +1,60 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2017 Free Software Foundation, Inc. @@ -3084,12 +2549,15 @@ index 0000000..03398b3 +} + +static inline void * -+grub_map_memory (grub_phys_addr_t a, grub_size_t size) ++grub_map_memory (grub_phys_addr_t a, ++ grub_size_t size __attribute__ ((unused))) +{ + grub_uint64_t addr; -+ + asm volatile ("csrrd %0, 0x181" : "=r" (addr)); -+ return (void *) (a | (addr & 0xffffffffffffff00UL)); ++ if (addr & 0x1) ++ return (void *) (a | (addr & 0xffffffffffffff00UL)); ++ else ++ return (void *) a; +} + +static inline void @@ -3427,20 +2895,22 @@ index 65bb2f9..28b5d74 100644 char *dst = grub_util_path_concat (2, efidir, efi_file); grub_install_copy_file (imgfile, dst, 1); diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c -index 1bb5eb8..240e193 100644 +index 1bb5eb8..575fa14 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c -@@ -783,6 +783,9 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, +@@ -783,6 +783,11 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off); grub_uint64_t *gpptr = (void *) (pe_target + got_off); unsigned unmatched_adr_got_page = 0; ++#ifdef GRUB_CPU_LOONGARCH64 + grub_uint64_t oprs[10240]= {0}; + int opri = -1; + grub_uint32_t la_abs = 0; ++#endif #define MASK19 ((1 << 19) - 1) #else grub_uint32_t *tr = (void *) (pe_target + tramp_off); -@@ -1122,6 +1125,173 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, +@@ -1122,6 +1127,173 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, } break; } @@ -3614,19 +3084,17 @@ index 1bb5eb8..240e193 100644 #endif #if defined(MKIMAGE_ELF32) case EM_ARM: -@@ -1310,7 +1480,10 @@ add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type, +@@ -1310,6 +1482,9 @@ add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type, /* The spec does not mention the requirement of a Page RVA. Here, align the address with a 4K boundary for safety. */ -- b->page_rva = (addr & ~(0x1000 - 1)); +#ifdef GRUB_CPU_LOONGARCH64 + if (type) +#endif -+ b->page_rva = (addr & ~(0x1000 - 1)); + b->page_rva = (addr & ~(0x1000 - 1)); b->block_size = sizeof (*b); } - -@@ -1320,7 +1493,11 @@ add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type, +@@ -1320,7 +1495,11 @@ add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type, /* Add a new entry. */ cur_index = ((b->block_size - sizeof (*b)) >> 1); @@ -3638,7 +3106,7 @@ index 1bb5eb8..240e193 100644 b->entries[cur_index] = grub_host_to_target16 (entry); b->block_size += 2; } -@@ -1366,6 +1543,10 @@ static void +@@ -1366,6 +1545,10 @@ static void translate_relocation_pe (struct translate_context *ctx, Elf_Addr addr, Elf_Addr info, @@ -3649,7 +3117,7 @@ index 1bb5eb8..240e193 100644 const struct grub_install_image_target_desc *image_target) { /* Necessary to relocate only absolute addresses. */ -@@ -1477,6 +1658,133 @@ translate_relocation_pe (struct translate_context *ctx, +@@ -1477,6 +1660,133 @@ translate_relocation_pe (struct translate_context *ctx, } break; break; @@ -3783,7 +3251,7 @@ index 1bb5eb8..240e193 100644 #if defined(MKIMAGE_ELF32) case EM_ARM: switch (ELF_R_TYPE (info)) -@@ -1565,10 +1873,18 @@ static void +@@ -1565,10 +1875,18 @@ static void translate_relocation (struct translate_context *ctx, Elf_Addr addr, Elf_Addr info, @@ -3802,7 +3270,7 @@ index 1bb5eb8..240e193 100644 else translate_relocation_raw (ctx, addr, info, image_target); } -@@ -1709,11 +2025,21 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout, +@@ -1709,11 +2027,21 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout, if ((grub_target_to_host32 (s->sh_type) == SHT_REL) || (grub_target_to_host32 (s->sh_type) == SHT_RELA)) { @@ -3824,7 +3292,7 @@ index 1bb5eb8..240e193 100644 if (!SUFFIX (is_kept_reloc_section) (s, image_target, smd)) { -@@ -1732,20 +2058,39 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout, +@@ -1732,20 +2060,39 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout, section_address = smd->vaddrs[grub_le_to_cpu32 (s->sh_info)]; @@ -3964,5 +3432,5 @@ index 16418e2..0d39c07 100644 #include -- -2.27.0 +2.1.0 diff --git a/grub.patches b/grub.patches index 63b9afbadc379f3959a142d3a79e831acc3c4ac3..ba7b8b5dcc72085fc9c2be0b4d6fb96b68f7cd0b 100644 --- a/grub.patches +++ b/grub.patches @@ -548,5 +548,5 @@ Patch0547: 0547-nx-set-attrs-in-our-kernel-loaders.patch Patch0548: 0548-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch Patch0549: 0549-Fixup-grub_efi_get_variable-type-in-our-loaders.patch # Support loongarch64 -#Patch1000: 1000-loongarch64-add-support.patch Patch1001: 1001-bls-make-list.patch +Patch1002: 1002-Add-LoongArch64-support-and-update-interface-to-v40.patch diff --git a/grub2.spec b/grub2.spec index b7a8c8558e68b2d3ccc409e5ef6d1f8d38dcdc42..15eb053d33092540eff5bdb24573c3f73d535067 100644 --- a/grub2.spec +++ b/grub2.spec @@ -1,4 +1,4 @@ -%define anolis_release .0.1 +%define anolis_release .0.2 %undefine _hardened_build %global tarversion 2.02 @@ -523,6 +523,11 @@ fi %endif %changelog +* Wed Jul 6 2022 QiMing Yang - 2.02-123.0.2.8 +- Delete LoongArch64 support old version due to compile error +- Add LoongArch64 support +- LoongArch64 support fdt and phy-addr BIOS + * Fri Jun 17 2022 Bo Ren - 2.02-123.0.1.8 - Build pc-modules package on x86_64 (geliwei@openanolis.org) - Add loongarch64 base support (zhangwenlong@loongson.cn)(chenguoqi@loongson.cn)