diff --git a/grub.macros b/grub.macros index c2401361df15a0383ececc3fab1227857b88dc62..846aa20845299b54db0c4e468ff07114030582e7 100644 --- a/grub.macros +++ b/grub.macros @@ -200,6 +200,14 @@ %global package_arch efi-loongarch64 %endif +%ifarch sw_64 +%global with_emu_arch 0 +%global efiarch sw_64 +%global target_cpu_name sw_64 +%global grub_target_name sw_64-efi +%global package_arch efi-sw_64 +%endif + %global _target_platform %{target_cpu_name}-%{_vendor}-%{_target_os}%{?_gnu} %global _alt_target_platform %{alt_target_cpu_name}-%{_vendor}-%{_target_os}%{?_gnu} diff --git a/grub.patches b/grub.patches index 10db3780fbf99ec27933a2daa46a0715a8eab3e4..ec96896dd68006eb5e51c9cd7a54e28fd17fe6a8 100644 --- a/grub.patches +++ b/grub.patches @@ -440,3 +440,8 @@ Patch0440: backport-0080-kern-misc-Add-sanity-check-after-grub_strtoul-call.patc Patch0441: backport-0081-loader-i386-linux-Cast-left-shift-to-grub_uint32_t.patch Patch0442: backport-0082-loader-i386-bsd-Use-safe-math-to-avoid-underflow.patch Patch0443: backport-fix-CVE-2024-56738.patch +Patch0444: sw64-Add-early-startup-code.patch +Patch0445: sw64-Add-Linux-load-logic.patch +Patch0446: sw64-Add-awareness-for-SW64-reloations.patch +Patch0447: sw64-Add-auxiliary-files.patch +Patch0448: sw64-Add-to-build-system.patch diff --git a/grub2.spec b/grub2.spec index bfe3ed2b41710f9f93b59057d21741902376a3fb..635e6ef3d1ed2ebbb367465737c55a1357e3d726 100644 --- a/grub2.spec +++ b/grub2.spec @@ -14,7 +14,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 48 +Release: 49 Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -440,6 +440,16 @@ fi %{_datadir}/man/man* %changelog +* Tue Feb 18 2025 sunway_fw - 1:2.06-49 +- Type:requirement +- CVE:NA +- SUG:NA +- DESC: add SW64 early startup code + add support running Linux underneath as UEFI payload for SW64 arch + add awareness of SW64 relocations throughout the grub tools and elf->PE relocation conversion support + add helper functions of memory, cache, timer, etc support for SW64 arch + add SW64 to the GRUB build system and various tools + * Tue Apr 8 2025 zhangqiumiao - 1:2.06-48 - Type:CVE - CVE:CVE-2024-56738 diff --git a/sw64-Add-Linux-load-logic.patch b/sw64-Add-Linux-load-logic.patch new file mode 100644 index 0000000000000000000000000000000000000000..dd6b2a6ddf67a65830c08e94ffdb829200ca44c3 --- /dev/null +++ b/sw64-Add-Linux-load-logic.patch @@ -0,0 +1,597 @@ +From cd40953880ea54d1e0d3c6580b2d3af04db92f16 Mon Sep 17 00:00:00 2001 +From: sunway_fw +Date: Tue, 18 Feb 2025 14:58:36 +0800 +Subject: [PATCH 2/5] sw64: Add Linux load logic + +We currently only support to run grub on SW64 as UEFI payload. Ideally, +we also only want to support running Linux underneath as UEFI payload. + +Signed-off-by: sunway_fw +--- + grub-core/loader/sw64/efi/linux.c | 519 ++++++++++++++++++++++++++++++ + include/grub/sw64/linux.h | 47 +++ + 2 files changed, 566 insertions(+) + create mode 100644 grub-core/loader/sw64/efi/linux.c + create mode 100644 include/grub/sw64/linux.h + +diff --git a/grub-core/loader/sw64/efi/linux.c b/grub-core/loader/sw64/efi/linux.c +new file mode 100644 +index 0000000..3b5c20b +--- /dev/null ++++ b/grub-core/loader/sw64/efi/linux.c +@@ -0,0 +1,519 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++#pragma GCC diagnostic ignored "-Wcast-align" ++ ++#define GRUB_EFI_SW64_FIRMWARE_INFO { 0xc47a23c3, 0xcebb, 0x4cc9, \ ++ { 0xa5, 0xe2, 0xde, 0xd0, 0x8f, 0xe4, 0x20, 0xb5 } } ++ ++#define GRUB_EFI_SW64_MEMORY_ATTRIBUTES { 0xdcfa911d, 0x26eb, 0x469f, \ ++ { 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20 } } ++ ++#define SW64_EFI_FIRMWARE_INFO_SIGNATURE \ ++ ('S' << 24 | 'H' << 16 | 'I' << 8 | 'F') ++ ++static grub_dl_t my_mod; ++static int loaded; ++static char *linux_args; ++ ++/* Initrd base and size. */ ++static void *initrd_mem; ++static grub_efi_uintn_t initrd_pages; ++static grub_addr_t initrd_start; ++static grub_efi_uintn_t initrd_size; ++static grub_uint64_t linux_entry; ++ ++struct sw64_firmware_info_head ++{ ++ grub_uint32_t signature; ++ grub_uint32_t revision; ++ grub_uint32_t length; ++}; ++ ++struct sw64_firmware_info ++{ ++ struct sw64_firmware_info_head firmware_info_head; ++ grub_uint32_t reserved; ++ grub_uint32_t need_boot_param; ++}; ++ ++void *raw_fdt; ++static struct boot_param *sunway_boot_params = (struct boot_param *)BOOT_PARAM_START; ++ ++static grub_efi_uint32_t ++sw64_efi_get_boot_param (void) ++{ ++ unsigned i; ++ struct sw64_firmware_info_head *firmware_info_head; ++ static grub_efi_packed_guid_t info_guid = GRUB_EFI_SW64_FIRMWARE_INFO; ++ ++ for (i = 0; i < grub_efi_system_table->num_table_entries; i++) ++ { ++ grub_efi_packed_guid_t *guid = ++ &grub_efi_system_table->configuration_table[i].vendor_guid; ++ ++ if (! grub_memcmp (guid, &info_guid, sizeof (grub_efi_packed_guid_t))) ++ { ++ firmware_info_head = grub_efi_system_table->configuration_table[i].vendor_table; ++ if (firmware_info_head->signature != SW64_EFI_FIRMWARE_INFO_SIGNATURE) { ++ return 1; ++ } ++ ++ if (firmware_info_head->revision == 1) { ++ return ((struct sw64_firmware_info *)firmware_info_head)->need_boot_param; ++ } ++ } ++ } ++ return 1; ++} ++ ++static void ++sw64_efi_memattr_repair (void) ++{ ++ unsigned i; ++ static grub_efi_packed_guid_t info_guid = GRUB_EFI_SW64_MEMORY_ATTRIBUTES; ++ ++ for (i = 0; i < grub_efi_system_table->num_table_entries; i++) { ++ grub_efi_packed_guid_t *guid = &grub_efi_system_table->configuration_table[i].vendor_guid; ++ ++ if (! grub_memcmp (guid, &info_guid, sizeof (grub_efi_packed_guid_t))) { ++ grub_efi_system_table->configuration_table[i].vendor_table = (void *)grub_virt_to_phys((grub_uint64_t)grub_efi_system_table->configuration_table[i].vendor_table); ++ } ++ } ++} ++ ++typedef ++void ++(*jump_to_kernel) ( ++ grub_uint64_t magic, ++ grub_uint64_t device_tree_base ++ ); ++ ++static grub_err_t ++finalize_params_linux (void) ++{ ++ int retval; ++ int node; ++ grub_efi_uintn_t mmap_size; ++ grub_efi_uintn_t map_key; ++ grub_efi_uintn_t desc_size; ++ grub_efi_uint32_t desc_version; ++ grub_efi_memory_descriptor_t *mmap_buf; ++ grub_efi_uintn_t i; ++ grub_uint32_t bootargs_size; ++ const char *last_bootargs; ++ static char *temp_linux_args; ++ ++ mmap_buf = 0; ++ ++ raw_fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE); ++ ++ if (!raw_fdt || grub_fdt_check_header_nosize(raw_fdt)) { ++ goto failure; ++ } ++ ++ node = grub_fdt_find_subnode (raw_fdt, 0, "chosen"); ++ if (node < 0) ++ node = grub_fdt_add_subnode (raw_fdt, 0, "chosen"); ++ ++ if (node < 1) ++ goto failure; ++ ++ initrd_start = grub_virt_to_phys (initrd_start); ++ ++ if (initrd_start) { ++ retval = grub_fdt_set_prop64 (raw_fdt, node, "linux,initrd-start", initrd_start); ++ if (retval) ++ goto failure; ++ ++ retval = grub_fdt_set_prop64 (raw_fdt, node, "linux,initrd-end", initrd_start + initrd_size); ++ if (retval) ++ goto failure; ++ } ++ ++ last_bootargs = grub_fdt_get_prop (raw_fdt, node, "bootargs", &bootargs_size); ++ if (last_bootargs && grub_strlen (last_bootargs) > 1) { ++ temp_linux_args = grub_malloc (grub_strlen (linux_args) + bootargs_size + 1); ++ if (!temp_linux_args) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory in finalize_params_linux")); ++ goto failure; ++ } ++ grub_memcpy (temp_linux_args, last_bootargs, bootargs_size - 1); ++ *(temp_linux_args + bootargs_size - 1) = ' '; ++ grub_memcpy (temp_linux_args + bootargs_size, linux_args, grub_strlen (linux_args) + 1); ++ grub_free (linux_args); ++ linux_args = temp_linux_args; ++ } ++ ++ retval = grub_fdt_set_prop (raw_fdt, node, "bootargs", linux_args, grub_strlen (linux_args) + 1); ++ if (retval) ++ goto failure; ++ ++ retval = grub_fdt_set_prop64 (raw_fdt, node, "linux,uefi-system-table", ++ grub_virt_to_phys((grub_uint64_t)grub_efi_system_table)); ++ if (retval) ++ goto failure; ++ ++ mmap_size = grub_efi_find_mmap_size (); ++ if (! mmap_size) ++ goto failure; ++ ++ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); ++ if (! mmap_buf) ++ goto failure; ++ ++ grub_efi_finish_boot_services (&mmap_size, mmap_buf, &map_key, &desc_size, &desc_version); ++ ++ retval = grub_fdt_set_prop64 (raw_fdt, node, "linux,uefi-mmap-start", ++ grub_virt_to_phys((grub_uint64_t)mmap_buf)); ++ ++ retval = grub_fdt_set_prop64 (raw_fdt, node, "linux,uefi-mmap-size", mmap_size); ++ if (retval) ++ goto failure_without_dprintf; ++ ++ retval = grub_fdt_set_prop64 (raw_fdt, node, "linux,uefi-mmap-desc-size", desc_size); ++ if (retval) ++ goto failure_without_dprintf; ++ ++ retval = grub_fdt_set_prop64 (raw_fdt, node, "linux,uefi-mmap-desc-ver", desc_version); ++ if (retval) ++ goto failure_without_dprintf; ++ ++ for (i = 0; i < mmap_size / desc_size; i++) { ++ grub_efi_memory_descriptor_t *curdesc = (grub_efi_memory_descriptor_t *) ++ ((char *) mmap_buf + desc_size * i); ++ ++ curdesc->physical_start = grub_virt_to_phys(curdesc->physical_start); ++ } ++ ++ sw64_efi_memattr_repair(); ++ ++ return GRUB_ERR_NONE; ++ ++failure: ++ grub_dprintf ("linux", "some wrong in finalize_params_linux\n"); ++ ++failure_without_dprintf: ++ raw_fdt = 0; ++ return GRUB_ERR_BAD_OS; ++} ++ ++static grub_err_t ++legacy_finalize_params_linux (void) ++{ ++ grub_efi_uintn_t mmap_size; ++ grub_efi_uintn_t map_key; ++ grub_efi_uintn_t desc_size; ++ grub_efi_uint32_t desc_version; ++ grub_efi_memory_descriptor_t *mmap_buf; ++ grub_err_t err; ++ grub_efi_uintn_t i; ++ ++ /* Initrd. */ ++ sunway_boot_params->initrd_start = (grub_uint64_t)initrd_start; ++ sunway_boot_params->initrd_size = (grub_uint64_t)initrd_size; ++ ++ /* DTB. */ ++ raw_fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE); ++ ++ if (!raw_fdt) ++ { ++ sunway_boot_params->dtb_start = 0; ++ grub_dprintf ("linux", "not found registered FDT\n"); ++ } ++ ++ if (raw_fdt) ++ { ++ err = grub_fdt_check_header_nosize(raw_fdt); ++ if (err) ++ grub_dprintf ("linux", "illegal FDT file\n"); ++ ++ sunway_boot_params->dtb_start = (grub_uint64_t)raw_fdt; ++ grub_dprintf ("linux", "dtb: [addr=0x%lx, size=0x%x]\n", ++ (grub_uint64_t) raw_fdt, grub_fdt_get_totalsize(raw_fdt)); ++ } ++ ++ /* MDT. ++ Must be done after grub_machine_fini because map_key is used by ++ exit_boot_services. */ ++ mmap_size = grub_efi_find_mmap_size (); ++ if (! mmap_size) { ++ grub_dprintf ("linux", "unable to get mmap_size\n"); ++ return GRUB_ERR_BAD_OS; ++ } ++ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size)); ++ if (! mmap_buf) { ++ grub_dprintf ("linux", "cannot allocate memory map\n"); ++ return GRUB_ERR_BAD_OS; ++ } ++ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, &map_key, ++ &desc_size, &desc_version); ++ for (i = 0; i < mmap_size / desc_size; i++) ++ { ++ grub_efi_memory_descriptor_t *curdesc = (grub_efi_memory_descriptor_t *) ++ ((char *) mmap_buf + desc_size * i); ++ ++ curdesc->physical_start = grub_virt_to_phys(curdesc->physical_start); ++ } ++ ++ sw64_efi_memattr_repair(); ++ ++ sunway_boot_params->command_line = (grub_uint64_t) linux_args; ++ sunway_boot_params->efi_systab = grub_virt_to_phys((grub_uint64_t)grub_efi_system_table); ++ sunway_boot_params->efi_memmap = grub_virt_to_phys((grub_uint64_t)mmap_buf); ++ sunway_boot_params->efi_memmap_size = mmap_size; ++ sunway_boot_params->efi_memdesc_size = desc_size; ++ sunway_boot_params->efi_memdesc_version = desc_version; ++ ++ return GRUB_ERR_NONE; ++} ++static void ++start_kernel(void) ++{ ++ local_irq_disable (); ++ grub_dprintf ("linux", "Jump to entry: %lx\n", linux_entry); ++ ++ jump_to_kernel jump = (jump_to_kernel) linux_entry; ++ if (sw64_efi_get_boot_param()) { ++ jump (0, 0); ++ } else { ++ jump (0xdeed2024, (grub_uint64_t)raw_fdt); ++ } ++} ++ ++static grub_err_t ++grub_linux_boot (void) ++{ ++ if (sw64_efi_get_boot_param()) { ++ legacy_finalize_params_linux(); ++ } else { ++ finalize_params_linux(); ++ } ++ ++ start_kernel (); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_linux_unload (void) ++{ ++ grub_dl_unref (my_mod); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_load_elf64 (grub_elf_t elf, const char *filename) ++{ ++ Elf64_Addr base_addr; ++ grub_size_t linux_size; ++ grub_uint64_t align; ++ ++ if (elf->ehdr.ehdr64.e_ident[EI_MAG0] != ELFMAG0 ++ || elf->ehdr.ehdr64.e_ident[EI_MAG1] != ELFMAG1 ++ || elf->ehdr.ehdr64.e_ident[EI_MAG2] != ELFMAG2 ++ || elf->ehdr.ehdr64.e_ident[EI_MAG3] != ELFMAG3 ++ || elf->ehdr.ehdr64.e_ident[EI_DATA] != ELFDATA2LSB) ++ return grub_error(GRUB_ERR_UNKNOWN_OS, ++ N_("invalid arch-independent ELF magic")); ++ ++ if (elf->ehdr.ehdr64.e_ident[EI_CLASS] != ELFCLASS64 ++ || elf->ehdr.ehdr64.e_version != EV_CURRENT ++ || elf->ehdr.ehdr64.e_machine != EM_SW_64) ++ return grub_error (GRUB_ERR_UNKNOWN_OS, ++ N_("invalid arch-dependent ELF magic")); ++ ++ if (elf->ehdr.ehdr64.e_type != ET_EXEC) ++ return grub_error (GRUB_ERR_UNKNOWN_OS, ++ N_("this ELF file is not of the right type")); ++ ++ /* FIXME: Should we support program headers at strange locations? */ ++ if (elf->ehdr.ehdr64.e_phoff + elf->ehdr.ehdr64.e_phnum * elf->ehdr.ehdr64.e_phentsize > GRUB_ELF_SEARCH) ++ return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset"); ++ ++ linux_size = grub_elf64_size (elf, &base_addr, &align); ++ if (linux_size == 0) ++ return grub_error (GRUB_ERR_BAD_OS, "linux size is 0"); ++ ++ linux_entry = (grub_uint64_t)elf->ehdr.ehdr64.e_entry; ++ grub_dprintf ("linux", "Segment phy_addr: %lx entry: %lx\n", (grub_uint64_t)base_addr,(grub_uint64_t)elf->ehdr.ehdr64.e_entry); ++ ++ /* Now load the segments into the area we claimed. */ ++ return grub_elf64_load (elf, filename, (void *) (grub_addr_t) (0), GRUB_ELF_LOAD_FLAGS_NONE, 0, 0); ++} ++ ++static grub_err_t ++grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), ++ int argc, char *argv[]) ++{ ++ grub_ssize_t size; ++ grub_elf_t elf = 0; ++ ++ grub_dl_ref (my_mod); ++ ++ grub_loader_unset (); ++ ++ if (argc == 0) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ goto fail; ++ } ++ ++ elf = grub_elf_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL); ++ if (! elf) ++ goto fail; ++ ++ grub_dprintf ("linux", "Loading linux: %s\n", argv[0]); ++ ++ if (grub_load_elf64 (elf, argv[0])) ++ goto fail; ++ ++ grub_memset (sunway_boot_params, 0, sizeof(*sunway_boot_params)); ++ size = grub_loader_cmdline_size(argc, argv); ++ ++ linux_args = grub_malloc (size + sizeof (LINUX_IMAGE)); ++ if (!linux_args) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto fail; ++ } ++ ++ /* Create kernel command line. */ ++ grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); ++ grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1, ++ size, GRUB_VERIFY_KERNEL_CMDLINE); ++ ++ grub_dprintf ("linux", "linux_args: '%s'\n", linux_args); ++ grub_errno = GRUB_ERR_NONE; ++ ++ grub_loader_set (grub_linux_boot, grub_linux_unload, 0); ++ ++ fail: ++ if (elf) ++ grub_elf_close (elf); ++ ++ if (grub_errno != GRUB_ERR_NONE) ++ { ++ grub_dl_unref (my_mod); ++ loaded = 0; ++ } ++ else ++ loaded = 1; ++ ++ return grub_errno; ++} ++ ++static grub_err_t ++grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), ++ int argc, char *argv[]) ++{ ++ struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 }; ++ ++ if (argc == 0) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ goto fail; ++ } ++ ++ if (! loaded) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); ++ goto fail; ++ } ++ ++ if (grub_initrd_init (argc, argv, &initrd_ctx)) ++ goto fail; ++ ++ initrd_size = grub_get_initrd_size (&initrd_ctx); ++ if (initrd_size == 0) ++ { ++ initrd_start = 0; ++ return grub_errno; ++ } ++ ++ grub_dprintf ("linux", "Loading initrd %s\n", argv[0]); ++ ++ initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size)); ++ initrd_mem = grub_efi_allocate_any_pages (initrd_pages); ++ if (! initrd_mem) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate pages"); ++ goto fail; ++ } ++ ++ grub_dprintf ("linux", "initrd: [addr=0x%lx, size=0x%lx]\n", ++ (grub_uint64_t) initrd_mem, initrd_size); ++ ++ if (grub_initrd_load (&initrd_ctx, argv, initrd_mem)) ++ goto fail; ++ ++ initrd_start = (grub_addr_t) initrd_mem; ++ ++ fail: ++ grub_initrd_close (&initrd_ctx); ++ if (initrd_mem && !initrd_start) ++ grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages); ++ ++ return grub_errno; ++} ++ ++static grub_command_t cmd_linux, cmd_initrd; ++ ++GRUB_MOD_INIT (linux) ++{ ++ cmd_linux = grub_register_command ("linux", grub_cmd_linux, ++ N_("FILE [ARGS...]"), N_("Load Linux.")); ++ ++ cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, ++ N_("FILE"), N_("Load initrd.")); ++ ++ my_mod = mod; ++} ++ ++GRUB_MOD_FINI (linux) ++{ ++ grub_unregister_command (cmd_linux); ++ grub_unregister_command (cmd_initrd); ++} +diff --git a/include/grub/sw64/linux.h b/include/grub/sw64/linux.h +new file mode 100644 +index 0000000..c4d0907 +--- /dev/null ++++ b/include/grub/sw64/linux.h +@@ -0,0 +1,47 @@ ++#ifndef GRUB_SW_H ++#define GRUB_SW_H 1 ++#define PAGE_OFFSET 0xfff0000000000000UL ++#define KTEXT_OFFSET 0xffffffff80000000UL ++#define GRUB_PRINTK_START (PAGE_OFFSET | 0x800000) ++#define GRUB_PRINTK_SIZE (0x20000) ++#define BOOT_PARAM_START 0xfff000000090a100ULL ++ ++#define GRUB_ELF_SEARCH 1024 ++#define IPL_MIN 0 ++#define IPL_MAX 7 ++#define barrier() __asm__ __volatile__("": : :"memory") ++#define local_irq_disable() do { swpipl(IPL_MAX); barrier(); } while(0) ++#define local_irq_enable() do { barrier(); swpipl(IPL_MIN); } while(0) ++ ++static inline ++grub_uint64_t ++grub_virt_to_phys(grub_uint64_t x) ++{ ++ if (x >= KTEXT_OFFSET) ++ x -= KTEXT_OFFSET; ++ else if (x >= PAGE_OFFSET) ++ x -= PAGE_OFFSET; ++ ++ return x; ++} ++ ++struct boot_param ++{ ++ grub_uint64_t initrd_start; /* logical address of initrd */ ++ grub_uint64_t initrd_size; /* size of initrd */ ++ grub_uint64_t dtb_start; /* logical address of dtb */ ++ grub_uint64_t efi_systab; /* logical address of EFI system table */ ++ grub_uint64_t efi_memmap; /* logical address of EFI memory map */ ++ grub_uint64_t efi_memmap_size; /* size of EFI memory map */ ++ grub_uint64_t efi_memdesc_size; /* size of an EFI memory map descriptor */ ++ grub_uint64_t efi_memdesc_version; /* memory descriptor version */ ++ grub_uint64_t command_line; /* logical address of cmdline */ ++}; ++ ++struct linux_sw64_kernel_header ++{ ++}; ++ ++#define linux_arch_kernel_header linux_sw64_kernel_header ++ ++#endif +-- +2.17.1 + diff --git a/sw64-Add-auxiliary-files.patch b/sw64-Add-auxiliary-files.patch new file mode 100644 index 0000000000000000000000000000000000000000..0c4eadcb2048f228a1a3d72fdb76d8145dfcf02e --- /dev/null +++ b/sw64-Add-auxiliary-files.patch @@ -0,0 +1,1770 @@ +From 9388fbee1ea1672e6ca174f405aaf3a9e15b18b7 Mon Sep 17 00:00:00 2001 +From: sunway_fw +Date: Tue, 25 Feb 2025 03:06:36 +0800 +Subject: [PATCH 4/5] sw64: Add auxiliary files + +To support a new architecture we need to provide a few helper functions +for memory, cache, timer, etc support. + +Signed-off-by: sunway_fw +--- + grub-core/kern/sw64/cache.c | 63 +++ + grub-core/kern/sw64/cache_flush.S | 44 ++ + grub-core/kern/sw64/dl_helper.c | 72 +++ + grub-core/kern/sw64/efi/callwrap.S | 261 +++++++++++ + grub-core/kern/sw64/efi/init.c | 75 ++++ + grub-core/lib/sw64/divide.S | 677 +++++++++++++++++++++++++++++ + grub-core/lib/sw64/setjmp.S | 75 ++++ + include/grub/sw64/divide.h | 11 + + include/grub/sw64/efi/memory.h | 7 + + include/grub/sw64/efi/time.h | 23 + + include/grub/sw64/io.h | 62 +++ + include/grub/sw64/jmpbuf-offsets.h | 35 ++ + include/grub/sw64/kernel.h | 25 ++ + include/grub/sw64/pal.h | 49 +++ + include/grub/sw64/regdef.h | 44 ++ + include/grub/sw64/setjmp.h | 28 ++ + include/grub/sw64/time.h | 28 ++ + include/grub/sw64/types.h | 32 ++ + 18 files changed, 1611 insertions(+) + create mode 100644 grub-core/kern/sw64/cache.c + create mode 100644 grub-core/kern/sw64/cache_flush.S + create mode 100644 grub-core/kern/sw64/dl_helper.c + create mode 100644 grub-core/kern/sw64/efi/callwrap.S + create mode 100644 grub-core/kern/sw64/efi/init.c + create mode 100644 grub-core/lib/sw64/divide.S + create mode 100644 grub-core/lib/sw64/setjmp.S + create mode 100644 include/grub/sw64/divide.h + create mode 100644 include/grub/sw64/efi/memory.h + create mode 100644 include/grub/sw64/efi/time.h + create mode 100644 include/grub/sw64/io.h + create mode 100644 include/grub/sw64/jmpbuf-offsets.h + create mode 100644 include/grub/sw64/kernel.h + create mode 100644 include/grub/sw64/pal.h + create mode 100644 include/grub/sw64/regdef.h + create mode 100644 include/grub/sw64/setjmp.h + create mode 100644 include/grub/sw64/time.h + create mode 100644 include/grub/sw64/types.h + +diff --git a/grub-core/kern/sw64/cache.c b/grub-core/kern/sw64/cache.c +new file mode 100644 +index 0000000..9278dda +--- /dev/null ++++ b/grub-core/kern/sw64/cache.c +@@ -0,0 +1,63 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++ ++static grub_int64_t dlinesz; ++static grub_int64_t ilinesz; ++ ++/* Prototypes for asm functions. */ ++void grub_arch_clean_dcache_range (grub_addr_t beg, grub_addr_t end, ++ grub_size_t line_size); ++void grub_arch_invalidate_icache_range (grub_addr_t beg, grub_addr_t end, ++ grub_size_t line_size); ++ ++static void ++probe_caches (void) ++{ ++ /* TODO */ ++ dlinesz = 128; ++ ilinesz = 128; ++} ++ ++void ++grub_arch_sync_caches (void *address, grub_size_t len) ++{ ++ grub_size_t start, end, max_align; ++ ++ if (dlinesz == 0) ++ probe_caches(); ++ if (dlinesz == 0) ++ grub_fatal ("Unknown cache line size!"); ++ ++ max_align = dlinesz > ilinesz ? dlinesz : ilinesz; ++ ++ start = ALIGN_DOWN ((grub_size_t) address, max_align); ++ end = ALIGN_UP ((grub_size_t) address + len, max_align); ++ ++ grub_arch_clean_dcache_range (start, end, dlinesz); ++ grub_arch_invalidate_icache_range (start, end, ilinesz); ++} ++ ++void ++grub_arch_sync_dma_caches (volatile void *address __attribute__((unused)), ++ grub_size_t len __attribute__((unused))) ++{ ++ /* DMA incoherent devices not supported yet */ ++} +diff --git a/grub-core/kern/sw64/cache_flush.S b/grub-core/kern/sw64/cache_flush.S +new file mode 100644 +index 0000000..dde3e5c +--- /dev/null ++++ b/grub-core/kern/sw64/cache_flush.S +@@ -0,0 +1,44 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 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 "cache_flush.S" ++ .text ++ ++/* ++ * Simple cache maintenance functions ++ */ ++ ++/* ++ * a0 - *beg (inclusive) ++ * a1 - *end (exclusive) ++ * a2 - line size ++*/ ++FUNCTION(grub_arch_clean_dcache_range) ++ /* TODO */ ++ ret ++ ++/* ++ * a0 - *beg (inclusive) ++ * a1 - *end (exclusive) ++ * a2 - line size ++ */ ++FUNCTION(grub_arch_invalidate_icache_range) ++ memb ++ ret +diff --git a/grub-core/kern/sw64/dl_helper.c b/grub-core/kern/sw64/dl_helper.c +new file mode 100644 +index 0000000..9628ddf +--- /dev/null ++++ b/grub-core/kern/sw64/dl_helper.c +@@ -0,0 +1,72 @@ ++/* dl.c - arch-dependent part of loadable module support */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2002,2004,2005,2007,2009 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#pragma GCC diagnostic ignored "-Wcast-align" ++ ++grub_err_t ++grub_sw64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, ++ grub_size_t *got) ++{ ++ const Elf64_Ehdr *e = ehdr; ++ grub_size_t cntt = 0, cntg = 0;; ++ const Elf64_Shdr *s; ++ unsigned i; ++ ++ *tramp = 0; ++ *got = 0; ++ ++ /* Find a symbol table. */ ++ for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff)); ++ i < grub_le_to_cpu16 (e->e_shnum); ++ i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) ++ if (grub_le_to_cpu32 (s->sh_type) == SHT_SYMTAB) ++ break; ++ ++ if (i == grub_le_to_cpu16 (e->e_shnum)) ++ return GRUB_ERR_NONE; ++ ++ for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff)); ++ i < grub_le_to_cpu16 (e->e_shnum); ++ i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) ++ if (grub_le_to_cpu32 (s->sh_type) == SHT_RELA) ++ { ++ Elf64_Rela *rel, *max; ++ ++ for (rel = (Elf64_Rela *) ((char *) e + grub_le_to_cpu32 (s->sh_offset)), ++ max = rel + grub_le_to_cpu32 (s->sh_size) / grub_le_to_cpu16 (s->sh_entsize); ++ rel < max; rel++) ++ switch (ELF64_R_TYPE (grub_le_to_cpu32 (rel->r_info))) ++ { ++ case R_SW64_LITERAL: ++ cntg++; ++ break; ++ } ++ } ++ *tramp = cntt; ++ *got = cntg * sizeof (grub_uint64_t); ++ ++ return GRUB_ERR_NONE; ++} ++ +diff --git a/grub-core/kern/sw64/efi/callwrap.S b/grub-core/kern/sw64/efi/callwrap.S +new file mode 100644 +index 0000000..13ee13d +--- /dev/null ++++ b/grub-core/kern/sw64/efi/callwrap.S +@@ -0,0 +1,261 @@ ++ .file "callwrap.S" ++ .text ++ .align 4 ++ .globl sw_efi_wrap_0 ++ .globl sw_efi_wrap_1 ++ .globl sw_efi_wrap_2 ++ .globl sw_efi_wrap_3 ++ .globl sw_efi_wrap_4 ++ .globl sw_efi_wrap_5 ++ .globl sw_efi_wrap_6 ++ .globl sw_efi_wrap_7 ++ .globl sw_efi_wrap_10 ++ ++ .ent sw_efi_wrap_0 ++sw_efi_wrap_0: ++ ++ ldi $30,-32($30) ++ stl $26,0($30) ++ stl $15,8($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,16($15) ++ ldl $27,16($15) ++ call $26,($27),0 ++ #ldi $29,0($29) !gpdisp!29 ++ mov $15,$30 ++ ldl $26,0($30) ++ ldl $15,8($30) ++ ldi $30,32($30) ++ ret $31,($26),1 ++ ++ .end sw_efi_wrap_0 ++ ++ .ent sw_efi_wrap_1 ++sw_efi_wrap_1: ++ ++ ldi $30,-32($30) ++ stl $26,0($30) ++ stl $15,8($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,16($15) ++ stl $17,24($15) ++ ldl $27,16($15) ++ ldl $16,24($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!31 ++ #ldi $29,0($29) !gpdisp!31 ++ mov $15,$30 ++ ldl $26,0($30) ++ ldl $15,8($30) ++ ldi $30,32($30) ++ ret $31,($26),1 ++ .end sw_efi_wrap_1 ++ ++ .ent sw_efi_wrap_2 ++sw_efi_wrap_2: ++ ldi $30,-48($30) ++ stl $26,0($30) ++ stl $15,8($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,16($15) ++ stl $17,24($15) ++ stl $18,32($15) ++ ldl $27,16($15) ++ ldl $16,24($15) ++ ldl $17,32($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!33 ++ #ldi $29,0($29) !gpdisp!33 ++ mov $15,$30 ++ ldl $26,0($30) ++ ldl $15,8($30) ++ ldi $30,48($30) ++ ret $31,($26),1 ++ .end sw_efi_wrap_2 ++ ++ .ent sw_efi_wrap_3 ++sw_efi_wrap_3: ++ ldi $30,-48($30) ++ stl $26,0($30) ++ stl $15,8($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,16($15) ++ stl $17,24($15) ++ stl $18,32($15) ++ stl $19,40($15) ++ ldl $27,16($15) ++ ldl $16,24($15) ++ ldl $17,32($15) ++ ldl $18,40($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!35 ++ #ldi $29,0($29) !gpdisp!35 ++ mov $15,$30 ++ ldl $26,0($30) ++ ldl $15,8($30) ++ ldi $30,48($30) ++ ret $31,($26),1 ++ .end sw_efi_wrap_3 ++ ++ .ent sw_efi_wrap_4 ++sw_efi_wrap_4: ++ ldi $30,-64($30) ++ stl $26,0($30) ++ stl $15,8($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,16($15) ++ stl $17,24($15) ++ stl $18,32($15) ++ stl $19,40($15) ++ stl $20,48($15) ++ ldl $27,16($15) ++ ldl $16,24($15) ++ ldl $17,32($15) ++ ldl $18,40($15) ++ ldl $19,48($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!37 ++ #ldi $29,0($29) !gpdisp!37 ++ mov $15,$30 ++ ldl $26,0($30) ++ ldl $15,8($30) ++ ldi $30,64($30) ++ ret $31,($26),1 ++ .end sw_efi_wrap_4 ++ ++ .ent sw_efi_wrap_5 ++sw_efi_wrap_5: ++ ldi $30,-64($30) ++ stl $26,0($30) ++ stl $15,8($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,16($15) ++ stl $17,24($15) ++ stl $18,32($15) ++ stl $19,40($15) ++ stl $20,48($15) ++ stl $21,56($15) ++ ldl $27,16($15) ++ ldl $16,24($15) ++ ldl $17,32($15) ++ ldl $18,40($15) ++ ldl $19,48($15) ++ ldl $20,56($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!39 ++ #ldi $29,0($29) !gpdisp!39 ++ mov $15,$30 ++ ldl $26,0($30) ++ ldl $15,8($30) ++ ldi $30,64($30) ++ ret $31,($26),1 ++ .end sw_efi_wrap_5 ++ ++ ++ .ent sw_efi_wrap_6 ++sw_efi_wrap_6: ++ ldi $30,-64($30) ++ stl $26,0($30) ++ stl $15,8($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,16($15) ++ stl $17,24($15) ++ stl $18,32($15) ++ stl $19,40($15) ++ stl $20,48($15) ++ stl $21,56($15) ++ ldl $27,16($15) ++ ldl $16,24($15) ++ ldl $17,32($15) ++ ldl $18,40($15) ++ ldl $19,48($15) ++ ldl $20,56($15) ++ ldl $21,64($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!41 ++ #ldi $29,0($29) !gpdisp!41 ++ mov $15,$30 ++ ldl $26,0($30) ++ ldl $15,8($30) ++ ldi $30,64($30) ++ ret $31,($26),1 ++ .end sw_efi_wrap_6 ++ ++ .ent sw_efi_wrap_7 ++sw_efi_wrap_7: ++ ldi $30,-80($30) ++ stl $26,16($30) ++ stl $15,24($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,32($15) ++ stl $17,40($15) ++ stl $18,48($15) ++ stl $19,56($15) ++ stl $20,64($15) ++ stl $21,72($15) ++ ldl $1,88($15) ++ stl $1,0($30) ++ ldl $27,32($15) ++ ldl $16,40($15) ++ ldl $17,48($15) ++ ldl $18,56($15) ++ ldl $19,64($15) ++ ldl $20,72($15) ++ ldl $21,80($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!43 ++ #ldi $29,0($29) !gpdisp!43 ++ mov $15,$30 ++ ldl $26,16($30) ++ ldl $15,24($30) ++ ldi $30,80($30) ++ ret $31,($26),1 ++ .end sw_efi_wrap_7 ++ ++ ++ .ent sw_efi_wrap_10 ++sw_efi_wrap_10: ++ ldi $30,-96($30) ++ stl $26,32($30) ++ stl $15,40($30) ++ mov $30,$15 ++ .prologue 1 ++ stl $16,48($15) ++ stl $17,56($15) ++ stl $18,64($15) ++ stl $19,72($15) ++ stl $20,80($15) ++ stl $21,88($15) ++ ldl $1,104($15) ++ stl $1,0($30) ++ ldl $1,112($15) ++ stl $1,8($30) ++ ldl $1,120($15) ++ stl $1,16($30) ++ ldl $1,128($15) ++ stl $1,24($30) ++ ldl $27,48($15) ++ ldl $16,56($15) ++ ldl $17,64($15) ++ ldl $18,72($15) ++ ldl $19,80($15) ++ ldl $20,88($15) ++ ldl $21,96($15) ++ call $26,($27),0 ++ #ldih $29,0($26) !gpdisp!45 ++ #ldi $29,0($29) !gpdisp!45 ++ mov $15,$30 ++ ldl $26,32($30) ++ ldl $15,40($30) ++ ldi $30,96($30) ++ ret $31,($26),1 ++ ++ .end sw_efi_wrap_10 +diff --git a/grub-core/kern/sw64/efi/init.c b/grub-core/kern/sw64/efi/init.c +new file mode 100644 +index 0000000..d647106 +--- /dev/null ++++ b/grub-core/kern/sw64/efi/init.c +@@ -0,0 +1,75 @@ ++/* init.c - initialize a riscv-based EFI system */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++grub_uint64_t cycle_freq; ++ ++static grub_uint64_t ++rpcc(void) ++{ ++ grub_uint64_t result; ++ ++ asm volatile ("rtc %0" : "=r"(result)); ++ ++ return result; ++} ++ ++static grub_uint64_t ++grub_efi_get_time_ms(void) ++{ ++ cycle_freq = cpuid(GET_CPU_FREQ, 0) * 1000UL * 1000UL; ++ ++ return rpcc() * 1000 / cycle_freq; ++} ++ ++static void ++grub_print_info (void) ++{ ++ grub_printf ("GNU %s %s\n", PACKAGE_NAME, PACKAGE_VERSION); ++ grub_printf ("CPU freq: %ld Mhz\n", cpuid(GET_CPU_FREQ, 0)); ++ grub_printf ("Build Time: %s %s\n", __DATE__, __TIME__); ++} ++ ++void ++grub_machine_init (void) ++{ ++ grub_efi_init (); ++ grub_print_info (); ++ grub_install_get_time_ms (grub_efi_get_time_ms); ++} ++ ++void ++grub_machine_fini (int flags) ++{ ++ if (!(flags & GRUB_LOADER_FLAG_NORETURN)) ++ return; ++ ++ grub_efi_fini (); ++ ++ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY)) ++ grub_efi_memory_fini (); ++} +diff --git a/grub-core/lib/sw64/divide.S b/grub-core/lib/sw64/divide.S +new file mode 100644 +index 0000000..980aba6 +--- /dev/null ++++ b/grub-core/lib/sw64/divide.S +@@ -0,0 +1,677 @@ ++/* ++ * divide.S ++ * ++ * (C) 1995 Linus Torvalds ++ * ++ * Alpha division.. ++ */ ++ ++/* ++ * The alpha chip doesn't provide hardware division, so we have to do it ++ * by hand. The compiler expects the functions ++ * ++ * __divqu: 64-bit unsigned long divide ++ * __remqu: 64-bit unsigned long remainder ++ * __divqs/__remqs: signed 64-bit ++ * __divlu/__remlu: unsigned 32-bit ++ * __divls/__remls: signed 32-bit ++ * ++ * These are not normal C functions: instead of the normal ++ * calling sequence, these expect their arguments in registers ++ * $24 and $25, and return the result in $27. Register $28 may ++ * be clobbered (assemembly temporary), anything else must be saved. ++ * ++ * In short: painful. ++ * ++ * This is a rather simple bit-at-a-time algorithm: it's very good ++ * at dividing random 64-bit numembers, but the more usual case where ++ * the divisor is small is handled better by the DEC algorithm ++ * using lookup tables. This uses much less memory, though, and is ++ * nicer on the cache.. Besides, I don't know the copyright status ++ * of the DEC code. ++ */ ++ ++/* ++ * My temporaries: ++ * $0 - current bit ++ * $1 - shifted divisor ++ * $2 - modulus/quotient ++ * ++ * $23 - return address ++ * $24 - dividend ++ * $25 - divisor ++ * ++ * $27 - quotient/modulus ++ * $28 - compare status ++ */ ++ ++#define halt .long 0 ++ ++/* ++ * Select function type and registers ++ */ ++#define mask $0 ++#define divisor $1 ++#define compare $28 ++#define tmp1 $3 ++#define tmp2 $4 ++ ++#define DIV ++#define INTSIZE ++ ++#undef DIV_ONLY ++#undef MOD_ONLY ++#undef func ++#undef modulus ++#undef quotient ++#undef GETSIGN ++#undef STACK ++#undef ufunction ++#undef sfunction ++#undef LONGIFY ++#undef SLONGIFY ++ ++#ifdef DIV ++#define DIV_ONLY(x,y...) x,##y ++#define MOD_ONLY(x,y...) ++#define func(x) __div##x ++#define modulus $2 ++#define quotient $27 ++#define GETSIGN(x) xor $24,$25,x ++#define STACK 48 ++#else ++#define DIV_ONLY(x,y...) ++#define MOD_ONLY(x,y...) x,##y ++#define func(x) __rem##x ++#define modulus $27 ++#define quotient $2 ++#define GETSIGN(x) bis $24,$24,x ++#define STACK 32 ++#endif ++ ++/* ++ * For 32-bit operations, we need to extend to 64-bit ++ */ ++#ifdef INTSIZE ++#define ufunction func(wu) ++#define sfunction func(w) ++#define LONGIFY(x) zapnot x,15,x ++/* define SLONGIFY(x) addw x,0,x */ ++#define SLONGIFY(x) ++#else ++#define ufunction func(lu) ++#define sfunction func(l) ++#define LONGIFY(x) ++#define SLONGIFY(x) ++#endif ++ ++.set noat ++.align 3 ++.globl ufunction ++.ent ufunction ++ufunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ ++7: stl $1, 0($30) ++ bis $25,$25,divisor ++ stl $2, 8($30) ++ bis $24,$24,modulus ++ stl $0,16($30) ++ bis $31,$31,quotient ++ LONGIFY(divisor) ++ stl tmp1,24($30) ++ LONGIFY(modulus) ++ bis $31,1,mask ++ DIV_ONLY(stl tmp2,32($30)) ++ beq divisor, 9f /* div by zero */ ++ ++#ifdef INTSIZE ++ /* ++ * shift divisor left, using 3-bit shifts for ++ * 32-bit divides as we can't overflow. Three-bit ++ * shifts will result in looping three times less ++ * here, but can result in two loops more later. ++ * Thus using a large shift isn't worth it (and ++ * s8add pairs better than a sll..) ++ */ ++1: cmpult divisor,modulus,compare ++ s8addl divisor,$31,divisor ++ s8addl mask,$31,mask ++ bne compare,1b ++#else ++1: cmpult divisor,modulus,compare ++ blt divisor, 2f ++ addl divisor,divisor,divisor ++ addl mask,mask,mask ++ bne compare,1b ++ nop ++#endif ++ ++ /* ok, start to go right again.. */ ++2: DIV_ONLY(addl quotient,mask,tmp2) ++ srl mask,1,mask ++ cmpule divisor,modulus,compare ++ subl modulus,divisor,tmp1 ++ DIV_ONLY(selne compare,tmp2,quotient,quotient) ++ srl divisor,1,divisor ++ selne compare,tmp1,modulus,modulus ++ bne mask,2b ++ ++9: ldl $1, 0($30) ++ ldl $2, 8($30) ++ ldl $0,16($30) ++ ldl tmp1,24($30) ++ DIV_ONLY(ldl tmp2,32($30)) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end ufunction ++ ++/* ++ * Uhh.. Ugly signed division. I'd rather not have it at all, but ++ * it's needed in some circumstances. There are different ways to ++ * handle this, really. This does: ++ * -a / b = a / -b = -(a / b) ++ * -a % b = -(a % b) ++ * a % -b = a % b ++ * which is probably not the best solution, but at least should ++ * have the property that (x/y)*y + (x%y) = x. ++ */ ++.align 3 ++.globl sfunction ++.ent sfunction ++sfunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ bis $24,$25,$28 ++ SLONGIFY($28) ++ bge $28,7b ++ stl $24,0($30) ++ subl $31,$24,$28 ++ stl $25,8($30) ++ sellt $24,$28,$24,$24 /* abs($24) */ ++ stl $23,16($30) ++ subl $31,$25,$28 ++ stl tmp1,24($30) ++ sellt $25,$28,$25,$25 /* abs($25) */ ++ nop ++ bsr $23,ufunction ++ ldl $24,0($30) ++ ldl $25,8($30) ++ GETSIGN($28) ++ subl $31,$27,tmp1 ++ SLONGIFY($28) ++ ldl $23,16($30) ++ sellt $28,tmp1,$27,$27 ++ ldl tmp1,24($30) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end sfunction ++ ++/*rem 32 */ ++ ++#undef DIV_ONLY ++#undef MOD_ONLY ++#undef func ++#undef modulus ++#undef quotient ++#undef GETSIGN ++#undef STACK ++#undef ufunction ++#undef sfunction ++#undef LONGIFY ++#undef SLONGIFY ++ ++ ++#undef DIV ++ ++ ++#ifdef DIV ++#define DIV_ONLY(x,y...) x,##y ++#define MOD_ONLY(x,y...) ++#define func(x) __div##x ++#define modulus $2 ++#define quotient $27 ++#define GETSIGN(x) xor $24,$25,x ++#define STACK 48 ++#else ++#define DIV_ONLY(x,y...) ++#define MOD_ONLY(x,y...) x,##y ++#define func(x) __rem##x ++#define modulus $27 ++#define quotient $2 ++#define GETSIGN(x) bis $24,$24,x ++#define STACK 32 ++#endif ++ ++/* ++ * For 32-bit operations, we need to extend to 64-bit ++ */ ++#ifdef INTSIZE ++#define ufunction func(wu) ++#define sfunction func(w) ++#define LONGIFY(x) zapnot x,15,x ++#define SLONGIFY(x) ++#else ++#define ufunction func(lu) ++#define sfunction func(l) ++#define LONGIFY(x) ++#define SLONGIFY(x) ++#endif ++ ++.align 3 ++.globl ufunction ++.ent ufunction ++ufunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ ++7: stl $1, 0($30) ++ bis $25,$25,divisor ++ stl $2, 8($30) ++ bis $24,$24,modulus ++ stl $0,16($30) ++ bis $31,$31,quotient ++ LONGIFY(divisor) ++ stl tmp1,24($30) ++ LONGIFY(modulus) ++ bis $31,1,mask ++ DIV_ONLY(stl tmp2,32($30)) ++ beq divisor, 9f /* div by zero */ ++ ++#ifdef INTSIZE ++ /* ++ * shift divisor left, using 3-bit shifts for ++ * 32-bit divides as we can't overflow. Three-bit ++ * shifts will result in looping three times less ++ * here, but can result in two loops more later. ++ * Thus using a large shift isn't worth it (and ++ * s8add pairs better than a sll..) ++ */ ++1: cmpult divisor,modulus,compare ++ s8addl divisor,$31,divisor ++ s8addl mask,$31,mask ++ bne compare,1b ++#else ++1: cmpult divisor,modulus,compare ++ blt divisor, 2f ++ addl divisor,divisor,divisor ++ addl mask,mask,mask ++ bne compare,1b ++ nop ++#endif ++ ++ /* ok, start to go right again.. */ ++2: DIV_ONLY(addl quotient,mask,tmp2) ++ srl mask,1,mask ++ cmpule divisor,modulus,compare ++ subl modulus,divisor,tmp1 ++ DIV_ONLY(selne compare,tmp2,quotient,quotient) ++ srl divisor,1,divisor ++ selne compare,tmp1,modulus,modulus ++ bne mask,2b ++ ++9: ldl $1, 0($30) ++ ldl $2, 8($30) ++ ldl $0,16($30) ++ ldl tmp1,24($30) ++ DIV_ONLY(ldl tmp2,32($30)) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end ufunction ++ ++/* ++ * Uhh.. Ugly signed division. I'd rather not have it at all, but ++ * it's needed in some circumstances. There are different ways to ++ * handle this, really. This does: ++ * -a / b = a / -b = -(a / b) ++ * -a % b = -(a % b) ++ * a % -b = a % b ++ * which is probably not the best solution, but at least should ++ * have the property that (x/y)*y + (x%y) = x. ++ */ ++.align 3 ++.globl sfunction ++.ent sfunction ++sfunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ bis $24,$25,$28 ++ SLONGIFY($28) ++ bge $28,7b ++ stl $24,0($30) ++ subl $31,$24,$28 ++ stl $25,8($30) ++ sellt $24,$28,$24,$24 /* abs($24) */ ++ stl $23,16($30) ++ subl $31,$25,$28 ++ stl tmp1,24($30) ++ sellt $25,$28,$25,$25 /* abs($25) */ ++ nop ++ bsr $23,ufunction ++ ldl $24,0($30) ++ ldl $25,8($30) ++ GETSIGN($28) ++ subl $31,$27,tmp1 ++ SLONGIFY($28) ++ ldl $23,16($30) ++ sellt $28,tmp1,$27,$27 ++ ldl tmp1,24($30) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end sfunction ++ ++/*div 64*/ ++ ++#undef DIV_ONLY ++#undef MOD_ONLY ++#undef func ++#undef modulus ++#undef quotient ++#undef GETSIGN ++#undef STACK ++#undef ufunction ++#undef sfunction ++#undef LONGIFY ++#undef SLONGIFY ++ ++ ++#define DIV ++#undef INTSIZE ++ ++#ifdef DIV ++#define DIV_ONLY(x,y...) x,##y ++#define MOD_ONLY(x,y...) ++#define func(x) __div##x ++#define modulus $2 ++#define quotient $27 ++#define GETSIGN(x) xor $24,$25,x ++#define STACK 48 ++#else ++#define DIV_ONLY(x,y...) ++#define MOD_ONLY(x,y...) x,##y ++#define func(x) __rem##x ++#define modulus $27 ++#define quotient $2 ++#define GETSIGN(x) bis $24,$24,x ++#define STACK 32 ++#endif ++ ++/* ++ * For 32-bit operations, we need to extend to 64-bit ++ */ ++#ifdef INTSIZE ++#define ufunction func(wu) ++#define sfunction func(w) ++#define LONGIFY(x) zapnot x,15,x ++#define SLONGIFY(x) ++#else ++#define ufunction func(lu) ++#define sfunction func(l) ++#define LONGIFY(x) ++#define SLONGIFY(x) ++#endif ++ ++.align 3 ++.globl ufunction ++.ent ufunction ++ufunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ ++7: stl $1, 0($30) ++ bis $25,$25,divisor ++ stl $2, 8($30) ++ bis $24,$24,modulus ++ stl $0,16($30) ++ bis $31,$31,quotient ++ LONGIFY(divisor) ++ stl tmp1,24($30) ++ LONGIFY(modulus) ++ bis $31,1,mask ++ DIV_ONLY(stl tmp2,32($30)) ++ beq divisor, 9f /* div by zero */ ++ ++#ifdef INTSIZE ++ /* ++ * shift divisor left, using 3-bit shifts for ++ * 32-bit divides as we can't overflow. Three-bit ++ * shifts will result in looping three times less ++ * here, but can result in two loops more later. ++ * Thus using a large shift isn't worth it (and ++ * s8add pairs better than a sll..) ++ */ ++1: cmpult divisor,modulus,compare ++ s8addl divisor,$31,divisor ++ s8addl mask,$31,mask ++ bne compare,1b ++#else ++1: cmpult divisor,modulus,compare ++ blt divisor, 2f ++ addl divisor,divisor,divisor ++ addl mask,mask,mask ++ bne compare,1b ++ nop ++#endif ++ ++ /* ok, start to go right again.. */ ++2: DIV_ONLY(addl quotient,mask,tmp2) ++ srl mask,1,mask ++ cmpule divisor,modulus,compare ++ subl modulus,divisor,tmp1 ++ DIV_ONLY(selne compare,tmp2,quotient,quotient) ++ srl divisor,1,divisor ++ selne compare,tmp1,modulus,modulus ++ bne mask,2b ++ ++9: ldl $1, 0($30) ++ ldl $2, 8($30) ++ ldl $0,16($30) ++ ldl tmp1,24($30) ++ DIV_ONLY(ldl tmp2,32($30)) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end ufunction ++ ++/* ++ * Uhh.. Ugly signed division. I'd rather not have it at all, but ++ * it's needed in some circumstances. There are different ways to ++ * handle this, really. This does: ++ * -a / b = a / -b = -(a / b) ++ * -a % b = -(a % b) ++ * a % -b = a % b ++ * which is probably not the best solution, but at least should ++ * have the property that (x/y)*y + (x%y) = x. ++ */ ++.align 3 ++.globl sfunction ++.ent sfunction ++sfunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ bis $24,$25,$28 ++ SLONGIFY($28) ++ bge $28,7b ++ stl $24,0($30) ++ subl $31,$24,$28 ++ stl $25,8($30) ++ sellt $24,$28,$24,$24 /* abs($24) */ ++ stl $23,16($30) ++ subl $31,$25,$28 ++ stl tmp1,24($30) ++ sellt $25,$28,$25,$25 /* abs($25) */ ++ nop ++ bsr $23,ufunction ++ ldl $24,0($30) ++ ldl $25,8($30) ++ GETSIGN($28) ++ subl $31,$27,tmp1 ++ SLONGIFY($28) ++ ldl $23,16($30) ++ sellt $28,tmp1,$27,$27 ++ ldl tmp1,24($30) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end sfunction ++ ++ ++/*rem 64*/ ++ ++#undef DIV_ONLY ++#undef MOD_ONLY ++#undef func ++#undef modulus ++#undef quotient ++#undef GETSIGN ++#undef STACK ++#undef ufunction ++#undef sfunction ++#undef LONGIFY ++#undef SLONGIFY ++ ++ ++#undef DIV ++ ++#ifdef DIV ++#define DIV_ONLY(x,y...) x,##y ++#define MOD_ONLY(x,y...) ++#define func(x) __div##x ++#define modulus $2 ++#define quotient $27 ++#define GETSIGN(x) xor $24,$25,x ++#define STACK 48 ++#else ++#define DIV_ONLY(x,y...) ++#define MOD_ONLY(x,y...) x,##y ++#define func(x) __rem##x ++#define modulus $27 ++#define quotient $2 ++#define GETSIGN(x) bis $24,$24,x ++#define STACK 32 ++#endif ++ ++/* ++ * For 32-bit operations, we need to extend to 64-bit ++ */ ++#ifdef INTSIZE ++#define ufunction func(wu) ++#define sfunction func(w) ++#define LONGIFY(x) zapnot x,15,x ++#define SLONGIFY(x) ++#else ++#define ufunction func(lu) ++#define sfunction func(l) ++#define LONGIFY(x) ++#define SLONGIFY(x) ++#endif ++ ++ ++.align 3 ++.globl ufunction ++.ent ufunction ++ufunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ ++7: stl $1, 0($30) ++ bis $25,$25,divisor ++ stl $2, 8($30) ++ bis $24,$24,modulus ++ stl $0,16($30) ++ bis $31,$31,quotient ++ LONGIFY(divisor) ++ stl tmp1,24($30) ++ LONGIFY(modulus) ++ bis $31,1,mask ++ DIV_ONLY(stl tmp2,32($30)) ++ beq divisor, 9f /* div by zero */ ++ ++#ifdef INTSIZE ++ /* ++ * shift divisor left, using 3-bit shifts for ++ * 32-bit divides as we can't overflow. Three-bit ++ * shifts will result in looping three times less ++ * here, but can result in two loops more later. ++ * Thus using a large shift isn't worth it (and ++ * s8add pairs better than a sll..) ++ */ ++1: cmpult divisor,modulus,compare ++ s8addl divisor,$31,divisor ++ s8addl mask,$31,mask ++ bne compare,1b ++#else ++1: cmpult divisor,modulus,compare ++ blt divisor, 2f ++ addl divisor,divisor,divisor ++ addl mask,mask,mask ++ bne compare,1b ++ nop ++#endif ++ ++ /* ok, start to go right again.. */ ++2: DIV_ONLY(addl quotient,mask,tmp2) ++ srl mask,1,mask ++ cmpule divisor,modulus,compare ++ subl modulus,divisor,tmp1 ++ DIV_ONLY(selne compare,tmp2,quotient,quotient) ++ srl divisor,1,divisor ++ selne compare,tmp1,modulus,modulus ++ bne mask,2b ++ ++9: ldl $1, 0($30) ++ ldl $2, 8($30) ++ ldl $0,16($30) ++ ldl tmp1,24($30) ++ DIV_ONLY(ldl tmp2,32($30)) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end ufunction ++ ++/* ++ * Uhh.. Ugly signed division. I'd rather not have it at all, but ++ * it's needed in some circumstances. There are different ways to ++ * handle this, really. This does: ++ * -a / b = a / -b = -(a / b) ++ * -a % b = -(a % b) ++ * a % -b = a % b ++ * which is probably not the best solution, but at least should ++ * have the property that (x/y)*y + (x%y) = x. ++ */ ++.align 3 ++.globl sfunction ++.ent sfunction ++sfunction: ++ subl $30,STACK,$30 ++ .frame $30,STACK,$23 ++ .prologue 0 ++ bis $24,$25,$28 ++ SLONGIFY($28) ++ bge $28,7b ++ stl $24,0($30) ++ subl $31,$24,$28 ++ stl $25,8($30) ++ sellt $24,$28,$24,$24 /* abs($24) */ ++ stl $23,16($30) ++ subl $31,$25,$28 ++ stl tmp1,24($30) ++ sellt $25,$28,$25,$25 /* abs($25) */ ++ nop ++ bsr $23,ufunction ++ ldl $24,0($30) ++ ldl $25,8($30) ++ GETSIGN($28) ++ subl $31,$27,tmp1 ++ SLONGIFY($28) ++ ldl $23,16($30) ++ sellt $28,tmp1,$27,$27 ++ ldl tmp1,24($30) ++ addl $30,STACK,$30 ++ ret $31,($23),1 ++ .end sfunction +diff --git a/grub-core/lib/sw64/setjmp.S b/grub-core/lib/sw64/setjmp.S +new file mode 100644 +index 0000000..7e84d6a +--- /dev/null ++++ b/grub-core/lib/sw64/setjmp.S +@@ -0,0 +1,75 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++ ++ .file "setjmp.S" ++ ++GRUB_MOD_LICENSE "GPLv2+" ++ ++FUNCTION(grub_setjmp) ++ ldgp gp, 0(pv) ++#define FRAME 0 ++ .frame sp, FRAME, ra, 0 ++ ++ stl s0, JB_S0*8(a0) ++ stl s1, JB_S1*8(a0) ++ stl s2, JB_S2*8(a0) ++ stl s3, JB_S3*8(a0) ++ stl s4, JB_S4*8(a0) ++ stl s5, JB_S5*8(a0) ++ stl ra, JB_PC*8(a0) ++ addl sp, FRAME, t1 ++ stl t1, JB_SP*8(a0) ++ stl fp, JB_FP*8(a0) ++ fstd $f2, JB_F2*8(a0) ++ fstd $f3, JB_F3*8(a0) ++ fstd $f4, JB_F4*8(a0) ++ fstd $f5, JB_F5*8(a0) ++ fstd $f6, JB_F6*8(a0) ++ fstd $f7, JB_F7*8(a0) ++ fstd $f8, JB_F8*8(a0) ++ fstd $f9, JB_F9*8(a0) ++ ldi a0, 0($31) ++ ret ++ ++FUNCTION(grub_longjmp) ++ mov a1, v0 ++ ldl s0, JB_S0*8(a0) ++ ldl s1, JB_S1*8(a0) ++ ldl s2, JB_S2*8(a0) ++ ldl s3, JB_S3*8(a0) ++ ldl s4, JB_S4*8(a0) ++ ldl s5, JB_S5*8(a0) ++ ldl ra, JB_PC*8(a0) ++ ldl fp, JB_FP*8(a0) ++ ldl t0, JB_SP*8(a0) ++ fldd $f2, JB_F2*8(a0) ++ fldd $f3, JB_F3*8(a0) ++ fldd $f4, JB_F4*8(a0) ++ fldd $f5, JB_F5*8(a0) ++ fldd $f6, JB_F6*8(a0) ++ fldd $f7, JB_F7*8(a0) ++ fldd $f8, JB_F8*8(a0) ++ fldd $f9, JB_F9*8(a0) ++ seleq v0, 1, v0, v0 ++ mov t0, sp ++ ret +diff --git a/include/grub/sw64/divide.h b/include/grub/sw64/divide.h +new file mode 100644 +index 0000000..a6c8eae +--- /dev/null ++++ b/include/grub/sw64/divide.h +@@ -0,0 +1,11 @@ ++#ifndef __DIVIDE_H__ ++#define __DIVIDE_H__ ++void EXPORT_FUNC(__divw) (void); ++void EXPORT_FUNC(__remw) (void); ++void EXPORT_FUNC(__divl) (void); ++void EXPORT_FUNC(__reml) (void); ++void EXPORT_FUNC(__divwu) (void); ++void EXPORT_FUNC(__remwu) (void); ++void EXPORT_FUNC(__divlu) (void); ++void EXPORT_FUNC(__remlu) (void); ++#endif +diff --git a/include/grub/sw64/efi/memory.h b/include/grub/sw64/efi/memory.h +new file mode 100644 +index 0000000..b869f46 +--- /dev/null ++++ b/include/grub/sw64/efi/memory.h +@@ -0,0 +1,7 @@ ++#ifndef GRUB_MEMORY_CPU_HEADER ++#include ++ ++#define GRUB_EFI_MAX_USABLE_ADDRESS 0xFFF000003FFFFFFFULL ++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS ++ ++#endif /* ! GRUB_MEMORY_CPU_HEADER */ +diff --git a/include/grub/sw64/efi/time.h b/include/grub/sw64/efi/time.h +new file mode 100644 +index 0000000..897ce9c +--- /dev/null ++++ b/include/grub/sw64/efi/time.h +@@ -0,0 +1,23 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2008 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_MACHINE_TIME_HEADER ++#define GRUB_MACHINE_TIME_HEADER 1 ++ ++#include ++ ++#endif /* ! GRUB_MACHINE_TIME_HEADER */ +diff --git a/include/grub/sw64/io.h b/include/grub/sw64/io.h +new file mode 100644 +index 0000000..dee76bd +--- /dev/null ++++ b/include/grub/sw64/io.h +@@ -0,0 +1,62 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2009 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_IO_H ++#define GRUB_IO_H 1 ++ ++#include ++ ++typedef grub_addr_t grub_port_t; ++ ++static __inline unsigned char ++grub_inb (grub_port_t port) ++{ ++ return *(volatile grub_uint8_t *) port; ++} ++ ++static __inline unsigned short int ++grub_inw (grub_port_t port) ++{ ++ return *(volatile grub_uint16_t *) port; ++} ++ ++static __inline unsigned int ++grub_inl (grub_port_t port) ++{ ++ return *(volatile grub_uint32_t *) port; ++} ++ ++static __inline void ++grub_outb (unsigned char value, grub_port_t port) ++{ ++ *(volatile grub_uint8_t *) port = value; ++} ++ ++static __inline void ++grub_outw (unsigned short int value, grub_port_t port) ++{ ++ *(volatile grub_uint16_t *) port = value; ++} ++ ++static __inline void ++grub_outl (unsigned int value, grub_port_t port) ++{ ++ *(volatile grub_uint32_t *) port = value; ++} ++ ++#endif /* _SYS_IO_H */ +diff --git a/include/grub/sw64/jmpbuf-offsets.h b/include/grub/sw64/jmpbuf-offsets.h +new file mode 100644 +index 0000000..86e8da2 +--- /dev/null ++++ b/include/grub/sw64/jmpbuf-offsets.h +@@ -0,0 +1,35 @@ ++/* Private macros for accessing __jmp_buf contents. Alpha version. ++ Copyright (C) 2006-2016 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library 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 ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#define JB_S0 0 ++#define JB_S1 1 ++#define JB_S2 2 ++#define JB_S3 3 ++#define JB_S4 4 ++#define JB_S5 5 ++#define JB_PC 6 ++#define JB_FP 7 ++#define JB_SP 8 ++#define JB_F2 9 ++#define JB_F3 10 ++#define JB_F4 11 ++#define JB_F5 12 ++#define JB_F6 13 ++#define JB_F7 14 ++#define JB_F8 15 ++#define JB_F9 16 +diff --git a/include/grub/sw64/kernel.h b/include/grub/sw64/kernel.h +new file mode 100644 +index 0000000..c5496a0 +--- /dev/null ++++ b/include/grub/sw64/kernel.h +@@ -0,0 +1,25 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2010 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_CPU_KERNEL_HEADER ++#define GRUB_CPU_KERNEL_HEADER 1 ++ ++#define GRUB_MOD_ALIGN 0x1 ++#define GRUB_MOD_GAP 0x0 ++ ++#endif /* ! GRUB_CPU_KERNEL_HEADER */ +diff --git a/include/grub/sw64/pal.h b/include/grub/sw64/pal.h +new file mode 100644 +index 0000000..274f07d +--- /dev/null ++++ b/include/grub/sw64/pal.h +@@ -0,0 +1,49 @@ ++#ifndef __SW64_PAL_H ++#define __SW64_PAL_H ++ ++#define HMC_cpuid 0x03 ++#define HMC_ret 0x1A ++#define HMC_swpipl 0x35 ++ ++#define GET_CPU_FREQ 4 ++ ++#define __CALL_HMC_W1(NAME, TYPE0) \ ++static inline void NAME(TYPE0 arg0) \ ++{ \ ++ register TYPE0 __r16 __asm__("$16") = arg0; \ ++ __asm__ __volatile__ ("sys_call %1 # "#NAME \ ++ : "=r"(__r16) \ ++ : "i"(HMC_ ## NAME), "0"(__r16) \ ++ : "$1", "$22", "$23", "$24", "$25"); \ ++} ++ ++#define __CALL_HMC_RW1(NAME, RTYPE, TYPE0) \ ++static inline RTYPE NAME(TYPE0 arg0) \ ++{ \ ++ register RTYPE __r0 __asm__("$0"); \ ++ register TYPE0 __r16 __asm__("$16") = arg0; \ ++ __asm__ __volatile__ ("sys_call %2 # "#NAME \ ++ : "=r"(__r16), "=r"(__r0) \ ++ : "i"(HMC_ ## NAME), "0"(__r16) \ ++ : "$1", "$22", "$23", "$24", "$25"); \ ++ return __r0; \ ++} ++ ++#define __CALL_HMC_RW2(NAME, RTYPE, TYPE0, TYPE1) \ ++static inline RTYPE NAME(TYPE0 arg0, TYPE1 arg1) \ ++{ \ ++ register RTYPE __r0 __asm__("$0"); \ ++ register TYPE0 __r16 __asm__("$16") = arg0; \ ++ register TYPE1 __r17 __asm__("$17") = arg1; \ ++ __asm__ __volatile__ ("sys_call %3 # "#NAME \ ++ : "=r"(__r16), "=r"(__r17), "=r"(__r0) \ ++ : "i"(HMC_ ## NAME), "0"(__r16), "1"(__r17) \ ++ : "$1", "$22", "$23", "$24", "$25"); \ ++ return __r0; \ ++} ++ ++__CALL_HMC_W1(ret, unsigned long); ++__CALL_HMC_RW1(swpipl, unsigned long, unsigned long); ++__CALL_HMC_RW2(cpuid, unsigned long, unsigned long, unsigned long); ++ ++#endif /* __SW_64_HMC_H */ +diff --git a/include/grub/sw64/regdef.h b/include/grub/sw64/regdef.h +new file mode 100644 +index 0000000..b30eb77 +--- /dev/null ++++ b/include/grub/sw64/regdef.h +@@ -0,0 +1,44 @@ ++#ifndef __sw_regdef_h__ ++#define __sw_regdef_h__ ++ ++#define v0 $0 /* function return value */ ++ ++#define t0 $1 /* temporary registers (caller-saved) */ ++#define t1 $2 ++#define t2 $3 ++#define t3 $4 ++#define t4 $5 ++#define t5 $6 ++#define t6 $7 ++#define t7 $8 ++ ++#define s0 $9 /* saved-registers (callee-saved registers) */ ++#define s1 $10 ++#define s2 $11 ++#define s3 $12 ++#define s4 $13 ++#define s5 $14 ++#define s6 $15 ++#define fp s6 /* frame-pointer (s6 in frame-less procedures) */ ++ ++#define a0 $16 /* argument registers (caller-saved) */ ++#define a1 $17 ++#define a2 $18 ++#define a3 $19 ++#define a4 $20 ++#define a5 $21 ++ ++#define t8 $22 /* more temps (caller-saved) */ ++#define t9 $23 ++#define t10 $24 ++#define t11 $25 ++#define ra $26 /* return address register */ ++#define t12 $27 ++ ++#define pv t12 /* procedure-variable register */ ++#define AT $at /* assembler temporary */ ++#define gp $29 /* global pointer */ ++#define sp $30 /* stack pointer */ ++#define zero $31 /* reads as zero, writes are noops */ ++ ++#endif /* __sw_64_regdef_h__ */ +diff --git a/include/grub/sw64/setjmp.h b/include/grub/sw64/setjmp.h +new file mode 100644 +index 0000000..a71c9c5 +--- /dev/null ++++ b/include/grub/sw64/setjmp.h +@@ -0,0 +1,28 @@ ++/* Define the machine-dependent type `jmp_buf'. Linux/IA-64 version. ++ Copyright (C) 1999, 2000, 2008 Free Software Foundation, Inc. ++ Contributed by David Mosberger-Tang . ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Library General Public License as ++ published by the Free Software Foundation; either version 2 of the ++ License, or (at your option) any later version. ++ ++ The GNU C Library 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 ++ Library General Public License for more details. ++ ++ You should have received a copy of the GNU Library General Public ++ License along with the GNU C Library; see the file COPYING.LIB. If not, ++ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. */ ++ ++/* User code must not depend on the internal representation of jmp_buf. */ ++ ++#define _JBLEN 70 ++ ++/* the __jmp_buf element type should be __float80 per ABI... */ ++typedef long grub_jmp_buf[_JBLEN] __attribute__ ((aligned (16))); /* guarantees 128-bit alignment! */ ++ ++int grub_setjmp (grub_jmp_buf env); ++void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn)); +diff --git a/include/grub/sw64/time.h b/include/grub/sw64/time.h +new file mode 100644 +index 0000000..03ee79f +--- /dev/null ++++ b/include/grub/sw64/time.h +@@ -0,0 +1,28 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2007, 2008 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 KERNEL_CPU_TIME_HEADER ++#define KERNEL_CPU_TIME_HEADER 1 ++ ++static __inline void ++grub_cpu_idle (void) ++{ ++ /* FIXME: not implemented */ ++} ++ ++#endif /* ! KERNEL_CPU_TIME_HEADER */ +diff --git a/include/grub/sw64/types.h b/include/grub/sw64/types.h +new file mode 100644 +index 0000000..91a546d +--- /dev/null ++++ b/include/grub/sw64/types.h +@@ -0,0 +1,32 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2008 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_TYPES_CPU_HEADER ++#define GRUB_TYPES_CPU_HEADER 1 ++ ++/* The size of void *. */ ++#define GRUB_TARGET_SIZEOF_VOID_P 8 ++ ++/* The size of long. */ ++#define GRUB_TARGET_SIZEOF_LONG 8 ++ ++/* ia64 is little-endian (usually). */ ++#undef GRUB_TARGET_WORDS_BIGENDIAN ++ ++ ++#endif /* ! GRUB_TYPES_CPU_HEADER */ +-- +2.17.1 + diff --git a/sw64-Add-awareness-for-SW64-reloations.patch b/sw64-Add-awareness-for-SW64-reloations.patch new file mode 100644 index 0000000000000000000000000000000000000000..22e8527c15ecfd2925b25a833c4e7abfa0b8e29e --- /dev/null +++ b/sw64-Add-awareness-for-SW64-reloations.patch @@ -0,0 +1,543 @@ +From 15a55b77227a70e127d4326e5bf7507100d984cb Mon Sep 17 00:00:00 2001 +From: sunway_fw +Date: Tue, 25 Feb 2025 03:02:19 +0800 +Subject: [PATCH 3/5] sw64: Add awareness for SW64 reloations + +This patch adds awareness of SW64 relocations throughout the grub tools +as well as dynamic linkage and elf->PE relocation conversion support. + +Signed-off-by: sunway_fw +--- + grub-core/kern/sw64/dl.c | 214 ++++++++++++++++++++++++++++++++++++ + include/grub/dl.h | 12 ++ + include/grub/elf.h | 39 +++++++ + util/grub-mkimagexx.c | 145 +++++++++++++++++++++++- + util/grub-module-verifier.c | 18 +++ + 5 files changed, 427 insertions(+), 1 deletion(-) + create mode 100644 grub-core/kern/sw64/dl.c + +diff --git a/grub-core/kern/sw64/dl.c b/grub-core/kern/sw64/dl.c +new file mode 100644 +index 0000000..8e3cac2 +--- /dev/null ++++ b/grub-core/kern/sw64/dl.c +@@ -0,0 +1,214 @@ ++/* dl.c - arch-dependent part of loadable module support */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * Check if EHDR is a valid ELF header. ++ */ ++grub_err_t ++grub_arch_dl_check_header (void *ehdr) ++{ ++ Elf_Ehdr *e = ehdr; ++ ++ /* Check the magic numbers. */ ++ if (e->e_ident[EI_DATA] != ELFDATA2LSB || e->e_machine != EM_SW_64) ++ return grub_error (GRUB_ERR_BAD_OS, ++ N_("invalid arch-dependent ELF magic")); ++ ++ return GRUB_ERR_NONE; ++} ++ ++#pragma GCC diagnostic ignored "-Wcast-align" ++ ++/* Relocate symbols. */ ++grub_err_t ++grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, ++ Elf_Shdr *s, grub_dl_segment_t seg) ++{ ++ Elf_Rela *rel, *max; ++ grub_uint64_t *gpptr, *gotptr; ++ ++ gotptr = (grub_uint64_t *) mod->got; ++ gpptr = (grub_uint64_t *) ((grub_uint64_t) mod->got + 0x8000); ++ ++ for (rel = (Elf_Rela *) ((char *) ehdr + s->sh_offset), ++ max = (Elf_Rela *) ((char *) rel + s->sh_size); ++ rel < max; ++ rel = (Elf_Rela *) ((char *) rel + s->sh_entsize)) ++ { ++ grub_addr_t addr; ++ Elf_Sym *sym; ++ grub_uint64_t value; ++ ++ if (seg->size < (rel->r_offset & ~3)) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "reloc offset is out of the segment"); ++ ++ addr = (grub_addr_t) seg->addr + rel->r_offset; ++ sym = (Elf_Sym *) ((char *) mod->symtab ++ + mod->symsize * ELF_R_SYM (rel->r_info)); ++ ++ /* On the PPC the value does not have an explicit ++ addend, add it. */ ++ value = sym->st_value + rel->r_addend; ++ ++ switch (ELF_R_TYPE (rel->r_info)) ++ { ++ case R_SW64_NONE: ++ break; ++ case R_SW64_REFLONG: ++ *(grub_uint32_t *)addr = value; ++ break; ++ case R_SW64_REFQUAD: ++ { ++ *(grub_uint32_t *)addr = value; ++ *((grub_uint32_t *)addr + 1) = value >> 32; ++ break; ++ } ++ case R_SW64_GPREL32: ++ { ++ value -= (grub_uint64_t)gpptr; ++ if ((grub_int32_t)value != value) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "R_SW64_GPREL32 relocation out of range"); ++ *(grub_uint32_t *) addr = value; ++ break; ++ } ++ case R_SW64_LITERAL: ++ { ++ grub_uint64_t li_hi; ++ grub_uint64_t li_lo; ++ ++ li_hi = (grub_uint64_t) gotptr + (((grub_uint64_t)ELF_R_TYPE(rel->r_info)) >> 8 ); ++ li_lo = li_hi - ((grub_uint64_t) gpptr); ++ if ((grub_int16_t)li_lo != li_lo) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "R_SW64_LITERAL relocation out of range"); ++ ++ *(grub_uint16_t *) addr = (li_lo & 0xffff); ++ *(grub_uint64_t *) (li_hi) = value; ++ gotptr++; ++ break; ++ } ++ case R_SW64_LITERAL_GOT: ++ break; ++ case R_SW64_LITUSE: ++ break; ++ case R_SW64_GPDISP: ++ { ++ grub_uint64_t hi; ++ grub_uint64_t lo; ++ grub_uint64_t gpoffset = (grub_int64_t)gpptr - addr; ++ lo = (grub_int16_t) gpoffset; ++ hi = (grub_int32_t) (gpoffset - lo); ++ if (hi + lo != gpoffset) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "R_SW64_GPDISP relocation out of range"); ++ ++ if (gpoffset & 0x8000) { ++ hi = ((gpoffset + 0x8000) >> 16) & 0xffff; ++ lo = gpoffset & 0xffff; ++ } else { ++ hi = (gpoffset >> 16) & 0xffff; ++ lo = gpoffset & 0xffff; ++ } ++ ++ *(grub_uint32_t *) addr = ( *(grub_uint32_t *)addr & 0xffff0000) | (hi & 0xffff); ++ *(grub_uint32_t *) ((unsigned long)addr + rel->r_addend) = ++ (((*(grub_uint32_t *)((unsigned long)addr + rel->r_addend)) & 0xffff0000) | (lo & 0xffff)); ++ break; ++ } ++ case R_SW64_BRADDR: ++ { ++ grub_uint64_t braddr = (*(grub_uint64_t *)addr) + value - ((grub_uint64_t)addr + 4); ++ braddr = (grub_int64_t)braddr >> 2; ++ if (braddr + (1<<21) >= 1<<21) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "R_SW64_BRADDR relocation out of range"); ++ ++ *(grub_uint32_t *) addr = (*(grub_uint32_t *)addr & (~0x1fffff)) | (braddr & 0x1fffff); ++ break; ++ } ++ case R_SW64_HINT: ++ break; ++ case R_SW64_SREL32: ++ { ++ value -= (grub_uint64_t)addr; ++ if ((grub_int32_t)value != value) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "R_SW64_SREL32 relocation out of range"); ++ ++ *(grub_uint32_t *) addr = value; ++ break; ++ } ++ case R_SW64_SREL64: ++ { ++ grub_uint64_t srel64 = *(grub_uint64_t *)addr + value;; ++ srel64 -= (grub_uint64_t)addr; ++ *(grub_uint64_t *) addr = srel64; ++ break; ++ } ++ case R_SW64_GPRELHIGH: ++ { ++ grub_uint64_t gprel_hi = (grub_int64_t)(value - (grub_uint64_t)gpptr); ++ ++ if (gprel_hi & 0x8000) ++ gprel_hi = (grub_int64_t)(((grub_int64_t)gprel_hi + 0x8000) >> 16); ++ else ++ gprel_hi = (grub_int64_t)gprel_hi >> 16; ++ ++ if ((grub_int16_t)gprel_hi != gprel_hi) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "GPRELHIGH out of range\n"); ++ ++ *(grub_uint32_t *) addr = (*(grub_uint32_t *)addr & 0xffff0000) | (gprel_hi & 0xffff); ++ break; ++ } ++ case R_SW64_GPRELLOW: ++ { ++ grub_uint64_t gprel_lo = value - (grub_uint64_t)gpptr; ++ *(grub_uint32_t *) addr = (*(grub_uint32_t *)addr & 0xffff0000) | (gprel_lo & 0xffff); ++ break; ++ } ++ case R_SW64_GPREL16: ++ { ++ grub_uint64_t gprel16 = (*(grub_uint64_t *)addr + value); ++ gprel16 = (grub_uint64_t)(gprel16 - (grub_uint64_t)gpptr); ++ if ((grub_int16_t)gprel16 != gprel16) ++ return grub_error (GRUB_ERR_BAD_MODULE, ++ "R_SW64_GPREL16 relocation out of range"); ++ *(grub_uint16_t *) addr = gprel16; ++ break; ++ } ++ default: ++ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ N_("relocation 0x%lx is not implemented yet"), ++ ELF_R_TYPE (rel->r_info)); ++ } ++ } ++ ++ return GRUB_ERR_NONE; ++} +diff --git a/include/grub/dl.h b/include/grub/dl.h +index 0233383..a40a5db 100644 +--- a/include/grub/dl.h ++++ b/include/grub/dl.h +@@ -296,6 +296,14 @@ grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + grub_err_t + grub_arm64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + grub_size_t *got); ++#if defined (__sw_64__) ++#define GRUB_SW64_DL_TRAMP_ALIGN 16 ++#define GRUB_SW64_DL_GOT_ALIGN 16 ++ ++grub_err_t ++grub_sw64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, ++ grub_size_t *got); ++#endif + + #if defined (__ia64__) + #define GRUB_ARCH_DL_TRAMP_ALIGN GRUB_IA64_DL_TRAMP_ALIGN +@@ -303,6 +311,10 @@ grub_arm64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + #define grub_arch_dl_get_tramp_got_size grub_ia64_dl_get_tramp_got_size + #elif defined (__aarch64__) + #define grub_arch_dl_get_tramp_got_size grub_arm64_dl_get_tramp_got_size ++#elif defined (__sw_64__) ++#define GRUB_ARCH_DL_TRAMP_ALIGN GRUB_SW64_DL_TRAMP_ALIGN ++#define GRUB_ARCH_DL_GOT_ALIGN GRUB_SW64_DL_GOT_ALIGN ++#define grub_arch_dl_get_tramp_got_size grub_sw64_dl_get_tramp_got_size + #else + grub_err_t + grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, +diff --git a/include/grub/elf.h b/include/grub/elf.h +index 73175bd..c753739 100644 +--- a/include/grub/elf.h ++++ b/include/grub/elf.h +@@ -255,6 +255,7 @@ typedef struct + chances of collision with official or non-GNU unofficial values. */ + + #define EM_ALPHA 0x9026 ++#define EM_SW_64 0x9916 + + /* Legal values for e_version (version). */ + +@@ -2561,6 +2562,44 @@ typedef Elf32_Addr Elf32_Conflict; + #define R_LARCH_PCALA_HI20 71 + #define R_LARCH_PCALA_LO12 72 + ++/* ++ * SW-64 ELF relocation types ++ */ ++#define R_SW64_NONE 0 /* No reloc */ ++#define R_SW64_REFLONG 1 /* Direct 32 bit */ ++#define R_SW64_REFQUAD 2 /* Direct 64 bit */ ++#define R_SW64_GPREL32 3 /* GP relative 32 bit */ ++#define R_SW64_LITERAL 4 /* GP relative 16 bit w/optimization */ ++#define R_SW64_LITUSE 5 /* Optimization hint for LITERAL */ ++#define R_SW64_GPDISP 6 /* Add displacement to GP */ ++#define R_SW64_BRADDR 7 /* PC+4 relative 23 bit shifted */ ++#define R_SW64_HINT 8 /* PC+4 relative 16 bit shifted */ ++#define R_SW64_SREL16 9 /* PC relative 16 bit */ ++#define R_SW64_SREL32 10 /* PC relative 32 bit */ ++#define R_SW64_SREL64 11 /* PC relative 64 bit */ ++#define R_SW64_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ ++#define R_SW64_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ ++#define R_SW64_GPREL16 19 /* GP relative 16 bit */ ++#define R_SW64_COPY 24 /* Copy symbol at runtime */ ++#define R_SW64_GLOB_DAT 25 /* Create GOT entry */ ++#define R_SW64_JMP_SLOT 26 /* Create PLT entry */ ++#define R_SW64_RELATIVE 27 /* Adjust by program base */ ++#define R_SW64_BRSGP 28 ++#define R_SW64_TLSGD 29 ++#define R_SW64_TLS_LDM 30 ++#define R_SW64_DTPMOD64 31 ++#define R_SW64_GOTDTPREL 32 ++#define R_SW64_DTPREL64 33 ++#define R_SW64_DTPRELHI 34 ++#define R_SW64_DTPRELLO 35 ++#define R_SW64_DTPREL16 36 ++#define R_SW64_GOTTPREL 37 ++#define R_SW64_TPREL64 38 ++#define R_SW64_TPRELHI 39 ++#define R_SW64_TPRELLO 40 ++#define R_SW64_TPREL16 41 ++#define R_SW64_LITERAL_GOT 43 ++ + #ifdef GRUB_TARGET_WORDSIZE + #if GRUB_TARGET_WORDSIZE == 32 + +diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c +index 6d1f77b..1af7634 100644 +--- a/util/grub-mkimagexx.c ++++ b/util/grub-mkimagexx.c +@@ -819,8 +819,14 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, + Elf_Half i; + Elf_Shdr *s; + #ifdef MKIMAGE_ELF64 ++ grub_uint64_t got_offset = 0; ++ + struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off); + grub_uint64_t *gpptr = (void *) (pe_target + got_off); ++ if (image_target->elf_target == EM_SW_64) { ++ got_offset = got_off; ++ gpptr = (void *) (pe_target + got_offset + 0x8000); ++ } + unsigned unmatched_adr_got_page = 0; + #define MASK19 ((1 << 19) - 1) + #else +@@ -1161,6 +1167,119 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, + } + break; + } ++ case EM_SW_64: ++ { ++ sym_addr += addend; ++ switch (ELF_R_TYPE (info)) ++ { ++ case R_SW64_NONE: ++ break; ++ case R_SW64_REFLONG: ++ *(grub_uint32_t *)target = grub_host_to_target32 (sym_addr); ++ break; ++ case R_SW64_REFQUAD: ++ { ++ *(grub_uint32_t *)target = grub_host_to_target32(sym_addr); ++ *((grub_uint32_t *)target + 1) = grub_host_to_target32(sym_addr >> 32); ++ break; ++ } ++ case R_SW64_GPREL32: ++ { ++ *(grub_uint32_t *) target = (grub_host_to_target64 (sym_addr) - ++ ((char *) gpptr - (char *)pe_target + image_target->vaddr_offset )) & 0xffffffff; ++ break; ++ } ++ case R_SW64_LITERAL: ++ { ++ grub_uint64_t li_hi; ++ grub_uint64_t li_lo; ++ ++ li_hi = (grub_uint64_t)pe_target + got_offset + (((grub_uint64_t)ELF_R_TYPE(r->r_info)) >> 8 ); ++ li_lo = li_hi - ((grub_uint64_t) gpptr); ++ *(grub_uint16_t *) target = (li_lo & 0xffff); ++ *(grub_uint64_t *) (li_hi) = grub_host_to_target64(grub_host_to_target64 (sym_addr)); ++ got_offset += 8; ++ break; ++ } ++ case R_SW64_LITERAL_GOT: ++ break; ++ case R_SW64_LITUSE: ++ break; ++ case R_SW64_GPDISP: ++ { ++ grub_uint64_t hi; ++ grub_uint64_t lo; ++ grub_int64_t gpoffset = (((char *) gpptr - (char *) pe_target + image_target->vaddr_offset)) ++ - ((offset + target_section_addr + image_target->vaddr_offset)); ++ if (gpoffset & 0x8000) { ++ hi = ((gpoffset + 0x8000) >> 16) & 0xffff; ++ lo = gpoffset & 0xffff; ++ } else { ++ hi = (gpoffset >> 16) & 0xffff; ++ lo = gpoffset & 0xffff; ++ } ++ *(grub_uint32_t *) target = grub_host_to_target32 ((grub_target_to_host32 (*target) & 0xffff0000) | (hi & 0xffff)); ++ *(grub_uint32_t *) ((unsigned long)target + addend) = ++ grub_host_to_target32 ((grub_target_to_host32 (*(grub_uint32_t *) ++ ((unsigned long)target + addend)) & 0xffff0000) | (lo & 0xffff)); ++ break; ++ ++ } ++ case R_SW64_BRADDR: ++ { ++ grub_uint64_t braddr = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr) - ((grub_uint64_t)target + 4); ++ braddr = braddr >> 2; ++ *(grub_uint32_t *) target = (*(grub_uint32_t *)target & (~0x1fffff)) | (braddr & 0x1fffff); ++ break; ++ } ++ case R_SW64_HINT: ++ break; ++ case R_SW64_SREL32: ++ { ++ grub_uint64_t srel32 = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr); ++ srel32 -= (grub_uint64_t)target; ++ *(grub_uint32_t *) target = srel32; ++ break; ++ } ++ case R_SW64_SREL64: ++ { ++ grub_uint64_t srel64 = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr); ++ srel64 -= (grub_uint64_t)target; ++ *(grub_uint64_t *) target = srel64; ++ break; ++ } ++ case R_SW64_GPRELHIGH: ++ { ++ grub_uint64_t gprel_hi = ((grub_host_to_target64 (sym_addr) - (((char *) gpptr - (char *)pe_target + image_target->vaddr_offset) + 0x0))); ++ ++ if (gprel_hi & 0x8000) ++ gprel_hi = ((gprel_hi + 0x8000) >> 16) & 0xffff; ++ else ++ gprel_hi = (gprel_hi >> 16) & 0xffff; ++ ++ *(grub_uint32_t *) target = grub_host_to_target32 ((grub_target_to_host32 (*target) & 0xffff0000) | (gprel_hi & 0xffff)); ++ break; ++ } ++ case R_SW64_GPRELLOW: ++ { ++ grub_uint64_t gprel_lo = (grub_host_to_target64 (sym_addr) - ((char *) gpptr - (char *)pe_target + image_target->vaddr_offset)); ++ *(grub_uint32_t *) target = grub_host_to_target32 ((grub_target_to_host32 (*target) & 0xffff0000) | (gprel_lo & 0xffff)); ++ break; ++ } ++ case R_SW64_GPREL16: ++ { ++ grub_uint64_t gprel16 = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr); ++ gprel16 = (grub_uint64_t)(gprel16 - (grub_uint64_t)gpptr); ++ *(grub_uint16_t *) target = gprel16; ++ break; ++ } ++ default: ++ grub_util_error (_("relocation 0x%lx is not implemented yet"), ++ ELF_R_TYPE (info)); ++ break; ++ } ++ break; ++ } + case EM_LOONGARCH: + { + grub_int64_t pc; +@@ -1693,6 +1812,19 @@ translate_relocation_pe (struct translate_context *ctx, + image_target); + } + break; ++ case EM_SW_64: ++ if (ELF_R_TYPE (info) == R_SW64_REFQUAD) ++ { ++ grub_util_info ("adding a relocation entry for 0x%llx", ++ (unsigned long long) addr); ++ ctx->current_address ++ = add_fixup_entry (&ctx->lst, ++ GRUB_PE32_REL_BASED_DIR64, ++ addr, ++ 0, ctx->current_address, ++ image_target); ++ } ++ break; + case EM_IA_64: + switch (ELF_R_TYPE (info)) + { +@@ -2147,7 +2279,7 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout, + + image_target->vaddr_offset, + 2 * layout->ia64jmpnum, + image_target); +- if (image_target->elf_target == EM_IA_64 || image_target->elf_target == EM_AARCH64) ++ if (image_target->elf_target == EM_IA_64 || image_target->elf_target == EM_AARCH64 || image_target->elf_target == EM_SW_64) + create_u64_fixups (&ctx, + layout->got_off + + image_target->vaddr_offset, +@@ -2519,6 +2651,17 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path, + layout->got_off = layout->kernel_size; + layout->kernel_size += ALIGN_UP (layout->got_size, 16); + } ++ if (image_target->elf_target == EM_SW_64) ++ { ++ grub_size_t tramp; ++ ++ layout->kernel_size = ALIGN_UP (layout->kernel_size, 16); ++ ++ grub_sw64_dl_get_tramp_got_size (e, &tramp, &layout->got_size); ++ ++ layout->got_off = layout->kernel_size; ++ layout->kernel_size += ALIGN_UP (layout->got_size, 16); ++ } + #endif + + if (image_target->id == IMAGE_EFI) +diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c +index 071d1c3..2daf8b6 100644 +--- a/util/grub-module-verifier.c ++++ b/util/grub-module-verifier.c +@@ -191,6 +191,24 @@ struct grub_module_verifier_arch archs[] = { + }, (int[]){ + -1 + } }, ++ { "sw64", 8, 0, EM_SW_64, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){ ++ R_SW64_NONE, ++ R_SW64_REFQUAD, ++ R_SW64_GPREL32, ++ R_SW64_LITERAL, ++ R_SW64_LITERAL_GOT, ++ R_SW64_LITUSE, ++ R_SW64_GPDISP, ++ R_SW64_BRSGP, ++ R_SW64_BRADDR, ++ R_SW64_HINT, ++ R_SW64_SREL32, ++ R_SW64_SREL64, ++ R_SW64_GPRELHIGH, ++ R_SW64_GPRELLOW, ++ R_SW64_GPREL16, ++ -1 ++ } }, + }; + + struct platform_whitelist { +-- +2.17.1 + diff --git a/sw64-Add-early-startup-code.patch b/sw64-Add-early-startup-code.patch new file mode 100644 index 0000000000000000000000000000000000000000..2e51f0d228912e6fe20ce72196b2a6328f7ade54 --- /dev/null +++ b/sw64-Add-early-startup-code.patch @@ -0,0 +1,62 @@ +From 56ba54b9bbe77bb9578ac3b5fa3376f4d9d3c90d Mon Sep 17 00:00:00 2001 +From: sunway_fw +Date: Tue, 18 Feb 2025 14:50:17 +0800 +Subject: [PATCH 1/5] sw64: Add early startup code + +On entry, we need to save the system table pointer as well as our image +handle. Add an early startup file that saves them and then brings us +into our main function. + +Signed-off-by: sunway_fw +--- + grub-core/kern/sw64/efi/startup.S | 38 +++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + create mode 100644 grub-core/kern/sw64/efi/startup.S + +diff --git a/grub-core/kern/sw64/efi/startup.S b/grub-core/kern/sw64/efi/startup.S +new file mode 100644 +index 0000000..85af868 +--- /dev/null ++++ b/grub-core/kern/sw64/efi/startup.S +@@ -0,0 +1,38 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2018 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++ ++ .file "startup.S" ++ .text ++ .globl start, _start ++ ++FUNCTION(start) ++FUNCTION(_start) ++ /* ++ * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in a1/a0. ++ */ ++ ldih $29,0($27) !gpdisp!1 ++ ldi $29,0($29) !gpdisp!1 ++ ldi $20, EXT_C(grub_efi_image_handle) ++ stl a0, 0($20) ++ ldi $20, EXT_C(grub_efi_system_table) ++ stl a1, 0($20) ++ call $31, grub_main ++ ret +-- +2.17.1 + diff --git a/sw64-Add-to-build-system.patch b/sw64-Add-to-build-system.patch new file mode 100644 index 0000000000000000000000000000000000000000..4aa04190fc3cc06d114ba97e3cf244fb3df6b41f --- /dev/null +++ b/sw64-Add-to-build-system.patch @@ -0,0 +1,661 @@ +From ccb1c1ec8bfc443dba00f523d305326564ba6713 Mon Sep 17 00:00:00 2001 +From: sunway_fw +Date: Tue, 25 Feb 2025 03:53:06 +0800 +Subject: [PATCH] sw64: Add to build system + +This patch adds SW64 to the GRUB build system and various tools, so GRUB +can be built on SW64 as a UEFI application. + +Signed-off-by: sunway_fw +--- + Makefile.util.def | 1 + + bootstrap.conf | 4 +++ + conf/Makefile.common | 3 ++ + configure.ac | 6 ++++ + gentpl.py | 7 ++-- + grub-core/Makefile.am | 7 ++++ + grub-core/Makefile.core.def | 18 ++++++++++ + grub-core/commands/file.c | 11 +++++- + grub-core/kern/compiler-rt.c | 2 +- + grub-core/kern/efi/mm.c | 2 +- + grub-core/lib/gnulib-patches/fix-sw64.patch | 40 +++++++++++++++++++++ + grub-core/lib/setjmp.S | 2 ++ + grub-core/loader/efi/chainloader.c | 2 ++ + include/grub/compiler-rt.h | 2 +- + include/grub/efi/api.h | 2 +- + include/grub/efi/efi.h | 2 +- + include/grub/efi/pe32.h | 1 + + include/grub/fdt.h | 4 +-- + include/grub/util/install.h | 1 + + util/grub-install-common.c | 1 + + util/grub-install.c | 16 +++++++++ + util/grub-mknetdir.c | 1 + + util/grub-mkrescue.c | 11 ++++-- + util/mkimage.c | 16 +++++++++ + 24 files changed, 149 insertions(+), 13 deletions(-) + create mode 100644 grub-core/lib/gnulib-patches/fix-sw64.patch + +diff --git a/Makefile.util.def b/Makefile.util.def +index 2208856..450ba2d 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -153,6 +153,7 @@ library = { + common = grub-core/kern/arm/dl_helper.c; + common = grub-core/kern/arm64/dl_helper.c; + common = grub-core/kern/loongarch64/dl_helper.c; ++ common = grub-core/kern/sw64/dl_helper.c; + common = grub-core/lib/minilzo/minilzo.c; + common = grub-core/lib/xzembed/xz_dec_bcj.c; + common = grub-core/lib/xzembed/xz_dec_lzma2.c; +diff --git a/bootstrap.conf b/bootstrap.conf +index 854d3c0..6132a69 100644 +--- a/bootstrap.conf ++++ b/bootstrap.conf +@@ -89,6 +89,10 @@ bootstrap_post_import_hook () { + patch -d gnulib -p1 \ + < "grub-core/lib/gnulib-patches/$patchname.patch" + done ++ for patchname in fix-sw64; do ++ patch -d gnulib -p1 \ ++ < "grub-core/lib/gnulib-patches/$patchname.patch" ++ done + for patchname in \ + 0001-Support-POTFILES-shell \ + 0002-Handle-gettext_printf-shell-function \ +diff --git a/conf/Makefile.common b/conf/Makefile.common +index 9fe5863..d6b1145 100644 +--- a/conf/Makefile.common ++++ b/conf/Makefile.common +@@ -20,6 +20,9 @@ endif + if COND_powerpc_ieee1275 + CFLAGS_PLATFORM += -mcpu=powerpc + endif ++if COND_sw_64_efi ++ CFLAGS_PLATFORM += -Wno-packed-not-aligned -Wno-cast-align -Wno-sign-compare ++endif + + # Other options + +diff --git a/configure.ac b/configure.ac +index 5efc675..deb38f0 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -153,6 +153,9 @@ case "$target_cpu" in + target_cpu=loongarch64 + machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_LOONGARCH64=1" + ;; ++ sw_64*) ++ target_cpu=sw64 ++ ;; + esac + + # Specify the platform (such as firmware). +@@ -179,6 +182,7 @@ if test "x$with_platform" = x; then + arm64-*) platform=efi ;; + riscv32-*) platform=efi ;; + riscv64-*) platform=efi ;; ++ sw64-*) platform=efi ;; + *) + AC_MSG_WARN([unsupported CPU: "$target_cpu" - only building utilities]) + platform=none +@@ -230,6 +234,7 @@ case "$target_cpu"-"$platform" in + arm64-efi) ;; + riscv32-efi) ;; + riscv64-efi) ;; ++ sw64-efi) ;; + *-emu) ;; + *-none) ;; + *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;; +@@ -2226,6 +2231,7 @@ AM_CONDITIONAL([COND_riscv32], [test x$target_cpu = xriscv32 ]) + AM_CONDITIONAL([COND_riscv64], [test x$target_cpu = xriscv64 ]) + AM_CONDITIONAL([COND_riscv32_efi], [test x$target_cpu = xriscv32 -a x$platform = xefi]) + AM_CONDITIONAL([COND_riscv64_efi], [test x$target_cpu = xriscv64 -a x$platform = xefi]) ++AM_CONDITIONAL([COND_sw_64_efi], [test x$target_cpu = xsw64 -a x$platform = xefi]) + + AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd]) + AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux]) +diff --git a/gentpl.py b/gentpl.py +index 3ccdf61..c6be7b8 100644 +--- a/gentpl.py ++++ b/gentpl.py +@@ -33,7 +33,7 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", + "powerpc_ieee1275", "mips_arc", "ia64_efi", + "mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi", + "arm_coreboot", "riscv32_efi", "riscv64_efi", +- "loongarch64_efi" ] ++ "loongarch64_efi", "sw_64_efi" ] + + GROUPS = {} + +@@ -51,11 +51,12 @@ GROUPS["arm64"] = [ "arm64_efi" ] + GROUPS["riscv32"] = [ "riscv32_efi" ] + GROUPS["riscv64"] = [ "riscv64_efi" ] + GROUPS["loongarch64"] = [ "loongarch64_efi" ] ++GROUPS["sw_64"] = [ "sw_64_efi" ] + + # Groups based on firmware + GROUPS["pc"] = [ "i386_pc" ] + GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi", +- "riscv32_efi", "riscv64_efi", "loongarch64_efi" ] ++ "riscv32_efi", "riscv64_efi", "loongarch64_efi", "sw_64_efi" ] + GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ] + GROUPS["uboot"] = [ "arm_uboot" ] + GROUPS["xen"] = [ "i386_xen", "x86_64_xen" ] +@@ -83,7 +84,7 @@ for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i) + + # Flattened Device Trees (FDT) + GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_efi", "riscv32_efi", +- "riscv64_efi", "loongarch64_efi" ] ++ "riscv64_efi", "loongarch64_efi", "sw_64_efi" ] + + # Needs software helpers for division + # Must match GRUB_DIVISION_IN_SOFTWARE in misc.h +diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am +index f5cdf0e..2c410fe 100644 +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -308,6 +308,13 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h + endif + ++if COND_sw_64_efi ++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/sw64/divide.h ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h ++endif ++ + if COND_emu + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index a379e70..2cc5820 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -93,6 +93,8 @@ kernel = { + sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; + mips_arc_ldflags = '-Wl,-Ttext,$(TARGET_LINK_ADDR)'; + mips_qemu_mips_ldflags = '-Wl,-Ttext,0x80200000'; ++ sw_64_efi_ldflags = '-Wl,-r,-d'; ++ sw_64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + + mips_arc_cppflags = '-DGRUB_DECOMPRESSOR_LINK_ADDR=$(TARGET_DECOMPRESSOR_LINK_ADDR)'; + i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; +@@ -126,6 +128,7 @@ kernel = { + riscv32_efi_startup = kern/riscv/efi/startup.S; + riscv64_efi_startup = kern/riscv/efi/startup.S; + loongarch64_efi_startup = kern/loongarch64/efi/startup.S; ++ sw_64_efi_startup = kern/sw64/efi/startup.S; + + common = kern/buffer.c; + common = kern/command.c; +@@ -326,6 +329,15 @@ kernel = { + extra_dist = video/sm712_init.c; + extra_dist = video/sis315_init.c; + mips_loongson = commands/keylayouts.c; ++ sw_64_efi = kern/sw64/dl.c; ++ sw_64_efi = kern/sw64/dl_helper.c; ++ sw_64_efi = kern/sw64/efi/init.c; ++ sw_64_efi = kern/efi/fdt.c; ++ sw_64_efi = lib/sw64/divide.S; ++ sw_64_efi = kern/sw64/efi/callwrap.S; ++ sw_64_efi = kern/sw64/cache.c; ++ sw_64_efi = kern/sw64/cache_flush.S; ++ sw_64_efi = commands/keylayouts.c; + + powerpc_ieee1275 = kern/powerpc/cache.S; + powerpc_ieee1275 = kern/powerpc/dl.c; +@@ -878,6 +890,7 @@ module = { + enable = riscv32_efi; + enable = riscv64_efi; + enable = loongarch64_efi; ++ enable = sw_64_efi; + }; + + module = { +@@ -956,6 +969,7 @@ module = { + i386_efi = commands/acpihalt.c; + x86_64_efi = commands/acpihalt.c; + loongarch64_efi = commands/acpihalt.c; ++ sw_64_efi = commands/acpihalt.c; + i386_multiboot = lib/i386/halt.c; + i386_coreboot = lib/i386/halt.c; + i386_qemu = lib/i386/halt.c; +@@ -1775,6 +1789,8 @@ module = { + extra_dist = lib/arm64/setjmp.S; + extra_dist = lib/riscv/setjmp.S; + extra_dist = lib/loongarch64/setjmp.S; ++ extra_dist = lib/sw64/setjmp.S; ++ extra_dist = lib/sw64/divide.S; + }; + + module = { +@@ -1876,6 +1892,7 @@ module = { + loongarch64 = loader/loongarch64/linux.c; + loongarch64 = loader/loongarch64/linux-elf.c; + loongarch64 = loader/loongarch64/linux-efi.c; ++ sw_64_efi = loader/sw64/efi/linux.c; + emu = loader/emu/linux.c; + + common = loader/linux.c; +@@ -1976,6 +1993,7 @@ module = { + enable = riscv64_efi; + enable = mips; + enable = loongarch64_efi; ++ enable = sw_64; + }; + + module = { +diff --git a/grub-core/commands/file.c b/grub-core/commands/file.c +index 9de0006..157a524 100644 +--- a/grub-core/commands/file.c ++++ b/grub-core/commands/file.c +@@ -94,6 +94,8 @@ static const struct grub_arg_option options[] = { + N_("Check if FILE is RISC-V 32bit EFI file"), 0, 0}, + {"is-riscv64-efi", 0, 0, + N_("Check if FILE is RISC-V 64bit EFI file"), 0, 0}, ++ {"is-sw64-efi", 0, 0, ++ N_("Check if FILE is SW64 EFI file"), 0, 0}, + {"is-hibernated-hiberfil", 0, 0, + N_("Check if FILE is hiberfil.sys in hibernated state"), 0, 0}, + {"is-x86_64-xnu", 0, 0, +@@ -136,6 +138,7 @@ enum + IS_ARM_EFI, + IS_RISCV32_EFI, + IS_RISCV64_EFI, ++ IS_SW64_EFI, + IS_HIBERNATED, + IS_XNU64, + IS_XNU32, +@@ -579,6 +582,7 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args) + case IS_ARM_EFI: + case IS_RISCV32_EFI: + case IS_RISCV64_EFI: ++ case IS_SW64_EFI: + { + char signature[4]; + grub_uint32_t pe_offset; +@@ -629,8 +633,13 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args) + grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_RISCV64)) + /* TODO: Determine bitness dynamically */ + break; ++ if (type == IS_SW64_EFI ++ && coff_head.machine != ++ grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_SW_64)) ++ /* TODO: Determine bitness dynamically */ ++ break; + if (type == IS_IA_EFI || type == IS_64_EFI || type == IS_ARM64_EFI || +- type == IS_RISCV32_EFI || type == IS_RISCV64_EFI) ++ type == IS_RISCV32_EFI || type == IS_RISCV64_EFI || type == IS_SW64_EFI) + { + struct grub_pe64_optional_header o64; + if (grub_file_read (file, &o64, sizeof (o64)) != sizeof (o64)) +diff --git a/grub-core/kern/compiler-rt.c b/grub-core/kern/compiler-rt.c +index 2057c2e..aac8742 100644 +--- a/grub-core/kern/compiler-rt.c ++++ b/grub-core/kern/compiler-rt.c +@@ -345,7 +345,7 @@ __ucmpdi2 (grub_uint64_t a, grub_uint64_t b) + #endif + + #if defined (__powerpc__) || defined(__mips__) || defined(__sparc__) || \ +- defined(__arm__) || defined(__riscv) ++ defined(__arm__) || defined(__riscv) || defined(__sw_64__) + + /* Based on libgcc2.c from gcc suite. */ + grub_uint32_t +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 6989fa9..95577ff 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -703,7 +703,7 @@ grub_efi_mm_init (void) + } + + #if defined (__aarch64__) || defined (__arm__) || defined (__riscv) \ +- || defined (__loongarch__) ++ || defined (__loongarch__) || defined (__sw_64__) + grub_err_t + grub_efi_get_ram_base(grub_addr_t *base_addr) + { +diff --git a/grub-core/lib/gnulib-patches/fix-sw64.patch b/grub-core/lib/gnulib-patches/fix-sw64.patch +new file mode 100644 +index 0000000..e4948cc +--- /dev/null ++++ b/grub-core/lib/gnulib-patches/fix-sw64.patch +@@ -0,0 +1,40 @@ ++diff --git a/build-aux/config.guess b/build-aux/config.guess ++index 927581d..54a4e8b 100755 ++--- a/build-aux/config.guess +++++ b/build-aux/config.guess ++@@ -930,6 +930,10 @@ EOF ++ UNAME_MACHINE=aarch64_be ++ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" ++ exit ;; +++ sw_64:Linux:*:*) +++ UNAME_MACHINE=sw_64 +++ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +++ exit ;; ++ alpha:Linux:*:*) ++ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in ++ EV5) UNAME_MACHINE=alphaev5 ;; ++diff --git a/build-aux/config.sub b/build-aux/config.sub ++index 6303428..2f50a1f 100755 ++--- a/build-aux/config.sub +++++ b/build-aux/config.sub ++@@ -917,6 +917,10 @@ case $basic_machine in ++ cpu=sparc ++ vendor=`echo "$basic_machine" | sed 's/-.*//'` ++ ;; +++ sw_64*) +++ cpu=sw_64 +++ vendor=sunway +++ ;; ++ ++ *-*) ++ # shellcheck disable=SC2162 ++@@ -1150,6 +1154,9 @@ case $cpu-$vendor in ++ tile*-*) ++ os=${os:-linux-gnu} ++ ;; +++ sw_64-*) +++ os=${os:-linux-gnu} +++ ;; ++ ++ *) ++ # Recognize the canonical CPU types that are allowed with any +diff --git a/grub-core/lib/setjmp.S b/grub-core/lib/setjmp.S +index da71fc7..bc354a9 100644 +--- a/grub-core/lib/setjmp.S ++++ b/grub-core/lib/setjmp.S +@@ -19,6 +19,8 @@ + #include "./loongarch64/setjmp.S" + #elif defined(__riscv) + #include "./riscv/setjmp.S" ++#elif defined(__sw_64__) ++#include "./sw64/setjmp.S" + #else + #error "Unknown target cpu type" + #endif +diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index faf60ef..e21d2e8 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -351,6 +351,8 @@ static const grub_uint16_t machine_type __attribute__((__unused__)) = + GRUB_PE32_MACHINE_RISCV32; + #elif defined(__riscv) && (__riscv_xlen == 64) + GRUB_PE32_MACHINE_RISCV64; ++#elif defined(__sw_64__) ++ GRUB_PE32_MACHINE_SW_64; + #else + #error this architecture is not supported by grub2 + #endif +diff --git a/include/grub/compiler-rt.h b/include/grub/compiler-rt.h +index 17828b3..a8782fc 100644 +--- a/include/grub/compiler-rt.h ++++ b/include/grub/compiler-rt.h +@@ -178,7 +178,7 @@ EXPORT_FUNC (__lshrdi3) (grub_uint64_t u, int b); + #endif + + #if defined (__powerpc__) || defined(__mips__) || defined(__sparc__) || \ +- defined (__arm__) || defined(__riscv) ++ defined (__arm__) || defined(__riscv) || defined(__sw_64__) + grub_uint32_t + EXPORT_FUNC(__bswapsi2) (grub_uint32_t u); + +diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h +index a74ce39..6fdee14 100644 +--- a/include/grub/efi/api.h ++++ b/include/grub/efi/api.h +@@ -2104,7 +2104,7 @@ typedef struct grub_efi_ip6_config_manual_address grub_efi_ip6_config_manual_add + + #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ + || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \ +- || defined(__riscv) || defined (__loongarch64) ++ || defined(__riscv) || defined (__loongarch64) || defined (__sw_64__) + + #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 c816359..d6414e0 100644 +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -135,7 +135,7 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, + char **device, + char **path); + +-#if defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__loongarch__) ++#if defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__loongarch__) || defined(__sw_64__) + 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 f8f2402..93e9fd3 100644 +--- a/include/grub/efi/pe32.h ++++ b/include/grub/efi/pe32.h +@@ -81,6 +81,7 @@ struct grub_pe32_coff_header + #define GRUB_PE32_MACHINE_RISCV64 0x5064 + #define GRUB_PE32_MACHINE_LOONGARCH32 0x6232 + #define GRUB_PE32_MACHINE_LOONGARCH64 0x6264 ++#define GRUB_PE32_MACHINE_SW_64 0x0284 + + #define GRUB_PE32_RELOCS_STRIPPED 0x0001 + #define GRUB_PE32_EXECUTABLE_IMAGE 0x0002 +diff --git a/include/grub/fdt.h b/include/grub/fdt.h +index ba2f9a9..ab576d5 100644 +--- a/include/grub/fdt.h ++++ b/include/grub/fdt.h +@@ -20,7 +20,7 @@ + #define GRUB_FDT_HEADER 1 + + #if !defined(GRUB_MACHINE_EMU) && \ +- (defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__loongarch__)) ++ (defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__loongarch__) || defined(__sw_64__)) + + #include + #include +@@ -148,6 +148,6 @@ int EXPORT_FUNC(grub_fdt_set_prop) (void *fdt, unsigned int nodeoffset, const ch + }) + + #endif /* !defined(GRUB_MACHINE_EMU) && \ +- (defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__loongarch__)) */ ++ (defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defined(__loongarch__) || defined(__sw_64__)) */ + + #endif /* ! GRUB_FDT_HEADER */ +diff --git a/include/grub/util/install.h b/include/grub/util/install.h +index a728afc..148cf31 100644 +--- a/include/grub/util/install.h ++++ b/include/grub/util/install.h +@@ -115,6 +115,7 @@ enum grub_install_plat + GRUB_INSTALL_PLATFORM_RISCV32_EFI, + GRUB_INSTALL_PLATFORM_RISCV64_EFI, + GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI, ++ GRUB_INSTALL_PLATFORM_SW64_EFI, + GRUB_INSTALL_PLATFORM_MAX + }; + +diff --git a/util/grub-install-common.c b/util/grub-install-common.c +index 1623913..0e4b32e 100644 +--- a/util/grub-install-common.c ++++ b/util/grub-install-common.c +@@ -940,6 +940,7 @@ static struct + [GRUB_INSTALL_PLATFORM_RISCV32_EFI] = { "riscv32", "efi" }, + [GRUB_INSTALL_PLATFORM_RISCV64_EFI] = { "riscv64", "efi" }, + [GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI] = { "loongarch64", "efi" }, ++ [GRUB_INSTALL_PLATFORM_SW64_EFI] = { "sw64", "efi" }, + }; + + char * +diff --git a/util/grub-install.c b/util/grub-install.c +index c8f15df..09c09df 100644 +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -334,6 +334,8 @@ get_default_platform (void) + #endif + #elif defined (__loongarch64) + return "loongarch64-efi"; ++#elif defined (__sw_64__) ++ return "sw64-efi"; + #else + return NULL; + #endif +@@ -510,6 +512,7 @@ have_bootdev (enum grub_install_plat pl) + case GRUB_INSTALL_PLATFORM_I386_XEN: + case GRUB_INSTALL_PLATFORM_X86_64_XEN: + case GRUB_INSTALL_PLATFORM_I386_XEN_PVH: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + return 0; + + /* pacify warning. */ +@@ -910,6 +913,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_IA64_EFI: + case GRUB_INSTALL_PLATFORM_X86_64_EFI: + case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + is_efi = 1; + grub_util_error (_("this utility cannot be used for EFI platforms" + " because it does not support UEFI Secure Boot")); +@@ -948,6 +952,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_I386_XEN: + case GRUB_INSTALL_PLATFORM_X86_64_XEN: + case GRUB_INSTALL_PLATFORM_I386_XEN_PVH: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + break; + + case GRUB_INSTALL_PLATFORM_I386_QEMU: +@@ -999,6 +1004,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_I386_XEN: + case GRUB_INSTALL_PLATFORM_X86_64_XEN: + case GRUB_INSTALL_PLATFORM_I386_XEN_PVH: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + free (install_device); + install_device = NULL; + break; +@@ -1142,6 +1148,9 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: + efi_file = "BOOTLOONGARCH64.EFI"; + break; ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: ++ efi_file = "BOOTSW64.EFI"; ++ break; + default: + grub_util_error ("%s", _("You've found a bug")); + break; +@@ -1178,6 +1187,9 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: + efi_file = "grubloongarch64.efi"; + break; ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: ++ efi_file = "grubsw64.efi"; ++ break; + default: + efi_file = "grub.efi"; + break; +@@ -1484,6 +1496,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_RISCV64_EFI: + case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + g = grub_util_guess_efi_drive (*curdev); + break; + case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: +@@ -1629,6 +1642,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_RISCV64_EFI: + case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + core_name = "core.efi"; + snprintf (mkimage_target, sizeof (mkimage_target), + "%s-%s", +@@ -1749,6 +1763,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_I386_XEN: + case GRUB_INSTALL_PLATFORM_X86_64_XEN: + case GRUB_INSTALL_PLATFORM_I386_XEN_PVH: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + break; + /* pacify warning. */ + case GRUB_INSTALL_PLATFORM_MAX: +@@ -1990,6 +2005,7 @@ main (int argc, char *argv[]) + case GRUB_INSTALL_PLATFORM_RISCV64_EFI: + case GRUB_INSTALL_PLATFORM_LOONGARCH64_EFI: + case GRUB_INSTALL_PLATFORM_IA64_EFI: ++ case GRUB_INSTALL_PLATFORM_SW64_EFI: + { + char *dst = grub_util_path_concat (2, efidir, efi_file); + grub_install_copy_file (imgfile, dst, 1); +diff --git a/util/grub-mknetdir.c b/util/grub-mknetdir.c +index 77958dd..5e4f393 100644 +--- a/util/grub-mknetdir.c ++++ b/util/grub-mknetdir.c +@@ -115,6 +115,7 @@ static struct + [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64-efi", "efinet", ".efi" }, + [GRUB_INSTALL_PLATFORM_RISCV32_EFI] = { "riscv32-efi", "efinet", ".efi" }, + [GRUB_INSTALL_PLATFORM_RISCV64_EFI] = { "riscv64-efi", "efinet", ".efi" }, ++ [GRUB_INSTALL_PLATFORM_SW64_EFI] = { "sw64-efi", "efinet", ".efi" }, + }; + + static void +diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c +index 59c48b1..bb19fc9 100644 +--- a/util/grub-mkrescue.c ++++ b/util/grub-mkrescue.c +@@ -544,7 +544,8 @@ main (int argc, char *argv[]) + || source_dirs[GRUB_INSTALL_PLATFORM_ARM64_EFI] + || source_dirs[GRUB_INSTALL_PLATFORM_RISCV32_EFI] + || source_dirs[GRUB_INSTALL_PLATFORM_RISCV64_EFI] +- || source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI]) ++ || source_dirs[GRUB_INSTALL_PLATFORM_X86_64_EFI] ++ || source_dirs[GRUB_INSTALL_PLATFORM_SW64_EFI]) + system_area = SYS_AREA_COMMON; + else if (source_dirs[GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275]) + system_area = SYS_AREA_SPARC; +@@ -743,7 +744,8 @@ main (int argc, char *argv[]) + || source_dirs[GRUB_INSTALL_PLATFORM_ARM_EFI] + || source_dirs[GRUB_INSTALL_PLATFORM_ARM64_EFI] + || source_dirs[GRUB_INSTALL_PLATFORM_RISCV32_EFI] +- || source_dirs[GRUB_INSTALL_PLATFORM_RISCV64_EFI]) ++ || source_dirs[GRUB_INSTALL_PLATFORM_RISCV64_EFI] ++ || source_dirs[GRUB_INSTALL_PLATFORM_SW64_EFI]) + { + char *efidir = grub_util_make_temporary_dir (); + char *efidir_efi = grub_util_path_concat (2, efidir, "efi"); +@@ -788,6 +790,11 @@ main (int argc, char *argv[]) + imgname); + free (imgname); + ++ imgname = grub_util_path_concat (2, efidir_efi_boot, "bootsw64.efi"); ++ make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_SW64_EFI, "sw64-efi", ++ imgname); ++ free (imgname); ++ + if (source_dirs[GRUB_INSTALL_PLATFORM_I386_EFI]) + { + imgname = grub_util_path_concat (2, efidir_efi_boot, "boot.efi"); +diff --git a/util/mkimage.c b/util/mkimage.c +index 4e09dfc..85da670 100644 +--- a/util/mkimage.c ++++ b/util/mkimage.c +@@ -425,6 +425,22 @@ static const struct grub_install_image_target_desc image_targets[] = + .pe_target = GRUB_PE32_MACHINE_IA64, + .elf_target = EM_IA_64, + }, ++ { ++ .dirname = "sw64-efi", ++ .names = {"sw64-efi", NULL}, ++ .voidp_sizeof = 8, ++ .bigendian = 0, ++ .id = IMAGE_EFI, ++ .flags = PLATFORM_FLAGS_NONE, ++ .total_module_size = TARGET_NO_FIELD, ++ .decompressor_compressed_size = TARGET_NO_FIELD, ++ .decompressor_uncompressed_size = TARGET_NO_FIELD, ++ .decompressor_uncompressed_addr = TARGET_NO_FIELD, ++ .section_align = GRUB_PE32_SECTION_ALIGNMENT, ++ .vaddr_offset = EFI64_HEADER_SIZE, ++ .pe_target = GRUB_PE32_MACHINE_SW_64, ++ .elf_target = EM_SW_64, ++ }, + { + .dirname = "mips-arc", + .names = {"mips-arc", NULL}, +-- +2.33.0 +