Create your Gitee Account
Explore and code with more than 12 million developers,Free private repositories !:)
Sign up
文件
This repository doesn't specify license. Please pay attention to the specific project description and its upstream code dependency when using it.
Clone or Download
1002-loongarch-Add-EFI-frame-buffer-support.patch 10.21 KB
Copy Edit Raw Blame History
From 1ebd229556ba767f76c829b6d00d8a7b5bf28e65 Mon Sep 17 00:00:00 2001
From: mengyingkun <mengyingkun@loongson.cn>
Date: Wed, 8 Feb 2023 09:24:05 +0800
Subject: [PATCH] loongarch: Add EFI frame buffer support
Signed-off-by: yangqiming <yangqiming@loongson.cn>
Signed-off-by: mengyingkun <mengyingkun@loongson.cn>
---
grub-core/loader/loongarch64/linux-elf.c | 232 +++++++++++++++++++++++
include/grub/loongarch64/linux.h | 47 +++++
2 files changed, 279 insertions(+)
diff --git a/grub-core/loader/loongarch64/linux-elf.c b/grub-core/loader/loongarch64/linux-elf.c
index 8260e4c..852e8f4 100644
--- a/grub-core/loader/loongarch64/linux-elf.c
+++ b/grub-core/loader/loongarch64/linux-elf.c
@@ -23,6 +23,7 @@
#include <grub/elfload.h>
#include <grub/cpu/relocator.h>
#include <grub/efi/memory.h>
+#include <grub/efi/graphics_output.h>
#define GRUB_ADDRESS_TYPE_SYSRAM 1
#define GRUB_ADDRESS_TYPE_RESERVED 2
@@ -34,13 +35,242 @@
{ 0x89, 0x9a, 0x43, 0x18, 0x02, 0x50, 0xa0, 0xc9 } \
}
+#define GRUB_EFI_LARCH_SCREEN_INFO_GUID \
+ { 0x07fd51a6, 0x9532, 0x926f, \
+ { 0x51, 0xdc, 0x6a, 0x63, 0x60, 0x2f, 0x84, 0xb4 } \
+ }
+
+#define GRUB_EFI_LARCH_CONSOLE_OUT_DEVICE_GUID \
+ { 0xd3b36f2c, 0xd551, 0x11d4, \
+ { 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+ }
+
static struct grub_relocator *relocator;
+static grub_efi_guid_t screen_info_guid = GRUB_EFI_LARCH_SCREEN_INFO_GUID;
void grub_linux_loongarch_elf_relocator_unload (void)
{
grub_relocator_unload (relocator);
}
+static void
+find_bits (unsigned long mask, grub_efi_uint8_t *pos, grub_efi_uint8_t *size)
+{
+ grub_efi_uint8_t first, len;
+
+ first = 0;
+ len = 0;
+
+ if (mask)
+ {
+ while (!(mask & 0x1))
+ {
+ mask = mask >> 1;
+ first++;
+ }
+
+ while (mask & 0x1)
+ {
+ mask = mask >> 1;
+ len++;
+ }
+ }
+
+ *pos = first;
+ *size = len;
+}
+
+static void
+setup_pixel_info (struct screen_info *si, grub_efi_uint32_t pixels_per_scan_line,
+ struct grub_efi_gop_pixel_bitmask pixel_info, int pixel_format)
+{
+ if (pixel_format == GRUB_EFI_GOT_RGBA8)
+ {
+ si->lfb_depth = 32;
+ si->lfb_linelength = pixels_per_scan_line * 4;
+ si->red_size = 8;
+ si->red_pos = 0;
+ si->green_size = 8;
+ si->green_pos = 8;
+ si->blue_size = 8;
+ si->blue_pos = 16;
+ si->rsvd_size = 8;
+ si->rsvd_pos = 24;
+ }
+ else if (pixel_format == GRUB_EFI_GOT_BGRA8)
+ {
+ si->lfb_depth = 32;
+ si->lfb_linelength = pixels_per_scan_line * 4;
+ si->red_size = 8;
+ si->red_pos = 16;
+ si->green_size = 8;
+ si->green_pos = 8;
+ si->blue_size = 8;
+ si->blue_pos = 0;
+ si->rsvd_size = 8;
+ si->rsvd_pos = 24;
+ }
+ else if (pixel_format == GRUB_EFI_GOT_BITMASK)
+ {
+ find_bits(pixel_info.r, &si->red_pos, &si->red_size);
+ find_bits(pixel_info.g, &si->green_pos, &si->green_size);
+ find_bits(pixel_info.b, &si->blue_pos, &si->blue_size);
+ find_bits(pixel_info.a, &si->rsvd_pos, &si->rsvd_size);
+ si->lfb_depth = si->red_size + si->green_size +
+ si->blue_size + si->rsvd_size;
+ si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8;
+ }
+ else
+ {
+ si->lfb_depth = 4;
+ si->lfb_linelength = si->lfb_width / 2;
+ si->red_size = 0;
+ si->red_pos = 0;
+ si->green_size = 0;
+ si->green_pos = 0;
+ si->blue_size = 0;
+ si->blue_pos = 0;
+ si->rsvd_size = 0;
+ si->rsvd_pos = 0;
+ }
+}
+
+static struct screen_info *
+alloc_screen_info (void)
+{
+ grub_efi_status_t status;
+ grub_efi_boot_services_t *b;
+ struct screen_info *si;
+
+ b = grub_efi_system_table->boot_services;
+ status = efi_call_3 (b->allocate_pool, GRUB_EFI_RUNTIME_SERVICES_DATA,
+ sizeof(*si), (void**)&si);
+ if (status != GRUB_EFI_SUCCESS)
+ return NULL;
+
+ status = b->install_configuration_table (&screen_info_guid, si);
+ if (status == GRUB_EFI_SUCCESS)
+ return si;
+
+ efi_call_1 (b->free_pool, si);
+
+ return NULL;
+}
+
+static struct screen_info *
+setup_screen_info (void)
+{
+ grub_efi_boot_services_t *b;
+ grub_efi_handle_t gop_handle;
+ struct screen_info *si = NULL;
+ struct grub_efi_gop *gop, *first_gop;
+ grub_efi_handle_t *handles;
+ grub_efi_uintn_t num_handles, i;
+ grub_efi_guid_t graphics_output_guid = GRUB_EFI_GOP_GUID;
+ grub_efi_uint16_t width, height;
+ grub_efi_uint32_t ext_lfb_base, pixels_per_scan_line;
+ grub_efi_uint64_t fb_base;
+ struct grub_efi_gop_pixel_bitmask pixel_info;
+ grub_efi_gop_pixel_format_t pixel_format;
+
+ si = alloc_screen_info();
+ if (!si)
+ return NULL;
+
+ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL,
+ &graphics_output_guid, NULL, &num_handles);
+ if (!handles || num_handles == 0)
+ goto free_screen_info;
+
+ gop = NULL;
+ first_gop = NULL;
+
+ for (i = 0; i < num_handles; i++)
+ {
+ struct grub_efi_gop_mode *mode;
+ struct grub_efi_gop_mode_info *info = NULL;
+ grub_efi_guid_t conout_proto = GRUB_EFI_LARCH_CONSOLE_OUT_DEVICE_GUID;
+ void *dummy = NULL;
+ grub_efi_uint8_t conout_found = 0;
+ grub_efi_uint64_t current_fb_base;
+
+ gop_handle = handles[i];
+ gop = grub_efi_open_protocol (gop_handle, &graphics_output_guid,
+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ dummy = grub_efi_open_protocol (gop_handle, &conout_proto,
+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (dummy != NULL)
+ conout_found = 1;
+
+ mode = gop->mode;
+ info = mode->info;
+ current_fb_base = mode->fb_base;
+
+ if ((!first_gop || conout_found) &&
+ info->pixel_format != GRUB_EFI_GOT_BLT_ONLY)
+ {
+ /*
+ * Systems that use the UEFI Console Splitter may
+ * provide multiple GOP devices, not all of which are
+ * backed by real hardware. The workaround is to search
+ * for a GOP implementing the ConOut protocol, and if
+ * one isn't found, to just fall back to the first GOP.
+ */
+ width = info->width;
+ height = info->height;
+ pixel_format = info->pixel_format;
+ pixel_info = info->pixel_bitmask;
+ pixels_per_scan_line = info->pixels_per_scanline;
+ fb_base = current_fb_base;
+
+ /*
+ * Once we've found a GOP supporting ConOut,
+ * don't bother looking any further.
+ */
+ first_gop = gop;
+ if (conout_found)
+ break;
+ }
+ }
+
+ /* Did we find any GOPs? */
+ if (!first_gop)
+ goto free_screen_info;
+
+ /* EFI framebuffer */
+ si->orig_video_isVGA = GRUB_VIDEO_TYPE_EFI;
+
+ si->lfb_width = width;
+ si->lfb_height = height;
+ si->lfb_base = fb_base;
+ grub_dprintf ("loongson", "Screen info fb base: 0x%"PRIxGRUB_UINT32_T"\n",
+ si->lfb_base);
+
+ ext_lfb_base = (grub_uint64_t)fb_base >> 32;
+ if (ext_lfb_base) {
+ si->capabilities |= GRUB_VIDEO_CAPABILITY_64BIT_BASE;
+ si->ext_lfb_base = ext_lfb_base;
+ }
+ si->pages = 1;
+
+ setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
+
+ si->lfb_size = si->lfb_linelength * si->lfb_height;
+ si->capabilities |= GRUB_VIDEO_CAPABILITY_SKIP_QUIRKS;
+
+ return si;
+
+free_screen_info:
+ b = grub_efi_system_table->boot_services;
+ b->install_configuration_table (&screen_info_guid, NULL);
+ if (si)
+ efi_call_1 (b->free_pool, si);
+
+ grub_dprintf ("loongson", "No screen info\n");
+ return NULL;
+}
+
static grub_err_t
allocate_fdt_and_exit_boot (struct linux_loongarch64_kernel_params *kernel_params)
{
@@ -242,6 +472,8 @@ 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));
diff --git a/include/grub/loongarch64/linux.h b/include/grub/loongarch64/linux.h
index f4b198a..c010982 100644
--- a/include/grub/loongarch64/linux.h
+++ b/include/grub/loongarch64/linux.h
@@ -79,6 +79,53 @@ struct linux_loongarch64_kernel_params
sizeof (FDT_ADDR_CELLS_STRING) + \
sizeof (FDT_SIZE_CELLS_STRING))
+/*
+ * These are set up by the setup-routine at boot-time:
+ */
+struct screen_info {
+ grub_efi_uint8_t orig_x; /* 0x00 */
+ grub_efi_uint8_t orig_y; /* 0x01 */
+ grub_efi_uint16_t ext_mem_k; /* 0x02 */
+ grub_efi_uint16_t orig_video_page; /* 0x04 */
+ grub_efi_uint8_t orig_video_mode; /* 0x06 */
+ grub_efi_uint8_t orig_video_cols; /* 0x07 */
+ grub_efi_uint8_t flags; /* 0x08 */
+ grub_efi_uint8_t unused2; /* 0x09 */
+ grub_efi_uint16_t orig_video_ega_bx;/* 0x0a */
+ grub_efi_uint16_t unused3; /* 0x0c */
+ grub_efi_uint8_t orig_video_lines; /* 0x0e */
+ grub_efi_uint8_t orig_video_isVGA; /* 0x0f */
+ grub_efi_uint16_t orig_video_points;/* 0x10 */
+
+ /* VESA graphic mode -- linear frame buffer */
+ grub_efi_uint16_t lfb_width; /* 0x12 */
+ grub_efi_uint16_t lfb_height; /* 0x14 */
+ grub_efi_uint16_t lfb_depth; /* 0x16 */
+ grub_efi_uint32_t lfb_base; /* 0x18 */
+ grub_efi_uint32_t lfb_size; /* 0x1c */
+ grub_efi_uint16_t cl_magic, cl_offset; /* 0x20 */
+ grub_efi_uint16_t lfb_linelength; /* 0x24 */
+ grub_efi_uint8_t red_size; /* 0x26 */
+ grub_efi_uint8_t red_pos; /* 0x27 */
+ grub_efi_uint8_t green_size; /* 0x28 */
+ grub_efi_uint8_t green_pos; /* 0x29 */
+ grub_efi_uint8_t blue_size; /* 0x2a */
+ grub_efi_uint8_t blue_pos; /* 0x2b */
+ grub_efi_uint8_t rsvd_size; /* 0x2c */
+ grub_efi_uint8_t rsvd_pos; /* 0x2d */
+ grub_efi_uint16_t vesapm_seg; /* 0x2e */
+ grub_efi_uint16_t vesapm_off; /* 0x30 */
+ grub_efi_uint16_t pages; /* 0x32 */
+ grub_efi_uint16_t vesa_attributes; /* 0x34 */
+ grub_efi_uint32_t capabilities; /* 0x36 */
+ grub_efi_uint32_t ext_lfb_base; /* 0x3a */
+ grub_efi_uint8_t _reserved[2]; /* 0x3e */
+} __attribute__((packed));
+
+#define GRUB_VIDEO_TYPE_EFI 0x70
+#define GRUB_VIDEO_CAPABILITY_SKIP_QUIRKS (1 << 0)
+#define GRUB_VIDEO_CAPABILITY_64BIT_BASE (1 << 1) /* Frame buffer base is 64-bit */
+
/* From arch/loongarch/include/asm/mach-loongson64/boot_param.h */
struct _extention_list_hdr {
grub_uint64_t signature;
--
2.33.0
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化