加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
loongarch-Add-support-for-v4.0-interface.patch 15.45 KB
一键复制 编辑 原始数据 按行查看 历史
From d984a64ff93443630fde3211e1a8ec42d92a6b56 Mon Sep 17 00:00:00 2001
From: mengyingkun <mengyingkun@loongson.cn>
Date: Mon, 13 Feb 2023 14:40:16 +0800
Subject: [PATCH] loongarch: Add support for v4.0 interface
This patch adds support for parameter passing converntion
between bootloader and kernel, defined in the document
"loongson devsys firmware kernel interface specification v4.0"
Signed-off-by: yangqiming <yangqiming@loongson.cn>
Signed-off-by: mengyingkun <mengyingkun@loongson.cn>
---
grub-core/lib/loongarch64/relocator.c | 2 +-
grub-core/loader/loongarch64/linux-elf.c | 177 ++++++++++++++++++++---
grub-core/loader/loongarch64/linux.c | 49 ++-----
include/grub/loongarch64/linux.h | 20 +++
4 files changed, 190 insertions(+), 58 deletions(-)
diff --git a/grub-core/lib/loongarch64/relocator.c b/grub-core/lib/loongarch64/relocator.c
index faa4553..587fc58 100644
--- a/grub-core/lib/loongarch64/relocator.c
+++ b/grub-core/lib/loongarch64/relocator.c
@@ -122,7 +122,7 @@ grub_relocator64_boot (struct grub_relocator *rel,
unsigned i;
grub_addr_t vtarget;
- err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
+ err = grub_relocator_alloc_chunk_align (rel, &ch, 0x3000000,
(0xffffffff - stateset_size)
+ 1, stateset_size,
grub_relocator_align,
diff --git a/grub-core/loader/loongarch64/linux-elf.c b/grub-core/loader/loongarch64/linux-elf.c
index 852e8f4..15f9984 100644
--- a/grub-core/loader/loongarch64/linux-elf.c
+++ b/grub-core/loader/loongarch64/linux-elf.c
@@ -25,11 +25,14 @@
#include <grub/efi/memory.h>
#include <grub/efi/graphics_output.h>
+#define GRUB_EFI_MMAP_NR_SLACK_SLOTS 8
+
#define GRUB_ADDRESS_TYPE_SYSRAM 1
#define GRUB_ADDRESS_TYPE_RESERVED 2
#define GRUB_ADDRESS_TYPE_ACPI 3
#define GRUB_ADDRESS_TYPE_NVS 4
#define GRUB_ADDRESS_TYPE_PMEM 5
+
#define GRUB_EFI_LOONGSON_BPI_TABLE_GUID \
{ 0x4660f721, 0x2ec5, 0x416a, \
{ 0x89, 0x9a, 0x43, 0x18, 0x02, 0x50, 0xa0, 0xc9 } \
@@ -45,6 +48,16 @@
{ 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
}
+#define GRUB_EFI_LARCH_BOOT_MEMMAP_GUID \
+ { 0x800f683f, 0xd08b, 0x423a, \
+ { 0xa2, 0x93, 0x96, 0x5c, 0x3c, 0x6f, 0xe2, 0xb4 } \
+ }
+
+#define GRUB_EFI_LARCH_INITRD_MEDIA_GUID \
+ { 0x5568e427, 0x68fc, 0x4f3d, \
+ { 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68 } \
+ }
+
static struct grub_relocator *relocator;
static grub_efi_guid_t screen_info_guid = GRUB_EFI_LARCH_SCREEN_INFO_GUID;
@@ -271,6 +284,135 @@ free_screen_info:
return NULL;
}
+static grub_err_t
+allocate_memmap_and_exit_boot (struct linux_loongarch64_kernel_params *kernel_params)
+{
+ grub_err_t err;
+ grub_efi_status_t status;
+ grub_efi_uintn_t mmap_size, desc_size, size;
+ grub_efi_uint32_t desc_version;
+ grub_efi_memory_descriptor_t *mmap_buf;
+ grub_efi_boot_services_t *b;
+ struct efi_boot_memmap *m, tmp;
+ struct efi_initrd *tbl = NULL;
+ grub_efi_guid_t boot_memmap_guid = GRUB_EFI_LARCH_BOOT_MEMMAP_GUID;
+ grub_efi_guid_t initrd_media_guid = GRUB_EFI_LARCH_INITRD_MEDIA_GUID;
+
+ setup_screen_info();
+
+ b = grub_efi_system_table->boot_services;
+
+ grub_dprintf ("loongson", "ramdisk_addr:0x%"PRIxGRUB_UINT64_T", \
+ size:0x%"PRIxGRUB_UINT64_T"\n",
+ kernel_params->ramdisk_addr,
+ kernel_params->ramdisk_size);
+#if 0
+ char string[64];
+
+ /* Set initrd info to cmdline*/
+ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size)
+ {
+ grub_printf ( "Initrd @ %p-%p\n",
+ (void *) kernel_params->ramdisk_addr,
+ (void *) (kernel_params->ramdisk_addr + kernel_params->ramdisk_size));
+ /* initrd */
+ grub_snprintf (string,
+ sizeof (GRUB_INITRD_STRING),
+ "initrd=0x%lx,0x%lx",
+ ((grub_uint64_t) kernel_params->ramdisk_addr & 0xffffffff),
+ (grub_uint64_t) kernel_params->ramdisk_size);
+ *(char*) ((grub_addr_t) kernel_params->linux_args + kernel_params->ramdisk_args_len - 2) = ' ';
+ grub_memcpy ((char*) ((grub_addr_t) kernel_params->linux_args + kernel_params->ramdisk_args_len - 1),
+ string, sizeof (GRUB_INITRD_STRING));
+ }
+#else
+ /* Set initrd info to system table*/
+ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size)
+ {
+ tbl = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (sizeof(struct efi_initrd)));
+ if (!tbl)
+ return grub_error (GRUB_ERR_IO, "cannot allocate tbl memory");
+ tbl->base = kernel_params->ramdisk_addr;
+ tbl->size = kernel_params->ramdisk_size;
+
+ status = b->install_configuration_table (&initrd_media_guid, tbl);
+ if (status != GRUB_EFI_SUCCESS) {
+ grub_error (GRUB_ERR_IO, "failed to install initrd media");
+ goto free_tbl;
+ }
+ }
+#endif
+
+ tmp.map_size = 0;
+ status = grub_efi_get_memory_map (&tmp.map_size, NULL, &tmp.map_key,
+ &tmp.desc_size, &tmp.desc_ver);
+ if (status != 0) {
+ grub_error (GRUB_ERR_IO, "cannot get memory map");
+ goto uninstall_initrd_table;
+ }
+ size = tmp.map_size + tmp.desc_size * GRUB_EFI_MMAP_NR_SLACK_SLOTS;
+ m = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (sizeof(*m) + size));
+ if (!m) {
+ grub_error (GRUB_ERR_IO, "cannot allocate m memory");
+ goto uninstall_initrd_table;
+ }
+
+ status = b->install_configuration_table (&boot_memmap_guid, m);
+ if (status != GRUB_EFI_SUCCESS) {
+ grub_error (GRUB_ERR_IO, "failed to install boot memmap");
+ goto free_m;
+ }
+
+ m->buff_size = m->map_size = size;
+ if (grub_efi_get_memory_map (&m->map_size, m->map,
+ &m->map_key, &m->desc_size,
+ &m->desc_ver) <= 0)
+ {
+ grub_error (GRUB_ERR_IO, "cannot get EFI memory map");
+ goto uninstall_mem_table;
+ }
+
+ mmap_size = grub_efi_find_mmap_size ();
+ if (! mmap_size)
+ goto uninstall_mem_table;
+
+ mmap_buf = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (mmap_size));
+ err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, NULL,
+ &desc_size, &desc_version);
+ if (err) {
+ grub_error (GRUB_ERR_IO, "failed to finish boot services");
+ goto free_map;
+ }
+
+ return 0;
+
+free_map:
+ if (mmap_buf)
+ grub_efi_free_pages ((grub_addr_t) mmap_buf,
+ GRUB_EFI_BYTES_TO_PAGES (mmap_size));
+
+uninstall_mem_table:
+ b->install_configuration_table (&boot_memmap_guid, NULL);
+
+free_m:
+ if (m)
+ grub_efi_free_pages ((grub_addr_t) m,
+ GRUB_EFI_BYTES_TO_PAGES (sizeof(*m) + size));
+
+uninstall_initrd_table:
+ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size)
+ b->install_configuration_table (&initrd_media_guid, NULL);
+
+free_tbl:
+ if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size) {
+ if (tbl)
+ grub_efi_free_pages ((grub_addr_t) tbl,
+ GRUB_EFI_BYTES_TO_PAGES (sizeof(struct efi_initrd)));
+ }
+
+ return grub_error(GRUB_ERR_BAD_OS, "failed to V40 boot");
+}
+
static grub_err_t
allocate_fdt_and_exit_boot (struct linux_loongarch64_kernel_params *kernel_params)
{
@@ -400,12 +542,11 @@ grub_linux_loongarch_elf_make_argv (struct linux_loongarch64_kernel_params *kern
}
if (kernel_params->ramdisk_addr && kernel_params->ramdisk_size)
- {
- size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4) \
- + ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4) \
- + ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"),
- 4);
- }
+ {
+ size += ALIGN_UP (sizeof (GRUB_RD_START_STRING), 4)
+ + ALIGN_UP (sizeof (GRUB_RD_SIZE_STRING), 4)
+ + ALIGN_UP (sizeof (GRUB_INITRD_STRING), 4);
+ }
size = ALIGN_UP (size, 8);
/* alloc memory */
@@ -427,33 +568,33 @@ grub_linux_loongarch_elf_make_argv (struct linux_loongarch64_kernel_params *kern
{
/* rd_start */
grub_snprintf (linux_args,
- sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"),
+ sizeof (GRUB_RD_START_STRING),
"rd_start=0x%lx",
(grub_uint64_t) kernel_params->ramdisk_addr);
*linux_argv = (grub_uint64_t) (grub_addr_t) linux_args;
linux_argv++;
- linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4);
+ linux_args += ALIGN_UP (sizeof (GRUB_RD_START_STRING), 4);
kernel_params->linux_argc++;
/* rd_size */
grub_snprintf (linux_args,
- sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"),
+ sizeof (GRUB_RD_SIZE_STRING),
"rd_size=0x%lx",
(grub_uint64_t) kernel_params->ramdisk_size);
*linux_argv = (grub_uint64_t) (grub_addr_t) linux_args;
linux_argv++;
- linux_args += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4);
+ linux_args += ALIGN_UP (sizeof (GRUB_RD_SIZE_STRING), 4);
kernel_params->linux_argc++;
/* initrd */
grub_snprintf (linux_args,
- sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"),
+ sizeof (GRUB_INITRD_STRING),
"initrd=0x%lx,0x%lx",
((grub_uint64_t) kernel_params->ramdisk_addr & 0xffffffff),
(grub_uint64_t) kernel_params->ramdisk_size);
*linux_argv = (grub_uint64_t) (grub_addr_t) linux_args;
linux_argv++;
- linux_args += ALIGN_UP (sizeof ("initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"), 4);
+ linux_args += ALIGN_UP (sizeof (GRUB_INITRD_STRING), 4);
kernel_params->linux_argc++;
}
@@ -472,8 +613,6 @@ grub_linux_loongarch_elf_linux_boot_image (struct linux_loongarch64_kernel_param
struct grub_relocator64_state state;
grub_err_t err;
- setup_screen_info ();
-
/* linux kernel type is ELF */
grub_memset (&state, 0, sizeof (state));
@@ -481,14 +620,14 @@ grub_linux_loongarch_elf_linux_boot_image (struct linux_loongarch64_kernel_param
state.gpr[1] = kernel_params->kernel_addr; /* ra */
if (grub_linux_loongarch_elf_get_boot_params (&boot_params) == 0)
{
- grub_printf("not find param, is fdt boot\n");
- if (allocate_fdt_and_exit_boot (kernel_params) != GRUB_ERR_NONE)
+ grub_dprintf("loongson", "V4.0 boot\n");
+ if (allocate_memmap_and_exit_boot (kernel_params) != GRUB_ERR_NONE)
return grub_errno;
state.gpr[4] = 1 << FLAGS_EFI_SUPPORT_BIT; /* a0 = flag */
- state.gpr[5] = (grub_uint64_t)kernel_params->fdt; /* a1 = fdt */
- state.gpr[6] = 0; /* a2 = flag */
+ state.gpr[5] = (grub_uint64_t)kernel_params->linux_args; /* a1 = cmdline */
+ state.gpr[6] = (grub_uint64_t)grub_efi_system_table; /* a2 = system_table */
} else {
- grub_printf("find param, is bpi boot\n");
+ grub_dprintf("loongson", "BPI boot\n");
grub_linux_loongarch_elf_make_argv (kernel_params);
state.gpr[4] = kernel_params->linux_argc; /* a0 = argc */
state.gpr[5] = kernel_params->linux_argv; /* a1 = args */
diff --git a/grub-core/loader/loongarch64/linux.c b/grub-core/loader/loongarch64/linux.c
index 4c02194..03b7940 100644
--- a/grub-core/loader/loongarch64/linux.c
+++ b/grub-core/loader/loongarch64/linux.c
@@ -230,7 +230,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("linux", "kernel @ %p\n", (void*) kernel_params.kernel_addr);
}
- cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
+ cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE)
+ + sizeof (GRUB_INITRD_STRING);
+ kernel_params.ramdisk_args_len = grub_loader_cmdline_size (argc, argv)
+ + sizeof (LINUX_IMAGE);
kernel_params.linux_argc = argc;
kernel_params.linux_args = grub_malloc (cmdline_size);
if (!kernel_params.linux_args)
@@ -250,7 +253,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
{
err = grub_create_loader_cmdline (argc, argv,
(char*) ((grub_addr_t) kernel_params.linux_args + sizeof (LINUX_IMAGE) - 1),
- cmdline_size,
+ kernel_params.ramdisk_args_len,
GRUB_VERIFY_KERNEL_CMDLINE);
if (err)
goto fail;
@@ -299,26 +302,6 @@ fail:
return grub_errno;
}
-/*
- * This function returns a pointer to a legally allocated initrd buffer,
- * or NULL if unsuccessful
- */
-static void *
-allocate_initrd_mem (int initrd_pages)
-{
- grub_addr_t max_addr;
-
- if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE)
- return NULL;
-
- max_addr += INITRD_MAX_ADDRESS_OFFSET - 1;
-
- return grub_efi_allocate_pages_real (max_addr, initrd_pages,
- GRUB_EFI_ALLOCATE_MAX_ADDRESS,
- GRUB_EFI_LOADER_DATA);
-}
-
-
static grub_err_t
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
@@ -326,6 +309,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
grub_size_t initrd_size;
void *initrd_mem = NULL;
+ grub_err_t err;
if (argc == 0)
{
@@ -345,16 +329,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
initrd_size = grub_get_initrd_size (&initrd_ctx);
grub_dprintf ("linux", "Loading initrd\n");
- if (is_bpi_boot == 0) {
- grub_size_t initrd_pages;
- initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size));
- initrd_mem = allocate_initrd_mem (initrd_pages);
- } else {
- grub_err_t err;
- initrd_mem = grub_linux_loongarch_alloc_initrd_mem_align (initrd_size, 0x10000, &err);
- if (err)
- goto fail;
- }
+ initrd_mem = grub_linux_loongarch_alloc_initrd_mem_align (initrd_size, 0x1000, &err);
+ if (err)
+ goto fail;
if (!initrd_mem)
{
@@ -369,14 +346,10 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
kernel_params.ramdisk_addr = (grub_addr_t) initrd_mem;
kernel_params.ramdisk_size = initrd_size;
grub_dprintf ("linux", "ramdisk [addr=%p, size=0x%lx]\n",
- (void *) initrd_mem, initrd_size);
+ (void *) initrd_mem, initrd_size);
fail:
grub_initrd_close (&initrd_ctx);
- if (is_bpi_boot == 0) {
- if (initrd_mem && !kernel_params.ramdisk_addr)
- grub_efi_free_pages ((grub_addr_t) initrd_mem,
- GRUB_EFI_BYTES_TO_PAGES (initrd_size));
- }
+
return grub_errno;
}
diff --git a/include/grub/loongarch64/linux.h b/include/grub/loongarch64/linux.h
index c010982..f20a719 100644
--- a/include/grub/loongarch64/linux.h
+++ b/include/grub/loongarch64/linux.h
@@ -59,6 +59,7 @@ struct linux_loongarch64_kernel_params
grub_size_t kernel_size; /* kernel size */
grub_addr_t ramdisk_addr; /* initrd load address */
grub_size_t ramdisk_size; /* initrd size */
+ int ramdisk_args_len; /* position of initrd in linux_args */
int linux_argc; /* cmdline parameters number*/
grub_addr_t linux_argv; /* cmdline parameters address*/
void* linux_args;
@@ -73,12 +74,31 @@ struct linux_loongarch64_kernel_params
#define ELF64_LOADMASK (0xf000000000000000ULL)
#define FLAGS_EFI_SUPPORT_BIT 0
+/*initrd info*/
+#define GRUB_RD_START_STRING "rd_start=0xXXXXXXXXXXXXXXXX"
+#define GRUB_RD_SIZE_STRING "rd_size=0xXXXXXXXXXXXXXXXX"
+#define GRUB_INITRD_STRING "initrd=0xXXXXXXXXXXXXXXXX,0xXXXXXXXXXXXXXXXX"
+
#define FDT_ADDR_CELLS_STRING "#address-cells"
#define FDT_SIZE_CELLS_STRING "#size-cells"
#define FDT_ADDR_SIZE_EXTRA ((2 * grub_fdt_prop_entry_size (sizeof(grub_uint32_t))) + \
sizeof (FDT_ADDR_CELLS_STRING) + \
sizeof (FDT_SIZE_CELLS_STRING))
+struct efi_boot_memmap {
+ grub_efi_uintn_t map_size;
+ grub_efi_uintn_t desc_size;
+ grub_efi_uint32_t desc_ver;
+ grub_efi_uintn_t map_key;
+ grub_efi_uintn_t buff_size;
+ grub_efi_memory_descriptor_t map[];
+};
+
+struct efi_initrd {
+ grub_efi_uintn_t base;
+ grub_efi_uintn_t size;
+};
+
/*
* These are set up by the setup-routine at boot-time:
*/
--
2.33.0
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化