mirror of
https://github.com/limine-bootloader/limine
synced 2025-02-09 05:34:54 +03:00
Implement UEFI EDID
This commit is contained in:
parent
c3c278ffdd
commit
443266feb3
87
stage23/drivers/edid.c
Normal file
87
stage23/drivers/edid.c
Normal file
@ -0,0 +1,87 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <drivers/edid.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <lib/blib.h>
|
||||
#include <lib/libc.h>
|
||||
#include <lib/print.h>
|
||||
|
||||
#if defined (bios)
|
||||
|
||||
#include <lib/real.h>
|
||||
|
||||
struct edid_info_struct *get_edid_info(void) {
|
||||
struct edid_info_struct *buf = conv_mem_alloc(sizeof(struct edid_info_struct));
|
||||
|
||||
struct rm_regs r = {0};
|
||||
|
||||
r.eax = 0x4f15;
|
||||
r.ebx = 0x0001;
|
||||
r.edi = (uint32_t)buf;
|
||||
rm_int(0x10, &r, &r);
|
||||
|
||||
if ((r.eax & 0x00ff) != 0x4f)
|
||||
goto fail;
|
||||
if ((r.eax & 0xff00) != 0)
|
||||
goto fail;
|
||||
|
||||
print("edid: Success.\n");
|
||||
return buf;
|
||||
|
||||
fail:
|
||||
print("edid: Could not fetch EDID data.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (uefi)
|
||||
|
||||
#include <efi.h>
|
||||
|
||||
struct edid_info_struct *get_edid_info(void) {
|
||||
struct edid_info_struct *buf = ext_mem_alloc(sizeof(struct edid_info_struct));
|
||||
|
||||
EFI_STATUS status;
|
||||
|
||||
EFI_HANDLE *handles = NULL;
|
||||
UINTN handles_size = 0;
|
||||
EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
|
||||
status = uefi_call_wrapper(gBS->LocateHandle, 5,
|
||||
ByProtocol, &gop_guid, NULL, &handles_size, handles);
|
||||
|
||||
if (status && status != EFI_BUFFER_TOO_SMALL)
|
||||
goto fail;
|
||||
|
||||
handles = ext_mem_alloc(handles_size);
|
||||
|
||||
status = uefi_call_wrapper(gBS->LocateHandle, 5,
|
||||
ByProtocol, &gop_guid, NULL, &handles_size, handles);
|
||||
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
EFI_EDID_ACTIVE_PROTOCOL *edid = NULL;
|
||||
EFI_GUID edid_guid = EFI_EDID_ACTIVE_PROTOCOL_GUID;
|
||||
|
||||
status = uefi_call_wrapper(gBS->HandleProtocol, 3,
|
||||
handles[0], &edid_guid, &edid);
|
||||
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
if (edid->SizeOfEdid < sizeof(struct edid_info_struct))
|
||||
goto fail;
|
||||
|
||||
memcpy(buf, edid->Edid, sizeof(struct edid_info_struct));
|
||||
|
||||
print("edid: Success.\n");
|
||||
return buf;
|
||||
|
||||
fail:
|
||||
print("edid: Could not fetch EDID data.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
35
stage23/drivers/edid.h
Normal file
35
stage23/drivers/edid.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef __DRIVERS__EDID_H__
|
||||
#define __DRIVERS__EDID_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct edid_info_struct {
|
||||
uint8_t padding[8];
|
||||
uint16_t manufacturer_id_be;
|
||||
uint16_t edid_id_code;
|
||||
uint32_t serial_num;
|
||||
uint8_t man_week;
|
||||
uint8_t man_year;
|
||||
uint8_t edid_version;
|
||||
uint8_t edid_revision;
|
||||
uint8_t video_input_type;
|
||||
uint8_t max_hor_size;
|
||||
uint8_t max_ver_size;
|
||||
uint8_t gamma_factor;
|
||||
uint8_t dpms_flags;
|
||||
uint8_t chroma_info[10];
|
||||
uint8_t est_timings1;
|
||||
uint8_t est_timings2;
|
||||
uint8_t man_res_timing;
|
||||
uint16_t std_timing_id[8];
|
||||
uint8_t det_timing_desc1[18];
|
||||
uint8_t det_timing_desc2[18];
|
||||
uint8_t det_timing_desc3[18];
|
||||
uint8_t det_timing_desc4[18];
|
||||
uint8_t unused;
|
||||
uint8_t checksum;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct edid_info_struct *get_edid_info(void);
|
||||
|
||||
#endif
|
@ -3,16 +3,37 @@
|
||||
#include <efi.h>
|
||||
#include <lib/blib.h>
|
||||
#include <drivers/gop.h>
|
||||
#include <drivers/edid.h>
|
||||
#include <lib/print.h>
|
||||
|
||||
// Most of this code taken from https://wiki.osdev.org/GOP
|
||||
|
||||
bool init_gop(struct fb_info *ret,
|
||||
uint16_t target_width, uint16_t target_height, uint16_t target_bpp) {
|
||||
(void)ret; (void)target_width; (void)target_height; (void)target_bpp;
|
||||
|
||||
EFI_STATUS status;
|
||||
|
||||
if (!target_width || !target_height || !target_bpp) {
|
||||
target_width = 1024;
|
||||
target_height = 768;
|
||||
target_bpp = 32;
|
||||
struct edid_info_struct *edid_info = get_edid_info();
|
||||
if (edid_info != NULL) {
|
||||
int edid_width = (int)edid_info->det_timing_desc1[2];
|
||||
edid_width += ((int)edid_info->det_timing_desc1[4] & 0xf0) << 4;
|
||||
int edid_height = (int)edid_info->det_timing_desc1[5];
|
||||
edid_height += ((int)edid_info->det_timing_desc1[7] & 0xf0) << 4;
|
||||
if (edid_width && edid_height) {
|
||||
target_width = edid_width;
|
||||
target_height = edid_height;
|
||||
print("gop: EDID detected screen resolution of %ux%u\n",
|
||||
target_width, target_height);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print("gop: Requested resolution of %ux%ux%u\n",
|
||||
target_width, target_height, target_bpp);
|
||||
}
|
||||
|
||||
EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
|
||||
|
||||
@ -20,7 +41,6 @@ bool init_gop(struct fb_info *ret,
|
||||
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
|
||||
UINTN mode_info_size;
|
||||
//UINTN native_mode, modes_count;
|
||||
|
||||
status = uefi_call_wrapper(gop->QueryMode, 4, gop,
|
||||
gop->Mode == NULL ? 0 : gop->Mode->Mode,
|
||||
@ -30,8 +50,32 @@ bool init_gop(struct fb_info *ret,
|
||||
status = uefi_call_wrapper(gop->SetMode, 2, gop, 0);
|
||||
}
|
||||
|
||||
if (EFI_ERROR(status)) {
|
||||
panic("GOP initialisation failed");
|
||||
if (status) {
|
||||
panic("gop: Initialisation failed");
|
||||
}
|
||||
|
||||
UINTN modes_count = gop->Mode->MaxMode;
|
||||
|
||||
// Find our mode
|
||||
for (size_t i = 0; i < modes_count; i++) {
|
||||
status = uefi_call_wrapper(gop->QueryMode, 4,
|
||||
gop, i, &mode_info_size, &mode_info);
|
||||
|
||||
if (status)
|
||||
continue;
|
||||
|
||||
if (mode_info->HorizontalResolution != target_width
|
||||
|| mode_info->VerticalResolution != target_height)
|
||||
continue;
|
||||
|
||||
print("gop: Found matching mode %x, attempting to set...\n", i);
|
||||
|
||||
status = uefi_call_wrapper(gop->SetMode, 2, gop, i);
|
||||
|
||||
if (status) {
|
||||
print("gop: Failed to set video mode %x, moving on...\n", i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ret->memory_model = 0x06;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <drivers/vbe.h>
|
||||
#include <drivers/edid.h>
|
||||
#include <lib/libc.h>
|
||||
#include <lib/blib.h>
|
||||
#include <lib/real.h>
|
||||
@ -12,7 +13,6 @@
|
||||
#include <lib/config.h>
|
||||
#include <lib/uri.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <mm/mtrr.h>
|
||||
|
||||
struct vbe_info_struct {
|
||||
char signature[4];
|
||||
@ -115,49 +115,6 @@ static int set_vbe_mode(uint16_t mode) {
|
||||
return r.eax & 0xff;
|
||||
}
|
||||
|
||||
struct edid_info_struct {
|
||||
uint8_t padding[8];
|
||||
uint16_t manufacturer_id_be;
|
||||
uint16_t edid_id_code;
|
||||
uint32_t serial_num;
|
||||
uint8_t man_week;
|
||||
uint8_t man_year;
|
||||
uint8_t edid_version;
|
||||
uint8_t edid_revision;
|
||||
uint8_t video_input_type;
|
||||
uint8_t max_hor_size;
|
||||
uint8_t max_ver_size;
|
||||
uint8_t gamma_factor;
|
||||
uint8_t dpms_flags;
|
||||
uint8_t chroma_info[10];
|
||||
uint8_t est_timings1;
|
||||
uint8_t est_timings2;
|
||||
uint8_t man_res_timing;
|
||||
uint16_t std_timing_id[8];
|
||||
uint8_t det_timing_desc1[18];
|
||||
uint8_t det_timing_desc2[18];
|
||||
uint8_t det_timing_desc3[18];
|
||||
uint8_t det_timing_desc4[18];
|
||||
uint8_t unused;
|
||||
uint8_t checksum;
|
||||
} __attribute__((packed));
|
||||
|
||||
static int get_edid_info(struct edid_info_struct *buf) {
|
||||
struct rm_regs r = {0};
|
||||
|
||||
r.eax = 0x4f15;
|
||||
r.ebx = 0x0001;
|
||||
r.edi = (uint32_t)buf;
|
||||
rm_int(0x10, &r, &r);
|
||||
|
||||
if ((r.eax & 0x00ff) != 0x4f)
|
||||
return -1;
|
||||
if ((r.eax & 0xff00) != 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct resolution {
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
@ -185,16 +142,16 @@ bool init_vbe(struct fb_info *ret,
|
||||
print("vbe: Product name: %s\n", (char *)rm_desegment(vbe_info.prod_name_seg, vbe_info.prod_name_off));
|
||||
print("vbe: Product revision: %s\n", (char *)rm_desegment(vbe_info.prod_rev_seg, vbe_info.prod_rev_off));
|
||||
|
||||
struct edid_info_struct edid_info;
|
||||
if (!target_width || !target_height || !target_bpp) {
|
||||
target_width = 1024;
|
||||
target_height = 768;
|
||||
target_bpp = 32;
|
||||
if (!get_edid_info(&edid_info)) {
|
||||
int edid_width = (int)edid_info.det_timing_desc1[2];
|
||||
edid_width += ((int)edid_info.det_timing_desc1[4] & 0xf0) << 4;
|
||||
int edid_height = (int)edid_info.det_timing_desc1[5];
|
||||
edid_height += ((int)edid_info.det_timing_desc1[7] & 0xf0) << 4;
|
||||
struct edid_info_struct *edid_info = get_edid_info();
|
||||
if (edid_info != NULL) {
|
||||
int edid_width = (int)edid_info->det_timing_desc1[2];
|
||||
edid_width += ((int)edid_info->det_timing_desc1[4] & 0xf0) << 4;
|
||||
int edid_height = (int)edid_info->det_timing_desc1[5];
|
||||
edid_height += ((int)edid_info->det_timing_desc1[7] & 0xf0) << 4;
|
||||
if (edid_width && edid_height) {
|
||||
target_width = edid_width;
|
||||
target_height = edid_height;
|
||||
|
@ -1,7 +1,6 @@
|
||||
DEFAULT_ENTRY=2
|
||||
TIMEOUT=3
|
||||
GRAPHICS=yes
|
||||
MENU_RESOLUTION=1024x768
|
||||
MENU_FONT=boot:///boot/font.bin
|
||||
|
||||
THEME_COLOURS=60000000;aa0000;00aaff;aa5500;0000aa;aa00aa;9076de;aaaaaa
|
||||
|
Loading…
x
Reference in New Issue
Block a user