Initial commit from Ventoy@7cbdc5c

This commit is contained in:
2026-08-23 00:38:40 -04:00
commit e9a7a16826
2848 changed files with 439164 additions and 0 deletions
@@ -0,0 +1,118 @@
/* cmdline.c - linux command line handling */
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <grub/lib/cmdline.h>
#include <grub/misc.h>
static unsigned int check_arg (char *c, int *has_space)
{
int space = 0;
unsigned int size = 0;
while (*c)
{
if (*c == '\\' || *c == '\'' || *c == '"')
size++;
else if (*c == ' ')
space = 1;
size++;
c++;
}
if (space)
size += 2;
if (has_space)
*has_space = space;
return size;
}
unsigned int grub_loader_cmdline_size (int argc, char *argv[])
{
int i;
unsigned int size = 0;
for (i = 0; i < argc; i++)
{
size += check_arg (argv[i], 0);
size++; /* Separator space or NULL. */
}
if (size == 0)
size = 1;
return size;
}
grub_err_t
grub_create_loader_cmdline (int argc, char *argv[], char *buf,
grub_size_t size, enum grub_verify_string_type type)
{
int i, space;
unsigned int arg_size;
char *c, *orig_buf = buf;
for (i = 0; i < argc; i++)
{
c = argv[i];
arg_size = check_arg(argv[i], &space);
arg_size++; /* Separator space or NULL. */
if (size < arg_size)
break;
size -= arg_size;
if (space)
*buf++ = '"';
while (*c)
{
if (*c == '\\' && *(c+1) == 'x' &&
grub_isxdigit(*(c+2)) && grub_isxdigit(*(c+3)))
{
*buf++ = *c++;
*buf++ = *c++;
*buf++ = *c++;
*buf++ = *c++;
continue;
}
else if (*c == '\\' || *c == '\'' || *c == '"')
*buf++ = '\\';
*buf++ = *c;
c++;
}
if (space)
*buf++ = '"';
*buf++ = ' ';
}
/* Replace last space with null. */
if (i)
buf--;
*buf = 0;
return grub_verify_string (orig_buf, type);
}
@@ -0,0 +1,40 @@
/* efi.c - generic EFI support */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007,2008,2009,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 <http://www.gnu.org/licenses/>.
*/
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/kernel.h>
#include <grub/acpi.h>
#include <grub/loader.h>
void
grub_halt (void)
{
grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
#if !defined(__ia64__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__mips__) &&\
!defined(__riscv)
grub_acpi_halt ();
#endif
efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL);
while (1);
}
@@ -0,0 +1,495 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2017 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/mm.h>
#include <grub/cache.h>
#include <grub/efi/efi.h>
#include <grub/cpu/efi/memory.h>
#include <grub/cpu/memory.h>
#include <grub/machine/loongson.h>
#pragma GCC diagnostic ignored "-Wunused-function"
#define loongson_params (&loongson_boot_params->boot_params.efi.smbios.lp)
#define loongson_boot_params_size ALIGN_UP (sizeof (*loongson_boot_params), 8)
#define loongson_reset_code_size (&grub_efi_loongson_reset_end - &grub_efi_loongson_reset_start)
extern grub_uint8_t grub_efi_loongson_reset_start;
extern grub_uint8_t grub_efi_loongson_reset_end;
static struct
{
grub_efi_loongson_boot_params boot_params;
grub_efi_loongson_memory_map memory_map;
grub_efi_loongson_cpu_info cpu_info;
grub_efi_loongson_system_info system_info;
grub_efi_loongson_irq_src_routing_table irq_src_routing_table;
grub_efi_loongson_interface_info interface_info;
grub_efi_loongson_special_attribute special_attribute;
grub_efi_loongson_board_devices board_devices;
} GRUB_PACKED
* loongson_boot_params;
static void
grub_efi_loongson_init_reset_system (void)
{
grub_efi_loongson_boot_params *boot_params;
grub_uint8_t *reset_code_addr = (grub_uint8_t *) loongson_boot_params +
loongson_boot_params_size;
boot_params = &loongson_boot_params->boot_params;
grub_efi_loongson_reset_system_addr =
(grub_uint64_t) grub_efi_system_table->runtime_services->reset_system;
grub_memcpy (reset_code_addr, &grub_efi_loongson_reset_start, loongson_reset_code_size);
grub_arch_sync_caches (reset_code_addr, loongson_reset_code_size);
boot_params->reset_system.reset_cold = (grub_uint64_t) reset_code_addr +
((grub_uint64_t) &grub_efi_loongson_reset_cold -
(grub_uint64_t) &grub_efi_loongson_reset_start);
boot_params->reset_system.reset_warm = (grub_uint64_t) reset_code_addr +
((grub_uint64_t) &grub_efi_loongson_reset_warm -
(grub_uint64_t) &grub_efi_loongson_reset_start);
boot_params->reset_system.shutdown = (grub_uint64_t) reset_code_addr +
((grub_uint64_t) &grub_efi_loongson_reset_shutdown -
(grub_uint64_t) &grub_efi_loongson_reset_start);
boot_params->reset_system.do_suspend = (grub_uint64_t) reset_code_addr +
((grub_uint64_t) &grub_efi_loongson_reset_suspend -
(grub_uint64_t) &grub_efi_loongson_reset_start);
}
static void
grub_efi_loongson_init_smbios (grub_efi_loongson_smbios_table *smbios_table)
{
grub_efi_loongson_smbios_table *dst = &loongson_boot_params->boot_params.efi.smbios;
dst->vers = smbios_table->vers;
dst->vga_bios = smbios_table->vga_bios;
}
static void
grub_efi_loongson_init_cpu_info (grub_efi_loongson_smbios_table *smbios_table)
{
grub_efi_loongson_cpu_info *src = (void *) smbios_table->lp.cpu_offset;
grub_efi_loongson_cpu_info *dst = &loongson_boot_params->cpu_info;
if (!src)
return;
grub_memcpy (dst, src, sizeof (grub_efi_loongson_cpu_info));
loongson_params->cpu_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params;
}
static void
grub_efi_loongson_init_system_info (grub_efi_loongson_smbios_table *smbios_table)
{
grub_efi_loongson_system_info *src = (void *) smbios_table->lp.system_offset;
grub_efi_loongson_system_info *dst = &loongson_boot_params->system_info;
if (!src)
return;
grub_memcpy (dst, src, sizeof (grub_efi_loongson_system_info));
loongson_params->system_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params;
}
static void
grub_efi_loongson_init_irq_src_routing_table (grub_efi_loongson_smbios_table *smbios_table)
{
grub_efi_loongson_irq_src_routing_table *src = (void *) smbios_table->lp.irq_offset;
grub_efi_loongson_irq_src_routing_table *dst = &loongson_boot_params->irq_src_routing_table;
if (!src)
return;
grub_memcpy (dst, src, sizeof (grub_efi_loongson_irq_src_routing_table));
loongson_params->irq_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params;
}
static void
grub_efi_loongson_init_interface_info (grub_efi_loongson_smbios_table *smbios_table)
{
grub_efi_loongson_interface_info *src = (void *) smbios_table->lp.interface_offset;
grub_efi_loongson_interface_info *dst = &loongson_boot_params->interface_info;
if (!src)
return;
grub_memcpy (dst, src, sizeof (grub_efi_loongson_interface_info));
loongson_params->interface_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params;
}
static void
grub_efi_loongson_init_special_attribute (grub_efi_loongson_smbios_table *smbios_table)
{
grub_efi_loongson_special_attribute *src = (void *) smbios_table->lp.special_offset;
grub_efi_loongson_special_attribute *dst = &loongson_boot_params->special_attribute;
if (!src)
return;
grub_memcpy (dst, src, sizeof (grub_efi_loongson_special_attribute));
loongson_params->special_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params;
}
static void
grub_efi_loongson_init_board_devices (grub_efi_loongson_smbios_table *smbios_table)
{
grub_efi_loongson_board_devices *src = (void *) smbios_table->lp.boarddev_table_offset;
grub_efi_loongson_board_devices *dst = &loongson_boot_params->board_devices;
if (!src)
return;
grub_memcpy (dst, src, sizeof (grub_efi_loongson_board_devices));
loongson_params->boarddev_table_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params;
}
#define ADD_MEMORY_DESCRIPTOR(desc, size) \
((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
static void
grub_efi_loongson_init_memory_map (grub_efi_loongson_smbios_table *smbios_table,
grub_efi_memory_descriptor_t *mmap_buf,
grub_efi_uintn_t mmap_size,
grub_efi_uintn_t desc_size)
{
grub_efi_loongson_memory_map *src = (void *) smbios_table->lp.memory_offset;
grub_efi_loongson_memory_map *dst = &loongson_boot_params->memory_map;
grub_efi_memory_descriptor_t *mmap_end;
grub_efi_memory_descriptor_t *desc;
grub_efi_memory_descriptor_t *desc_next;
grub_efi_uint32_t mem_types_reserved[] =
{
1, // GRUB_EFI_RESERVED_MEMORY_TYPE
0, // GRUB_EFI_LOADER_CODE
0, // GRUB_EFI_LOADER_DATA
0, // GRUB_EFI_BOOT_SERVICES_CODE
0, // GRUB_EFI_BOOT_SERVICES_DATA
1, // GRUB_EFI_RUNTIME_SERVICES_CODE
1, // GRUB_EFI_RUNTIME_SERVICES_DATA
0, // GRUB_EFI_CONVENTIONAL_MEMORY
1, // GRUB_EFI_UNUSABLE_MEMORY
0, // GRUB_EFI_ACPI_RECLAIM_MEMORY
0, // GRUB_EFI_ACPI_MEMORY_NVS
1, // GRUB_EFI_MEMORY_MAPPED_IO
1, // GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE
1, // GRUB_EFI_PAL_CODE
1, // GRUB_EFI_PERSISTENT_MEMORY
};
grub_uint32_t need_sort = 1;
if (!src)
return;
dst->vers = src->vers;
dst->nr_map = 0;
dst->mem_freq = src->mem_freq;
loongson_params->memory_offset = (grub_uint64_t) dst - (grub_uint64_t) loongson_params;
if (!mmap_buf || !mmap_size || !desc_size)
return;
mmap_end = ADD_MEMORY_DESCRIPTOR (mmap_buf, mmap_size);
/* drop reserved */
for (desc = mmap_buf,
desc_next = desc;
desc < mmap_end;
desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size))
{
desc->type = mem_types_reserved[desc->type];
if (desc->type)
continue;
if (desc != desc_next)
*desc_next = *desc;
desc_next = ADD_MEMORY_DESCRIPTOR (desc_next, desc_size);
}
mmap_end = desc_next;
/* sort: low->high */
while (need_sort)
{
need_sort = 0;
for (desc = mmap_buf,
desc_next = ADD_MEMORY_DESCRIPTOR (desc, desc_size);
(desc < mmap_end) && (desc_next < mmap_end);
desc = desc_next,
desc_next = ADD_MEMORY_DESCRIPTOR (desc, desc_size))
{
grub_efi_memory_descriptor_t tmp;
if (desc->physical_start <= desc_next->physical_start)
continue;
tmp = *desc;
*desc = *desc_next;
*desc_next = tmp;
need_sort = 1;
}
}
/* combine continuous memory map */
for (desc = mmap_buf,
desc_next = ADD_MEMORY_DESCRIPTOR (desc, desc_size);
desc_next < mmap_end;
desc_next = ADD_MEMORY_DESCRIPTOR (desc_next, desc_size))
{
grub_efi_physical_address_t prev_end = desc->physical_start + (desc->num_pages << 12);
if (prev_end == desc_next->physical_start)
{
desc->num_pages += desc_next->num_pages;
continue;
}
desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size);
grub_memcpy (desc, desc_next, desc_size);
}
mmap_end = ADD_MEMORY_DESCRIPTOR (desc, desc_size);
/* write to loongson memory map */
for (desc = mmap_buf;
desc < mmap_end;
desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size))
{
grub_efi_physical_address_t physical_start = grub_vtop ((void *) desc->physical_start);
grub_efi_physical_address_t physical_end = physical_start + (desc->num_pages << 12);
physical_start = ALIGN_UP (physical_start, 0x100000);
physical_end = ALIGN_DOWN (physical_end, 0x100000);
if (physical_start >= physical_end || (physical_end - physical_start) < 0x100000)
continue;
dst->map[dst->nr_map].node_id = (desc->physical_start >> 44) & 0xf;
dst->map[dst->nr_map].mem_type = (physical_end <= 0x10000000) ?
GRUB_EFI_LOONGSON_SYSTEM_RAM_LOW :
GRUB_EFI_LOONGSON_SYSTEM_RAM_HIGH;
dst->map[dst->nr_map].mem_start = physical_start;
dst->map[dst->nr_map].mem_size = (physical_end - physical_start) >> 20;
grub_dprintf ("loongson", "memory map %03u: 0x%016lx 0x%016lx @ %u\n",
dst->nr_map, physical_start, physical_end - physical_start,
dst->map[dst->nr_map].node_id);
dst->nr_map ++;
}
}
#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
#define SUB_MEMORY_DESCRIPTOR(desc, size) \
((grub_efi_memory_descriptor_t *) ((char *) (desc) - (size)))
void
grub_efi_loongson_alloc_boot_params (void)
{
grub_efi_memory_descriptor_t *mmap_buf;
grub_efi_memory_descriptor_t *mmap_end;
grub_efi_memory_descriptor_t *desc;
grub_efi_uintn_t mmap_size;
grub_efi_uintn_t desc_size;
grub_efi_physical_address_t address;
grub_efi_allocate_type_t type;
grub_efi_uintn_t pages;
grub_efi_status_t status;
grub_efi_boot_services_t *b;
int mm_status;
type = GRUB_EFI_ALLOCATE_ADDRESS;
pages = BYTES_TO_PAGES (loongson_boot_params_size + loongson_reset_code_size);
mmap_size = (1 << 12);
mmap_buf = grub_malloc (mmap_size);
if (!mmap_buf)
grub_fatal ("out of memory!");
mm_status = grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0);
if (mm_status == 0)
{
grub_free (mmap_buf);
mmap_size += desc_size * 32;
mmap_buf = grub_malloc (mmap_size);
if (!mmap_buf)
grub_fatal ("out of memory!");
mm_status = grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0);
}
if (mm_status < 0)
grub_fatal ("cannot get memory map!");
mmap_end = ADD_MEMORY_DESCRIPTOR (mmap_buf, mmap_size);
for (desc = SUB_MEMORY_DESCRIPTOR (mmap_end, desc_size);
desc >= mmap_buf;
desc = SUB_MEMORY_DESCRIPTOR (desc, desc_size))
{
if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY)
continue;
if (desc->physical_start >= GRUB_EFI_MAX_USABLE_ADDRESS)
continue;
if (desc->num_pages < pages)
continue;
address = desc->physical_start;
break;
}
grub_free (mmap_buf);
b = grub_efi_system_table->boot_services;
status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_RUNTIME_SERVICES_DATA, pages, &address);
if (status != GRUB_EFI_SUCCESS)
grub_fatal ("cannot allocate Loongson boot parameters!");
loongson_boot_params = (void *) ((grub_addr_t) address);
}
void
grub_efi_loongson_free_boot_params (void)
{
grub_efi_free_pages ((grub_addr_t) loongson_boot_params,
BYTES_TO_PAGES (loongson_boot_params_size + loongson_reset_code_size));
}
void *
grub_efi_loongson_get_smbios_table (void)
{
static grub_efi_loongson_smbios_table *smbios_table;
grub_efi_loongson_boot_params *old_boot_params;
struct bootparamsinterface* boot_params;
void * tmp_boot_params = NULL;
char * p = NULL;
if(smbios_table)
return smbios_table;
tmp_boot_params = grub_efi_loongson_get_boot_params();
if(tmp_boot_params == NULL)
{
grub_dprintf("loongson", "tmp_boot_params is NULL\n");
return tmp_boot_params;
}
boot_params = (struct bootparamsinterface *)tmp_boot_params;
p = (char *)&(boot_params->signature);
if(grub_strncmp(p, "BPI", 3) == 0)
{
grub_dprintf("loongson", "find new bpi\n");
return boot_params ? boot_params : 0;
}
else
{
old_boot_params = (grub_efi_loongson_boot_params *)tmp_boot_params;
return old_boot_params ? &old_boot_params->efi.smbios : 0;
}
}
int
grub_efi_is_loongson (void)
{
return grub_efi_loongson_get_smbios_table () ? 1 : 0;
}
void *
grub_efi_loongson_get_boot_params (void)
{
static void * boot_params = NULL;
grub_efi_configuration_table_t *tables;
grub_efi_guid_t smbios_guid = GRUB_EFI_LOONGSON_SMBIOS_TABLE_GUID;
unsigned int i;
if (boot_params)
return boot_params;
/* Look for Loongson SMBIOS in UEFI config tables. */
tables = grub_efi_system_table->configuration_table;
for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
if (grub_memcmp (&tables[i].vendor_guid, &smbios_guid, sizeof (smbios_guid)) == 0)
{
boot_params= tables[i].vendor_table;
grub_dprintf ("loongson", "found registered SMBIOS @ %p\n", boot_params);
break;
}
return boot_params;
}
grub_uint8_t
grub_efi_loongson_calculatesum8 (const grub_uint8_t *buffer, grub_efi_uintn_t length)
{
grub_uint8_t sum;
grub_efi_uintn_t count;
for (sum = 0, count = 0; count < length; count++)
{
sum = (grub_uint8_t) (sum + *(buffer + count));
}
return sum;
}
grub_uint8_t
grub_efi_loongson_grub_calculatechecksum8 (const grub_uint8_t *buffer, grub_efi_uintn_t length)
{
grub_uint8_t checksum;
checksum = grub_efi_loongson_calculatesum8(buffer, length);
return (grub_uint8_t) (0x100 - checksum);
}
grub_uint32_t
grub_efi_loongson_memmap_sort(struct memmap array[], grub_uint32_t length, mem_map * bpmem, grub_uint32_t index, grub_uint32_t memtype)
{
grub_uint64_t tempmemsize = 0;
grub_uint32_t j = 0;
grub_uint32_t t = 0;
for(j = 0; j < length;)
{
tempmemsize = array[j].memsize;
for(t = j + 1; t < length; t++)
{
if(array[j].memstart + tempmemsize == array[t].memstart)
{
tempmemsize += array[t].memsize;
}
else
{
break;
}
}
bpmem->map[index].memtype = memtype;
bpmem->map[index].memstart = array[j].memstart;
bpmem->map[index].memsize = tempmemsize;
grub_dprintf("loongson", "map[%d]:type %x, start 0x%llx, end 0x%llx\n",
index,
bpmem->map[index].memtype,
(unsigned long long)bpmem->map[index].memstart,
(unsigned long long)bpmem->map[index].memstart+ bpmem->map[index].memsize
);
j = t;
index++;
}
return index;
}
@@ -0,0 +1,61 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2017 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/symbol.h>
.file "loongson.S"
.text
.set push
.set noreorder
.align 4
VARIABLE (grub_efi_loongson_reset_start)
VARIABLE (grub_efi_loongson_reset_system_addr)
.dword 0
reset_system:
bal 1f
move $a1, $zero
1:
ld $t9, -16($ra)
move $a2, $zero
jalr $t9
move $a3, $zero
FUNCTION(grub_efi_loongson_reset_cold)
b reset_system
li $a0, 0
FUNCTION(grub_efi_loongson_reset_warm)
b reset_system
li $a0, 1
FUNCTION(grub_efi_loongson_reset_shutdown)
b reset_system
li $a0, 2
FUNCTION(grub_efi_loongson_reset_suspend)
b reset_system
li $a0, 3
VARIABLE (grub_efi_loongson_reset_end)
.set pop
@@ -0,0 +1,169 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2017 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/types.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/cache.h>
#include <grub/mips64/relocator.h>
#include <grub/relocator_private.h>
extern grub_uint8_t grub_relocator_forward_start;
extern grub_uint8_t grub_relocator_forward_end;
extern grub_uint8_t grub_relocator_backward_start;
extern grub_uint8_t grub_relocator_backward_end;
#define REGW_SIZEOF (6 * sizeof (grub_uint32_t))
#define JUMP_SIZEOF (2 * sizeof (grub_uint32_t))
#define RELOCATOR_SRC_SIZEOF(x) (&grub_relocator_##x##_end \
- &grub_relocator_##x##_start)
#define RELOCATOR_SIZEOF(x) (RELOCATOR_SRC_SIZEOF(x) \
+ REGW_SIZEOF * 3)
grub_size_t grub_relocator_align = sizeof (grub_uint64_t);
grub_size_t grub_relocator_forward_size;
grub_size_t grub_relocator_backward_size;
grub_size_t grub_relocator_jumper_size = JUMP_SIZEOF + REGW_SIZEOF;
void
grub_cpu_relocator_init (void)
{
grub_relocator_forward_size = RELOCATOR_SIZEOF(forward);
grub_relocator_backward_size = RELOCATOR_SIZEOF(backward);
}
static void
write_reg (int regn, grub_uint64_t val, void **target)
{
grub_uint32_t lui;
grub_uint32_t ori;
grub_uint32_t dsll;
/* lui $r, 0 */
lui = (0x3c00 | regn) << 16;
/* ori $r, $r, 0 */
ori = (0x3400 | (regn << 5) | regn) << 16;
/* dsll $r, $r, 16 */
dsll = (regn << 16) | (regn << 11) | (16 << 6) | 56;
/* lui $r, val[63:48]. */
*(grub_uint32_t *) *target = lui | (grub_uint16_t) (val >> 48);
*target = ((grub_uint32_t *) *target) + 1;
/* ori $r, val[47:32]. */
*(grub_uint32_t *) *target = ori | (grub_uint16_t) (val >> 32);
*target = ((grub_uint32_t *) *target) + 1;
/* dsll $r, $r, 16 */
*(grub_uint32_t *) *target = dsll;
*target = ((grub_uint32_t *) *target) + 1;
/* ori $r, val[31:16]. */
*(grub_uint32_t *) *target = ori | (grub_uint16_t) (val >> 16);
*target = ((grub_uint32_t *) *target) + 1;
/* dsll $r, $r, 16 */
*(grub_uint32_t *) *target = dsll;
*target = ((grub_uint32_t *) *target) + 1;
/* ori $r, val[15:0]. */
*(grub_uint32_t *) *target = ori | (grub_uint16_t) val;
*target = ((grub_uint32_t *) *target) + 1;
}
static void
write_jump (int regn, void **target)
{
/* j $r. */
*(grub_uint32_t *) *target = (regn << 21) | 0x8;
*target = ((grub_uint32_t *) *target) + 1;
/* nop. */
*(grub_uint32_t *) *target = 0;
*target = ((grub_uint32_t *) *target) + 1;
}
void
grub_cpu_relocator_jumper (void *rels, grub_addr_t addr)
{
write_reg (1, addr, &rels);
write_jump (1, &rels);
}
void
grub_cpu_relocator_backward (void *ptr0, void *src, void *dest,
grub_size_t size)
{
void *ptr = ptr0;
write_reg (8, (grub_uint64_t) src, &ptr);
write_reg (9, (grub_uint64_t) dest, &ptr);
write_reg (10, (grub_uint64_t) size, &ptr);
grub_memcpy (ptr, &grub_relocator_backward_start,
RELOCATOR_SRC_SIZEOF (backward));
}
void
grub_cpu_relocator_forward (void *ptr0, void *src, void *dest,
grub_size_t size)
{
void *ptr = ptr0;
write_reg (8, (grub_uint64_t) src, &ptr);
write_reg (9, (grub_uint64_t) dest, &ptr);
write_reg (10, (grub_uint64_t) size, &ptr);
grub_memcpy (ptr, &grub_relocator_forward_start,
RELOCATOR_SRC_SIZEOF (forward));
}
grub_err_t
grub_relocator64_boot (struct grub_relocator *rel,
struct grub_relocator64_state state)
{
grub_relocator_chunk_t ch;
void *ptr;
grub_err_t err;
void *relst;
grub_size_t relsize;
grub_size_t stateset_size = 31 * REGW_SIZEOF + JUMP_SIZEOF;
unsigned i;
grub_addr_t vtarget;
err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
(0xffffffff - stateset_size)
+ 1, stateset_size,
grub_relocator_align,
GRUB_RELOCATOR_PREFERENCE_NONE, 0);
if (err)
return err;
ptr = get_virtual_current_address (ch);
for (i = 1; i < 32; i++)
write_reg (i, state.gpr[i], &ptr);
write_jump (state.jumpreg, &ptr);
vtarget = (grub_addr_t) grub_map_memory (get_physical_target_address (ch),
stateset_size);
err = grub_relocator_prepare_relocs (rel, vtarget, &relst, &relsize);
if (err)
return err;
grub_arch_sync_caches ((void *) relst, relsize);
((void (*) (void)) relst) ();
/* Not reached. */
return GRUB_ERR_NONE;
}
@@ -0,0 +1,56 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2017 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/symbol.h>
.p2align 4 /* force 16-byte alignment */
.set push
.set noreorder
.set nomacro
VARIABLE (grub_relocator_forward_start)
copycont1:
ld $11,0($8)
sd $11,0($9)
daddiu $8, $8, 8
daddiu $10, $10, -8
bne $10, $0, copycont1
daddiu $9, $9, 8
VARIABLE (grub_relocator_forward_end)
VARIABLE (grub_relocator_backward_start)
daddu $9, $9, $10
daddu $8, $8, $10
/* Backward movsl is implicitly off-by-one. compensate that. */
daddiu $9, $9, -8
daddiu $8, $8, -8
copycont2:
ld $11,0($8)
sd $11,0($9)
daddiu $8, $8, -8
daddiu $10, $10, -8
bne $10, $0, copycont2
daddiu $9, $9, -8
VARIABLE (grub_relocator_backward_end)
.set pop
@@ -0,0 +1,69 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,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 <http://www.gnu.org/licenses/>.
*/
#include <grub/symbol.h>
#include <grub/dl.h>
#include <grub/mips64/asm.h>
.file "setjmp.S"
GRUB_MOD_LICENSE "GPLv3+"
.text
/*
* int grub_setjmp (grub_jmp_buf env)
*/
FUNCTION(grub_setjmp)
GRUB_ASM_REG_S $s0, 0($a0)
GRUB_ASM_REG_S $s1, 8($a0)
GRUB_ASM_REG_S $s2, 16($a0)
GRUB_ASM_REG_S $s3, 24($a0)
GRUB_ASM_REG_S $s4, 32($a0)
GRUB_ASM_REG_S $s5, 40($a0)
GRUB_ASM_REG_S $s6, 48($a0)
GRUB_ASM_REG_S $s7, 56($a0)
GRUB_ASM_REG_S $s8, 64($a0)
GRUB_ASM_REG_S $gp, 72($a0)
GRUB_ASM_REG_S $sp, 80($a0)
GRUB_ASM_REG_S $ra, 88($a0)
move $v0, $zero
move $v1, $zero
jr $ra
nop
/*
* int grub_longjmp (grub_jmp_buf env, int val)
*/
FUNCTION(grub_longjmp)
GRUB_ASM_REG_L $s0, 0($a0)
GRUB_ASM_REG_L $s1, 8($a0)
GRUB_ASM_REG_L $s2, 16($a0)
GRUB_ASM_REG_L $s3, 24($a0)
GRUB_ASM_REG_L $s4, 32($a0)
GRUB_ASM_REG_L $s5, 40($a0)
GRUB_ASM_REG_L $s6, 48($a0)
GRUB_ASM_REG_L $s7, 56($a0)
GRUB_ASM_REG_L $s8, 64($a0)
GRUB_ASM_REG_L $gp, 72($a0)
GRUB_ASM_REG_L $sp, 80($a0)
GRUB_ASM_REG_L $ra, 88($a0)
addiu $v0, $zero, 1
movn $v0, $a1, $a1
move $v1, $zero
jr $ra
nop
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,26 @@
#if defined(__i386__)
#include "./i386/setjmp.S"
#elif defined(__x86_64__)
#include "./x86_64/setjmp.S"
#elif defined(__sparc__)
#include "./sparc64/setjmp.S"
#elif defined(__mips__)
#if _MIPS_SIM == _ABI64
#include "./mips64/setjmp.S"
#else
#include "./mips/setjmp.S"
#endif
#elif defined(__powerpc__) || defined(__PPC__)
#include "./powerpc/setjmp.S"
#elif defined(__ia64__)
#include "./ia64/setjmp.S"
#include "./ia64/longjmp.S"
#elif defined(__arm__)
#include "./arm/setjmp.S"
#elif defined(__aarch64__)
#include "./arm64/setjmp.S"
#elif defined(__riscv)
#include "./riscv/setjmp.S"
#else
#error "Unknown target cpu type"
#endif
File diff suppressed because it is too large Load Diff